Merge "Unit tests for the CHPP discovery client" am: 1fe638ad34

Original change: https://googleplex-android-review.googlesource.com/c/platform/system/chre/+/11964439

Change-Id: I0800e7043c2ba0df9c2477a0c719698bf4c67da0
diff --git a/Android.mk b/Android.mk
index 6b93aa5..b6fe16e 100644
--- a/Android.mk
+++ b/Android.mk
@@ -16,6 +16,14 @@
 
 LOCAL_PATH := $(call my-dir)
 
+# If the daemon is using USF, but USF isn't enabled, disable the daemon.
+# TODO (b/157659611): Remove when USF is available on partner with a prebuilt.
+ifeq ($(CHRE_DAEMON_USES_USF),true)
+  ifneq ($(USF_ENABLED),true)
+    CHRE_DAEMON_ENABLED := false
+  endif
+endif
+
 # Don't build the daemon for targets that don't contain a vendor image as
 # libsdsprpc and libadsprpc are provided by vendor code
 ifeq ($(BUILDING_VENDOR_IMAGE),true)
@@ -56,23 +64,38 @@
     host/common/log_message_parser_base.cc \
     host/common/socket_server.cc \
     host/common/st_hal_lpma_handler.cc \
-    host/msm/daemon/fastrpc_daemon.cc \
-    host/msm/daemon/main.cc \
-    host/msm/daemon/generated/chre_slpi_stub.c \
     platform/shared/host_protocol_common.cc
 
+MSM_DAEMON_SRC_FILES := \
+    host/msm/daemon/fastrpc_daemon.cc \
+    host/msm/daemon/main.cc \
+    host/msm/daemon/generated/chre_slpi_stub.c
+
+USF_DAEMON_SRC_FILES := \
+    host/usf_daemon/usf_daemon.cc \
+    host/usf_daemon/main.cc
+
 LOCAL_C_INCLUDES := \
-    external/fastrpc/inc \
     system/chre/external/flatbuffers/include \
     system/chre/host/common/include \
-    system/chre/host/msm/daemon \
     system/chre/platform/shared/include \
-    system/chre/platform/slpi/include \
     system/chre/util/include \
     system/core/base/include \
     system/core/libcutils/include \
     system/core/liblog/include \
-    system/core/libutils/include \
+    system/core/libutils/include
+
+MSM_DAEMON_INCLUDES := \
+    external/fastrpc/inc \
+    system/chre/platform/slpi/include \
+    system/chre/host/msm/daemon
+
+USF_DAEMON_INCLUDES := \
+    system/chre/host/usf_daemon \
+    vendor/google/sensors/usf/core/include \
+    vendor/google/sensors/usf/pal/android/include \
+    vendor/google/sensors/usf/pal/include \
+    vendor/google/sensors/usf/core/fbs
 
 LOCAL_SHARED_LIBRARIES := \
     libjsoncpp \
@@ -84,6 +107,22 @@
     android.hardware.soundtrigger@2.0 \
     libpower
 
+USF_DAEMON_SHARED_LIBRARIES := libusf
+
+ifeq ($(CHRE_DAEMON_USES_USF),true)
+LOCAL_C_INCLUDES += $(USF_DAEMON_INCLUDES)
+LOCAL_SRC_FILES += $(USF_DAEMON_SRC_FILES)
+LOCAL_SHARED_LIBRARIES += $(USF_DAEMON_SHARED_LIBRARIES)
+else
+LOCAL_SRC_FILES += $(MSM_DAEMON_SRC_FILES)
+LOCAL_C_INCLUDES += $(MSM_DAEMON_INCLUDES)
+ifeq ($(CHRE_DAEMON_USE_SDSPRPC),true)
+LOCAL_SHARED_LIBRARIES += libsdsprpc
+else
+LOCAL_SHARED_LIBRARIES += libadsprpc
+endif
+endif
+
 # Enable tokenized logging
 ifeq ($(CHRE_USE_TOKENIZED_LOGGING),true)
 LOCAL_CFLAGS += -DCHRE_USE_TOKENIZED_LOGGING
@@ -102,10 +141,9 @@
 LOCAL_SRC_FILES += $(PIGWEED_TOKENIZER_DIR_RELPATH)/pw_varint/varint.cc
 endif
 
-ifeq ($(CHRE_DAEMON_USE_SDSPRPC),true)
-LOCAL_SHARED_LIBRARIES += libsdsprpc
-else
-LOCAL_SHARED_LIBRARIES += libadsprpc
+ifeq ($(CHRE_DAEMON_LPMA_ENABLED),true)
+LOCAL_SHARED_LIBRARIES += android.hardware.soundtrigger@2.0
+LOCAL_SHARED_LIBRARIES += libpower
 endif
 
 include $(BUILD_EXECUTABLE)
diff --git a/Makefile b/Makefile
index c08e9c4..f12534e 100644
--- a/Makefile
+++ b/Makefile
@@ -92,6 +92,7 @@
 # implementation of CHRE. Example: this CHRE implementation is never built for
 # google_cm4_nanohub as Nanohub itself is a CHRE implementation.
 include $(CHRE_PREFIX)/build/variant/google_arm64_android.mk
+include $(CHRE_PREFIX)/build/variant/google_armv8a_aoc.mk
 include $(CHRE_PREFIX)/build/variant/google_hexagonv55_slpi-see.mk
 include $(CHRE_PREFIX)/build/variant/google_hexagonv60_slpi.mk
 include $(CHRE_PREFIX)/build/variant/google_hexagonv62_slpi.mk
diff --git a/apps/apps.mk b/apps/apps.mk
index a76dc71..265b96f 100644
--- a/apps/apps.mk
+++ b/apps/apps.mk
@@ -7,6 +7,9 @@
 COMMON_CFLAGS += -Iapps/include
 
 # App makefiles ################################################################
+ifeq ($(CHRE_AUDIO_SUPPORT_ENABLED), true)
+include apps/audio_world/audio_world.mk
+endif
 
 ifeq ($(CHRE_AUDIO_SUPPORT_ENABLED), true)
 include apps/audio_world/audio_world.mk
diff --git a/apps/power_test/common/idl/chre_power_test_generated.h b/apps/power_test/common/idl/chre_power_test_generated.h
index 918bec1..0475a97 100644
--- a/apps/power_test/common/idl/chre_power_test_generated.h
+++ b/apps/power_test/common/idl/chre_power_test_generated.h
@@ -10,79 +10,56 @@
 namespace power_test {
 
 struct TimerMessage;
-struct TimerMessageBuilder;
 struct TimerMessageT;
 
 struct WifiScanMessage;
-struct WifiScanMessageBuilder;
 struct WifiScanMessageT;
 
 struct GnssLocationMessage;
-struct GnssLocationMessageBuilder;
 struct GnssLocationMessageT;
 
 struct CellQueryMessage;
-struct CellQueryMessageBuilder;
 struct CellQueryMessageT;
 
 struct AudioRequestMessage;
-struct AudioRequestMessageBuilder;
 struct AudioRequestMessageT;
 
 struct SensorRequestMessage;
-struct SensorRequestMessageBuilder;
 struct SensorRequestMessageT;
 
 struct BreakItMessage;
-struct BreakItMessageBuilder;
 struct BreakItMessageT;
 
 struct NanoappResponseMessage;
-struct NanoappResponseMessageBuilder;
 struct NanoappResponseMessageT;
 
 /// Indicates which of the following messages is being sent to / from the
 /// nanoapp. Use uint as the base type to match the message type in
 /// chreMessageFromHostData.
 enum class MessageType : uint32_t {
-  UNSPECIFIED = 0,
-  /// Should be used with TimerMessage
-  TIMER_TEST = 1,
-  /// Should be used with WifiScanMessage
-  WIFI_SCAN_TEST = 2,
-  /// Should be used with GnssLocationMessage
-  GNSS_LOCATION_TEST = 3,
-  /// Should be used with CellQueryMessage
-  CELL_QUERY_TEST = 4,
-  /// Should be used with AudioRequestMessage
-  AUDIO_REQUEST_TEST = 5,
-  /// Should be used with SensorRequestMessage
-  SENSOR_REQUEST_TEST = 6,
-  /// Should be used with BreakItMessage
-  BREAK_IT_TEST = 7,
-  /// Should be used with NanoappResponseMessage
+  UNSPECIFIED = 0  /// Should be used with TimerMessage
+,
+  TIMER_TEST = 1  /// Should be used with WifiScanMessage
+,
+  WIFI_SCAN_TEST = 2  /// Should be used with GnssLocationMessage
+,
+  GNSS_LOCATION_TEST = 3  /// Should be used with CellQueryMessage
+,
+  CELL_QUERY_TEST = 4  /// Should be used with AudioRequestMessage
+,
+  AUDIO_REQUEST_TEST = 5  /// Should be used with SensorRequestMessage
+,
+  SENSOR_REQUEST_TEST = 6  /// Should be used with BreakItMessage
+,
+  BREAK_IT_TEST = 7  /// Should be used with NanoappResponseMessage
+,
   NANOAPP_RESPONSE = 8,
   MIN = UNSPECIFIED,
   MAX = NANOAPP_RESPONSE
 };
 
-inline const MessageType (&EnumValuesMessageType())[9] {
-  static const MessageType values[] = {
-    MessageType::UNSPECIFIED,
-    MessageType::TIMER_TEST,
-    MessageType::WIFI_SCAN_TEST,
-    MessageType::GNSS_LOCATION_TEST,
-    MessageType::CELL_QUERY_TEST,
-    MessageType::AUDIO_REQUEST_TEST,
-    MessageType::SENSOR_REQUEST_TEST,
-    MessageType::BREAK_IT_TEST,
-    MessageType::NANOAPP_RESPONSE
-  };
-  return values;
-}
-
-inline const char * const *EnumNamesMessageType() {
-  static const char * const names[10] = {
+inline const char **EnumNamesMessageType() {
+  static const char *names[] = {
     "UNSPECIFIED",
     "TIMER_TEST",
     "WIFI_SCAN_TEST",
@@ -98,8 +75,7 @@
 }
 
 inline const char *EnumNameMessageType(MessageType e) {
-  if (flatbuffers::IsOutRange(e, MessageType::UNSPECIFIED, MessageType::NANOAPP_RESPONSE)) return "";
-  const size_t index = static_cast<size_t>(e);
+  const size_t index = static_cast<int>(e);
   return EnumNamesMessageType()[index];
 }
 
@@ -126,30 +102,8 @@
   MAX = GEOMAGNETIC_FIELD_TEMPERATURE
 };
 
-inline const SensorType (&EnumValuesSensorType())[16] {
-  static const SensorType values[] = {
-    SensorType::UNKNOWN,
-    SensorType::ACCELEROMETER,
-    SensorType::INSTANT_MOTION_DETECT,
-    SensorType::STATIONARY_DETECT,
-    SensorType::GYROSCOPE,
-    SensorType::UNCALIBRATED_GYROSCOPE,
-    SensorType::GEOMAGNETIC_FIELD,
-    SensorType::UNCALIBRATED_GEOMAGNETIC_FIELD,
-    SensorType::PRESSURE,
-    SensorType::LIGHT,
-    SensorType::PROXIMITY,
-    SensorType::STEP_DETECT,
-    SensorType::UNCALIBRATED_ACCELEROMETER,
-    SensorType::ACCELEROMETER_TEMPERATURE,
-    SensorType::GYROSCOPE_TEMPERATURE,
-    SensorType::GEOMAGNETIC_FIELD_TEMPERATURE
-  };
-  return values;
-}
-
-inline const char * const *EnumNamesSensorType() {
-  static const char * const names[60] = {
+inline const char **EnumNamesSensorType() {
+  static const char *names[] = {
     "UNKNOWN",
     "ACCELEROMETER",
     "INSTANT_MOTION_DETECT",
@@ -215,8 +169,7 @@
 }
 
 inline const char *EnumNameSensorType(SensorType e) {
-  if (flatbuffers::IsOutRange(e, SensorType::UNKNOWN, SensorType::GEOMAGNETIC_FIELD_TEMPERATURE)) return "";
-  const size_t index = static_cast<size_t>(e);
+  const size_t index = static_cast<int>(e);
   return EnumNamesSensorType()[index];
 }
 
@@ -234,8 +187,7 @@
 /// the given interval
 struct TimerMessage FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   typedef TimerMessageT NativeTableType;
-  typedef TimerMessageBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_ENABLE = 4,
     VT_WAKEUP_INTERVAL_NS = 6
   };
@@ -243,13 +195,13 @@
     return GetField<uint8_t>(VT_ENABLE, 0) != 0;
   }
   bool mutate_enable(bool _enable) {
-    return SetField<uint8_t>(VT_ENABLE, static_cast<uint8_t>(_enable), 0);
+    return SetField(VT_ENABLE, static_cast<uint8_t>(_enable));
   }
   uint64_t wakeup_interval_ns() const {
     return GetField<uint64_t>(VT_WAKEUP_INTERVAL_NS, 0);
   }
   bool mutate_wakeup_interval_ns(uint64_t _wakeup_interval_ns) {
-    return SetField<uint64_t>(VT_WAKEUP_INTERVAL_NS, _wakeup_interval_ns, 0);
+    return SetField(VT_WAKEUP_INTERVAL_NS, _wakeup_interval_ns);
   }
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
@@ -263,7 +215,6 @@
 };
 
 struct TimerMessageBuilder {
-  typedef TimerMessage Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
   void add_enable(bool enable) {
@@ -272,13 +223,13 @@
   void add_wakeup_interval_ns(uint64_t wakeup_interval_ns) {
     fbb_.AddElement<uint64_t>(TimerMessage::VT_WAKEUP_INTERVAL_NS, wakeup_interval_ns, 0);
   }
-  explicit TimerMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  TimerMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   TimerMessageBuilder &operator=(const TimerMessageBuilder &);
   flatbuffers::Offset<TimerMessage> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 2);
     auto o = flatbuffers::Offset<TimerMessage>(end);
     return o;
   }
@@ -310,8 +261,7 @@
 /// the scan interval to use if scanning is being started
 struct WifiScanMessage FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   typedef WifiScanMessageT NativeTableType;
-  typedef WifiScanMessageBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_ENABLE = 4,
     VT_SCAN_INTERVAL_NS = 6
   };
@@ -319,13 +269,13 @@
     return GetField<uint8_t>(VT_ENABLE, 0) != 0;
   }
   bool mutate_enable(bool _enable) {
-    return SetField<uint8_t>(VT_ENABLE, static_cast<uint8_t>(_enable), 0);
+    return SetField(VT_ENABLE, static_cast<uint8_t>(_enable));
   }
   uint64_t scan_interval_ns() const {
     return GetField<uint64_t>(VT_SCAN_INTERVAL_NS, 0);
   }
   bool mutate_scan_interval_ns(uint64_t _scan_interval_ns) {
-    return SetField<uint64_t>(VT_SCAN_INTERVAL_NS, _scan_interval_ns, 0);
+    return SetField(VT_SCAN_INTERVAL_NS, _scan_interval_ns);
   }
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
@@ -339,7 +289,6 @@
 };
 
 struct WifiScanMessageBuilder {
-  typedef WifiScanMessage Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
   void add_enable(bool enable) {
@@ -348,13 +297,13 @@
   void add_scan_interval_ns(uint64_t scan_interval_ns) {
     fbb_.AddElement<uint64_t>(WifiScanMessage::VT_SCAN_INTERVAL_NS, scan_interval_ns, 0);
   }
-  explicit WifiScanMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  WifiScanMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   WifiScanMessageBuilder &operator=(const WifiScanMessageBuilder &);
   flatbuffers::Offset<WifiScanMessage> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 2);
     auto o = flatbuffers::Offset<WifiScanMessage>(end);
     return o;
   }
@@ -388,8 +337,7 @@
 /// sampling at the requested interval
 struct GnssLocationMessage FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   typedef GnssLocationMessageT NativeTableType;
-  typedef GnssLocationMessageBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_ENABLE = 4,
     VT_SCAN_INTERVAL_MILLIS = 6,
     VT_MIN_TIME_TO_NEXT_FIX_MILLIS = 8
@@ -398,19 +346,19 @@
     return GetField<uint8_t>(VT_ENABLE, 0) != 0;
   }
   bool mutate_enable(bool _enable) {
-    return SetField<uint8_t>(VT_ENABLE, static_cast<uint8_t>(_enable), 0);
+    return SetField(VT_ENABLE, static_cast<uint8_t>(_enable));
   }
   uint32_t scan_interval_millis() const {
     return GetField<uint32_t>(VT_SCAN_INTERVAL_MILLIS, 0);
   }
   bool mutate_scan_interval_millis(uint32_t _scan_interval_millis) {
-    return SetField<uint32_t>(VT_SCAN_INTERVAL_MILLIS, _scan_interval_millis, 0);
+    return SetField(VT_SCAN_INTERVAL_MILLIS, _scan_interval_millis);
   }
   uint32_t min_time_to_next_fix_millis() const {
     return GetField<uint32_t>(VT_MIN_TIME_TO_NEXT_FIX_MILLIS, 0);
   }
   bool mutate_min_time_to_next_fix_millis(uint32_t _min_time_to_next_fix_millis) {
-    return SetField<uint32_t>(VT_MIN_TIME_TO_NEXT_FIX_MILLIS, _min_time_to_next_fix_millis, 0);
+    return SetField(VT_MIN_TIME_TO_NEXT_FIX_MILLIS, _min_time_to_next_fix_millis);
   }
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
@@ -425,7 +373,6 @@
 };
 
 struct GnssLocationMessageBuilder {
-  typedef GnssLocationMessage Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
   void add_enable(bool enable) {
@@ -437,13 +384,13 @@
   void add_min_time_to_next_fix_millis(uint32_t min_time_to_next_fix_millis) {
     fbb_.AddElement<uint32_t>(GnssLocationMessage::VT_MIN_TIME_TO_NEXT_FIX_MILLIS, min_time_to_next_fix_millis, 0);
   }
-  explicit GnssLocationMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  GnssLocationMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   GnssLocationMessageBuilder &operator=(const GnssLocationMessageBuilder &);
   flatbuffers::Offset<GnssLocationMessage> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 3);
     auto o = flatbuffers::Offset<GnssLocationMessage>(end);
     return o;
   }
@@ -477,8 +424,7 @@
 /// modem for the latest cell scan results on the given interval
 struct CellQueryMessage FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   typedef CellQueryMessageT NativeTableType;
-  typedef CellQueryMessageBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_ENABLE = 4,
     VT_QUERY_INTERVAL_NS = 6
   };
@@ -486,13 +432,13 @@
     return GetField<uint8_t>(VT_ENABLE, 0) != 0;
   }
   bool mutate_enable(bool _enable) {
-    return SetField<uint8_t>(VT_ENABLE, static_cast<uint8_t>(_enable), 0);
+    return SetField(VT_ENABLE, static_cast<uint8_t>(_enable));
   }
   uint64_t query_interval_ns() const {
     return GetField<uint64_t>(VT_QUERY_INTERVAL_NS, 0);
   }
   bool mutate_query_interval_ns(uint64_t _query_interval_ns) {
-    return SetField<uint64_t>(VT_QUERY_INTERVAL_NS, _query_interval_ns, 0);
+    return SetField(VT_QUERY_INTERVAL_NS, _query_interval_ns);
   }
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
@@ -506,7 +452,6 @@
 };
 
 struct CellQueryMessageBuilder {
-  typedef CellQueryMessage Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
   void add_enable(bool enable) {
@@ -515,13 +460,13 @@
   void add_query_interval_ns(uint64_t query_interval_ns) {
     fbb_.AddElement<uint64_t>(CellQueryMessage::VT_QUERY_INTERVAL_NS, query_interval_ns, 0);
   }
-  explicit CellQueryMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  CellQueryMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   CellQueryMessageBuilder &operator=(const CellQueryMessageBuilder &);
   flatbuffers::Offset<CellQueryMessage> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 2);
     auto o = flatbuffers::Offset<CellQueryMessage>(end);
     return o;
   }
@@ -554,8 +499,7 @@
 /// source, the nanoapp will only request audio from the first source.
 struct AudioRequestMessage FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   typedef AudioRequestMessageT NativeTableType;
-  typedef AudioRequestMessageBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_ENABLE = 4,
     VT_BUFFER_DURATION_NS = 6
   };
@@ -563,7 +507,7 @@
     return GetField<uint8_t>(VT_ENABLE, 0) != 0;
   }
   bool mutate_enable(bool _enable) {
-    return SetField<uint8_t>(VT_ENABLE, static_cast<uint8_t>(_enable), 0);
+    return SetField(VT_ENABLE, static_cast<uint8_t>(_enable));
   }
   /// The buffer duration is also used as the interval for how often
   /// the buffer should be delivered to the nanoapp.
@@ -571,7 +515,7 @@
     return GetField<uint64_t>(VT_BUFFER_DURATION_NS, 0);
   }
   bool mutate_buffer_duration_ns(uint64_t _buffer_duration_ns) {
-    return SetField<uint64_t>(VT_BUFFER_DURATION_NS, _buffer_duration_ns, 0);
+    return SetField(VT_BUFFER_DURATION_NS, _buffer_duration_ns);
   }
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
@@ -585,7 +529,6 @@
 };
 
 struct AudioRequestMessageBuilder {
-  typedef AudioRequestMessage Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
   void add_enable(bool enable) {
@@ -594,13 +537,13 @@
   void add_buffer_duration_ns(uint64_t buffer_duration_ns) {
     fbb_.AddElement<uint64_t>(AudioRequestMessage::VT_BUFFER_DURATION_NS, buffer_duration_ns, 0);
   }
-  explicit AudioRequestMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  AudioRequestMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   AudioRequestMessageBuilder &operator=(const AudioRequestMessageBuilder &);
   flatbuffers::Offset<AudioRequestMessage> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 2);
     auto o = flatbuffers::Offset<AudioRequestMessage>(end);
     return o;
   }
@@ -621,12 +564,12 @@
 struct SensorRequestMessageT : public flatbuffers::NativeTable {
   typedef SensorRequestMessage TableType;
   bool enable;
-  chre::power_test::SensorType sensor;
+  SensorType sensor;
   uint64_t sampling_interval_ns;
   uint64_t latency_ns;
   SensorRequestMessageT()
       : enable(false),
-        sensor(chre::power_test::SensorType::UNKNOWN),
+        sensor(SensorType::UNKNOWN),
         sampling_interval_ns(0),
         latency_ns(0) {
   }
@@ -636,8 +579,7 @@
 /// a given sensor
 struct SensorRequestMessage FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   typedef SensorRequestMessageT NativeTableType;
-  typedef SensorRequestMessageBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_ENABLE = 4,
     VT_SENSOR = 6,
     VT_SAMPLING_INTERVAL_NS = 8,
@@ -647,25 +589,25 @@
     return GetField<uint8_t>(VT_ENABLE, 0) != 0;
   }
   bool mutate_enable(bool _enable) {
-    return SetField<uint8_t>(VT_ENABLE, static_cast<uint8_t>(_enable), 0);
+    return SetField(VT_ENABLE, static_cast<uint8_t>(_enable));
   }
-  chre::power_test::SensorType sensor() const {
-    return static_cast<chre::power_test::SensorType>(GetField<uint8_t>(VT_SENSOR, 0));
+  SensorType sensor() const {
+    return static_cast<SensorType>(GetField<uint8_t>(VT_SENSOR, 0));
   }
-  bool mutate_sensor(chre::power_test::SensorType _sensor) {
-    return SetField<uint8_t>(VT_SENSOR, static_cast<uint8_t>(_sensor), 0);
+  bool mutate_sensor(SensorType _sensor) {
+    return SetField(VT_SENSOR, static_cast<uint8_t>(_sensor));
   }
   uint64_t sampling_interval_ns() const {
     return GetField<uint64_t>(VT_SAMPLING_INTERVAL_NS, 0);
   }
   bool mutate_sampling_interval_ns(uint64_t _sampling_interval_ns) {
-    return SetField<uint64_t>(VT_SAMPLING_INTERVAL_NS, _sampling_interval_ns, 0);
+    return SetField(VT_SAMPLING_INTERVAL_NS, _sampling_interval_ns);
   }
   uint64_t latency_ns() const {
     return GetField<uint64_t>(VT_LATENCY_NS, 0);
   }
   bool mutate_latency_ns(uint64_t _latency_ns) {
-    return SetField<uint64_t>(VT_LATENCY_NS, _latency_ns, 0);
+    return SetField(VT_LATENCY_NS, _latency_ns);
   }
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
@@ -681,13 +623,12 @@
 };
 
 struct SensorRequestMessageBuilder {
-  typedef SensorRequestMessage Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
   void add_enable(bool enable) {
     fbb_.AddElement<uint8_t>(SensorRequestMessage::VT_ENABLE, static_cast<uint8_t>(enable), 0);
   }
-  void add_sensor(chre::power_test::SensorType sensor) {
+  void add_sensor(SensorType sensor) {
     fbb_.AddElement<uint8_t>(SensorRequestMessage::VT_SENSOR, static_cast<uint8_t>(sensor), 0);
   }
   void add_sampling_interval_ns(uint64_t sampling_interval_ns) {
@@ -696,13 +637,13 @@
   void add_latency_ns(uint64_t latency_ns) {
     fbb_.AddElement<uint64_t>(SensorRequestMessage::VT_LATENCY_NS, latency_ns, 0);
   }
-  explicit SensorRequestMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  SensorRequestMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   SensorRequestMessageBuilder &operator=(const SensorRequestMessageBuilder &);
   flatbuffers::Offset<SensorRequestMessage> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 4);
     auto o = flatbuffers::Offset<SensorRequestMessage>(end);
     return o;
   }
@@ -711,7 +652,7 @@
 inline flatbuffers::Offset<SensorRequestMessage> CreateSensorRequestMessage(
     flatbuffers::FlatBufferBuilder &_fbb,
     bool enable = false,
-    chre::power_test::SensorType sensor = chre::power_test::SensorType::UNKNOWN,
+    SensorType sensor = SensorType::UNKNOWN,
     uint64_t sampling_interval_ns = 0,
     uint64_t latency_ns = 0) {
   SensorRequestMessageBuilder builder_(_fbb);
@@ -737,15 +678,14 @@
 /// enables all sensors at their fastest sampling rate.
 struct BreakItMessage FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   typedef BreakItMessageT NativeTableType;
-  typedef BreakItMessageBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_ENABLE = 4
   };
   bool enable() const {
     return GetField<uint8_t>(VT_ENABLE, 0) != 0;
   }
   bool mutate_enable(bool _enable) {
-    return SetField<uint8_t>(VT_ENABLE, static_cast<uint8_t>(_enable), 0);
+    return SetField(VT_ENABLE, static_cast<uint8_t>(_enable));
   }
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
@@ -758,19 +698,18 @@
 };
 
 struct BreakItMessageBuilder {
-  typedef BreakItMessage Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
   void add_enable(bool enable) {
     fbb_.AddElement<uint8_t>(BreakItMessage::VT_ENABLE, static_cast<uint8_t>(enable), 0);
   }
-  explicit BreakItMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  BreakItMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   BreakItMessageBuilder &operator=(const BreakItMessageBuilder &);
   flatbuffers::Offset<BreakItMessage> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 1);
     auto o = flatbuffers::Offset<BreakItMessage>(end);
     return o;
   }
@@ -798,15 +737,14 @@
 /// Any failures will be printed to the logs.
 struct NanoappResponseMessage FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   typedef NanoappResponseMessageT NativeTableType;
-  typedef NanoappResponseMessageBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_SUCCESS = 4
   };
   bool success() const {
     return GetField<uint8_t>(VT_SUCCESS, 0) != 0;
   }
   bool mutate_success(bool _success) {
-    return SetField<uint8_t>(VT_SUCCESS, static_cast<uint8_t>(_success), 0);
+    return SetField(VT_SUCCESS, static_cast<uint8_t>(_success));
   }
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
@@ -819,19 +757,18 @@
 };
 
 struct NanoappResponseMessageBuilder {
-  typedef NanoappResponseMessage Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
   void add_success(bool success) {
     fbb_.AddElement<uint8_t>(NanoappResponseMessage::VT_SUCCESS, static_cast<uint8_t>(success), 0);
   }
-  explicit NanoappResponseMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  NanoappResponseMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   NanoappResponseMessageBuilder &operator=(const NanoappResponseMessageBuilder &);
   flatbuffers::Offset<NanoappResponseMessage> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 1);
     auto o = flatbuffers::Offset<NanoappResponseMessage>(end);
     return o;
   }
@@ -848,16 +785,16 @@
 flatbuffers::Offset<NanoappResponseMessage> CreateNanoappResponseMessage(flatbuffers::FlatBufferBuilder &_fbb, const NanoappResponseMessageT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
 
 inline TimerMessageT *TimerMessage::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
-  std::unique_ptr<chre::power_test::TimerMessageT> _o = std::unique_ptr<chre::power_test::TimerMessageT>(new TimerMessageT());
-  UnPackTo(_o.get(), _resolver);
-  return _o.release();
+  auto _o = new TimerMessageT();
+  UnPackTo(_o, _resolver);
+  return _o;
 }
 
 inline void TimerMessage::UnPackTo(TimerMessageT *_o, const flatbuffers::resolver_function_t *_resolver) const {
   (void)_o;
   (void)_resolver;
-  { auto _e = enable(); _o->enable = _e; }
-  { auto _e = wakeup_interval_ns(); _o->wakeup_interval_ns = _e; }
+  { auto _e = enable(); _o->enable = _e; };
+  { auto _e = wakeup_interval_ns(); _o->wakeup_interval_ns = _e; };
 }
 
 inline flatbuffers::Offset<TimerMessage> TimerMessage::Pack(flatbuffers::FlatBufferBuilder &_fbb, const TimerMessageT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
@@ -867,7 +804,6 @@
 inline flatbuffers::Offset<TimerMessage> CreateTimerMessage(flatbuffers::FlatBufferBuilder &_fbb, const TimerMessageT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
   (void)_rehasher;
   (void)_o;
-  struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const TimerMessageT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
   auto _enable = _o->enable;
   auto _wakeup_interval_ns = _o->wakeup_interval_ns;
   return chre::power_test::CreateTimerMessage(
@@ -877,16 +813,16 @@
 }
 
 inline WifiScanMessageT *WifiScanMessage::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
-  std::unique_ptr<chre::power_test::WifiScanMessageT> _o = std::unique_ptr<chre::power_test::WifiScanMessageT>(new WifiScanMessageT());
-  UnPackTo(_o.get(), _resolver);
-  return _o.release();
+  auto _o = new WifiScanMessageT();
+  UnPackTo(_o, _resolver);
+  return _o;
 }
 
 inline void WifiScanMessage::UnPackTo(WifiScanMessageT *_o, const flatbuffers::resolver_function_t *_resolver) const {
   (void)_o;
   (void)_resolver;
-  { auto _e = enable(); _o->enable = _e; }
-  { auto _e = scan_interval_ns(); _o->scan_interval_ns = _e; }
+  { auto _e = enable(); _o->enable = _e; };
+  { auto _e = scan_interval_ns(); _o->scan_interval_ns = _e; };
 }
 
 inline flatbuffers::Offset<WifiScanMessage> WifiScanMessage::Pack(flatbuffers::FlatBufferBuilder &_fbb, const WifiScanMessageT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
@@ -896,7 +832,6 @@
 inline flatbuffers::Offset<WifiScanMessage> CreateWifiScanMessage(flatbuffers::FlatBufferBuilder &_fbb, const WifiScanMessageT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
   (void)_rehasher;
   (void)_o;
-  struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const WifiScanMessageT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
   auto _enable = _o->enable;
   auto _scan_interval_ns = _o->scan_interval_ns;
   return chre::power_test::CreateWifiScanMessage(
@@ -906,17 +841,17 @@
 }
 
 inline GnssLocationMessageT *GnssLocationMessage::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
-  std::unique_ptr<chre::power_test::GnssLocationMessageT> _o = std::unique_ptr<chre::power_test::GnssLocationMessageT>(new GnssLocationMessageT());
-  UnPackTo(_o.get(), _resolver);
-  return _o.release();
+  auto _o = new GnssLocationMessageT();
+  UnPackTo(_o, _resolver);
+  return _o;
 }
 
 inline void GnssLocationMessage::UnPackTo(GnssLocationMessageT *_o, const flatbuffers::resolver_function_t *_resolver) const {
   (void)_o;
   (void)_resolver;
-  { auto _e = enable(); _o->enable = _e; }
-  { auto _e = scan_interval_millis(); _o->scan_interval_millis = _e; }
-  { auto _e = min_time_to_next_fix_millis(); _o->min_time_to_next_fix_millis = _e; }
+  { auto _e = enable(); _o->enable = _e; };
+  { auto _e = scan_interval_millis(); _o->scan_interval_millis = _e; };
+  { auto _e = min_time_to_next_fix_millis(); _o->min_time_to_next_fix_millis = _e; };
 }
 
 inline flatbuffers::Offset<GnssLocationMessage> GnssLocationMessage::Pack(flatbuffers::FlatBufferBuilder &_fbb, const GnssLocationMessageT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
@@ -926,7 +861,6 @@
 inline flatbuffers::Offset<GnssLocationMessage> CreateGnssLocationMessage(flatbuffers::FlatBufferBuilder &_fbb, const GnssLocationMessageT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
   (void)_rehasher;
   (void)_o;
-  struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const GnssLocationMessageT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
   auto _enable = _o->enable;
   auto _scan_interval_millis = _o->scan_interval_millis;
   auto _min_time_to_next_fix_millis = _o->min_time_to_next_fix_millis;
@@ -938,16 +872,16 @@
 }
 
 inline CellQueryMessageT *CellQueryMessage::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
-  std::unique_ptr<chre::power_test::CellQueryMessageT> _o = std::unique_ptr<chre::power_test::CellQueryMessageT>(new CellQueryMessageT());
-  UnPackTo(_o.get(), _resolver);
-  return _o.release();
+  auto _o = new CellQueryMessageT();
+  UnPackTo(_o, _resolver);
+  return _o;
 }
 
 inline void CellQueryMessage::UnPackTo(CellQueryMessageT *_o, const flatbuffers::resolver_function_t *_resolver) const {
   (void)_o;
   (void)_resolver;
-  { auto _e = enable(); _o->enable = _e; }
-  { auto _e = query_interval_ns(); _o->query_interval_ns = _e; }
+  { auto _e = enable(); _o->enable = _e; };
+  { auto _e = query_interval_ns(); _o->query_interval_ns = _e; };
 }
 
 inline flatbuffers::Offset<CellQueryMessage> CellQueryMessage::Pack(flatbuffers::FlatBufferBuilder &_fbb, const CellQueryMessageT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
@@ -957,7 +891,6 @@
 inline flatbuffers::Offset<CellQueryMessage> CreateCellQueryMessage(flatbuffers::FlatBufferBuilder &_fbb, const CellQueryMessageT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
   (void)_rehasher;
   (void)_o;
-  struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const CellQueryMessageT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
   auto _enable = _o->enable;
   auto _query_interval_ns = _o->query_interval_ns;
   return chre::power_test::CreateCellQueryMessage(
@@ -967,16 +900,16 @@
 }
 
 inline AudioRequestMessageT *AudioRequestMessage::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
-  std::unique_ptr<chre::power_test::AudioRequestMessageT> _o = std::unique_ptr<chre::power_test::AudioRequestMessageT>(new AudioRequestMessageT());
-  UnPackTo(_o.get(), _resolver);
-  return _o.release();
+  auto _o = new AudioRequestMessageT();
+  UnPackTo(_o, _resolver);
+  return _o;
 }
 
 inline void AudioRequestMessage::UnPackTo(AudioRequestMessageT *_o, const flatbuffers::resolver_function_t *_resolver) const {
   (void)_o;
   (void)_resolver;
-  { auto _e = enable(); _o->enable = _e; }
-  { auto _e = buffer_duration_ns(); _o->buffer_duration_ns = _e; }
+  { auto _e = enable(); _o->enable = _e; };
+  { auto _e = buffer_duration_ns(); _o->buffer_duration_ns = _e; };
 }
 
 inline flatbuffers::Offset<AudioRequestMessage> AudioRequestMessage::Pack(flatbuffers::FlatBufferBuilder &_fbb, const AudioRequestMessageT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
@@ -986,7 +919,6 @@
 inline flatbuffers::Offset<AudioRequestMessage> CreateAudioRequestMessage(flatbuffers::FlatBufferBuilder &_fbb, const AudioRequestMessageT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
   (void)_rehasher;
   (void)_o;
-  struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const AudioRequestMessageT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
   auto _enable = _o->enable;
   auto _buffer_duration_ns = _o->buffer_duration_ns;
   return chre::power_test::CreateAudioRequestMessage(
@@ -996,18 +928,18 @@
 }
 
 inline SensorRequestMessageT *SensorRequestMessage::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
-  std::unique_ptr<chre::power_test::SensorRequestMessageT> _o = std::unique_ptr<chre::power_test::SensorRequestMessageT>(new SensorRequestMessageT());
-  UnPackTo(_o.get(), _resolver);
-  return _o.release();
+  auto _o = new SensorRequestMessageT();
+  UnPackTo(_o, _resolver);
+  return _o;
 }
 
 inline void SensorRequestMessage::UnPackTo(SensorRequestMessageT *_o, const flatbuffers::resolver_function_t *_resolver) const {
   (void)_o;
   (void)_resolver;
-  { auto _e = enable(); _o->enable = _e; }
-  { auto _e = sensor(); _o->sensor = _e; }
-  { auto _e = sampling_interval_ns(); _o->sampling_interval_ns = _e; }
-  { auto _e = latency_ns(); _o->latency_ns = _e; }
+  { auto _e = enable(); _o->enable = _e; };
+  { auto _e = sensor(); _o->sensor = _e; };
+  { auto _e = sampling_interval_ns(); _o->sampling_interval_ns = _e; };
+  { auto _e = latency_ns(); _o->latency_ns = _e; };
 }
 
 inline flatbuffers::Offset<SensorRequestMessage> SensorRequestMessage::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SensorRequestMessageT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
@@ -1017,7 +949,6 @@
 inline flatbuffers::Offset<SensorRequestMessage> CreateSensorRequestMessage(flatbuffers::FlatBufferBuilder &_fbb, const SensorRequestMessageT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
   (void)_rehasher;
   (void)_o;
-  struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const SensorRequestMessageT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
   auto _enable = _o->enable;
   auto _sensor = _o->sensor;
   auto _sampling_interval_ns = _o->sampling_interval_ns;
@@ -1031,15 +962,15 @@
 }
 
 inline BreakItMessageT *BreakItMessage::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
-  std::unique_ptr<chre::power_test::BreakItMessageT> _o = std::unique_ptr<chre::power_test::BreakItMessageT>(new BreakItMessageT());
-  UnPackTo(_o.get(), _resolver);
-  return _o.release();
+  auto _o = new BreakItMessageT();
+  UnPackTo(_o, _resolver);
+  return _o;
 }
 
 inline void BreakItMessage::UnPackTo(BreakItMessageT *_o, const flatbuffers::resolver_function_t *_resolver) const {
   (void)_o;
   (void)_resolver;
-  { auto _e = enable(); _o->enable = _e; }
+  { auto _e = enable(); _o->enable = _e; };
 }
 
 inline flatbuffers::Offset<BreakItMessage> BreakItMessage::Pack(flatbuffers::FlatBufferBuilder &_fbb, const BreakItMessageT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
@@ -1049,7 +980,6 @@
 inline flatbuffers::Offset<BreakItMessage> CreateBreakItMessage(flatbuffers::FlatBufferBuilder &_fbb, const BreakItMessageT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
   (void)_rehasher;
   (void)_o;
-  struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const BreakItMessageT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
   auto _enable = _o->enable;
   return chre::power_test::CreateBreakItMessage(
       _fbb,
@@ -1057,15 +987,15 @@
 }
 
 inline NanoappResponseMessageT *NanoappResponseMessage::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
-  std::unique_ptr<chre::power_test::NanoappResponseMessageT> _o = std::unique_ptr<chre::power_test::NanoappResponseMessageT>(new NanoappResponseMessageT());
-  UnPackTo(_o.get(), _resolver);
-  return _o.release();
+  auto _o = new NanoappResponseMessageT();
+  UnPackTo(_o, _resolver);
+  return _o;
 }
 
 inline void NanoappResponseMessage::UnPackTo(NanoappResponseMessageT *_o, const flatbuffers::resolver_function_t *_resolver) const {
   (void)_o;
   (void)_resolver;
-  { auto _e = success(); _o->success = _e; }
+  { auto _e = success(); _o->success = _e; };
 }
 
 inline flatbuffers::Offset<NanoappResponseMessage> NanoappResponseMessage::Pack(flatbuffers::FlatBufferBuilder &_fbb, const NanoappResponseMessageT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
@@ -1075,7 +1005,6 @@
 inline flatbuffers::Offset<NanoappResponseMessage> CreateNanoappResponseMessage(flatbuffers::FlatBufferBuilder &_fbb, const NanoappResponseMessageT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
   (void)_rehasher;
   (void)_o;
-  struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const NanoappResponseMessageT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
   auto _success = _o->success;
   return chre::power_test::CreateNanoappResponseMessage(
       _fbb,
diff --git a/apps/power_test/common/include/generated/chre_power_test_generated.h b/apps/power_test/common/include/generated/chre_power_test_generated.h
index 70ef458..153a5e6 100644
--- a/apps/power_test/common/include/generated/chre_power_test_generated.h
+++ b/apps/power_test/common/include/generated/chre_power_test_generated.h
@@ -10,71 +10,48 @@
 namespace power_test {
 
 struct TimerMessage;
-struct TimerMessageBuilder;
 
 struct WifiScanMessage;
-struct WifiScanMessageBuilder;
 
 struct GnssLocationMessage;
-struct GnssLocationMessageBuilder;
 
 struct CellQueryMessage;
-struct CellQueryMessageBuilder;
 
 struct AudioRequestMessage;
-struct AudioRequestMessageBuilder;
 
 struct SensorRequestMessage;
-struct SensorRequestMessageBuilder;
 
 struct BreakItMessage;
-struct BreakItMessageBuilder;
 
 struct NanoappResponseMessage;
-struct NanoappResponseMessageBuilder;
 
 /// Indicates which of the following messages is being sent to / from the
 /// nanoapp. Use uint as the base type to match the message type in
 /// chreMessageFromHostData.
 enum class MessageType : uint32_t {
-  UNSPECIFIED = 0,
-  /// Should be used with TimerMessage
-  TIMER_TEST = 1,
-  /// Should be used with WifiScanMessage
-  WIFI_SCAN_TEST = 2,
-  /// Should be used with GnssLocationMessage
-  GNSS_LOCATION_TEST = 3,
-  /// Should be used with CellQueryMessage
-  CELL_QUERY_TEST = 4,
-  /// Should be used with AudioRequestMessage
-  AUDIO_REQUEST_TEST = 5,
-  /// Should be used with SensorRequestMessage
-  SENSOR_REQUEST_TEST = 6,
-  /// Should be used with BreakItMessage
-  BREAK_IT_TEST = 7,
-  /// Should be used with NanoappResponseMessage
+  UNSPECIFIED = 0  /// Should be used with TimerMessage
+,
+  TIMER_TEST = 1  /// Should be used with WifiScanMessage
+,
+  WIFI_SCAN_TEST = 2  /// Should be used with GnssLocationMessage
+,
+  GNSS_LOCATION_TEST = 3  /// Should be used with CellQueryMessage
+,
+  CELL_QUERY_TEST = 4  /// Should be used with AudioRequestMessage
+,
+  AUDIO_REQUEST_TEST = 5  /// Should be used with SensorRequestMessage
+,
+  SENSOR_REQUEST_TEST = 6  /// Should be used with BreakItMessage
+,
+  BREAK_IT_TEST = 7  /// Should be used with NanoappResponseMessage
+,
   NANOAPP_RESPONSE = 8,
   MIN = UNSPECIFIED,
   MAX = NANOAPP_RESPONSE
 };
 
-inline const MessageType (&EnumValuesMessageType())[9] {
-  static const MessageType values[] = {
-    MessageType::UNSPECIFIED,
-    MessageType::TIMER_TEST,
-    MessageType::WIFI_SCAN_TEST,
-    MessageType::GNSS_LOCATION_TEST,
-    MessageType::CELL_QUERY_TEST,
-    MessageType::AUDIO_REQUEST_TEST,
-    MessageType::SENSOR_REQUEST_TEST,
-    MessageType::BREAK_IT_TEST,
-    MessageType::NANOAPP_RESPONSE
-  };
-  return values;
-}
-
-inline const char * const *EnumNamesMessageType() {
-  static const char * const names[10] = {
+inline const char **EnumNamesMessageType() {
+  static const char *names[] = {
     "UNSPECIFIED",
     "TIMER_TEST",
     "WIFI_SCAN_TEST",
@@ -90,8 +67,7 @@
 }
 
 inline const char *EnumNameMessageType(MessageType e) {
-  if (flatbuffers::IsOutRange(e, MessageType::UNSPECIFIED, MessageType::NANOAPP_RESPONSE)) return "";
-  const size_t index = static_cast<size_t>(e);
+  const size_t index = static_cast<int>(e);
   return EnumNamesMessageType()[index];
 }
 
@@ -118,30 +94,8 @@
   MAX = GEOMAGNETIC_FIELD_TEMPERATURE
 };
 
-inline const SensorType (&EnumValuesSensorType())[16] {
-  static const SensorType values[] = {
-    SensorType::UNKNOWN,
-    SensorType::ACCELEROMETER,
-    SensorType::INSTANT_MOTION_DETECT,
-    SensorType::STATIONARY_DETECT,
-    SensorType::GYROSCOPE,
-    SensorType::UNCALIBRATED_GYROSCOPE,
-    SensorType::GEOMAGNETIC_FIELD,
-    SensorType::UNCALIBRATED_GEOMAGNETIC_FIELD,
-    SensorType::PRESSURE,
-    SensorType::LIGHT,
-    SensorType::PROXIMITY,
-    SensorType::STEP_DETECT,
-    SensorType::UNCALIBRATED_ACCELEROMETER,
-    SensorType::ACCELEROMETER_TEMPERATURE,
-    SensorType::GYROSCOPE_TEMPERATURE,
-    SensorType::GEOMAGNETIC_FIELD_TEMPERATURE
-  };
-  return values;
-}
-
-inline const char * const *EnumNamesSensorType() {
-  static const char * const names[60] = {
+inline const char **EnumNamesSensorType() {
+  static const char *names[] = {
     "UNKNOWN",
     "ACCELEROMETER",
     "INSTANT_MOTION_DETECT",
@@ -207,16 +161,14 @@
 }
 
 inline const char *EnumNameSensorType(SensorType e) {
-  if (flatbuffers::IsOutRange(e, SensorType::UNKNOWN, SensorType::GEOMAGNETIC_FIELD_TEMPERATURE)) return "";
-  const size_t index = static_cast<size_t>(e);
+  const size_t index = static_cast<int>(e);
   return EnumNamesSensorType()[index];
 }
 
 /// Represents a message to ask the nanoapp to create a timer that wakes up at
 /// the given interval
 struct TimerMessage FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  typedef TimerMessageBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_ENABLE = 4,
     VT_WAKEUP_INTERVAL_NS = 6
   };
@@ -235,7 +187,6 @@
 };
 
 struct TimerMessageBuilder {
-  typedef TimerMessage Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
   void add_enable(bool enable) {
@@ -244,13 +195,13 @@
   void add_wakeup_interval_ns(uint64_t wakeup_interval_ns) {
     fbb_.AddElement<uint64_t>(TimerMessage::VT_WAKEUP_INTERVAL_NS, wakeup_interval_ns, 0);
   }
-  explicit TimerMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  TimerMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   TimerMessageBuilder &operator=(const TimerMessageBuilder &);
   flatbuffers::Offset<TimerMessage> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 2);
     auto o = flatbuffers::Offset<TimerMessage>(end);
     return o;
   }
@@ -269,8 +220,7 @@
 /// Represents a message to ask the nanoapp to start or stop WiFi scanning and
 /// the scan interval to use if scanning is being started
 struct WifiScanMessage FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  typedef WifiScanMessageBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_ENABLE = 4,
     VT_SCAN_INTERVAL_NS = 6
   };
@@ -289,7 +239,6 @@
 };
 
 struct WifiScanMessageBuilder {
-  typedef WifiScanMessage Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
   void add_enable(bool enable) {
@@ -298,13 +247,13 @@
   void add_scan_interval_ns(uint64_t scan_interval_ns) {
     fbb_.AddElement<uint64_t>(WifiScanMessage::VT_SCAN_INTERVAL_NS, scan_interval_ns, 0);
   }
-  explicit WifiScanMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  WifiScanMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   WifiScanMessageBuilder &operator=(const WifiScanMessageBuilder &);
   flatbuffers::Offset<WifiScanMessage> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 2);
     auto o = flatbuffers::Offset<WifiScanMessage>(end);
     return o;
   }
@@ -323,8 +272,7 @@
 /// Represents a message to ask the nanoapp to start or stop Gnss location
 /// sampling at the requested interval
 struct GnssLocationMessage FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  typedef GnssLocationMessageBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_ENABLE = 4,
     VT_SCAN_INTERVAL_MILLIS = 6,
     VT_MIN_TIME_TO_NEXT_FIX_MILLIS = 8
@@ -348,7 +296,6 @@
 };
 
 struct GnssLocationMessageBuilder {
-  typedef GnssLocationMessage Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
   void add_enable(bool enable) {
@@ -360,13 +307,13 @@
   void add_min_time_to_next_fix_millis(uint32_t min_time_to_next_fix_millis) {
     fbb_.AddElement<uint32_t>(GnssLocationMessage::VT_MIN_TIME_TO_NEXT_FIX_MILLIS, min_time_to_next_fix_millis, 0);
   }
-  explicit GnssLocationMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  GnssLocationMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   GnssLocationMessageBuilder &operator=(const GnssLocationMessageBuilder &);
   flatbuffers::Offset<GnssLocationMessage> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 3);
     auto o = flatbuffers::Offset<GnssLocationMessage>(end);
     return o;
   }
@@ -387,8 +334,7 @@
 /// Represents a message to ask the nanoapp to start or stop querying the cell
 /// modem for the latest cell scan results on the given interval
 struct CellQueryMessage FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  typedef CellQueryMessageBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_ENABLE = 4,
     VT_QUERY_INTERVAL_NS = 6
   };
@@ -407,7 +353,6 @@
 };
 
 struct CellQueryMessageBuilder {
-  typedef CellQueryMessage Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
   void add_enable(bool enable) {
@@ -416,13 +361,13 @@
   void add_query_interval_ns(uint64_t query_interval_ns) {
     fbb_.AddElement<uint64_t>(CellQueryMessage::VT_QUERY_INTERVAL_NS, query_interval_ns, 0);
   }
-  explicit CellQueryMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  CellQueryMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   CellQueryMessageBuilder &operator=(const CellQueryMessageBuilder &);
   flatbuffers::Offset<CellQueryMessage> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 2);
     auto o = flatbuffers::Offset<CellQueryMessage>(end);
     return o;
   }
@@ -442,8 +387,7 @@
 /// data buffered at given interval. Note: If there is more than one audio
 /// source, the nanoapp will only request audio from the first source.
 struct AudioRequestMessage FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  typedef AudioRequestMessageBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_ENABLE = 4,
     VT_BUFFER_DURATION_NS = 6
   };
@@ -464,7 +408,6 @@
 };
 
 struct AudioRequestMessageBuilder {
-  typedef AudioRequestMessage Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
   void add_enable(bool enable) {
@@ -473,13 +416,13 @@
   void add_buffer_duration_ns(uint64_t buffer_duration_ns) {
     fbb_.AddElement<uint64_t>(AudioRequestMessage::VT_BUFFER_DURATION_NS, buffer_duration_ns, 0);
   }
-  explicit AudioRequestMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  AudioRequestMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   AudioRequestMessageBuilder &operator=(const AudioRequestMessageBuilder &);
   flatbuffers::Offset<AudioRequestMessage> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 2);
     auto o = flatbuffers::Offset<AudioRequestMessage>(end);
     return o;
   }
@@ -498,8 +441,7 @@
 /// Represents a message to ask the nanoapp to start / stop sampling / batching
 /// a given sensor
 struct SensorRequestMessage FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  typedef SensorRequestMessageBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_ENABLE = 4,
     VT_SENSOR = 6,
     VT_SAMPLING_INTERVAL_NS = 8,
@@ -508,8 +450,8 @@
   bool enable() const {
     return GetField<uint8_t>(VT_ENABLE, 0) != 0;
   }
-  chre::power_test::SensorType sensor() const {
-    return static_cast<chre::power_test::SensorType>(GetField<uint8_t>(VT_SENSOR, 0));
+  SensorType sensor() const {
+    return static_cast<SensorType>(GetField<uint8_t>(VT_SENSOR, 0));
   }
   uint64_t sampling_interval_ns() const {
     return GetField<uint64_t>(VT_SAMPLING_INTERVAL_NS, 0);
@@ -528,13 +470,12 @@
 };
 
 struct SensorRequestMessageBuilder {
-  typedef SensorRequestMessage Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
   void add_enable(bool enable) {
     fbb_.AddElement<uint8_t>(SensorRequestMessage::VT_ENABLE, static_cast<uint8_t>(enable), 0);
   }
-  void add_sensor(chre::power_test::SensorType sensor) {
+  void add_sensor(SensorType sensor) {
     fbb_.AddElement<uint8_t>(SensorRequestMessage::VT_SENSOR, static_cast<uint8_t>(sensor), 0);
   }
   void add_sampling_interval_ns(uint64_t sampling_interval_ns) {
@@ -543,13 +484,13 @@
   void add_latency_ns(uint64_t latency_ns) {
     fbb_.AddElement<uint64_t>(SensorRequestMessage::VT_LATENCY_NS, latency_ns, 0);
   }
-  explicit SensorRequestMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  SensorRequestMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   SensorRequestMessageBuilder &operator=(const SensorRequestMessageBuilder &);
   flatbuffers::Offset<SensorRequestMessage> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 4);
     auto o = flatbuffers::Offset<SensorRequestMessage>(end);
     return o;
   }
@@ -558,7 +499,7 @@
 inline flatbuffers::Offset<SensorRequestMessage> CreateSensorRequestMessage(
     flatbuffers::FlatBufferBuilder &_fbb,
     bool enable = false,
-    chre::power_test::SensorType sensor = chre::power_test::SensorType::UNKNOWN,
+    SensorType sensor = SensorType::UNKNOWN,
     uint64_t sampling_interval_ns = 0,
     uint64_t latency_ns = 0) {
   SensorRequestMessageBuilder builder_(_fbb);
@@ -573,8 +514,7 @@
 /// Break-it mode enables WiFi / GNSS / Cell to be queried every second and
 /// enables all sensors at their fastest sampling rate.
 struct BreakItMessage FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  typedef BreakItMessageBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_ENABLE = 4
   };
   bool enable() const {
@@ -588,19 +528,18 @@
 };
 
 struct BreakItMessageBuilder {
-  typedef BreakItMessage Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
   void add_enable(bool enable) {
     fbb_.AddElement<uint8_t>(BreakItMessage::VT_ENABLE, static_cast<uint8_t>(enable), 0);
   }
-  explicit BreakItMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  BreakItMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   BreakItMessageBuilder &operator=(const BreakItMessageBuilder &);
   flatbuffers::Offset<BreakItMessage> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 1);
     auto o = flatbuffers::Offset<BreakItMessage>(end);
     return o;
   }
@@ -617,8 +556,7 @@
 /// Indicates whether the nanoapp successfully performed the requested action.
 /// Any failures will be printed to the logs.
 struct NanoappResponseMessage FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  typedef NanoappResponseMessageBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_SUCCESS = 4
   };
   bool success() const {
@@ -632,19 +570,18 @@
 };
 
 struct NanoappResponseMessageBuilder {
-  typedef NanoappResponseMessage Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
   void add_success(bool success) {
     fbb_.AddElement<uint8_t>(NanoappResponseMessage::VT_SUCCESS, static_cast<uint8_t>(success), 0);
   }
-  explicit NanoappResponseMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  NanoappResponseMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   NanoappResponseMessageBuilder &operator=(const NanoappResponseMessageBuilder &);
   flatbuffers::Offset<NanoappResponseMessage> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 1);
     auto o = flatbuffers::Offset<NanoappResponseMessage>(end);
     return o;
   }
diff --git a/apps/wifi_offload/include/chre/apps/wifi_offload/generated/flatbuffers_types_generated.h b/apps/wifi_offload/include/chre/apps/wifi_offload/generated/flatbuffers_types_generated.h
index 45d3106..8183f7e 100644
--- a/apps/wifi_offload/include/chre/apps/wifi_offload/generated/flatbuffers_types_generated.h
+++ b/apps/wifi_offload/include/chre/apps/wifi_offload/generated/flatbuffers_types_generated.h
@@ -1,5 +1,20 @@
-// automatically generated by the FlatBuffers compiler, do not modify
+/*
+ * Copyright (C) 2017 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.
+ */
 
+// automatically generated by the FlatBuffers compiler, do not modify
 
 #ifndef FLATBUFFERS_GENERATED_FLATBUFFERSTYPES_WIFI_OFFLOAD_FBS_H_
 #define FLATBUFFERS_GENERATED_FLATBUFFERSTYPES_WIFI_OFFLOAD_FBS_H_
@@ -10,65 +25,49 @@
 namespace fbs {
 
 struct Ssid;
-struct SsidBuilder;
 
 struct PreferredNetwork;
-struct PreferredNetworkBuilder;
 
 struct ScanResult;
-struct ScanResultBuilder;
 
 struct ScanResultMessage;
-struct ScanResultMessageBuilder;
 
 struct ScanParams;
-struct ScanParamsBuilder;
 
 struct ScanFilter;
-struct ScanFilterBuilder;
 
 struct ScanConfig;
-struct ScanConfigBuilder;
 
 struct ScanRecord;
-struct ScanRecordBuilder;
 
 struct RpcLogRecord;
-struct RpcLogRecordBuilder;
 
 struct ScanStats;
-struct ScanStatsBuilder;
 
 struct Ssid FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  typedef SsidBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
-    VT_SSID = 4
-  };
+  enum { VT_SSID = 4 };
   const flatbuffers::Vector<uint8_t> *ssid() const {
     return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_SSID);
   }
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
-           VerifyOffset(verifier, VT_SSID) &&
-           verifier.VerifyVector(ssid()) &&
-           verifier.EndTable();
+           VerifyField<flatbuffers::uoffset_t>(verifier, VT_SSID) &&
+           verifier.Verify(ssid()) && verifier.EndTable();
   }
 };
 
 struct SsidBuilder {
-  typedef Ssid Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
   void add_ssid(flatbuffers::Offset<flatbuffers::Vector<uint8_t>> ssid) {
     fbb_.AddOffset(Ssid::VT_SSID, ssid);
   }
-  explicit SsidBuilder(flatbuffers::FlatBufferBuilder &_fbb)
-        : fbb_(_fbb) {
+  explicit SsidBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   SsidBuilder &operator=(const SsidBuilder &);
   flatbuffers::Offset<Ssid> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 1);
     auto o = flatbuffers::Offset<Ssid>(end);
     return o;
   }
@@ -85,27 +84,19 @@
 inline flatbuffers::Offset<Ssid> CreateSsidDirect(
     flatbuffers::FlatBufferBuilder &_fbb,
     const std::vector<uint8_t> *ssid = nullptr) {
-  auto ssid__ = ssid ? _fbb.CreateVector<uint8_t>(*ssid) : 0;
   return wifi_offload::fbs::CreateSsid(
-      _fbb,
-      ssid__);
+      _fbb, ssid ? _fbb.CreateVector<uint8_t>(*ssid) : 0);
 }
 
 struct PreferredNetwork FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  typedef PreferredNetworkBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
-    VT_SSID = 4,
-    VT_SECURITY_MODES = 6
-  };
-  const wifi_offload::fbs::Ssid *ssid() const {
-    return GetPointer<const wifi_offload::fbs::Ssid *>(VT_SSID);
-  }
+  enum { VT_SSID = 4, VT_SECURITY_MODES = 6 };
+  const Ssid *ssid() const { return GetPointer<const Ssid *>(VT_SSID); }
   uint8_t security_modes() const {
     return GetField<uint8_t>(VT_SECURITY_MODES, 0);
   }
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
-           VerifyOffset(verifier, VT_SSID) &&
+           VerifyField<flatbuffers::uoffset_t>(verifier, VT_SSID) &&
            verifier.VerifyTable(ssid()) &&
            VerifyField<uint8_t>(verifier, VT_SECURITY_MODES) &&
            verifier.EndTable();
@@ -113,30 +104,28 @@
 };
 
 struct PreferredNetworkBuilder {
-  typedef PreferredNetwork Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
-  void add_ssid(flatbuffers::Offset<wifi_offload::fbs::Ssid> ssid) {
+  void add_ssid(flatbuffers::Offset<Ssid> ssid) {
     fbb_.AddOffset(PreferredNetwork::VT_SSID, ssid);
   }
   void add_security_modes(uint8_t security_modes) {
-    fbb_.AddElement<uint8_t>(PreferredNetwork::VT_SECURITY_MODES, security_modes, 0);
+    fbb_.AddElement<uint8_t>(PreferredNetwork::VT_SECURITY_MODES,
+                             security_modes, 0);
   }
-  explicit PreferredNetworkBuilder(flatbuffers::FlatBufferBuilder &_fbb)
-        : fbb_(_fbb) {
+  explicit PreferredNetworkBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   PreferredNetworkBuilder &operator=(const PreferredNetworkBuilder &);
   flatbuffers::Offset<PreferredNetwork> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 2);
     auto o = flatbuffers::Offset<PreferredNetwork>(end);
     return o;
   }
 };
 
 inline flatbuffers::Offset<PreferredNetwork> CreatePreferredNetwork(
-    flatbuffers::FlatBufferBuilder &_fbb,
-    flatbuffers::Offset<wifi_offload::fbs::Ssid> ssid = 0,
+    flatbuffers::FlatBufferBuilder &_fbb, flatbuffers::Offset<Ssid> ssid = 0,
     uint8_t security_modes = 0) {
   PreferredNetworkBuilder builder_(_fbb);
   builder_.add_ssid(ssid);
@@ -145,8 +134,7 @@
 }
 
 struct ScanResult FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  typedef ScanResultBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_SSID = 4,
     VT_SECURITY_MODES = 6,
     VT_BSSID = 8,
@@ -155,47 +143,37 @@
     VT_RSSI_DBM = 14,
     VT_TSF = 16
   };
-  const wifi_offload::fbs::Ssid *ssid() const {
-    return GetPointer<const wifi_offload::fbs::Ssid *>(VT_SSID);
-  }
+  const Ssid *ssid() const { return GetPointer<const Ssid *>(VT_SSID); }
   uint8_t security_modes() const {
     return GetField<uint8_t>(VT_SECURITY_MODES, 0);
   }
   const flatbuffers::Vector<uint8_t> *bssid() const {
     return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_BSSID);
   }
-  uint16_t capability() const {
-    return GetField<uint16_t>(VT_CAPABILITY, 0);
-  }
+  uint16_t capability() const { return GetField<uint16_t>(VT_CAPABILITY, 0); }
   uint32_t frequency_scanned_mhz() const {
     return GetField<uint32_t>(VT_FREQUENCY_SCANNED_MHZ, 0);
   }
-  int8_t rssi_dbm() const {
-    return GetField<int8_t>(VT_RSSI_DBM, 0);
-  }
-  uint64_t tsf() const {
-    return GetField<uint64_t>(VT_TSF, 0);
-  }
+  int8_t rssi_dbm() const { return GetField<int8_t>(VT_RSSI_DBM, 0); }
+  uint64_t tsf() const { return GetField<uint64_t>(VT_TSF, 0); }
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
-           VerifyOffset(verifier, VT_SSID) &&
+           VerifyField<flatbuffers::uoffset_t>(verifier, VT_SSID) &&
            verifier.VerifyTable(ssid()) &&
            VerifyField<uint8_t>(verifier, VT_SECURITY_MODES) &&
-           VerifyOffset(verifier, VT_BSSID) &&
-           verifier.VerifyVector(bssid()) &&
+           VerifyField<flatbuffers::uoffset_t>(verifier, VT_BSSID) &&
+           verifier.Verify(bssid()) &&
            VerifyField<uint16_t>(verifier, VT_CAPABILITY) &&
            VerifyField<uint32_t>(verifier, VT_FREQUENCY_SCANNED_MHZ) &&
            VerifyField<int8_t>(verifier, VT_RSSI_DBM) &&
-           VerifyField<uint64_t>(verifier, VT_TSF) &&
-           verifier.EndTable();
+           VerifyField<uint64_t>(verifier, VT_TSF) && verifier.EndTable();
   }
 };
 
 struct ScanResultBuilder {
-  typedef ScanResult Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
-  void add_ssid(flatbuffers::Offset<wifi_offload::fbs::Ssid> ssid) {
+  void add_ssid(flatbuffers::Offset<Ssid> ssid) {
     fbb_.AddOffset(ScanResult::VT_SSID, ssid);
   }
   void add_security_modes(uint8_t security_modes) {
@@ -208,7 +186,8 @@
     fbb_.AddElement<uint16_t>(ScanResult::VT_CAPABILITY, capability, 0);
   }
   void add_frequency_scanned_mhz(uint32_t frequency_scanned_mhz) {
-    fbb_.AddElement<uint32_t>(ScanResult::VT_FREQUENCY_SCANNED_MHZ, frequency_scanned_mhz, 0);
+    fbb_.AddElement<uint32_t>(ScanResult::VT_FREQUENCY_SCANNED_MHZ,
+                              frequency_scanned_mhz, 0);
   }
   void add_rssi_dbm(int8_t rssi_dbm) {
     fbb_.AddElement<int8_t>(ScanResult::VT_RSSI_DBM, rssi_dbm, 0);
@@ -216,27 +195,23 @@
   void add_tsf(uint64_t tsf) {
     fbb_.AddElement<uint64_t>(ScanResult::VT_TSF, tsf, 0);
   }
-  explicit ScanResultBuilder(flatbuffers::FlatBufferBuilder &_fbb)
-        : fbb_(_fbb) {
+  explicit ScanResultBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   ScanResultBuilder &operator=(const ScanResultBuilder &);
   flatbuffers::Offset<ScanResult> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 7);
     auto o = flatbuffers::Offset<ScanResult>(end);
     return o;
   }
 };
 
 inline flatbuffers::Offset<ScanResult> CreateScanResult(
-    flatbuffers::FlatBufferBuilder &_fbb,
-    flatbuffers::Offset<wifi_offload::fbs::Ssid> ssid = 0,
+    flatbuffers::FlatBufferBuilder &_fbb, flatbuffers::Offset<Ssid> ssid = 0,
     uint8_t security_modes = 0,
     flatbuffers::Offset<flatbuffers::Vector<uint8_t>> bssid = 0,
-    uint16_t capability = 0,
-    uint32_t frequency_scanned_mhz = 0,
-    int8_t rssi_dbm = 0,
-    uint64_t tsf = 0) {
+    uint16_t capability = 0, uint32_t frequency_scanned_mhz = 0,
+    int8_t rssi_dbm = 0, uint64_t tsf = 0) {
   ScanResultBuilder builder_(_fbb);
   builder_.add_tsf(tsf);
   builder_.add_frequency_scanned_mhz(frequency_scanned_mhz);
@@ -249,57 +224,46 @@
 }
 
 inline flatbuffers::Offset<ScanResult> CreateScanResultDirect(
-    flatbuffers::FlatBufferBuilder &_fbb,
-    flatbuffers::Offset<wifi_offload::fbs::Ssid> ssid = 0,
-    uint8_t security_modes = 0,
-    const std::vector<uint8_t> *bssid = nullptr,
-    uint16_t capability = 0,
-    uint32_t frequency_scanned_mhz = 0,
-    int8_t rssi_dbm = 0,
-    uint64_t tsf = 0) {
-  auto bssid__ = bssid ? _fbb.CreateVector<uint8_t>(*bssid) : 0;
+    flatbuffers::FlatBufferBuilder &_fbb, flatbuffers::Offset<Ssid> ssid = 0,
+    uint8_t security_modes = 0, const std::vector<uint8_t> *bssid = nullptr,
+    uint16_t capability = 0, uint32_t frequency_scanned_mhz = 0,
+    int8_t rssi_dbm = 0, uint64_t tsf = 0) {
   return wifi_offload::fbs::CreateScanResult(
-      _fbb,
-      ssid,
-      security_modes,
-      bssid__,
-      capability,
-      frequency_scanned_mhz,
-      rssi_dbm,
-      tsf);
+      _fbb, ssid, security_modes,
+      bssid ? _fbb.CreateVector<uint8_t>(*bssid) : 0, capability,
+      frequency_scanned_mhz, rssi_dbm, tsf);
 }
 
 struct ScanResultMessage FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  typedef ScanResultMessageBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
-    VT_SCAN_RESULTS = 4
-  };
-  const flatbuffers::Vector<flatbuffers::Offset<wifi_offload::fbs::ScanResult>> *scan_results() const {
-    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<wifi_offload::fbs::ScanResult>> *>(VT_SCAN_RESULTS);
+  enum { VT_SCAN_RESULTS = 4 };
+  const flatbuffers::Vector<flatbuffers::Offset<ScanResult>> *scan_results()
+      const {
+    return GetPointer<
+        const flatbuffers::Vector<flatbuffers::Offset<ScanResult>> *>(
+        VT_SCAN_RESULTS);
   }
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
-           VerifyOffset(verifier, VT_SCAN_RESULTS) &&
-           verifier.VerifyVector(scan_results()) &&
-           verifier.VerifyVectorOfTables(scan_results()) &&
-           verifier.EndTable();
+           VerifyField<flatbuffers::uoffset_t>(verifier, VT_SCAN_RESULTS) &&
+           verifier.Verify(scan_results()) &&
+           verifier.VerifyVectorOfTables(scan_results()) && verifier.EndTable();
   }
 };
 
 struct ScanResultMessageBuilder {
-  typedef ScanResultMessage Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
-  void add_scan_results(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<wifi_offload::fbs::ScanResult>>> scan_results) {
+  void add_scan_results(
+      flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<ScanResult>>>
+          scan_results) {
     fbb_.AddOffset(ScanResultMessage::VT_SCAN_RESULTS, scan_results);
   }
-  explicit ScanResultMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
-        : fbb_(_fbb) {
+  explicit ScanResultMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   ScanResultMessageBuilder &operator=(const ScanResultMessageBuilder &);
   flatbuffers::Offset<ScanResultMessage> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 1);
     auto o = flatbuffers::Offset<ScanResultMessage>(end);
     return o;
   }
@@ -307,7 +271,8 @@
 
 inline flatbuffers::Offset<ScanResultMessage> CreateScanResultMessage(
     flatbuffers::FlatBufferBuilder &_fbb,
-    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<wifi_offload::fbs::ScanResult>>> scan_results = 0) {
+    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<ScanResult>>>
+        scan_results = 0) {
   ScanResultMessageBuilder builder_(_fbb);
   builder_.add_scan_results(scan_results);
   return builder_.Finish();
@@ -315,61 +280,71 @@
 
 inline flatbuffers::Offset<ScanResultMessage> CreateScanResultMessageDirect(
     flatbuffers::FlatBufferBuilder &_fbb,
-    const std::vector<flatbuffers::Offset<wifi_offload::fbs::ScanResult>> *scan_results = nullptr) {
-  auto scan_results__ = scan_results ? _fbb.CreateVector<flatbuffers::Offset<wifi_offload::fbs::ScanResult>>(*scan_results) : 0;
+    const std::vector<flatbuffers::Offset<ScanResult>> *scan_results =
+        nullptr) {
   return wifi_offload::fbs::CreateScanResultMessage(
       _fbb,
-      scan_results__);
+      scan_results
+          ? _fbb.CreateVector<flatbuffers::Offset<ScanResult>>(*scan_results)
+          : 0);
 }
 
 struct ScanParams FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  typedef ScanParamsBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_SSIDS_TO_SCAN = 4,
     VT_FREQUENCIES_TO_SCAN_MHZ = 6,
     VT_DISCONNECTED_MODE_SCAN_INTERVAL_MS = 8
   };
-  const flatbuffers::Vector<flatbuffers::Offset<wifi_offload::fbs::Ssid>> *ssids_to_scan() const {
-    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<wifi_offload::fbs::Ssid>> *>(VT_SSIDS_TO_SCAN);
+  const flatbuffers::Vector<flatbuffers::Offset<Ssid>> *ssids_to_scan() const {
+    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Ssid>> *>(
+        VT_SSIDS_TO_SCAN);
   }
   const flatbuffers::Vector<uint32_t> *frequencies_to_scan_mhz() const {
-    return GetPointer<const flatbuffers::Vector<uint32_t> *>(VT_FREQUENCIES_TO_SCAN_MHZ);
+    return GetPointer<const flatbuffers::Vector<uint32_t> *>(
+        VT_FREQUENCIES_TO_SCAN_MHZ);
   }
   uint32_t disconnected_mode_scan_interval_ms() const {
     return GetField<uint32_t>(VT_DISCONNECTED_MODE_SCAN_INTERVAL_MS, 0);
   }
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
-           VerifyOffset(verifier, VT_SSIDS_TO_SCAN) &&
-           verifier.VerifyVector(ssids_to_scan()) &&
+           VerifyField<flatbuffers::uoffset_t>(verifier, VT_SSIDS_TO_SCAN) &&
+           verifier.Verify(ssids_to_scan()) &&
            verifier.VerifyVectorOfTables(ssids_to_scan()) &&
-           VerifyOffset(verifier, VT_FREQUENCIES_TO_SCAN_MHZ) &&
-           verifier.VerifyVector(frequencies_to_scan_mhz()) &&
-           VerifyField<uint32_t>(verifier, VT_DISCONNECTED_MODE_SCAN_INTERVAL_MS) &&
+           VerifyField<flatbuffers::uoffset_t>(verifier,
+                                               VT_FREQUENCIES_TO_SCAN_MHZ) &&
+           verifier.Verify(frequencies_to_scan_mhz()) &&
+           VerifyField<uint32_t>(verifier,
+                                 VT_DISCONNECTED_MODE_SCAN_INTERVAL_MS) &&
            verifier.EndTable();
   }
 };
 
 struct ScanParamsBuilder {
-  typedef ScanParams Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
-  void add_ssids_to_scan(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<wifi_offload::fbs::Ssid>>> ssids_to_scan) {
+  void add_ssids_to_scan(
+      flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Ssid>>>
+          ssids_to_scan) {
     fbb_.AddOffset(ScanParams::VT_SSIDS_TO_SCAN, ssids_to_scan);
   }
-  void add_frequencies_to_scan_mhz(flatbuffers::Offset<flatbuffers::Vector<uint32_t>> frequencies_to_scan_mhz) {
-    fbb_.AddOffset(ScanParams::VT_FREQUENCIES_TO_SCAN_MHZ, frequencies_to_scan_mhz);
+  void add_frequencies_to_scan_mhz(
+      flatbuffers::Offset<flatbuffers::Vector<uint32_t>>
+          frequencies_to_scan_mhz) {
+    fbb_.AddOffset(ScanParams::VT_FREQUENCIES_TO_SCAN_MHZ,
+                   frequencies_to_scan_mhz);
   }
-  void add_disconnected_mode_scan_interval_ms(uint32_t disconnected_mode_scan_interval_ms) {
-    fbb_.AddElement<uint32_t>(ScanParams::VT_DISCONNECTED_MODE_SCAN_INTERVAL_MS, disconnected_mode_scan_interval_ms, 0);
+  void add_disconnected_mode_scan_interval_ms(
+      uint32_t disconnected_mode_scan_interval_ms) {
+    fbb_.AddElement<uint32_t>(ScanParams::VT_DISCONNECTED_MODE_SCAN_INTERVAL_MS,
+                              disconnected_mode_scan_interval_ms, 0);
   }
-  explicit ScanParamsBuilder(flatbuffers::FlatBufferBuilder &_fbb)
-        : fbb_(_fbb) {
+  explicit ScanParamsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   ScanParamsBuilder &operator=(const ScanParamsBuilder &);
   flatbuffers::Offset<ScanParams> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 3);
     auto o = flatbuffers::Offset<ScanParams>(end);
     return o;
   }
@@ -377,11 +352,14 @@
 
 inline flatbuffers::Offset<ScanParams> CreateScanParams(
     flatbuffers::FlatBufferBuilder &_fbb,
-    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<wifi_offload::fbs::Ssid>>> ssids_to_scan = 0,
-    flatbuffers::Offset<flatbuffers::Vector<uint32_t>> frequencies_to_scan_mhz = 0,
+    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Ssid>>>
+        ssids_to_scan = 0,
+    flatbuffers::Offset<flatbuffers::Vector<uint32_t>> frequencies_to_scan_mhz =
+        0,
     uint32_t disconnected_mode_scan_interval_ms = 0) {
   ScanParamsBuilder builder_(_fbb);
-  builder_.add_disconnected_mode_scan_interval_ms(disconnected_mode_scan_interval_ms);
+  builder_.add_disconnected_mode_scan_interval_ms(
+      disconnected_mode_scan_interval_ms);
   builder_.add_frequencies_to_scan_mhz(frequencies_to_scan_mhz);
   builder_.add_ssids_to_scan(ssids_to_scan);
   return builder_.Finish();
@@ -389,34 +367,35 @@
 
 inline flatbuffers::Offset<ScanParams> CreateScanParamsDirect(
     flatbuffers::FlatBufferBuilder &_fbb,
-    const std::vector<flatbuffers::Offset<wifi_offload::fbs::Ssid>> *ssids_to_scan = nullptr,
+    const std::vector<flatbuffers::Offset<Ssid>> *ssids_to_scan = nullptr,
     const std::vector<uint32_t> *frequencies_to_scan_mhz = nullptr,
     uint32_t disconnected_mode_scan_interval_ms = 0) {
-  auto ssids_to_scan__ = ssids_to_scan ? _fbb.CreateVector<flatbuffers::Offset<wifi_offload::fbs::Ssid>>(*ssids_to_scan) : 0;
-  auto frequencies_to_scan_mhz__ = frequencies_to_scan_mhz ? _fbb.CreateVector<uint32_t>(*frequencies_to_scan_mhz) : 0;
   return wifi_offload::fbs::CreateScanParams(
       _fbb,
-      ssids_to_scan__,
-      frequencies_to_scan_mhz__,
+      ssids_to_scan
+          ? _fbb.CreateVector<flatbuffers::Offset<Ssid>>(*ssids_to_scan)
+          : 0,
+      frequencies_to_scan_mhz
+          ? _fbb.CreateVector<uint32_t>(*frequencies_to_scan_mhz)
+          : 0,
       disconnected_mode_scan_interval_ms);
 }
 
 struct ScanFilter FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  typedef ScanFilterBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
-    VT_NETWORKS_TO_MATCH = 4,
-    VT_MIN_RSSI_THRESHOLD_DBM = 6
-  };
-  const flatbuffers::Vector<flatbuffers::Offset<wifi_offload::fbs::PreferredNetwork>> *networks_to_match() const {
-    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<wifi_offload::fbs::PreferredNetwork>> *>(VT_NETWORKS_TO_MATCH);
+  enum { VT_NETWORKS_TO_MATCH = 4, VT_MIN_RSSI_THRESHOLD_DBM = 6 };
+  const flatbuffers::Vector<flatbuffers::Offset<PreferredNetwork>>
+      *networks_to_match() const {
+    return GetPointer<
+        const flatbuffers::Vector<flatbuffers::Offset<PreferredNetwork>> *>(
+        VT_NETWORKS_TO_MATCH);
   }
   int8_t min_rssi_threshold_dbm() const {
     return GetField<int8_t>(VT_MIN_RSSI_THRESHOLD_DBM, 0);
   }
   bool Verify(flatbuffers::Verifier &verifier) const {
-    return VerifyTableStart(verifier) &&
-           VerifyOffset(verifier, VT_NETWORKS_TO_MATCH) &&
-           verifier.VerifyVector(networks_to_match()) &&
+    return VerifyTableStart(verifier) && VerifyField<flatbuffers::uoffset_t>(
+                                             verifier, VT_NETWORKS_TO_MATCH) &&
+           verifier.Verify(networks_to_match()) &&
            verifier.VerifyVectorOfTables(networks_to_match()) &&
            VerifyField<int8_t>(verifier, VT_MIN_RSSI_THRESHOLD_DBM) &&
            verifier.EndTable();
@@ -424,22 +403,24 @@
 };
 
 struct ScanFilterBuilder {
-  typedef ScanFilter Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
-  void add_networks_to_match(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<wifi_offload::fbs::PreferredNetwork>>> networks_to_match) {
+  void add_networks_to_match(
+      flatbuffers::Offset<
+          flatbuffers::Vector<flatbuffers::Offset<PreferredNetwork>>>
+          networks_to_match) {
     fbb_.AddOffset(ScanFilter::VT_NETWORKS_TO_MATCH, networks_to_match);
   }
   void add_min_rssi_threshold_dbm(int8_t min_rssi_threshold_dbm) {
-    fbb_.AddElement<int8_t>(ScanFilter::VT_MIN_RSSI_THRESHOLD_DBM, min_rssi_threshold_dbm, 0);
+    fbb_.AddElement<int8_t>(ScanFilter::VT_MIN_RSSI_THRESHOLD_DBM,
+                            min_rssi_threshold_dbm, 0);
   }
-  explicit ScanFilterBuilder(flatbuffers::FlatBufferBuilder &_fbb)
-        : fbb_(_fbb) {
+  explicit ScanFilterBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   ScanFilterBuilder &operator=(const ScanFilterBuilder &);
   flatbuffers::Offset<ScanFilter> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 2);
     auto o = flatbuffers::Offset<ScanFilter>(end);
     return o;
   }
@@ -447,7 +428,9 @@
 
 inline flatbuffers::Offset<ScanFilter> CreateScanFilter(
     flatbuffers::FlatBufferBuilder &_fbb,
-    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<wifi_offload::fbs::PreferredNetwork>>> networks_to_match = 0,
+    flatbuffers::Offset<
+        flatbuffers::Vector<flatbuffers::Offset<PreferredNetwork>>>
+        networks_to_match = 0,
     int8_t min_rssi_threshold_dbm = 0) {
   ScanFilterBuilder builder_(_fbb);
   builder_.add_networks_to_match(networks_to_match);
@@ -457,54 +440,50 @@
 
 inline flatbuffers::Offset<ScanFilter> CreateScanFilterDirect(
     flatbuffers::FlatBufferBuilder &_fbb,
-    const std::vector<flatbuffers::Offset<wifi_offload::fbs::PreferredNetwork>> *networks_to_match = nullptr,
+    const std::vector<flatbuffers::Offset<PreferredNetwork>>
+        *networks_to_match = nullptr,
     int8_t min_rssi_threshold_dbm = 0) {
-  auto networks_to_match__ = networks_to_match ? _fbb.CreateVector<flatbuffers::Offset<wifi_offload::fbs::PreferredNetwork>>(*networks_to_match) : 0;
   return wifi_offload::fbs::CreateScanFilter(
       _fbb,
-      networks_to_match__,
+      networks_to_match
+          ? _fbb.CreateVector<flatbuffers::Offset<PreferredNetwork>>(
+                *networks_to_match)
+          : 0,
       min_rssi_threshold_dbm);
 }
 
 struct ScanConfig FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  typedef ScanConfigBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
-    VT_SCAN_PARAMS = 4,
-    VT_SCAN_FILTER = 6
-  };
-  const wifi_offload::fbs::ScanParams *scan_params() const {
-    return GetPointer<const wifi_offload::fbs::ScanParams *>(VT_SCAN_PARAMS);
+  enum { VT_SCAN_PARAMS = 4, VT_SCAN_FILTER = 6 };
+  const ScanParams *scan_params() const {
+    return GetPointer<const ScanParams *>(VT_SCAN_PARAMS);
   }
-  const wifi_offload::fbs::ScanFilter *scan_filter() const {
-    return GetPointer<const wifi_offload::fbs::ScanFilter *>(VT_SCAN_FILTER);
+  const ScanFilter *scan_filter() const {
+    return GetPointer<const ScanFilter *>(VT_SCAN_FILTER);
   }
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
-           VerifyOffset(verifier, VT_SCAN_PARAMS) &&
+           VerifyField<flatbuffers::uoffset_t>(verifier, VT_SCAN_PARAMS) &&
            verifier.VerifyTable(scan_params()) &&
-           VerifyOffset(verifier, VT_SCAN_FILTER) &&
-           verifier.VerifyTable(scan_filter()) &&
-           verifier.EndTable();
+           VerifyField<flatbuffers::uoffset_t>(verifier, VT_SCAN_FILTER) &&
+           verifier.VerifyTable(scan_filter()) && verifier.EndTable();
   }
 };
 
 struct ScanConfigBuilder {
-  typedef ScanConfig Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
-  void add_scan_params(flatbuffers::Offset<wifi_offload::fbs::ScanParams> scan_params) {
+  void add_scan_params(flatbuffers::Offset<ScanParams> scan_params) {
     fbb_.AddOffset(ScanConfig::VT_SCAN_PARAMS, scan_params);
   }
-  void add_scan_filter(flatbuffers::Offset<wifi_offload::fbs::ScanFilter> scan_filter) {
+  void add_scan_filter(flatbuffers::Offset<ScanFilter> scan_filter) {
     fbb_.AddOffset(ScanConfig::VT_SCAN_FILTER, scan_filter);
   }
-  explicit ScanConfigBuilder(flatbuffers::FlatBufferBuilder &_fbb)
-        : fbb_(_fbb) {
+  explicit ScanConfigBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   ScanConfigBuilder &operator=(const ScanConfigBuilder &);
   flatbuffers::Offset<ScanConfig> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 2);
     auto o = flatbuffers::Offset<ScanConfig>(end);
     return o;
   }
@@ -512,8 +491,8 @@
 
 inline flatbuffers::Offset<ScanConfig> CreateScanConfig(
     flatbuffers::FlatBufferBuilder &_fbb,
-    flatbuffers::Offset<wifi_offload::fbs::ScanParams> scan_params = 0,
-    flatbuffers::Offset<wifi_offload::fbs::ScanFilter> scan_filter = 0) {
+    flatbuffers::Offset<ScanParams> scan_params = 0,
+    flatbuffers::Offset<ScanFilter> scan_filter = 0) {
   ScanConfigBuilder builder_(_fbb);
   builder_.add_scan_filter(scan_filter);
   builder_.add_scan_params(scan_params);
@@ -521,8 +500,7 @@
 }
 
 struct ScanRecord FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  typedef ScanRecordBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_TIME_SPENT_SCANNING_MS = 4,
     VT_NUM_CHANNELS_SCANNED = 6,
     VT_NUM_ENTRIES_AGGREGATED = 8
@@ -546,35 +524,34 @@
 };
 
 struct ScanRecordBuilder {
-  typedef ScanRecord Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
   void add_time_spent_scanning_ms(uint32_t time_spent_scanning_ms) {
-    fbb_.AddElement<uint32_t>(ScanRecord::VT_TIME_SPENT_SCANNING_MS, time_spent_scanning_ms, 0);
+    fbb_.AddElement<uint32_t>(ScanRecord::VT_TIME_SPENT_SCANNING_MS,
+                              time_spent_scanning_ms, 0);
   }
   void add_num_channels_scanned(uint32_t num_channels_scanned) {
-    fbb_.AddElement<uint32_t>(ScanRecord::VT_NUM_CHANNELS_SCANNED, num_channels_scanned, 0);
+    fbb_.AddElement<uint32_t>(ScanRecord::VT_NUM_CHANNELS_SCANNED,
+                              num_channels_scanned, 0);
   }
   void add_num_entries_aggregated(uint32_t num_entries_aggregated) {
-    fbb_.AddElement<uint32_t>(ScanRecord::VT_NUM_ENTRIES_AGGREGATED, num_entries_aggregated, 0);
+    fbb_.AddElement<uint32_t>(ScanRecord::VT_NUM_ENTRIES_AGGREGATED,
+                              num_entries_aggregated, 0);
   }
-  explicit ScanRecordBuilder(flatbuffers::FlatBufferBuilder &_fbb)
-        : fbb_(_fbb) {
+  explicit ScanRecordBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   ScanRecordBuilder &operator=(const ScanRecordBuilder &);
   flatbuffers::Offset<ScanRecord> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 3);
     auto o = flatbuffers::Offset<ScanRecord>(end);
     return o;
   }
 };
 
 inline flatbuffers::Offset<ScanRecord> CreateScanRecord(
-    flatbuffers::FlatBufferBuilder &_fbb,
-    uint32_t time_spent_scanning_ms = 0,
-    uint32_t num_channels_scanned = 0,
-    uint32_t num_entries_aggregated = 0) {
+    flatbuffers::FlatBufferBuilder &_fbb, uint32_t time_spent_scanning_ms = 0,
+    uint32_t num_channels_scanned = 0, uint32_t num_entries_aggregated = 0) {
   ScanRecordBuilder builder_(_fbb);
   builder_.add_num_entries_aggregated(num_entries_aggregated);
   builder_.add_num_channels_scanned(num_channels_scanned);
@@ -583,14 +560,8 @@
 }
 
 struct RpcLogRecord FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  typedef RpcLogRecordBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
-    VT_RECORD_TYPE = 4,
-    VT_TIMESTAMP_CHRE_MS = 6
-  };
-  uint8_t record_type() const {
-    return GetField<uint8_t>(VT_RECORD_TYPE, 0);
-  }
+  enum { VT_RECORD_TYPE = 4, VT_TIMESTAMP_CHRE_MS = 6 };
+  uint8_t record_type() const { return GetField<uint8_t>(VT_RECORD_TYPE, 0); }
   uint32_t timestamp_chre_ms() const {
     return GetField<uint32_t>(VT_TIMESTAMP_CHRE_MS, 0);
   }
@@ -603,30 +574,28 @@
 };
 
 struct RpcLogRecordBuilder {
-  typedef RpcLogRecord Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
   void add_record_type(uint8_t record_type) {
     fbb_.AddElement<uint8_t>(RpcLogRecord::VT_RECORD_TYPE, record_type, 0);
   }
   void add_timestamp_chre_ms(uint32_t timestamp_chre_ms) {
-    fbb_.AddElement<uint32_t>(RpcLogRecord::VT_TIMESTAMP_CHRE_MS, timestamp_chre_ms, 0);
+    fbb_.AddElement<uint32_t>(RpcLogRecord::VT_TIMESTAMP_CHRE_MS,
+                              timestamp_chre_ms, 0);
   }
-  explicit RpcLogRecordBuilder(flatbuffers::FlatBufferBuilder &_fbb)
-        : fbb_(_fbb) {
+  explicit RpcLogRecordBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   RpcLogRecordBuilder &operator=(const RpcLogRecordBuilder &);
   flatbuffers::Offset<RpcLogRecord> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 2);
     auto o = flatbuffers::Offset<RpcLogRecord>(end);
     return o;
   }
 };
 
 inline flatbuffers::Offset<RpcLogRecord> CreateRpcLogRecord(
-    flatbuffers::FlatBufferBuilder &_fbb,
-    uint8_t record_type = 0,
+    flatbuffers::FlatBufferBuilder &_fbb, uint8_t record_type = 0,
     uint32_t timestamp_chre_ms = 0) {
   RpcLogRecordBuilder builder_(_fbb);
   builder_.add_timestamp_chre_ms(timestamp_chre_ms);
@@ -635,8 +604,7 @@
 }
 
 struct ScanStats FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  typedef ScanStatsBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_NUM_SCANS_REQUESTED_BY_NANOAPP = 4,
     VT_NUM_SCANS_SERVICED_BY_HARDWARE = 6,
     VT_NUM_SCANS_SERVICED_BY_CACHE = 8,
@@ -666,13 +634,20 @@
     return GetField<uint32_t>(VT_LAST_SUBSCRIPTION_DURATION_MS, 0);
   }
   const flatbuffers::Vector<uint8_t> *channel_scan_count() const {
-    return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_CHANNEL_SCAN_COUNT);
+    return GetPointer<const flatbuffers::Vector<uint8_t> *>(
+        VT_CHANNEL_SCAN_COUNT);
   }
-  const flatbuffers::Vector<flatbuffers::Offset<wifi_offload::fbs::ScanRecord>> *scan_records() const {
-    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<wifi_offload::fbs::ScanRecord>> *>(VT_SCAN_RECORDS);
+  const flatbuffers::Vector<flatbuffers::Offset<ScanRecord>> *scan_records()
+      const {
+    return GetPointer<
+        const flatbuffers::Vector<flatbuffers::Offset<ScanRecord>> *>(
+        VT_SCAN_RECORDS);
   }
-  const flatbuffers::Vector<flatbuffers::Offset<wifi_offload::fbs::RpcLogRecord>> *rpc_log_records() const {
-    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<wifi_offload::fbs::RpcLogRecord>> *>(VT_RPC_LOG_RECORDS);
+  const flatbuffers::Vector<flatbuffers::Offset<RpcLogRecord>>
+      *rpc_log_records() const {
+    return GetPointer<
+        const flatbuffers::Vector<flatbuffers::Offset<RpcLogRecord>> *>(
+        VT_RPC_LOG_RECORDS);
   }
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
@@ -682,56 +657,70 @@
            VerifyField<uint32_t>(verifier, VT_UPDATED_AT_CHRE_MS) &&
            VerifyField<uint32_t>(verifier, VT_SENT_AT_CHRE_MS) &&
            VerifyField<uint32_t>(verifier, VT_LAST_SUBSCRIPTION_DURATION_MS) &&
-           VerifyOffset(verifier, VT_CHANNEL_SCAN_COUNT) &&
-           verifier.VerifyVector(channel_scan_count()) &&
-           VerifyOffset(verifier, VT_SCAN_RECORDS) &&
-           verifier.VerifyVector(scan_records()) &&
+           VerifyField<flatbuffers::uoffset_t>(verifier,
+                                               VT_CHANNEL_SCAN_COUNT) &&
+           verifier.Verify(channel_scan_count()) &&
+           VerifyField<flatbuffers::uoffset_t>(verifier, VT_SCAN_RECORDS) &&
+           verifier.Verify(scan_records()) &&
            verifier.VerifyVectorOfTables(scan_records()) &&
-           VerifyOffset(verifier, VT_RPC_LOG_RECORDS) &&
-           verifier.VerifyVector(rpc_log_records()) &&
+           VerifyField<flatbuffers::uoffset_t>(verifier, VT_RPC_LOG_RECORDS) &&
+           verifier.Verify(rpc_log_records()) &&
            verifier.VerifyVectorOfTables(rpc_log_records()) &&
            verifier.EndTable();
   }
 };
 
 struct ScanStatsBuilder {
-  typedef ScanStats Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
-  void add_num_scans_requested_by_nanoapp(uint32_t num_scans_requested_by_nanoapp) {
-    fbb_.AddElement<uint32_t>(ScanStats::VT_NUM_SCANS_REQUESTED_BY_NANOAPP, num_scans_requested_by_nanoapp, 0);
+  void add_num_scans_requested_by_nanoapp(
+      uint32_t num_scans_requested_by_nanoapp) {
+    fbb_.AddElement<uint32_t>(ScanStats::VT_NUM_SCANS_REQUESTED_BY_NANOAPP,
+                              num_scans_requested_by_nanoapp, 0);
   }
-  void add_num_scans_serviced_by_hardware(uint32_t num_scans_serviced_by_hardware) {
-    fbb_.AddElement<uint32_t>(ScanStats::VT_NUM_SCANS_SERVICED_BY_HARDWARE, num_scans_serviced_by_hardware, 0);
+  void add_num_scans_serviced_by_hardware(
+      uint32_t num_scans_serviced_by_hardware) {
+    fbb_.AddElement<uint32_t>(ScanStats::VT_NUM_SCANS_SERVICED_BY_HARDWARE,
+                              num_scans_serviced_by_hardware, 0);
   }
   void add_num_scans_serviced_by_cache(uint32_t num_scans_serviced_by_cache) {
-    fbb_.AddElement<uint32_t>(ScanStats::VT_NUM_SCANS_SERVICED_BY_CACHE, num_scans_serviced_by_cache, 0);
+    fbb_.AddElement<uint32_t>(ScanStats::VT_NUM_SCANS_SERVICED_BY_CACHE,
+                              num_scans_serviced_by_cache, 0);
   }
   void add_updated_at_chre_ms(uint32_t updated_at_chre_ms) {
-    fbb_.AddElement<uint32_t>(ScanStats::VT_UPDATED_AT_CHRE_MS, updated_at_chre_ms, 0);
+    fbb_.AddElement<uint32_t>(ScanStats::VT_UPDATED_AT_CHRE_MS,
+                              updated_at_chre_ms, 0);
   }
   void add_sent_at_chre_ms(uint32_t sent_at_chre_ms) {
-    fbb_.AddElement<uint32_t>(ScanStats::VT_SENT_AT_CHRE_MS, sent_at_chre_ms, 0);
+    fbb_.AddElement<uint32_t>(ScanStats::VT_SENT_AT_CHRE_MS, sent_at_chre_ms,
+                              0);
   }
-  void add_last_subscription_duration_ms(uint32_t last_subscription_duration_ms) {
-    fbb_.AddElement<uint32_t>(ScanStats::VT_LAST_SUBSCRIPTION_DURATION_MS, last_subscription_duration_ms, 0);
+  void add_last_subscription_duration_ms(
+      uint32_t last_subscription_duration_ms) {
+    fbb_.AddElement<uint32_t>(ScanStats::VT_LAST_SUBSCRIPTION_DURATION_MS,
+                              last_subscription_duration_ms, 0);
   }
-  void add_channel_scan_count(flatbuffers::Offset<flatbuffers::Vector<uint8_t>> channel_scan_count) {
+  void add_channel_scan_count(
+      flatbuffers::Offset<flatbuffers::Vector<uint8_t>> channel_scan_count) {
     fbb_.AddOffset(ScanStats::VT_CHANNEL_SCAN_COUNT, channel_scan_count);
   }
-  void add_scan_records(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<wifi_offload::fbs::ScanRecord>>> scan_records) {
+  void add_scan_records(
+      flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<ScanRecord>>>
+          scan_records) {
     fbb_.AddOffset(ScanStats::VT_SCAN_RECORDS, scan_records);
   }
-  void add_rpc_log_records(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<wifi_offload::fbs::RpcLogRecord>>> rpc_log_records) {
+  void add_rpc_log_records(
+      flatbuffers::Offset<
+          flatbuffers::Vector<flatbuffers::Offset<RpcLogRecord>>>
+          rpc_log_records) {
     fbb_.AddOffset(ScanStats::VT_RPC_LOG_RECORDS, rpc_log_records);
   }
-  explicit ScanStatsBuilder(flatbuffers::FlatBufferBuilder &_fbb)
-        : fbb_(_fbb) {
+  explicit ScanStatsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   ScanStatsBuilder &operator=(const ScanStatsBuilder &);
   flatbuffers::Offset<ScanStats> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 9);
     auto o = flatbuffers::Offset<ScanStats>(end);
     return o;
   }
@@ -741,13 +730,13 @@
     flatbuffers::FlatBufferBuilder &_fbb,
     uint32_t num_scans_requested_by_nanoapp = 0,
     uint32_t num_scans_serviced_by_hardware = 0,
-    uint32_t num_scans_serviced_by_cache = 0,
-    uint32_t updated_at_chre_ms = 0,
-    uint32_t sent_at_chre_ms = 0,
-    uint32_t last_subscription_duration_ms = 0,
+    uint32_t num_scans_serviced_by_cache = 0, uint32_t updated_at_chre_ms = 0,
+    uint32_t sent_at_chre_ms = 0, uint32_t last_subscription_duration_ms = 0,
     flatbuffers::Offset<flatbuffers::Vector<uint8_t>> channel_scan_count = 0,
-    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<wifi_offload::fbs::ScanRecord>>> scan_records = 0,
-    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<wifi_offload::fbs::RpcLogRecord>>> rpc_log_records = 0) {
+    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<ScanRecord>>>
+        scan_records = 0,
+    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<RpcLogRecord>>>
+        rpc_log_records = 0) {
   ScanStatsBuilder builder_(_fbb);
   builder_.add_rpc_log_records(rpc_log_records);
   builder_.add_scan_records(scan_records);
@@ -765,27 +754,24 @@
     flatbuffers::FlatBufferBuilder &_fbb,
     uint32_t num_scans_requested_by_nanoapp = 0,
     uint32_t num_scans_serviced_by_hardware = 0,
-    uint32_t num_scans_serviced_by_cache = 0,
-    uint32_t updated_at_chre_ms = 0,
-    uint32_t sent_at_chre_ms = 0,
-    uint32_t last_subscription_duration_ms = 0,
+    uint32_t num_scans_serviced_by_cache = 0, uint32_t updated_at_chre_ms = 0,
+    uint32_t sent_at_chre_ms = 0, uint32_t last_subscription_duration_ms = 0,
     const std::vector<uint8_t> *channel_scan_count = nullptr,
-    const std::vector<flatbuffers::Offset<wifi_offload::fbs::ScanRecord>> *scan_records = nullptr,
-    const std::vector<flatbuffers::Offset<wifi_offload::fbs::RpcLogRecord>> *rpc_log_records = nullptr) {
-  auto channel_scan_count__ = channel_scan_count ? _fbb.CreateVector<uint8_t>(*channel_scan_count) : 0;
-  auto scan_records__ = scan_records ? _fbb.CreateVector<flatbuffers::Offset<wifi_offload::fbs::ScanRecord>>(*scan_records) : 0;
-  auto rpc_log_records__ = rpc_log_records ? _fbb.CreateVector<flatbuffers::Offset<wifi_offload::fbs::RpcLogRecord>>(*rpc_log_records) : 0;
+    const std::vector<flatbuffers::Offset<ScanRecord>> *scan_records = nullptr,
+    const std::vector<flatbuffers::Offset<RpcLogRecord>> *rpc_log_records =
+        nullptr) {
   return wifi_offload::fbs::CreateScanStats(
-      _fbb,
-      num_scans_requested_by_nanoapp,
-      num_scans_serviced_by_hardware,
-      num_scans_serviced_by_cache,
-      updated_at_chre_ms,
-      sent_at_chre_ms,
+      _fbb, num_scans_requested_by_nanoapp, num_scans_serviced_by_hardware,
+      num_scans_serviced_by_cache, updated_at_chre_ms, sent_at_chre_ms,
       last_subscription_duration_ms,
-      channel_scan_count__,
-      scan_records__,
-      rpc_log_records__);
+      channel_scan_count ? _fbb.CreateVector<uint8_t>(*channel_scan_count) : 0,
+      scan_records
+          ? _fbb.CreateVector<flatbuffers::Offset<ScanRecord>>(*scan_records)
+          : 0,
+      rpc_log_records
+          ? _fbb.CreateVector<flatbuffers::Offset<RpcLogRecord>>(
+                *rpc_log_records)
+          : 0);
 }
 
 }  // namespace fbs
diff --git a/apps/wifi_offload/include/chre/apps/wifi_offload/generated/generate_code.sh b/apps/wifi_offload/include/chre/apps/wifi_offload/generated/generate_code.sh
index 15a5ba6..09ab1a7 100755
--- a/apps/wifi_offload/include/chre/apps/wifi_offload/generated/generate_code.sh
+++ b/apps/wifi_offload/include/chre/apps/wifi_offload/generated/generate_code.sh
@@ -1,5 +1,8 @@
 #!/bin/bash -e
 
+# Path to flatc compiler
+FLATC_PATH="$ANDROID_BUILD_TOP/external/flatbuffers/flatc"
+
 # Flat buffer schema files
 FLATC_SRCS="flatbuffers_types.fbs"
 
@@ -7,4 +10,4 @@
 FLATC_ARGS="--cpp --no-includes"
 
 # Generate c++ code
-flatc $FLATC_ARGS $FLATC_SRCS
+$FLATC_PATH $FLATC_ARGS $FLATC_SRCS
diff --git a/build/arch/armv8a.mk b/build/arch/armv8a.mk
new file mode 100644
index 0000000..c9a604d
--- /dev/null
+++ b/build/arch/armv8a.mk
@@ -0,0 +1,44 @@
+#
+# Build targets for an ARMv8 based processor
+#
+
+# The ARMV8A_XX binary path needs to be specified by a
+# higher level makefile
+TARGET_AR = $(ARMV8A_AR)
+TARGET_CC = $(ARMV8A_CC)
+TARGET_LD = $(ARMV8A_LD)
+
+TARGET_CFLAGS += $(DEFINES)
+TARGET_CFLAGS += $(CPPFLAGS)
+COMMON_CXX_CFLAGS += $(CXXFLAGS)
+COMMON_C_CFLAGS += $(CFLAGS)
+
+TARGET_SO_LDFLAGS += $(LDFLAGS)
+TARGET_SO_EARLY_LIBS += $(LDLIBS)
+
+# TODO(stange): Move most of these includes to platform.mk so nanoapps can't
+# refer to AoC APIs
+TARGET_CFLAGS += -I$(AOC_TOP_DIR)/AOC/core/arm/generic/include
+TARGET_CFLAGS += -I$(AOC_TOP_DIR)/AOC/drivers/processor/aoc/include
+TARGET_CFLAGS += -I$(AOC_TOP_DIR)/AOC/drivers/sys_mem/base/include
+TARGET_CFLAGS += -I$(AOC_TOP_DIR)/AOC/libs/bionic_interface/include
+TARGET_CFLAGS += -I$(AOC_TOP_DIR)/AOC/libs/common/basic/include
+TARGET_CFLAGS += -I$(AOC_TOP_DIR)/AOC/libs/common/libc/include
+TARGET_CFLAGS += -I$(AOC_TOP_DIR)/AOC/libs/common/heap/common/include
+TARGET_CFLAGS += -I$(AOC_TOP_DIR)/external/libcxx/include
+
+# TODO: Fix ar_client so the following two can be removed.
+TARGET_CFLAGS += -Wno-strict-prototypes
+TARGET_CFLAGS += -Wno-missing-prototypes
+
+# TODO: Fix log_null so this can be removed.
+TARGET_CFLAGS += -Wno-unused-parameter
+
+TARGET_CFLAGS += -Wframe-larger-than=1024
+
+# Don't add these flags when building just the static archive as they generate
+# sections that will break static linking.
+ifeq ($(IS_ARCHIVE_ONLY_BUILD),)
+TARGET_CFLAGS += -fPIC
+TARGET_SO_LDFLAGS += -shared
+endif
diff --git a/build/build_template.mk b/build/build_template.mk
index fdc5656..b5d8239 100644
--- a/build/build_template.mk
+++ b/build/build_template.mk
@@ -110,7 +110,11 @@
 $(1)_header: $$($$(1)_HEADER)
 
 .PHONY: $(1)
+ifeq ($(IS_ARCHIVE_ONLY_BUILD),true)
+$(1): $(1)_ar
+else
 $(1): $(1)_ar $(1)_so $(1)_bin $(1)_header
+endif
 
 # If building the runtime, simply add the archive and shared object to the all
 # target. When building CHRE, it is expected that this runtime just be linked
diff --git a/build/nanoapp/app.mk b/build/nanoapp/app.mk
index 25f7791..b153345 100644
--- a/build/nanoapp/app.mk
+++ b/build/nanoapp/app.mk
@@ -112,6 +112,7 @@
 GOOGLE_HEXAGONV66_SLPI-SEE_SRCS += $(DSO_SUPPORT_LIB_SRCS)
 GOOGLE_HEXAGONV66_SLPI-SEE-UIMG_SRCS += $(DSO_SUPPORT_LIB_SRCS)
 GOOGLE_ARM64_ANDROID_SRCS += $(DSO_SUPPORT_LIB_SRCS)
+GOOGLE_AOC_SRCS += $(DSO_SUPPORT_LIB_SRCS)
 GOOGLE_X86_LINUX_SRCS += $(DSO_SUPPORT_LIB_SRCS)
 QCOM_HEXAGONV60_NANOHUB_SRCS += $(APP_SUPPORT_PATH)/qcom_nanohub/app_support.cc
 QCOM_HEXAGONV60_NANOHUB-UIMG_SRCS += $(APP_SUPPORT_PATH)/qcom_nanohub/app_support_uimg.cc
@@ -127,6 +128,7 @@
 
 # Supported variants includes
 include $(CHRE_PREFIX)/build/variant/google_arm64_android.mk
+include $(CHRE_PREFIX)/build/variant/google_armv8a_aoc.mk
 include $(CHRE_PREFIX)/build/variant/google_cm4_nanohub.mk
 include $(CHRE_PREFIX)/build/variant/google_hexagonv55_slpi-see.mk
 include $(CHRE_PREFIX)/build/variant/google_hexagonv60_slpi.mk
diff --git a/build/nanoapp/google_aoc.mk b/build/nanoapp/google_aoc.mk
new file mode 100644
index 0000000..2828d2d
--- /dev/null
+++ b/build/nanoapp/google_aoc.mk
@@ -0,0 +1,31 @@
+#
+# Nanoapp Build Rules for Google CHRE on AoC
+#
+
+################################################################################
+#
+# Google Generic CHRE on AoC Nanoapp Build Template
+#
+# Invoke this to instantiate a set of Nanoapp post processing build targets.
+#
+# TARGET_NAME_nanoapp - The resulting nanoapp output.
+#
+# Argument List:
+#     $1 - TARGET_NAME         - The name of the target being built.
+#
+################################################################################
+
+ifndef GOOGLE_AOC_NANOAPP_BUILD_TEMPLATE
+define GOOGLE_AOC_NANOAPP_BUILD_TEMPLATE
+
+.PHONY: $(1)_nanoapp
+all: $(1)_nanoapp
+
+$(1)_nanoapp: $(1)
+
+endef
+endif
+
+# Template Invocation ##########################################################
+
+$(eval $(call GOOGLE_AOC_NANOAPP_BUILD_TEMPLATE, $(TARGET_NAME)))
diff --git a/build/variant/google_armv8a_aoc.mk b/build/variant/google_armv8a_aoc.mk
new file mode 100644
index 0000000..b6d84eb
--- /dev/null
+++ b/build/variant/google_armv8a_aoc.mk
@@ -0,0 +1,77 @@
+include $(CHRE_PREFIX)/build/clean_build_template_args.mk
+
+TARGET_NAME = google_armv8a_aoc
+ifneq ($(filter $(TARGET_NAME)% all, $(MAKECMDGOALS)),)
+
+# Environment Checks
+ifeq ($(AOC_TOP_DIR),)
+$(error "The AoC root source directory needs to be exported as the AOC_TOP_DIR \
+         environment variable")
+endif
+
+ifeq ($(AOC_PLATFORM) ,)
+$(error "The platform/simulator we're building for needs to be exported as the \
+         AOC_PLATFORM environment variable. For example: \
+         export AOC_PLATFORM=qemu")
+endif
+
+SUPPORTED_AOC_PLATFORMS_ON_CHRE := fpga_a32 whi_a0_a32
+ifeq ($(filter $(AOC_PLATFORM),$(SUPPORTED_AOC_PLATFORMS_ON_CHRE)),)
+$(error "Unsupported AoC Platform - $(AOC_PLATFORM) - try PLATFORM=fpga_a32 or\
+         whi_a0_a32")
+endif
+
+# The SRC_DIR variable is used in toolchain selection in AoC, add that as
+# a dependency before including the platform toolchain makefile
+ifeq ($(SRC_DIR),)
+SRC_DIR=$(AOC_TOP_DIR)/AOC
+endif
+
+include $(AOC_TOP_DIR)/AOC/build/$(AOC_PLATFORM)/toolchain.mk
+include $(AOC_TOP_DIR)/AOC/targets/aoc.$(AOC_PLATFORM)/local.mk
+
+# Sized based on the buffer allocated in the host daemon (4096 bytes), minus
+# FlatBuffer overhead (max 80 bytes), minus some extra space to make a nice
+# round number and allow for addition of new fields to the FlatBuffer
+TARGET_CFLAGS = -DCHRE_MESSAGE_TO_HOST_MAX_SIZE=4000
+TARGET_CFLAGS += $(AOC_CFLAGS)
+TARGET_CFLAGS += $(FREERTOS_CFLAGS)
+
+# add platform specific flags
+ifeq ($(AOC_PLATFORM),linux)
+TARGET_CFLAGS += $(AOC_LINUX_CFLAGS)
+endif
+ifeq ($(AOC_PLATFORM),fpga_a32)
+TARGET_CFLAGS += $(AOC_FPGA_A32_CFLAGS)
+# We need a function stack size of at least 400 bytes, which might not be
+# the case by default
+TARGET_CFLAGS += -Wframe-larger-than=420
+endif
+ifeq ($(AOC_PLATFORM),whi_a0_a32)
+TARGET_CFLAGS += $(AOC_WHI_A0_A32_CFLAGS)
+# We need a function stack size of at least 400 bytes, which might not be
+# the case by default
+TARGET_CFLAGS += -Wframe-larger-than=420
+endif
+
+TARGET_VARIANT_SRCS += $(AOC_SRCS)
+TARGET_VARIANT_SRCS += $(FREERTOS_SRCS)
+TARGET_VARIANT_SRCS += $(GOOGLE_AOC_SRCS)
+
+TARGET_PLATFORM_ID = 0x476F6F676C000008
+
+# Set platform-based build variables for arch armv8a
+ARMV8A_AR = $(CLANG_PATH)/llvm-ar
+ARMV8A_CC = $(CXX)
+ARMV8A_LD = $(LD)
+
+ifneq ($(IS_NANOAPP_BUILD),)
+include $(CHRE_PREFIX)/build/nanoapp/google_aoc.mk
+
+# TODO: Remove once dynamic loading is implemented.
+TARGET_CFLAGS += -DCHRE_NANOAPP_DISABLE_BACKCOMPAT
+endif
+
+include $(CHRE_PREFIX)/build/arch/armv8a.mk
+include $(CHRE_PREFIX)/build/build_template.mk
+endif
\ No newline at end of file
diff --git a/chpp/platform/aoc/include/chpp/platform/log.h b/chpp/platform/aoc/include/chpp/platform/log.h
new file mode 100644
index 0000000..71633d8
--- /dev/null
+++ b/chpp/platform/aoc/include/chpp/platform/log.h
@@ -0,0 +1,34 @@
+/*
+ * 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 CHPP_LOG_H_
+#define CHPP_LOG_H_
+
+#include <chre.h>
+#include <inttypes.h>
+
+#define CHPP_AOC_LOG(level, fmt, ...) \
+  chreLog(level, "CHPP: " fmt, ##__VA_ARGS__)
+
+#define CHPP_LOGE(fmt, ...) CHPP_AOC_LOG(CHRE_LOG_ERROR, fmt, ##__VA_ARGS__)
+#define CHPP_LOGW(fmt, ...) CHPP_AOC_LOG(CHRE_LOG_WARN, fmt, ##__VA_ARGS__)
+#define CHPP_LOGI(fmt, ...) CHPP_AOC_LOG(CHRE_LOG_INFO, fmt, ##__VA_ARGS__)
+#define CHPP_LOGD(fmt, ...) CHPP_AOC_LOG(CHRE_LOG_DEBUG, fmt, ##__VA_ARGS__)
+
+#define CHPP_LOG_OOM(fmt, ...) \
+  CHPP_AOC_LOG(CHRE_LOG_ERROR, "(OOM) " fmt, ##__VA_ARGS__)
+
+#endif  // CHPP_LOG_H_
diff --git a/chpp/platform/aoc/include/chpp/platform/platform_link.h b/chpp/platform/aoc/include/chpp/platform/platform_link.h
new file mode 100644
index 0000000..99f7a60
--- /dev/null
+++ b/chpp/platform/aoc/include/chpp/platform/platform_link.h
@@ -0,0 +1,33 @@
+/*
+ * 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 CHPP_PLATFORM_LINK_H_
+#define CHPP_PLATFORM_LINK_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct ChppPlatformLinkParameters {
+  size_t index;
+  bool sync;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // CHPP_PLATFORM_LINK_H_
diff --git a/chpp/platform/aoc/include/chpp/platform/platform_mutex.h b/chpp/platform/aoc/include/chpp/platform/platform_mutex.h
new file mode 100644
index 0000000..c745478
--- /dev/null
+++ b/chpp/platform/aoc/include/chpp/platform/platform_mutex.h
@@ -0,0 +1,65 @@
+/*
+ * 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 CHPP_PLATFORM_MUTEX_H_
+#define CHPP_PLATFORM_MUTEX_H_
+
+#include "chpp/platform/log.h"
+#include "FreeRTOS.h"
+#include "semphr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Encapsulates a mutex handle and its associated semaphore structure.
+ * The static semaphore is used to avoid heap allocations.
+ */
+struct ChppMutex {
+  SemaphoreHandle_t semaphoreHandle;
+  StaticSemaphore_t staticSemaphore;
+};
+
+static inline void chppMutexInit(struct ChppMutex *mutex) {
+  mutex->semaphoreHandle = xSemaphoreCreateMutexStatic(&mutex->staticSemaphore);
+}
+
+static inline void chppMutexDeinit(struct ChppMutex *mutex) {
+  if (mutex->semaphoreHandle) {
+    vSemaphoreDelete(mutex->semaphoreHandle);
+  }
+}
+
+static inline void chppMutexLock(struct ChppMutex *mutex) {
+  TickType_t blockForever = portMAX_DELAY;
+  if (pdTRUE != xSemaphoreTake(mutex->semaphoreHandle, blockForever)) {
+    // TODO: Use CHPP_ASSERT
+    CHPP_LOGE("Failed to lock mutex");
+  }
+}
+
+static inline void chppMutexUnlock(struct ChppMutex *mutex) {
+  if (pdTRUE != xSemaphoreGive(mutex->semaphoreHandle)) {
+    CHPP_LOGE("Failed to properly unlock mutex!");
+  }
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // CHPP_PLATFORM_MUTEX_H_
diff --git a/chpp/platform/aoc/include/chpp/platform/platform_notifier.h b/chpp/platform/aoc/include/chpp/platform/platform_notifier.h
new file mode 100644
index 0000000..9cc6145
--- /dev/null
+++ b/chpp/platform/aoc/include/chpp/platform/platform_notifier.h
@@ -0,0 +1,95 @@
+/*
+ * 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 CHPP_PLATFORM_SYNC_H_
+#define CHPP_PLATFORM_SYNC_H_
+
+#include "chpp/mutex.h"
+
+#include "chpp/platform/log.h"
+#include "FreeRTOS.h"
+#include "semphr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Wrapper structure for a FreeRTOS semaphore, that includes
+ * a static semaphore structure instance to avoid heap allocations
+ */
+struct ChppSemaphore {
+  SemaphoreHandle_t handle;
+  StaticSemaphore_t staticSemaphore;
+};
+
+struct ChppNotifier {
+  struct ChppSemaphore cvSemaphore;
+  struct ChppMutex mutex;  // Platform-specific mutex
+  bool signaled;           // Whether a notification has occurred
+  bool shouldExit;         // Whether the thread should exit
+};
+
+/**
+ * Platform implementation of chppNotifierInit()
+ */
+void chppPlatformNotifierInit(struct ChppNotifier *notifier);
+
+/**
+ * Platform implementation of chppNotifierDeinit()
+ */
+void chppPlatformNotifierDeinit(struct ChppNotifier *notifier);
+
+/**
+ * Platform implementation of chppNotifierWait()
+ */
+bool chppPlatformNotifierWait(struct ChppNotifier *notifier);
+
+/**
+ * Platform implementation of chppNotifierEvent()
+ */
+void chppPlatformNotifierEvent(struct ChppNotifier *notifier);
+
+/**
+ * Platform implementation of chppNotifierExit()
+ */
+void chppPlatformNotifierExit(struct ChppNotifier *notifier);
+
+static inline void chppNotifierInit(struct ChppNotifier *notifier) {
+  chppPlatformNotifierInit(notifier);
+}
+
+static inline void chppNotifierDeinit(struct ChppNotifier *notifier) {
+  chppPlatformNotifierDeinit(notifier);
+}
+
+static inline bool chppNotifierWait(struct ChppNotifier *notifier) {
+  return chppPlatformNotifierWait(notifier);
+}
+
+static inline void chppNotifierEvent(struct ChppNotifier *notifier) {
+  chppPlatformNotifierEvent(notifier);
+}
+
+static inline void chppNotifierExit(struct ChppNotifier *notifier) {
+  chppPlatformNotifierExit(notifier);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // CHPP_PLATFORM_SYNC_H_
diff --git a/chpp/platform/aoc/link.cc b/chpp/platform/aoc/link.cc
new file mode 100644
index 0000000..f94cb83
--- /dev/null
+++ b/chpp/platform/aoc/link.cc
@@ -0,0 +1,25 @@
+/*
+ * 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 "chpp/link.h"
+
+#include "chpp/macros.h"
+
+bool chppPlatformLinkSend(struct ChppPlatformLinkParameters *params,
+                          uint8_t *buf, size_t len) {
+  // TODO: Implement this
+  return params->sync;
+}
diff --git a/chpp/platform/aoc/memory.cc b/chpp/platform/aoc/memory.cc
new file mode 100644
index 0000000..eff5855
--- /dev/null
+++ b/chpp/platform/aoc/memory.cc
@@ -0,0 +1,47 @@
+/*
+ * 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 "chpp/memory.h"
+#include "chpp/macros.h"
+
+#include "chre/platform/memory.h"
+#include "string.h"
+
+void *chppMalloc(const size_t size) {
+  return chre::memoryAlloc(size);
+}
+
+void chppFree(void *ptr) {
+  chre::memoryFree(ptr);
+}
+
+void *chppRealloc(void *oldPtr, const size_t newSize, const size_t oldSize) {
+  if (newSize == 0) {
+    chppFree(oldPtr);
+    return nullptr;
+  }
+  if (newSize == oldSize) {
+    return oldPtr;
+  }
+
+  void *ptr = chppMalloc(newSize);
+  if (ptr != nullptr) {
+    memcpy(ptr, oldPtr, newSize > oldSize ? oldSize : newSize);
+    chppFree(oldPtr);
+  }
+
+  return ptr;
+}
diff --git a/chpp/platform/aoc/notifier.cc b/chpp/platform/aoc/notifier.cc
new file mode 100644
index 0000000..2a00f6b
--- /dev/null
+++ b/chpp/platform/aoc/notifier.cc
@@ -0,0 +1,83 @@
+/*
+ * 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 <stdbool.h>
+
+#include "chpp/macros.h"
+#include "chpp/memory.h"
+#include "chpp/notifier.h"
+
+void chppPlatformNotifierInit(struct ChppNotifier *notifier) {
+  notifier->signaled = false;
+  notifier->shouldExit = false;
+  notifier->cvSemaphore.handle =
+      xSemaphoreCreateBinaryStatic(&notifier->cvSemaphore.staticSemaphore);
+  if (notifier->cvSemaphore.handle == nullptr) {
+    // TODO: Use CHPP_ASSERT
+    CHPP_LOGE("Failed to initialize CHPP notifier");
+  } else {
+    chppMutexInit(&notifier->mutex);
+  }
+}
+
+void chppPlatformNotifierDeinit(struct ChppNotifier *notifier) {
+  if (notifier->cvSemaphore.handle != nullptr) {
+    chppMutexDeinit(&notifier->mutex);
+    vSemaphoreDelete(notifier->cvSemaphore.handle);
+  }
+}
+
+bool chppPlatformNotifierWait(struct ChppNotifier *notifier) {
+  if (notifier->cvSemaphore.handle != nullptr) {
+    chppMutexLock(&notifier->mutex);
+
+    while (!notifier->signaled && !notifier->shouldExit) {
+      chppMutexUnlock(&notifier->mutex);
+      const TickType_t timeout = portMAX_DELAY;  // block indefinitely
+      xSemaphoreTake(notifier->cvSemaphore.handle, timeout);
+      chppMutexLock(&notifier->mutex);
+    }
+    notifier->signaled = false;
+
+    bool shouldExit = notifier->shouldExit;
+    chppMutexUnlock(&notifier->mutex);
+    return !shouldExit;
+  } else {
+    return false;
+  }
+}
+
+void chppPlatformNotifierEvent(struct ChppNotifier *notifier) {
+  if (notifier->cvSemaphore.handle != nullptr) {
+    chppMutexLock(&notifier->mutex);
+
+    notifier->signaled = true;
+    xSemaphoreGive(notifier->cvSemaphore.handle);
+
+    chppMutexUnlock(&notifier->mutex);
+  }
+}
+
+void chppPlatformNotifierExit(struct ChppNotifier *notifier) {
+  if (notifier->cvSemaphore.handle != nullptr) {
+    chppMutexLock(&notifier->mutex);
+
+    notifier->shouldExit = true;
+    xSemaphoreGive(notifier->cvSemaphore.handle);
+
+    chppMutexUnlock(&notifier->mutex);
+  }
+}
diff --git a/chre_daemon.rc b/chre_daemon.rc
index 120da10..544d3fe 100644
--- a/chre_daemon.rc
+++ b/chre_daemon.rc
@@ -17,7 +17,7 @@
 service vendor.chre /vendor/bin/chre
     class late_start
     user context_hub
-    group wakelock context_hub
+    group wakelock context_hub system
     capabilities BLOCK_SUSPEND
     socket chre seqpacket 0660 root context_hub
     shutdown critical
diff --git a/core/include/chre/core/event_loop_common.h b/core/include/chre/core/event_loop_common.h
index 03765f0..ea1cdbc 100644
--- a/core/include/chre/core/event_loop_common.h
+++ b/core/include/chre/core/event_loop_common.h
@@ -53,6 +53,7 @@
   SettingChangeEvent,
   GnssLocationReportEvent,
   GnssMeasurementReportEvent,
+  TimerSyncRequest,
 };
 
 //! The function signature of a system callback mirrors the CHRE event free
diff --git a/core/include/chre/core/host_comms_manager.h b/core/include/chre/core/host_comms_manager.h
index 22956a0..4a2ebcc 100644
--- a/core/include/chre/core/host_comms_manager.h
+++ b/core/include/chre/core/host_comms_manager.h
@@ -175,6 +175,14 @@
    */
   void onMessageToHostComplete(const MessageToHost *msgToHost);
 
+  /**
+   * @return A reference to the platform's host link implementation giving the
+   *         ability to communicate to the host AP.
+   */
+  HostLink &getHostLink() {
+    return mHostLink;
+  }
+
  private:
   //! The maximum number of messages we can have outstanding at any given time
   static constexpr size_t kMaxOutstandingMessages = 32;
diff --git a/external/external.mk b/external/external.mk
index 4a04a13..c95b43e 100644
--- a/external/external.mk
+++ b/external/external.mk
@@ -29,7 +29,7 @@
 #
 # Kiss FFT
 #
-
+ifeq ($(CHRE_AUDIO_SUPPORT_ENABLED), true)
 # Common Compiler Flags ########################################################
 
 # Include paths.
@@ -42,3 +42,4 @@
 
 COMMON_SRCS += external/kiss_fft/kiss_fft.c
 COMMON_SRCS += external/kiss_fft/kiss_fftr.c
+endif
diff --git a/external/flatbuffers/README.md b/external/flatbuffers/README.md
index 09cc0f4..65ccf32 100644
--- a/external/flatbuffers/README.md
+++ b/external/flatbuffers/README.md
@@ -3,7 +3,6 @@
 When upgrading to a newer FlatBuffers release, be sure to manually merge the
 changes described in the comment at the top of flatbuffers.h, and apply them to
 new additions as well (e.g. removal of std::string usage) to maintain support.
-The FlatBuffers IDL compiler (flatc) can be used without modification, but must
-match the version of the Flatbuffers library used here.
+The FlatBuffers IDL compiler (flatc) can be used without modification.
 
 The FlatBuffers project is hosted at https://github.com/google/flatbuffers/
diff --git a/external/flatbuffers/include/flatbuffers/flatbuffers.h b/external/flatbuffers/include/flatbuffers/flatbuffers.h
index 5ca119e..07ffffe 100644
--- a/external/flatbuffers/include/flatbuffers/flatbuffers.h
+++ b/external/flatbuffers/include/flatbuffers/flatbuffers.h
@@ -24,78 +24,212 @@
  * via the introduction of the feature flag FLATBUFFERS_CHRE. When defined,
  * standard library features not used in CHRE are removed or remapped to their
  * CHRE-specific alternatives. This includes removing support for strings,
- * replacing std::vector with chre::DynamicVector, use of CHRE_ASSERT, removal
- * of uses of std::function, etc.
+ * replacing std::vector with chre::DynamicVector, use of CHRE_ASSERT instead of
+ * assert(), etc.
  */
 
-#ifdef FLATBUFFERS_CHRE
-#include "chre/util/container_support.h"
-#include "chre/util/dynamic_vector.h"
+#include <cstdint>
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
+#include <utility>
+#include <type_traits>
+#include <vector>
+#include <algorithm>
+#include <memory>
 
-// Before the flatbuffers/base.h include where it's used
-#define FLATBUFFERS_ASSERT CHRE_ASSERT
+#ifndef FLATBUFFERS_CHRE
+  #include <assert.h>
+
+  #include <set>
+  #include <string>
+#else
+  // TODO: we should be able to leave this flag unset if we connect unique_ptr_t
+  // to chre::UniquePtr, but the features wrapped by this flag (e.g. use of
+  // std::function) aren't strictly required, so setting it for now.
+  #define FLATBUFFERS_CPP98_STL
+
+  #include "chre/util/container_support.h"
+  #include "chre/util/dynamic_vector.h"
+  #include "chre/util/unique_ptr.h"
+
+  #ifndef CHRE_ASSERT_USES_STDLIB_ASSERT
+    #pragma push_macro("assert")
+    #define assert CHRE_ASSERT
+  #endif  // CHRE_ASSERT_USES_STDLIB_ASSERT
+#endif  // FLATBUFFERS_CHRE
+#ifdef _STLPORT_VERSION
+  #define FLATBUFFERS_CPP98_STL
+#endif
+#ifndef FLATBUFFERS_CPP98_STL
+  #include <functional>
 #endif
 
-#include "flatbuffers/base.h"
-
-#if defined(FLATBUFFERS_NAN_DEFAULTS)
-#  include <cmath>
+/// @cond FLATBUFFERS_INTERNAL
+#if __cplusplus <= 199711L && \
+    (!defined(_MSC_VER) || _MSC_VER < 1600) && \
+    (!defined(__GNUC__) || \
+      (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40400))
+  #error A C++11 compatible compiler with support for the auto typing is \
+         required for FlatBuffers.
+  #error __cplusplus _MSC_VER __GNUC__  __GNUC_MINOR__  __GNUC_PATCHLEVEL__
 #endif
 
+#if !defined(__clang__) && \
+    defined(__GNUC__) && \
+    (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40600)
+  // Backwards compatability for g++ 4.4, and 4.5 which don't have the nullptr
+  // and constexpr keywords. Note the __clang__ check is needed, because clang
+  // presents itself as an older GNUC compiler.
+  #ifndef nullptr_t
+    const class nullptr_t {
+    public:
+      template<class T> inline operator T*() const { return 0; }
+    private:
+      void operator&() const;
+    } nullptr = {};
+  #endif
+  #ifndef constexpr
+    #define constexpr const
+  #endif
+#endif
+
+// The wire format uses a little endian encoding (since that's efficient for
+// the common platforms).
+#if !defined(FLATBUFFERS_LITTLEENDIAN)
+  #if defined(__GNUC__) || defined(__clang__)
+    #ifdef __BIG_ENDIAN__
+      #define FLATBUFFERS_LITTLEENDIAN 0
+    #else
+      #define FLATBUFFERS_LITTLEENDIAN 1
+    #endif // __BIG_ENDIAN__
+  #elif defined(_MSC_VER)
+    #if defined(_M_PPC)
+      #define FLATBUFFERS_LITTLEENDIAN 0
+    #else
+      #define FLATBUFFERS_LITTLEENDIAN 1
+    #endif
+  #else
+    #error Unable to determine endianness, define FLATBUFFERS_LITTLEENDIAN.
+  #endif
+#endif // !defined(FLATBUFFERS_LITTLEENDIAN)
+
+#define FLATBUFFERS_VERSION_MAJOR 1
+#define FLATBUFFERS_VERSION_MINOR 6
+#define FLATBUFFERS_VERSION_REVISION 0
+#define FLATBUFFERS_STRING_EXPAND(X) #X
+#define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X)
+
+#if (!defined(_MSC_VER) || _MSC_VER > 1600) && \
+    (!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 407))
+  #define FLATBUFFERS_FINAL_CLASS final
+#else
+  #define FLATBUFFERS_FINAL_CLASS
+#endif
+
+#if (!defined(_MSC_VER) || _MSC_VER >= 1900) && \
+    (!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 406))
+  #define FLATBUFFERS_CONSTEXPR constexpr
+#else
+  #define FLATBUFFERS_CONSTEXPR
+#endif
+
+/// @endcond
+
+/// @file
 namespace flatbuffers {
-// Generic 'operator==' with conditional specialisations.
-// T e - new value of a scalar field.
-// T def - default of scalar (is known at compile-time).
-template<typename T> inline bool IsTheSameAs(T e, T def) { return e == def; }
 
-#if defined(FLATBUFFERS_NAN_DEFAULTS) && \
-    defined(FLATBUFFERS_HAS_NEW_STRTOD) && (FLATBUFFERS_HAS_NEW_STRTOD > 0)
-// Like `operator==(e, def)` with weak NaN if T=(float|double).
-template<typename T> inline bool IsFloatTheSameAs(T e, T def) {
-  return (e == def) || ((def != def) && (e != e));
-}
-template<> inline bool IsTheSameAs<float>(float e, float def) {
-  return IsFloatTheSameAs(e, def);
-}
-template<> inline bool IsTheSameAs<double>(double e, double def) {
-  return IsFloatTheSameAs(e, def);
-}
+/// @cond FLATBUFFERS_INTERNAL
+// Our default offset / size type, 32bit on purpose on 64bit systems.
+// Also, using a consistent offset type maintains compatibility of serialized
+// offset values between 32bit and 64bit systems.
+typedef uint32_t uoffset_t;
+
+// Signed offsets for references that can go in both directions.
+typedef int32_t soffset_t;
+
+// Offset/index used in v-tables, can be changed to uint8_t in
+// format forks to save a bit of space if desired.
+typedef uint16_t voffset_t;
+
+typedef uintmax_t largest_scalar_t;
+
+// In 32bits, this evaluates to 2GB - 1
+#define FLATBUFFERS_MAX_BUFFER_SIZE ((1ULL << (sizeof(soffset_t) * 8 - 1)) - 1)
+
+// We support aligning the contents of buffers up to this size.
+#define FLATBUFFERS_MAX_ALIGNMENT 16
+
+#ifndef FLATBUFFERS_CPP98_STL
+// Pointer to relinquished memory.
+typedef std::unique_ptr<uint8_t, std::function<void(uint8_t * /* unused */)>>
+          unique_ptr_t;
 #endif
 
-// Check 'v' is out of closed range [low; high].
-// Workaround for GCC warning [-Werror=type-limits]:
-// comparison is always true due to limited range of data type.
-template<typename T>
-inline bool IsOutRange(const T &v, const T &low, const T &high) {
-  return (v < low) || (high < v);
-}
-
-// Check 'v' is in closed range [low; high].
-template<typename T>
-inline bool IsInRange(const T &v, const T &low, const T &high) {
-  return !IsOutRange(v, low, high);
-}
-
 // Wrapper for uoffset_t to allow safe template specialization.
-// Value is allowed to be 0 to indicate a null object (see e.g. AddOffset).
 template<typename T> struct Offset {
   uoffset_t o;
   Offset() : o(0) {}
   Offset(uoffset_t _o) : o(_o) {} // NOLINT(google-explicit-constructor)
   Offset<void> Union() const { return Offset<void>(o); }
-  bool IsNull() const { return !o; }
 };
 
 inline void EndianCheck() {
   int endiantest = 1;
   // If this fails, see FLATBUFFERS_LITTLEENDIAN above.
-  FLATBUFFERS_ASSERT(*reinterpret_cast<char *>(&endiantest) ==
-                     FLATBUFFERS_LITTLEENDIAN);
+  assert(*reinterpret_cast<char *>(&endiantest) == FLATBUFFERS_LITTLEENDIAN);
   (void)endiantest;
 }
 
-template<typename T> FLATBUFFERS_CONSTEXPR size_t AlignOf() {
-  // clang-format off
+template<typename T> T EndianSwap(T t) {
+  #if defined(_MSC_VER)
+    #define FLATBUFFERS_BYTESWAP16 _byteswap_ushort
+    #define FLATBUFFERS_BYTESWAP32 _byteswap_ulong
+    #define FLATBUFFERS_BYTESWAP64 _byteswap_uint64
+  #else
+    #if defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ < 408
+      // __builtin_bswap16 was missing prior to GCC 4.8.
+      #define FLATBUFFERS_BYTESWAP16(x) \
+        static_cast<uint16_t>(__builtin_bswap32(static_cast<uint32_t>(x) << 16))
+    #else
+      #define FLATBUFFERS_BYTESWAP16 __builtin_bswap16
+    #endif
+    #define FLATBUFFERS_BYTESWAP32 __builtin_bswap32
+    #define FLATBUFFERS_BYTESWAP64 __builtin_bswap64
+  #endif
+  if (sizeof(T) == 1) {   // Compile-time if-then's.
+    return t;
+  } else if (sizeof(T) == 2) {
+    auto r = FLATBUFFERS_BYTESWAP16(*reinterpret_cast<uint16_t *>(&t));
+    return *reinterpret_cast<T *>(&r);
+  } else if (sizeof(T) == 4) {
+    auto r = FLATBUFFERS_BYTESWAP32(*reinterpret_cast<uint32_t *>(&t));
+    return *reinterpret_cast<T *>(&r);
+  } else if (sizeof(T) == 8) {
+    auto r = FLATBUFFERS_BYTESWAP64(*reinterpret_cast<uint64_t *>(&t));
+    return *reinterpret_cast<T *>(&r);
+  } else {
+    assert(0);
+  }
+}
+
+template<typename T> T EndianScalar(T t) {
+  #if FLATBUFFERS_LITTLEENDIAN
+    return t;
+  #else
+    return EndianSwap(t);
+  #endif
+}
+
+template<typename T> T ReadScalar(const void *p) {
+  return EndianScalar(*reinterpret_cast<const T *>(p));
+}
+
+template<typename T> void WriteScalar(void *p, T t) {
+  *reinterpret_cast<T *>(p) = EndianScalar(t);
+}
+
+template<typename T> size_t AlignOf() {
   #ifdef _MSC_VER
     return __alignof(T);
   #else
@@ -105,7 +239,6 @@
       return alignof(T);
     #endif
   #endif
-  // clang-format on
 }
 
 // When we read serialized data from memory, in the case of most scalars,
@@ -144,51 +277,49 @@
 
 // An STL compatible iterator implementation for Vector below, effectively
 // calling Get() for every element.
-template<typename T, typename IT> struct VectorIterator {
-  typedef std::random_access_iterator_tag iterator_category;
-  typedef IT value_type;
-  typedef ptrdiff_t difference_type;
-  typedef IT *pointer;
-  typedef IT &reference;
+template<typename T, typename IT>
+struct VectorIterator
+    : public std::iterator<std::random_access_iterator_tag, IT, uoffset_t> {
 
-  VectorIterator(const uint8_t *data, uoffset_t i)
-      : data_(data + IndirectHelper<T>::element_stride * i) {}
+  typedef std::iterator<std::random_access_iterator_tag, IT, uoffset_t> super_type;
+
+public:
+  VectorIterator(const uint8_t *data, uoffset_t i) :
+      data_(data + IndirectHelper<T>::element_stride * i) {}
   VectorIterator(const VectorIterator &other) : data_(other.data_) {}
-  VectorIterator() : data_(nullptr) {}
+  #ifndef FLATBUFFERS_CPP98_STL
+  VectorIterator(VectorIterator &&other) : data_(std::move(other.data_)) {}
+  #endif
 
   VectorIterator &operator=(const VectorIterator &other) {
     data_ = other.data_;
     return *this;
   }
 
-  // clang-format off
-  #if !defined(FLATBUFFERS_CPP98_STL)
   VectorIterator &operator=(VectorIterator &&other) {
     data_ = other.data_;
     return *this;
   }
-  #endif  // !defined(FLATBUFFERS_CPP98_STL)
-  // clang-format on
 
   bool operator==(const VectorIterator &other) const {
     return data_ == other.data_;
   }
 
-  bool operator<(const VectorIterator &other) const {
-    return data_ < other.data_;
-  }
-
   bool operator!=(const VectorIterator &other) const {
     return data_ != other.data_;
   }
 
-  difference_type operator-(const VectorIterator &other) const {
+  ptrdiff_t operator-(const VectorIterator &other) const {
     return (data_ - other.data_) / IndirectHelper<T>::element_stride;
   }
 
-  IT operator*() const { return IndirectHelper<T>::Read(data_, 0); }
+  typename super_type::value_type operator *() const {
+    return IndirectHelper<T>::Read(data_, 0);
+  }
 
-  IT operator->() const { return IndirectHelper<T>::Read(data_, 0); }
+  typename super_type::value_type operator->() const {
+    return IndirectHelper<T>::Read(data_, 0);
+  }
 
   VectorIterator &operator++() {
     data_ += IndirectHelper<T>::element_stride;
@@ -201,12 +332,11 @@
     return temp;
   }
 
-  VectorIterator operator+(const uoffset_t &offset) const {
-    return VectorIterator(data_ + offset * IndirectHelper<T>::element_stride,
-                          0);
+  VectorIterator operator+(const uoffset_t &offset) {
+    return VectorIterator(data_ + offset * IndirectHelper<T>::element_stride, 0);
   }
 
-  VectorIterator &operator+=(const uoffset_t &offset) {
+  VectorIterator& operator+=(const uoffset_t &offset) {
     data_ += offset * IndirectHelper<T>::element_stride;
     return *this;
   }
@@ -222,60 +352,38 @@
     return temp;
   }
 
-  VectorIterator operator-(const uoffset_t &offset) const {
-    return VectorIterator(data_ - offset * IndirectHelper<T>::element_stride,
-                          0);
+  VectorIterator operator-(const uoffset_t &offset) {
+    return VectorIterator(data_ - offset * IndirectHelper<T>::element_stride, 0);
   }
 
-  VectorIterator &operator-=(const uoffset_t &offset) {
+  VectorIterator& operator-=(const uoffset_t &offset) {
     data_ -= offset * IndirectHelper<T>::element_stride;
     return *this;
   }
 
- private:
+private:
   const uint8_t *data_;
 };
 
-template<typename Iterator>
-struct VectorReverseIterator : public std::reverse_iterator<Iterator> {
-  explicit VectorReverseIterator(Iterator iter)
-      : std::reverse_iterator<Iterator>(iter) {}
-
-  typename Iterator::value_type operator*() const {
-    return *(std::reverse_iterator<Iterator>::current);
-  }
-
-  typename Iterator::value_type operator->() const {
-    return *(std::reverse_iterator<Iterator>::current);
-  }
-};
-
-#ifndef FLATBUFFERS_CHRE
-struct String;
-#endif
-
 // This is used as a helper type for accessing vectors.
 // Vector::data() assumes the vector elements start after the length field.
 template<typename T> class Vector {
- public:
+public:
   typedef VectorIterator<T, typename IndirectHelper<T>::mutable_return_type>
-      iterator;
+    iterator;
   typedef VectorIterator<T, typename IndirectHelper<T>::return_type>
-      const_iterator;
-  typedef VectorReverseIterator<iterator> reverse_iterator;
-  typedef VectorReverseIterator<const_iterator> const_reverse_iterator;
+    const_iterator;
 
   uoffset_t size() const { return EndianScalar(length_); }
 
   // Deprecated: use size(). Here for backwards compatibility.
-  FLATBUFFERS_ATTRIBUTE(deprecated("use size() instead"))
   uoffset_t Length() const { return size(); }
 
   typedef typename IndirectHelper<T>::return_type return_type;
   typedef typename IndirectHelper<T>::mutable_return_type mutable_return_type;
 
   return_type Get(uoffset_t i) const {
-    FLATBUFFERS_ASSERT(i < size());
+    assert(i < size());
     return IndirectHelper<T>::Read(Data(), i);
   }
 
@@ -288,20 +396,6 @@
     return static_cast<E>(Get(i));
   }
 
-  // If this a vector of unions, this does the cast for you. There's no check
-  // to make sure this is the right type!
-  template<typename U> const U *GetAs(uoffset_t i) const {
-    return reinterpret_cast<const U *>(Get(i));
-  }
-
-  #ifndef FLATBUFFERS_CHRE
-  // If this a vector of unions, this does the cast for you. There's no check
-  // to make sure this is actually a string!
-  const String *GetAsString(uoffset_t i) const {
-    return reinterpret_cast<const String *>(Get(i));
-  }
-  #endif
-
   const void *GetStructFromOffset(size_t o) const {
     return reinterpret_cast<const void *>(Data() + o);
   }
@@ -312,28 +406,10 @@
   iterator end() { return iterator(Data(), size()); }
   const_iterator end() const { return const_iterator(Data(), size()); }
 
-  reverse_iterator rbegin() { return reverse_iterator(end() - 1); }
-  const_reverse_iterator rbegin() const {
-    return const_reverse_iterator(end() - 1);
-  }
-
-  reverse_iterator rend() { return reverse_iterator(begin() - 1); }
-  const_reverse_iterator rend() const {
-    return const_reverse_iterator(begin() - 1);
-  }
-
-  const_iterator cbegin() const { return begin(); }
-
-  const_iterator cend() const { return end(); }
-
-  const_reverse_iterator crbegin() const { return rbegin(); }
-
-  const_reverse_iterator crend() const { return rend(); }
-
   // Change elements if you have a non-const pointer to this object.
   // Scalars only. See reflection.h, and the documentation.
-  void Mutate(uoffset_t i, const T &val) {
-    FLATBUFFERS_ASSERT(i < size());
+  void Mutate(uoffset_t i, const T& val) {
+    assert(i < size());
     WriteScalar(data() + i, val);
   }
 
@@ -341,15 +417,15 @@
   // "val" points to the new table/string, as you can obtain from
   // e.g. reflection::AddFlatBuffer().
   void MutateOffset(uoffset_t i, const uint8_t *val) {
-    FLATBUFFERS_ASSERT(i < size());
-    static_assert(sizeof(T) == sizeof(uoffset_t), "Unrelated types");
+    assert(i < size());
+    assert(sizeof(T) == sizeof(uoffset_t));
     WriteScalar(data() + i,
                 static_cast<uoffset_t>(val - (Data() + i * sizeof(uoffset_t))));
   }
 
   // Get a mutable pointer to tables/strings inside this vector.
   mutable_return_type GetMutableObject(uoffset_t i) const {
-    FLATBUFFERS_ASSERT(i < size());
+    assert(i < size());
     return const_cast<mutable_return_type>(IndirectHelper<T>::Read(Data(), i));
   }
 
@@ -358,15 +434,17 @@
     return reinterpret_cast<const uint8_t *>(&length_ + 1);
   }
 
-  uint8_t *Data() { return reinterpret_cast<uint8_t *>(&length_ + 1); }
+  uint8_t *Data() {
+    return reinterpret_cast<uint8_t *>(&length_ + 1);
+  }
 
   // Similarly, but typed, much like std::vector::data
   const T *data() const { return reinterpret_cast<const T *>(Data()); }
   T *data() { return reinterpret_cast<T *>(Data()); }
 
   template<typename K> return_type LookupByKey(K key) const {
-    void *search_result = std::bsearch(
-        &key, Data(), size(), IndirectHelper<T>::element_stride, KeyCompare<K>);
+    void *search_result = std::bsearch(&key, Data(), size(),
+        IndirectHelper<T>::element_stride, KeyCompare<K>);
 
     if (!search_result) {
       return nullptr;  // Key not found.
@@ -377,19 +455,14 @@
     return IndirectHelper<T>::Read(element, 0);
   }
 
- protected:
+protected:
   // This class is only used to access pre-existing data. Don't ever
   // try to construct these manually.
   Vector();
 
   uoffset_t length_;
 
- private:
-  // This class is a pointer. Copying will therefore create an invalid object.
-  // Private and unimplemented copy constructor.
-  Vector(const Vector &);
-  Vector &operator=(const Vector &);
-
+private:
   template<typename K> static int KeyCompare(const void *ap, const void *bp) {
     const K *key = reinterpret_cast<const K *>(ap);
     const uint8_t *data = reinterpret_cast<const uint8_t *>(bp);
@@ -404,662 +477,177 @@
 // Represent a vector much like the template above, but in this case we
 // don't know what the element types are (used with reflection.h).
 class VectorOfAny {
- public:
+public:
   uoffset_t size() const { return EndianScalar(length_); }
 
   const uint8_t *Data() const {
     return reinterpret_cast<const uint8_t *>(&length_ + 1);
   }
-  uint8_t *Data() { return reinterpret_cast<uint8_t *>(&length_ + 1); }
-
- protected:
+  uint8_t *Data() {
+    return reinterpret_cast<uint8_t *>(&length_ + 1);
+  }
+protected:
   VectorOfAny();
 
   uoffset_t length_;
-
- private:
-  VectorOfAny(const VectorOfAny &);
-  VectorOfAny &operator=(const VectorOfAny &);
 };
 
-#ifndef FLATBUFFERS_CPP98_STL
-template<typename T, typename U>
-Vector<Offset<T>> *VectorCast(Vector<Offset<U>> *ptr) {
-  static_assert(std::is_base_of<T, U>::value, "Unrelated types");
-  return reinterpret_cast<Vector<Offset<T>> *>(ptr);
-}
-
-template<typename T, typename U>
-const Vector<Offset<T>> *VectorCast(const Vector<Offset<U>> *ptr) {
-  static_assert(std::is_base_of<T, U>::value, "Unrelated types");
-  return reinterpret_cast<const Vector<Offset<T>> *>(ptr);
-}
-#endif
-
 // Convenient helper function to get the length of any vector, regardless
-// of whether it is null or not (the field is not set).
+// of wether it is null or not (the field is not set).
 template<typename T> static inline size_t VectorLength(const Vector<T> *v) {
-  return v ? v->size() : 0;
+  return v ? v->Length() : 0;
 }
 
-// This is used as a helper type for accessing arrays.
-template<typename T, uint16_t length> class Array {
-  typedef
-      typename flatbuffers::integral_constant<bool,
-                                              flatbuffers::is_scalar<T>::value>
-          scalar_tag;
-  typedef
-      typename flatbuffers::conditional<scalar_tag::value, T, const T *>::type
-          IndirectHelperType;
-
- public:
-  typedef typename IndirectHelper<IndirectHelperType>::return_type return_type;
-  typedef VectorIterator<T, return_type> const_iterator;
-  typedef VectorReverseIterator<const_iterator> const_reverse_iterator;
-
-  FLATBUFFERS_CONSTEXPR uint16_t size() const { return length; }
-
-  return_type Get(uoffset_t i) const {
-    FLATBUFFERS_ASSERT(i < size());
-    return IndirectHelper<IndirectHelperType>::Read(Data(), i);
-  }
-
-  return_type operator[](uoffset_t i) const { return Get(i); }
-
-  // If this is a Vector of enums, T will be its storage type, not the enum
-  // type. This function makes it convenient to retrieve value with enum
-  // type E.
-  template<typename E> E GetEnum(uoffset_t i) const {
-    return static_cast<E>(Get(i));
-  }
-
-  const_iterator begin() const { return const_iterator(Data(), 0); }
-  const_iterator end() const { return const_iterator(Data(), size()); }
-
-  const_reverse_iterator rbegin() const {
-    return const_reverse_iterator(end());
-  }
-  const_reverse_iterator rend() const { return const_reverse_iterator(end()); }
-
-  const_iterator cbegin() const { return begin(); }
-  const_iterator cend() const { return end(); }
-
-  const_reverse_iterator crbegin() const { return rbegin(); }
-  const_reverse_iterator crend() const { return rend(); }
-
-  // Get a mutable pointer to elements inside this array.
-  // This method used to mutate arrays of structs followed by a @p Mutate
-  // operation. For primitive types use @p Mutate directly.
-  // @warning Assignments and reads to/from the dereferenced pointer are not
-  //  automatically converted to the correct endianness.
-  typename flatbuffers::conditional<scalar_tag::value, void, T *>::type
-  GetMutablePointer(uoffset_t i) const {
-    FLATBUFFERS_ASSERT(i < size());
-    return const_cast<T *>(&data()[i]);
-  }
-
-  // Change elements if you have a non-const pointer to this object.
-  void Mutate(uoffset_t i, const T &val) { MutateImpl(scalar_tag(), i, val); }
-
-  // The raw data in little endian format. Use with care.
-  const uint8_t *Data() const { return data_; }
-
-  uint8_t *Data() { return data_; }
-
-  // Similarly, but typed, much like std::vector::data
-  const T *data() const { return reinterpret_cast<const T *>(Data()); }
-  T *data() { return reinterpret_cast<T *>(Data()); }
-
- protected:
-  void MutateImpl(flatbuffers::integral_constant<bool, true>, uoffset_t i,
-                  const T &val) {
-    FLATBUFFERS_ASSERT(i < size());
-    WriteScalar(data() + i, val);
-  }
-
-  void MutateImpl(flatbuffers::integral_constant<bool, false>, uoffset_t i,
-                  const T &val) {
-    *(GetMutablePointer(i)) = val;
-  }
-
-  // This class is only used to access pre-existing data. Don't ever
-  // try to construct these manually.
-  // 'constexpr' allows us to use 'size()' at compile time.
-  // @note Must not use 'FLATBUFFERS_CONSTEXPR' here, as const is not allowed on
-  //  a constructor.
-#if defined(__cpp_constexpr)
-  constexpr Array();
-#else
-  Array();
-#endif
-
-  uint8_t data_[length * sizeof(T)];
-
- private:
-  // This class is a pointer. Copying will therefore create an invalid object.
-  // Private and unimplemented copy constructor.
-  Array(const Array &);
-  Array &operator=(const Array &);
-};
-
-// Specialization for Array[struct] with access using Offset<void> pointer.
-// This specialization used by idl_gen_text.cpp.
-template<typename T, uint16_t length> class Array<Offset<T>, length> {
-  static_assert(flatbuffers::is_same<T, void>::value, "unexpected type T");
-
- public:
-  typedef const void *return_type;
-
-  const uint8_t *Data() const { return data_; }
-
-  // Make idl_gen_text.cpp::PrintContainer happy.
-  return_type operator[](uoffset_t) const {
-    FLATBUFFERS_ASSERT(false);
-    return nullptr;
-  }
-
- private:
-  // This class is only used to access pre-existing data.
-  Array();
-  Array(const Array &);
-  Array &operator=(const Array &);
-
-  uint8_t data_[1];
-};
-
 #ifndef FLATBUFFERS_CHRE
-// Lexicographically compare two strings (possibly containing nulls), and
-// return true if the first is less than the second.
-static inline bool StringLessThan(const char *a_data, uoffset_t a_size,
-                                  const char *b_data, uoffset_t b_size) {
-  const auto cmp = memcmp(a_data, b_data, (std::min)(a_size, b_size));
-  return cmp == 0 ? a_size < b_size : cmp < 0;
-}
-
 struct String : public Vector<char> {
   const char *c_str() const { return reinterpret_cast<const char *>(Data()); }
-  std::string str() const { return std::string(c_str(), size()); }
+  std::string str() const { return std::string(c_str(), Length()); }
 
-  // clang-format off
-  #ifdef FLATBUFFERS_HAS_STRING_VIEW
-  flatbuffers::string_view string_view() const {
-    return flatbuffers::string_view(c_str(), size());
-  }
-  #endif // FLATBUFFERS_HAS_STRING_VIEW
-  // clang-format on
-
-  bool operator<(const String &o) const {
-    return StringLessThan(this->data(), this->size(), o.data(), o.size());
+  bool operator <(const String &o) const {
+    return strcmp(c_str(), o.c_str()) < 0;
   }
 };
+#endif  // FLATBUFFERS_CHRE
 
-// Convenience function to get std::string from a String returning an empty
-// string on null pointer.
-static inline std::string GetString(const String *str) {
-  return str ? str->str() : "";
-}
-
-// Convenience function to get char* from a String returning an empty string on
-// null pointer.
-static inline const char *GetCstring(const String *str) {
-  return str ? str->c_str() : "";
-}
-#endif  // !FLATBUFFERS_CHRE
-
-// Allocator interface. This is flatbuffers-specific and meant only for
-// `vector_downward` usage.
-class Allocator {
+// Simple indirection for buffer allocation, to allow this to be overridden
+// with custom allocation (see the FlatBufferBuilder constructor).
+class simple_allocator {
  public:
-  virtual ~Allocator() {}
-
-  // Allocate `size` bytes of memory.
-  virtual uint8_t *allocate(size_t size) = 0;
-
-  // Deallocate `size` bytes of memory at `p` allocated by this allocator.
-  virtual void deallocate(uint8_t *p, size_t size) = 0;
-
-  // Reallocate `new_size` bytes of memory, replacing the old region of size
-  // `old_size` at `p`. In contrast to a normal realloc, this grows downwards,
-  // and is intended specifcally for `vector_downward` use.
-  // `in_use_back` and `in_use_front` indicate how much of `old_size` is
-  // actually in use at each end, and needs to be copied.
-  virtual uint8_t *reallocate_downward(uint8_t *old_p, size_t old_size,
-                                       size_t new_size, size_t in_use_back,
-                                       size_t in_use_front) {
-    FLATBUFFERS_ASSERT(new_size > old_size);  // vector_downward only grows
-    uint8_t *new_p = allocate(new_size);
-    memcpy_downward(old_p, old_size, new_p, new_size, in_use_back,
-                    in_use_front);
-    deallocate(old_p, old_size);
-    return new_p;
-  }
-
- protected:
-  // Called by `reallocate_downward` to copy memory from `old_p` of `old_size`
-  // to `new_p` of `new_size`. Only memory of size `in_use_front` and
-  // `in_use_back` will be copied from the front and back of the old memory
-  // allocation.
-  void memcpy_downward(uint8_t *old_p, size_t old_size, uint8_t *new_p,
-                       size_t new_size, size_t in_use_back,
-                       size_t in_use_front) {
-    memcpy(new_p + new_size - in_use_back, old_p + old_size - in_use_back,
-           in_use_back);
-    memcpy(new_p, old_p, in_use_front);
-  }
-};
-
-// DefaultAllocator uses new/delete to allocate memory regions
-class DefaultAllocator : public Allocator {
- public:
-  uint8_t *allocate(size_t size) FLATBUFFERS_OVERRIDE {
+  virtual ~simple_allocator() {}
+  virtual uint8_t *allocate(size_t size) const {
     #ifndef FLATBUFFERS_CHRE
       return new uint8_t[size];
     #else
       return static_cast<uint8_t *>(chre::memoryAlloc(size));
     #endif
   }
-
-  void deallocate(uint8_t *p, size_t) FLATBUFFERS_OVERRIDE {
+  virtual void deallocate(uint8_t *p) const {
     #ifndef FLATBUFFERS_CHRE
       delete[] p;
     #else
       return chre::memoryFree(p);
     #endif
   }
-
-  static void dealloc(void *p, size_t) { delete[] static_cast<uint8_t *>(p); }
-};
-
-// These functions allow for a null allocator to mean use the default allocator,
-// as used by DetachedBuffer and vector_downward below.
-// This is to avoid having a statically or dynamically allocated default
-// allocator, or having to move it between the classes that may own it.
-inline uint8_t *Allocate(Allocator *allocator, size_t size) {
-  return allocator ? allocator->allocate(size)
-                   : DefaultAllocator().allocate(size);
-}
-
-inline void Deallocate(Allocator *allocator, uint8_t *p, size_t size) {
-  if (allocator)
-    allocator->deallocate(p, size);
-  else
-    DefaultAllocator().deallocate(p, size);
-}
-
-inline uint8_t *ReallocateDownward(Allocator *allocator, uint8_t *old_p,
-                                   size_t old_size, size_t new_size,
-                                   size_t in_use_back, size_t in_use_front) {
-  return allocator ? allocator->reallocate_downward(old_p, old_size, new_size,
-                                                    in_use_back, in_use_front)
-                   : DefaultAllocator().reallocate_downward(
-                         old_p, old_size, new_size, in_use_back, in_use_front);
-}
-
-// DetachedBuffer is a finished flatbuffer memory region, detached from its
-// builder. The original memory region and allocator are also stored so that
-// the DetachedBuffer can manage the memory lifetime.
-class DetachedBuffer {
- public:
-  DetachedBuffer()
-      : allocator_(nullptr),
-        own_allocator_(false),
-        buf_(nullptr),
-        reserved_(0),
-        cur_(nullptr),
-        size_(0) {}
-
-  DetachedBuffer(Allocator *allocator, bool own_allocator, uint8_t *buf,
-                 size_t reserved, uint8_t *cur, size_t sz)
-      : allocator_(allocator),
-        own_allocator_(own_allocator),
-        buf_(buf),
-        reserved_(reserved),
-        cur_(cur),
-        size_(sz) {}
-
-  // clang-format off
-  #if !defined(FLATBUFFERS_CPP98_STL)
-  // clang-format on
-  DetachedBuffer(DetachedBuffer &&other)
-      : allocator_(other.allocator_),
-        own_allocator_(other.own_allocator_),
-        buf_(other.buf_),
-        reserved_(other.reserved_),
-        cur_(other.cur_),
-        size_(other.size_) {
-    other.reset();
-  }
-  // clang-format off
-  #endif  // !defined(FLATBUFFERS_CPP98_STL)
-  // clang-format on
-
-  // clang-format off
-  #if !defined(FLATBUFFERS_CPP98_STL)
-  // clang-format on
-  DetachedBuffer &operator=(DetachedBuffer &&other) {
-    if (this == &other) return *this;
-
-    destroy();
-
-    allocator_ = other.allocator_;
-    own_allocator_ = other.own_allocator_;
-    buf_ = other.buf_;
-    reserved_ = other.reserved_;
-    cur_ = other.cur_;
-    size_ = other.size_;
-
-    other.reset();
-
-    return *this;
-  }
-  // clang-format off
-  #endif  // !defined(FLATBUFFERS_CPP98_STL)
-  // clang-format on
-
-  ~DetachedBuffer() { destroy(); }
-
-  const uint8_t *data() const { return cur_; }
-
-  uint8_t *data() { return cur_; }
-
-  size_t size() const { return size_; }
-
-  // clang-format off
-  #if 0  // disabled for now due to the ordering of classes in this header
-  template <class T>
-  bool Verify() const {
-    Verifier verifier(data(), size());
-    return verifier.Verify<T>(nullptr);
-  }
-
-  template <class T>
-  const T* GetRoot() const {
-    return flatbuffers::GetRoot<T>(data());
-  }
-
-  template <class T>
-  T* GetRoot() {
-    return flatbuffers::GetRoot<T>(data());
-  }
-  #endif
-  // clang-format on
-
-  // clang-format off
-  #if !defined(FLATBUFFERS_CPP98_STL)
-  // clang-format on
-  // These may change access mode, leave these at end of public section
-  FLATBUFFERS_DELETE_FUNC(DetachedBuffer(const DetachedBuffer &other))
-  FLATBUFFERS_DELETE_FUNC(
-      DetachedBuffer &operator=(const DetachedBuffer &other))
-  // clang-format off
-  #endif  // !defined(FLATBUFFERS_CPP98_STL)
-  // clang-format on
-
- protected:
-  Allocator *allocator_;
-  bool own_allocator_;
-  uint8_t *buf_;
-  size_t reserved_;
-  uint8_t *cur_;
-  size_t size_;
-
-  inline void destroy() {
-    if (buf_) Deallocate(allocator_, buf_, reserved_);
-    if (own_allocator_ && allocator_) { delete allocator_; }
-    reset();
-  }
-
-  inline void reset() {
-    allocator_ = nullptr;
-    own_allocator_ = false;
-    buf_ = nullptr;
-    reserved_ = 0;
-    cur_ = nullptr;
-    size_ = 0;
-  }
 };
 
 // This is a minimal replication of std::vector<uint8_t> functionality,
 // except growing from higher to lower addresses. i.e push_back() inserts data
 // in the lowest address in the vector.
-// Since this vector leaves the lower part unused, we support a "scratch-pad"
-// that can be stored there for temporary data, to share the allocated space.
-// Essentially, this supports 2 std::vectors in a single buffer.
 class vector_downward {
  public:
-  explicit vector_downward(size_t initial_size, Allocator *allocator,
-                           bool own_allocator, size_t buffer_minalign)
-      : allocator_(allocator),
-        own_allocator_(own_allocator),
-        initial_size_(initial_size),
-        buffer_minalign_(buffer_minalign),
-        reserved_(0),
-        buf_(nullptr),
-        cur_(nullptr),
-        scratch_(nullptr) {}
-
-  // clang-format off
-  #if !defined(FLATBUFFERS_CPP98_STL)
-  vector_downward(vector_downward &&other)
-  #else
-  vector_downward(vector_downward &other)
-  #endif  // defined(FLATBUFFERS_CPP98_STL)
-      // clang-format on
-      : allocator_(other.allocator_),
-        own_allocator_(other.own_allocator_),
-        initial_size_(other.initial_size_),
-        buffer_minalign_(other.buffer_minalign_),
-        reserved_(other.reserved_),
-        buf_(other.buf_),
-        cur_(other.cur_),
-        scratch_(other.scratch_) {
-    // No change in other.allocator_
-    // No change in other.initial_size_
-    // No change in other.buffer_minalign_
-    other.own_allocator_ = false;
-    other.reserved_ = 0;
-    other.buf_ = nullptr;
-    other.cur_ = nullptr;
-    other.scratch_ = nullptr;
-  }
-
-  // clang-format off
-  #if !defined(FLATBUFFERS_CPP98_STL)
-  // clang-format on
-  vector_downward &operator=(vector_downward &&other) {
-    // Move construct a temporary and swap idiom
-    vector_downward temp(std::move(other));
-    swap(temp);
-    return *this;
-  }
-  // clang-format off
-  #endif  // defined(FLATBUFFERS_CPP98_STL)
-  // clang-format on
+  explicit vector_downward(size_t initial_size,
+                           const simple_allocator &allocator)
+    : reserved_((initial_size + sizeof(largest_scalar_t) - 1) &
+        ~(sizeof(largest_scalar_t) - 1)),
+      buf_(allocator.allocate(reserved_)),
+      cur_(buf_ + reserved_),
+      allocator_(allocator) {}
 
   ~vector_downward() {
-    clear_buffer();
-    clear_allocator();
-  }
-
-  void reset() {
-    clear_buffer();
-    clear();
+    if (buf_)
+      allocator_.deallocate(buf_);
   }
 
   void clear() {
-    if (buf_) {
-      cur_ = buf_ + reserved_;
-    } else {
-      reserved_ = 0;
-      cur_ = nullptr;
-    }
-    clear_scratch();
+    if (buf_ == nullptr)
+      buf_ = allocator_.allocate(reserved_);
+
+    cur_ = buf_ + reserved_;
   }
 
-  void clear_scratch() { scratch_ = buf_; }
-
-  void clear_allocator() {
-    if (own_allocator_ && allocator_) { delete allocator_; }
-    allocator_ = nullptr;
-    own_allocator_ = false;
-  }
-
-  void clear_buffer() {
-    if (buf_) Deallocate(allocator_, buf_, reserved_);
-    buf_ = nullptr;
-  }
-
+  #ifndef FLATBUFFERS_CPP98_STL
   // Relinquish the pointer to the caller.
-  uint8_t *release_raw(size_t &allocated_bytes, size_t &offset) {
-    auto *buf = buf_;
-    allocated_bytes = reserved_;
-    offset = static_cast<size_t>(cur_ - buf_);
+  unique_ptr_t release() {
+    // Actually deallocate from the start of the allocated memory.
+    std::function<void(uint8_t *)> deleter(
+      std::bind(&simple_allocator::deallocate, allocator_, buf_));
 
-    // release_raw only relinquishes the buffer ownership.
-    // Does not deallocate or reset the allocator. Destructor will do that.
+    // Point to the desired offset.
+    unique_ptr_t retval(data(), deleter);
+
+    // Don't deallocate when this instance is destroyed.
     buf_ = nullptr;
-    clear();
-    return buf;
+    cur_ = nullptr;
+
+    return retval;
+  }
+  #endif
+
+  size_t growth_policy(size_t bytes) {
+    return (bytes / 2) & ~(sizeof(largest_scalar_t) - 1);
   }
 
-  // Relinquish the pointer to the caller.
-  DetachedBuffer release() {
-    // allocator ownership (if any) is transferred to DetachedBuffer.
-    DetachedBuffer fb(allocator_, own_allocator_, buf_, reserved_, cur_,
-                      size());
-    if (own_allocator_) {
-      allocator_ = nullptr;
-      own_allocator_ = false;
+  uint8_t *make_space(size_t len) {
+    if (len > static_cast<size_t>(cur_ - buf_)) {
+      reallocate(len);
     }
-    buf_ = nullptr;
-    clear();
-    return fb;
-  }
-
-  size_t ensure_space(size_t len) {
-    FLATBUFFERS_ASSERT(cur_ >= scratch_ && scratch_ >= buf_);
-    if (len > static_cast<size_t>(cur_ - scratch_)) { reallocate(len); }
+    cur_ -= len;
     // Beyond this, signed offsets may not have enough range:
     // (FlatBuffers > 2GB not supported).
-    FLATBUFFERS_ASSERT(size() < FLATBUFFERS_MAX_BUFFER_SIZE);
-    return len;
-  }
-
-  inline uint8_t *make_space(size_t len) {
-    size_t space = ensure_space(len);
-    cur_ -= space;
+    assert(size() < FLATBUFFERS_MAX_BUFFER_SIZE);
     return cur_;
   }
 
-  // Returns nullptr if using the DefaultAllocator.
-  Allocator *get_custom_allocator() { return allocator_; }
-
   uoffset_t size() const {
+    assert(cur_ != nullptr && buf_ != nullptr);
     return static_cast<uoffset_t>(reserved_ - static_cast<size_t>(cur_ - buf_));
   }
 
-  uoffset_t scratch_size() const {
-    return static_cast<uoffset_t>(scratch_ - buf_);
-  }
-
-  size_t capacity() const { return reserved_; }
-
   uint8_t *data() const {
-    FLATBUFFERS_ASSERT(cur_);
+    assert(cur_ != nullptr);
     return cur_;
   }
 
-  uint8_t *scratch_data() const {
-    FLATBUFFERS_ASSERT(buf_);
-    return buf_;
-  }
-
-  uint8_t *scratch_end() const {
-    FLATBUFFERS_ASSERT(scratch_);
-    return scratch_;
-  }
-
   uint8_t *data_at(size_t offset) const { return buf_ + reserved_ - offset; }
 
   void push(const uint8_t *bytes, size_t num) {
-    if (num > 0) { memcpy(make_space(num), bytes, num); }
+    auto dest = make_space(num);
+    memcpy(dest, bytes, num);
   }
 
   // Specialized version of push() that avoids memcpy call for small data.
-  template<typename T> void push_small(const T &little_endian_t) {
-    make_space(sizeof(T));
-    *reinterpret_cast<T *>(cur_) = little_endian_t;
-  }
-
-  template<typename T> void scratch_push_small(const T &t) {
-    ensure_space(sizeof(T));
-    *reinterpret_cast<T *>(scratch_) = t;
-    scratch_ += sizeof(T);
+  template<typename T> void push_small(T little_endian_t) {
+    auto dest = make_space(sizeof(T));
+    *reinterpret_cast<T *>(dest) = little_endian_t;
   }
 
   // fill() is most frequently called with small byte counts (<= 4),
   // which is why we're using loops rather than calling memset.
   void fill(size_t zero_pad_bytes) {
-    make_space(zero_pad_bytes);
-    for (size_t i = 0; i < zero_pad_bytes; i++) cur_[i] = 0;
+    auto dest = make_space(zero_pad_bytes);
+    for (size_t i = 0; i < zero_pad_bytes; i++) dest[i] = 0;
   }
 
   // Version for when we know the size is larger.
-  // Precondition: zero_pad_bytes > 0
   void fill_big(size_t zero_pad_bytes) {
-    memset(make_space(zero_pad_bytes), 0, zero_pad_bytes);
+    auto dest = make_space(zero_pad_bytes);
+    memset(dest, 0, zero_pad_bytes);
   }
 
   void pop(size_t bytes_to_remove) { cur_ += bytes_to_remove; }
-  void scratch_pop(size_t bytes_to_remove) { scratch_ -= bytes_to_remove; }
-
-  void swap(vector_downward &other) {
-    using std::swap;
-    swap(allocator_, other.allocator_);
-    swap(own_allocator_, other.own_allocator_);
-    swap(initial_size_, other.initial_size_);
-    swap(buffer_minalign_, other.buffer_minalign_);
-    swap(reserved_, other.reserved_);
-    swap(buf_, other.buf_);
-    swap(cur_, other.cur_);
-    swap(scratch_, other.scratch_);
-  }
-
-  void swap_allocator(vector_downward &other) {
-    using std::swap;
-    swap(allocator_, other.allocator_);
-    swap(own_allocator_, other.own_allocator_);
-  }
 
  private:
   // You shouldn't really be copying instances of this class.
-  FLATBUFFERS_DELETE_FUNC(vector_downward(const vector_downward &))
-  FLATBUFFERS_DELETE_FUNC(vector_downward &operator=(const vector_downward &))
+  vector_downward(const vector_downward &);
+  vector_downward &operator=(const vector_downward &);
 
-  Allocator *allocator_;
-  bool own_allocator_;
-  size_t initial_size_;
-  size_t buffer_minalign_;
   size_t reserved_;
   uint8_t *buf_;
   uint8_t *cur_;  // Points at location between empty (below) and used (above).
-  uint8_t *scratch_;  // Points to the end of the scratchpad in use.
+  const simple_allocator &allocator_;
 
   void reallocate(size_t len) {
-    auto old_reserved = reserved_;
     auto old_size = size();
-    auto old_scratch_size = scratch_size();
-    reserved_ +=
-        (std::max)(len, old_reserved ? old_reserved / 2 : initial_size_);
-    reserved_ = (reserved_ + buffer_minalign_ - 1) & ~(buffer_minalign_ - 1);
-    if (buf_) {
-      buf_ = ReallocateDownward(allocator_, buf_, old_reserved, reserved_,
-                                old_size, old_scratch_size);
-    } else {
-      buf_ = Allocate(allocator_, reserved_);
-    }
-    cur_ = buf_ + reserved_ - old_size;
-    scratch_ = buf_ + old_scratch_size;
+    auto largest_align = AlignOf<largest_scalar_t>();
+    reserved_ += (std::max)(len, growth_policy(reserved_));
+    // Round up to avoid undefined behavior from unaligned loads and stores.
+    reserved_ = (reserved_ + (largest_align - 1)) & ~(largest_align - 1);
+    auto new_buf = allocator_.allocate(reserved_);
+    auto new_cur = new_buf + reserved_ - old_size;
+    memcpy(new_cur, cur_, old_size);
+    cur_ = new_cur;
+    allocator_.deallocate(buf_);
+    buf_ = new_buf;
   }
 };
 
@@ -1070,21 +658,19 @@
   return static_cast<voffset_t>((field_id + fixed_fields) * sizeof(voffset_t));
 }
 
-#ifndef FLATBUFFERS_CHRE
-template<typename T, typename Alloc>
-const T *data(const std::vector<T, Alloc> &v) {
-  // Eventually the returned pointer gets passed down to memcpy, so
-  // we need it to be non-null to avoid undefined behavior.
-  static uint8_t t;
-  return v.empty() ? reinterpret_cast<const T *>(&t) : &v.front();
+// Computes how many bytes you'd have to pad to be able to write an
+// "scalar_size" scalar if the buffer had grown to "buf_size" (downwards in
+// memory).
+inline size_t PaddingBytes(size_t buf_size, size_t scalar_size) {
+  return ((~buf_size) + 1) & (scalar_size - 1);
 }
-template<typename T, typename Alloc> T *data(std::vector<T, Alloc> &v) {
-  // Eventually the returned pointer gets passed down to memcpy, so
-  // we need it to be non-null to avoid undefined behavior.
-  static uint8_t t;
-  return v.empty() ? reinterpret_cast<T *>(&t) : &v.front();
+
+template <typename T> const T* data(const std::vector<T> &v) {
+  return v.empty() ? nullptr : &v.front();
 }
-#endif
+template <typename T> T* data(std::vector<T> &v) {
+  return v.empty() ? nullptr : &v.front();
+}
 
 /// @endcond
 
@@ -1097,111 +683,46 @@
 /// `PushElement`/`AddElement`/`EndTable`, or the builtin `CreateString`/
 /// `CreateVector` functions. Do this is depth-first order to build up a tree to
 /// the root. `Finish()` wraps up the buffer ready for transport.
-class FlatBufferBuilder {
+class FlatBufferBuilder
+/// @cond FLATBUFFERS_INTERNAL
+FLATBUFFERS_FINAL_CLASS
+/// @endcond
+{
  public:
   /// @brief Default constructor for FlatBufferBuilder.
   /// @param[in] initial_size The initial size of the buffer, in bytes. Defaults
-  /// to `1024`.
-  /// @param[in] allocator An `Allocator` to use. If null will use
-  /// `DefaultAllocator`.
-  /// @param[in] own_allocator Whether the builder/vector should own the
-  /// allocator. Defaults to / `false`.
-  /// @param[in] buffer_minalign Force the buffer to be aligned to the given
-  /// minimum alignment upon reallocation. Only needed if you intend to store
-  /// types with custom alignment AND you wish to read the buffer in-place
-  /// directly after creation.
-  explicit FlatBufferBuilder(
-      size_t initial_size = 1024, Allocator *allocator = nullptr,
-      bool own_allocator = false,
-      size_t buffer_minalign = AlignOf<largest_scalar_t>())
-      : buf_(initial_size, allocator, own_allocator, buffer_minalign),
-        num_field_loc(0),
-        max_voffset_(0),
-        nested(false),
-        finished(false),
-        minalign_(1),
-        force_defaults_(false),
+  /// to`1024`.
+  /// @param[in] allocator A pointer to the `simple_allocator` that should be
+  /// used. Defaults to `nullptr`, which means the `default_allocator` will be
+  /// be used.
+  explicit FlatBufferBuilder(uoffset_t initial_size = 1024,
+                             const simple_allocator *allocator = nullptr)
+      : buf_(initial_size, allocator ? *allocator : default_allocator),
+        nested(false), finished(false), minalign_(1), force_defaults_(false),
         dedup_vtables_(true) {
     #ifndef FLATBUFFERS_CHRE
     string_pool = nullptr;
     #endif
 
+    offsetbuf_.reserve(16);  // Avoid first few reallocs.
+    vtables_.reserve(16);
     EndianCheck();
   }
 
-  // clang-format off
-  /// @brief Move constructor for FlatBufferBuilder.
-  #if !defined(FLATBUFFERS_CPP98_STL)
-  FlatBufferBuilder(FlatBufferBuilder &&other)
-  #else
-  FlatBufferBuilder(FlatBufferBuilder &other)
-  #endif  // #if !defined(FLATBUFFERS_CPP98_STL)
-    : buf_(1024, nullptr, false, AlignOf<largest_scalar_t>()),
-      num_field_loc(0),
-      max_voffset_(0),
-      nested(false),
-      finished(false),
-      minalign_(1),
-      force_defaults_(false),
-      dedup_vtables_(true) {
-    #ifndef FLATBUFFERS_CHRE
-    string_pool = nullptr;
-    #endif
-
-    EndianCheck();
-    // Default construct and swap idiom.
-    // Lack of delegating constructors in vs2010 makes it more verbose than needed.
-    Swap(other);
-  }
-  // clang-format on
-
-  // clang-format off
-  #if !defined(FLATBUFFERS_CPP98_STL)
-  // clang-format on
-  /// @brief Move assignment operator for FlatBufferBuilder.
-  FlatBufferBuilder &operator=(FlatBufferBuilder &&other) {
-    // Move construct a temporary and swap idiom
-    FlatBufferBuilder temp(std::move(other));
-    Swap(temp);
-    return *this;
-  }
-  // clang-format off
-  #endif  // defined(FLATBUFFERS_CPP98_STL)
-  // clang-format on
-
-  void Swap(FlatBufferBuilder &other) {
-    using std::swap;
-    buf_.swap(other.buf_);
-    swap(num_field_loc, other.num_field_loc);
-    swap(max_voffset_, other.max_voffset_);
-    swap(nested, other.nested);
-    swap(finished, other.finished);
-    swap(minalign_, other.minalign_);
-    swap(force_defaults_, other.force_defaults_);
-    swap(dedup_vtables_, other.dedup_vtables_);
-    #ifndef FLATBUFFERS_CHRE
-    swap(string_pool, other.string_pool);
-    #endif
-  }
-
   ~FlatBufferBuilder() {
     #ifndef FLATBUFFERS_CHRE
     if (string_pool) delete string_pool;
     #endif
   }
 
-  void Reset() {
-    Clear();       // clear builder state
-    buf_.reset();  // deallocate buffer
-  }
-
   /// @brief Reset all the state in this FlatBufferBuilder so it can be reused
   /// to construct another buffer.
   void Clear() {
-    ClearOffsets();
     buf_.clear();
+    offsetbuf_.clear();
     nested = false;
     finished = false;
+    vtables_.clear();
     minalign_ = 1;
     #ifndef FLATBUFFERS_CHRE
     if (string_pool) string_pool->clear();
@@ -1224,36 +745,18 @@
   /// @return Returns a `uint8_t` pointer to the unfinished buffer.
   uint8_t *GetCurrentBufferPointer() const { return buf_.data(); }
 
+  #ifndef FLATBUFFERS_CPP98_STL
   /// @brief Get the released pointer to the serialized buffer.
   /// @warning Do NOT attempt to use this FlatBufferBuilder afterwards!
-  /// @return A `FlatBuffer` that owns the buffer and its allocator and
-  /// behaves similar to a `unique_ptr` with a deleter.
-  FLATBUFFERS_ATTRIBUTE(deprecated("use Release() instead"))
-  DetachedBuffer ReleaseBufferPointer() {
+  /// @return The `unique_ptr` returned has a special allocator that knows how
+  /// to deallocate this pointer (since it points to the middle of an
+  /// allocation). Thus, do not mix this pointer with other `unique_ptr`'s, or
+  /// call `release()`/`reset()` on it.
+  unique_ptr_t ReleaseBufferPointer() {
     Finished();
     return buf_.release();
   }
-
-  /// @brief Get the released DetachedBuffer.
-  /// @return A `DetachedBuffer` that owns the buffer and its allocator.
-  DetachedBuffer Release() {
-    Finished();
-    return buf_.release();
-  }
-
-  /// @brief Get the released pointer to the serialized buffer.
-  /// @param size The size of the memory block containing
-  /// the serialized `FlatBuffer`.
-  /// @param offset The offset from the released pointer where the finished
-  /// `FlatBuffer` starts.
-  /// @return A raw pointer to the start of the memory block containing
-  /// the serialized `FlatBuffer`.
-  /// @remark If the allocator is owned, it gets deleted when the destructor is
-  /// called..
-  uint8_t *ReleaseRaw(size_t &size, size_t &offset) {
-    Finished();
-    return buf_.release_raw(size, offset);
-  }
+  #endif
 
   /// @brief get the minimum alignment this buffer needs to be accessed
   /// properly. This is only known once all elements have been written (after
@@ -1272,30 +775,24 @@
     // FlatBufferBuilder::Finish with your root table.
     // If you really need to access an unfinished buffer, call
     // GetCurrentBufferPointer instead.
-    FLATBUFFERS_ASSERT(finished);
+    assert(finished);
   }
   /// @endcond
 
   /// @brief In order to save space, fields that are set to their default value
   /// don't get serialized into the buffer.
-  /// @param[in] fd When set to `true`, always serializes default values that
-  /// are set. Optional fields which are not set explicitly, will still not be
-  /// serialized.
+  /// @param[in] bool fd When set to `true`, always serializes default values.
   void ForceDefaults(bool fd) { force_defaults_ = fd; }
 
   /// @brief By default vtables are deduped in order to save space.
-  /// @param[in] dedup When set to `true`, dedup vtables.
+  /// @param[in] bool dedup When set to `true`, dedup vtables.
   void DedupVtables(bool dedup) { dedup_vtables_ = dedup; }
 
   /// @cond FLATBUFFERS_INTERNAL
   void Pad(size_t num_bytes) { buf_.fill(num_bytes); }
 
-  void TrackMinAlign(size_t elem_size) {
-    if (elem_size > minalign_) minalign_ = elem_size;
-  }
-
   void Align(size_t elem_size) {
-    TrackMinAlign(elem_size);
+    if (elem_size > minalign_) minalign_ = elem_size;
     buf_.fill(PaddingBytes(buf_.size(), elem_size));
   }
 
@@ -1304,13 +801,20 @@
     finished = true;
   }
 
-  void PushBytes(const uint8_t *bytes, size_t size) { buf_.push(bytes, size); }
+  void PushBytes(const uint8_t *bytes, size_t size) {
+    buf_.push(bytes, size);
+  }
 
   void PopBytes(size_t amount) { buf_.pop(amount); }
 
   template<typename T> void AssertScalarT() {
+    #ifndef FLATBUFFERS_CPP98_STL
     // The code assumes power of 2 sizes and endian-swap-ability.
-    static_assert(flatbuffers::is_scalar<T>::value, "T must be a scalar type");
+    static_assert(std::is_scalar<T>::value
+        // The Offset<T> type is essentially a scalar but fails is_scalar.
+        || sizeof(T) == sizeof(Offset<void>),
+           "T must be a scalar type");
+    #endif
   }
 
   // Write a single aligned scalar to the buffer
@@ -1331,21 +835,19 @@
   // vtables later.
   void TrackField(voffset_t field, uoffset_t off) {
     FieldLoc fl = { off, field };
-    buf_.scratch_push_small(fl);
-    num_field_loc++;
-    max_voffset_ = (std::max)(max_voffset_, field);
+    offsetbuf_.push_back(fl);
   }
 
   // Like PushElement, but additionally tracks the field this represents.
   template<typename T> void AddElement(voffset_t field, T e, T def) {
     // We don't serialize values equal to the default.
-    if (IsTheSameAs(e, def) && !force_defaults_) return;
+    if (e == def && !force_defaults_) return;
     auto off = PushElement(e);
     TrackField(field, off);
   }
 
   template<typename T> void AddOffset(voffset_t field, Offset<T> off) {
-    if (off.IsNull()) return;  // Don't store.
+    if (!off.o) return;  // An offset of 0 means NULL, don't store.
     AddElement(field, ReferTo(off.o), static_cast<uoffset_t>(0));
   }
 
@@ -1367,7 +869,7 @@
     // Align to ensure GetSize() below is correct.
     Align(sizeof(uoffset_t));
     // Offset must refer to something already in buffer.
-    FLATBUFFERS_ASSERT(off && off <= GetSize());
+    assert(off && off <= GetSize());
     return GetSize() - off + static_cast<uoffset_t>(sizeof(uoffset_t));
   }
 
@@ -1380,9 +882,7 @@
     // Ignoring this assert may appear to work in simple cases, but the reason
     // it is here is that storing objects in-line may cause vtable offsets
     // to not fit anymore. It also leads to vtable duplication.
-    FLATBUFFERS_ASSERT(!nested);
-    // If you hit this, fields were added outside the scope of a table.
-    FLATBUFFERS_ASSERT(!num_field_loc);
+    assert(!nested);
   }
 
   // From generated code (or from the parser), we call StartTable/EndTable
@@ -1396,57 +896,49 @@
   // This finishes one serialized object by generating the vtable if it's a
   // table, comparing it against existing vtables, and writing the
   // resulting vtable offset.
-  uoffset_t EndTable(uoffset_t start) {
+  uoffset_t EndTable(uoffset_t start, voffset_t numfields) {
     // If you get this assert, a corresponding StartTable wasn't called.
-    FLATBUFFERS_ASSERT(nested);
+    assert(nested);
     // Write the vtable offset, which is the start of any Table.
     // We fill it's value later.
     auto vtableoffsetloc = PushElement<soffset_t>(0);
     // Write a vtable, which consists entirely of voffset_t elements.
     // It starts with the number of offsets, followed by a type id, followed
     // by the offsets themselves. In reverse:
-    // Include space for the last offset and ensure empty tables have a
-    // minimum size.
-    max_voffset_ =
-        (std::max)(static_cast<voffset_t>(max_voffset_ + sizeof(voffset_t)),
-                   FieldIndexToOffset(0));
-    buf_.fill_big(max_voffset_);
+    buf_.fill_big(numfields * sizeof(voffset_t));
     auto table_object_size = vtableoffsetloc - start;
-    // Vtable use 16bit offsets.
-    FLATBUFFERS_ASSERT(table_object_size < 0x10000);
-    WriteScalar<voffset_t>(buf_.data() + sizeof(voffset_t),
-                           static_cast<voffset_t>(table_object_size));
-    WriteScalar<voffset_t>(buf_.data(), max_voffset_);
+    assert(table_object_size < 0x10000);  // Vtable use 16bit offsets.
+    PushElement<voffset_t>(static_cast<voffset_t>(table_object_size));
+    PushElement<voffset_t>(FieldIndexToOffset(numfields));
     // Write the offsets into the table
-    for (auto it = buf_.scratch_end() - num_field_loc * sizeof(FieldLoc);
-         it < buf_.scratch_end(); it += sizeof(FieldLoc)) {
-      auto field_location = reinterpret_cast<FieldLoc *>(it);
+    for (auto field_location = offsetbuf_.begin();
+              field_location != offsetbuf_.end();
+            ++field_location) {
       auto pos = static_cast<voffset_t>(vtableoffsetloc - field_location->off);
       // If this asserts, it means you've set a field twice.
-      FLATBUFFERS_ASSERT(
-          !ReadScalar<voffset_t>(buf_.data() + field_location->id));
+      assert(!ReadScalar<voffset_t>(buf_.data() + field_location->id));
       WriteScalar<voffset_t>(buf_.data() + field_location->id, pos);
     }
-    ClearOffsets();
+    offsetbuf_.clear();
     auto vt1 = reinterpret_cast<voffset_t *>(buf_.data());
     auto vt1_size = ReadScalar<voffset_t>(vt1);
     auto vt_use = GetSize();
     // See if we already have generated a vtable with this exact same
     // layout before. If so, make it point to the old one, remove this one.
     if (dedup_vtables_) {
-      for (auto it = buf_.scratch_data(); it < buf_.scratch_end();
-           it += sizeof(uoffset_t)) {
-        auto vt_offset_ptr = reinterpret_cast<uoffset_t *>(it);
-        auto vt2 = reinterpret_cast<voffset_t *>(buf_.data_at(*vt_offset_ptr));
-        auto vt2_size = ReadScalar<voffset_t>(vt2);
-        if (vt1_size != vt2_size || 0 != memcmp(vt2, vt1, vt1_size)) continue;
-        vt_use = *vt_offset_ptr;
+      for (auto it = vtables_.begin(); it != vtables_.end(); ++it) {
+        auto vt2 = reinterpret_cast<voffset_t *>(buf_.data_at(*it));
+        auto vt2_size = *vt2;
+        if (vt1_size != vt2_size || memcmp(vt2, vt1, vt1_size)) continue;
+        vt_use = *it;
         buf_.pop(GetSize() - vtableoffsetloc);
         break;
       }
     }
     // If this is a new vtable, remember it.
-    if (vt_use == GetSize()) { buf_.scratch_push_small(vt_use); }
+    if (vt_use == GetSize()) {
+      vtables_.push_back(vt_use);
+    }
     // Fill the vtable offset we created above.
     // The offset points from the beginning of the object to where the
     // vtable is stored.
@@ -1454,20 +946,22 @@
     // flexibility (storing all vtables at the start of the file).
     WriteScalar(buf_.data_at(vtableoffsetloc),
                 static_cast<soffset_t>(vt_use) -
-                    static_cast<soffset_t>(vtableoffsetloc));
+                  static_cast<soffset_t>(vtableoffsetloc));
 
     nested = false;
     return vtableoffsetloc;
   }
 
-  FLATBUFFERS_ATTRIBUTE(deprecated("call the version above instead"))
-  uoffset_t EndTable(uoffset_t start, voffset_t /*numfields*/) {
-    return EndTable(start);
-  }
-
   // This checks a required field has been set in a given table that has
   // just been constructed.
-  template<typename T> void Required(Offset<T> table, voffset_t field);
+  template<typename T> void Required(Offset<T> table, voffset_t field) {
+    auto table_ptr = buf_.data_at(table.o);
+    auto vtable_ptr = table_ptr - ReadScalar<soffset_t>(table_ptr);
+    bool ok = ReadScalar<voffset_t>(vtable_ptr + field) != 0;
+    // If this fails, the caller will show what field needs to be set.
+    assert(ok);
+    (void)ok;
+  }
 
   uoffset_t StartStruct(size_t alignment) {
     Align(alignment);
@@ -1476,16 +970,11 @@
 
   uoffset_t EndStruct() { return GetSize(); }
 
-  void ClearOffsets() {
-    buf_.scratch_pop(num_field_loc * sizeof(FieldLoc));
-    num_field_loc = 0;
-    max_voffset_ = 0;
-  }
+  void ClearOffsets() { offsetbuf_.clear(); }
 
   // Aligns such that when "len" bytes are written, an object can be written
   // after it with "alignment" without padding.
   void PreAlign(size_t len, size_t alignment) {
-    TrackMinAlign(alignment);
     buf_.fill(PaddingBytes(GetSize() + len, alignment));
   }
   template<typename T> void PreAlign(size_t len) {
@@ -1515,13 +1004,6 @@
     return CreateString(str, strlen(str));
   }
 
-  /// @brief Store a string in the buffer, which is null-terminated.
-  /// @param[in] str A char pointer to a C-string to add to the buffer.
-  /// @return Returns the offset in the buffer where the string starts.
-  Offset<String> CreateString(char *str) {
-    return CreateString(str, strlen(str));
-  }
-
   /// @brief Store a string in the buffer, which can contain any binary data.
   /// @param[in] str A const reference to a std::string to store in the buffer.
   /// @return Returns the offset in the buffer where the string starts.
@@ -1529,30 +1011,11 @@
     return CreateString(str.c_str(), str.length());
   }
 
-  // clang-format off
-  #ifdef FLATBUFFERS_HAS_STRING_VIEW
-  /// @brief Store a string in the buffer, which can contain any binary data.
-  /// @param[in] str A const string_view to copy in to the buffer.
-  /// @return Returns the offset in the buffer where the string starts.
-  Offset<String> CreateString(flatbuffers::string_view str) {
-    return CreateString(str.data(), str.size());
-  }
-  #endif // FLATBUFFERS_HAS_STRING_VIEW
-  // clang-format on
-
   /// @brief Store a string in the buffer, which can contain any binary data.
   /// @param[in] str A const pointer to a `String` struct to add to the buffer.
   /// @return Returns the offset in the buffer where the string starts
   Offset<String> CreateString(const String *str) {
-    return str ? CreateString(str->c_str(), str->size()) : 0;
-  }
-
-  /// @brief Store a string in the buffer, which can contain any binary data.
-  /// @param[in] str A const reference to a std::string like type with support
-  /// of T::c_str() and T::length() to store in the buffer.
-  /// @return Returns the offset in the buffer where the string starts.
-  template<typename T> Offset<String> CreateString(const T &str) {
-    return CreateString(str.c_str(), str.length());
+    return str ? CreateString(str->c_str(), str->Length()) : 0;
   }
 
   /// @brief Store a string in the buffer, which can contain any binary data.
@@ -1604,13 +1067,13 @@
   /// @param[in] str A const pointer to a `String` struct to add to the buffer.
   /// @return Returns the offset in the buffer where the string starts
   Offset<String> CreateSharedString(const String *str) {
-    return CreateSharedString(str->c_str(), str->size());
+    return CreateSharedString(str->c_str(), str->Length());
   }
-  #endif  // !FLATBUFFERS_CHRE
+  #endif  // FLATBUFFERS_CHRE
 
   /// @cond FLATBUFFERS_INTERNAL
   uoffset_t EndVector(size_t len) {
-    FLATBUFFERS_ASSERT(nested);  // Hit if no corresponding StartVector.
+    assert(nested);  // Hit if no corresponding StartVector.
     nested = false;
     return PushElement(static_cast<uoffset_t>(len));
   }
@@ -1631,11 +1094,9 @@
     PreAlign(len * elemsize, alignment);
   }
 
-  // Similar to ForceVectorAlignment but for String fields.
-  void ForceStringAlignment(size_t len, size_t alignment) {
-    PreAlign((len + 1) * sizeof(char), alignment);
+  uint8_t *ReserveElements(size_t len, size_t elemsize) {
+    return buf_.make_space(len * elemsize);
   }
-
   /// @endcond
 
   /// @brief Serialize an array into a FlatBuffer `vector`.
@@ -1646,33 +1107,13 @@
   /// @return Returns a typed `Offset` into the serialized data indicating
   /// where the vector is stored.
   template<typename T> Offset<Vector<T>> CreateVector(const T *v, size_t len) {
-    // If this assert hits, you're specifying a template argument that is
-    // causing the wrong overload to be selected, remove it.
-    AssertScalarT<T>();
     StartVector(len, sizeof(T));
-    // clang-format off
-    #if FLATBUFFERS_LITTLEENDIAN
-      PushBytes(reinterpret_cast<const uint8_t *>(v), len * sizeof(T));
-    #else
-      if (sizeof(T) == 1) {
-        PushBytes(reinterpret_cast<const uint8_t *>(v), len);
-      } else {
-        for (auto i = len; i > 0; ) {
-          PushElement(v[--i]);
-        }
-      }
-    #endif
-    // clang-format on
+    for (auto i = len; i > 0; ) {
+      PushElement(v[--i]);
+    }
     return Offset<Vector<T>>(EndVector(len));
   }
 
-  template<typename T>
-  Offset<Vector<Offset<T>>> CreateVector(const Offset<T> *v, size_t len) {
-    StartVector(len, sizeof(Offset<T>));
-    for (auto i = len; i > 0;) { PushElement(v[--i]); }
-    return Offset<Vector<Offset<T>>>(EndVector(len));
-  }
-
   #ifndef FLATBUFFERS_CHRE
   /// @brief Serialize a `std::vector` into a FlatBuffer `vector`.
   /// @tparam T The data type of the `std::vector` elements.
@@ -1689,19 +1130,19 @@
   // Background: https://isocpp.org/blog/2012/11/on-vectorbool
   Offset<Vector<uint8_t>> CreateVector(const std::vector<bool> &v) {
     StartVector(v.size(), sizeof(uint8_t));
-    for (auto i = v.size(); i > 0;) {
+    for (auto i = v.size(); i > 0; ) {
       PushElement(static_cast<uint8_t>(v[--i]));
     }
     return Offset<Vector<uint8_t>>(EndVector(v.size()));
   }
-  #else  // else if defined(FLATBUFFERS_CHRE)
+  #else  // FLATBUFFERS_CHRE
   // We need to define this function as it's optionally used in the
   // Create<Type>Direct() helper functions generated by the FlatBuffer compiler,
   // however its use at runtime is not supported.
   template<typename T> Offset<Vector<T>> CreateVector(
       const std::vector<T>& /* v */) {
     // std::vector use by FlatBuffers is not supported in CHRE.
-    FLATBUFFERS_ASSERT(false);
+    CHRE_ASSERT(false);
     return 0;
   }
 
@@ -1717,8 +1158,7 @@
   }
   #endif  // FLATBUFFERS_CHRE
 
-  // clang-format off
-  #if !defined(FLATBUFFERS_CPP98_STL) && !defined(FLATBUFFERS_CHRE)
+  #ifndef FLATBUFFERS_CPP98_STL
   /// @brief Serialize values returned by a function into a FlatBuffer `vector`.
   /// This is a convenience function that takes care of iteration for you.
   /// @tparam T The data type of the `std::vector` elements.
@@ -1733,25 +1173,8 @@
     return CreateVector(elems);
   }
   #endif
-  // clang-format on
 
   #ifndef FLATBUFFERS_CHRE
-  /// @brief Serialize values returned by a function into a FlatBuffer `vector`.
-  /// This is a convenience function that takes care of iteration for you.
-  /// @tparam T The data type of the `std::vector` elements.
-  /// @param f A function that takes the current iteration 0..vector_size-1,
-  /// and the state parameter returning any type that you can construct a
-  /// FlatBuffers vector out of.
-  /// @param state State passed to f.
-  /// @return Returns a typed `Offset` into the serialized data indicating
-  /// where the vector is stored.
-  template<typename T, typename F, typename S>
-  Offset<Vector<T>> CreateVector(size_t vector_size, F f, S *state) {
-    std::vector<T> elems(vector_size);
-    for (size_t i = 0; i < vector_size; i++) elems[i] = f(i, state);
-    return CreateVector(elems);
-  }
-
   /// @brief Serialize a `std::vector<std::string>` into a FlatBuffer `vector`.
   /// This is a convenience function for a common case.
   /// @param v A const reference to the `std::vector` to serialize into the
@@ -1764,7 +1187,7 @@
     for (size_t i = 0; i < v.size(); i++) offsets[i] = CreateString(v[i]);
     return CreateVector(offsets);
   }
-  #endif  // !FLATBUFFERS_CHRE
+  #endif  // FLATBUFFERS_CHRE
 
   /// @brief Serialize an array of structs into a FlatBuffer `vector`.
   /// @tparam T The data type of the struct array elements.
@@ -1773,36 +1196,17 @@
   /// @param[in] len The number of elements to serialize.
   /// @return Returns a typed `Offset` into the serialized data indicating
   /// where the vector is stored.
-  template<typename T>
-  Offset<Vector<const T *>> CreateVectorOfStructs(const T *v, size_t len) {
+  template<typename T> Offset<Vector<const T *>> CreateVectorOfStructs(
+      const T *v, size_t len) {
     StartVector(len * sizeof(T) / AlignOf<T>(), AlignOf<T>());
     PushBytes(reinterpret_cast<const uint8_t *>(v), sizeof(T) * len);
     return Offset<Vector<const T *>>(EndVector(len));
   }
 
-  #ifndef FLATBUFFERS_CHRE
-  /// @brief Serialize an array of native structs into a FlatBuffer `vector`.
-  /// @tparam T The data type of the struct array elements.
-  /// @tparam S The data type of the native struct array elements.
-  /// @param[in] v A pointer to the array of type `S` to serialize into the
-  /// buffer as a `vector`.
-  /// @param[in] len The number of elements to serialize.
-  /// @return Returns a typed `Offset` into the serialized data indicating
-  /// where the vector is stored.
-  template<typename T, typename S>
-  Offset<Vector<const T *>> CreateVectorOfNativeStructs(const S *v,
-                                                        size_t len) {
-    extern T Pack(const S &);
-    std::vector<T> vv(len);
-    std::transform(v, v + len, vv.begin(), Pack);
-    return CreateVectorOfStructs<T>(data(vv), vv.size());
-  }
-
-  // clang-format off
   #ifndef FLATBUFFERS_CPP98_STL
   /// @brief Serialize an array of structs into a FlatBuffer `vector`.
   /// @tparam T The data type of the struct array elements.
-  /// @param[in] filler A function that takes the current iteration 0..vector_size-1
+  /// @param[in] f A function that takes the current iteration 0..vector_size-1
   /// and a pointer to the struct that must be filled.
   /// @return Returns a typed `Offset` into the serialized data indicating
   /// where the vector is stored.
@@ -1810,153 +1214,44 @@
   /// accessors.
   template<typename T> Offset<Vector<const T *>> CreateVectorOfStructs(
       size_t vector_size, const std::function<void(size_t i, T *)> &filler) {
-    T* structs = StartVectorOfStructs<T>(vector_size);
+    StartVector(vector_size * sizeof(T) / AlignOf<T>(), AlignOf<T>());
+    T *structs = reinterpret_cast<T *>(buf_.make_space(vector_size * sizeof(T)));
     for (size_t i = 0; i < vector_size; i++) {
       filler(i, structs);
       structs++;
     }
-    return EndVectorOfStructs<T>(vector_size);
+    return Offset<Vector<const T *>>(EndVector(vector_size));
   }
   #endif
-  #endif  // !FLATBUFFERS_CHRE
-  // clang-format on
 
-  /// @brief Serialize an array of structs into a FlatBuffer `vector`.
-  /// @tparam T The data type of the struct array elements.
-  /// @param[in] f A function that takes the current iteration 0..vector_size-1,
-  /// a pointer to the struct that must be filled and the state argument.
-  /// @param[in] state Arbitrary state to pass to f.
-  /// @return Returns a typed `Offset` into the serialized data indicating
-  /// where the vector is stored.
-  /// This is mostly useful when flatbuffers are generated with mutation
-  /// accessors.
-  template<typename T, typename F, typename S>
-  Offset<Vector<const T *>> CreateVectorOfStructs(size_t vector_size, F f,
-                                                  S *state) {
-    T *structs = StartVectorOfStructs<T>(vector_size);
-    for (size_t i = 0; i < vector_size; i++) {
-      f(i, structs, state);
-      structs++;
-    }
-    return EndVectorOfStructs<T>(vector_size);
-  }
-
-  #ifndef FLATBUFFERS_CHRE
   /// @brief Serialize a `std::vector` of structs into a FlatBuffer `vector`.
   /// @tparam T The data type of the `std::vector` struct elements.
-  /// @param[in] v A const reference to the `std::vector` of structs to
+  /// @param[in]] v A const reference to the `std::vector` of structs to
   /// serialize into the buffer as a `vector`.
   /// @return Returns a typed `Offset` into the serialized data indicating
   /// where the vector is stored.
-  template<typename T, typename Alloc>
-  Offset<Vector<const T *>> CreateVectorOfStructs(
-      const std::vector<T, Alloc> &v) {
+  template<typename T> Offset<Vector<const T *>> CreateVectorOfStructs(
+      const std::vector<T> &v) {
     return CreateVectorOfStructs(data(v), v.size());
   }
 
-  /// @brief Serialize a `std::vector` of native structs into a FlatBuffer
-  /// `vector`.
-  /// @tparam T The data type of the `std::vector` struct elements.
-  /// @tparam S The data type of the `std::vector` native struct elements.
-  /// @param[in] v A const reference to the `std::vector` of structs to
-  /// serialize into the buffer as a `vector`.
-  /// @return Returns a typed `Offset` into the serialized data indicating
-  /// where the vector is stored.
-  template<typename T, typename S>
-  Offset<Vector<const T *>> CreateVectorOfNativeStructs(
-      const std::vector<S> &v) {
-    return CreateVectorOfNativeStructs<T, S>(data(v), v.size());
-  }
-
   /// @cond FLATBUFFERS_INTERNAL
-  template<typename T> struct StructKeyComparator {
-    bool operator()(const T &a, const T &b) const {
-      return a.KeyCompareLessThan(&b);
-    }
-
-   private:
-    StructKeyComparator &operator=(const StructKeyComparator &);
-  };
-  /// @endcond
-
-  /// @brief Serialize a `std::vector` of structs into a FlatBuffer `vector`
-  /// in sorted order.
-  /// @tparam T The data type of the `std::vector` struct elements.
-  /// @param[in] v A const reference to the `std::vector` of structs to
-  /// serialize into the buffer as a `vector`.
-  /// @return Returns a typed `Offset` into the serialized data indicating
-  /// where the vector is stored.
   template<typename T>
-  Offset<Vector<const T *>> CreateVectorOfSortedStructs(std::vector<T> *v) {
-    return CreateVectorOfSortedStructs(data(*v), v->size());
-  }
-
-  /// @brief Serialize a `std::vector` of native structs into a FlatBuffer
-  /// `vector` in sorted order.
-  /// @tparam T The data type of the `std::vector` struct elements.
-  /// @tparam S The data type of the `std::vector` native struct elements.
-  /// @param[in] v A const reference to the `std::vector` of structs to
-  /// serialize into the buffer as a `vector`.
-  /// @return Returns a typed `Offset` into the serialized data indicating
-  /// where the vector is stored.
-  template<typename T, typename S>
-  Offset<Vector<const T *>> CreateVectorOfSortedNativeStructs(
-      std::vector<S> *v) {
-    return CreateVectorOfSortedNativeStructs<T, S>(data(*v), v->size());
-  }
-
-  /// @brief Serialize an array of structs into a FlatBuffer `vector` in sorted
-  /// order.
-  /// @tparam T The data type of the struct array elements.
-  /// @param[in] v A pointer to the array of type `T` to serialize into the
-  /// buffer as a `vector`.
-  /// @param[in] len The number of elements to serialize.
-  /// @return Returns a typed `Offset` into the serialized data indicating
-  /// where the vector is stored.
-  template<typename T>
-  Offset<Vector<const T *>> CreateVectorOfSortedStructs(T *v, size_t len) {
-    std::sort(v, v + len, StructKeyComparator<T>());
-    return CreateVectorOfStructs(v, len);
-  }
-
-  /// @brief Serialize an array of native structs into a FlatBuffer `vector` in
-  /// sorted order.
-  /// @tparam T The data type of the struct array elements.
-  /// @tparam S The data type of the native struct array elements.
-  /// @param[in] v A pointer to the array of type `S` to serialize into the
-  /// buffer as a `vector`.
-  /// @param[in] len The number of elements to serialize.
-  /// @return Returns a typed `Offset` into the serialized data indicating
-  /// where the vector is stored.
-  template<typename T, typename S>
-  Offset<Vector<const T *>> CreateVectorOfSortedNativeStructs(S *v,
-                                                              size_t len) {
-    extern T Pack(const S &);
-    typedef T (*Pack_t)(const S &);
-    std::vector<T> vv(len);
-    std::transform(v, v + len, vv.begin(), static_cast<Pack_t &>(Pack));
-    return CreateVectorOfSortedStructs<T>(vv, len);
-  }
-
-  /// @cond FLATBUFFERS_INTERNAL
-  template<typename T> struct TableKeyComparator {
-    TableKeyComparator(vector_downward &buf) : buf_(buf) {}
-    TableKeyComparator(const TableKeyComparator &other) : buf_(other.buf_) {}
+  struct TableKeyComparator {
+  explicit TableKeyComparator(vector_downward& buf) : buf_(buf) {}
     bool operator()(const Offset<T> &a, const Offset<T> &b) const {
       auto table_a = reinterpret_cast<T *>(buf_.data_at(a.o));
       auto table_b = reinterpret_cast<T *>(buf_.data_at(b.o));
       return table_a->KeyCompareLessThan(table_b);
     }
-    vector_downward &buf_;
+    vector_downward& buf_;
 
-   private:
-    TableKeyComparator &operator=(const TableKeyComparator &other) {
-      buf_ = other.buf_;
-      return *this;
-    }
+  private:
+    TableKeyComparator& operator= (const TableKeyComparator&);
   };
   /// @endcond
 
+  #ifndef FLATBUFFERS_CHRE
   /// @brief Serialize an array of `table` offsets as a `vector` in the buffer
   /// in sorted order.
   /// @tparam T The data type that the offset refers to.
@@ -1965,9 +1260,8 @@
   /// @param[in] len The number of elements to store in the `vector`.
   /// @return Returns a typed `Offset` into the serialized data indicating
   /// where the vector is stored.
-  template<typename T>
-  Offset<Vector<Offset<T>>> CreateVectorOfSortedTables(Offset<T> *v,
-                                                       size_t len) {
+  template<typename T> Offset<Vector<Offset<T>>> CreateVectorOfSortedTables(
+      Offset<T> *v, size_t len) {
     std::sort(v, v + len, TableKeyComparator<T>(buf_));
     return CreateVector(v, len);
   }
@@ -1979,12 +1273,11 @@
   /// offsets to store in the buffer in sorted order.
   /// @return Returns a typed `Offset` into the serialized data indicating
   /// where the vector is stored.
-  template<typename T>
-  Offset<Vector<Offset<T>>> CreateVectorOfSortedTables(
+  template<typename T> Offset<Vector<Offset<T>>> CreateVectorOfSortedTables(
       std::vector<Offset<T>> *v) {
     return CreateVectorOfSortedTables(data(*v), v->size());
   }
-  #endif  // !FLATBUFFERS_CHRE
+  #endif  // FLATBUFFERS_CHRE
 
   /// @brief Specialized version of `CreateVector` for non-copying use cases.
   /// Write the data any time later to the returned buffer pointer `buf`.
@@ -2012,48 +1305,21 @@
   /// @param[out] buf A pointer to a pointer of type `T` that can be
   /// written to at a later time to serialize the data into a `vector`
   /// in the buffer.
-  template<typename T>
-  Offset<Vector<T>> CreateUninitializedVector(size_t len, T **buf) {
-    AssertScalarT<T>();
+  template<typename T> Offset<Vector<T>> CreateUninitializedVector(
+      size_t len, T **buf) {
     return CreateUninitializedVector(len, sizeof(T),
                                      reinterpret_cast<uint8_t **>(buf));
   }
 
-  template<typename T>
-  Offset<Vector<const T *>> CreateUninitializedVectorOfStructs(size_t len,
-                                                               T **buf) {
-    return CreateUninitializedVector(len, sizeof(T),
-                                     reinterpret_cast<uint8_t **>(buf));
-  }
-
-  // @brief Create a vector of scalar type T given as input a vector of scalar
-  // type U, useful with e.g. pre "enum class" enums, or any existing scalar
-  // data of the wrong type.
-  template<typename T, typename U>
-  Offset<Vector<T>> CreateVectorScalarCast(const U *v, size_t len) {
-    AssertScalarT<T>();
-    AssertScalarT<U>();
-    StartVector(len, sizeof(T));
-    for (auto i = len; i > 0;) { PushElement(static_cast<T>(v[--i])); }
-    return Offset<Vector<T>>(EndVector(len));
-  }
-
-  /// @brief Write a struct by itself, typically to be part of a union.
-  template<typename T> Offset<const T *> CreateStruct(const T &structobj) {
-    NotNested();
-    Align(AlignOf<T>());
-    buf_.push_small(structobj);
-    return Offset<const T *>(GetSize());
-  }
-
   /// @brief The length of a FlatBuffer file header.
   static const size_t kFileIdentifierLength = 4;
 
   /// @brief Finish serializing a buffer by writing the root offset.
   /// @param[in] file_identifier If a `file_identifier` is given, the buffer
   /// will be prefixed with a standard FlatBuffers file header.
-  template<typename T>
-  void Finish(Offset<T> root, const char *file_identifier = nullptr) {
+  template<typename T> void Finish(Offset<T> root,
+                                   const char *file_identifier = nullptr) {
+
     Finish(root.o, file_identifier, false);
   }
 
@@ -2064,35 +1330,32 @@
   /// All >32 bit quantities in this buffer will be aligned when the whole
   /// size pre-fixed buffer is aligned.
   /// These kinds of buffers are useful for creating a stream of FlatBuffers.
-  template<typename T>
-  void FinishSizePrefixed(Offset<T> root,
-                          const char *file_identifier = nullptr) {
+  template<typename T> void FinishSizePrefixed(Offset<T> root,
+                                   const char *file_identifier = nullptr) {
     Finish(root.o, file_identifier, true);
   }
 
-  void SwapBufAllocator(FlatBufferBuilder &other) {
-    buf_.swap_allocator(other.buf_);
-  }
-
- protected:
+ private:
   // You shouldn't really be copying instances of this class.
   FlatBufferBuilder(const FlatBufferBuilder &);
   FlatBufferBuilder &operator=(const FlatBufferBuilder &);
 
   void Finish(uoffset_t root, const char *file_identifier, bool size_prefix) {
     NotNested();
-    buf_.clear_scratch();
     // This will cause the whole buffer to be aligned.
-    PreAlign((size_prefix ? sizeof(uoffset_t) : 0) + sizeof(uoffset_t) +
-                 (file_identifier ? kFileIdentifierLength : 0),
+    PreAlign((size_prefix ? sizeof(uoffset_t) : 0) +
+             sizeof(uoffset_t) +
+             (file_identifier ? kFileIdentifierLength : 0),
              minalign_);
     if (file_identifier) {
-      FLATBUFFERS_ASSERT(strlen(file_identifier) == kFileIdentifierLength);
+      assert(strlen(file_identifier) == kFileIdentifierLength);
       PushBytes(reinterpret_cast<const uint8_t *>(file_identifier),
                 kFileIdentifierLength);
     }
     PushElement(ReferTo(root));  // Location of root.
-    if (size_prefix) { PushElement(GetSize()); }
+    if (size_prefix) {
+      PushElement(GetSize());
+    }
     finished = true;
   }
 
@@ -2101,14 +1364,16 @@
     voffset_t id;
   };
 
+  simple_allocator default_allocator;
+
   vector_downward buf_;
 
+  #ifndef FLATBUFFERS_CHRE
   // Accumulating offsets of table members while it is being built.
-  // We store these in the scratch pad of buf_, after the vtable offsets.
-  uoffset_t num_field_loc;
-  // Track how much of the vtable is in use, so we can output the most compact
-  // possible vtable.
-  voffset_t max_voffset_;
+  std::vector<FieldLoc> offsetbuf_;
+  #else
+  chre::DynamicVector<FieldLoc> offsetbuf_;
+  #endif  // FLATBUFFERS_CHRE
 
   // Ensure objects are not nested.
   bool nested;
@@ -2116,6 +1381,12 @@
   // Ensure the buffer is finished before it is being accessed.
   bool finished;
 
+  #ifndef FLATBUFFERS_CHRE
+  std::vector<uoffset_t> vtables_;  // todo: Could make this into a map?
+  #else
+  chre::DynamicVector<uoffset_t> vtables_;
+  #endif
+
   size_t minalign_;
 
   bool force_defaults_;  // Serialize values equal to their defaults anyway.
@@ -2124,12 +1395,12 @@
 
   #ifndef FLATBUFFERS_CHRE
   struct StringOffsetCompare {
-    StringOffsetCompare(const vector_downward &buf) : buf_(&buf) {}
-    bool operator()(const Offset<String> &a, const Offset<String> &b) const {
+    explicit StringOffsetCompare(const vector_downward &buf) : buf_(&buf) {}
+    bool operator() (const Offset<String> &a, const Offset<String> &b) const {
       auto stra = reinterpret_cast<const String *>(buf_->data_at(a.o));
       auto strb = reinterpret_cast<const String *>(buf_->data_at(b.o));
-      return StringLessThan(stra->data(), stra->size(), strb->data(),
-                            strb->size());
+      return strncmp(stra->c_str(), strb->c_str(),
+                     std::min(stra->size(), strb->size()) + 1) < 0;
     }
     const vector_downward *buf_;
   };
@@ -2137,22 +1408,7 @@
   // For use with CreateSharedString. Instantiated on first use only.
   typedef std::set<Offset<String>, StringOffsetCompare> StringOffsetMap;
   StringOffsetMap *string_pool;
-  #endif  // !FLATBUFFERS_CHRE
-
- private:
-  // Allocates space for a vector of structures.
-  // Must be completed with EndVectorOfStructs().
-  template<typename T> T *StartVectorOfStructs(size_t vector_size) {
-    StartVector(vector_size * sizeof(T) / AlignOf<T>(), AlignOf<T>());
-    return reinterpret_cast<T *>(buf_.make_space(vector_size * sizeof(T)));
-  }
-
-  // End the vector of structues in the flatbuffers.
-  // Vector should have previously be started with StartVectorOfStructs().
-  template<typename T>
-  Offset<Vector<const T *>> EndVectorOfStructs(size_t vector_size) {
-    return Offset<Vector<const T *>>(EndVector(vector_size));
-  }
+  #endif  // FLATBUFFERS_CHRE
 };
 /// @}
 
@@ -2160,9 +1416,8 @@
 // Helpers to get a typed pointer to the root object contained in the buffer.
 template<typename T> T *GetMutableRoot(void *buf) {
   EndianCheck();
-  return reinterpret_cast<T *>(
-      reinterpret_cast<uint8_t *>(buf) +
-      EndianScalar(*reinterpret_cast<uoffset_t *>(buf)));
+  return reinterpret_cast<T *>(reinterpret_cast<uint8_t *>(buf) +
+    EndianScalar(*reinterpret_cast<uoffset_t *>(buf)));
 }
 
 template<typename T> const T *GetRoot(const void *buf) {
@@ -2176,101 +1431,62 @@
 /// Helpers to get a typed pointer to objects that are currently being built.
 /// @warning Creating new objects will lead to reallocations and invalidates
 /// the pointer!
-template<typename T>
-T *GetMutableTemporaryPointer(FlatBufferBuilder &fbb, Offset<T> offset) {
-  return reinterpret_cast<T *>(fbb.GetCurrentBufferPointer() + fbb.GetSize() -
-                               offset.o);
+template<typename T> T *GetMutableTemporaryPointer(FlatBufferBuilder &fbb,
+                                                   Offset<T> offset) {
+  return reinterpret_cast<T *>(fbb.GetCurrentBufferPointer() +
+    fbb.GetSize() - offset.o);
 }
 
-template<typename T>
-const T *GetTemporaryPointer(FlatBufferBuilder &fbb, Offset<T> offset) {
+template<typename T> const T *GetTemporaryPointer(FlatBufferBuilder &fbb,
+                                                  Offset<T> offset) {
   return GetMutableTemporaryPointer<T>(fbb, offset);
 }
 
-/// @brief Get a pointer to the the file_identifier section of the buffer.
-/// @return Returns a const char pointer to the start of the file_identifier
-/// characters in the buffer.  The returned char * has length
-/// 'flatbuffers::FlatBufferBuilder::kFileIdentifierLength'.
-/// This function is UNDEFINED for FlatBuffers whose schema does not include
-/// a file_identifier (likely points at padding or the start of a the root
-/// vtable).
-inline const char *GetBufferIdentifier(const void *buf,
-                                       bool size_prefixed = false) {
-  return reinterpret_cast<const char *>(buf) +
-         ((size_prefixed) ? 2 * sizeof(uoffset_t) : sizeof(uoffset_t));
-}
-
 // Helper to see if the identifier in a buffer has the expected value.
-inline bool BufferHasIdentifier(const void *buf, const char *identifier,
-                                bool size_prefixed = false) {
-  return strncmp(GetBufferIdentifier(buf, size_prefixed), identifier,
-                 FlatBufferBuilder::kFileIdentifierLength) == 0;
+inline bool BufferHasIdentifier(const void *buf, const char *identifier) {
+  return strncmp(reinterpret_cast<const char *>(buf) + sizeof(uoffset_t),
+                 identifier, FlatBufferBuilder::kFileIdentifierLength) == 0;
 }
 
 // Helper class to verify the integrity of a FlatBuffer
 class Verifier FLATBUFFERS_FINAL_CLASS {
  public:
-  Verifier(const uint8_t *buf, size_t buf_len, uoffset_t _max_depth = 64,
-           uoffset_t _max_tables = 1000000, bool _check_alignment = true)
-      : buf_(buf),
-        size_(buf_len),
-        depth_(0),
-        max_depth_(_max_depth),
-        num_tables_(0),
-        max_tables_(_max_tables),
-        upper_bound_(0),
-        check_alignment_(_check_alignment) {
-    FLATBUFFERS_ASSERT(size_ < FLATBUFFERS_MAX_BUFFER_SIZE);
-  }
+  Verifier(const uint8_t *buf, size_t buf_len, size_t _max_depth = 64,
+           size_t _max_tables = 1000000)
+    : buf_(buf), end_(buf + buf_len), depth_(0), max_depth_(_max_depth),
+      num_tables_(0), max_tables_(_max_tables)
+    #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
+        , upper_bound_(buf)
+    #endif
+    {}
 
   // Central location where any verification failures register.
   bool Check(bool ok) const {
-    // clang-format off
     #ifdef FLATBUFFERS_DEBUG_VERIFICATION_FAILURE
-      FLATBUFFERS_ASSERT(ok);
+      assert(ok);
     #endif
     #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
       if (!ok)
-        upper_bound_ = 0;
+        upper_bound_ = buf_;
     #endif
-    // clang-format on
     return ok;
   }
 
   // Verify any range within the buffer.
-  bool Verify(size_t elem, size_t elem_len) const {
-    // clang-format off
+  bool Verify(const void *elem, size_t elem_len) const {
     #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
-      auto upper_bound = elem + elem_len;
+      auto upper_bound = reinterpret_cast<const uint8_t *>(elem) + elem_len;
       if (upper_bound_ < upper_bound)
         upper_bound_ =  upper_bound;
     #endif
-    // clang-format on
-    return Check(elem_len < size_ && elem <= size_ - elem_len);
-  }
-
-  template<typename T> bool VerifyAlignment(size_t elem) const {
-    return Check((elem & (sizeof(T) - 1)) == 0 || !check_alignment_);
+    return Check(elem_len <= (size_t) (end_ - buf_) &&
+                 elem >= buf_ &&
+                 elem <= end_ - elem_len);
   }
 
   // Verify a range indicated by sizeof(T).
-  template<typename T> bool Verify(size_t elem) const {
-    return VerifyAlignment<T>(elem) && Verify(elem, sizeof(T));
-  }
-
-  bool VerifyFromPointer(const uint8_t *p, size_t len) {
-    auto o = static_cast<size_t>(p - buf_);
-    return Verify(o, len);
-  }
-
-  // Verify relative to a known-good base pointer.
-  bool Verify(const uint8_t *base, voffset_t elem_off, size_t elem_len) const {
-    return Verify(static_cast<size_t>(base - buf_) + elem_off, elem_len);
-  }
-
-  template<typename T>
-  bool Verify(const uint8_t *base, voffset_t elem_off) const {
-    return Verify(static_cast<size_t>(base - buf_) + elem_off, sizeof(T));
+  template<typename T> bool Verify(const void *elem) const {
+    return Verify(elem, sizeof(T));
   }
 
   // Verify a pointer (may be NULL) of a table type.
@@ -2279,33 +1495,34 @@
   }
 
   // Verify a pointer (may be NULL) of any vector type.
-  template<typename T> bool VerifyVector(const Vector<T> *vec) const {
-    return !vec || VerifyVectorOrString(reinterpret_cast<const uint8_t *>(vec),
-                                        sizeof(T));
+  template<typename T> bool Verify(const Vector<T> *vec) const {
+    const uint8_t *end;
+    return !vec ||
+           VerifyVector(reinterpret_cast<const uint8_t *>(vec), sizeof(T),
+                        &end);
   }
 
   // Verify a pointer (may be NULL) of a vector to struct.
-  template<typename T> bool VerifyVector(const Vector<const T *> *vec) const {
-    return VerifyVector(reinterpret_cast<const Vector<T> *>(vec));
+  template<typename T> bool Verify(const Vector<const T *> *vec) const {
+    return Verify(reinterpret_cast<const Vector<T> *>(vec));
   }
 
   #ifndef FLATBUFFERS_CHRE
   // Verify a pointer (may be NULL) to string.
-  bool VerifyString(const String *str) const {
-    size_t end;
-    return !str || (VerifyVectorOrString(reinterpret_cast<const uint8_t *>(str),
-                                         1, &end) &&
-                    Verify(end, 1) &&           // Must have terminator
-                    Check(buf_[end] == '\0'));  // Terminating byte must be 0.
+  bool Verify(const String *str) const {
+    const uint8_t *end;
+    return !str ||
+           (VerifyVector(reinterpret_cast<const uint8_t *>(str), 1, &end) &&
+            Verify(end, 1) &&      // Must have terminator
+            Check(*end == '\0'));  // Terminating byte must be 0.
   }
-  #endif
+  #endif  // FLATBUFFERS_CHRE
 
   // Common code between vectors and strings.
-  bool VerifyVectorOrString(const uint8_t *vec, size_t elem_size,
-                            size_t *end = nullptr) const {
-    auto veco = static_cast<size_t>(vec - buf_);
+  bool VerifyVector(const uint8_t *vec, size_t elem_size,
+                    const uint8_t **end) const {
     // Check we can read the size field.
-    if (!Verify<uoffset_t>(veco)) return false;
+    if (!Verify<uoffset_t>(vec)) return false;
     // Check the whole array. If this is a string, the byte past the array
     // must be 0.
     auto size = ReadScalar<uoffset_t>(vec);
@@ -2313,21 +1530,21 @@
     if (!Check(size < max_elems))
       return false;  // Protect against byte_size overflowing.
     auto byte_size = sizeof(size) + elem_size * size;
-    if (end) *end = veco + byte_size;
-    return Verify(veco, byte_size);
+    *end = vec + byte_size;
+    return Verify(vec, byte_size);
   }
 
   #ifndef FLATBUFFERS_CHRE
   // Special case for string contents, after the above has been called.
   bool VerifyVectorOfStrings(const Vector<Offset<String>> *vec) const {
-    if (vec) {
-      for (uoffset_t i = 0; i < vec->size(); i++) {
-        if (!VerifyString(vec->Get(i))) return false;
+      if (vec) {
+        for (uoffset_t i = 0; i < vec->size(); i++) {
+          if (!Verify(vec->Get(i))) return false;
+        }
       }
-    }
-    return true;
+      return true;
   }
-  #endif
+  #endif  // FLATBUFFERS_CHRE
 
   // Special case for table contents, after the above has been called.
   template<typename T> bool VerifyVectorOfTables(const Vector<Offset<T>> *vec) {
@@ -2339,66 +1556,33 @@
     return true;
   }
 
-  __supress_ubsan__("unsigned-integer-overflow") bool VerifyTableStart(
-      const uint8_t *table) {
-    // Check the vtable offset.
-    auto tableo = static_cast<size_t>(table - buf_);
-    if (!Verify<soffset_t>(tableo)) return false;
-    // This offset may be signed, but doing the subtraction unsigned always
-    // gives the result we want.
-    auto vtableo = tableo - static_cast<size_t>(ReadScalar<soffset_t>(table));
-    // Check the vtable size field, then check vtable fits in its entirety.
-    return VerifyComplexity() && Verify<voffset_t>(vtableo) &&
-           VerifyAlignment<voffset_t>(ReadScalar<voffset_t>(buf_ + vtableo)) &&
-           Verify(vtableo, ReadScalar<voffset_t>(buf_ + vtableo));
-  }
-
-  template<typename T>
-  bool VerifyBufferFromStart(const char *identifier, size_t start) {
-    if (identifier && (size_ < 2 * sizeof(flatbuffers::uoffset_t) ||
-                       !BufferHasIdentifier(buf_ + start, identifier))) {
+  template<typename T> bool VerifyBufferFromStart(const char *identifier,
+                                                  const uint8_t *start) {
+    if (identifier &&
+        (size_t(end_ - start) < 2 * sizeof(flatbuffers::uoffset_t) ||
+         !BufferHasIdentifier(start, identifier))) {
       return false;
     }
 
     // Call T::Verify, which must be in the generated code for this type.
-    auto o = VerifyOffset(start);
-    return o && reinterpret_cast<const T *>(buf_ + start + o)->Verify(*this)
-    // clang-format off
-    #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
-           && GetComputedSize()
-    #endif
-        ;
-    // clang-format on
+    return Verify<uoffset_t>(start) &&
+      reinterpret_cast<const T *>(start + ReadScalar<uoffset_t>(start))->
+        Verify(*this)
+        #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
+          && GetComputedSize()
+        #endif
+            ;
   }
 
   // Verify this whole buffer, starting with root type T.
-  template<typename T> bool VerifyBuffer() { return VerifyBuffer<T>(nullptr); }
-
   template<typename T> bool VerifyBuffer(const char *identifier) {
-    return VerifyBufferFromStart<T>(identifier, 0);
+    return VerifyBufferFromStart<T>(identifier, buf_);
   }
 
   template<typename T> bool VerifySizePrefixedBuffer(const char *identifier) {
-    return Verify<uoffset_t>(0U) &&
-           ReadScalar<uoffset_t>(buf_) == size_ - sizeof(uoffset_t) &&
-           VerifyBufferFromStart<T>(identifier, sizeof(uoffset_t));
-  }
-
-  uoffset_t VerifyOffset(size_t start) const {
-    if (!Verify<uoffset_t>(start)) return 0;
-    auto o = ReadScalar<uoffset_t>(buf_ + start);
-    // May not point to itself.
-    if (!Check(o != 0)) return 0;
-    // Can't wrap around / buffers are max 2GB.
-    if (!Check(static_cast<soffset_t>(o) >= 0)) return 0;
-    // Must be inside the buffer to create a pointer from it (pointer outside
-    // buffer is UB).
-    if (!Verify(start + o, 1)) return 0;
-    return o;
-  }
-
-  uoffset_t VerifyOffset(const uint8_t *base, voffset_t start) const {
-    return VerifyOffset(static_cast<size_t>(base - buf_) + start);
+    return Verify<uoffset_t>(buf_) &&
+           ReadScalar<uoffset_t>(buf_) == end_ - buf_ - sizeof(uoffset_t) &&
+           VerifyBufferFromStart<T>(identifier, buf_ + sizeof(uoffset_t));
   }
 
   // Called at the start of a table to increase counters measuring data
@@ -2417,32 +1601,26 @@
     return true;
   }
 
+  #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
   // Returns the message size in bytes
   size_t GetComputedSize() const {
-    // clang-format off
-    #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
-      uintptr_t size = upper_bound_;
-      // Align the size to uoffset_t
-      size = (size - 1 + sizeof(uoffset_t)) & ~(sizeof(uoffset_t) - 1);
-      return (size > size_) ?  0 : size;
-    #else
-      // Must turn on FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE for this to work.
-      (void)upper_bound_;
-      FLATBUFFERS_ASSERT(false);
-      return 0;
-    #endif
-    // clang-format on
+    uintptr_t size = upper_bound_ - buf_;
+    // Align the size to uoffset_t
+    size = (size - 1 + sizeof(uoffset_t)) & ~(sizeof(uoffset_t) - 1);
+    return (buf_  + size > end_) ?  0 : size;
   }
+  #endif
 
  private:
   const uint8_t *buf_;
-  size_t size_;
-  uoffset_t depth_;
-  uoffset_t max_depth_;
-  uoffset_t num_tables_;
-  uoffset_t max_tables_;
-  mutable size_t upper_bound_;
-  bool check_alignment_;
+  const uint8_t *end_;
+  size_t depth_;
+  size_t max_depth_;
+  size_t num_tables_;
+  size_t max_tables_;
+#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
+  mutable const uint8_t *upper_bound_;
+#endif
 };
 
 // Convenient way to bundle a buffer and its length, to pass it around
@@ -2452,11 +1630,9 @@
 template<typename T> struct BufferRef : BufferRefBase {
   BufferRef() : buf(nullptr), len(0), must_free(false) {}
   BufferRef(uint8_t *_buf, uoffset_t _len)
-      : buf(_buf), len(_len), must_free(false) {}
+    : buf(_buf), len(_len), must_free(false) {}
 
-  ~BufferRef() {
-    if (must_free) free(buf);
-  }
+  ~BufferRef() { if (must_free) free(buf); }
 
   const T *GetRoot() const { return flatbuffers::GetRoot<T>(buf); }
 
@@ -2488,12 +1664,6 @@
   uint8_t *GetAddressOf(uoffset_t o) { return &data_[o]; }
 
  private:
-  // private constructor & copy constructor: you obtain instances of this
-  // class by pointing to existing data only
-  Struct();
-  Struct(const Struct &);
-  Struct &operator=(const Struct &);
-
   uint8_t data_[1];
 };
 
@@ -2525,8 +1695,9 @@
   template<typename P> P GetPointer(voffset_t field) {
     auto field_offset = GetOptionalFieldOffset(field);
     auto p = data_ + field_offset;
-    return field_offset ? reinterpret_cast<P>(p + ReadScalar<uoffset_t>(p))
-                        : nullptr;
+    return field_offset
+      ? reinterpret_cast<P>(p + ReadScalar<uoffset_t>(p))
+      : nullptr;
   }
   template<typename P> P GetPointer(voffset_t field) const {
     return const_cast<Table *>(this)->GetPointer<P>(field);
@@ -2538,9 +1709,9 @@
     return field_offset ? reinterpret_cast<P>(p) : nullptr;
   }
 
-  template<typename T> bool SetField(voffset_t field, T val, T def) {
+  template<typename T> bool SetField(voffset_t field, T val) {
     auto field_offset = GetOptionalFieldOffset(field);
-    if (!field_offset) return IsTheSameAs(val, def);
+    if (!field_offset) return false;
     WriteScalar(data_ + field_offset, val);
     return true;
   }
@@ -2568,37 +1739,32 @@
   // Verify the vtable of this table.
   // Call this once per table, followed by VerifyField once per field.
   bool VerifyTableStart(Verifier &verifier) const {
-    return verifier.VerifyTableStart(data_);
+    // Check the vtable offset.
+    if (!verifier.Verify<soffset_t>(data_)) return false;
+    auto vtable = GetVTable();
+    // Check the vtable size field, then check vtable fits in its entirety.
+    return verifier.VerifyComplexity() &&
+           verifier.Verify<voffset_t>(vtable) &&
+           (ReadScalar<voffset_t>(vtable) & (sizeof(voffset_t) - 1)) == 0 &&
+           verifier.Verify(vtable, ReadScalar<voffset_t>(vtable));
   }
 
   // Verify a particular field.
-  template<typename T>
-  bool VerifyField(const Verifier &verifier, voffset_t field) const {
+  template<typename T> bool VerifyField(const Verifier &verifier,
+                                        voffset_t field) const {
     // Calling GetOptionalFieldOffset should be safe now thanks to
     // VerifyTable().
     auto field_offset = GetOptionalFieldOffset(field);
     // Check the actual field.
-    return !field_offset || verifier.Verify<T>(data_, field_offset);
+    return !field_offset || verifier.Verify<T>(data_ + field_offset);
   }
 
   // VerifyField for required fields.
-  template<typename T>
-  bool VerifyFieldRequired(const Verifier &verifier, voffset_t field) const {
+  template<typename T> bool VerifyFieldRequired(const Verifier &verifier,
+                                        voffset_t field) const {
     auto field_offset = GetOptionalFieldOffset(field);
     return verifier.Check(field_offset != 0) &&
-           verifier.Verify<T>(data_, field_offset);
-  }
-
-  // Versions for offsets.
-  bool VerifyOffset(const Verifier &verifier, voffset_t field) const {
-    auto field_offset = GetOptionalFieldOffset(field);
-    return !field_offset || verifier.VerifyOffset(data_, field_offset);
-  }
-
-  bool VerifyOffsetRequired(const Verifier &verifier, voffset_t field) const {
-    auto field_offset = GetOptionalFieldOffset(field);
-    return verifier.Check(field_offset != 0) &&
-           verifier.VerifyOffset(data_, field_offset);
+           verifier.Verify<T>(data_ + field_offset);
   }
 
  private:
@@ -2606,20 +1772,10 @@
   // class by pointing to existing data only
   Table();
   Table(const Table &other);
-  Table &operator=(const Table &);
 
   uint8_t data_[1];
 };
 
-template<typename T>
-void FlatBufferBuilder::Required(Offset<T> table, voffset_t field) {
-  auto table_ptr = reinterpret_cast<const Table *>(buf_.data_at(table.o));
-  bool ok = table_ptr->GetOptionalFieldOffset(field) != 0;
-  // If this fails, the caller will show what field needs to be set.
-  FLATBUFFERS_ASSERT(ok);
-  (void)ok;
-}
-
 /// @brief This can compute the start of a FlatBuffer from a root pointer, i.e.
 /// it is the opposite transformation of GetRoot().
 /// This may be useful if you want to pass on a root and have the recipient
@@ -2628,10 +1784,10 @@
   auto table = reinterpret_cast<const Table *>(root);
   auto vtable = table->GetVTable();
   // Either the vtable is before the root or after the root.
-  auto start = (std::min)(vtable, reinterpret_cast<const uint8_t *>(root));
+  auto start = std::min(vtable, reinterpret_cast<const uint8_t *>(root));
   // Align to at least sizeof(uoffset_t).
-  start = reinterpret_cast<const uint8_t *>(reinterpret_cast<uintptr_t>(start) &
-                                            ~(sizeof(uoffset_t) - 1));
+  start = reinterpret_cast<const uint8_t *>(
+            reinterpret_cast<uintptr_t>(start) & ~(sizeof(uoffset_t) - 1));
   // Additionally, there may be a file_identifier in the buffer, and the root
   // offset. The buffer may have been aligned to any size between
   // sizeof(uoffset_t) and FLATBUFFERS_MAX_ALIGNMENT (see "force_align").
@@ -2644,29 +1800,25 @@
   static_assert(FlatBufferBuilder::kFileIdentifierLength == sizeof(uoffset_t),
                 "file_identifier is assumed to be the same size as uoffset_t");
   for (auto possible_roots = FLATBUFFERS_MAX_ALIGNMENT / sizeof(uoffset_t) + 1;
-       possible_roots; possible_roots--) {
-    start -= sizeof(uoffset_t);
-    if (ReadScalar<uoffset_t>(start) + start ==
-        reinterpret_cast<const uint8_t *>(root))
-      return start;
+       possible_roots;
+       possible_roots--) {
+      start -= sizeof(uoffset_t);
+      if (ReadScalar<uoffset_t>(start) + start ==
+          reinterpret_cast<const uint8_t *>(root)) return start;
   }
   // We didn't find the root, either the "root" passed isn't really a root,
   // or the buffer is corrupt.
   // Assert, because calling this function with bad data may cause reads
   // outside of buffer boundaries.
-  FLATBUFFERS_ASSERT(false);
+  assert(false);
   return nullptr;
 }
 
-/// @brief This return the prefixed size of a FlatBuffer.
-inline uoffset_t GetPrefixedSize(const uint8_t *buf) {
-  return ReadScalar<uoffset_t>(buf);
-}
-
 // Base class for native objects (FlatBuffer data de-serialized into native
 // C++ data structures).
 // Contains no functionality, purely documentative.
-struct NativeTable {};
+struct NativeTable {
+};
 
 /// @brief Function types to be used with resolving hashes into objects and
 /// back again. The resolver gets a pointer to a field inside an object API
@@ -2677,8 +1829,7 @@
 /// if you wish. The resolver does the opposite lookup, for when the object
 /// is being serialized again.
 typedef uint64_t hash_value_t;
-// clang-format off
-#if defined(FLATBUFFERS_CPP98_STL) || defined(FLATBUFFERS_CHRE)
+#ifdef FLATBUFFERS_CPP98_STL
   typedef void (*resolver_function_t)(void **pointer_adr, hash_value_t hash);
   typedef hash_value_t (*rehasher_function_t)(void *pointer);
 #else
@@ -2686,7 +1837,6 @@
           resolver_function_t;
   typedef std::function<hash_value_t (void *pointer)> rehasher_function_t;
 #endif
-// clang-format on
 
 // Helper function to test if a field is present, using any of the field
 // enums in the generated code.
@@ -2695,11 +1845,9 @@
 // Note: this function will return false for fields equal to the default
 // value, since they're not stored in the buffer (unless force_defaults was
 // used).
-template<typename T>
-bool IsFieldPresent(const T *table, typename T::FlatBuffersVTableOffset field) {
+template<typename T> bool IsFieldPresent(const T *table, voffset_t field) {
   // Cast, since Table is a private baseclass of any table types.
-  return reinterpret_cast<const Table *>(table)->CheckField(
-      static_cast<voffset_t>(field));
+  return reinterpret_cast<const Table *>(table)->CheckField(field);
 }
 
 // Utility function for reverse lookups on the EnumNames*() functions
@@ -2707,7 +1855,8 @@
 // names must be NULL terminated.
 inline int LookupEnum(const char **names, const char *name) {
   for (const char **p = names; *p; p++)
-    if (!strcmp(*p, name)) return static_cast<int>(p - names);
+    if (!strcmp(*p, name))
+      return static_cast<int>(p - names);
   return -1;
 }
 
@@ -2721,94 +1870,23 @@
 // by the force_align attribute.
 // These are used in the generated code only.
 
-// clang-format off
 #if defined(_MSC_VER)
-  #define FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(alignment) \
-    __pragma(pack(1)) \
+  #define MANUALLY_ALIGNED_STRUCT(alignment) \
+    __pragma(pack(1)); \
     struct __declspec(align(alignment))
-  #define FLATBUFFERS_STRUCT_END(name, size) \
-    __pragma(pack()) \
+  #define STRUCT_END(name, size) \
+    __pragma(pack()); \
     static_assert(sizeof(name) == size, "compiler breaks packing rules")
-#elif defined(__GNUC__) || defined(__clang__) || defined(__ICCARM__)
-  #define FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(alignment) \
+#elif defined(__GNUC__) || defined(__clang__)
+  #define MANUALLY_ALIGNED_STRUCT(alignment) \
     _Pragma("pack(1)") \
     struct __attribute__((aligned(alignment)))
-  #define FLATBUFFERS_STRUCT_END(name, size) \
+  #define STRUCT_END(name, size) \
     _Pragma("pack()") \
     static_assert(sizeof(name) == size, "compiler breaks packing rules")
 #else
   #error Unknown compiler, please define structure alignment macros
 #endif
-// clang-format on
-
-// Minimal reflection via code generation.
-// Besides full-fat reflection (see reflection.h) and parsing/printing by
-// loading schemas (see idl.h), we can also have code generation for mimimal
-// reflection data which allows pretty-printing and other uses without needing
-// a schema or a parser.
-// Generate code with --reflect-types (types only) or --reflect-names (names
-// also) to enable.
-// See minireflect.h for utilities using this functionality.
-
-// These types are organized slightly differently as the ones in idl.h.
-enum SequenceType { ST_TABLE, ST_STRUCT, ST_UNION, ST_ENUM };
-
-// Scalars have the same order as in idl.h
-// clang-format off
-#define FLATBUFFERS_GEN_ELEMENTARY_TYPES(ET) \
-  ET(ET_UTYPE) \
-  ET(ET_BOOL) \
-  ET(ET_CHAR) \
-  ET(ET_UCHAR) \
-  ET(ET_SHORT) \
-  ET(ET_USHORT) \
-  ET(ET_INT) \
-  ET(ET_UINT) \
-  ET(ET_LONG) \
-  ET(ET_ULONG) \
-  ET(ET_FLOAT) \
-  ET(ET_DOUBLE) \
-  ET(ET_STRING) \
-  ET(ET_SEQUENCE)  // See SequenceType.
-
-enum ElementaryType {
-  #define FLATBUFFERS_ET(E) E,
-    FLATBUFFERS_GEN_ELEMENTARY_TYPES(FLATBUFFERS_ET)
-  #undef FLATBUFFERS_ET
-};
-
-inline const char * const *ElementaryTypeNames() {
-  static const char * const names[] = {
-    #define FLATBUFFERS_ET(E) #E,
-      FLATBUFFERS_GEN_ELEMENTARY_TYPES(FLATBUFFERS_ET)
-    #undef FLATBUFFERS_ET
-  };
-  return names;
-}
-// clang-format on
-
-// Basic type info cost just 16bits per field!
-struct TypeCode {
-  uint16_t base_type : 4;  // ElementaryType
-  uint16_t is_vector : 1;
-  int16_t sequence_ref : 11;  // Index into type_refs below, or -1 for none.
-};
-
-static_assert(sizeof(TypeCode) == 2, "TypeCode");
-
-struct TypeTable;
-
-// Signature of the static method present in each type.
-typedef const TypeTable *(*TypeFunction)();
-
-struct TypeTable {
-  SequenceType st;
-  size_t num_elems;  // of type_codes, values, names (but not type_refs).
-  const TypeCode *type_codes;     // num_elems count
-  const TypeFunction *type_refs;  // less than num_elems entries (see TypeCode).
-  const int64_t *values;  // Only set for non-consecutive enum/union or structs.
-  const char *const *names;  // Only set if compiled with --reflect-names.
-};
 
 // String which identifies the current version of FlatBuffers.
 // flatbuffer_version_string is used by Google developers to identify which
@@ -2820,7 +1898,6 @@
 // appreciate if you left it in.
 
 // Weak linkage is culled by VS & doesn't work on cygwin.
-// clang-format off
 #if !defined(_WIN32) && !defined(__CYGWIN__)
 
 extern volatile __attribute__((weak)) const char *flatbuffer_version_string;
@@ -2832,7 +1909,7 @@
 
 #endif  // !defined(_WIN32) && !defined(__CYGWIN__)
 
-#define FLATBUFFERS_DEFINE_BITMASK_OPERATORS(E, T)\
+#define DEFINE_BITMASK_OPERATORS(E, T)\
     inline E operator | (E lhs, E rhs){\
         return E(T(lhs) | T(rhs));\
     }\
@@ -2864,6 +1941,10 @@
 /// @endcond
 }  // namespace flatbuffers
 
-// clang-format on
+#ifdef FLATBUFFERS_CHRE
+  #ifndef CHRE_ASSERT_USES_STDLIB_ASSERT
+    #pragma pop_macro("assert")
+  #endif  // define CHRE_ASSERT_USES_STDLIB_ASSERT
+#endif
 
 #endif  // FLATBUFFERS_H_
diff --git a/external/flatbuffers/include/flatbuffers/base.h b/external/flatbuffers/include/flatbuffers_v1.12/base.h
similarity index 100%
rename from external/flatbuffers/include/flatbuffers/base.h
rename to external/flatbuffers/include/flatbuffers_v1.12/base.h
diff --git a/external/flatbuffers/include/flatbuffers_v1.12/flatbuffers.h b/external/flatbuffers/include/flatbuffers_v1.12/flatbuffers.h
new file mode 100644
index 0000000..5ca119e
--- /dev/null
+++ b/external/flatbuffers/include/flatbuffers_v1.12/flatbuffers.h
@@ -0,0 +1,2869 @@
+/*
+ * Copyright 2014 Google Inc. All rights reserved.
+ *
+ * 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 FLATBUFFERS_H_
+#define FLATBUFFERS_H_
+
+/**
+ * @file
+ * A customized version of the FlatBuffers implementation header file targeted
+ * for use within CHRE. This file differs from the mainline FlatBuffers release
+ * via the introduction of the feature flag FLATBUFFERS_CHRE. When defined,
+ * standard library features not used in CHRE are removed or remapped to their
+ * CHRE-specific alternatives. This includes removing support for strings,
+ * replacing std::vector with chre::DynamicVector, use of CHRE_ASSERT, removal
+ * of uses of std::function, etc.
+ */
+
+#ifdef FLATBUFFERS_CHRE
+#include "chre/util/container_support.h"
+#include "chre/util/dynamic_vector.h"
+
+// Before the flatbuffers/base.h include where it's used
+#define FLATBUFFERS_ASSERT CHRE_ASSERT
+#endif
+
+#include "flatbuffers/base.h"
+
+#if defined(FLATBUFFERS_NAN_DEFAULTS)
+#  include <cmath>
+#endif
+
+namespace flatbuffers {
+// Generic 'operator==' with conditional specialisations.
+// T e - new value of a scalar field.
+// T def - default of scalar (is known at compile-time).
+template<typename T> inline bool IsTheSameAs(T e, T def) { return e == def; }
+
+#if defined(FLATBUFFERS_NAN_DEFAULTS) && \
+    defined(FLATBUFFERS_HAS_NEW_STRTOD) && (FLATBUFFERS_HAS_NEW_STRTOD > 0)
+// Like `operator==(e, def)` with weak NaN if T=(float|double).
+template<typename T> inline bool IsFloatTheSameAs(T e, T def) {
+  return (e == def) || ((def != def) && (e != e));
+}
+template<> inline bool IsTheSameAs<float>(float e, float def) {
+  return IsFloatTheSameAs(e, def);
+}
+template<> inline bool IsTheSameAs<double>(double e, double def) {
+  return IsFloatTheSameAs(e, def);
+}
+#endif
+
+// Check 'v' is out of closed range [low; high].
+// Workaround for GCC warning [-Werror=type-limits]:
+// comparison is always true due to limited range of data type.
+template<typename T>
+inline bool IsOutRange(const T &v, const T &low, const T &high) {
+  return (v < low) || (high < v);
+}
+
+// Check 'v' is in closed range [low; high].
+template<typename T>
+inline bool IsInRange(const T &v, const T &low, const T &high) {
+  return !IsOutRange(v, low, high);
+}
+
+// Wrapper for uoffset_t to allow safe template specialization.
+// Value is allowed to be 0 to indicate a null object (see e.g. AddOffset).
+template<typename T> struct Offset {
+  uoffset_t o;
+  Offset() : o(0) {}
+  Offset(uoffset_t _o) : o(_o) {} // NOLINT(google-explicit-constructor)
+  Offset<void> Union() const { return Offset<void>(o); }
+  bool IsNull() const { return !o; }
+};
+
+inline void EndianCheck() {
+  int endiantest = 1;
+  // If this fails, see FLATBUFFERS_LITTLEENDIAN above.
+  FLATBUFFERS_ASSERT(*reinterpret_cast<char *>(&endiantest) ==
+                     FLATBUFFERS_LITTLEENDIAN);
+  (void)endiantest;
+}
+
+template<typename T> FLATBUFFERS_CONSTEXPR size_t AlignOf() {
+  // clang-format off
+  #ifdef _MSC_VER
+    return __alignof(T);
+  #else
+    #ifndef alignof
+      return __alignof__(T);
+    #else
+      return alignof(T);
+    #endif
+  #endif
+  // clang-format on
+}
+
+// When we read serialized data from memory, in the case of most scalars,
+// we want to just read T, but in the case of Offset, we want to actually
+// perform the indirection and return a pointer.
+// The template specialization below does just that.
+// It is wrapped in a struct since function templates can't overload on the
+// return type like this.
+// The typedef is for the convenience of callers of this function
+// (avoiding the need for a trailing return decltype)
+template<typename T> struct IndirectHelper {
+  typedef T return_type;
+  typedef T mutable_return_type;
+  static const size_t element_stride = sizeof(T);
+  static return_type Read(const uint8_t *p, uoffset_t i) {
+    return EndianScalar((reinterpret_cast<const T *>(p))[i]);
+  }
+};
+template<typename T> struct IndirectHelper<Offset<T>> {
+  typedef const T *return_type;
+  typedef T *mutable_return_type;
+  static const size_t element_stride = sizeof(uoffset_t);
+  static return_type Read(const uint8_t *p, uoffset_t i) {
+    p += i * sizeof(uoffset_t);
+    return reinterpret_cast<return_type>(p + ReadScalar<uoffset_t>(p));
+  }
+};
+template<typename T> struct IndirectHelper<const T *> {
+  typedef const T *return_type;
+  typedef T *mutable_return_type;
+  static const size_t element_stride = sizeof(T);
+  static return_type Read(const uint8_t *p, uoffset_t i) {
+    return reinterpret_cast<const T *>(p + i * sizeof(T));
+  }
+};
+
+// An STL compatible iterator implementation for Vector below, effectively
+// calling Get() for every element.
+template<typename T, typename IT> struct VectorIterator {
+  typedef std::random_access_iterator_tag iterator_category;
+  typedef IT value_type;
+  typedef ptrdiff_t difference_type;
+  typedef IT *pointer;
+  typedef IT &reference;
+
+  VectorIterator(const uint8_t *data, uoffset_t i)
+      : data_(data + IndirectHelper<T>::element_stride * i) {}
+  VectorIterator(const VectorIterator &other) : data_(other.data_) {}
+  VectorIterator() : data_(nullptr) {}
+
+  VectorIterator &operator=(const VectorIterator &other) {
+    data_ = other.data_;
+    return *this;
+  }
+
+  // clang-format off
+  #if !defined(FLATBUFFERS_CPP98_STL)
+  VectorIterator &operator=(VectorIterator &&other) {
+    data_ = other.data_;
+    return *this;
+  }
+  #endif  // !defined(FLATBUFFERS_CPP98_STL)
+  // clang-format on
+
+  bool operator==(const VectorIterator &other) const {
+    return data_ == other.data_;
+  }
+
+  bool operator<(const VectorIterator &other) const {
+    return data_ < other.data_;
+  }
+
+  bool operator!=(const VectorIterator &other) const {
+    return data_ != other.data_;
+  }
+
+  difference_type operator-(const VectorIterator &other) const {
+    return (data_ - other.data_) / IndirectHelper<T>::element_stride;
+  }
+
+  IT operator*() const { return IndirectHelper<T>::Read(data_, 0); }
+
+  IT operator->() const { return IndirectHelper<T>::Read(data_, 0); }
+
+  VectorIterator &operator++() {
+    data_ += IndirectHelper<T>::element_stride;
+    return *this;
+  }
+
+  VectorIterator operator++(int) {
+    VectorIterator temp(data_, 0);
+    data_ += IndirectHelper<T>::element_stride;
+    return temp;
+  }
+
+  VectorIterator operator+(const uoffset_t &offset) const {
+    return VectorIterator(data_ + offset * IndirectHelper<T>::element_stride,
+                          0);
+  }
+
+  VectorIterator &operator+=(const uoffset_t &offset) {
+    data_ += offset * IndirectHelper<T>::element_stride;
+    return *this;
+  }
+
+  VectorIterator &operator--() {
+    data_ -= IndirectHelper<T>::element_stride;
+    return *this;
+  }
+
+  VectorIterator operator--(int) {
+    VectorIterator temp(data_, 0);
+    data_ -= IndirectHelper<T>::element_stride;
+    return temp;
+  }
+
+  VectorIterator operator-(const uoffset_t &offset) const {
+    return VectorIterator(data_ - offset * IndirectHelper<T>::element_stride,
+                          0);
+  }
+
+  VectorIterator &operator-=(const uoffset_t &offset) {
+    data_ -= offset * IndirectHelper<T>::element_stride;
+    return *this;
+  }
+
+ private:
+  const uint8_t *data_;
+};
+
+template<typename Iterator>
+struct VectorReverseIterator : public std::reverse_iterator<Iterator> {
+  explicit VectorReverseIterator(Iterator iter)
+      : std::reverse_iterator<Iterator>(iter) {}
+
+  typename Iterator::value_type operator*() const {
+    return *(std::reverse_iterator<Iterator>::current);
+  }
+
+  typename Iterator::value_type operator->() const {
+    return *(std::reverse_iterator<Iterator>::current);
+  }
+};
+
+#ifndef FLATBUFFERS_CHRE
+struct String;
+#endif
+
+// This is used as a helper type for accessing vectors.
+// Vector::data() assumes the vector elements start after the length field.
+template<typename T> class Vector {
+ public:
+  typedef VectorIterator<T, typename IndirectHelper<T>::mutable_return_type>
+      iterator;
+  typedef VectorIterator<T, typename IndirectHelper<T>::return_type>
+      const_iterator;
+  typedef VectorReverseIterator<iterator> reverse_iterator;
+  typedef VectorReverseIterator<const_iterator> const_reverse_iterator;
+
+  uoffset_t size() const { return EndianScalar(length_); }
+
+  // Deprecated: use size(). Here for backwards compatibility.
+  FLATBUFFERS_ATTRIBUTE(deprecated("use size() instead"))
+  uoffset_t Length() const { return size(); }
+
+  typedef typename IndirectHelper<T>::return_type return_type;
+  typedef typename IndirectHelper<T>::mutable_return_type mutable_return_type;
+
+  return_type Get(uoffset_t i) const {
+    FLATBUFFERS_ASSERT(i < size());
+    return IndirectHelper<T>::Read(Data(), i);
+  }
+
+  return_type operator[](uoffset_t i) const { return Get(i); }
+
+  // If this is a Vector of enums, T will be its storage type, not the enum
+  // type. This function makes it convenient to retrieve value with enum
+  // type E.
+  template<typename E> E GetEnum(uoffset_t i) const {
+    return static_cast<E>(Get(i));
+  }
+
+  // If this a vector of unions, this does the cast for you. There's no check
+  // to make sure this is the right type!
+  template<typename U> const U *GetAs(uoffset_t i) const {
+    return reinterpret_cast<const U *>(Get(i));
+  }
+
+  #ifndef FLATBUFFERS_CHRE
+  // If this a vector of unions, this does the cast for you. There's no check
+  // to make sure this is actually a string!
+  const String *GetAsString(uoffset_t i) const {
+    return reinterpret_cast<const String *>(Get(i));
+  }
+  #endif
+
+  const void *GetStructFromOffset(size_t o) const {
+    return reinterpret_cast<const void *>(Data() + o);
+  }
+
+  iterator begin() { return iterator(Data(), 0); }
+  const_iterator begin() const { return const_iterator(Data(), 0); }
+
+  iterator end() { return iterator(Data(), size()); }
+  const_iterator end() const { return const_iterator(Data(), size()); }
+
+  reverse_iterator rbegin() { return reverse_iterator(end() - 1); }
+  const_reverse_iterator rbegin() const {
+    return const_reverse_iterator(end() - 1);
+  }
+
+  reverse_iterator rend() { return reverse_iterator(begin() - 1); }
+  const_reverse_iterator rend() const {
+    return const_reverse_iterator(begin() - 1);
+  }
+
+  const_iterator cbegin() const { return begin(); }
+
+  const_iterator cend() const { return end(); }
+
+  const_reverse_iterator crbegin() const { return rbegin(); }
+
+  const_reverse_iterator crend() const { return rend(); }
+
+  // Change elements if you have a non-const pointer to this object.
+  // Scalars only. See reflection.h, and the documentation.
+  void Mutate(uoffset_t i, const T &val) {
+    FLATBUFFERS_ASSERT(i < size());
+    WriteScalar(data() + i, val);
+  }
+
+  // Change an element of a vector of tables (or strings).
+  // "val" points to the new table/string, as you can obtain from
+  // e.g. reflection::AddFlatBuffer().
+  void MutateOffset(uoffset_t i, const uint8_t *val) {
+    FLATBUFFERS_ASSERT(i < size());
+    static_assert(sizeof(T) == sizeof(uoffset_t), "Unrelated types");
+    WriteScalar(data() + i,
+                static_cast<uoffset_t>(val - (Data() + i * sizeof(uoffset_t))));
+  }
+
+  // Get a mutable pointer to tables/strings inside this vector.
+  mutable_return_type GetMutableObject(uoffset_t i) const {
+    FLATBUFFERS_ASSERT(i < size());
+    return const_cast<mutable_return_type>(IndirectHelper<T>::Read(Data(), i));
+  }
+
+  // The raw data in little endian format. Use with care.
+  const uint8_t *Data() const {
+    return reinterpret_cast<const uint8_t *>(&length_ + 1);
+  }
+
+  uint8_t *Data() { return reinterpret_cast<uint8_t *>(&length_ + 1); }
+
+  // Similarly, but typed, much like std::vector::data
+  const T *data() const { return reinterpret_cast<const T *>(Data()); }
+  T *data() { return reinterpret_cast<T *>(Data()); }
+
+  template<typename K> return_type LookupByKey(K key) const {
+    void *search_result = std::bsearch(
+        &key, Data(), size(), IndirectHelper<T>::element_stride, KeyCompare<K>);
+
+    if (!search_result) {
+      return nullptr;  // Key not found.
+    }
+
+    const uint8_t *element = reinterpret_cast<const uint8_t *>(search_result);
+
+    return IndirectHelper<T>::Read(element, 0);
+  }
+
+ protected:
+  // This class is only used to access pre-existing data. Don't ever
+  // try to construct these manually.
+  Vector();
+
+  uoffset_t length_;
+
+ private:
+  // This class is a pointer. Copying will therefore create an invalid object.
+  // Private and unimplemented copy constructor.
+  Vector(const Vector &);
+  Vector &operator=(const Vector &);
+
+  template<typename K> static int KeyCompare(const void *ap, const void *bp) {
+    const K *key = reinterpret_cast<const K *>(ap);
+    const uint8_t *data = reinterpret_cast<const uint8_t *>(bp);
+    auto table = IndirectHelper<T>::Read(data, 0);
+
+    // std::bsearch compares with the operands transposed, so we negate the
+    // result here.
+    return -table->KeyCompareWithValue(*key);
+  }
+};
+
+// Represent a vector much like the template above, but in this case we
+// don't know what the element types are (used with reflection.h).
+class VectorOfAny {
+ public:
+  uoffset_t size() const { return EndianScalar(length_); }
+
+  const uint8_t *Data() const {
+    return reinterpret_cast<const uint8_t *>(&length_ + 1);
+  }
+  uint8_t *Data() { return reinterpret_cast<uint8_t *>(&length_ + 1); }
+
+ protected:
+  VectorOfAny();
+
+  uoffset_t length_;
+
+ private:
+  VectorOfAny(const VectorOfAny &);
+  VectorOfAny &operator=(const VectorOfAny &);
+};
+
+#ifndef FLATBUFFERS_CPP98_STL
+template<typename T, typename U>
+Vector<Offset<T>> *VectorCast(Vector<Offset<U>> *ptr) {
+  static_assert(std::is_base_of<T, U>::value, "Unrelated types");
+  return reinterpret_cast<Vector<Offset<T>> *>(ptr);
+}
+
+template<typename T, typename U>
+const Vector<Offset<T>> *VectorCast(const Vector<Offset<U>> *ptr) {
+  static_assert(std::is_base_of<T, U>::value, "Unrelated types");
+  return reinterpret_cast<const Vector<Offset<T>> *>(ptr);
+}
+#endif
+
+// Convenient helper function to get the length of any vector, regardless
+// of whether it is null or not (the field is not set).
+template<typename T> static inline size_t VectorLength(const Vector<T> *v) {
+  return v ? v->size() : 0;
+}
+
+// This is used as a helper type for accessing arrays.
+template<typename T, uint16_t length> class Array {
+  typedef
+      typename flatbuffers::integral_constant<bool,
+                                              flatbuffers::is_scalar<T>::value>
+          scalar_tag;
+  typedef
+      typename flatbuffers::conditional<scalar_tag::value, T, const T *>::type
+          IndirectHelperType;
+
+ public:
+  typedef typename IndirectHelper<IndirectHelperType>::return_type return_type;
+  typedef VectorIterator<T, return_type> const_iterator;
+  typedef VectorReverseIterator<const_iterator> const_reverse_iterator;
+
+  FLATBUFFERS_CONSTEXPR uint16_t size() const { return length; }
+
+  return_type Get(uoffset_t i) const {
+    FLATBUFFERS_ASSERT(i < size());
+    return IndirectHelper<IndirectHelperType>::Read(Data(), i);
+  }
+
+  return_type operator[](uoffset_t i) const { return Get(i); }
+
+  // If this is a Vector of enums, T will be its storage type, not the enum
+  // type. This function makes it convenient to retrieve value with enum
+  // type E.
+  template<typename E> E GetEnum(uoffset_t i) const {
+    return static_cast<E>(Get(i));
+  }
+
+  const_iterator begin() const { return const_iterator(Data(), 0); }
+  const_iterator end() const { return const_iterator(Data(), size()); }
+
+  const_reverse_iterator rbegin() const {
+    return const_reverse_iterator(end());
+  }
+  const_reverse_iterator rend() const { return const_reverse_iterator(end()); }
+
+  const_iterator cbegin() const { return begin(); }
+  const_iterator cend() const { return end(); }
+
+  const_reverse_iterator crbegin() const { return rbegin(); }
+  const_reverse_iterator crend() const { return rend(); }
+
+  // Get a mutable pointer to elements inside this array.
+  // This method used to mutate arrays of structs followed by a @p Mutate
+  // operation. For primitive types use @p Mutate directly.
+  // @warning Assignments and reads to/from the dereferenced pointer are not
+  //  automatically converted to the correct endianness.
+  typename flatbuffers::conditional<scalar_tag::value, void, T *>::type
+  GetMutablePointer(uoffset_t i) const {
+    FLATBUFFERS_ASSERT(i < size());
+    return const_cast<T *>(&data()[i]);
+  }
+
+  // Change elements if you have a non-const pointer to this object.
+  void Mutate(uoffset_t i, const T &val) { MutateImpl(scalar_tag(), i, val); }
+
+  // The raw data in little endian format. Use with care.
+  const uint8_t *Data() const { return data_; }
+
+  uint8_t *Data() { return data_; }
+
+  // Similarly, but typed, much like std::vector::data
+  const T *data() const { return reinterpret_cast<const T *>(Data()); }
+  T *data() { return reinterpret_cast<T *>(Data()); }
+
+ protected:
+  void MutateImpl(flatbuffers::integral_constant<bool, true>, uoffset_t i,
+                  const T &val) {
+    FLATBUFFERS_ASSERT(i < size());
+    WriteScalar(data() + i, val);
+  }
+
+  void MutateImpl(flatbuffers::integral_constant<bool, false>, uoffset_t i,
+                  const T &val) {
+    *(GetMutablePointer(i)) = val;
+  }
+
+  // This class is only used to access pre-existing data. Don't ever
+  // try to construct these manually.
+  // 'constexpr' allows us to use 'size()' at compile time.
+  // @note Must not use 'FLATBUFFERS_CONSTEXPR' here, as const is not allowed on
+  //  a constructor.
+#if defined(__cpp_constexpr)
+  constexpr Array();
+#else
+  Array();
+#endif
+
+  uint8_t data_[length * sizeof(T)];
+
+ private:
+  // This class is a pointer. Copying will therefore create an invalid object.
+  // Private and unimplemented copy constructor.
+  Array(const Array &);
+  Array &operator=(const Array &);
+};
+
+// Specialization for Array[struct] with access using Offset<void> pointer.
+// This specialization used by idl_gen_text.cpp.
+template<typename T, uint16_t length> class Array<Offset<T>, length> {
+  static_assert(flatbuffers::is_same<T, void>::value, "unexpected type T");
+
+ public:
+  typedef const void *return_type;
+
+  const uint8_t *Data() const { return data_; }
+
+  // Make idl_gen_text.cpp::PrintContainer happy.
+  return_type operator[](uoffset_t) const {
+    FLATBUFFERS_ASSERT(false);
+    return nullptr;
+  }
+
+ private:
+  // This class is only used to access pre-existing data.
+  Array();
+  Array(const Array &);
+  Array &operator=(const Array &);
+
+  uint8_t data_[1];
+};
+
+#ifndef FLATBUFFERS_CHRE
+// Lexicographically compare two strings (possibly containing nulls), and
+// return true if the first is less than the second.
+static inline bool StringLessThan(const char *a_data, uoffset_t a_size,
+                                  const char *b_data, uoffset_t b_size) {
+  const auto cmp = memcmp(a_data, b_data, (std::min)(a_size, b_size));
+  return cmp == 0 ? a_size < b_size : cmp < 0;
+}
+
+struct String : public Vector<char> {
+  const char *c_str() const { return reinterpret_cast<const char *>(Data()); }
+  std::string str() const { return std::string(c_str(), size()); }
+
+  // clang-format off
+  #ifdef FLATBUFFERS_HAS_STRING_VIEW
+  flatbuffers::string_view string_view() const {
+    return flatbuffers::string_view(c_str(), size());
+  }
+  #endif // FLATBUFFERS_HAS_STRING_VIEW
+  // clang-format on
+
+  bool operator<(const String &o) const {
+    return StringLessThan(this->data(), this->size(), o.data(), o.size());
+  }
+};
+
+// Convenience function to get std::string from a String returning an empty
+// string on null pointer.
+static inline std::string GetString(const String *str) {
+  return str ? str->str() : "";
+}
+
+// Convenience function to get char* from a String returning an empty string on
+// null pointer.
+static inline const char *GetCstring(const String *str) {
+  return str ? str->c_str() : "";
+}
+#endif  // !FLATBUFFERS_CHRE
+
+// Allocator interface. This is flatbuffers-specific and meant only for
+// `vector_downward` usage.
+class Allocator {
+ public:
+  virtual ~Allocator() {}
+
+  // Allocate `size` bytes of memory.
+  virtual uint8_t *allocate(size_t size) = 0;
+
+  // Deallocate `size` bytes of memory at `p` allocated by this allocator.
+  virtual void deallocate(uint8_t *p, size_t size) = 0;
+
+  // Reallocate `new_size` bytes of memory, replacing the old region of size
+  // `old_size` at `p`. In contrast to a normal realloc, this grows downwards,
+  // and is intended specifcally for `vector_downward` use.
+  // `in_use_back` and `in_use_front` indicate how much of `old_size` is
+  // actually in use at each end, and needs to be copied.
+  virtual uint8_t *reallocate_downward(uint8_t *old_p, size_t old_size,
+                                       size_t new_size, size_t in_use_back,
+                                       size_t in_use_front) {
+    FLATBUFFERS_ASSERT(new_size > old_size);  // vector_downward only grows
+    uint8_t *new_p = allocate(new_size);
+    memcpy_downward(old_p, old_size, new_p, new_size, in_use_back,
+                    in_use_front);
+    deallocate(old_p, old_size);
+    return new_p;
+  }
+
+ protected:
+  // Called by `reallocate_downward` to copy memory from `old_p` of `old_size`
+  // to `new_p` of `new_size`. Only memory of size `in_use_front` and
+  // `in_use_back` will be copied from the front and back of the old memory
+  // allocation.
+  void memcpy_downward(uint8_t *old_p, size_t old_size, uint8_t *new_p,
+                       size_t new_size, size_t in_use_back,
+                       size_t in_use_front) {
+    memcpy(new_p + new_size - in_use_back, old_p + old_size - in_use_back,
+           in_use_back);
+    memcpy(new_p, old_p, in_use_front);
+  }
+};
+
+// DefaultAllocator uses new/delete to allocate memory regions
+class DefaultAllocator : public Allocator {
+ public:
+  uint8_t *allocate(size_t size) FLATBUFFERS_OVERRIDE {
+    #ifndef FLATBUFFERS_CHRE
+      return new uint8_t[size];
+    #else
+      return static_cast<uint8_t *>(chre::memoryAlloc(size));
+    #endif
+  }
+
+  void deallocate(uint8_t *p, size_t) FLATBUFFERS_OVERRIDE {
+    #ifndef FLATBUFFERS_CHRE
+      delete[] p;
+    #else
+      return chre::memoryFree(p);
+    #endif
+  }
+
+  static void dealloc(void *p, size_t) { delete[] static_cast<uint8_t *>(p); }
+};
+
+// These functions allow for a null allocator to mean use the default allocator,
+// as used by DetachedBuffer and vector_downward below.
+// This is to avoid having a statically or dynamically allocated default
+// allocator, or having to move it between the classes that may own it.
+inline uint8_t *Allocate(Allocator *allocator, size_t size) {
+  return allocator ? allocator->allocate(size)
+                   : DefaultAllocator().allocate(size);
+}
+
+inline void Deallocate(Allocator *allocator, uint8_t *p, size_t size) {
+  if (allocator)
+    allocator->deallocate(p, size);
+  else
+    DefaultAllocator().deallocate(p, size);
+}
+
+inline uint8_t *ReallocateDownward(Allocator *allocator, uint8_t *old_p,
+                                   size_t old_size, size_t new_size,
+                                   size_t in_use_back, size_t in_use_front) {
+  return allocator ? allocator->reallocate_downward(old_p, old_size, new_size,
+                                                    in_use_back, in_use_front)
+                   : DefaultAllocator().reallocate_downward(
+                         old_p, old_size, new_size, in_use_back, in_use_front);
+}
+
+// DetachedBuffer is a finished flatbuffer memory region, detached from its
+// builder. The original memory region and allocator are also stored so that
+// the DetachedBuffer can manage the memory lifetime.
+class DetachedBuffer {
+ public:
+  DetachedBuffer()
+      : allocator_(nullptr),
+        own_allocator_(false),
+        buf_(nullptr),
+        reserved_(0),
+        cur_(nullptr),
+        size_(0) {}
+
+  DetachedBuffer(Allocator *allocator, bool own_allocator, uint8_t *buf,
+                 size_t reserved, uint8_t *cur, size_t sz)
+      : allocator_(allocator),
+        own_allocator_(own_allocator),
+        buf_(buf),
+        reserved_(reserved),
+        cur_(cur),
+        size_(sz) {}
+
+  // clang-format off
+  #if !defined(FLATBUFFERS_CPP98_STL)
+  // clang-format on
+  DetachedBuffer(DetachedBuffer &&other)
+      : allocator_(other.allocator_),
+        own_allocator_(other.own_allocator_),
+        buf_(other.buf_),
+        reserved_(other.reserved_),
+        cur_(other.cur_),
+        size_(other.size_) {
+    other.reset();
+  }
+  // clang-format off
+  #endif  // !defined(FLATBUFFERS_CPP98_STL)
+  // clang-format on
+
+  // clang-format off
+  #if !defined(FLATBUFFERS_CPP98_STL)
+  // clang-format on
+  DetachedBuffer &operator=(DetachedBuffer &&other) {
+    if (this == &other) return *this;
+
+    destroy();
+
+    allocator_ = other.allocator_;
+    own_allocator_ = other.own_allocator_;
+    buf_ = other.buf_;
+    reserved_ = other.reserved_;
+    cur_ = other.cur_;
+    size_ = other.size_;
+
+    other.reset();
+
+    return *this;
+  }
+  // clang-format off
+  #endif  // !defined(FLATBUFFERS_CPP98_STL)
+  // clang-format on
+
+  ~DetachedBuffer() { destroy(); }
+
+  const uint8_t *data() const { return cur_; }
+
+  uint8_t *data() { return cur_; }
+
+  size_t size() const { return size_; }
+
+  // clang-format off
+  #if 0  // disabled for now due to the ordering of classes in this header
+  template <class T>
+  bool Verify() const {
+    Verifier verifier(data(), size());
+    return verifier.Verify<T>(nullptr);
+  }
+
+  template <class T>
+  const T* GetRoot() const {
+    return flatbuffers::GetRoot<T>(data());
+  }
+
+  template <class T>
+  T* GetRoot() {
+    return flatbuffers::GetRoot<T>(data());
+  }
+  #endif
+  // clang-format on
+
+  // clang-format off
+  #if !defined(FLATBUFFERS_CPP98_STL)
+  // clang-format on
+  // These may change access mode, leave these at end of public section
+  FLATBUFFERS_DELETE_FUNC(DetachedBuffer(const DetachedBuffer &other))
+  FLATBUFFERS_DELETE_FUNC(
+      DetachedBuffer &operator=(const DetachedBuffer &other))
+  // clang-format off
+  #endif  // !defined(FLATBUFFERS_CPP98_STL)
+  // clang-format on
+
+ protected:
+  Allocator *allocator_;
+  bool own_allocator_;
+  uint8_t *buf_;
+  size_t reserved_;
+  uint8_t *cur_;
+  size_t size_;
+
+  inline void destroy() {
+    if (buf_) Deallocate(allocator_, buf_, reserved_);
+    if (own_allocator_ && allocator_) { delete allocator_; }
+    reset();
+  }
+
+  inline void reset() {
+    allocator_ = nullptr;
+    own_allocator_ = false;
+    buf_ = nullptr;
+    reserved_ = 0;
+    cur_ = nullptr;
+    size_ = 0;
+  }
+};
+
+// This is a minimal replication of std::vector<uint8_t> functionality,
+// except growing from higher to lower addresses. i.e push_back() inserts data
+// in the lowest address in the vector.
+// Since this vector leaves the lower part unused, we support a "scratch-pad"
+// that can be stored there for temporary data, to share the allocated space.
+// Essentially, this supports 2 std::vectors in a single buffer.
+class vector_downward {
+ public:
+  explicit vector_downward(size_t initial_size, Allocator *allocator,
+                           bool own_allocator, size_t buffer_minalign)
+      : allocator_(allocator),
+        own_allocator_(own_allocator),
+        initial_size_(initial_size),
+        buffer_minalign_(buffer_minalign),
+        reserved_(0),
+        buf_(nullptr),
+        cur_(nullptr),
+        scratch_(nullptr) {}
+
+  // clang-format off
+  #if !defined(FLATBUFFERS_CPP98_STL)
+  vector_downward(vector_downward &&other)
+  #else
+  vector_downward(vector_downward &other)
+  #endif  // defined(FLATBUFFERS_CPP98_STL)
+      // clang-format on
+      : allocator_(other.allocator_),
+        own_allocator_(other.own_allocator_),
+        initial_size_(other.initial_size_),
+        buffer_minalign_(other.buffer_minalign_),
+        reserved_(other.reserved_),
+        buf_(other.buf_),
+        cur_(other.cur_),
+        scratch_(other.scratch_) {
+    // No change in other.allocator_
+    // No change in other.initial_size_
+    // No change in other.buffer_minalign_
+    other.own_allocator_ = false;
+    other.reserved_ = 0;
+    other.buf_ = nullptr;
+    other.cur_ = nullptr;
+    other.scratch_ = nullptr;
+  }
+
+  // clang-format off
+  #if !defined(FLATBUFFERS_CPP98_STL)
+  // clang-format on
+  vector_downward &operator=(vector_downward &&other) {
+    // Move construct a temporary and swap idiom
+    vector_downward temp(std::move(other));
+    swap(temp);
+    return *this;
+  }
+  // clang-format off
+  #endif  // defined(FLATBUFFERS_CPP98_STL)
+  // clang-format on
+
+  ~vector_downward() {
+    clear_buffer();
+    clear_allocator();
+  }
+
+  void reset() {
+    clear_buffer();
+    clear();
+  }
+
+  void clear() {
+    if (buf_) {
+      cur_ = buf_ + reserved_;
+    } else {
+      reserved_ = 0;
+      cur_ = nullptr;
+    }
+    clear_scratch();
+  }
+
+  void clear_scratch() { scratch_ = buf_; }
+
+  void clear_allocator() {
+    if (own_allocator_ && allocator_) { delete allocator_; }
+    allocator_ = nullptr;
+    own_allocator_ = false;
+  }
+
+  void clear_buffer() {
+    if (buf_) Deallocate(allocator_, buf_, reserved_);
+    buf_ = nullptr;
+  }
+
+  // Relinquish the pointer to the caller.
+  uint8_t *release_raw(size_t &allocated_bytes, size_t &offset) {
+    auto *buf = buf_;
+    allocated_bytes = reserved_;
+    offset = static_cast<size_t>(cur_ - buf_);
+
+    // release_raw only relinquishes the buffer ownership.
+    // Does not deallocate or reset the allocator. Destructor will do that.
+    buf_ = nullptr;
+    clear();
+    return buf;
+  }
+
+  // Relinquish the pointer to the caller.
+  DetachedBuffer release() {
+    // allocator ownership (if any) is transferred to DetachedBuffer.
+    DetachedBuffer fb(allocator_, own_allocator_, buf_, reserved_, cur_,
+                      size());
+    if (own_allocator_) {
+      allocator_ = nullptr;
+      own_allocator_ = false;
+    }
+    buf_ = nullptr;
+    clear();
+    return fb;
+  }
+
+  size_t ensure_space(size_t len) {
+    FLATBUFFERS_ASSERT(cur_ >= scratch_ && scratch_ >= buf_);
+    if (len > static_cast<size_t>(cur_ - scratch_)) { reallocate(len); }
+    // Beyond this, signed offsets may not have enough range:
+    // (FlatBuffers > 2GB not supported).
+    FLATBUFFERS_ASSERT(size() < FLATBUFFERS_MAX_BUFFER_SIZE);
+    return len;
+  }
+
+  inline uint8_t *make_space(size_t len) {
+    size_t space = ensure_space(len);
+    cur_ -= space;
+    return cur_;
+  }
+
+  // Returns nullptr if using the DefaultAllocator.
+  Allocator *get_custom_allocator() { return allocator_; }
+
+  uoffset_t size() const {
+    return static_cast<uoffset_t>(reserved_ - static_cast<size_t>(cur_ - buf_));
+  }
+
+  uoffset_t scratch_size() const {
+    return static_cast<uoffset_t>(scratch_ - buf_);
+  }
+
+  size_t capacity() const { return reserved_; }
+
+  uint8_t *data() const {
+    FLATBUFFERS_ASSERT(cur_);
+    return cur_;
+  }
+
+  uint8_t *scratch_data() const {
+    FLATBUFFERS_ASSERT(buf_);
+    return buf_;
+  }
+
+  uint8_t *scratch_end() const {
+    FLATBUFFERS_ASSERT(scratch_);
+    return scratch_;
+  }
+
+  uint8_t *data_at(size_t offset) const { return buf_ + reserved_ - offset; }
+
+  void push(const uint8_t *bytes, size_t num) {
+    if (num > 0) { memcpy(make_space(num), bytes, num); }
+  }
+
+  // Specialized version of push() that avoids memcpy call for small data.
+  template<typename T> void push_small(const T &little_endian_t) {
+    make_space(sizeof(T));
+    *reinterpret_cast<T *>(cur_) = little_endian_t;
+  }
+
+  template<typename T> void scratch_push_small(const T &t) {
+    ensure_space(sizeof(T));
+    *reinterpret_cast<T *>(scratch_) = t;
+    scratch_ += sizeof(T);
+  }
+
+  // fill() is most frequently called with small byte counts (<= 4),
+  // which is why we're using loops rather than calling memset.
+  void fill(size_t zero_pad_bytes) {
+    make_space(zero_pad_bytes);
+    for (size_t i = 0; i < zero_pad_bytes; i++) cur_[i] = 0;
+  }
+
+  // Version for when we know the size is larger.
+  // Precondition: zero_pad_bytes > 0
+  void fill_big(size_t zero_pad_bytes) {
+    memset(make_space(zero_pad_bytes), 0, zero_pad_bytes);
+  }
+
+  void pop(size_t bytes_to_remove) { cur_ += bytes_to_remove; }
+  void scratch_pop(size_t bytes_to_remove) { scratch_ -= bytes_to_remove; }
+
+  void swap(vector_downward &other) {
+    using std::swap;
+    swap(allocator_, other.allocator_);
+    swap(own_allocator_, other.own_allocator_);
+    swap(initial_size_, other.initial_size_);
+    swap(buffer_minalign_, other.buffer_minalign_);
+    swap(reserved_, other.reserved_);
+    swap(buf_, other.buf_);
+    swap(cur_, other.cur_);
+    swap(scratch_, other.scratch_);
+  }
+
+  void swap_allocator(vector_downward &other) {
+    using std::swap;
+    swap(allocator_, other.allocator_);
+    swap(own_allocator_, other.own_allocator_);
+  }
+
+ private:
+  // You shouldn't really be copying instances of this class.
+  FLATBUFFERS_DELETE_FUNC(vector_downward(const vector_downward &))
+  FLATBUFFERS_DELETE_FUNC(vector_downward &operator=(const vector_downward &))
+
+  Allocator *allocator_;
+  bool own_allocator_;
+  size_t initial_size_;
+  size_t buffer_minalign_;
+  size_t reserved_;
+  uint8_t *buf_;
+  uint8_t *cur_;  // Points at location between empty (below) and used (above).
+  uint8_t *scratch_;  // Points to the end of the scratchpad in use.
+
+  void reallocate(size_t len) {
+    auto old_reserved = reserved_;
+    auto old_size = size();
+    auto old_scratch_size = scratch_size();
+    reserved_ +=
+        (std::max)(len, old_reserved ? old_reserved / 2 : initial_size_);
+    reserved_ = (reserved_ + buffer_minalign_ - 1) & ~(buffer_minalign_ - 1);
+    if (buf_) {
+      buf_ = ReallocateDownward(allocator_, buf_, old_reserved, reserved_,
+                                old_size, old_scratch_size);
+    } else {
+      buf_ = Allocate(allocator_, reserved_);
+    }
+    cur_ = buf_ + reserved_ - old_size;
+    scratch_ = buf_ + old_scratch_size;
+  }
+};
+
+// Converts a Field ID to a virtual table offset.
+inline voffset_t FieldIndexToOffset(voffset_t field_id) {
+  // Should correspond to what EndTable() below builds up.
+  const int fixed_fields = 2;  // Vtable size and Object Size.
+  return static_cast<voffset_t>((field_id + fixed_fields) * sizeof(voffset_t));
+}
+
+#ifndef FLATBUFFERS_CHRE
+template<typename T, typename Alloc>
+const T *data(const std::vector<T, Alloc> &v) {
+  // Eventually the returned pointer gets passed down to memcpy, so
+  // we need it to be non-null to avoid undefined behavior.
+  static uint8_t t;
+  return v.empty() ? reinterpret_cast<const T *>(&t) : &v.front();
+}
+template<typename T, typename Alloc> T *data(std::vector<T, Alloc> &v) {
+  // Eventually the returned pointer gets passed down to memcpy, so
+  // we need it to be non-null to avoid undefined behavior.
+  static uint8_t t;
+  return v.empty() ? reinterpret_cast<T *>(&t) : &v.front();
+}
+#endif
+
+/// @endcond
+
+/// @addtogroup flatbuffers_cpp_api
+/// @{
+/// @class FlatBufferBuilder
+/// @brief Helper class to hold data needed in creation of a FlatBuffer.
+/// To serialize data, you typically call one of the `Create*()` functions in
+/// the generated code, which in turn call a sequence of `StartTable`/
+/// `PushElement`/`AddElement`/`EndTable`, or the builtin `CreateString`/
+/// `CreateVector` functions. Do this is depth-first order to build up a tree to
+/// the root. `Finish()` wraps up the buffer ready for transport.
+class FlatBufferBuilder {
+ public:
+  /// @brief Default constructor for FlatBufferBuilder.
+  /// @param[in] initial_size The initial size of the buffer, in bytes. Defaults
+  /// to `1024`.
+  /// @param[in] allocator An `Allocator` to use. If null will use
+  /// `DefaultAllocator`.
+  /// @param[in] own_allocator Whether the builder/vector should own the
+  /// allocator. Defaults to / `false`.
+  /// @param[in] buffer_minalign Force the buffer to be aligned to the given
+  /// minimum alignment upon reallocation. Only needed if you intend to store
+  /// types with custom alignment AND you wish to read the buffer in-place
+  /// directly after creation.
+  explicit FlatBufferBuilder(
+      size_t initial_size = 1024, Allocator *allocator = nullptr,
+      bool own_allocator = false,
+      size_t buffer_minalign = AlignOf<largest_scalar_t>())
+      : buf_(initial_size, allocator, own_allocator, buffer_minalign),
+        num_field_loc(0),
+        max_voffset_(0),
+        nested(false),
+        finished(false),
+        minalign_(1),
+        force_defaults_(false),
+        dedup_vtables_(true) {
+    #ifndef FLATBUFFERS_CHRE
+    string_pool = nullptr;
+    #endif
+
+    EndianCheck();
+  }
+
+  // clang-format off
+  /// @brief Move constructor for FlatBufferBuilder.
+  #if !defined(FLATBUFFERS_CPP98_STL)
+  FlatBufferBuilder(FlatBufferBuilder &&other)
+  #else
+  FlatBufferBuilder(FlatBufferBuilder &other)
+  #endif  // #if !defined(FLATBUFFERS_CPP98_STL)
+    : buf_(1024, nullptr, false, AlignOf<largest_scalar_t>()),
+      num_field_loc(0),
+      max_voffset_(0),
+      nested(false),
+      finished(false),
+      minalign_(1),
+      force_defaults_(false),
+      dedup_vtables_(true) {
+    #ifndef FLATBUFFERS_CHRE
+    string_pool = nullptr;
+    #endif
+
+    EndianCheck();
+    // Default construct and swap idiom.
+    // Lack of delegating constructors in vs2010 makes it more verbose than needed.
+    Swap(other);
+  }
+  // clang-format on
+
+  // clang-format off
+  #if !defined(FLATBUFFERS_CPP98_STL)
+  // clang-format on
+  /// @brief Move assignment operator for FlatBufferBuilder.
+  FlatBufferBuilder &operator=(FlatBufferBuilder &&other) {
+    // Move construct a temporary and swap idiom
+    FlatBufferBuilder temp(std::move(other));
+    Swap(temp);
+    return *this;
+  }
+  // clang-format off
+  #endif  // defined(FLATBUFFERS_CPP98_STL)
+  // clang-format on
+
+  void Swap(FlatBufferBuilder &other) {
+    using std::swap;
+    buf_.swap(other.buf_);
+    swap(num_field_loc, other.num_field_loc);
+    swap(max_voffset_, other.max_voffset_);
+    swap(nested, other.nested);
+    swap(finished, other.finished);
+    swap(minalign_, other.minalign_);
+    swap(force_defaults_, other.force_defaults_);
+    swap(dedup_vtables_, other.dedup_vtables_);
+    #ifndef FLATBUFFERS_CHRE
+    swap(string_pool, other.string_pool);
+    #endif
+  }
+
+  ~FlatBufferBuilder() {
+    #ifndef FLATBUFFERS_CHRE
+    if (string_pool) delete string_pool;
+    #endif
+  }
+
+  void Reset() {
+    Clear();       // clear builder state
+    buf_.reset();  // deallocate buffer
+  }
+
+  /// @brief Reset all the state in this FlatBufferBuilder so it can be reused
+  /// to construct another buffer.
+  void Clear() {
+    ClearOffsets();
+    buf_.clear();
+    nested = false;
+    finished = false;
+    minalign_ = 1;
+    #ifndef FLATBUFFERS_CHRE
+    if (string_pool) string_pool->clear();
+    #endif
+  }
+
+  /// @brief The current size of the serialized buffer, counting from the end.
+  /// @return Returns an `uoffset_t` with the current size of the buffer.
+  uoffset_t GetSize() const { return buf_.size(); }
+
+  /// @brief Get the serialized buffer (after you call `Finish()`).
+  /// @return Returns an `uint8_t` pointer to the FlatBuffer data inside the
+  /// buffer.
+  uint8_t *GetBufferPointer() const {
+    Finished();
+    return buf_.data();
+  }
+
+  /// @brief Get a pointer to an unfinished buffer.
+  /// @return Returns a `uint8_t` pointer to the unfinished buffer.
+  uint8_t *GetCurrentBufferPointer() const { return buf_.data(); }
+
+  /// @brief Get the released pointer to the serialized buffer.
+  /// @warning Do NOT attempt to use this FlatBufferBuilder afterwards!
+  /// @return A `FlatBuffer` that owns the buffer and its allocator and
+  /// behaves similar to a `unique_ptr` with a deleter.
+  FLATBUFFERS_ATTRIBUTE(deprecated("use Release() instead"))
+  DetachedBuffer ReleaseBufferPointer() {
+    Finished();
+    return buf_.release();
+  }
+
+  /// @brief Get the released DetachedBuffer.
+  /// @return A `DetachedBuffer` that owns the buffer and its allocator.
+  DetachedBuffer Release() {
+    Finished();
+    return buf_.release();
+  }
+
+  /// @brief Get the released pointer to the serialized buffer.
+  /// @param size The size of the memory block containing
+  /// the serialized `FlatBuffer`.
+  /// @param offset The offset from the released pointer where the finished
+  /// `FlatBuffer` starts.
+  /// @return A raw pointer to the start of the memory block containing
+  /// the serialized `FlatBuffer`.
+  /// @remark If the allocator is owned, it gets deleted when the destructor is
+  /// called..
+  uint8_t *ReleaseRaw(size_t &size, size_t &offset) {
+    Finished();
+    return buf_.release_raw(size, offset);
+  }
+
+  /// @brief get the minimum alignment this buffer needs to be accessed
+  /// properly. This is only known once all elements have been written (after
+  /// you call Finish()). You can use this information if you need to embed
+  /// a FlatBuffer in some other buffer, such that you can later read it
+  /// without first having to copy it into its own buffer.
+  size_t GetBufferMinAlignment() {
+    Finished();
+    return minalign_;
+  }
+
+  /// @cond FLATBUFFERS_INTERNAL
+  void Finished() const {
+    // If you get this assert, you're attempting to get access a buffer
+    // which hasn't been finished yet. Be sure to call
+    // FlatBufferBuilder::Finish with your root table.
+    // If you really need to access an unfinished buffer, call
+    // GetCurrentBufferPointer instead.
+    FLATBUFFERS_ASSERT(finished);
+  }
+  /// @endcond
+
+  /// @brief In order to save space, fields that are set to their default value
+  /// don't get serialized into the buffer.
+  /// @param[in] fd When set to `true`, always serializes default values that
+  /// are set. Optional fields which are not set explicitly, will still not be
+  /// serialized.
+  void ForceDefaults(bool fd) { force_defaults_ = fd; }
+
+  /// @brief By default vtables are deduped in order to save space.
+  /// @param[in] dedup When set to `true`, dedup vtables.
+  void DedupVtables(bool dedup) { dedup_vtables_ = dedup; }
+
+  /// @cond FLATBUFFERS_INTERNAL
+  void Pad(size_t num_bytes) { buf_.fill(num_bytes); }
+
+  void TrackMinAlign(size_t elem_size) {
+    if (elem_size > minalign_) minalign_ = elem_size;
+  }
+
+  void Align(size_t elem_size) {
+    TrackMinAlign(elem_size);
+    buf_.fill(PaddingBytes(buf_.size(), elem_size));
+  }
+
+  void PushFlatBuffer(const uint8_t *bytes, size_t size) {
+    PushBytes(bytes, size);
+    finished = true;
+  }
+
+  void PushBytes(const uint8_t *bytes, size_t size) { buf_.push(bytes, size); }
+
+  void PopBytes(size_t amount) { buf_.pop(amount); }
+
+  template<typename T> void AssertScalarT() {
+    // The code assumes power of 2 sizes and endian-swap-ability.
+    static_assert(flatbuffers::is_scalar<T>::value, "T must be a scalar type");
+  }
+
+  // Write a single aligned scalar to the buffer
+  template<typename T> uoffset_t PushElement(T element) {
+    AssertScalarT<T>();
+    T litle_endian_element = EndianScalar(element);
+    Align(sizeof(T));
+    buf_.push_small(litle_endian_element);
+    return GetSize();
+  }
+
+  template<typename T> uoffset_t PushElement(Offset<T> off) {
+    // Special case for offsets: see ReferTo below.
+    return PushElement(ReferTo(off.o));
+  }
+
+  // When writing fields, we track where they are, so we can create correct
+  // vtables later.
+  void TrackField(voffset_t field, uoffset_t off) {
+    FieldLoc fl = { off, field };
+    buf_.scratch_push_small(fl);
+    num_field_loc++;
+    max_voffset_ = (std::max)(max_voffset_, field);
+  }
+
+  // Like PushElement, but additionally tracks the field this represents.
+  template<typename T> void AddElement(voffset_t field, T e, T def) {
+    // We don't serialize values equal to the default.
+    if (IsTheSameAs(e, def) && !force_defaults_) return;
+    auto off = PushElement(e);
+    TrackField(field, off);
+  }
+
+  template<typename T> void AddOffset(voffset_t field, Offset<T> off) {
+    if (off.IsNull()) return;  // Don't store.
+    AddElement(field, ReferTo(off.o), static_cast<uoffset_t>(0));
+  }
+
+  template<typename T> void AddStruct(voffset_t field, const T *structptr) {
+    if (!structptr) return;  // Default, don't store.
+    Align(AlignOf<T>());
+    buf_.push_small(*structptr);
+    TrackField(field, GetSize());
+  }
+
+  void AddStructOffset(voffset_t field, uoffset_t off) {
+    TrackField(field, off);
+  }
+
+  // Offsets initially are relative to the end of the buffer (downwards).
+  // This function converts them to be relative to the current location
+  // in the buffer (when stored here), pointing upwards.
+  uoffset_t ReferTo(uoffset_t off) {
+    // Align to ensure GetSize() below is correct.
+    Align(sizeof(uoffset_t));
+    // Offset must refer to something already in buffer.
+    FLATBUFFERS_ASSERT(off && off <= GetSize());
+    return GetSize() - off + static_cast<uoffset_t>(sizeof(uoffset_t));
+  }
+
+  void NotNested() {
+    // If you hit this, you're trying to construct a Table/Vector/String
+    // during the construction of its parent table (between the MyTableBuilder
+    // and table.Finish().
+    // Move the creation of these sub-objects to above the MyTableBuilder to
+    // not get this assert.
+    // Ignoring this assert may appear to work in simple cases, but the reason
+    // it is here is that storing objects in-line may cause vtable offsets
+    // to not fit anymore. It also leads to vtable duplication.
+    FLATBUFFERS_ASSERT(!nested);
+    // If you hit this, fields were added outside the scope of a table.
+    FLATBUFFERS_ASSERT(!num_field_loc);
+  }
+
+  // From generated code (or from the parser), we call StartTable/EndTable
+  // with a sequence of AddElement calls in between.
+  uoffset_t StartTable() {
+    NotNested();
+    nested = true;
+    return GetSize();
+  }
+
+  // This finishes one serialized object by generating the vtable if it's a
+  // table, comparing it against existing vtables, and writing the
+  // resulting vtable offset.
+  uoffset_t EndTable(uoffset_t start) {
+    // If you get this assert, a corresponding StartTable wasn't called.
+    FLATBUFFERS_ASSERT(nested);
+    // Write the vtable offset, which is the start of any Table.
+    // We fill it's value later.
+    auto vtableoffsetloc = PushElement<soffset_t>(0);
+    // Write a vtable, which consists entirely of voffset_t elements.
+    // It starts with the number of offsets, followed by a type id, followed
+    // by the offsets themselves. In reverse:
+    // Include space for the last offset and ensure empty tables have a
+    // minimum size.
+    max_voffset_ =
+        (std::max)(static_cast<voffset_t>(max_voffset_ + sizeof(voffset_t)),
+                   FieldIndexToOffset(0));
+    buf_.fill_big(max_voffset_);
+    auto table_object_size = vtableoffsetloc - start;
+    // Vtable use 16bit offsets.
+    FLATBUFFERS_ASSERT(table_object_size < 0x10000);
+    WriteScalar<voffset_t>(buf_.data() + sizeof(voffset_t),
+                           static_cast<voffset_t>(table_object_size));
+    WriteScalar<voffset_t>(buf_.data(), max_voffset_);
+    // Write the offsets into the table
+    for (auto it = buf_.scratch_end() - num_field_loc * sizeof(FieldLoc);
+         it < buf_.scratch_end(); it += sizeof(FieldLoc)) {
+      auto field_location = reinterpret_cast<FieldLoc *>(it);
+      auto pos = static_cast<voffset_t>(vtableoffsetloc - field_location->off);
+      // If this asserts, it means you've set a field twice.
+      FLATBUFFERS_ASSERT(
+          !ReadScalar<voffset_t>(buf_.data() + field_location->id));
+      WriteScalar<voffset_t>(buf_.data() + field_location->id, pos);
+    }
+    ClearOffsets();
+    auto vt1 = reinterpret_cast<voffset_t *>(buf_.data());
+    auto vt1_size = ReadScalar<voffset_t>(vt1);
+    auto vt_use = GetSize();
+    // See if we already have generated a vtable with this exact same
+    // layout before. If so, make it point to the old one, remove this one.
+    if (dedup_vtables_) {
+      for (auto it = buf_.scratch_data(); it < buf_.scratch_end();
+           it += sizeof(uoffset_t)) {
+        auto vt_offset_ptr = reinterpret_cast<uoffset_t *>(it);
+        auto vt2 = reinterpret_cast<voffset_t *>(buf_.data_at(*vt_offset_ptr));
+        auto vt2_size = ReadScalar<voffset_t>(vt2);
+        if (vt1_size != vt2_size || 0 != memcmp(vt2, vt1, vt1_size)) continue;
+        vt_use = *vt_offset_ptr;
+        buf_.pop(GetSize() - vtableoffsetloc);
+        break;
+      }
+    }
+    // If this is a new vtable, remember it.
+    if (vt_use == GetSize()) { buf_.scratch_push_small(vt_use); }
+    // Fill the vtable offset we created above.
+    // The offset points from the beginning of the object to where the
+    // vtable is stored.
+    // Offsets default direction is downward in memory for future format
+    // flexibility (storing all vtables at the start of the file).
+    WriteScalar(buf_.data_at(vtableoffsetloc),
+                static_cast<soffset_t>(vt_use) -
+                    static_cast<soffset_t>(vtableoffsetloc));
+
+    nested = false;
+    return vtableoffsetloc;
+  }
+
+  FLATBUFFERS_ATTRIBUTE(deprecated("call the version above instead"))
+  uoffset_t EndTable(uoffset_t start, voffset_t /*numfields*/) {
+    return EndTable(start);
+  }
+
+  // This checks a required field has been set in a given table that has
+  // just been constructed.
+  template<typename T> void Required(Offset<T> table, voffset_t field);
+
+  uoffset_t StartStruct(size_t alignment) {
+    Align(alignment);
+    return GetSize();
+  }
+
+  uoffset_t EndStruct() { return GetSize(); }
+
+  void ClearOffsets() {
+    buf_.scratch_pop(num_field_loc * sizeof(FieldLoc));
+    num_field_loc = 0;
+    max_voffset_ = 0;
+  }
+
+  // Aligns such that when "len" bytes are written, an object can be written
+  // after it with "alignment" without padding.
+  void PreAlign(size_t len, size_t alignment) {
+    TrackMinAlign(alignment);
+    buf_.fill(PaddingBytes(GetSize() + len, alignment));
+  }
+  template<typename T> void PreAlign(size_t len) {
+    AssertScalarT<T>();
+    PreAlign(len, sizeof(T));
+  }
+  /// @endcond
+
+  #ifndef FLATBUFFERS_CHRE
+  /// @brief Store a string in the buffer, which can contain any binary data.
+  /// @param[in] str A const char pointer to the data to be stored as a string.
+  /// @param[in] len The number of bytes that should be stored from `str`.
+  /// @return Returns the offset in the buffer where the string starts.
+  Offset<String> CreateString(const char *str, size_t len) {
+    NotNested();
+    PreAlign<uoffset_t>(len + 1);  // Always 0-terminated.
+    buf_.fill(1);
+    PushBytes(reinterpret_cast<const uint8_t *>(str), len);
+    PushElement(static_cast<uoffset_t>(len));
+    return Offset<String>(GetSize());
+  }
+
+  /// @brief Store a string in the buffer, which is null-terminated.
+  /// @param[in] str A const char pointer to a C-string to add to the buffer.
+  /// @return Returns the offset in the buffer where the string starts.
+  Offset<String> CreateString(const char *str) {
+    return CreateString(str, strlen(str));
+  }
+
+  /// @brief Store a string in the buffer, which is null-terminated.
+  /// @param[in] str A char pointer to a C-string to add to the buffer.
+  /// @return Returns the offset in the buffer where the string starts.
+  Offset<String> CreateString(char *str) {
+    return CreateString(str, strlen(str));
+  }
+
+  /// @brief Store a string in the buffer, which can contain any binary data.
+  /// @param[in] str A const reference to a std::string to store in the buffer.
+  /// @return Returns the offset in the buffer where the string starts.
+  Offset<String> CreateString(const std::string &str) {
+    return CreateString(str.c_str(), str.length());
+  }
+
+  // clang-format off
+  #ifdef FLATBUFFERS_HAS_STRING_VIEW
+  /// @brief Store a string in the buffer, which can contain any binary data.
+  /// @param[in] str A const string_view to copy in to the buffer.
+  /// @return Returns the offset in the buffer where the string starts.
+  Offset<String> CreateString(flatbuffers::string_view str) {
+    return CreateString(str.data(), str.size());
+  }
+  #endif // FLATBUFFERS_HAS_STRING_VIEW
+  // clang-format on
+
+  /// @brief Store a string in the buffer, which can contain any binary data.
+  /// @param[in] str A const pointer to a `String` struct to add to the buffer.
+  /// @return Returns the offset in the buffer where the string starts
+  Offset<String> CreateString(const String *str) {
+    return str ? CreateString(str->c_str(), str->size()) : 0;
+  }
+
+  /// @brief Store a string in the buffer, which can contain any binary data.
+  /// @param[in] str A const reference to a std::string like type with support
+  /// of T::c_str() and T::length() to store in the buffer.
+  /// @return Returns the offset in the buffer where the string starts.
+  template<typename T> Offset<String> CreateString(const T &str) {
+    return CreateString(str.c_str(), str.length());
+  }
+
+  /// @brief Store a string in the buffer, which can contain any binary data.
+  /// If a string with this exact contents has already been serialized before,
+  /// instead simply returns the offset of the existing string.
+  /// @param[in] str A const char pointer to the data to be stored as a string.
+  /// @param[in] len The number of bytes that should be stored from `str`.
+  /// @return Returns the offset in the buffer where the string starts.
+  Offset<String> CreateSharedString(const char *str, size_t len) {
+    if (!string_pool)
+      string_pool = new StringOffsetMap(StringOffsetCompare(buf_));
+    auto size_before_string = buf_.size();
+    // Must first serialize the string, since the set is all offsets into
+    // buffer.
+    auto off = CreateString(str, len);
+    auto it = string_pool->find(off);
+    // If it exists we reuse existing serialized data!
+    if (it != string_pool->end()) {
+      // We can remove the string we serialized.
+      buf_.pop(buf_.size() - size_before_string);
+      return *it;
+    }
+    // Record this string for future use.
+    string_pool->insert(off);
+    return off;
+  }
+
+  /// @brief Store a string in the buffer, which null-terminated.
+  /// If a string with this exact contents has already been serialized before,
+  /// instead simply returns the offset of the existing string.
+  /// @param[in] str A const char pointer to a C-string to add to the buffer.
+  /// @return Returns the offset in the buffer where the string starts.
+  Offset<String> CreateSharedString(const char *str) {
+    return CreateSharedString(str, strlen(str));
+  }
+
+  /// @brief Store a string in the buffer, which can contain any binary data.
+  /// If a string with this exact contents has already been serialized before,
+  /// instead simply returns the offset of the existing string.
+  /// @param[in] str A const reference to a std::string to store in the buffer.
+  /// @return Returns the offset in the buffer where the string starts.
+  Offset<String> CreateSharedString(const std::string &str) {
+    return CreateSharedString(str.c_str(), str.length());
+  }
+
+  /// @brief Store a string in the buffer, which can contain any binary data.
+  /// If a string with this exact contents has already been serialized before,
+  /// instead simply returns the offset of the existing string.
+  /// @param[in] str A const pointer to a `String` struct to add to the buffer.
+  /// @return Returns the offset in the buffer where the string starts
+  Offset<String> CreateSharedString(const String *str) {
+    return CreateSharedString(str->c_str(), str->size());
+  }
+  #endif  // !FLATBUFFERS_CHRE
+
+  /// @cond FLATBUFFERS_INTERNAL
+  uoffset_t EndVector(size_t len) {
+    FLATBUFFERS_ASSERT(nested);  // Hit if no corresponding StartVector.
+    nested = false;
+    return PushElement(static_cast<uoffset_t>(len));
+  }
+
+  void StartVector(size_t len, size_t elemsize) {
+    NotNested();
+    nested = true;
+    PreAlign<uoffset_t>(len * elemsize);
+    PreAlign(len * elemsize, elemsize);  // Just in case elemsize > uoffset_t.
+  }
+
+  // Call this right before StartVector/CreateVector if you want to force the
+  // alignment to be something different than what the element size would
+  // normally dictate.
+  // This is useful when storing a nested_flatbuffer in a vector of bytes,
+  // or when storing SIMD floats, etc.
+  void ForceVectorAlignment(size_t len, size_t elemsize, size_t alignment) {
+    PreAlign(len * elemsize, alignment);
+  }
+
+  // Similar to ForceVectorAlignment but for String fields.
+  void ForceStringAlignment(size_t len, size_t alignment) {
+    PreAlign((len + 1) * sizeof(char), alignment);
+  }
+
+  /// @endcond
+
+  /// @brief Serialize an array into a FlatBuffer `vector`.
+  /// @tparam T The data type of the array elements.
+  /// @param[in] v A pointer to the array of type `T` to serialize into the
+  /// buffer as a `vector`.
+  /// @param[in] len The number of elements to serialize.
+  /// @return Returns a typed `Offset` into the serialized data indicating
+  /// where the vector is stored.
+  template<typename T> Offset<Vector<T>> CreateVector(const T *v, size_t len) {
+    // If this assert hits, you're specifying a template argument that is
+    // causing the wrong overload to be selected, remove it.
+    AssertScalarT<T>();
+    StartVector(len, sizeof(T));
+    // clang-format off
+    #if FLATBUFFERS_LITTLEENDIAN
+      PushBytes(reinterpret_cast<const uint8_t *>(v), len * sizeof(T));
+    #else
+      if (sizeof(T) == 1) {
+        PushBytes(reinterpret_cast<const uint8_t *>(v), len);
+      } else {
+        for (auto i = len; i > 0; ) {
+          PushElement(v[--i]);
+        }
+      }
+    #endif
+    // clang-format on
+    return Offset<Vector<T>>(EndVector(len));
+  }
+
+  template<typename T>
+  Offset<Vector<Offset<T>>> CreateVector(const Offset<T> *v, size_t len) {
+    StartVector(len, sizeof(Offset<T>));
+    for (auto i = len; i > 0;) { PushElement(v[--i]); }
+    return Offset<Vector<Offset<T>>>(EndVector(len));
+  }
+
+  #ifndef FLATBUFFERS_CHRE
+  /// @brief Serialize a `std::vector` into a FlatBuffer `vector`.
+  /// @tparam T The data type of the `std::vector` elements.
+  /// @param v A const reference to the `std::vector` to serialize into the
+  /// buffer as a `vector`.
+  /// @return Returns a typed `Offset` into the serialized data indicating
+  /// where the vector is stored.
+  template<typename T> Offset<Vector<T>> CreateVector(const std::vector<T> &v) {
+    return CreateVector(data(v), v.size());
+  }
+
+  // vector<bool> may be implemented using a bit-set, so we can't access it as
+  // an array. Instead, read elements manually.
+  // Background: https://isocpp.org/blog/2012/11/on-vectorbool
+  Offset<Vector<uint8_t>> CreateVector(const std::vector<bool> &v) {
+    StartVector(v.size(), sizeof(uint8_t));
+    for (auto i = v.size(); i > 0;) {
+      PushElement(static_cast<uint8_t>(v[--i]));
+    }
+    return Offset<Vector<uint8_t>>(EndVector(v.size()));
+  }
+  #else  // else if defined(FLATBUFFERS_CHRE)
+  // We need to define this function as it's optionally used in the
+  // Create<Type>Direct() helper functions generated by the FlatBuffer compiler,
+  // however its use at runtime is not supported.
+  template<typename T> Offset<Vector<T>> CreateVector(
+      const std::vector<T>& /* v */) {
+    // std::vector use by FlatBuffers is not supported in CHRE.
+    FLATBUFFERS_ASSERT(false);
+    return 0;
+  }
+
+  /// @brief Serialize a `chre::DynamicVector` into a FlatBuffer `vector`.
+  /// @tparam T The data type of the `chre::DynamicVector` elements.
+  /// @param v A const reference to the `chre::DynamicVector` to serialize into
+  /// the buffer as a `vector`.
+  /// @return Returns a typed `Offset` into the serialized data indicating
+  /// where the vector is stored.
+  template<typename T> Offset<Vector<T>> CreateVector(
+      const chre::DynamicVector<T> &v) {
+    return CreateVector(v.data(), v.size());
+  }
+  #endif  // FLATBUFFERS_CHRE
+
+  // clang-format off
+  #if !defined(FLATBUFFERS_CPP98_STL) && !defined(FLATBUFFERS_CHRE)
+  /// @brief Serialize values returned by a function into a FlatBuffer `vector`.
+  /// This is a convenience function that takes care of iteration for you.
+  /// @tparam T The data type of the `std::vector` elements.
+  /// @param f A function that takes the current iteration 0..vector_size-1 and
+  /// returns any type that you can construct a FlatBuffers vector out of.
+  /// @return Returns a typed `Offset` into the serialized data indicating
+  /// where the vector is stored.
+  template<typename T> Offset<Vector<T>> CreateVector(size_t vector_size,
+      const std::function<T (size_t i)> &f) {
+    std::vector<T> elems(vector_size);
+    for (size_t i = 0; i < vector_size; i++) elems[i] = f(i);
+    return CreateVector(elems);
+  }
+  #endif
+  // clang-format on
+
+  #ifndef FLATBUFFERS_CHRE
+  /// @brief Serialize values returned by a function into a FlatBuffer `vector`.
+  /// This is a convenience function that takes care of iteration for you.
+  /// @tparam T The data type of the `std::vector` elements.
+  /// @param f A function that takes the current iteration 0..vector_size-1,
+  /// and the state parameter returning any type that you can construct a
+  /// FlatBuffers vector out of.
+  /// @param state State passed to f.
+  /// @return Returns a typed `Offset` into the serialized data indicating
+  /// where the vector is stored.
+  template<typename T, typename F, typename S>
+  Offset<Vector<T>> CreateVector(size_t vector_size, F f, S *state) {
+    std::vector<T> elems(vector_size);
+    for (size_t i = 0; i < vector_size; i++) elems[i] = f(i, state);
+    return CreateVector(elems);
+  }
+
+  /// @brief Serialize a `std::vector<std::string>` into a FlatBuffer `vector`.
+  /// This is a convenience function for a common case.
+  /// @param v A const reference to the `std::vector` to serialize into the
+  /// buffer as a `vector`.
+  /// @return Returns a typed `Offset` into the serialized data indicating
+  /// where the vector is stored.
+  Offset<Vector<Offset<String>>> CreateVectorOfStrings(
+      const std::vector<std::string> &v) {
+    std::vector<Offset<String>> offsets(v.size());
+    for (size_t i = 0; i < v.size(); i++) offsets[i] = CreateString(v[i]);
+    return CreateVector(offsets);
+  }
+  #endif  // !FLATBUFFERS_CHRE
+
+  /// @brief Serialize an array of structs into a FlatBuffer `vector`.
+  /// @tparam T The data type of the struct array elements.
+  /// @param[in] v A pointer to the array of type `T` to serialize into the
+  /// buffer as a `vector`.
+  /// @param[in] len The number of elements to serialize.
+  /// @return Returns a typed `Offset` into the serialized data indicating
+  /// where the vector is stored.
+  template<typename T>
+  Offset<Vector<const T *>> CreateVectorOfStructs(const T *v, size_t len) {
+    StartVector(len * sizeof(T) / AlignOf<T>(), AlignOf<T>());
+    PushBytes(reinterpret_cast<const uint8_t *>(v), sizeof(T) * len);
+    return Offset<Vector<const T *>>(EndVector(len));
+  }
+
+  #ifndef FLATBUFFERS_CHRE
+  /// @brief Serialize an array of native structs into a FlatBuffer `vector`.
+  /// @tparam T The data type of the struct array elements.
+  /// @tparam S The data type of the native struct array elements.
+  /// @param[in] v A pointer to the array of type `S` to serialize into the
+  /// buffer as a `vector`.
+  /// @param[in] len The number of elements to serialize.
+  /// @return Returns a typed `Offset` into the serialized data indicating
+  /// where the vector is stored.
+  template<typename T, typename S>
+  Offset<Vector<const T *>> CreateVectorOfNativeStructs(const S *v,
+                                                        size_t len) {
+    extern T Pack(const S &);
+    std::vector<T> vv(len);
+    std::transform(v, v + len, vv.begin(), Pack);
+    return CreateVectorOfStructs<T>(data(vv), vv.size());
+  }
+
+  // clang-format off
+  #ifndef FLATBUFFERS_CPP98_STL
+  /// @brief Serialize an array of structs into a FlatBuffer `vector`.
+  /// @tparam T The data type of the struct array elements.
+  /// @param[in] filler A function that takes the current iteration 0..vector_size-1
+  /// and a pointer to the struct that must be filled.
+  /// @return Returns a typed `Offset` into the serialized data indicating
+  /// where the vector is stored.
+  /// This is mostly useful when flatbuffers are generated with mutation
+  /// accessors.
+  template<typename T> Offset<Vector<const T *>> CreateVectorOfStructs(
+      size_t vector_size, const std::function<void(size_t i, T *)> &filler) {
+    T* structs = StartVectorOfStructs<T>(vector_size);
+    for (size_t i = 0; i < vector_size; i++) {
+      filler(i, structs);
+      structs++;
+    }
+    return EndVectorOfStructs<T>(vector_size);
+  }
+  #endif
+  #endif  // !FLATBUFFERS_CHRE
+  // clang-format on
+
+  /// @brief Serialize an array of structs into a FlatBuffer `vector`.
+  /// @tparam T The data type of the struct array elements.
+  /// @param[in] f A function that takes the current iteration 0..vector_size-1,
+  /// a pointer to the struct that must be filled and the state argument.
+  /// @param[in] state Arbitrary state to pass to f.
+  /// @return Returns a typed `Offset` into the serialized data indicating
+  /// where the vector is stored.
+  /// This is mostly useful when flatbuffers are generated with mutation
+  /// accessors.
+  template<typename T, typename F, typename S>
+  Offset<Vector<const T *>> CreateVectorOfStructs(size_t vector_size, F f,
+                                                  S *state) {
+    T *structs = StartVectorOfStructs<T>(vector_size);
+    for (size_t i = 0; i < vector_size; i++) {
+      f(i, structs, state);
+      structs++;
+    }
+    return EndVectorOfStructs<T>(vector_size);
+  }
+
+  #ifndef FLATBUFFERS_CHRE
+  /// @brief Serialize a `std::vector` of structs into a FlatBuffer `vector`.
+  /// @tparam T The data type of the `std::vector` struct elements.
+  /// @param[in] v A const reference to the `std::vector` of structs to
+  /// serialize into the buffer as a `vector`.
+  /// @return Returns a typed `Offset` into the serialized data indicating
+  /// where the vector is stored.
+  template<typename T, typename Alloc>
+  Offset<Vector<const T *>> CreateVectorOfStructs(
+      const std::vector<T, Alloc> &v) {
+    return CreateVectorOfStructs(data(v), v.size());
+  }
+
+  /// @brief Serialize a `std::vector` of native structs into a FlatBuffer
+  /// `vector`.
+  /// @tparam T The data type of the `std::vector` struct elements.
+  /// @tparam S The data type of the `std::vector` native struct elements.
+  /// @param[in] v A const reference to the `std::vector` of structs to
+  /// serialize into the buffer as a `vector`.
+  /// @return Returns a typed `Offset` into the serialized data indicating
+  /// where the vector is stored.
+  template<typename T, typename S>
+  Offset<Vector<const T *>> CreateVectorOfNativeStructs(
+      const std::vector<S> &v) {
+    return CreateVectorOfNativeStructs<T, S>(data(v), v.size());
+  }
+
+  /// @cond FLATBUFFERS_INTERNAL
+  template<typename T> struct StructKeyComparator {
+    bool operator()(const T &a, const T &b) const {
+      return a.KeyCompareLessThan(&b);
+    }
+
+   private:
+    StructKeyComparator &operator=(const StructKeyComparator &);
+  };
+  /// @endcond
+
+  /// @brief Serialize a `std::vector` of structs into a FlatBuffer `vector`
+  /// in sorted order.
+  /// @tparam T The data type of the `std::vector` struct elements.
+  /// @param[in] v A const reference to the `std::vector` of structs to
+  /// serialize into the buffer as a `vector`.
+  /// @return Returns a typed `Offset` into the serialized data indicating
+  /// where the vector is stored.
+  template<typename T>
+  Offset<Vector<const T *>> CreateVectorOfSortedStructs(std::vector<T> *v) {
+    return CreateVectorOfSortedStructs(data(*v), v->size());
+  }
+
+  /// @brief Serialize a `std::vector` of native structs into a FlatBuffer
+  /// `vector` in sorted order.
+  /// @tparam T The data type of the `std::vector` struct elements.
+  /// @tparam S The data type of the `std::vector` native struct elements.
+  /// @param[in] v A const reference to the `std::vector` of structs to
+  /// serialize into the buffer as a `vector`.
+  /// @return Returns a typed `Offset` into the serialized data indicating
+  /// where the vector is stored.
+  template<typename T, typename S>
+  Offset<Vector<const T *>> CreateVectorOfSortedNativeStructs(
+      std::vector<S> *v) {
+    return CreateVectorOfSortedNativeStructs<T, S>(data(*v), v->size());
+  }
+
+  /// @brief Serialize an array of structs into a FlatBuffer `vector` in sorted
+  /// order.
+  /// @tparam T The data type of the struct array elements.
+  /// @param[in] v A pointer to the array of type `T` to serialize into the
+  /// buffer as a `vector`.
+  /// @param[in] len The number of elements to serialize.
+  /// @return Returns a typed `Offset` into the serialized data indicating
+  /// where the vector is stored.
+  template<typename T>
+  Offset<Vector<const T *>> CreateVectorOfSortedStructs(T *v, size_t len) {
+    std::sort(v, v + len, StructKeyComparator<T>());
+    return CreateVectorOfStructs(v, len);
+  }
+
+  /// @brief Serialize an array of native structs into a FlatBuffer `vector` in
+  /// sorted order.
+  /// @tparam T The data type of the struct array elements.
+  /// @tparam S The data type of the native struct array elements.
+  /// @param[in] v A pointer to the array of type `S` to serialize into the
+  /// buffer as a `vector`.
+  /// @param[in] len The number of elements to serialize.
+  /// @return Returns a typed `Offset` into the serialized data indicating
+  /// where the vector is stored.
+  template<typename T, typename S>
+  Offset<Vector<const T *>> CreateVectorOfSortedNativeStructs(S *v,
+                                                              size_t len) {
+    extern T Pack(const S &);
+    typedef T (*Pack_t)(const S &);
+    std::vector<T> vv(len);
+    std::transform(v, v + len, vv.begin(), static_cast<Pack_t &>(Pack));
+    return CreateVectorOfSortedStructs<T>(vv, len);
+  }
+
+  /// @cond FLATBUFFERS_INTERNAL
+  template<typename T> struct TableKeyComparator {
+    TableKeyComparator(vector_downward &buf) : buf_(buf) {}
+    TableKeyComparator(const TableKeyComparator &other) : buf_(other.buf_) {}
+    bool operator()(const Offset<T> &a, const Offset<T> &b) const {
+      auto table_a = reinterpret_cast<T *>(buf_.data_at(a.o));
+      auto table_b = reinterpret_cast<T *>(buf_.data_at(b.o));
+      return table_a->KeyCompareLessThan(table_b);
+    }
+    vector_downward &buf_;
+
+   private:
+    TableKeyComparator &operator=(const TableKeyComparator &other) {
+      buf_ = other.buf_;
+      return *this;
+    }
+  };
+  /// @endcond
+
+  /// @brief Serialize an array of `table` offsets as a `vector` in the buffer
+  /// in sorted order.
+  /// @tparam T The data type that the offset refers to.
+  /// @param[in] v An array of type `Offset<T>` that contains the `table`
+  /// offsets to store in the buffer in sorted order.
+  /// @param[in] len The number of elements to store in the `vector`.
+  /// @return Returns a typed `Offset` into the serialized data indicating
+  /// where the vector is stored.
+  template<typename T>
+  Offset<Vector<Offset<T>>> CreateVectorOfSortedTables(Offset<T> *v,
+                                                       size_t len) {
+    std::sort(v, v + len, TableKeyComparator<T>(buf_));
+    return CreateVector(v, len);
+  }
+
+  /// @brief Serialize an array of `table` offsets as a `vector` in the buffer
+  /// in sorted order.
+  /// @tparam T The data type that the offset refers to.
+  /// @param[in] v An array of type `Offset<T>` that contains the `table`
+  /// offsets to store in the buffer in sorted order.
+  /// @return Returns a typed `Offset` into the serialized data indicating
+  /// where the vector is stored.
+  template<typename T>
+  Offset<Vector<Offset<T>>> CreateVectorOfSortedTables(
+      std::vector<Offset<T>> *v) {
+    return CreateVectorOfSortedTables(data(*v), v->size());
+  }
+  #endif  // !FLATBUFFERS_CHRE
+
+  /// @brief Specialized version of `CreateVector` for non-copying use cases.
+  /// Write the data any time later to the returned buffer pointer `buf`.
+  /// @param[in] len The number of elements to store in the `vector`.
+  /// @param[in] elemsize The size of each element in the `vector`.
+  /// @param[out] buf A pointer to a `uint8_t` pointer that can be
+  /// written to at a later time to serialize the data into a `vector`
+  /// in the buffer.
+  uoffset_t CreateUninitializedVector(size_t len, size_t elemsize,
+                                      uint8_t **buf) {
+    NotNested();
+    StartVector(len, elemsize);
+    buf_.make_space(len * elemsize);
+    auto vec_start = GetSize();
+    auto vec_end = EndVector(len);
+    *buf = buf_.data_at(vec_start);
+    return vec_end;
+  }
+
+  /// @brief Specialized version of `CreateVector` for non-copying use cases.
+  /// Write the data any time later to the returned buffer pointer `buf`.
+  /// @tparam T The data type of the data that will be stored in the buffer
+  /// as a `vector`.
+  /// @param[in] len The number of elements to store in the `vector`.
+  /// @param[out] buf A pointer to a pointer of type `T` that can be
+  /// written to at a later time to serialize the data into a `vector`
+  /// in the buffer.
+  template<typename T>
+  Offset<Vector<T>> CreateUninitializedVector(size_t len, T **buf) {
+    AssertScalarT<T>();
+    return CreateUninitializedVector(len, sizeof(T),
+                                     reinterpret_cast<uint8_t **>(buf));
+  }
+
+  template<typename T>
+  Offset<Vector<const T *>> CreateUninitializedVectorOfStructs(size_t len,
+                                                               T **buf) {
+    return CreateUninitializedVector(len, sizeof(T),
+                                     reinterpret_cast<uint8_t **>(buf));
+  }
+
+  // @brief Create a vector of scalar type T given as input a vector of scalar
+  // type U, useful with e.g. pre "enum class" enums, or any existing scalar
+  // data of the wrong type.
+  template<typename T, typename U>
+  Offset<Vector<T>> CreateVectorScalarCast(const U *v, size_t len) {
+    AssertScalarT<T>();
+    AssertScalarT<U>();
+    StartVector(len, sizeof(T));
+    for (auto i = len; i > 0;) { PushElement(static_cast<T>(v[--i])); }
+    return Offset<Vector<T>>(EndVector(len));
+  }
+
+  /// @brief Write a struct by itself, typically to be part of a union.
+  template<typename T> Offset<const T *> CreateStruct(const T &structobj) {
+    NotNested();
+    Align(AlignOf<T>());
+    buf_.push_small(structobj);
+    return Offset<const T *>(GetSize());
+  }
+
+  /// @brief The length of a FlatBuffer file header.
+  static const size_t kFileIdentifierLength = 4;
+
+  /// @brief Finish serializing a buffer by writing the root offset.
+  /// @param[in] file_identifier If a `file_identifier` is given, the buffer
+  /// will be prefixed with a standard FlatBuffers file header.
+  template<typename T>
+  void Finish(Offset<T> root, const char *file_identifier = nullptr) {
+    Finish(root.o, file_identifier, false);
+  }
+
+  /// @brief Finish a buffer with a 32 bit size field pre-fixed (size of the
+  /// buffer following the size field). These buffers are NOT compatible
+  /// with standard buffers created by Finish, i.e. you can't call GetRoot
+  /// on them, you have to use GetSizePrefixedRoot instead.
+  /// All >32 bit quantities in this buffer will be aligned when the whole
+  /// size pre-fixed buffer is aligned.
+  /// These kinds of buffers are useful for creating a stream of FlatBuffers.
+  template<typename T>
+  void FinishSizePrefixed(Offset<T> root,
+                          const char *file_identifier = nullptr) {
+    Finish(root.o, file_identifier, true);
+  }
+
+  void SwapBufAllocator(FlatBufferBuilder &other) {
+    buf_.swap_allocator(other.buf_);
+  }
+
+ protected:
+  // You shouldn't really be copying instances of this class.
+  FlatBufferBuilder(const FlatBufferBuilder &);
+  FlatBufferBuilder &operator=(const FlatBufferBuilder &);
+
+  void Finish(uoffset_t root, const char *file_identifier, bool size_prefix) {
+    NotNested();
+    buf_.clear_scratch();
+    // This will cause the whole buffer to be aligned.
+    PreAlign((size_prefix ? sizeof(uoffset_t) : 0) + sizeof(uoffset_t) +
+                 (file_identifier ? kFileIdentifierLength : 0),
+             minalign_);
+    if (file_identifier) {
+      FLATBUFFERS_ASSERT(strlen(file_identifier) == kFileIdentifierLength);
+      PushBytes(reinterpret_cast<const uint8_t *>(file_identifier),
+                kFileIdentifierLength);
+    }
+    PushElement(ReferTo(root));  // Location of root.
+    if (size_prefix) { PushElement(GetSize()); }
+    finished = true;
+  }
+
+  struct FieldLoc {
+    uoffset_t off;
+    voffset_t id;
+  };
+
+  vector_downward buf_;
+
+  // Accumulating offsets of table members while it is being built.
+  // We store these in the scratch pad of buf_, after the vtable offsets.
+  uoffset_t num_field_loc;
+  // Track how much of the vtable is in use, so we can output the most compact
+  // possible vtable.
+  voffset_t max_voffset_;
+
+  // Ensure objects are not nested.
+  bool nested;
+
+  // Ensure the buffer is finished before it is being accessed.
+  bool finished;
+
+  size_t minalign_;
+
+  bool force_defaults_;  // Serialize values equal to their defaults anyway.
+
+  bool dedup_vtables_;
+
+  #ifndef FLATBUFFERS_CHRE
+  struct StringOffsetCompare {
+    StringOffsetCompare(const vector_downward &buf) : buf_(&buf) {}
+    bool operator()(const Offset<String> &a, const Offset<String> &b) const {
+      auto stra = reinterpret_cast<const String *>(buf_->data_at(a.o));
+      auto strb = reinterpret_cast<const String *>(buf_->data_at(b.o));
+      return StringLessThan(stra->data(), stra->size(), strb->data(),
+                            strb->size());
+    }
+    const vector_downward *buf_;
+  };
+
+  // For use with CreateSharedString. Instantiated on first use only.
+  typedef std::set<Offset<String>, StringOffsetCompare> StringOffsetMap;
+  StringOffsetMap *string_pool;
+  #endif  // !FLATBUFFERS_CHRE
+
+ private:
+  // Allocates space for a vector of structures.
+  // Must be completed with EndVectorOfStructs().
+  template<typename T> T *StartVectorOfStructs(size_t vector_size) {
+    StartVector(vector_size * sizeof(T) / AlignOf<T>(), AlignOf<T>());
+    return reinterpret_cast<T *>(buf_.make_space(vector_size * sizeof(T)));
+  }
+
+  // End the vector of structues in the flatbuffers.
+  // Vector should have previously be started with StartVectorOfStructs().
+  template<typename T>
+  Offset<Vector<const T *>> EndVectorOfStructs(size_t vector_size) {
+    return Offset<Vector<const T *>>(EndVector(vector_size));
+  }
+};
+/// @}
+
+/// @cond FLATBUFFERS_INTERNAL
+// Helpers to get a typed pointer to the root object contained in the buffer.
+template<typename T> T *GetMutableRoot(void *buf) {
+  EndianCheck();
+  return reinterpret_cast<T *>(
+      reinterpret_cast<uint8_t *>(buf) +
+      EndianScalar(*reinterpret_cast<uoffset_t *>(buf)));
+}
+
+template<typename T> const T *GetRoot(const void *buf) {
+  return GetMutableRoot<T>(const_cast<void *>(buf));
+}
+
+template<typename T> const T *GetSizePrefixedRoot(const void *buf) {
+  return GetRoot<T>(reinterpret_cast<const uint8_t *>(buf) + sizeof(uoffset_t));
+}
+
+/// Helpers to get a typed pointer to objects that are currently being built.
+/// @warning Creating new objects will lead to reallocations and invalidates
+/// the pointer!
+template<typename T>
+T *GetMutableTemporaryPointer(FlatBufferBuilder &fbb, Offset<T> offset) {
+  return reinterpret_cast<T *>(fbb.GetCurrentBufferPointer() + fbb.GetSize() -
+                               offset.o);
+}
+
+template<typename T>
+const T *GetTemporaryPointer(FlatBufferBuilder &fbb, Offset<T> offset) {
+  return GetMutableTemporaryPointer<T>(fbb, offset);
+}
+
+/// @brief Get a pointer to the the file_identifier section of the buffer.
+/// @return Returns a const char pointer to the start of the file_identifier
+/// characters in the buffer.  The returned char * has length
+/// 'flatbuffers::FlatBufferBuilder::kFileIdentifierLength'.
+/// This function is UNDEFINED for FlatBuffers whose schema does not include
+/// a file_identifier (likely points at padding or the start of a the root
+/// vtable).
+inline const char *GetBufferIdentifier(const void *buf,
+                                       bool size_prefixed = false) {
+  return reinterpret_cast<const char *>(buf) +
+         ((size_prefixed) ? 2 * sizeof(uoffset_t) : sizeof(uoffset_t));
+}
+
+// Helper to see if the identifier in a buffer has the expected value.
+inline bool BufferHasIdentifier(const void *buf, const char *identifier,
+                                bool size_prefixed = false) {
+  return strncmp(GetBufferIdentifier(buf, size_prefixed), identifier,
+                 FlatBufferBuilder::kFileIdentifierLength) == 0;
+}
+
+// Helper class to verify the integrity of a FlatBuffer
+class Verifier FLATBUFFERS_FINAL_CLASS {
+ public:
+  Verifier(const uint8_t *buf, size_t buf_len, uoffset_t _max_depth = 64,
+           uoffset_t _max_tables = 1000000, bool _check_alignment = true)
+      : buf_(buf),
+        size_(buf_len),
+        depth_(0),
+        max_depth_(_max_depth),
+        num_tables_(0),
+        max_tables_(_max_tables),
+        upper_bound_(0),
+        check_alignment_(_check_alignment) {
+    FLATBUFFERS_ASSERT(size_ < FLATBUFFERS_MAX_BUFFER_SIZE);
+  }
+
+  // Central location where any verification failures register.
+  bool Check(bool ok) const {
+    // clang-format off
+    #ifdef FLATBUFFERS_DEBUG_VERIFICATION_FAILURE
+      FLATBUFFERS_ASSERT(ok);
+    #endif
+    #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
+      if (!ok)
+        upper_bound_ = 0;
+    #endif
+    // clang-format on
+    return ok;
+  }
+
+  // Verify any range within the buffer.
+  bool Verify(size_t elem, size_t elem_len) const {
+    // clang-format off
+    #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
+      auto upper_bound = elem + elem_len;
+      if (upper_bound_ < upper_bound)
+        upper_bound_ =  upper_bound;
+    #endif
+    // clang-format on
+    return Check(elem_len < size_ && elem <= size_ - elem_len);
+  }
+
+  template<typename T> bool VerifyAlignment(size_t elem) const {
+    return Check((elem & (sizeof(T) - 1)) == 0 || !check_alignment_);
+  }
+
+  // Verify a range indicated by sizeof(T).
+  template<typename T> bool Verify(size_t elem) const {
+    return VerifyAlignment<T>(elem) && Verify(elem, sizeof(T));
+  }
+
+  bool VerifyFromPointer(const uint8_t *p, size_t len) {
+    auto o = static_cast<size_t>(p - buf_);
+    return Verify(o, len);
+  }
+
+  // Verify relative to a known-good base pointer.
+  bool Verify(const uint8_t *base, voffset_t elem_off, size_t elem_len) const {
+    return Verify(static_cast<size_t>(base - buf_) + elem_off, elem_len);
+  }
+
+  template<typename T>
+  bool Verify(const uint8_t *base, voffset_t elem_off) const {
+    return Verify(static_cast<size_t>(base - buf_) + elem_off, sizeof(T));
+  }
+
+  // Verify a pointer (may be NULL) of a table type.
+  template<typename T> bool VerifyTable(const T *table) {
+    return !table || table->Verify(*this);
+  }
+
+  // Verify a pointer (may be NULL) of any vector type.
+  template<typename T> bool VerifyVector(const Vector<T> *vec) const {
+    return !vec || VerifyVectorOrString(reinterpret_cast<const uint8_t *>(vec),
+                                        sizeof(T));
+  }
+
+  // Verify a pointer (may be NULL) of a vector to struct.
+  template<typename T> bool VerifyVector(const Vector<const T *> *vec) const {
+    return VerifyVector(reinterpret_cast<const Vector<T> *>(vec));
+  }
+
+  #ifndef FLATBUFFERS_CHRE
+  // Verify a pointer (may be NULL) to string.
+  bool VerifyString(const String *str) const {
+    size_t end;
+    return !str || (VerifyVectorOrString(reinterpret_cast<const uint8_t *>(str),
+                                         1, &end) &&
+                    Verify(end, 1) &&           // Must have terminator
+                    Check(buf_[end] == '\0'));  // Terminating byte must be 0.
+  }
+  #endif
+
+  // Common code between vectors and strings.
+  bool VerifyVectorOrString(const uint8_t *vec, size_t elem_size,
+                            size_t *end = nullptr) const {
+    auto veco = static_cast<size_t>(vec - buf_);
+    // Check we can read the size field.
+    if (!Verify<uoffset_t>(veco)) return false;
+    // Check the whole array. If this is a string, the byte past the array
+    // must be 0.
+    auto size = ReadScalar<uoffset_t>(vec);
+    auto max_elems = FLATBUFFERS_MAX_BUFFER_SIZE / elem_size;
+    if (!Check(size < max_elems))
+      return false;  // Protect against byte_size overflowing.
+    auto byte_size = sizeof(size) + elem_size * size;
+    if (end) *end = veco + byte_size;
+    return Verify(veco, byte_size);
+  }
+
+  #ifndef FLATBUFFERS_CHRE
+  // Special case for string contents, after the above has been called.
+  bool VerifyVectorOfStrings(const Vector<Offset<String>> *vec) const {
+    if (vec) {
+      for (uoffset_t i = 0; i < vec->size(); i++) {
+        if (!VerifyString(vec->Get(i))) return false;
+      }
+    }
+    return true;
+  }
+  #endif
+
+  // Special case for table contents, after the above has been called.
+  template<typename T> bool VerifyVectorOfTables(const Vector<Offset<T>> *vec) {
+    if (vec) {
+      for (uoffset_t i = 0; i < vec->size(); i++) {
+        if (!vec->Get(i)->Verify(*this)) return false;
+      }
+    }
+    return true;
+  }
+
+  __supress_ubsan__("unsigned-integer-overflow") bool VerifyTableStart(
+      const uint8_t *table) {
+    // Check the vtable offset.
+    auto tableo = static_cast<size_t>(table - buf_);
+    if (!Verify<soffset_t>(tableo)) return false;
+    // This offset may be signed, but doing the subtraction unsigned always
+    // gives the result we want.
+    auto vtableo = tableo - static_cast<size_t>(ReadScalar<soffset_t>(table));
+    // Check the vtable size field, then check vtable fits in its entirety.
+    return VerifyComplexity() && Verify<voffset_t>(vtableo) &&
+           VerifyAlignment<voffset_t>(ReadScalar<voffset_t>(buf_ + vtableo)) &&
+           Verify(vtableo, ReadScalar<voffset_t>(buf_ + vtableo));
+  }
+
+  template<typename T>
+  bool VerifyBufferFromStart(const char *identifier, size_t start) {
+    if (identifier && (size_ < 2 * sizeof(flatbuffers::uoffset_t) ||
+                       !BufferHasIdentifier(buf_ + start, identifier))) {
+      return false;
+    }
+
+    // Call T::Verify, which must be in the generated code for this type.
+    auto o = VerifyOffset(start);
+    return o && reinterpret_cast<const T *>(buf_ + start + o)->Verify(*this)
+    // clang-format off
+    #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
+           && GetComputedSize()
+    #endif
+        ;
+    // clang-format on
+  }
+
+  // Verify this whole buffer, starting with root type T.
+  template<typename T> bool VerifyBuffer() { return VerifyBuffer<T>(nullptr); }
+
+  template<typename T> bool VerifyBuffer(const char *identifier) {
+    return VerifyBufferFromStart<T>(identifier, 0);
+  }
+
+  template<typename T> bool VerifySizePrefixedBuffer(const char *identifier) {
+    return Verify<uoffset_t>(0U) &&
+           ReadScalar<uoffset_t>(buf_) == size_ - sizeof(uoffset_t) &&
+           VerifyBufferFromStart<T>(identifier, sizeof(uoffset_t));
+  }
+
+  uoffset_t VerifyOffset(size_t start) const {
+    if (!Verify<uoffset_t>(start)) return 0;
+    auto o = ReadScalar<uoffset_t>(buf_ + start);
+    // May not point to itself.
+    if (!Check(o != 0)) return 0;
+    // Can't wrap around / buffers are max 2GB.
+    if (!Check(static_cast<soffset_t>(o) >= 0)) return 0;
+    // Must be inside the buffer to create a pointer from it (pointer outside
+    // buffer is UB).
+    if (!Verify(start + o, 1)) return 0;
+    return o;
+  }
+
+  uoffset_t VerifyOffset(const uint8_t *base, voffset_t start) const {
+    return VerifyOffset(static_cast<size_t>(base - buf_) + start);
+  }
+
+  // Called at the start of a table to increase counters measuring data
+  // structure depth and amount, and possibly bails out with false if
+  // limits set by the constructor have been hit. Needs to be balanced
+  // with EndTable().
+  bool VerifyComplexity() {
+    depth_++;
+    num_tables_++;
+    return Check(depth_ <= max_depth_ && num_tables_ <= max_tables_);
+  }
+
+  // Called at the end of a table to pop the depth count.
+  bool EndTable() {
+    depth_--;
+    return true;
+  }
+
+  // Returns the message size in bytes
+  size_t GetComputedSize() const {
+    // clang-format off
+    #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
+      uintptr_t size = upper_bound_;
+      // Align the size to uoffset_t
+      size = (size - 1 + sizeof(uoffset_t)) & ~(sizeof(uoffset_t) - 1);
+      return (size > size_) ?  0 : size;
+    #else
+      // Must turn on FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE for this to work.
+      (void)upper_bound_;
+      FLATBUFFERS_ASSERT(false);
+      return 0;
+    #endif
+    // clang-format on
+  }
+
+ private:
+  const uint8_t *buf_;
+  size_t size_;
+  uoffset_t depth_;
+  uoffset_t max_depth_;
+  uoffset_t num_tables_;
+  uoffset_t max_tables_;
+  mutable size_t upper_bound_;
+  bool check_alignment_;
+};
+
+// Convenient way to bundle a buffer and its length, to pass it around
+// typed by its root.
+// A BufferRef does not own its buffer.
+struct BufferRefBase {};  // for std::is_base_of
+template<typename T> struct BufferRef : BufferRefBase {
+  BufferRef() : buf(nullptr), len(0), must_free(false) {}
+  BufferRef(uint8_t *_buf, uoffset_t _len)
+      : buf(_buf), len(_len), must_free(false) {}
+
+  ~BufferRef() {
+    if (must_free) free(buf);
+  }
+
+  const T *GetRoot() const { return flatbuffers::GetRoot<T>(buf); }
+
+  bool Verify() {
+    Verifier verifier(buf, len);
+    return verifier.VerifyBuffer<T>(nullptr);
+  }
+
+  uint8_t *buf;
+  uoffset_t len;
+  bool must_free;
+};
+
+// "structs" are flat structures that do not have an offset table, thus
+// always have all members present and do not support forwards/backwards
+// compatible extensions.
+
+class Struct FLATBUFFERS_FINAL_CLASS {
+ public:
+  template<typename T> T GetField(uoffset_t o) const {
+    return ReadScalar<T>(&data_[o]);
+  }
+
+  template<typename T> T GetStruct(uoffset_t o) const {
+    return reinterpret_cast<T>(&data_[o]);
+  }
+
+  const uint8_t *GetAddressOf(uoffset_t o) const { return &data_[o]; }
+  uint8_t *GetAddressOf(uoffset_t o) { return &data_[o]; }
+
+ private:
+  // private constructor & copy constructor: you obtain instances of this
+  // class by pointing to existing data only
+  Struct();
+  Struct(const Struct &);
+  Struct &operator=(const Struct &);
+
+  uint8_t data_[1];
+};
+
+// "tables" use an offset table (possibly shared) that allows fields to be
+// omitted and added at will, but uses an extra indirection to read.
+class Table {
+ public:
+  const uint8_t *GetVTable() const {
+    return data_ - ReadScalar<soffset_t>(data_);
+  }
+
+  // This gets the field offset for any of the functions below it, or 0
+  // if the field was not present.
+  voffset_t GetOptionalFieldOffset(voffset_t field) const {
+    // The vtable offset is always at the start.
+    auto vtable = GetVTable();
+    // The first element is the size of the vtable (fields + type id + itself).
+    auto vtsize = ReadScalar<voffset_t>(vtable);
+    // If the field we're accessing is outside the vtable, we're reading older
+    // data, so it's the same as if the offset was 0 (not present).
+    return field < vtsize ? ReadScalar<voffset_t>(vtable + field) : 0;
+  }
+
+  template<typename T> T GetField(voffset_t field, T defaultval) const {
+    auto field_offset = GetOptionalFieldOffset(field);
+    return field_offset ? ReadScalar<T>(data_ + field_offset) : defaultval;
+  }
+
+  template<typename P> P GetPointer(voffset_t field) {
+    auto field_offset = GetOptionalFieldOffset(field);
+    auto p = data_ + field_offset;
+    return field_offset ? reinterpret_cast<P>(p + ReadScalar<uoffset_t>(p))
+                        : nullptr;
+  }
+  template<typename P> P GetPointer(voffset_t field) const {
+    return const_cast<Table *>(this)->GetPointer<P>(field);
+  }
+
+  template<typename P> P GetStruct(voffset_t field) const {
+    auto field_offset = GetOptionalFieldOffset(field);
+    auto p = const_cast<uint8_t *>(data_ + field_offset);
+    return field_offset ? reinterpret_cast<P>(p) : nullptr;
+  }
+
+  template<typename T> bool SetField(voffset_t field, T val, T def) {
+    auto field_offset = GetOptionalFieldOffset(field);
+    if (!field_offset) return IsTheSameAs(val, def);
+    WriteScalar(data_ + field_offset, val);
+    return true;
+  }
+
+  bool SetPointer(voffset_t field, const uint8_t *val) {
+    auto field_offset = GetOptionalFieldOffset(field);
+    if (!field_offset) return false;
+    WriteScalar(data_ + field_offset,
+                static_cast<uoffset_t>(val - (data_ + field_offset)));
+    return true;
+  }
+
+  uint8_t *GetAddressOf(voffset_t field) {
+    auto field_offset = GetOptionalFieldOffset(field);
+    return field_offset ? data_ + field_offset : nullptr;
+  }
+  const uint8_t *GetAddressOf(voffset_t field) const {
+    return const_cast<Table *>(this)->GetAddressOf(field);
+  }
+
+  bool CheckField(voffset_t field) const {
+    return GetOptionalFieldOffset(field) != 0;
+  }
+
+  // Verify the vtable of this table.
+  // Call this once per table, followed by VerifyField once per field.
+  bool VerifyTableStart(Verifier &verifier) const {
+    return verifier.VerifyTableStart(data_);
+  }
+
+  // Verify a particular field.
+  template<typename T>
+  bool VerifyField(const Verifier &verifier, voffset_t field) const {
+    // Calling GetOptionalFieldOffset should be safe now thanks to
+    // VerifyTable().
+    auto field_offset = GetOptionalFieldOffset(field);
+    // Check the actual field.
+    return !field_offset || verifier.Verify<T>(data_, field_offset);
+  }
+
+  // VerifyField for required fields.
+  template<typename T>
+  bool VerifyFieldRequired(const Verifier &verifier, voffset_t field) const {
+    auto field_offset = GetOptionalFieldOffset(field);
+    return verifier.Check(field_offset != 0) &&
+           verifier.Verify<T>(data_, field_offset);
+  }
+
+  // Versions for offsets.
+  bool VerifyOffset(const Verifier &verifier, voffset_t field) const {
+    auto field_offset = GetOptionalFieldOffset(field);
+    return !field_offset || verifier.VerifyOffset(data_, field_offset);
+  }
+
+  bool VerifyOffsetRequired(const Verifier &verifier, voffset_t field) const {
+    auto field_offset = GetOptionalFieldOffset(field);
+    return verifier.Check(field_offset != 0) &&
+           verifier.VerifyOffset(data_, field_offset);
+  }
+
+ private:
+  // private constructor & copy constructor: you obtain instances of this
+  // class by pointing to existing data only
+  Table();
+  Table(const Table &other);
+  Table &operator=(const Table &);
+
+  uint8_t data_[1];
+};
+
+template<typename T>
+void FlatBufferBuilder::Required(Offset<T> table, voffset_t field) {
+  auto table_ptr = reinterpret_cast<const Table *>(buf_.data_at(table.o));
+  bool ok = table_ptr->GetOptionalFieldOffset(field) != 0;
+  // If this fails, the caller will show what field needs to be set.
+  FLATBUFFERS_ASSERT(ok);
+  (void)ok;
+}
+
+/// @brief This can compute the start of a FlatBuffer from a root pointer, i.e.
+/// it is the opposite transformation of GetRoot().
+/// This may be useful if you want to pass on a root and have the recipient
+/// delete the buffer afterwards.
+inline const uint8_t *GetBufferStartFromRootPointer(const void *root) {
+  auto table = reinterpret_cast<const Table *>(root);
+  auto vtable = table->GetVTable();
+  // Either the vtable is before the root or after the root.
+  auto start = (std::min)(vtable, reinterpret_cast<const uint8_t *>(root));
+  // Align to at least sizeof(uoffset_t).
+  start = reinterpret_cast<const uint8_t *>(reinterpret_cast<uintptr_t>(start) &
+                                            ~(sizeof(uoffset_t) - 1));
+  // Additionally, there may be a file_identifier in the buffer, and the root
+  // offset. The buffer may have been aligned to any size between
+  // sizeof(uoffset_t) and FLATBUFFERS_MAX_ALIGNMENT (see "force_align").
+  // Sadly, the exact alignment is only known when constructing the buffer,
+  // since it depends on the presence of values with said alignment properties.
+  // So instead, we simply look at the next uoffset_t values (root,
+  // file_identifier, and alignment padding) to see which points to the root.
+  // None of the other values can "impersonate" the root since they will either
+  // be 0 or four ASCII characters.
+  static_assert(FlatBufferBuilder::kFileIdentifierLength == sizeof(uoffset_t),
+                "file_identifier is assumed to be the same size as uoffset_t");
+  for (auto possible_roots = FLATBUFFERS_MAX_ALIGNMENT / sizeof(uoffset_t) + 1;
+       possible_roots; possible_roots--) {
+    start -= sizeof(uoffset_t);
+    if (ReadScalar<uoffset_t>(start) + start ==
+        reinterpret_cast<const uint8_t *>(root))
+      return start;
+  }
+  // We didn't find the root, either the "root" passed isn't really a root,
+  // or the buffer is corrupt.
+  // Assert, because calling this function with bad data may cause reads
+  // outside of buffer boundaries.
+  FLATBUFFERS_ASSERT(false);
+  return nullptr;
+}
+
+/// @brief This return the prefixed size of a FlatBuffer.
+inline uoffset_t GetPrefixedSize(const uint8_t *buf) {
+  return ReadScalar<uoffset_t>(buf);
+}
+
+// Base class for native objects (FlatBuffer data de-serialized into native
+// C++ data structures).
+// Contains no functionality, purely documentative.
+struct NativeTable {};
+
+/// @brief Function types to be used with resolving hashes into objects and
+/// back again. The resolver gets a pointer to a field inside an object API
+/// object that is of the type specified in the schema using the attribute
+/// `cpp_type` (it is thus important whatever you write to this address
+/// matches that type). The value of this field is initially null, so you
+/// may choose to implement a delayed binding lookup using this function
+/// if you wish. The resolver does the opposite lookup, for when the object
+/// is being serialized again.
+typedef uint64_t hash_value_t;
+// clang-format off
+#if defined(FLATBUFFERS_CPP98_STL) || defined(FLATBUFFERS_CHRE)
+  typedef void (*resolver_function_t)(void **pointer_adr, hash_value_t hash);
+  typedef hash_value_t (*rehasher_function_t)(void *pointer);
+#else
+  typedef std::function<void (void **pointer_adr, hash_value_t hash)>
+          resolver_function_t;
+  typedef std::function<hash_value_t (void *pointer)> rehasher_function_t;
+#endif
+// clang-format on
+
+// Helper function to test if a field is present, using any of the field
+// enums in the generated code.
+// `table` must be a generated table type. Since this is a template parameter,
+// this is not typechecked to be a subclass of Table, so beware!
+// Note: this function will return false for fields equal to the default
+// value, since they're not stored in the buffer (unless force_defaults was
+// used).
+template<typename T>
+bool IsFieldPresent(const T *table, typename T::FlatBuffersVTableOffset field) {
+  // Cast, since Table is a private baseclass of any table types.
+  return reinterpret_cast<const Table *>(table)->CheckField(
+      static_cast<voffset_t>(field));
+}
+
+// Utility function for reverse lookups on the EnumNames*() functions
+// (in the generated C++ code)
+// names must be NULL terminated.
+inline int LookupEnum(const char **names, const char *name) {
+  for (const char **p = names; *p; p++)
+    if (!strcmp(*p, name)) return static_cast<int>(p - names);
+  return -1;
+}
+
+// These macros allow us to layout a struct with a guarantee that they'll end
+// up looking the same on different compilers and platforms.
+// It does this by disallowing the compiler to do any padding, and then
+// does padding itself by inserting extra padding fields that make every
+// element aligned to its own size.
+// Additionally, it manually sets the alignment of the struct as a whole,
+// which is typically its largest element, or a custom size set in the schema
+// by the force_align attribute.
+// These are used in the generated code only.
+
+// clang-format off
+#if defined(_MSC_VER)
+  #define FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(alignment) \
+    __pragma(pack(1)) \
+    struct __declspec(align(alignment))
+  #define FLATBUFFERS_STRUCT_END(name, size) \
+    __pragma(pack()) \
+    static_assert(sizeof(name) == size, "compiler breaks packing rules")
+#elif defined(__GNUC__) || defined(__clang__) || defined(__ICCARM__)
+  #define FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(alignment) \
+    _Pragma("pack(1)") \
+    struct __attribute__((aligned(alignment)))
+  #define FLATBUFFERS_STRUCT_END(name, size) \
+    _Pragma("pack()") \
+    static_assert(sizeof(name) == size, "compiler breaks packing rules")
+#else
+  #error Unknown compiler, please define structure alignment macros
+#endif
+// clang-format on
+
+// Minimal reflection via code generation.
+// Besides full-fat reflection (see reflection.h) and parsing/printing by
+// loading schemas (see idl.h), we can also have code generation for mimimal
+// reflection data which allows pretty-printing and other uses without needing
+// a schema or a parser.
+// Generate code with --reflect-types (types only) or --reflect-names (names
+// also) to enable.
+// See minireflect.h for utilities using this functionality.
+
+// These types are organized slightly differently as the ones in idl.h.
+enum SequenceType { ST_TABLE, ST_STRUCT, ST_UNION, ST_ENUM };
+
+// Scalars have the same order as in idl.h
+// clang-format off
+#define FLATBUFFERS_GEN_ELEMENTARY_TYPES(ET) \
+  ET(ET_UTYPE) \
+  ET(ET_BOOL) \
+  ET(ET_CHAR) \
+  ET(ET_UCHAR) \
+  ET(ET_SHORT) \
+  ET(ET_USHORT) \
+  ET(ET_INT) \
+  ET(ET_UINT) \
+  ET(ET_LONG) \
+  ET(ET_ULONG) \
+  ET(ET_FLOAT) \
+  ET(ET_DOUBLE) \
+  ET(ET_STRING) \
+  ET(ET_SEQUENCE)  // See SequenceType.
+
+enum ElementaryType {
+  #define FLATBUFFERS_ET(E) E,
+    FLATBUFFERS_GEN_ELEMENTARY_TYPES(FLATBUFFERS_ET)
+  #undef FLATBUFFERS_ET
+};
+
+inline const char * const *ElementaryTypeNames() {
+  static const char * const names[] = {
+    #define FLATBUFFERS_ET(E) #E,
+      FLATBUFFERS_GEN_ELEMENTARY_TYPES(FLATBUFFERS_ET)
+    #undef FLATBUFFERS_ET
+  };
+  return names;
+}
+// clang-format on
+
+// Basic type info cost just 16bits per field!
+struct TypeCode {
+  uint16_t base_type : 4;  // ElementaryType
+  uint16_t is_vector : 1;
+  int16_t sequence_ref : 11;  // Index into type_refs below, or -1 for none.
+};
+
+static_assert(sizeof(TypeCode) == 2, "TypeCode");
+
+struct TypeTable;
+
+// Signature of the static method present in each type.
+typedef const TypeTable *(*TypeFunction)();
+
+struct TypeTable {
+  SequenceType st;
+  size_t num_elems;  // of type_codes, values, names (but not type_refs).
+  const TypeCode *type_codes;     // num_elems count
+  const TypeFunction *type_refs;  // less than num_elems entries (see TypeCode).
+  const int64_t *values;  // Only set for non-consecutive enum/union or structs.
+  const char *const *names;  // Only set if compiled with --reflect-names.
+};
+
+// String which identifies the current version of FlatBuffers.
+// flatbuffer_version_string is used by Google developers to identify which
+// applications uploaded to Google Play are using this library.  This allows
+// the development team at Google to determine the popularity of the library.
+// How it works: Applications that are uploaded to the Google Play Store are
+// scanned for this version string.  We track which applications are using it
+// to measure popularity.  You are free to remove it (of course) but we would
+// appreciate if you left it in.
+
+// Weak linkage is culled by VS & doesn't work on cygwin.
+// clang-format off
+#if !defined(_WIN32) && !defined(__CYGWIN__)
+
+extern volatile __attribute__((weak)) const char *flatbuffer_version_string;
+volatile __attribute__((weak)) const char *flatbuffer_version_string =
+  "FlatBuffers "
+  FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MAJOR) "."
+  FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MINOR) "."
+  FLATBUFFERS_STRING(FLATBUFFERS_VERSION_REVISION);
+
+#endif  // !defined(_WIN32) && !defined(__CYGWIN__)
+
+#define FLATBUFFERS_DEFINE_BITMASK_OPERATORS(E, T)\
+    inline E operator | (E lhs, E rhs){\
+        return E(T(lhs) | T(rhs));\
+    }\
+    inline E operator & (E lhs, E rhs){\
+        return E(T(lhs) & T(rhs));\
+    }\
+    inline E operator ^ (E lhs, E rhs){\
+        return E(T(lhs) ^ T(rhs));\
+    }\
+    inline E operator ~ (E lhs){\
+        return E(~T(lhs));\
+    }\
+    inline E operator |= (E &lhs, E rhs){\
+        lhs = lhs | rhs;\
+        return lhs;\
+    }\
+    inline E operator &= (E &lhs, E rhs){\
+        lhs = lhs & rhs;\
+        return lhs;\
+    }\
+    inline E operator ^= (E &lhs, E rhs){\
+        lhs = lhs ^ rhs;\
+        return lhs;\
+    }\
+    inline bool operator !(E rhs) \
+    {\
+        return !bool(T(rhs)); \
+    }
+/// @endcond
+}  // namespace flatbuffers
+
+// clang-format on
+
+#endif  // FLATBUFFERS_H_
diff --git a/external/flatbuffers/include/flatbuffers/stl_emulation.h b/external/flatbuffers/include/flatbuffers_v1.12/stl_emulation.h
similarity index 100%
rename from external/flatbuffers/include/flatbuffers/stl_emulation.h
rename to external/flatbuffers/include/flatbuffers_v1.12/stl_emulation.h
diff --git a/external/kiss_fft/_kiss_fft_guts.h b/external/kiss_fft/_kiss_fft_guts.h
index e83771f..6aa102d 100644
--- a/external/kiss_fft/_kiss_fft_guts.h
+++ b/external/kiss_fft/_kiss_fft_guts.h
@@ -55,9 +55,13 @@
 #define SAMP_MIN -SAMP_MAX
 
 #if defined(CHECK_OVERFLOW)
+#ifdef CHRE_KISS_FFT_CAN_USE_STDIO
 #  define CHECK_OVERFLOW_OP(a,op,b)  \
 	if ( (SAMPPROD)(a) op (SAMPPROD)(b) > SAMP_MAX || (SAMPPROD)(a) op (SAMPPROD)(b) < SAMP_MIN ) { \
 		fprintf(stderr,"WARNING:overflow @ " __FILE__ "(%d): (%d " #op" %d) = %ld\n",__LINE__,(a),(b),(SAMPPROD)(a) op (SAMPPROD)(b) );  }
+#else
+#define CHECK_OVERFLOW(a, op, b) {}
+#endif
 #endif
 
 
@@ -145,10 +149,13 @@
 	}while(0)
 
 
+#ifdef CHRE_KISS_FFT_CAN_USE_STDIO
 /* a debugging function */
 #define pcpx(c)\
     fprintf(stderr,"%g + %gi\n",(double)((c)->r),(double)((c)->i) )
-
+#else
+#define pcpx(c) {}
+#endif
 
 #ifdef KISS_FFT_USE_ALLOCA
 // define this to allow use of alloca instead of malloc for temporary buffers
diff --git a/external/kiss_fft/kiss_fft.c b/external/kiss_fft/kiss_fft.c
index 7f439c2..c1ea7e3 100644
--- a/external/kiss_fft/kiss_fft.c
+++ b/external/kiss_fft/kiss_fft.c
@@ -18,6 +18,14 @@
  fixed or floating point complex numbers.  It also delares the kf_ internal functions.
  */
 
+// CHRE modifications begin
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wcast-align"
+#pragma clang diagnostic ignored "-Wbad-function-cast"
+#endif
+// CHRE modifications end
+
 static void kf_bfly2(
         kiss_fft_cpx * Fout,
         const size_t fstride,
@@ -406,3 +414,9 @@
     }
     return n;
 }
+
+// CHRE modifications begin
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
+// CHRE modifications end
diff --git a/external/kiss_fft/kiss_fftr.c b/external/kiss_fft/kiss_fftr.c
index f31f23e..0dad8a2 100644
--- a/external/kiss_fft/kiss_fftr.c
+++ b/external/kiss_fft/kiss_fftr.c
@@ -15,6 +15,14 @@
 #include "kiss_fftr.h"
 #include "_kiss_fft_guts.h"
 
+// CHRE modifications begin
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wcast-align"
+#pragma clang diagnostic ignored "-Wbad-function-cast"
+#endif
+// CHRE modifications end
+
 struct kiss_fftr_state{
     kiss_fft_cfg substate;
     kiss_fft_cpx * tmpbuf;
@@ -31,7 +39,9 @@
     size_t subsize, memneeded;
 
     if (nfft & 1) {
+#if CHRE_KISS_FFT_CAN_USE_STDIO
         fprintf(stderr,"Real FFT optimization must be even.\n");
+#endif
         return NULL;
     }
     nfft >>= 1;
@@ -71,8 +81,12 @@
     kiss_fft_cpx fpnk,fpk,f1k,f2k,tw,tdc;
 
     if ( st->substate->inverse) {
+#if CHRE_KISS_FFT_CAN_USE_STDIO
         fprintf(stderr,"kiss fft usage error: improper alloc\n");
         exit(1);
+#else
+        return;
+#endif
     }
 
     ncfft = st->substate->nfft;
@@ -126,8 +140,12 @@
     int k, ncfft;
 
     if (st->substate->inverse == 0) {
+#if CHRE_KISS_FFT_CAN_USE_STDIO
         fprintf (stderr, "kiss fft usage error: improper alloc\n");
         exit (1);
+#else
+        return;
+#endif
     }
 
     ncfft = st->substate->nfft;
@@ -157,3 +175,9 @@
     }
     kiss_fft (st->substate, st->tmpbuf, (kiss_fft_cpx *) timedata);
 }
+
+// CHRE modifications begin
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
+// CHRE modifications end
diff --git a/host/common/include/chre_host/daemon_base.h b/host/common/include/chre_host/daemon_base.h
index 7423849..469f9a8 100644
--- a/host/common/include/chre_host/daemon_base.h
+++ b/host/common/include/chre_host/daemon_base.h
@@ -66,7 +66,8 @@
    * @param message A buffer containing the message
    * @param messageLen size of the message buffer in bytes
    */
-  virtual void onMessageReceived(unsigned char *message, size_t messageLen) = 0;
+  virtual void onMessageReceived(const unsigned char *message,
+                                 size_t messageLen) = 0;
 
   /**
    * Function to query if a graceful shutdown of CHRE was requested
@@ -77,6 +78,16 @@
     return mChreShutdownRequested;
   }
 
+  /**
+   * Loads the supplied file into the provided buffer.
+   *
+   * @param filename The name of the file to load.
+   * @param buffer The buffer to load into.
+   * @return true if successful, false otherwise.
+   */
+  static bool readFileContents(const char *filename,
+                               std::vector<uint8_t> *buffer);
+
  protected:
   //! The host ID to use when preloading nanoapps. This is used before the
   //! server is started and is sufficiently high enough so as to not collide
@@ -112,8 +123,9 @@
    * @param name The filename of the nanoapp to load.
    * @param transactionId The transaction ID to use when loading the app.
    */
-  void loadPreloadedNanoapp(const std::string &directory,
-                            const std::string &name, uint32_t transactionId);
+  virtual void loadPreloadedNanoapp(const std::string &directory,
+                                    const std::string &name,
+                                    uint32_t transactionId);
 
   /**
    * Sends a preloaded nanoapp filename / metadata to CHRE.
@@ -165,20 +177,11 @@
                              bool logOnError);
 
   /**
-   * Loads the supplied file into the provided buffer.
-   *
-   * @param filename The name of the file to load.
-   * @param buffer The buffer to load into.
-   * @return true if successful, false otherwise.
-   */
-  bool readFileContents(const char *filename, std::vector<uint8_t> *buffer);
-
-  /**
    * Handles a message that is directed towards the daemon.
    *
    * @param message The message sent to the daemon.
    */
-  void handleDaemonMessage(const uint8_t *message);
+  virtual void handleDaemonMessage(const uint8_t *message);
 
  private:
   //! Set to true when we request a graceful shutdown of CHRE
diff --git a/host/common/include/chre_host/generated/host_messages_generated.h b/host/common/include/chre_host/generated/host_messages_generated.h
index 4e280b6..237545a 100644
--- a/host/common/include/chre_host/generated/host_messages_generated.h
+++ b/host/common/include/chre_host/generated/host_messages_generated.h
@@ -10,85 +10,65 @@
 namespace fbs {
 
 struct NanoappMessage;
-struct NanoappMessageBuilder;
 struct NanoappMessageT;
 
 struct HubInfoRequest;
-struct HubInfoRequestBuilder;
 struct HubInfoRequestT;
 
 struct HubInfoResponse;
-struct HubInfoResponseBuilder;
 struct HubInfoResponseT;
 
 struct NanoappListRequest;
-struct NanoappListRequestBuilder;
 struct NanoappListRequestT;
 
 struct NanoappListEntry;
-struct NanoappListEntryBuilder;
 struct NanoappListEntryT;
 
 struct NanoappListResponse;
-struct NanoappListResponseBuilder;
 struct NanoappListResponseT;
 
 struct LoadNanoappRequest;
-struct LoadNanoappRequestBuilder;
 struct LoadNanoappRequestT;
 
 struct LoadNanoappResponse;
-struct LoadNanoappResponseBuilder;
 struct LoadNanoappResponseT;
 
 struct UnloadNanoappRequest;
-struct UnloadNanoappRequestBuilder;
 struct UnloadNanoappRequestT;
 
 struct UnloadNanoappResponse;
-struct UnloadNanoappResponseBuilder;
 struct UnloadNanoappResponseT;
 
 struct LogMessage;
-struct LogMessageBuilder;
 struct LogMessageT;
 
 struct TimeSyncMessage;
-struct TimeSyncMessageBuilder;
 struct TimeSyncMessageT;
 
 struct DebugDumpRequest;
-struct DebugDumpRequestBuilder;
 struct DebugDumpRequestT;
 
 struct DebugDumpData;
-struct DebugDumpDataBuilder;
 struct DebugDumpDataT;
 
 struct DebugDumpResponse;
-struct DebugDumpResponseBuilder;
 struct DebugDumpResponseT;
 
 struct TimeSyncRequest;
-struct TimeSyncRequestBuilder;
 struct TimeSyncRequestT;
 
 struct LowPowerMicAccessRequest;
-struct LowPowerMicAccessRequestBuilder;
 struct LowPowerMicAccessRequestT;
 
 struct LowPowerMicAccessRelease;
-struct LowPowerMicAccessReleaseBuilder;
 struct LowPowerMicAccessReleaseT;
 
 struct SettingChangeMessage;
-struct SettingChangeMessageBuilder;
 struct SettingChangeMessageT;
 
 struct HostAddress;
 
 struct MessageContainer;
-struct MessageContainerBuilder;
 struct MessageContainerT;
 
 /// An enum describing the setting type.
@@ -98,15 +78,8 @@
   MAX = LOCATION
 };
 
-inline const Setting (&EnumValuesSetting())[1] {
-  static const Setting values[] = {
-    Setting::LOCATION
-  };
-  return values;
-}
-
-inline const char * const *EnumNamesSetting() {
-  static const char * const names[2] = {
+inline const char **EnumNamesSetting() {
+  static const char *names[] = {
     "LOCATION",
     nullptr
   };
@@ -114,8 +87,7 @@
 }
 
 inline const char *EnumNameSetting(Setting e) {
-  if (flatbuffers::IsOutRange(e, Setting::LOCATION, Setting::LOCATION)) return "";
-  const size_t index = static_cast<size_t>(e);
+  const size_t index = static_cast<int>(e);
   return EnumNamesSetting()[index];
 }
 
@@ -127,16 +99,8 @@
   MAX = ENABLED
 };
 
-inline const SettingState (&EnumValuesSettingState())[2] {
-  static const SettingState values[] = {
-    SettingState::DISABLED,
-    SettingState::ENABLED
-  };
-  return values;
-}
-
-inline const char * const *EnumNamesSettingState() {
-  static const char * const names[3] = {
+inline const char **EnumNamesSettingState() {
+  static const char *names[] = {
     "DISABLED",
     "ENABLED",
     nullptr
@@ -145,8 +109,7 @@
 }
 
 inline const char *EnumNameSettingState(SettingState e) {
-  if (flatbuffers::IsOutRange(e, SettingState::DISABLED, SettingState::ENABLED)) return "";
-  const size_t index = static_cast<size_t>(e);
+  const size_t index = static_cast<int>(e);
   return EnumNamesSettingState()[index];
 }
 
@@ -176,33 +139,8 @@
   MAX = SettingChangeMessage
 };
 
-inline const ChreMessage (&EnumValuesChreMessage())[19] {
-  static const ChreMessage values[] = {
-    ChreMessage::NONE,
-    ChreMessage::NanoappMessage,
-    ChreMessage::HubInfoRequest,
-    ChreMessage::HubInfoResponse,
-    ChreMessage::NanoappListRequest,
-    ChreMessage::NanoappListResponse,
-    ChreMessage::LoadNanoappRequest,
-    ChreMessage::LoadNanoappResponse,
-    ChreMessage::UnloadNanoappRequest,
-    ChreMessage::UnloadNanoappResponse,
-    ChreMessage::LogMessage,
-    ChreMessage::TimeSyncMessage,
-    ChreMessage::DebugDumpRequest,
-    ChreMessage::DebugDumpData,
-    ChreMessage::DebugDumpResponse,
-    ChreMessage::TimeSyncRequest,
-    ChreMessage::LowPowerMicAccessRequest,
-    ChreMessage::LowPowerMicAccessRelease,
-    ChreMessage::SettingChangeMessage
-  };
-  return values;
-}
-
-inline const char * const *EnumNamesChreMessage() {
-  static const char * const names[20] = {
+inline const char **EnumNamesChreMessage() {
+  static const char *names[] = {
     "NONE",
     "NanoappMessage",
     "HubInfoRequest",
@@ -228,8 +166,7 @@
 }
 
 inline const char *EnumNameChreMessage(ChreMessage e) {
-  if (flatbuffers::IsOutRange(e, ChreMessage::NONE, ChreMessage::SettingChangeMessage)) return "";
-  const size_t index = static_cast<size_t>(e);
+  const size_t index = static_cast<int>(e);
   return EnumNamesChreMessage()[index];
 }
 
@@ -237,266 +174,190 @@
   static const ChreMessage enum_value = ChreMessage::NONE;
 };
 
-template<> struct ChreMessageTraits<chre::fbs::NanoappMessage> {
+template<> struct ChreMessageTraits<NanoappMessage> {
   static const ChreMessage enum_value = ChreMessage::NanoappMessage;
 };
 
-template<> struct ChreMessageTraits<chre::fbs::HubInfoRequest> {
+template<> struct ChreMessageTraits<HubInfoRequest> {
   static const ChreMessage enum_value = ChreMessage::HubInfoRequest;
 };
 
-template<> struct ChreMessageTraits<chre::fbs::HubInfoResponse> {
+template<> struct ChreMessageTraits<HubInfoResponse> {
   static const ChreMessage enum_value = ChreMessage::HubInfoResponse;
 };
 
-template<> struct ChreMessageTraits<chre::fbs::NanoappListRequest> {
+template<> struct ChreMessageTraits<NanoappListRequest> {
   static const ChreMessage enum_value = ChreMessage::NanoappListRequest;
 };
 
-template<> struct ChreMessageTraits<chre::fbs::NanoappListResponse> {
+template<> struct ChreMessageTraits<NanoappListResponse> {
   static const ChreMessage enum_value = ChreMessage::NanoappListResponse;
 };
 
-template<> struct ChreMessageTraits<chre::fbs::LoadNanoappRequest> {
+template<> struct ChreMessageTraits<LoadNanoappRequest> {
   static const ChreMessage enum_value = ChreMessage::LoadNanoappRequest;
 };
 
-template<> struct ChreMessageTraits<chre::fbs::LoadNanoappResponse> {
+template<> struct ChreMessageTraits<LoadNanoappResponse> {
   static const ChreMessage enum_value = ChreMessage::LoadNanoappResponse;
 };
 
-template<> struct ChreMessageTraits<chre::fbs::UnloadNanoappRequest> {
+template<> struct ChreMessageTraits<UnloadNanoappRequest> {
   static const ChreMessage enum_value = ChreMessage::UnloadNanoappRequest;
 };
 
-template<> struct ChreMessageTraits<chre::fbs::UnloadNanoappResponse> {
+template<> struct ChreMessageTraits<UnloadNanoappResponse> {
   static const ChreMessage enum_value = ChreMessage::UnloadNanoappResponse;
 };
 
-template<> struct ChreMessageTraits<chre::fbs::LogMessage> {
+template<> struct ChreMessageTraits<LogMessage> {
   static const ChreMessage enum_value = ChreMessage::LogMessage;
 };
 
-template<> struct ChreMessageTraits<chre::fbs::TimeSyncMessage> {
+template<> struct ChreMessageTraits<TimeSyncMessage> {
   static const ChreMessage enum_value = ChreMessage::TimeSyncMessage;
 };
 
-template<> struct ChreMessageTraits<chre::fbs::DebugDumpRequest> {
+template<> struct ChreMessageTraits<DebugDumpRequest> {
   static const ChreMessage enum_value = ChreMessage::DebugDumpRequest;
 };
 
-template<> struct ChreMessageTraits<chre::fbs::DebugDumpData> {
+template<> struct ChreMessageTraits<DebugDumpData> {
   static const ChreMessage enum_value = ChreMessage::DebugDumpData;
 };
 
-template<> struct ChreMessageTraits<chre::fbs::DebugDumpResponse> {
+template<> struct ChreMessageTraits<DebugDumpResponse> {
   static const ChreMessage enum_value = ChreMessage::DebugDumpResponse;
 };
 
-template<> struct ChreMessageTraits<chre::fbs::TimeSyncRequest> {
+template<> struct ChreMessageTraits<TimeSyncRequest> {
   static const ChreMessage enum_value = ChreMessage::TimeSyncRequest;
 };
 
-template<> struct ChreMessageTraits<chre::fbs::LowPowerMicAccessRequest> {
+template<> struct ChreMessageTraits<LowPowerMicAccessRequest> {
   static const ChreMessage enum_value = ChreMessage::LowPowerMicAccessRequest;
 };
 
-template<> struct ChreMessageTraits<chre::fbs::LowPowerMicAccessRelease> {
+template<> struct ChreMessageTraits<LowPowerMicAccessRelease> {
   static const ChreMessage enum_value = ChreMessage::LowPowerMicAccessRelease;
 };
 
-template<> struct ChreMessageTraits<chre::fbs::SettingChangeMessage> {
+template<> struct ChreMessageTraits<SettingChangeMessage> {
   static const ChreMessage enum_value = ChreMessage::SettingChangeMessage;
 };
 
 struct ChreMessageUnion {
   ChreMessage type;
-  void *value;
+  flatbuffers::NativeTable *table;
 
-  ChreMessageUnion() : type(ChreMessage::NONE), value(nullptr) {}
-  ChreMessageUnion(ChreMessageUnion&& u) FLATBUFFERS_NOEXCEPT :
-    type(ChreMessage::NONE), value(nullptr)
-    { std::swap(type, u.type); std::swap(value, u.value); }
+  ChreMessageUnion() : type(ChreMessage::NONE), table(nullptr) {}
+  ChreMessageUnion(ChreMessageUnion&& u):
+    type(std::move(u.type)), table(std::move(u.table)) {}
   ChreMessageUnion(const ChreMessageUnion &);
-  ChreMessageUnion &operator=(const ChreMessageUnion &u)
-    { ChreMessageUnion t(u); std::swap(type, t.type); std::swap(value, t.value); return *this; }
-  ChreMessageUnion &operator=(ChreMessageUnion &&u) FLATBUFFERS_NOEXCEPT
-    { std::swap(type, u.type); std::swap(value, u.value); return *this; }
+  ChreMessageUnion &operator=(const ChreMessageUnion &);
   ~ChreMessageUnion() { Reset(); }
 
   void Reset();
 
-#ifndef FLATBUFFERS_CPP98_STL
   template <typename T>
-  void Set(T&& val) {
-    using RT = typename std::remove_reference<T>::type;
+  void Set(T&& value) {
     Reset();
-    type = ChreMessageTraits<typename RT::TableType>::enum_value;
+    type = ChreMessageTraits<typename T::TableType>::enum_value;
     if (type != ChreMessage::NONE) {
-      value = new RT(std::forward<T>(val));
+      table = new T(std::forward<T>(value));
     }
   }
-#endif  // FLATBUFFERS_CPP98_STL
 
-  static void *UnPack(const void *obj, ChreMessage type, const flatbuffers::resolver_function_t *resolver);
+  static flatbuffers::NativeTable *UnPack(const void *obj, ChreMessage type, const flatbuffers::resolver_function_t *resolver);
   flatbuffers::Offset<void> Pack(flatbuffers::FlatBufferBuilder &_fbb, const flatbuffers::rehasher_function_t *_rehasher = nullptr) const;
 
-  chre::fbs::NanoappMessageT *AsNanoappMessage() {
+  NanoappMessageT *AsNanoappMessage() {
     return type == ChreMessage::NanoappMessage ?
-      reinterpret_cast<chre::fbs::NanoappMessageT *>(value) : nullptr;
+      reinterpret_cast<NanoappMessageT *>(table) : nullptr;
   }
-  const chre::fbs::NanoappMessageT *AsNanoappMessage() const {
-    return type == ChreMessage::NanoappMessage ?
-      reinterpret_cast<const chre::fbs::NanoappMessageT *>(value) : nullptr;
-  }
-  chre::fbs::HubInfoRequestT *AsHubInfoRequest() {
+  HubInfoRequestT *AsHubInfoRequest() {
     return type == ChreMessage::HubInfoRequest ?
-      reinterpret_cast<chre::fbs::HubInfoRequestT *>(value) : nullptr;
+      reinterpret_cast<HubInfoRequestT *>(table) : nullptr;
   }
-  const chre::fbs::HubInfoRequestT *AsHubInfoRequest() const {
-    return type == ChreMessage::HubInfoRequest ?
-      reinterpret_cast<const chre::fbs::HubInfoRequestT *>(value) : nullptr;
-  }
-  chre::fbs::HubInfoResponseT *AsHubInfoResponse() {
+  HubInfoResponseT *AsHubInfoResponse() {
     return type == ChreMessage::HubInfoResponse ?
-      reinterpret_cast<chre::fbs::HubInfoResponseT *>(value) : nullptr;
+      reinterpret_cast<HubInfoResponseT *>(table) : nullptr;
   }
-  const chre::fbs::HubInfoResponseT *AsHubInfoResponse() const {
-    return type == ChreMessage::HubInfoResponse ?
-      reinterpret_cast<const chre::fbs::HubInfoResponseT *>(value) : nullptr;
-  }
-  chre::fbs::NanoappListRequestT *AsNanoappListRequest() {
+  NanoappListRequestT *AsNanoappListRequest() {
     return type == ChreMessage::NanoappListRequest ?
-      reinterpret_cast<chre::fbs::NanoappListRequestT *>(value) : nullptr;
+      reinterpret_cast<NanoappListRequestT *>(table) : nullptr;
   }
-  const chre::fbs::NanoappListRequestT *AsNanoappListRequest() const {
-    return type == ChreMessage::NanoappListRequest ?
-      reinterpret_cast<const chre::fbs::NanoappListRequestT *>(value) : nullptr;
-  }
-  chre::fbs::NanoappListResponseT *AsNanoappListResponse() {
+  NanoappListResponseT *AsNanoappListResponse() {
     return type == ChreMessage::NanoappListResponse ?
-      reinterpret_cast<chre::fbs::NanoappListResponseT *>(value) : nullptr;
+      reinterpret_cast<NanoappListResponseT *>(table) : nullptr;
   }
-  const chre::fbs::NanoappListResponseT *AsNanoappListResponse() const {
-    return type == ChreMessage::NanoappListResponse ?
-      reinterpret_cast<const chre::fbs::NanoappListResponseT *>(value) : nullptr;
-  }
-  chre::fbs::LoadNanoappRequestT *AsLoadNanoappRequest() {
+  LoadNanoappRequestT *AsLoadNanoappRequest() {
     return type == ChreMessage::LoadNanoappRequest ?
-      reinterpret_cast<chre::fbs::LoadNanoappRequestT *>(value) : nullptr;
+      reinterpret_cast<LoadNanoappRequestT *>(table) : nullptr;
   }
-  const chre::fbs::LoadNanoappRequestT *AsLoadNanoappRequest() const {
-    return type == ChreMessage::LoadNanoappRequest ?
-      reinterpret_cast<const chre::fbs::LoadNanoappRequestT *>(value) : nullptr;
-  }
-  chre::fbs::LoadNanoappResponseT *AsLoadNanoappResponse() {
+  LoadNanoappResponseT *AsLoadNanoappResponse() {
     return type == ChreMessage::LoadNanoappResponse ?
-      reinterpret_cast<chre::fbs::LoadNanoappResponseT *>(value) : nullptr;
+      reinterpret_cast<LoadNanoappResponseT *>(table) : nullptr;
   }
-  const chre::fbs::LoadNanoappResponseT *AsLoadNanoappResponse() const {
-    return type == ChreMessage::LoadNanoappResponse ?
-      reinterpret_cast<const chre::fbs::LoadNanoappResponseT *>(value) : nullptr;
-  }
-  chre::fbs::UnloadNanoappRequestT *AsUnloadNanoappRequest() {
+  UnloadNanoappRequestT *AsUnloadNanoappRequest() {
     return type == ChreMessage::UnloadNanoappRequest ?
-      reinterpret_cast<chre::fbs::UnloadNanoappRequestT *>(value) : nullptr;
+      reinterpret_cast<UnloadNanoappRequestT *>(table) : nullptr;
   }
-  const chre::fbs::UnloadNanoappRequestT *AsUnloadNanoappRequest() const {
-    return type == ChreMessage::UnloadNanoappRequest ?
-      reinterpret_cast<const chre::fbs::UnloadNanoappRequestT *>(value) : nullptr;
-  }
-  chre::fbs::UnloadNanoappResponseT *AsUnloadNanoappResponse() {
+  UnloadNanoappResponseT *AsUnloadNanoappResponse() {
     return type == ChreMessage::UnloadNanoappResponse ?
-      reinterpret_cast<chre::fbs::UnloadNanoappResponseT *>(value) : nullptr;
+      reinterpret_cast<UnloadNanoappResponseT *>(table) : nullptr;
   }
-  const chre::fbs::UnloadNanoappResponseT *AsUnloadNanoappResponse() const {
-    return type == ChreMessage::UnloadNanoappResponse ?
-      reinterpret_cast<const chre::fbs::UnloadNanoappResponseT *>(value) : nullptr;
-  }
-  chre::fbs::LogMessageT *AsLogMessage() {
+  LogMessageT *AsLogMessage() {
     return type == ChreMessage::LogMessage ?
-      reinterpret_cast<chre::fbs::LogMessageT *>(value) : nullptr;
+      reinterpret_cast<LogMessageT *>(table) : nullptr;
   }
-  const chre::fbs::LogMessageT *AsLogMessage() const {
-    return type == ChreMessage::LogMessage ?
-      reinterpret_cast<const chre::fbs::LogMessageT *>(value) : nullptr;
-  }
-  chre::fbs::TimeSyncMessageT *AsTimeSyncMessage() {
+  TimeSyncMessageT *AsTimeSyncMessage() {
     return type == ChreMessage::TimeSyncMessage ?
-      reinterpret_cast<chre::fbs::TimeSyncMessageT *>(value) : nullptr;
+      reinterpret_cast<TimeSyncMessageT *>(table) : nullptr;
   }
-  const chre::fbs::TimeSyncMessageT *AsTimeSyncMessage() const {
-    return type == ChreMessage::TimeSyncMessage ?
-      reinterpret_cast<const chre::fbs::TimeSyncMessageT *>(value) : nullptr;
-  }
-  chre::fbs::DebugDumpRequestT *AsDebugDumpRequest() {
+  DebugDumpRequestT *AsDebugDumpRequest() {
     return type == ChreMessage::DebugDumpRequest ?
-      reinterpret_cast<chre::fbs::DebugDumpRequestT *>(value) : nullptr;
+      reinterpret_cast<DebugDumpRequestT *>(table) : nullptr;
   }
-  const chre::fbs::DebugDumpRequestT *AsDebugDumpRequest() const {
-    return type == ChreMessage::DebugDumpRequest ?
-      reinterpret_cast<const chre::fbs::DebugDumpRequestT *>(value) : nullptr;
-  }
-  chre::fbs::DebugDumpDataT *AsDebugDumpData() {
+  DebugDumpDataT *AsDebugDumpData() {
     return type == ChreMessage::DebugDumpData ?
-      reinterpret_cast<chre::fbs::DebugDumpDataT *>(value) : nullptr;
+      reinterpret_cast<DebugDumpDataT *>(table) : nullptr;
   }
-  const chre::fbs::DebugDumpDataT *AsDebugDumpData() const {
-    return type == ChreMessage::DebugDumpData ?
-      reinterpret_cast<const chre::fbs::DebugDumpDataT *>(value) : nullptr;
-  }
-  chre::fbs::DebugDumpResponseT *AsDebugDumpResponse() {
+  DebugDumpResponseT *AsDebugDumpResponse() {
     return type == ChreMessage::DebugDumpResponse ?
-      reinterpret_cast<chre::fbs::DebugDumpResponseT *>(value) : nullptr;
+      reinterpret_cast<DebugDumpResponseT *>(table) : nullptr;
   }
-  const chre::fbs::DebugDumpResponseT *AsDebugDumpResponse() const {
-    return type == ChreMessage::DebugDumpResponse ?
-      reinterpret_cast<const chre::fbs::DebugDumpResponseT *>(value) : nullptr;
-  }
-  chre::fbs::TimeSyncRequestT *AsTimeSyncRequest() {
+  TimeSyncRequestT *AsTimeSyncRequest() {
     return type == ChreMessage::TimeSyncRequest ?
-      reinterpret_cast<chre::fbs::TimeSyncRequestT *>(value) : nullptr;
+      reinterpret_cast<TimeSyncRequestT *>(table) : nullptr;
   }
-  const chre::fbs::TimeSyncRequestT *AsTimeSyncRequest() const {
-    return type == ChreMessage::TimeSyncRequest ?
-      reinterpret_cast<const chre::fbs::TimeSyncRequestT *>(value) : nullptr;
-  }
-  chre::fbs::LowPowerMicAccessRequestT *AsLowPowerMicAccessRequest() {
+  LowPowerMicAccessRequestT *AsLowPowerMicAccessRequest() {
     return type == ChreMessage::LowPowerMicAccessRequest ?
-      reinterpret_cast<chre::fbs::LowPowerMicAccessRequestT *>(value) : nullptr;
+      reinterpret_cast<LowPowerMicAccessRequestT *>(table) : nullptr;
   }
-  const chre::fbs::LowPowerMicAccessRequestT *AsLowPowerMicAccessRequest() const {
-    return type == ChreMessage::LowPowerMicAccessRequest ?
-      reinterpret_cast<const chre::fbs::LowPowerMicAccessRequestT *>(value) : nullptr;
-  }
-  chre::fbs::LowPowerMicAccessReleaseT *AsLowPowerMicAccessRelease() {
+  LowPowerMicAccessReleaseT *AsLowPowerMicAccessRelease() {
     return type == ChreMessage::LowPowerMicAccessRelease ?
-      reinterpret_cast<chre::fbs::LowPowerMicAccessReleaseT *>(value) : nullptr;
+      reinterpret_cast<LowPowerMicAccessReleaseT *>(table) : nullptr;
   }
-  const chre::fbs::LowPowerMicAccessReleaseT *AsLowPowerMicAccessRelease() const {
-    return type == ChreMessage::LowPowerMicAccessRelease ?
-      reinterpret_cast<const chre::fbs::LowPowerMicAccessReleaseT *>(value) : nullptr;
-  }
-  chre::fbs::SettingChangeMessageT *AsSettingChangeMessage() {
+  SettingChangeMessageT *AsSettingChangeMessage() {
     return type == ChreMessage::SettingChangeMessage ?
-      reinterpret_cast<chre::fbs::SettingChangeMessageT *>(value) : nullptr;
-  }
-  const chre::fbs::SettingChangeMessageT *AsSettingChangeMessage() const {
-    return type == ChreMessage::SettingChangeMessage ?
-      reinterpret_cast<const chre::fbs::SettingChangeMessageT *>(value) : nullptr;
+      reinterpret_cast<SettingChangeMessageT *>(table) : nullptr;
   }
 };
 
 bool VerifyChreMessage(flatbuffers::Verifier &verifier, const void *obj, ChreMessage type);
 bool VerifyChreMessageVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types);
 
-FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(2) HostAddress FLATBUFFERS_FINAL_CLASS {
+MANUALLY_ALIGNED_STRUCT(2) HostAddress FLATBUFFERS_FINAL_CLASS {
  private:
   uint16_t client_id_;
 
  public:
   HostAddress() {
-    memset(static_cast<void *>(this), 0, sizeof(HostAddress));
+    memset(this, 0, sizeof(HostAddress));
+  }
+  HostAddress(const HostAddress &_o) {
+    memcpy(this, &_o, sizeof(HostAddress));
   }
   HostAddress(uint16_t _client_id)
       : client_id_(flatbuffers::EndianScalar(_client_id)) {
@@ -508,7 +369,7 @@
     flatbuffers::WriteScalar(&client_id_, _client_id);
   }
 };
-FLATBUFFERS_STRUCT_END(HostAddress, 2);
+STRUCT_END(HostAddress, 2);
 
 struct NanoappMessageT : public flatbuffers::NativeTable {
   typedef NanoappMessage TableType;
@@ -526,8 +387,7 @@
 /// Represents a message sent to/from a nanoapp from/to a client on the host
 struct NanoappMessage FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   typedef NanoappMessageT NativeTableType;
-  typedef NanoappMessageBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_APP_ID = 4,
     VT_MESSAGE_TYPE = 6,
     VT_HOST_ENDPOINT = 8,
@@ -537,13 +397,13 @@
     return GetField<uint64_t>(VT_APP_ID, 0);
   }
   bool mutate_app_id(uint64_t _app_id) {
-    return SetField<uint64_t>(VT_APP_ID, _app_id, 0);
+    return SetField(VT_APP_ID, _app_id);
   }
   uint32_t message_type() const {
     return GetField<uint32_t>(VT_MESSAGE_TYPE, 0);
   }
   bool mutate_message_type(uint32_t _message_type) {
-    return SetField<uint32_t>(VT_MESSAGE_TYPE, _message_type, 0);
+    return SetField(VT_MESSAGE_TYPE, _message_type);
   }
   /// Identifies the host-side endpoint on the host that sent or should receive
   /// this message. The default value is a special value defined in the HAL and
@@ -552,7 +412,7 @@
     return GetField<uint16_t>(VT_HOST_ENDPOINT, 65534);
   }
   bool mutate_host_endpoint(uint16_t _host_endpoint) {
-    return SetField<uint16_t>(VT_HOST_ENDPOINT, _host_endpoint, 65534);
+    return SetField(VT_HOST_ENDPOINT, _host_endpoint);
   }
   /// Vector containing arbitrary application-specific message data
   const flatbuffers::Vector<uint8_t> *message() const {
@@ -566,8 +426,8 @@
            VerifyField<uint64_t>(verifier, VT_APP_ID) &&
            VerifyField<uint32_t>(verifier, VT_MESSAGE_TYPE) &&
            VerifyField<uint16_t>(verifier, VT_HOST_ENDPOINT) &&
-           VerifyOffsetRequired(verifier, VT_MESSAGE) &&
-           verifier.VerifyVector(message()) &&
+           VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_MESSAGE) &&
+           verifier.Verify(message()) &&
            verifier.EndTable();
   }
   NanoappMessageT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
@@ -576,7 +436,6 @@
 };
 
 struct NanoappMessageBuilder {
-  typedef NanoappMessage Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
   void add_app_id(uint64_t app_id) {
@@ -591,13 +450,13 @@
   void add_message(flatbuffers::Offset<flatbuffers::Vector<uint8_t>> message) {
     fbb_.AddOffset(NanoappMessage::VT_MESSAGE, message);
   }
-  explicit NanoappMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  NanoappMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   NanoappMessageBuilder &operator=(const NanoappMessageBuilder &);
   flatbuffers::Offset<NanoappMessage> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 4);
     auto o = flatbuffers::Offset<NanoappMessage>(end);
     fbb_.Required(o, NanoappMessage::VT_MESSAGE);
     return o;
@@ -624,13 +483,12 @@
     uint32_t message_type = 0,
     uint16_t host_endpoint = 65534,
     const std::vector<uint8_t> *message = nullptr) {
-  auto message__ = message ? _fbb.CreateVector<uint8_t>(*message) : 0;
   return chre::fbs::CreateNanoappMessage(
       _fbb,
       app_id,
       message_type,
       host_endpoint,
-      message__);
+      message ? _fbb.CreateVector<uint8_t>(*message) : 0);
 }
 
 flatbuffers::Offset<NanoappMessage> CreateNanoappMessage(flatbuffers::FlatBufferBuilder &_fbb, const NanoappMessageT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
@@ -643,7 +501,6 @@
 
 struct HubInfoRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   typedef HubInfoRequestT NativeTableType;
-  typedef HubInfoRequestBuilder Builder;
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
            verifier.EndTable();
@@ -654,16 +511,15 @@
 };
 
 struct HubInfoRequestBuilder {
-  typedef HubInfoRequest Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
-  explicit HubInfoRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  HubInfoRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   HubInfoRequestBuilder &operator=(const HubInfoRequestBuilder &);
   flatbuffers::Offset<HubInfoRequest> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 0);
     auto o = flatbuffers::Offset<HubInfoRequest>(end);
     return o;
   }
@@ -706,8 +562,7 @@
 
 struct HubInfoResponse FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   typedef HubInfoResponseT NativeTableType;
-  typedef HubInfoResponseBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_NAME = 4,
     VT_VENDOR = 6,
     VT_TOOLCHAIN = 8,
@@ -749,68 +604,68 @@
     return GetField<uint32_t>(VT_PLATFORM_VERSION, 0);
   }
   bool mutate_platform_version(uint32_t _platform_version) {
-    return SetField<uint32_t>(VT_PLATFORM_VERSION, _platform_version, 0);
+    return SetField(VT_PLATFORM_VERSION, _platform_version);
   }
   /// Toolchain version reported in the HAL; semantics not strictly defined
   uint32_t toolchain_version() const {
     return GetField<uint32_t>(VT_TOOLCHAIN_VERSION, 0);
   }
   bool mutate_toolchain_version(uint32_t _toolchain_version) {
-    return SetField<uint32_t>(VT_TOOLCHAIN_VERSION, _toolchain_version, 0);
+    return SetField(VT_TOOLCHAIN_VERSION, _toolchain_version);
   }
   float peak_mips() const {
     return GetField<float>(VT_PEAK_MIPS, 0.0f);
   }
   bool mutate_peak_mips(float _peak_mips) {
-    return SetField<float>(VT_PEAK_MIPS, _peak_mips, 0.0f);
+    return SetField(VT_PEAK_MIPS, _peak_mips);
   }
   float stopped_power() const {
     return GetField<float>(VT_STOPPED_POWER, 0.0f);
   }
   bool mutate_stopped_power(float _stopped_power) {
-    return SetField<float>(VT_STOPPED_POWER, _stopped_power, 0.0f);
+    return SetField(VT_STOPPED_POWER, _stopped_power);
   }
   float sleep_power() const {
     return GetField<float>(VT_SLEEP_POWER, 0.0f);
   }
   bool mutate_sleep_power(float _sleep_power) {
-    return SetField<float>(VT_SLEEP_POWER, _sleep_power, 0.0f);
+    return SetField(VT_SLEEP_POWER, _sleep_power);
   }
   float peak_power() const {
     return GetField<float>(VT_PEAK_POWER, 0.0f);
   }
   bool mutate_peak_power(float _peak_power) {
-    return SetField<float>(VT_PEAK_POWER, _peak_power, 0.0f);
+    return SetField(VT_PEAK_POWER, _peak_power);
   }
   /// Maximum size message that can be sent to a nanoapp
   uint32_t max_msg_len() const {
     return GetField<uint32_t>(VT_MAX_MSG_LEN, 0);
   }
   bool mutate_max_msg_len(uint32_t _max_msg_len) {
-    return SetField<uint32_t>(VT_MAX_MSG_LEN, _max_msg_len, 0);
+    return SetField(VT_MAX_MSG_LEN, _max_msg_len);
   }
   /// @see chreGetPlatformId()
   uint64_t platform_id() const {
     return GetField<uint64_t>(VT_PLATFORM_ID, 0);
   }
   bool mutate_platform_id(uint64_t _platform_id) {
-    return SetField<uint64_t>(VT_PLATFORM_ID, _platform_id, 0);
+    return SetField(VT_PLATFORM_ID, _platform_id);
   }
   /// @see chreGetVersion()
   uint32_t chre_platform_version() const {
     return GetField<uint32_t>(VT_CHRE_PLATFORM_VERSION, 0);
   }
   bool mutate_chre_platform_version(uint32_t _chre_platform_version) {
-    return SetField<uint32_t>(VT_CHRE_PLATFORM_VERSION, _chre_platform_version, 0);
+    return SetField(VT_CHRE_PLATFORM_VERSION, _chre_platform_version);
   }
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
-           VerifyOffset(verifier, VT_NAME) &&
-           verifier.VerifyVector(name()) &&
-           VerifyOffset(verifier, VT_VENDOR) &&
-           verifier.VerifyVector(vendor()) &&
-           VerifyOffset(verifier, VT_TOOLCHAIN) &&
-           verifier.VerifyVector(toolchain()) &&
+           VerifyField<flatbuffers::uoffset_t>(verifier, VT_NAME) &&
+           verifier.Verify(name()) &&
+           VerifyField<flatbuffers::uoffset_t>(verifier, VT_VENDOR) &&
+           verifier.Verify(vendor()) &&
+           VerifyField<flatbuffers::uoffset_t>(verifier, VT_TOOLCHAIN) &&
+           verifier.Verify(toolchain()) &&
            VerifyField<uint32_t>(verifier, VT_PLATFORM_VERSION) &&
            VerifyField<uint32_t>(verifier, VT_TOOLCHAIN_VERSION) &&
            VerifyField<float>(verifier, VT_PEAK_MIPS) &&
@@ -828,7 +683,6 @@
 };
 
 struct HubInfoResponseBuilder {
-  typedef HubInfoResponse Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
   void add_name(flatbuffers::Offset<flatbuffers::Vector<int8_t>> name) {
@@ -867,13 +721,13 @@
   void add_chre_platform_version(uint32_t chre_platform_version) {
     fbb_.AddElement<uint32_t>(HubInfoResponse::VT_CHRE_PLATFORM_VERSION, chre_platform_version, 0);
   }
-  explicit HubInfoResponseBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  HubInfoResponseBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   HubInfoResponseBuilder &operator=(const HubInfoResponseBuilder &);
   flatbuffers::Offset<HubInfoResponse> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 12);
     auto o = flatbuffers::Offset<HubInfoResponse>(end);
     return o;
   }
@@ -923,14 +777,11 @@
     uint32_t max_msg_len = 0,
     uint64_t platform_id = 0,
     uint32_t chre_platform_version = 0) {
-  auto name__ = name ? _fbb.CreateVector<int8_t>(*name) : 0;
-  auto vendor__ = vendor ? _fbb.CreateVector<int8_t>(*vendor) : 0;
-  auto toolchain__ = toolchain ? _fbb.CreateVector<int8_t>(*toolchain) : 0;
   return chre::fbs::CreateHubInfoResponse(
       _fbb,
-      name__,
-      vendor__,
-      toolchain__,
+      name ? _fbb.CreateVector<int8_t>(*name) : 0,
+      vendor ? _fbb.CreateVector<int8_t>(*vendor) : 0,
+      toolchain ? _fbb.CreateVector<int8_t>(*toolchain) : 0,
       platform_version,
       toolchain_version,
       peak_mips,
@@ -952,7 +803,6 @@
 
 struct NanoappListRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   typedef NanoappListRequestT NativeTableType;
-  typedef NanoappListRequestBuilder Builder;
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
            verifier.EndTable();
@@ -963,16 +813,15 @@
 };
 
 struct NanoappListRequestBuilder {
-  typedef NanoappListRequest Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
-  explicit NanoappListRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  NanoappListRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   NanoappListRequestBuilder &operator=(const NanoappListRequestBuilder &);
   flatbuffers::Offset<NanoappListRequest> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 0);
     auto o = flatbuffers::Offset<NanoappListRequest>(end);
     return o;
   }
@@ -1002,8 +851,7 @@
 
 struct NanoappListEntry FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   typedef NanoappListEntryT NativeTableType;
-  typedef NanoappListEntryBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_APP_ID = 4,
     VT_VERSION = 6,
     VT_ENABLED = 8,
@@ -1013,19 +861,19 @@
     return GetField<uint64_t>(VT_APP_ID, 0);
   }
   bool mutate_app_id(uint64_t _app_id) {
-    return SetField<uint64_t>(VT_APP_ID, _app_id, 0);
+    return SetField(VT_APP_ID, _app_id);
   }
   uint32_t version() const {
     return GetField<uint32_t>(VT_VERSION, 0);
   }
   bool mutate_version(uint32_t _version) {
-    return SetField<uint32_t>(VT_VERSION, _version, 0);
+    return SetField(VT_VERSION, _version);
   }
   bool enabled() const {
     return GetField<uint8_t>(VT_ENABLED, 1) != 0;
   }
   bool mutate_enabled(bool _enabled) {
-    return SetField<uint8_t>(VT_ENABLED, static_cast<uint8_t>(_enabled), 1);
+    return SetField(VT_ENABLED, static_cast<uint8_t>(_enabled));
   }
   /// Whether the nanoapp is a pre-loaded "system" nanoapp, i.e. one that should
   /// not show up in the list of nanoapps in the context hub HAL. System
@@ -1035,7 +883,7 @@
     return GetField<uint8_t>(VT_IS_SYSTEM, 0) != 0;
   }
   bool mutate_is_system(bool _is_system) {
-    return SetField<uint8_t>(VT_IS_SYSTEM, static_cast<uint8_t>(_is_system), 0);
+    return SetField(VT_IS_SYSTEM, static_cast<uint8_t>(_is_system));
   }
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
@@ -1051,7 +899,6 @@
 };
 
 struct NanoappListEntryBuilder {
-  typedef NanoappListEntry Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
   void add_app_id(uint64_t app_id) {
@@ -1066,13 +913,13 @@
   void add_is_system(bool is_system) {
     fbb_.AddElement<uint8_t>(NanoappListEntry::VT_IS_SYSTEM, static_cast<uint8_t>(is_system), 0);
   }
-  explicit NanoappListEntryBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  NanoappListEntryBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   NanoappListEntryBuilder &operator=(const NanoappListEntryBuilder &);
   flatbuffers::Offset<NanoappListEntry> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 4);
     auto o = flatbuffers::Offset<NanoappListEntry>(end);
     return o;
   }
@@ -1096,27 +943,26 @@
 
 struct NanoappListResponseT : public flatbuffers::NativeTable {
   typedef NanoappListResponse TableType;
-  std::vector<std::unique_ptr<chre::fbs::NanoappListEntryT>> nanoapps;
+  std::vector<std::unique_ptr<NanoappListEntryT>> nanoapps;
   NanoappListResponseT() {
   }
 };
 
 struct NanoappListResponse FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   typedef NanoappListResponseT NativeTableType;
-  typedef NanoappListResponseBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_NANOAPPS = 4
   };
-  const flatbuffers::Vector<flatbuffers::Offset<chre::fbs::NanoappListEntry>> *nanoapps() const {
-    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<chre::fbs::NanoappListEntry>> *>(VT_NANOAPPS);
+  const flatbuffers::Vector<flatbuffers::Offset<NanoappListEntry>> *nanoapps() const {
+    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<NanoappListEntry>> *>(VT_NANOAPPS);
   }
-  flatbuffers::Vector<flatbuffers::Offset<chre::fbs::NanoappListEntry>> *mutable_nanoapps() {
-    return GetPointer<flatbuffers::Vector<flatbuffers::Offset<chre::fbs::NanoappListEntry>> *>(VT_NANOAPPS);
+  flatbuffers::Vector<flatbuffers::Offset<NanoappListEntry>> *mutable_nanoapps() {
+    return GetPointer<flatbuffers::Vector<flatbuffers::Offset<NanoappListEntry>> *>(VT_NANOAPPS);
   }
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
-           VerifyOffsetRequired(verifier, VT_NANOAPPS) &&
-           verifier.VerifyVector(nanoapps()) &&
+           VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_NANOAPPS) &&
+           verifier.Verify(nanoapps()) &&
            verifier.VerifyVectorOfTables(nanoapps()) &&
            verifier.EndTable();
   }
@@ -1126,19 +972,18 @@
 };
 
 struct NanoappListResponseBuilder {
-  typedef NanoappListResponse Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
-  void add_nanoapps(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<chre::fbs::NanoappListEntry>>> nanoapps) {
+  void add_nanoapps(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<NanoappListEntry>>> nanoapps) {
     fbb_.AddOffset(NanoappListResponse::VT_NANOAPPS, nanoapps);
   }
-  explicit NanoappListResponseBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  NanoappListResponseBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   NanoappListResponseBuilder &operator=(const NanoappListResponseBuilder &);
   flatbuffers::Offset<NanoappListResponse> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 1);
     auto o = flatbuffers::Offset<NanoappListResponse>(end);
     fbb_.Required(o, NanoappListResponse::VT_NANOAPPS);
     return o;
@@ -1147,7 +992,7 @@
 
 inline flatbuffers::Offset<NanoappListResponse> CreateNanoappListResponse(
     flatbuffers::FlatBufferBuilder &_fbb,
-    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<chre::fbs::NanoappListEntry>>> nanoapps = 0) {
+    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<NanoappListEntry>>> nanoapps = 0) {
   NanoappListResponseBuilder builder_(_fbb);
   builder_.add_nanoapps(nanoapps);
   return builder_.Finish();
@@ -1155,11 +1000,10 @@
 
 inline flatbuffers::Offset<NanoappListResponse> CreateNanoappListResponseDirect(
     flatbuffers::FlatBufferBuilder &_fbb,
-    const std::vector<flatbuffers::Offset<chre::fbs::NanoappListEntry>> *nanoapps = nullptr) {
-  auto nanoapps__ = nanoapps ? _fbb.CreateVector<flatbuffers::Offset<chre::fbs::NanoappListEntry>>(*nanoapps) : 0;
+    const std::vector<flatbuffers::Offset<NanoappListEntry>> *nanoapps = nullptr) {
   return chre::fbs::CreateNanoappListResponse(
       _fbb,
-      nanoapps__);
+      nanoapps ? _fbb.CreateVector<flatbuffers::Offset<NanoappListEntry>>(*nanoapps) : 0);
 }
 
 flatbuffers::Offset<NanoappListResponse> CreateNanoappListResponse(flatbuffers::FlatBufferBuilder &_fbb, const NanoappListResponseT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
@@ -1224,8 +1068,7 @@
 /// process crashes), then the load request will be cancelled at CHRE and fail.
 struct LoadNanoappRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   typedef LoadNanoappRequestT NativeTableType;
-  typedef LoadNanoappRequestBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_TRANSACTION_ID = 4,
     VT_APP_ID = 6,
     VT_APP_VERSION = 8,
@@ -1239,25 +1082,25 @@
     return GetField<uint32_t>(VT_TRANSACTION_ID, 0);
   }
   bool mutate_transaction_id(uint32_t _transaction_id) {
-    return SetField<uint32_t>(VT_TRANSACTION_ID, _transaction_id, 0);
+    return SetField(VT_TRANSACTION_ID, _transaction_id);
   }
   uint64_t app_id() const {
     return GetField<uint64_t>(VT_APP_ID, 0);
   }
   bool mutate_app_id(uint64_t _app_id) {
-    return SetField<uint64_t>(VT_APP_ID, _app_id, 0);
+    return SetField(VT_APP_ID, _app_id);
   }
   uint32_t app_version() const {
     return GetField<uint32_t>(VT_APP_VERSION, 0);
   }
   bool mutate_app_version(uint32_t _app_version) {
-    return SetField<uint32_t>(VT_APP_VERSION, _app_version, 0);
+    return SetField(VT_APP_VERSION, _app_version);
   }
   uint32_t target_api_version() const {
     return GetField<uint32_t>(VT_TARGET_API_VERSION, 0);
   }
   bool mutate_target_api_version(uint32_t _target_api_version) {
-    return SetField<uint32_t>(VT_TARGET_API_VERSION, _target_api_version, 0);
+    return SetField(VT_TARGET_API_VERSION, _target_api_version);
   }
   const flatbuffers::Vector<uint8_t> *app_binary() const {
     return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_APP_BINARY);
@@ -1273,13 +1116,13 @@
     return GetField<uint32_t>(VT_FRAGMENT_ID, 0);
   }
   bool mutate_fragment_id(uint32_t _fragment_id) {
-    return SetField<uint32_t>(VT_FRAGMENT_ID, _fragment_id, 0);
+    return SetField(VT_FRAGMENT_ID, _fragment_id);
   }
   uint32_t total_app_size() const {
     return GetField<uint32_t>(VT_TOTAL_APP_SIZE, 0);
   }
   bool mutate_total_app_size(uint32_t _total_app_size) {
-    return SetField<uint32_t>(VT_TOTAL_APP_SIZE, _total_app_size, 0);
+    return SetField(VT_TOTAL_APP_SIZE, _total_app_size);
   }
   /// Null-terminated ASCII string containing the file name that contains the
   /// app binary to be loaded.
@@ -1295,12 +1138,12 @@
            VerifyField<uint64_t>(verifier, VT_APP_ID) &&
            VerifyField<uint32_t>(verifier, VT_APP_VERSION) &&
            VerifyField<uint32_t>(verifier, VT_TARGET_API_VERSION) &&
-           VerifyOffsetRequired(verifier, VT_APP_BINARY) &&
-           verifier.VerifyVector(app_binary()) &&
+           VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_APP_BINARY) &&
+           verifier.Verify(app_binary()) &&
            VerifyField<uint32_t>(verifier, VT_FRAGMENT_ID) &&
            VerifyField<uint32_t>(verifier, VT_TOTAL_APP_SIZE) &&
-           VerifyOffset(verifier, VT_APP_BINARY_FILE_NAME) &&
-           verifier.VerifyVector(app_binary_file_name()) &&
+           VerifyField<flatbuffers::uoffset_t>(verifier, VT_APP_BINARY_FILE_NAME) &&
+           verifier.Verify(app_binary_file_name()) &&
            verifier.EndTable();
   }
   LoadNanoappRequestT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
@@ -1309,7 +1152,6 @@
 };
 
 struct LoadNanoappRequestBuilder {
-  typedef LoadNanoappRequest Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
   void add_transaction_id(uint32_t transaction_id) {
@@ -1336,13 +1178,13 @@
   void add_app_binary_file_name(flatbuffers::Offset<flatbuffers::Vector<int8_t>> app_binary_file_name) {
     fbb_.AddOffset(LoadNanoappRequest::VT_APP_BINARY_FILE_NAME, app_binary_file_name);
   }
-  explicit LoadNanoappRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  LoadNanoappRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   LoadNanoappRequestBuilder &operator=(const LoadNanoappRequestBuilder &);
   flatbuffers::Offset<LoadNanoappRequest> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 8);
     auto o = flatbuffers::Offset<LoadNanoappRequest>(end);
     fbb_.Required(o, LoadNanoappRequest::VT_APP_BINARY);
     return o;
@@ -1381,18 +1223,16 @@
     uint32_t fragment_id = 0,
     uint32_t total_app_size = 0,
     const std::vector<int8_t> *app_binary_file_name = nullptr) {
-  auto app_binary__ = app_binary ? _fbb.CreateVector<uint8_t>(*app_binary) : 0;
-  auto app_binary_file_name__ = app_binary_file_name ? _fbb.CreateVector<int8_t>(*app_binary_file_name) : 0;
   return chre::fbs::CreateLoadNanoappRequest(
       _fbb,
       transaction_id,
       app_id,
       app_version,
       target_api_version,
-      app_binary__,
+      app_binary ? _fbb.CreateVector<uint8_t>(*app_binary) : 0,
       fragment_id,
       total_app_size,
-      app_binary_file_name__);
+      app_binary_file_name ? _fbb.CreateVector<int8_t>(*app_binary_file_name) : 0);
 }
 
 flatbuffers::Offset<LoadNanoappRequest> CreateLoadNanoappRequest(flatbuffers::FlatBufferBuilder &_fbb, const LoadNanoappRequestT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
@@ -1411,8 +1251,7 @@
 
 struct LoadNanoappResponse FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   typedef LoadNanoappResponseT NativeTableType;
-  typedef LoadNanoappResponseBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_TRANSACTION_ID = 4,
     VT_SUCCESS = 6,
     VT_FRAGMENT_ID = 8
@@ -1421,7 +1260,7 @@
     return GetField<uint32_t>(VT_TRANSACTION_ID, 0);
   }
   bool mutate_transaction_id(uint32_t _transaction_id) {
-    return SetField<uint32_t>(VT_TRANSACTION_ID, _transaction_id, 0);
+    return SetField(VT_TRANSACTION_ID, _transaction_id);
   }
   /// Denotes whether a load request succeeded or failed.
   /// If any fragment of a load request fails, the entire load request for
@@ -1430,14 +1269,14 @@
     return GetField<uint8_t>(VT_SUCCESS, 0) != 0;
   }
   bool mutate_success(bool _success) {
-    return SetField<uint8_t>(VT_SUCCESS, static_cast<uint8_t>(_success), 0);
+    return SetField(VT_SUCCESS, static_cast<uint8_t>(_success));
   }
   /// The fragment count of the load reponse is for.
   uint32_t fragment_id() const {
     return GetField<uint32_t>(VT_FRAGMENT_ID, 0);
   }
   bool mutate_fragment_id(uint32_t _fragment_id) {
-    return SetField<uint32_t>(VT_FRAGMENT_ID, _fragment_id, 0);
+    return SetField(VT_FRAGMENT_ID, _fragment_id);
   }
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
@@ -1452,7 +1291,6 @@
 };
 
 struct LoadNanoappResponseBuilder {
-  typedef LoadNanoappResponse Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
   void add_transaction_id(uint32_t transaction_id) {
@@ -1464,13 +1302,13 @@
   void add_fragment_id(uint32_t fragment_id) {
     fbb_.AddElement<uint32_t>(LoadNanoappResponse::VT_FRAGMENT_ID, fragment_id, 0);
   }
-  explicit LoadNanoappResponseBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  LoadNanoappResponseBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   LoadNanoappResponseBuilder &operator=(const LoadNanoappResponseBuilder &);
   flatbuffers::Offset<LoadNanoappResponse> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 3);
     auto o = flatbuffers::Offset<LoadNanoappResponse>(end);
     return o;
   }
@@ -1504,8 +1342,7 @@
 
 struct UnloadNanoappRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   typedef UnloadNanoappRequestT NativeTableType;
-  typedef UnloadNanoappRequestBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_TRANSACTION_ID = 4,
     VT_APP_ID = 6,
     VT_ALLOW_SYSTEM_NANOAPP_UNLOAD = 8
@@ -1514,13 +1351,13 @@
     return GetField<uint32_t>(VT_TRANSACTION_ID, 0);
   }
   bool mutate_transaction_id(uint32_t _transaction_id) {
-    return SetField<uint32_t>(VT_TRANSACTION_ID, _transaction_id, 0);
+    return SetField(VT_TRANSACTION_ID, _transaction_id);
   }
   uint64_t app_id() const {
     return GetField<uint64_t>(VT_APP_ID, 0);
   }
   bool mutate_app_id(uint64_t _app_id) {
-    return SetField<uint64_t>(VT_APP_ID, _app_id, 0);
+    return SetField(VT_APP_ID, _app_id);
   }
   /// Set to true to allow this request to unload nanoapps identified as "system
   /// nanoapps", i.e. ones with is_system set to true in NanoappListResponse.
@@ -1528,7 +1365,7 @@
     return GetField<uint8_t>(VT_ALLOW_SYSTEM_NANOAPP_UNLOAD, 0) != 0;
   }
   bool mutate_allow_system_nanoapp_unload(bool _allow_system_nanoapp_unload) {
-    return SetField<uint8_t>(VT_ALLOW_SYSTEM_NANOAPP_UNLOAD, static_cast<uint8_t>(_allow_system_nanoapp_unload), 0);
+    return SetField(VT_ALLOW_SYSTEM_NANOAPP_UNLOAD, static_cast<uint8_t>(_allow_system_nanoapp_unload));
   }
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
@@ -1543,7 +1380,6 @@
 };
 
 struct UnloadNanoappRequestBuilder {
-  typedef UnloadNanoappRequest Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
   void add_transaction_id(uint32_t transaction_id) {
@@ -1555,13 +1391,13 @@
   void add_allow_system_nanoapp_unload(bool allow_system_nanoapp_unload) {
     fbb_.AddElement<uint8_t>(UnloadNanoappRequest::VT_ALLOW_SYSTEM_NANOAPP_UNLOAD, static_cast<uint8_t>(allow_system_nanoapp_unload), 0);
   }
-  explicit UnloadNanoappRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  UnloadNanoappRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   UnloadNanoappRequestBuilder &operator=(const UnloadNanoappRequestBuilder &);
   flatbuffers::Offset<UnloadNanoappRequest> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 3);
     auto o = flatbuffers::Offset<UnloadNanoappRequest>(end);
     return o;
   }
@@ -1593,8 +1429,7 @@
 
 struct UnloadNanoappResponse FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   typedef UnloadNanoappResponseT NativeTableType;
-  typedef UnloadNanoappResponseBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_TRANSACTION_ID = 4,
     VT_SUCCESS = 6
   };
@@ -1602,13 +1437,13 @@
     return GetField<uint32_t>(VT_TRANSACTION_ID, 0);
   }
   bool mutate_transaction_id(uint32_t _transaction_id) {
-    return SetField<uint32_t>(VT_TRANSACTION_ID, _transaction_id, 0);
+    return SetField(VT_TRANSACTION_ID, _transaction_id);
   }
   bool success() const {
     return GetField<uint8_t>(VT_SUCCESS, 0) != 0;
   }
   bool mutate_success(bool _success) {
-    return SetField<uint8_t>(VT_SUCCESS, static_cast<uint8_t>(_success), 0);
+    return SetField(VT_SUCCESS, static_cast<uint8_t>(_success));
   }
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
@@ -1622,7 +1457,6 @@
 };
 
 struct UnloadNanoappResponseBuilder {
-  typedef UnloadNanoappResponse Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
   void add_transaction_id(uint32_t transaction_id) {
@@ -1631,13 +1465,13 @@
   void add_success(bool success) {
     fbb_.AddElement<uint8_t>(UnloadNanoappResponse::VT_SUCCESS, static_cast<uint8_t>(success), 0);
   }
-  explicit UnloadNanoappResponseBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  UnloadNanoappResponseBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   UnloadNanoappResponseBuilder &operator=(const UnloadNanoappResponseBuilder &);
   flatbuffers::Offset<UnloadNanoappResponse> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 2);
     auto o = flatbuffers::Offset<UnloadNanoappResponse>(end);
     return o;
   }
@@ -1665,8 +1499,7 @@
 /// Represents log messages from CHRE.
 struct LogMessage FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   typedef LogMessageT NativeTableType;
-  typedef LogMessageBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_BUFFER = 4
   };
   /// A buffer containing formatted log data. A flat array is used here to avoid
@@ -1690,8 +1523,8 @@
   }
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
-           VerifyOffset(verifier, VT_BUFFER) &&
-           verifier.VerifyVector(buffer()) &&
+           VerifyField<flatbuffers::uoffset_t>(verifier, VT_BUFFER) &&
+           verifier.Verify(buffer()) &&
            verifier.EndTable();
   }
   LogMessageT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
@@ -1700,19 +1533,18 @@
 };
 
 struct LogMessageBuilder {
-  typedef LogMessage Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
   void add_buffer(flatbuffers::Offset<flatbuffers::Vector<int8_t>> buffer) {
     fbb_.AddOffset(LogMessage::VT_BUFFER, buffer);
   }
-  explicit LogMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  LogMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   LogMessageBuilder &operator=(const LogMessageBuilder &);
   flatbuffers::Offset<LogMessage> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 1);
     auto o = flatbuffers::Offset<LogMessage>(end);
     return o;
   }
@@ -1729,10 +1561,9 @@
 inline flatbuffers::Offset<LogMessage> CreateLogMessageDirect(
     flatbuffers::FlatBufferBuilder &_fbb,
     const std::vector<int8_t> *buffer = nullptr) {
-  auto buffer__ = buffer ? _fbb.CreateVector<int8_t>(*buffer) : 0;
   return chre::fbs::CreateLogMessage(
       _fbb,
-      buffer__);
+      buffer ? _fbb.CreateVector<int8_t>(*buffer) : 0);
 }
 
 flatbuffers::Offset<LogMessage> CreateLogMessage(flatbuffers::FlatBufferBuilder &_fbb, const LogMessageT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
@@ -1748,8 +1579,7 @@
 /// Represents a message sent to CHRE to indicate AP timestamp for time sync
 struct TimeSyncMessage FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   typedef TimeSyncMessageT NativeTableType;
-  typedef TimeSyncMessageBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_OFFSET = 4
   };
   /// Offset between AP and CHRE timestamp
@@ -1757,7 +1587,7 @@
     return GetField<int64_t>(VT_OFFSET, 0);
   }
   bool mutate_offset(int64_t _offset) {
-    return SetField<int64_t>(VT_OFFSET, _offset, 0);
+    return SetField(VT_OFFSET, _offset);
   }
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
@@ -1770,19 +1600,18 @@
 };
 
 struct TimeSyncMessageBuilder {
-  typedef TimeSyncMessage Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
   void add_offset(int64_t offset) {
     fbb_.AddElement<int64_t>(TimeSyncMessage::VT_OFFSET, offset, 0);
   }
-  explicit TimeSyncMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  TimeSyncMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   TimeSyncMessageBuilder &operator=(const TimeSyncMessageBuilder &);
   flatbuffers::Offset<TimeSyncMessage> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 1);
     auto o = flatbuffers::Offset<TimeSyncMessage>(end);
     return o;
   }
@@ -1810,7 +1639,6 @@
 /// indicating the completion of the operation.
 struct DebugDumpRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   typedef DebugDumpRequestT NativeTableType;
-  typedef DebugDumpRequestBuilder Builder;
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
            verifier.EndTable();
@@ -1821,16 +1649,15 @@
 };
 
 struct DebugDumpRequestBuilder {
-  typedef DebugDumpRequest Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
-  explicit DebugDumpRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  DebugDumpRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   DebugDumpRequestBuilder &operator=(const DebugDumpRequestBuilder &);
   flatbuffers::Offset<DebugDumpRequest> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 0);
     auto o = flatbuffers::Offset<DebugDumpRequest>(end);
     return o;
   }
@@ -1853,8 +1680,7 @@
 
 struct DebugDumpData FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   typedef DebugDumpDataT NativeTableType;
-  typedef DebugDumpDataBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_DEBUG_STR = 4
   };
   /// Null-terminated ASCII string containing debugging information
@@ -1866,8 +1692,8 @@
   }
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
-           VerifyOffset(verifier, VT_DEBUG_STR) &&
-           verifier.VerifyVector(debug_str()) &&
+           VerifyField<flatbuffers::uoffset_t>(verifier, VT_DEBUG_STR) &&
+           verifier.Verify(debug_str()) &&
            verifier.EndTable();
   }
   DebugDumpDataT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
@@ -1876,19 +1702,18 @@
 };
 
 struct DebugDumpDataBuilder {
-  typedef DebugDumpData Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
   void add_debug_str(flatbuffers::Offset<flatbuffers::Vector<int8_t>> debug_str) {
     fbb_.AddOffset(DebugDumpData::VT_DEBUG_STR, debug_str);
   }
-  explicit DebugDumpDataBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  DebugDumpDataBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   DebugDumpDataBuilder &operator=(const DebugDumpDataBuilder &);
   flatbuffers::Offset<DebugDumpData> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 1);
     auto o = flatbuffers::Offset<DebugDumpData>(end);
     return o;
   }
@@ -1905,10 +1730,9 @@
 inline flatbuffers::Offset<DebugDumpData> CreateDebugDumpDataDirect(
     flatbuffers::FlatBufferBuilder &_fbb,
     const std::vector<int8_t> *debug_str = nullptr) {
-  auto debug_str__ = debug_str ? _fbb.CreateVector<int8_t>(*debug_str) : 0;
   return chre::fbs::CreateDebugDumpData(
       _fbb,
-      debug_str__);
+      debug_str ? _fbb.CreateVector<int8_t>(*debug_str) : 0);
 }
 
 flatbuffers::Offset<DebugDumpData> CreateDebugDumpData(flatbuffers::FlatBufferBuilder &_fbb, const DebugDumpDataT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
@@ -1925,8 +1749,7 @@
 
 struct DebugDumpResponse FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   typedef DebugDumpResponseT NativeTableType;
-  typedef DebugDumpResponseBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_SUCCESS = 4,
     VT_DATA_COUNT = 6
   };
@@ -1936,14 +1759,14 @@
     return GetField<uint8_t>(VT_SUCCESS, 0) != 0;
   }
   bool mutate_success(bool _success) {
-    return SetField<uint8_t>(VT_SUCCESS, static_cast<uint8_t>(_success), 0);
+    return SetField(VT_SUCCESS, static_cast<uint8_t>(_success));
   }
   /// The number of DebugDumpData messages sent in this session
   uint32_t data_count() const {
     return GetField<uint32_t>(VT_DATA_COUNT, 0);
   }
   bool mutate_data_count(uint32_t _data_count) {
-    return SetField<uint32_t>(VT_DATA_COUNT, _data_count, 0);
+    return SetField(VT_DATA_COUNT, _data_count);
   }
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
@@ -1957,7 +1780,6 @@
 };
 
 struct DebugDumpResponseBuilder {
-  typedef DebugDumpResponse Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
   void add_success(bool success) {
@@ -1966,13 +1788,13 @@
   void add_data_count(uint32_t data_count) {
     fbb_.AddElement<uint32_t>(DebugDumpResponse::VT_DATA_COUNT, data_count, 0);
   }
-  explicit DebugDumpResponseBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  DebugDumpResponseBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   DebugDumpResponseBuilder &operator=(const DebugDumpResponseBuilder &);
   flatbuffers::Offset<DebugDumpResponse> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 2);
     auto o = flatbuffers::Offset<DebugDumpResponse>(end);
     return o;
   }
@@ -2000,7 +1822,6 @@
 /// (system feature, platform-specific - not all platforms necessarily use this)
 struct TimeSyncRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   typedef TimeSyncRequestT NativeTableType;
-  typedef TimeSyncRequestBuilder Builder;
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
            verifier.EndTable();
@@ -2011,16 +1832,15 @@
 };
 
 struct TimeSyncRequestBuilder {
-  typedef TimeSyncRequest Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
-  explicit TimeSyncRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  TimeSyncRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   TimeSyncRequestBuilder &operator=(const TimeSyncRequestBuilder &);
   flatbuffers::Offset<TimeSyncRequest> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 0);
     auto o = flatbuffers::Offset<TimeSyncRequest>(end);
     return o;
   }
@@ -2046,7 +1866,6 @@
 /// CHRE needs it. The host does not send a response.
 struct LowPowerMicAccessRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   typedef LowPowerMicAccessRequestT NativeTableType;
-  typedef LowPowerMicAccessRequestBuilder Builder;
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
            verifier.EndTable();
@@ -2057,16 +1876,15 @@
 };
 
 struct LowPowerMicAccessRequestBuilder {
-  typedef LowPowerMicAccessRequest Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
-  explicit LowPowerMicAccessRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  LowPowerMicAccessRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   LowPowerMicAccessRequestBuilder &operator=(const LowPowerMicAccessRequestBuilder &);
   flatbuffers::Offset<LowPowerMicAccessRequest> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 0);
     auto o = flatbuffers::Offset<LowPowerMicAccessRequest>(end);
     return o;
   }
@@ -2090,7 +1908,6 @@
 /// microphone data.
 struct LowPowerMicAccessRelease FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   typedef LowPowerMicAccessReleaseT NativeTableType;
-  typedef LowPowerMicAccessReleaseBuilder Builder;
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
            verifier.EndTable();
@@ -2101,16 +1918,15 @@
 };
 
 struct LowPowerMicAccessReleaseBuilder {
-  typedef LowPowerMicAccessRelease Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
-  explicit LowPowerMicAccessReleaseBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  LowPowerMicAccessReleaseBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   LowPowerMicAccessReleaseBuilder &operator=(const LowPowerMicAccessReleaseBuilder &);
   flatbuffers::Offset<LowPowerMicAccessRelease> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 0);
     auto o = flatbuffers::Offset<LowPowerMicAccessRelease>(end);
     return o;
   }
@@ -2126,35 +1942,34 @@
 
 struct SettingChangeMessageT : public flatbuffers::NativeTable {
   typedef SettingChangeMessage TableType;
-  chre::fbs::Setting setting;
-  chre::fbs::SettingState state;
+  Setting setting;
+  SettingState state;
   SettingChangeMessageT()
-      : setting(chre::fbs::Setting::LOCATION),
-        state(chre::fbs::SettingState::DISABLED) {
+      : setting(Setting::LOCATION),
+        state(SettingState::DISABLED) {
   }
 };
 
 /// Notification from the host that a system setting has changed
 struct SettingChangeMessage FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   typedef SettingChangeMessageT NativeTableType;
-  typedef SettingChangeMessageBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_SETTING = 4,
     VT_STATE = 6
   };
   /// The setting that has changed
-  chre::fbs::Setting setting() const {
-    return static_cast<chre::fbs::Setting>(GetField<int8_t>(VT_SETTING, 0));
+  Setting setting() const {
+    return static_cast<Setting>(GetField<int8_t>(VT_SETTING, 0));
   }
-  bool mutate_setting(chre::fbs::Setting _setting) {
-    return SetField<int8_t>(VT_SETTING, static_cast<int8_t>(_setting), 0);
+  bool mutate_setting(Setting _setting) {
+    return SetField(VT_SETTING, static_cast<int8_t>(_setting));
   }
   /// The new setting value
-  chre::fbs::SettingState state() const {
-    return static_cast<chre::fbs::SettingState>(GetField<int8_t>(VT_STATE, 0));
+  SettingState state() const {
+    return static_cast<SettingState>(GetField<int8_t>(VT_STATE, 0));
   }
-  bool mutate_state(chre::fbs::SettingState _state) {
-    return SetField<int8_t>(VT_STATE, static_cast<int8_t>(_state), 0);
+  bool mutate_state(SettingState _state) {
+    return SetField(VT_STATE, static_cast<int8_t>(_state));
   }
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
@@ -2168,22 +1983,21 @@
 };
 
 struct SettingChangeMessageBuilder {
-  typedef SettingChangeMessage Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
-  void add_setting(chre::fbs::Setting setting) {
+  void add_setting(Setting setting) {
     fbb_.AddElement<int8_t>(SettingChangeMessage::VT_SETTING, static_cast<int8_t>(setting), 0);
   }
-  void add_state(chre::fbs::SettingState state) {
+  void add_state(SettingState state) {
     fbb_.AddElement<int8_t>(SettingChangeMessage::VT_STATE, static_cast<int8_t>(state), 0);
   }
-  explicit SettingChangeMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  SettingChangeMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   SettingChangeMessageBuilder &operator=(const SettingChangeMessageBuilder &);
   flatbuffers::Offset<SettingChangeMessage> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 2);
     auto o = flatbuffers::Offset<SettingChangeMessage>(end);
     return o;
   }
@@ -2191,8 +2005,8 @@
 
 inline flatbuffers::Offset<SettingChangeMessage> CreateSettingChangeMessage(
     flatbuffers::FlatBufferBuilder &_fbb,
-    chre::fbs::Setting setting = chre::fbs::Setting::LOCATION,
-    chre::fbs::SettingState state = chre::fbs::SettingState::DISABLED) {
+    Setting setting = Setting::LOCATION,
+    SettingState state = SettingState::DISABLED) {
   SettingChangeMessageBuilder builder_(_fbb);
   builder_.add_state(state);
   builder_.add_setting(setting);
@@ -2203,8 +2017,8 @@
 
 struct MessageContainerT : public flatbuffers::NativeTable {
   typedef MessageContainer TableType;
-  chre::fbs::ChreMessageUnion message;
-  std::unique_ptr<chre::fbs::HostAddress> host_addr;
+  ChreMessageUnion message;
+  std::unique_ptr<HostAddress> host_addr;
   MessageContainerT() {
   }
 };
@@ -2214,73 +2028,20 @@
 /// structure (root type), so we must wrap it in a table.
 struct MessageContainer FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   typedef MessageContainerT NativeTableType;
-  typedef MessageContainerBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_MESSAGE_TYPE = 4,
     VT_MESSAGE = 6,
     VT_HOST_ADDR = 8
   };
-  chre::fbs::ChreMessage message_type() const {
-    return static_cast<chre::fbs::ChreMessage>(GetField<uint8_t>(VT_MESSAGE_TYPE, 0));
+  ChreMessage message_type() const {
+    return static_cast<ChreMessage>(GetField<uint8_t>(VT_MESSAGE_TYPE, 0));
+  }
+  bool mutate_message_type(ChreMessage _message_type) {
+    return SetField(VT_MESSAGE_TYPE, static_cast<uint8_t>(_message_type));
   }
   const void *message() const {
     return GetPointer<const void *>(VT_MESSAGE);
   }
-  template<typename T> const T *message_as() const;
-  const chre::fbs::NanoappMessage *message_as_NanoappMessage() const {
-    return message_type() == chre::fbs::ChreMessage::NanoappMessage ? static_cast<const chre::fbs::NanoappMessage *>(message()) : nullptr;
-  }
-  const chre::fbs::HubInfoRequest *message_as_HubInfoRequest() const {
-    return message_type() == chre::fbs::ChreMessage::HubInfoRequest ? static_cast<const chre::fbs::HubInfoRequest *>(message()) : nullptr;
-  }
-  const chre::fbs::HubInfoResponse *message_as_HubInfoResponse() const {
-    return message_type() == chre::fbs::ChreMessage::HubInfoResponse ? static_cast<const chre::fbs::HubInfoResponse *>(message()) : nullptr;
-  }
-  const chre::fbs::NanoappListRequest *message_as_NanoappListRequest() const {
-    return message_type() == chre::fbs::ChreMessage::NanoappListRequest ? static_cast<const chre::fbs::NanoappListRequest *>(message()) : nullptr;
-  }
-  const chre::fbs::NanoappListResponse *message_as_NanoappListResponse() const {
-    return message_type() == chre::fbs::ChreMessage::NanoappListResponse ? static_cast<const chre::fbs::NanoappListResponse *>(message()) : nullptr;
-  }
-  const chre::fbs::LoadNanoappRequest *message_as_LoadNanoappRequest() const {
-    return message_type() == chre::fbs::ChreMessage::LoadNanoappRequest ? static_cast<const chre::fbs::LoadNanoappRequest *>(message()) : nullptr;
-  }
-  const chre::fbs::LoadNanoappResponse *message_as_LoadNanoappResponse() const {
-    return message_type() == chre::fbs::ChreMessage::LoadNanoappResponse ? static_cast<const chre::fbs::LoadNanoappResponse *>(message()) : nullptr;
-  }
-  const chre::fbs::UnloadNanoappRequest *message_as_UnloadNanoappRequest() const {
-    return message_type() == chre::fbs::ChreMessage::UnloadNanoappRequest ? static_cast<const chre::fbs::UnloadNanoappRequest *>(message()) : nullptr;
-  }
-  const chre::fbs::UnloadNanoappResponse *message_as_UnloadNanoappResponse() const {
-    return message_type() == chre::fbs::ChreMessage::UnloadNanoappResponse ? static_cast<const chre::fbs::UnloadNanoappResponse *>(message()) : nullptr;
-  }
-  const chre::fbs::LogMessage *message_as_LogMessage() const {
-    return message_type() == chre::fbs::ChreMessage::LogMessage ? static_cast<const chre::fbs::LogMessage *>(message()) : nullptr;
-  }
-  const chre::fbs::TimeSyncMessage *message_as_TimeSyncMessage() const {
-    return message_type() == chre::fbs::ChreMessage::TimeSyncMessage ? static_cast<const chre::fbs::TimeSyncMessage *>(message()) : nullptr;
-  }
-  const chre::fbs::DebugDumpRequest *message_as_DebugDumpRequest() const {
-    return message_type() == chre::fbs::ChreMessage::DebugDumpRequest ? static_cast<const chre::fbs::DebugDumpRequest *>(message()) : nullptr;
-  }
-  const chre::fbs::DebugDumpData *message_as_DebugDumpData() const {
-    return message_type() == chre::fbs::ChreMessage::DebugDumpData ? static_cast<const chre::fbs::DebugDumpData *>(message()) : nullptr;
-  }
-  const chre::fbs::DebugDumpResponse *message_as_DebugDumpResponse() const {
-    return message_type() == chre::fbs::ChreMessage::DebugDumpResponse ? static_cast<const chre::fbs::DebugDumpResponse *>(message()) : nullptr;
-  }
-  const chre::fbs::TimeSyncRequest *message_as_TimeSyncRequest() const {
-    return message_type() == chre::fbs::ChreMessage::TimeSyncRequest ? static_cast<const chre::fbs::TimeSyncRequest *>(message()) : nullptr;
-  }
-  const chre::fbs::LowPowerMicAccessRequest *message_as_LowPowerMicAccessRequest() const {
-    return message_type() == chre::fbs::ChreMessage::LowPowerMicAccessRequest ? static_cast<const chre::fbs::LowPowerMicAccessRequest *>(message()) : nullptr;
-  }
-  const chre::fbs::LowPowerMicAccessRelease *message_as_LowPowerMicAccessRelease() const {
-    return message_type() == chre::fbs::ChreMessage::LowPowerMicAccessRelease ? static_cast<const chre::fbs::LowPowerMicAccessRelease *>(message()) : nullptr;
-  }
-  const chre::fbs::SettingChangeMessage *message_as_SettingChangeMessage() const {
-    return message_type() == chre::fbs::ChreMessage::SettingChangeMessage ? static_cast<const chre::fbs::SettingChangeMessage *>(message()) : nullptr;
-  }
   void *mutable_message() {
     return GetPointer<void *>(VT_MESSAGE);
   }
@@ -2290,18 +2051,18 @@
   /// value by the entity guarding access to CHRE.
   /// This is wrapped in a struct to ensure that it is always included when
   /// encoding the message, so it can be mutated by the host daemon.
-  const chre::fbs::HostAddress *host_addr() const {
-    return GetStruct<const chre::fbs::HostAddress *>(VT_HOST_ADDR);
+  const HostAddress *host_addr() const {
+    return GetStruct<const HostAddress *>(VT_HOST_ADDR);
   }
-  chre::fbs::HostAddress *mutable_host_addr() {
-    return GetStruct<chre::fbs::HostAddress *>(VT_HOST_ADDR);
+  HostAddress *mutable_host_addr() {
+    return GetStruct<HostAddress *>(VT_HOST_ADDR);
   }
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
            VerifyField<uint8_t>(verifier, VT_MESSAGE_TYPE) &&
-           VerifyOffsetRequired(verifier, VT_MESSAGE) &&
+           VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_MESSAGE) &&
            VerifyChreMessage(verifier, message(), message_type()) &&
-           VerifyFieldRequired<chre::fbs::HostAddress>(verifier, VT_HOST_ADDR) &&
+           VerifyFieldRequired<HostAddress>(verifier, VT_HOST_ADDR) &&
            verifier.EndTable();
   }
   MessageContainerT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
@@ -2309,98 +2070,25 @@
   static flatbuffers::Offset<MessageContainer> Pack(flatbuffers::FlatBufferBuilder &_fbb, const MessageContainerT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
 };
 
-template<> inline const chre::fbs::NanoappMessage *MessageContainer::message_as<chre::fbs::NanoappMessage>() const {
-  return message_as_NanoappMessage();
-}
-
-template<> inline const chre::fbs::HubInfoRequest *MessageContainer::message_as<chre::fbs::HubInfoRequest>() const {
-  return message_as_HubInfoRequest();
-}
-
-template<> inline const chre::fbs::HubInfoResponse *MessageContainer::message_as<chre::fbs::HubInfoResponse>() const {
-  return message_as_HubInfoResponse();
-}
-
-template<> inline const chre::fbs::NanoappListRequest *MessageContainer::message_as<chre::fbs::NanoappListRequest>() const {
-  return message_as_NanoappListRequest();
-}
-
-template<> inline const chre::fbs::NanoappListResponse *MessageContainer::message_as<chre::fbs::NanoappListResponse>() const {
-  return message_as_NanoappListResponse();
-}
-
-template<> inline const chre::fbs::LoadNanoappRequest *MessageContainer::message_as<chre::fbs::LoadNanoappRequest>() const {
-  return message_as_LoadNanoappRequest();
-}
-
-template<> inline const chre::fbs::LoadNanoappResponse *MessageContainer::message_as<chre::fbs::LoadNanoappResponse>() const {
-  return message_as_LoadNanoappResponse();
-}
-
-template<> inline const chre::fbs::UnloadNanoappRequest *MessageContainer::message_as<chre::fbs::UnloadNanoappRequest>() const {
-  return message_as_UnloadNanoappRequest();
-}
-
-template<> inline const chre::fbs::UnloadNanoappResponse *MessageContainer::message_as<chre::fbs::UnloadNanoappResponse>() const {
-  return message_as_UnloadNanoappResponse();
-}
-
-template<> inline const chre::fbs::LogMessage *MessageContainer::message_as<chre::fbs::LogMessage>() const {
-  return message_as_LogMessage();
-}
-
-template<> inline const chre::fbs::TimeSyncMessage *MessageContainer::message_as<chre::fbs::TimeSyncMessage>() const {
-  return message_as_TimeSyncMessage();
-}
-
-template<> inline const chre::fbs::DebugDumpRequest *MessageContainer::message_as<chre::fbs::DebugDumpRequest>() const {
-  return message_as_DebugDumpRequest();
-}
-
-template<> inline const chre::fbs::DebugDumpData *MessageContainer::message_as<chre::fbs::DebugDumpData>() const {
-  return message_as_DebugDumpData();
-}
-
-template<> inline const chre::fbs::DebugDumpResponse *MessageContainer::message_as<chre::fbs::DebugDumpResponse>() const {
-  return message_as_DebugDumpResponse();
-}
-
-template<> inline const chre::fbs::TimeSyncRequest *MessageContainer::message_as<chre::fbs::TimeSyncRequest>() const {
-  return message_as_TimeSyncRequest();
-}
-
-template<> inline const chre::fbs::LowPowerMicAccessRequest *MessageContainer::message_as<chre::fbs::LowPowerMicAccessRequest>() const {
-  return message_as_LowPowerMicAccessRequest();
-}
-
-template<> inline const chre::fbs::LowPowerMicAccessRelease *MessageContainer::message_as<chre::fbs::LowPowerMicAccessRelease>() const {
-  return message_as_LowPowerMicAccessRelease();
-}
-
-template<> inline const chre::fbs::SettingChangeMessage *MessageContainer::message_as<chre::fbs::SettingChangeMessage>() const {
-  return message_as_SettingChangeMessage();
-}
-
 struct MessageContainerBuilder {
-  typedef MessageContainer Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
-  void add_message_type(chre::fbs::ChreMessage message_type) {
+  void add_message_type(ChreMessage message_type) {
     fbb_.AddElement<uint8_t>(MessageContainer::VT_MESSAGE_TYPE, static_cast<uint8_t>(message_type), 0);
   }
   void add_message(flatbuffers::Offset<void> message) {
     fbb_.AddOffset(MessageContainer::VT_MESSAGE, message);
   }
-  void add_host_addr(const chre::fbs::HostAddress *host_addr) {
+  void add_host_addr(const HostAddress *host_addr) {
     fbb_.AddStruct(MessageContainer::VT_HOST_ADDR, host_addr);
   }
-  explicit MessageContainerBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  MessageContainerBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   MessageContainerBuilder &operator=(const MessageContainerBuilder &);
   flatbuffers::Offset<MessageContainer> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 3);
     auto o = flatbuffers::Offset<MessageContainer>(end);
     fbb_.Required(o, MessageContainer::VT_MESSAGE);
     fbb_.Required(o, MessageContainer::VT_HOST_ADDR);
@@ -2410,9 +2098,9 @@
 
 inline flatbuffers::Offset<MessageContainer> CreateMessageContainer(
     flatbuffers::FlatBufferBuilder &_fbb,
-    chre::fbs::ChreMessage message_type = chre::fbs::ChreMessage::NONE,
+    ChreMessage message_type = ChreMessage::NONE,
     flatbuffers::Offset<void> message = 0,
-    const chre::fbs::HostAddress *host_addr = 0) {
+    const HostAddress *host_addr = 0) {
   MessageContainerBuilder builder_(_fbb);
   builder_.add_host_addr(host_addr);
   builder_.add_message(message);
@@ -2423,18 +2111,18 @@
 flatbuffers::Offset<MessageContainer> CreateMessageContainer(flatbuffers::FlatBufferBuilder &_fbb, const MessageContainerT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
 
 inline NanoappMessageT *NanoappMessage::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
-  std::unique_ptr<chre::fbs::NanoappMessageT> _o = std::unique_ptr<chre::fbs::NanoappMessageT>(new NanoappMessageT());
-  UnPackTo(_o.get(), _resolver);
-  return _o.release();
+  auto _o = new NanoappMessageT();
+  UnPackTo(_o, _resolver);
+  return _o;
 }
 
 inline void NanoappMessage::UnPackTo(NanoappMessageT *_o, const flatbuffers::resolver_function_t *_resolver) const {
   (void)_o;
   (void)_resolver;
-  { auto _e = app_id(); _o->app_id = _e; }
-  { auto _e = message_type(); _o->message_type = _e; }
-  { auto _e = host_endpoint(); _o->host_endpoint = _e; }
-  { auto _e = message(); if (_e) { _o->message.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->message[_i] = _e->Get(_i); } } }
+  { auto _e = app_id(); _o->app_id = _e; };
+  { auto _e = message_type(); _o->message_type = _e; };
+  { auto _e = host_endpoint(); _o->host_endpoint = _e; };
+  { auto _e = message(); if (_e) for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->message.push_back(_e->Get(_i)); } };
 }
 
 inline flatbuffers::Offset<NanoappMessage> NanoappMessage::Pack(flatbuffers::FlatBufferBuilder &_fbb, const NanoappMessageT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
@@ -2444,7 +2132,6 @@
 inline flatbuffers::Offset<NanoappMessage> CreateNanoappMessage(flatbuffers::FlatBufferBuilder &_fbb, const NanoappMessageT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
   (void)_rehasher;
   (void)_o;
-  struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const NanoappMessageT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
   auto _app_id = _o->app_id;
   auto _message_type = _o->message_type;
   auto _host_endpoint = _o->host_endpoint;
@@ -2458,9 +2145,9 @@
 }
 
 inline HubInfoRequestT *HubInfoRequest::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
-  std::unique_ptr<chre::fbs::HubInfoRequestT> _o = std::unique_ptr<chre::fbs::HubInfoRequestT>(new HubInfoRequestT());
-  UnPackTo(_o.get(), _resolver);
-  return _o.release();
+  auto _o = new HubInfoRequestT();
+  UnPackTo(_o, _resolver);
+  return _o;
 }
 
 inline void HubInfoRequest::UnPackTo(HubInfoRequestT *_o, const flatbuffers::resolver_function_t *_resolver) const {
@@ -2475,32 +2162,31 @@
 inline flatbuffers::Offset<HubInfoRequest> CreateHubInfoRequest(flatbuffers::FlatBufferBuilder &_fbb, const HubInfoRequestT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
   (void)_rehasher;
   (void)_o;
-  struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const HubInfoRequestT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
   return chre::fbs::CreateHubInfoRequest(
       _fbb);
 }
 
 inline HubInfoResponseT *HubInfoResponse::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
-  std::unique_ptr<chre::fbs::HubInfoResponseT> _o = std::unique_ptr<chre::fbs::HubInfoResponseT>(new HubInfoResponseT());
-  UnPackTo(_o.get(), _resolver);
-  return _o.release();
+  auto _o = new HubInfoResponseT();
+  UnPackTo(_o, _resolver);
+  return _o;
 }
 
 inline void HubInfoResponse::UnPackTo(HubInfoResponseT *_o, const flatbuffers::resolver_function_t *_resolver) const {
   (void)_o;
   (void)_resolver;
-  { auto _e = name(); if (_e) { _o->name.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->name[_i] = _e->Get(_i); } } }
-  { auto _e = vendor(); if (_e) { _o->vendor.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->vendor[_i] = _e->Get(_i); } } }
-  { auto _e = toolchain(); if (_e) { _o->toolchain.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->toolchain[_i] = _e->Get(_i); } } }
-  { auto _e = platform_version(); _o->platform_version = _e; }
-  { auto _e = toolchain_version(); _o->toolchain_version = _e; }
-  { auto _e = peak_mips(); _o->peak_mips = _e; }
-  { auto _e = stopped_power(); _o->stopped_power = _e; }
-  { auto _e = sleep_power(); _o->sleep_power = _e; }
-  { auto _e = peak_power(); _o->peak_power = _e; }
-  { auto _e = max_msg_len(); _o->max_msg_len = _e; }
-  { auto _e = platform_id(); _o->platform_id = _e; }
-  { auto _e = chre_platform_version(); _o->chre_platform_version = _e; }
+  { auto _e = name(); if (_e) for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->name.push_back(_e->Get(_i)); } };
+  { auto _e = vendor(); if (_e) for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->vendor.push_back(_e->Get(_i)); } };
+  { auto _e = toolchain(); if (_e) for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->toolchain.push_back(_e->Get(_i)); } };
+  { auto _e = platform_version(); _o->platform_version = _e; };
+  { auto _e = toolchain_version(); _o->toolchain_version = _e; };
+  { auto _e = peak_mips(); _o->peak_mips = _e; };
+  { auto _e = stopped_power(); _o->stopped_power = _e; };
+  { auto _e = sleep_power(); _o->sleep_power = _e; };
+  { auto _e = peak_power(); _o->peak_power = _e; };
+  { auto _e = max_msg_len(); _o->max_msg_len = _e; };
+  { auto _e = platform_id(); _o->platform_id = _e; };
+  { auto _e = chre_platform_version(); _o->chre_platform_version = _e; };
 }
 
 inline flatbuffers::Offset<HubInfoResponse> HubInfoResponse::Pack(flatbuffers::FlatBufferBuilder &_fbb, const HubInfoResponseT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
@@ -2510,7 +2196,6 @@
 inline flatbuffers::Offset<HubInfoResponse> CreateHubInfoResponse(flatbuffers::FlatBufferBuilder &_fbb, const HubInfoResponseT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
   (void)_rehasher;
   (void)_o;
-  struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const HubInfoResponseT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
   auto _name = _o->name.size() ? _fbb.CreateVector(_o->name) : 0;
   auto _vendor = _o->vendor.size() ? _fbb.CreateVector(_o->vendor) : 0;
   auto _toolchain = _o->toolchain.size() ? _fbb.CreateVector(_o->toolchain) : 0;
@@ -2540,9 +2225,9 @@
 }
 
 inline NanoappListRequestT *NanoappListRequest::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
-  std::unique_ptr<chre::fbs::NanoappListRequestT> _o = std::unique_ptr<chre::fbs::NanoappListRequestT>(new NanoappListRequestT());
-  UnPackTo(_o.get(), _resolver);
-  return _o.release();
+  auto _o = new NanoappListRequestT();
+  UnPackTo(_o, _resolver);
+  return _o;
 }
 
 inline void NanoappListRequest::UnPackTo(NanoappListRequestT *_o, const flatbuffers::resolver_function_t *_resolver) const {
@@ -2557,24 +2242,23 @@
 inline flatbuffers::Offset<NanoappListRequest> CreateNanoappListRequest(flatbuffers::FlatBufferBuilder &_fbb, const NanoappListRequestT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
   (void)_rehasher;
   (void)_o;
-  struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const NanoappListRequestT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
   return chre::fbs::CreateNanoappListRequest(
       _fbb);
 }
 
 inline NanoappListEntryT *NanoappListEntry::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
-  std::unique_ptr<chre::fbs::NanoappListEntryT> _o = std::unique_ptr<chre::fbs::NanoappListEntryT>(new NanoappListEntryT());
-  UnPackTo(_o.get(), _resolver);
-  return _o.release();
+  auto _o = new NanoappListEntryT();
+  UnPackTo(_o, _resolver);
+  return _o;
 }
 
 inline void NanoappListEntry::UnPackTo(NanoappListEntryT *_o, const flatbuffers::resolver_function_t *_resolver) const {
   (void)_o;
   (void)_resolver;
-  { auto _e = app_id(); _o->app_id = _e; }
-  { auto _e = version(); _o->version = _e; }
-  { auto _e = enabled(); _o->enabled = _e; }
-  { auto _e = is_system(); _o->is_system = _e; }
+  { auto _e = app_id(); _o->app_id = _e; };
+  { auto _e = version(); _o->version = _e; };
+  { auto _e = enabled(); _o->enabled = _e; };
+  { auto _e = is_system(); _o->is_system = _e; };
 }
 
 inline flatbuffers::Offset<NanoappListEntry> NanoappListEntry::Pack(flatbuffers::FlatBufferBuilder &_fbb, const NanoappListEntryT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
@@ -2584,7 +2268,6 @@
 inline flatbuffers::Offset<NanoappListEntry> CreateNanoappListEntry(flatbuffers::FlatBufferBuilder &_fbb, const NanoappListEntryT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
   (void)_rehasher;
   (void)_o;
-  struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const NanoappListEntryT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
   auto _app_id = _o->app_id;
   auto _version = _o->version;
   auto _enabled = _o->enabled;
@@ -2598,15 +2281,15 @@
 }
 
 inline NanoappListResponseT *NanoappListResponse::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
-  std::unique_ptr<chre::fbs::NanoappListResponseT> _o = std::unique_ptr<chre::fbs::NanoappListResponseT>(new NanoappListResponseT());
-  UnPackTo(_o.get(), _resolver);
-  return _o.release();
+  auto _o = new NanoappListResponseT();
+  UnPackTo(_o, _resolver);
+  return _o;
 }
 
 inline void NanoappListResponse::UnPackTo(NanoappListResponseT *_o, const flatbuffers::resolver_function_t *_resolver) const {
   (void)_o;
   (void)_resolver;
-  { auto _e = nanoapps(); if (_e) { _o->nanoapps.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->nanoapps[_i] = std::unique_ptr<chre::fbs::NanoappListEntryT>(_e->Get(_i)->UnPack(_resolver)); } } }
+  { auto _e = nanoapps(); if (_e) for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->nanoapps.push_back(std::unique_ptr<NanoappListEntryT>(_e->Get(_i)->UnPack(_resolver))); } };
 }
 
 inline flatbuffers::Offset<NanoappListResponse> NanoappListResponse::Pack(flatbuffers::FlatBufferBuilder &_fbb, const NanoappListResponseT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
@@ -2616,30 +2299,29 @@
 inline flatbuffers::Offset<NanoappListResponse> CreateNanoappListResponse(flatbuffers::FlatBufferBuilder &_fbb, const NanoappListResponseT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
   (void)_rehasher;
   (void)_o;
-  struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const NanoappListResponseT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
-  auto _nanoapps = _fbb.CreateVector<flatbuffers::Offset<chre::fbs::NanoappListEntry>> (_o->nanoapps.size(), [](size_t i, _VectorArgs *__va) { return CreateNanoappListEntry(*__va->__fbb, __va->__o->nanoapps[i].get(), __va->__rehasher); }, &_va );
+  auto _nanoapps = _fbb.CreateVector<flatbuffers::Offset<NanoappListEntry>>(_o->nanoapps.size(), [&](size_t i) { return CreateNanoappListEntry(_fbb, _o->nanoapps[i].get(), _rehasher); });
   return chre::fbs::CreateNanoappListResponse(
       _fbb,
       _nanoapps);
 }
 
 inline LoadNanoappRequestT *LoadNanoappRequest::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
-  std::unique_ptr<chre::fbs::LoadNanoappRequestT> _o = std::unique_ptr<chre::fbs::LoadNanoappRequestT>(new LoadNanoappRequestT());
-  UnPackTo(_o.get(), _resolver);
-  return _o.release();
+  auto _o = new LoadNanoappRequestT();
+  UnPackTo(_o, _resolver);
+  return _o;
 }
 
 inline void LoadNanoappRequest::UnPackTo(LoadNanoappRequestT *_o, const flatbuffers::resolver_function_t *_resolver) const {
   (void)_o;
   (void)_resolver;
-  { auto _e = transaction_id(); _o->transaction_id = _e; }
-  { auto _e = app_id(); _o->app_id = _e; }
-  { auto _e = app_version(); _o->app_version = _e; }
-  { auto _e = target_api_version(); _o->target_api_version = _e; }
-  { auto _e = app_binary(); if (_e) { _o->app_binary.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->app_binary[_i] = _e->Get(_i); } } }
-  { auto _e = fragment_id(); _o->fragment_id = _e; }
-  { auto _e = total_app_size(); _o->total_app_size = _e; }
-  { auto _e = app_binary_file_name(); if (_e) { _o->app_binary_file_name.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->app_binary_file_name[_i] = _e->Get(_i); } } }
+  { auto _e = transaction_id(); _o->transaction_id = _e; };
+  { auto _e = app_id(); _o->app_id = _e; };
+  { auto _e = app_version(); _o->app_version = _e; };
+  { auto _e = target_api_version(); _o->target_api_version = _e; };
+  { auto _e = app_binary(); if (_e) for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->app_binary.push_back(_e->Get(_i)); } };
+  { auto _e = fragment_id(); _o->fragment_id = _e; };
+  { auto _e = total_app_size(); _o->total_app_size = _e; };
+  { auto _e = app_binary_file_name(); if (_e) for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->app_binary_file_name.push_back(_e->Get(_i)); } };
 }
 
 inline flatbuffers::Offset<LoadNanoappRequest> LoadNanoappRequest::Pack(flatbuffers::FlatBufferBuilder &_fbb, const LoadNanoappRequestT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
@@ -2649,7 +2331,6 @@
 inline flatbuffers::Offset<LoadNanoappRequest> CreateLoadNanoappRequest(flatbuffers::FlatBufferBuilder &_fbb, const LoadNanoappRequestT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
   (void)_rehasher;
   (void)_o;
-  struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const LoadNanoappRequestT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
   auto _transaction_id = _o->transaction_id;
   auto _app_id = _o->app_id;
   auto _app_version = _o->app_version;
@@ -2671,17 +2352,17 @@
 }
 
 inline LoadNanoappResponseT *LoadNanoappResponse::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
-  std::unique_ptr<chre::fbs::LoadNanoappResponseT> _o = std::unique_ptr<chre::fbs::LoadNanoappResponseT>(new LoadNanoappResponseT());
-  UnPackTo(_o.get(), _resolver);
-  return _o.release();
+  auto _o = new LoadNanoappResponseT();
+  UnPackTo(_o, _resolver);
+  return _o;
 }
 
 inline void LoadNanoappResponse::UnPackTo(LoadNanoappResponseT *_o, const flatbuffers::resolver_function_t *_resolver) const {
   (void)_o;
   (void)_resolver;
-  { auto _e = transaction_id(); _o->transaction_id = _e; }
-  { auto _e = success(); _o->success = _e; }
-  { auto _e = fragment_id(); _o->fragment_id = _e; }
+  { auto _e = transaction_id(); _o->transaction_id = _e; };
+  { auto _e = success(); _o->success = _e; };
+  { auto _e = fragment_id(); _o->fragment_id = _e; };
 }
 
 inline flatbuffers::Offset<LoadNanoappResponse> LoadNanoappResponse::Pack(flatbuffers::FlatBufferBuilder &_fbb, const LoadNanoappResponseT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
@@ -2691,7 +2372,6 @@
 inline flatbuffers::Offset<LoadNanoappResponse> CreateLoadNanoappResponse(flatbuffers::FlatBufferBuilder &_fbb, const LoadNanoappResponseT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
   (void)_rehasher;
   (void)_o;
-  struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const LoadNanoappResponseT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
   auto _transaction_id = _o->transaction_id;
   auto _success = _o->success;
   auto _fragment_id = _o->fragment_id;
@@ -2703,17 +2383,17 @@
 }
 
 inline UnloadNanoappRequestT *UnloadNanoappRequest::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
-  std::unique_ptr<chre::fbs::UnloadNanoappRequestT> _o = std::unique_ptr<chre::fbs::UnloadNanoappRequestT>(new UnloadNanoappRequestT());
-  UnPackTo(_o.get(), _resolver);
-  return _o.release();
+  auto _o = new UnloadNanoappRequestT();
+  UnPackTo(_o, _resolver);
+  return _o;
 }
 
 inline void UnloadNanoappRequest::UnPackTo(UnloadNanoappRequestT *_o, const flatbuffers::resolver_function_t *_resolver) const {
   (void)_o;
   (void)_resolver;
-  { auto _e = transaction_id(); _o->transaction_id = _e; }
-  { auto _e = app_id(); _o->app_id = _e; }
-  { auto _e = allow_system_nanoapp_unload(); _o->allow_system_nanoapp_unload = _e; }
+  { auto _e = transaction_id(); _o->transaction_id = _e; };
+  { auto _e = app_id(); _o->app_id = _e; };
+  { auto _e = allow_system_nanoapp_unload(); _o->allow_system_nanoapp_unload = _e; };
 }
 
 inline flatbuffers::Offset<UnloadNanoappRequest> UnloadNanoappRequest::Pack(flatbuffers::FlatBufferBuilder &_fbb, const UnloadNanoappRequestT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
@@ -2723,7 +2403,6 @@
 inline flatbuffers::Offset<UnloadNanoappRequest> CreateUnloadNanoappRequest(flatbuffers::FlatBufferBuilder &_fbb, const UnloadNanoappRequestT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
   (void)_rehasher;
   (void)_o;
-  struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const UnloadNanoappRequestT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
   auto _transaction_id = _o->transaction_id;
   auto _app_id = _o->app_id;
   auto _allow_system_nanoapp_unload = _o->allow_system_nanoapp_unload;
@@ -2735,16 +2414,16 @@
 }
 
 inline UnloadNanoappResponseT *UnloadNanoappResponse::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
-  std::unique_ptr<chre::fbs::UnloadNanoappResponseT> _o = std::unique_ptr<chre::fbs::UnloadNanoappResponseT>(new UnloadNanoappResponseT());
-  UnPackTo(_o.get(), _resolver);
-  return _o.release();
+  auto _o = new UnloadNanoappResponseT();
+  UnPackTo(_o, _resolver);
+  return _o;
 }
 
 inline void UnloadNanoappResponse::UnPackTo(UnloadNanoappResponseT *_o, const flatbuffers::resolver_function_t *_resolver) const {
   (void)_o;
   (void)_resolver;
-  { auto _e = transaction_id(); _o->transaction_id = _e; }
-  { auto _e = success(); _o->success = _e; }
+  { auto _e = transaction_id(); _o->transaction_id = _e; };
+  { auto _e = success(); _o->success = _e; };
 }
 
 inline flatbuffers::Offset<UnloadNanoappResponse> UnloadNanoappResponse::Pack(flatbuffers::FlatBufferBuilder &_fbb, const UnloadNanoappResponseT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
@@ -2754,7 +2433,6 @@
 inline flatbuffers::Offset<UnloadNanoappResponse> CreateUnloadNanoappResponse(flatbuffers::FlatBufferBuilder &_fbb, const UnloadNanoappResponseT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
   (void)_rehasher;
   (void)_o;
-  struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const UnloadNanoappResponseT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
   auto _transaction_id = _o->transaction_id;
   auto _success = _o->success;
   return chre::fbs::CreateUnloadNanoappResponse(
@@ -2764,15 +2442,15 @@
 }
 
 inline LogMessageT *LogMessage::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
-  std::unique_ptr<chre::fbs::LogMessageT> _o = std::unique_ptr<chre::fbs::LogMessageT>(new LogMessageT());
-  UnPackTo(_o.get(), _resolver);
-  return _o.release();
+  auto _o = new LogMessageT();
+  UnPackTo(_o, _resolver);
+  return _o;
 }
 
 inline void LogMessage::UnPackTo(LogMessageT *_o, const flatbuffers::resolver_function_t *_resolver) const {
   (void)_o;
   (void)_resolver;
-  { auto _e = buffer(); if (_e) { _o->buffer.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->buffer[_i] = _e->Get(_i); } } }
+  { auto _e = buffer(); if (_e) for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->buffer.push_back(_e->Get(_i)); } };
 }
 
 inline flatbuffers::Offset<LogMessage> LogMessage::Pack(flatbuffers::FlatBufferBuilder &_fbb, const LogMessageT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
@@ -2782,7 +2460,6 @@
 inline flatbuffers::Offset<LogMessage> CreateLogMessage(flatbuffers::FlatBufferBuilder &_fbb, const LogMessageT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
   (void)_rehasher;
   (void)_o;
-  struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const LogMessageT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
   auto _buffer = _o->buffer.size() ? _fbb.CreateVector(_o->buffer) : 0;
   return chre::fbs::CreateLogMessage(
       _fbb,
@@ -2790,15 +2467,15 @@
 }
 
 inline TimeSyncMessageT *TimeSyncMessage::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
-  std::unique_ptr<chre::fbs::TimeSyncMessageT> _o = std::unique_ptr<chre::fbs::TimeSyncMessageT>(new TimeSyncMessageT());
-  UnPackTo(_o.get(), _resolver);
-  return _o.release();
+  auto _o = new TimeSyncMessageT();
+  UnPackTo(_o, _resolver);
+  return _o;
 }
 
 inline void TimeSyncMessage::UnPackTo(TimeSyncMessageT *_o, const flatbuffers::resolver_function_t *_resolver) const {
   (void)_o;
   (void)_resolver;
-  { auto _e = offset(); _o->offset = _e; }
+  { auto _e = offset(); _o->offset = _e; };
 }
 
 inline flatbuffers::Offset<TimeSyncMessage> TimeSyncMessage::Pack(flatbuffers::FlatBufferBuilder &_fbb, const TimeSyncMessageT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
@@ -2808,7 +2485,6 @@
 inline flatbuffers::Offset<TimeSyncMessage> CreateTimeSyncMessage(flatbuffers::FlatBufferBuilder &_fbb, const TimeSyncMessageT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
   (void)_rehasher;
   (void)_o;
-  struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const TimeSyncMessageT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
   auto _offset = _o->offset;
   return chre::fbs::CreateTimeSyncMessage(
       _fbb,
@@ -2816,9 +2492,9 @@
 }
 
 inline DebugDumpRequestT *DebugDumpRequest::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
-  std::unique_ptr<chre::fbs::DebugDumpRequestT> _o = std::unique_ptr<chre::fbs::DebugDumpRequestT>(new DebugDumpRequestT());
-  UnPackTo(_o.get(), _resolver);
-  return _o.release();
+  auto _o = new DebugDumpRequestT();
+  UnPackTo(_o, _resolver);
+  return _o;
 }
 
 inline void DebugDumpRequest::UnPackTo(DebugDumpRequestT *_o, const flatbuffers::resolver_function_t *_resolver) const {
@@ -2833,21 +2509,20 @@
 inline flatbuffers::Offset<DebugDumpRequest> CreateDebugDumpRequest(flatbuffers::FlatBufferBuilder &_fbb, const DebugDumpRequestT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
   (void)_rehasher;
   (void)_o;
-  struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const DebugDumpRequestT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
   return chre::fbs::CreateDebugDumpRequest(
       _fbb);
 }
 
 inline DebugDumpDataT *DebugDumpData::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
-  std::unique_ptr<chre::fbs::DebugDumpDataT> _o = std::unique_ptr<chre::fbs::DebugDumpDataT>(new DebugDumpDataT());
-  UnPackTo(_o.get(), _resolver);
-  return _o.release();
+  auto _o = new DebugDumpDataT();
+  UnPackTo(_o, _resolver);
+  return _o;
 }
 
 inline void DebugDumpData::UnPackTo(DebugDumpDataT *_o, const flatbuffers::resolver_function_t *_resolver) const {
   (void)_o;
   (void)_resolver;
-  { auto _e = debug_str(); if (_e) { _o->debug_str.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->debug_str[_i] = _e->Get(_i); } } }
+  { auto _e = debug_str(); if (_e) for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->debug_str.push_back(_e->Get(_i)); } };
 }
 
 inline flatbuffers::Offset<DebugDumpData> DebugDumpData::Pack(flatbuffers::FlatBufferBuilder &_fbb, const DebugDumpDataT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
@@ -2857,7 +2532,6 @@
 inline flatbuffers::Offset<DebugDumpData> CreateDebugDumpData(flatbuffers::FlatBufferBuilder &_fbb, const DebugDumpDataT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
   (void)_rehasher;
   (void)_o;
-  struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const DebugDumpDataT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
   auto _debug_str = _o->debug_str.size() ? _fbb.CreateVector(_o->debug_str) : 0;
   return chre::fbs::CreateDebugDumpData(
       _fbb,
@@ -2865,16 +2539,16 @@
 }
 
 inline DebugDumpResponseT *DebugDumpResponse::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
-  std::unique_ptr<chre::fbs::DebugDumpResponseT> _o = std::unique_ptr<chre::fbs::DebugDumpResponseT>(new DebugDumpResponseT());
-  UnPackTo(_o.get(), _resolver);
-  return _o.release();
+  auto _o = new DebugDumpResponseT();
+  UnPackTo(_o, _resolver);
+  return _o;
 }
 
 inline void DebugDumpResponse::UnPackTo(DebugDumpResponseT *_o, const flatbuffers::resolver_function_t *_resolver) const {
   (void)_o;
   (void)_resolver;
-  { auto _e = success(); _o->success = _e; }
-  { auto _e = data_count(); _o->data_count = _e; }
+  { auto _e = success(); _o->success = _e; };
+  { auto _e = data_count(); _o->data_count = _e; };
 }
 
 inline flatbuffers::Offset<DebugDumpResponse> DebugDumpResponse::Pack(flatbuffers::FlatBufferBuilder &_fbb, const DebugDumpResponseT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
@@ -2884,7 +2558,6 @@
 inline flatbuffers::Offset<DebugDumpResponse> CreateDebugDumpResponse(flatbuffers::FlatBufferBuilder &_fbb, const DebugDumpResponseT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
   (void)_rehasher;
   (void)_o;
-  struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const DebugDumpResponseT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
   auto _success = _o->success;
   auto _data_count = _o->data_count;
   return chre::fbs::CreateDebugDumpResponse(
@@ -2894,9 +2567,9 @@
 }
 
 inline TimeSyncRequestT *TimeSyncRequest::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
-  std::unique_ptr<chre::fbs::TimeSyncRequestT> _o = std::unique_ptr<chre::fbs::TimeSyncRequestT>(new TimeSyncRequestT());
-  UnPackTo(_o.get(), _resolver);
-  return _o.release();
+  auto _o = new TimeSyncRequestT();
+  UnPackTo(_o, _resolver);
+  return _o;
 }
 
 inline void TimeSyncRequest::UnPackTo(TimeSyncRequestT *_o, const flatbuffers::resolver_function_t *_resolver) const {
@@ -2911,15 +2584,14 @@
 inline flatbuffers::Offset<TimeSyncRequest> CreateTimeSyncRequest(flatbuffers::FlatBufferBuilder &_fbb, const TimeSyncRequestT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
   (void)_rehasher;
   (void)_o;
-  struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const TimeSyncRequestT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
   return chre::fbs::CreateTimeSyncRequest(
       _fbb);
 }
 
 inline LowPowerMicAccessRequestT *LowPowerMicAccessRequest::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
-  std::unique_ptr<chre::fbs::LowPowerMicAccessRequestT> _o = std::unique_ptr<chre::fbs::LowPowerMicAccessRequestT>(new LowPowerMicAccessRequestT());
-  UnPackTo(_o.get(), _resolver);
-  return _o.release();
+  auto _o = new LowPowerMicAccessRequestT();
+  UnPackTo(_o, _resolver);
+  return _o;
 }
 
 inline void LowPowerMicAccessRequest::UnPackTo(LowPowerMicAccessRequestT *_o, const flatbuffers::resolver_function_t *_resolver) const {
@@ -2934,15 +2606,14 @@
 inline flatbuffers::Offset<LowPowerMicAccessRequest> CreateLowPowerMicAccessRequest(flatbuffers::FlatBufferBuilder &_fbb, const LowPowerMicAccessRequestT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
   (void)_rehasher;
   (void)_o;
-  struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const LowPowerMicAccessRequestT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
   return chre::fbs::CreateLowPowerMicAccessRequest(
       _fbb);
 }
 
 inline LowPowerMicAccessReleaseT *LowPowerMicAccessRelease::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
-  std::unique_ptr<chre::fbs::LowPowerMicAccessReleaseT> _o = std::unique_ptr<chre::fbs::LowPowerMicAccessReleaseT>(new LowPowerMicAccessReleaseT());
-  UnPackTo(_o.get(), _resolver);
-  return _o.release();
+  auto _o = new LowPowerMicAccessReleaseT();
+  UnPackTo(_o, _resolver);
+  return _o;
 }
 
 inline void LowPowerMicAccessRelease::UnPackTo(LowPowerMicAccessReleaseT *_o, const flatbuffers::resolver_function_t *_resolver) const {
@@ -2957,22 +2628,21 @@
 inline flatbuffers::Offset<LowPowerMicAccessRelease> CreateLowPowerMicAccessRelease(flatbuffers::FlatBufferBuilder &_fbb, const LowPowerMicAccessReleaseT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
   (void)_rehasher;
   (void)_o;
-  struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const LowPowerMicAccessReleaseT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
   return chre::fbs::CreateLowPowerMicAccessRelease(
       _fbb);
 }
 
 inline SettingChangeMessageT *SettingChangeMessage::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
-  std::unique_ptr<chre::fbs::SettingChangeMessageT> _o = std::unique_ptr<chre::fbs::SettingChangeMessageT>(new SettingChangeMessageT());
-  UnPackTo(_o.get(), _resolver);
-  return _o.release();
+  auto _o = new SettingChangeMessageT();
+  UnPackTo(_o, _resolver);
+  return _o;
 }
 
 inline void SettingChangeMessage::UnPackTo(SettingChangeMessageT *_o, const flatbuffers::resolver_function_t *_resolver) const {
   (void)_o;
   (void)_resolver;
-  { auto _e = setting(); _o->setting = _e; }
-  { auto _e = state(); _o->state = _e; }
+  { auto _e = setting(); _o->setting = _e; };
+  { auto _e = state(); _o->state = _e; };
 }
 
 inline flatbuffers::Offset<SettingChangeMessage> SettingChangeMessage::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SettingChangeMessageT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
@@ -2982,7 +2652,6 @@
 inline flatbuffers::Offset<SettingChangeMessage> CreateSettingChangeMessage(flatbuffers::FlatBufferBuilder &_fbb, const SettingChangeMessageT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
   (void)_rehasher;
   (void)_o;
-  struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const SettingChangeMessageT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
   auto _setting = _o->setting;
   auto _state = _o->state;
   return chre::fbs::CreateSettingChangeMessage(
@@ -2992,17 +2661,17 @@
 }
 
 inline MessageContainerT *MessageContainer::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
-  std::unique_ptr<chre::fbs::MessageContainerT> _o = std::unique_ptr<chre::fbs::MessageContainerT>(new MessageContainerT());
-  UnPackTo(_o.get(), _resolver);
-  return _o.release();
+  auto _o = new MessageContainerT();
+  UnPackTo(_o, _resolver);
+  return _o;
 }
 
 inline void MessageContainer::UnPackTo(MessageContainerT *_o, const flatbuffers::resolver_function_t *_resolver) const {
   (void)_o;
   (void)_resolver;
-  { auto _e = message_type(); _o->message.type = _e; }
-  { auto _e = message(); if (_e) _o->message.value = chre::fbs::ChreMessageUnion::UnPack(_e, message_type(), _resolver); }
-  { auto _e = host_addr(); if (_e) _o->host_addr = std::unique_ptr<chre::fbs::HostAddress>(new chre::fbs::HostAddress(*_e)); }
+  { auto _e = message_type(); _o->message.type = _e; };
+  { auto _e = message(); if (_e) _o->message.table = ChreMessageUnion::UnPack(_e, message_type(),_resolver); };
+  { auto _e = host_addr(); if (_e) _o->host_addr = std::unique_ptr<HostAddress>(new HostAddress(*_e)); };
 }
 
 inline flatbuffers::Offset<MessageContainer> MessageContainer::Pack(flatbuffers::FlatBufferBuilder &_fbb, const MessageContainerT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
@@ -3012,7 +2681,6 @@
 inline flatbuffers::Offset<MessageContainer> CreateMessageContainer(flatbuffers::FlatBufferBuilder &_fbb, const MessageContainerT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
   (void)_rehasher;
   (void)_o;
-  struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const MessageContainerT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
   auto _message_type = _o->message.type;
   auto _message = _o->message.Pack(_fbb);
   auto _host_addr = _o->host_addr ? _o->host_addr.get() : 0;
@@ -3029,83 +2697,82 @@
       return true;
     }
     case ChreMessage::NanoappMessage: {
-      auto ptr = reinterpret_cast<const chre::fbs::NanoappMessage *>(obj);
+      auto ptr = reinterpret_cast<const NanoappMessage *>(obj);
       return verifier.VerifyTable(ptr);
     }
     case ChreMessage::HubInfoRequest: {
-      auto ptr = reinterpret_cast<const chre::fbs::HubInfoRequest *>(obj);
+      auto ptr = reinterpret_cast<const HubInfoRequest *>(obj);
       return verifier.VerifyTable(ptr);
     }
     case ChreMessage::HubInfoResponse: {
-      auto ptr = reinterpret_cast<const chre::fbs::HubInfoResponse *>(obj);
+      auto ptr = reinterpret_cast<const HubInfoResponse *>(obj);
       return verifier.VerifyTable(ptr);
     }
     case ChreMessage::NanoappListRequest: {
-      auto ptr = reinterpret_cast<const chre::fbs::NanoappListRequest *>(obj);
+      auto ptr = reinterpret_cast<const NanoappListRequest *>(obj);
       return verifier.VerifyTable(ptr);
     }
     case ChreMessage::NanoappListResponse: {
-      auto ptr = reinterpret_cast<const chre::fbs::NanoappListResponse *>(obj);
+      auto ptr = reinterpret_cast<const NanoappListResponse *>(obj);
       return verifier.VerifyTable(ptr);
     }
     case ChreMessage::LoadNanoappRequest: {
-      auto ptr = reinterpret_cast<const chre::fbs::LoadNanoappRequest *>(obj);
+      auto ptr = reinterpret_cast<const LoadNanoappRequest *>(obj);
       return verifier.VerifyTable(ptr);
     }
     case ChreMessage::LoadNanoappResponse: {
-      auto ptr = reinterpret_cast<const chre::fbs::LoadNanoappResponse *>(obj);
+      auto ptr = reinterpret_cast<const LoadNanoappResponse *>(obj);
       return verifier.VerifyTable(ptr);
     }
     case ChreMessage::UnloadNanoappRequest: {
-      auto ptr = reinterpret_cast<const chre::fbs::UnloadNanoappRequest *>(obj);
+      auto ptr = reinterpret_cast<const UnloadNanoappRequest *>(obj);
       return verifier.VerifyTable(ptr);
     }
     case ChreMessage::UnloadNanoappResponse: {
-      auto ptr = reinterpret_cast<const chre::fbs::UnloadNanoappResponse *>(obj);
+      auto ptr = reinterpret_cast<const UnloadNanoappResponse *>(obj);
       return verifier.VerifyTable(ptr);
     }
     case ChreMessage::LogMessage: {
-      auto ptr = reinterpret_cast<const chre::fbs::LogMessage *>(obj);
+      auto ptr = reinterpret_cast<const LogMessage *>(obj);
       return verifier.VerifyTable(ptr);
     }
     case ChreMessage::TimeSyncMessage: {
-      auto ptr = reinterpret_cast<const chre::fbs::TimeSyncMessage *>(obj);
+      auto ptr = reinterpret_cast<const TimeSyncMessage *>(obj);
       return verifier.VerifyTable(ptr);
     }
     case ChreMessage::DebugDumpRequest: {
-      auto ptr = reinterpret_cast<const chre::fbs::DebugDumpRequest *>(obj);
+      auto ptr = reinterpret_cast<const DebugDumpRequest *>(obj);
       return verifier.VerifyTable(ptr);
     }
     case ChreMessage::DebugDumpData: {
-      auto ptr = reinterpret_cast<const chre::fbs::DebugDumpData *>(obj);
+      auto ptr = reinterpret_cast<const DebugDumpData *>(obj);
       return verifier.VerifyTable(ptr);
     }
     case ChreMessage::DebugDumpResponse: {
-      auto ptr = reinterpret_cast<const chre::fbs::DebugDumpResponse *>(obj);
+      auto ptr = reinterpret_cast<const DebugDumpResponse *>(obj);
       return verifier.VerifyTable(ptr);
     }
     case ChreMessage::TimeSyncRequest: {
-      auto ptr = reinterpret_cast<const chre::fbs::TimeSyncRequest *>(obj);
+      auto ptr = reinterpret_cast<const TimeSyncRequest *>(obj);
       return verifier.VerifyTable(ptr);
     }
     case ChreMessage::LowPowerMicAccessRequest: {
-      auto ptr = reinterpret_cast<const chre::fbs::LowPowerMicAccessRequest *>(obj);
+      auto ptr = reinterpret_cast<const LowPowerMicAccessRequest *>(obj);
       return verifier.VerifyTable(ptr);
     }
     case ChreMessage::LowPowerMicAccessRelease: {
-      auto ptr = reinterpret_cast<const chre::fbs::LowPowerMicAccessRelease *>(obj);
+      auto ptr = reinterpret_cast<const LowPowerMicAccessRelease *>(obj);
       return verifier.VerifyTable(ptr);
     }
     case ChreMessage::SettingChangeMessage: {
-      auto ptr = reinterpret_cast<const chre::fbs::SettingChangeMessage *>(obj);
+      auto ptr = reinterpret_cast<const SettingChangeMessage *>(obj);
       return verifier.VerifyTable(ptr);
     }
-    default: return true;
+    default: return false;
   }
 }
 
 inline bool VerifyChreMessageVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types) {
-  if (!values || !types) return !values && !types;
   if (values->size() != types->size()) return false;
   for (flatbuffers::uoffset_t i = 0; i < values->size(); ++i) {
     if (!VerifyChreMessage(
@@ -3116,78 +2783,78 @@
   return true;
 }
 
-inline void *ChreMessageUnion::UnPack(const void *obj, ChreMessage type, const flatbuffers::resolver_function_t *resolver) {
+inline flatbuffers::NativeTable *ChreMessageUnion::UnPack(const void *obj, ChreMessage type, const flatbuffers::resolver_function_t *resolver) {
   switch (type) {
     case ChreMessage::NanoappMessage: {
-      auto ptr = reinterpret_cast<const chre::fbs::NanoappMessage *>(obj);
+      auto ptr = reinterpret_cast<const NanoappMessage *>(obj);
       return ptr->UnPack(resolver);
     }
     case ChreMessage::HubInfoRequest: {
-      auto ptr = reinterpret_cast<const chre::fbs::HubInfoRequest *>(obj);
+      auto ptr = reinterpret_cast<const HubInfoRequest *>(obj);
       return ptr->UnPack(resolver);
     }
     case ChreMessage::HubInfoResponse: {
-      auto ptr = reinterpret_cast<const chre::fbs::HubInfoResponse *>(obj);
+      auto ptr = reinterpret_cast<const HubInfoResponse *>(obj);
       return ptr->UnPack(resolver);
     }
     case ChreMessage::NanoappListRequest: {
-      auto ptr = reinterpret_cast<const chre::fbs::NanoappListRequest *>(obj);
+      auto ptr = reinterpret_cast<const NanoappListRequest *>(obj);
       return ptr->UnPack(resolver);
     }
     case ChreMessage::NanoappListResponse: {
-      auto ptr = reinterpret_cast<const chre::fbs::NanoappListResponse *>(obj);
+      auto ptr = reinterpret_cast<const NanoappListResponse *>(obj);
       return ptr->UnPack(resolver);
     }
     case ChreMessage::LoadNanoappRequest: {
-      auto ptr = reinterpret_cast<const chre::fbs::LoadNanoappRequest *>(obj);
+      auto ptr = reinterpret_cast<const LoadNanoappRequest *>(obj);
       return ptr->UnPack(resolver);
     }
     case ChreMessage::LoadNanoappResponse: {
-      auto ptr = reinterpret_cast<const chre::fbs::LoadNanoappResponse *>(obj);
+      auto ptr = reinterpret_cast<const LoadNanoappResponse *>(obj);
       return ptr->UnPack(resolver);
     }
     case ChreMessage::UnloadNanoappRequest: {
-      auto ptr = reinterpret_cast<const chre::fbs::UnloadNanoappRequest *>(obj);
+      auto ptr = reinterpret_cast<const UnloadNanoappRequest *>(obj);
       return ptr->UnPack(resolver);
     }
     case ChreMessage::UnloadNanoappResponse: {
-      auto ptr = reinterpret_cast<const chre::fbs::UnloadNanoappResponse *>(obj);
+      auto ptr = reinterpret_cast<const UnloadNanoappResponse *>(obj);
       return ptr->UnPack(resolver);
     }
     case ChreMessage::LogMessage: {
-      auto ptr = reinterpret_cast<const chre::fbs::LogMessage *>(obj);
+      auto ptr = reinterpret_cast<const LogMessage *>(obj);
       return ptr->UnPack(resolver);
     }
     case ChreMessage::TimeSyncMessage: {
-      auto ptr = reinterpret_cast<const chre::fbs::TimeSyncMessage *>(obj);
+      auto ptr = reinterpret_cast<const TimeSyncMessage *>(obj);
       return ptr->UnPack(resolver);
     }
     case ChreMessage::DebugDumpRequest: {
-      auto ptr = reinterpret_cast<const chre::fbs::DebugDumpRequest *>(obj);
+      auto ptr = reinterpret_cast<const DebugDumpRequest *>(obj);
       return ptr->UnPack(resolver);
     }
     case ChreMessage::DebugDumpData: {
-      auto ptr = reinterpret_cast<const chre::fbs::DebugDumpData *>(obj);
+      auto ptr = reinterpret_cast<const DebugDumpData *>(obj);
       return ptr->UnPack(resolver);
     }
     case ChreMessage::DebugDumpResponse: {
-      auto ptr = reinterpret_cast<const chre::fbs::DebugDumpResponse *>(obj);
+      auto ptr = reinterpret_cast<const DebugDumpResponse *>(obj);
       return ptr->UnPack(resolver);
     }
     case ChreMessage::TimeSyncRequest: {
-      auto ptr = reinterpret_cast<const chre::fbs::TimeSyncRequest *>(obj);
+      auto ptr = reinterpret_cast<const TimeSyncRequest *>(obj);
       return ptr->UnPack(resolver);
     }
     case ChreMessage::LowPowerMicAccessRequest: {
-      auto ptr = reinterpret_cast<const chre::fbs::LowPowerMicAccessRequest *>(obj);
+      auto ptr = reinterpret_cast<const LowPowerMicAccessRequest *>(obj);
       return ptr->UnPack(resolver);
     }
     case ChreMessage::LowPowerMicAccessRelease: {
-      auto ptr = reinterpret_cast<const chre::fbs::LowPowerMicAccessRelease *>(obj);
+      auto ptr = reinterpret_cast<const LowPowerMicAccessRelease *>(obj);
       return ptr->UnPack(resolver);
     }
     case ChreMessage::SettingChangeMessage: {
-      auto ptr = reinterpret_cast<const chre::fbs::SettingChangeMessage *>(obj);
+      auto ptr = reinterpret_cast<const SettingChangeMessage *>(obj);
       return ptr->UnPack(resolver);
     }
     default: return nullptr;
@@ -3197,255 +2864,176 @@
 inline flatbuffers::Offset<void> ChreMessageUnion::Pack(flatbuffers::FlatBufferBuilder &_fbb, const flatbuffers::rehasher_function_t *_rehasher) const {
   switch (type) {
     case ChreMessage::NanoappMessage: {
-      auto ptr = reinterpret_cast<const chre::fbs::NanoappMessageT *>(value);
+      auto ptr = reinterpret_cast<const NanoappMessageT *>(table);
       return CreateNanoappMessage(_fbb, ptr, _rehasher).Union();
     }
     case ChreMessage::HubInfoRequest: {
-      auto ptr = reinterpret_cast<const chre::fbs::HubInfoRequestT *>(value);
+      auto ptr = reinterpret_cast<const HubInfoRequestT *>(table);
       return CreateHubInfoRequest(_fbb, ptr, _rehasher).Union();
     }
     case ChreMessage::HubInfoResponse: {
-      auto ptr = reinterpret_cast<const chre::fbs::HubInfoResponseT *>(value);
+      auto ptr = reinterpret_cast<const HubInfoResponseT *>(table);
       return CreateHubInfoResponse(_fbb, ptr, _rehasher).Union();
     }
     case ChreMessage::NanoappListRequest: {
-      auto ptr = reinterpret_cast<const chre::fbs::NanoappListRequestT *>(value);
+      auto ptr = reinterpret_cast<const NanoappListRequestT *>(table);
       return CreateNanoappListRequest(_fbb, ptr, _rehasher).Union();
     }
     case ChreMessage::NanoappListResponse: {
-      auto ptr = reinterpret_cast<const chre::fbs::NanoappListResponseT *>(value);
+      auto ptr = reinterpret_cast<const NanoappListResponseT *>(table);
       return CreateNanoappListResponse(_fbb, ptr, _rehasher).Union();
     }
     case ChreMessage::LoadNanoappRequest: {
-      auto ptr = reinterpret_cast<const chre::fbs::LoadNanoappRequestT *>(value);
+      auto ptr = reinterpret_cast<const LoadNanoappRequestT *>(table);
       return CreateLoadNanoappRequest(_fbb, ptr, _rehasher).Union();
     }
     case ChreMessage::LoadNanoappResponse: {
-      auto ptr = reinterpret_cast<const chre::fbs::LoadNanoappResponseT *>(value);
+      auto ptr = reinterpret_cast<const LoadNanoappResponseT *>(table);
       return CreateLoadNanoappResponse(_fbb, ptr, _rehasher).Union();
     }
     case ChreMessage::UnloadNanoappRequest: {
-      auto ptr = reinterpret_cast<const chre::fbs::UnloadNanoappRequestT *>(value);
+      auto ptr = reinterpret_cast<const UnloadNanoappRequestT *>(table);
       return CreateUnloadNanoappRequest(_fbb, ptr, _rehasher).Union();
     }
     case ChreMessage::UnloadNanoappResponse: {
-      auto ptr = reinterpret_cast<const chre::fbs::UnloadNanoappResponseT *>(value);
+      auto ptr = reinterpret_cast<const UnloadNanoappResponseT *>(table);
       return CreateUnloadNanoappResponse(_fbb, ptr, _rehasher).Union();
     }
     case ChreMessage::LogMessage: {
-      auto ptr = reinterpret_cast<const chre::fbs::LogMessageT *>(value);
+      auto ptr = reinterpret_cast<const LogMessageT *>(table);
       return CreateLogMessage(_fbb, ptr, _rehasher).Union();
     }
     case ChreMessage::TimeSyncMessage: {
-      auto ptr = reinterpret_cast<const chre::fbs::TimeSyncMessageT *>(value);
+      auto ptr = reinterpret_cast<const TimeSyncMessageT *>(table);
       return CreateTimeSyncMessage(_fbb, ptr, _rehasher).Union();
     }
     case ChreMessage::DebugDumpRequest: {
-      auto ptr = reinterpret_cast<const chre::fbs::DebugDumpRequestT *>(value);
+      auto ptr = reinterpret_cast<const DebugDumpRequestT *>(table);
       return CreateDebugDumpRequest(_fbb, ptr, _rehasher).Union();
     }
     case ChreMessage::DebugDumpData: {
-      auto ptr = reinterpret_cast<const chre::fbs::DebugDumpDataT *>(value);
+      auto ptr = reinterpret_cast<const DebugDumpDataT *>(table);
       return CreateDebugDumpData(_fbb, ptr, _rehasher).Union();
     }
     case ChreMessage::DebugDumpResponse: {
-      auto ptr = reinterpret_cast<const chre::fbs::DebugDumpResponseT *>(value);
+      auto ptr = reinterpret_cast<const DebugDumpResponseT *>(table);
       return CreateDebugDumpResponse(_fbb, ptr, _rehasher).Union();
     }
     case ChreMessage::TimeSyncRequest: {
-      auto ptr = reinterpret_cast<const chre::fbs::TimeSyncRequestT *>(value);
+      auto ptr = reinterpret_cast<const TimeSyncRequestT *>(table);
       return CreateTimeSyncRequest(_fbb, ptr, _rehasher).Union();
     }
     case ChreMessage::LowPowerMicAccessRequest: {
-      auto ptr = reinterpret_cast<const chre::fbs::LowPowerMicAccessRequestT *>(value);
+      auto ptr = reinterpret_cast<const LowPowerMicAccessRequestT *>(table);
       return CreateLowPowerMicAccessRequest(_fbb, ptr, _rehasher).Union();
     }
     case ChreMessage::LowPowerMicAccessRelease: {
-      auto ptr = reinterpret_cast<const chre::fbs::LowPowerMicAccessReleaseT *>(value);
+      auto ptr = reinterpret_cast<const LowPowerMicAccessReleaseT *>(table);
       return CreateLowPowerMicAccessRelease(_fbb, ptr, _rehasher).Union();
     }
     case ChreMessage::SettingChangeMessage: {
-      auto ptr = reinterpret_cast<const chre::fbs::SettingChangeMessageT *>(value);
+      auto ptr = reinterpret_cast<const SettingChangeMessageT *>(table);
       return CreateSettingChangeMessage(_fbb, ptr, _rehasher).Union();
     }
     default: return 0;
   }
 }
 
-inline ChreMessageUnion::ChreMessageUnion(const ChreMessageUnion &u) : type(u.type), value(nullptr) {
-  switch (type) {
-    case ChreMessage::NanoappMessage: {
-      value = new chre::fbs::NanoappMessageT(*reinterpret_cast<chre::fbs::NanoappMessageT *>(u.value));
-      break;
-    }
-    case ChreMessage::HubInfoRequest: {
-      value = new chre::fbs::HubInfoRequestT(*reinterpret_cast<chre::fbs::HubInfoRequestT *>(u.value));
-      break;
-    }
-    case ChreMessage::HubInfoResponse: {
-      value = new chre::fbs::HubInfoResponseT(*reinterpret_cast<chre::fbs::HubInfoResponseT *>(u.value));
-      break;
-    }
-    case ChreMessage::NanoappListRequest: {
-      value = new chre::fbs::NanoappListRequestT(*reinterpret_cast<chre::fbs::NanoappListRequestT *>(u.value));
-      break;
-    }
-    case ChreMessage::NanoappListResponse: {
-      FLATBUFFERS_ASSERT(false);  // chre::fbs::NanoappListResponseT not copyable.
-      break;
-    }
-    case ChreMessage::LoadNanoappRequest: {
-      value = new chre::fbs::LoadNanoappRequestT(*reinterpret_cast<chre::fbs::LoadNanoappRequestT *>(u.value));
-      break;
-    }
-    case ChreMessage::LoadNanoappResponse: {
-      value = new chre::fbs::LoadNanoappResponseT(*reinterpret_cast<chre::fbs::LoadNanoappResponseT *>(u.value));
-      break;
-    }
-    case ChreMessage::UnloadNanoappRequest: {
-      value = new chre::fbs::UnloadNanoappRequestT(*reinterpret_cast<chre::fbs::UnloadNanoappRequestT *>(u.value));
-      break;
-    }
-    case ChreMessage::UnloadNanoappResponse: {
-      value = new chre::fbs::UnloadNanoappResponseT(*reinterpret_cast<chre::fbs::UnloadNanoappResponseT *>(u.value));
-      break;
-    }
-    case ChreMessage::LogMessage: {
-      value = new chre::fbs::LogMessageT(*reinterpret_cast<chre::fbs::LogMessageT *>(u.value));
-      break;
-    }
-    case ChreMessage::TimeSyncMessage: {
-      value = new chre::fbs::TimeSyncMessageT(*reinterpret_cast<chre::fbs::TimeSyncMessageT *>(u.value));
-      break;
-    }
-    case ChreMessage::DebugDumpRequest: {
-      value = new chre::fbs::DebugDumpRequestT(*reinterpret_cast<chre::fbs::DebugDumpRequestT *>(u.value));
-      break;
-    }
-    case ChreMessage::DebugDumpData: {
-      value = new chre::fbs::DebugDumpDataT(*reinterpret_cast<chre::fbs::DebugDumpDataT *>(u.value));
-      break;
-    }
-    case ChreMessage::DebugDumpResponse: {
-      value = new chre::fbs::DebugDumpResponseT(*reinterpret_cast<chre::fbs::DebugDumpResponseT *>(u.value));
-      break;
-    }
-    case ChreMessage::TimeSyncRequest: {
-      value = new chre::fbs::TimeSyncRequestT(*reinterpret_cast<chre::fbs::TimeSyncRequestT *>(u.value));
-      break;
-    }
-    case ChreMessage::LowPowerMicAccessRequest: {
-      value = new chre::fbs::LowPowerMicAccessRequestT(*reinterpret_cast<chre::fbs::LowPowerMicAccessRequestT *>(u.value));
-      break;
-    }
-    case ChreMessage::LowPowerMicAccessRelease: {
-      value = new chre::fbs::LowPowerMicAccessReleaseT(*reinterpret_cast<chre::fbs::LowPowerMicAccessReleaseT *>(u.value));
-      break;
-    }
-    case ChreMessage::SettingChangeMessage: {
-      value = new chre::fbs::SettingChangeMessageT(*reinterpret_cast<chre::fbs::SettingChangeMessageT *>(u.value));
-      break;
-    }
-    default:
-      break;
-  }
-}
-
 inline void ChreMessageUnion::Reset() {
   switch (type) {
     case ChreMessage::NanoappMessage: {
-      auto ptr = reinterpret_cast<chre::fbs::NanoappMessageT *>(value);
+      auto ptr = reinterpret_cast<NanoappMessageT *>(table);
       delete ptr;
       break;
     }
     case ChreMessage::HubInfoRequest: {
-      auto ptr = reinterpret_cast<chre::fbs::HubInfoRequestT *>(value);
+      auto ptr = reinterpret_cast<HubInfoRequestT *>(table);
       delete ptr;
       break;
     }
     case ChreMessage::HubInfoResponse: {
-      auto ptr = reinterpret_cast<chre::fbs::HubInfoResponseT *>(value);
+      auto ptr = reinterpret_cast<HubInfoResponseT *>(table);
       delete ptr;
       break;
     }
     case ChreMessage::NanoappListRequest: {
-      auto ptr = reinterpret_cast<chre::fbs::NanoappListRequestT *>(value);
+      auto ptr = reinterpret_cast<NanoappListRequestT *>(table);
       delete ptr;
       break;
     }
     case ChreMessage::NanoappListResponse: {
-      auto ptr = reinterpret_cast<chre::fbs::NanoappListResponseT *>(value);
+      auto ptr = reinterpret_cast<NanoappListResponseT *>(table);
       delete ptr;
       break;
     }
     case ChreMessage::LoadNanoappRequest: {
-      auto ptr = reinterpret_cast<chre::fbs::LoadNanoappRequestT *>(value);
+      auto ptr = reinterpret_cast<LoadNanoappRequestT *>(table);
       delete ptr;
       break;
     }
     case ChreMessage::LoadNanoappResponse: {
-      auto ptr = reinterpret_cast<chre::fbs::LoadNanoappResponseT *>(value);
+      auto ptr = reinterpret_cast<LoadNanoappResponseT *>(table);
       delete ptr;
       break;
     }
     case ChreMessage::UnloadNanoappRequest: {
-      auto ptr = reinterpret_cast<chre::fbs::UnloadNanoappRequestT *>(value);
+      auto ptr = reinterpret_cast<UnloadNanoappRequestT *>(table);
       delete ptr;
       break;
     }
     case ChreMessage::UnloadNanoappResponse: {
-      auto ptr = reinterpret_cast<chre::fbs::UnloadNanoappResponseT *>(value);
+      auto ptr = reinterpret_cast<UnloadNanoappResponseT *>(table);
       delete ptr;
       break;
     }
     case ChreMessage::LogMessage: {
-      auto ptr = reinterpret_cast<chre::fbs::LogMessageT *>(value);
+      auto ptr = reinterpret_cast<LogMessageT *>(table);
       delete ptr;
       break;
     }
     case ChreMessage::TimeSyncMessage: {
-      auto ptr = reinterpret_cast<chre::fbs::TimeSyncMessageT *>(value);
+      auto ptr = reinterpret_cast<TimeSyncMessageT *>(table);
       delete ptr;
       break;
     }
     case ChreMessage::DebugDumpRequest: {
-      auto ptr = reinterpret_cast<chre::fbs::DebugDumpRequestT *>(value);
+      auto ptr = reinterpret_cast<DebugDumpRequestT *>(table);
       delete ptr;
       break;
     }
     case ChreMessage::DebugDumpData: {
-      auto ptr = reinterpret_cast<chre::fbs::DebugDumpDataT *>(value);
+      auto ptr = reinterpret_cast<DebugDumpDataT *>(table);
       delete ptr;
       break;
     }
     case ChreMessage::DebugDumpResponse: {
-      auto ptr = reinterpret_cast<chre::fbs::DebugDumpResponseT *>(value);
+      auto ptr = reinterpret_cast<DebugDumpResponseT *>(table);
       delete ptr;
       break;
     }
     case ChreMessage::TimeSyncRequest: {
-      auto ptr = reinterpret_cast<chre::fbs::TimeSyncRequestT *>(value);
+      auto ptr = reinterpret_cast<TimeSyncRequestT *>(table);
       delete ptr;
       break;
     }
     case ChreMessage::LowPowerMicAccessRequest: {
-      auto ptr = reinterpret_cast<chre::fbs::LowPowerMicAccessRequestT *>(value);
+      auto ptr = reinterpret_cast<LowPowerMicAccessRequestT *>(table);
       delete ptr;
       break;
     }
     case ChreMessage::LowPowerMicAccessRelease: {
-      auto ptr = reinterpret_cast<chre::fbs::LowPowerMicAccessReleaseT *>(value);
+      auto ptr = reinterpret_cast<LowPowerMicAccessReleaseT *>(table);
       delete ptr;
       break;
     }
     case ChreMessage::SettingChangeMessage: {
-      auto ptr = reinterpret_cast<chre::fbs::SettingChangeMessageT *>(value);
+      auto ptr = reinterpret_cast<SettingChangeMessageT *>(table);
       delete ptr;
       break;
     }
     default: break;
   }
-  value = nullptr;
+  table = nullptr;
   type = ChreMessage::NONE;
 }
 
@@ -3453,10 +3041,6 @@
   return flatbuffers::GetRoot<chre::fbs::MessageContainer>(buf);
 }
 
-inline const chre::fbs::MessageContainer *GetSizePrefixedMessageContainer(const void *buf) {
-  return flatbuffers::GetSizePrefixedRoot<chre::fbs::MessageContainer>(buf);
-}
-
 inline MessageContainer *GetMutableMessageContainer(void *buf) {
   return flatbuffers::GetMutableRoot<MessageContainer>(buf);
 }
@@ -3466,33 +3050,16 @@
   return verifier.VerifyBuffer<chre::fbs::MessageContainer>(nullptr);
 }
 
-inline bool VerifySizePrefixedMessageContainerBuffer(
-    flatbuffers::Verifier &verifier) {
-  return verifier.VerifySizePrefixedBuffer<chre::fbs::MessageContainer>(nullptr);
-}
-
 inline void FinishMessageContainerBuffer(
     flatbuffers::FlatBufferBuilder &fbb,
     flatbuffers::Offset<chre::fbs::MessageContainer> root) {
   fbb.Finish(root);
 }
 
-inline void FinishSizePrefixedMessageContainerBuffer(
-    flatbuffers::FlatBufferBuilder &fbb,
-    flatbuffers::Offset<chre::fbs::MessageContainer> root) {
-  fbb.FinishSizePrefixed(root);
-}
-
-inline std::unique_ptr<chre::fbs::MessageContainerT> UnPackMessageContainer(
+inline std::unique_ptr<MessageContainerT> UnPackMessageContainer(
     const void *buf,
     const flatbuffers::resolver_function_t *res = nullptr) {
-  return std::unique_ptr<chre::fbs::MessageContainerT>(GetMessageContainer(buf)->UnPack(res));
-}
-
-inline std::unique_ptr<chre::fbs::MessageContainerT> UnPackSizePrefixedMessageContainer(
-    const void *buf,
-    const flatbuffers::resolver_function_t *res = nullptr) {
-  return std::unique_ptr<chre::fbs::MessageContainerT>(GetSizePrefixedMessageContainer(buf)->UnPack(res));
+  return std::unique_ptr<MessageContainerT>(GetMessageContainer(buf)->UnPack(res));
 }
 
 }  // namespace fbs
diff --git a/host/common/include/chre_host/log_message_parser_base.h b/host/common/include/chre_host/log_message_parser_base.h
index e949ce3..932c196 100644
--- a/host/common/include/chre_host/log_message_parser_base.h
+++ b/host/common/include/chre_host/log_message_parser_base.h
@@ -46,8 +46,7 @@
     return true;
   };
 
-  virtual void log(const uint8_t * /* logBuffer */,
-                   size_t /* logBufferSize */) {}
+  virtual void log(const uint8_t *logBuffer, size_t logBufferSize);
 
   /**
    * With verbose logging enabled (via enableVerbose()), dump a
@@ -71,6 +70,21 @@
 
   void emitLogMessage(uint8_t level, uint64_t timestampNanos,
                       const char *logMessage);
+
+ private:
+  enum LogLevel : uint8_t {
+    ERROR = 1,
+    WARNING = 2,
+    INFO = 3,
+    DEBUG = 4,
+  };
+
+  //! See host_messages.fbs for the definition of this struct.
+  struct LogMessage {
+    enum LogLevel logLevel;
+    uint64_t timestampNanos;
+    char logMessage[];
+  } __attribute__((packed));
 };
 
 }  // namespace chre
diff --git a/host/common/include/chre_host/tokenized_log_message_parser.h b/host/common/include/chre_host/tokenized_log_message_parser.h
index d82140d..7677b38 100644
--- a/host/common/include/chre_host/tokenized_log_message_parser.h
+++ b/host/common/include/chre_host/tokenized_log_message_parser.h
@@ -18,6 +18,7 @@
 #define CHRE_TOKENIZED_LOG_MESSAGE_PARSER_H_
 
 #include <memory>
+#include "chre_host/daemon_base.h"
 #include "chre_host/log_message_parser_base.h"
 
 #include "pw_tokenizer/detokenize.h"
@@ -25,12 +26,14 @@
 using pw::tokenizer::DetokenizedString;
 using pw::tokenizer::Detokenizer;
 
+namespace android {
 namespace chre {
 
 class ChreTokenizedLogMessageParser : public ChreLogMessageParserBase {
  public:
   virtual bool init() override final {
     mDetokenizer = logDetokenizerInit();
+    return mDetokenizer != nullptr;
   }
 
   virtual void log(const uint8_t *logBuffer,
@@ -55,7 +58,7 @@
     constexpr const char kLogDatabaseFilePath[] =
         "/vendor/etc/chre/libchre_log_database.bin";
     std::vector<uint8_t> tokenData;
-    if (readFileContents(kLogDatabaseFilePath, &tokenData)) {
+    if (ChreDaemonBase::readFileContents(kLogDatabaseFilePath, &tokenData)) {
       pw::tokenizer::TokenDatabase database =
           pw::tokenizer::TokenDatabase::Create(tokenData);
       if (database.ok()) {
@@ -71,7 +74,7 @@
 
   // Log messages are routed through ashLog if tokenized logging
   // is disabled, so only parse tokenized log messages here.
-  void parseAndEmitTokenizedLogMessages(unsigned char *message,
+  void parseAndEmitTokenizedLogMessages(const uint8_t *message,
                                         unsigned int messageLen,
                                         const Detokenizer *detokenizer) {
     if (detokenizer != nullptr) {
@@ -80,24 +83,16 @@
       // logs (b/148873804)
       constexpr size_t kLogMessageHeaderSize =
           1 /*logLevel*/ + sizeof(uint64_t) /*timestamp*/;
-
-      const fbs::MessageContainer *container =
-          fbs::GetMessageContainer(message);
-      const auto *logMessage =
-          static_cast<const fbs::LogMessage *>(container->message());
-
-      const flatbuffers::Vector<int8_t> &logData = *logMessage->buffer();
-      const uint8_t *log = reinterpret_cast<const uint8_t *>(logData.data());
-      uint8_t level = *log;
-      ++log;
+      uint8_t level = *message;
+      ++message;
 
       uint64_t timestampNanos;
-      memcpy(&timestampNanos, log, sizeof(uint64_t));
+      memcpy(&timestampNanos, message, sizeof(uint64_t));
       timestampNanos = le64toh(timestampNanos);
-      log += sizeof(uint64_t);
+      message += sizeof(uint64_t);
 
       DetokenizedString detokenizedLog =
-          detokenizer->Detokenize(log, messageLen - kLogMessageHeaderSize);
+          detokenizer->Detokenize(message, messageLen - kLogMessageHeaderSize);
       std::string decodedLog = detokenizedLog.BestStringWithErrors();
       emitLogMessage(level, timestampNanos, decodedLog.c_str());
     } else {
@@ -107,5 +102,6 @@
 };
 
 }  // namespace chre
+}  // namespace android
 
 #endif  // CHRE_TOKENIZED_LOG_MESSAGE_PARSER_H_
\ No newline at end of file
diff --git a/host/common/log_message_parser_base.cc b/host/common/log_message_parser_base.cc
index 86d70d5..3de5002 100644
--- a/host/common/log_message_parser_base.cc
+++ b/host/common/log_message_parser_base.cc
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <endian.h>
 #include <cstdio>
 
 #include "chre_host/log_message_parser_base.h"
@@ -27,14 +28,6 @@
 #else
 constexpr bool kVerboseLoggingEnabled = false;
 #endif
-
-enum ChreLogLevel : uint8_t {
-  LOG_LEVEL_ERROR = 0,
-  LOG_LEVEL_WARN = 1,
-  LOG_LEVEL_INFO = 2,
-  LOG_LEVEL_DEBUG = 3
-};
-
 }  // anonymous namespace
 
 ChreLogMessageParserBase::ChreLogMessageParserBase()
@@ -85,19 +78,33 @@
 android_LogPriority ChreLogMessageParserBase::chreLogLevelToAndroidLogPriority(
     uint8_t level) {
   switch (level) {
-    case LOG_LEVEL_ERROR:
+    case LogLevel::ERROR:
       return ANDROID_LOG_ERROR;
-    case LOG_LEVEL_WARN:
+    case LogLevel::WARNING:
       return ANDROID_LOG_WARN;
-    case LOG_LEVEL_INFO:
+    case LogLevel::INFO:
       return ANDROID_LOG_INFO;
-    case LOG_LEVEL_DEBUG:
+    case LogLevel::DEBUG:
       return ANDROID_LOG_DEBUG;
     default:
       return ANDROID_LOG_SILENT;
   }
 }
 
+void ChreLogMessageParserBase::log(const uint8_t *logBuffer,
+                                   size_t logBufferSize) {
+  size_t bufferIndex = 0;
+  while (bufferIndex < logBufferSize) {
+    const LogMessage *message =
+        reinterpret_cast<const LogMessage *>(&logBuffer[bufferIndex]);
+    emitLogMessage(message->logLevel, le64toh(message->timestampNanos),
+                   message->logMessage);
+    bufferIndex += sizeof(LogMessage) +
+                   strnlen(message->logMessage, logBufferSize - bufferIndex) +
+                   1;
+  }
+}
+
 void ChreLogMessageParserBase::emitLogMessage(uint8_t level,
                                               uint64_t timestampNanos,
                                               const char *logMessage) {
diff --git a/host/msm/daemon/fastrpc_daemon.cc b/host/msm/daemon/fastrpc_daemon.cc
index 5ba4ccc..7ffe5c0 100644
--- a/host/msm/daemon/fastrpc_daemon.cc
+++ b/host/msm/daemon/fastrpc_daemon.cc
@@ -147,7 +147,13 @@
   }
 
   if (messageType == fbs::ChreMessage::LogMessage) {
-    mLogger.log(messageBuffer, messageLen);
+    std::unique_ptr<fbs::MessageContainerT> container =
+        fbs::UnPackMessageContainer(messageBuffer);
+    const auto *logMessage = container->message.AsLogMessage();
+    const std::vector<int8_t> &logData = logMessage->buffer;
+
+    mLogger.log(reinterpret_cast<const uint8_t *>(logData.data()),
+                logData.size());
   } else if (messageType == fbs::ChreMessage::TimeSyncRequest) {
     sendTimeSync(true /* logOnError */);
   } else if (messageType == fbs::ChreMessage::LowPowerMicAccessRequest) {
diff --git a/host/usf_daemon/main.cc b/host/usf_daemon/main.cc
new file mode 100644
index 0000000..0911d1f
--- /dev/null
+++ b/host/usf_daemon/main.cc
@@ -0,0 +1,33 @@
+/*
+ * 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 "usf_daemon.h"
+
+#include "chre_host/log.h"
+
+int main() {
+  LOGI("CHRE Starting!");
+
+  android::chre::UsfChreDaemon daemon;
+
+  if (!daemon.init()) {
+    LOGE("Failed to initialize the CHRE daemon..");
+  } else {
+    daemon.run();
+  }
+
+  return 0;
+}
diff --git a/host/usf_daemon/usf_daemon.cc b/host/usf_daemon/usf_daemon.cc
new file mode 100644
index 0000000..5b0d47c
--- /dev/null
+++ b/host/usf_daemon/usf_daemon.cc
@@ -0,0 +1,365 @@
+/*
+ * 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 "usf_daemon.h"
+
+#include <unistd.h>
+#include <chrono>
+#include <fstream>
+#include <thread>
+
+#include "usf/usf_client.h"
+
+// Aliased for consistency with the way these symbols are referenced in
+// CHRE-side code
+namespace fbs = ::chre::fbs;
+
+namespace android {
+namespace chre {
+
+namespace {
+
+using ReffedTransportClientPtr = refcount::reffed_ptr<usf::UsfTransportClient>;
+
+constexpr uint8_t kConnectRetries = 5;
+constexpr int kRetryDelayMilliSeconds = 100;
+
+bool connectToUsfWithRetry(ReffedTransportClientPtr &client) {
+  // client has already been nullptr-checked
+  uint8_t retryCount = 0;
+  bool success = false;
+  usf::UsfErr err;
+
+  while (retryCount < kConnectRetries) {
+    if ((err = client->Connect()) == usf::kErrNone) {
+      success = true;
+      break;
+    }
+    ++retryCount;
+    std::this_thread::sleep_for(
+        std::chrono::milliseconds(kRetryDelayMilliSeconds));
+  }
+
+  if (success) {
+    LOGD("Connected to USF Transport server (retry count: %u)", retryCount + 1);
+  }
+
+  return success;
+}
+
+}  // namespace
+
+bool UsfChreDaemon::init() {
+  constexpr size_t kMaxTimeSyncRetries = 5;
+  constexpr useconds_t kTimeSyncRetryDelayUs = 50000;  // 50 ms
+  bool success = false;
+  usf::UsfErr err;
+
+  if ((err = usf::UsfClientMgr::Init()) != usf::kErrNone) {
+    LOGE("Failed to initialize usf client mgr: (err %d)",
+         static_cast<int>(err));
+  } else if ((err = usf::UsfTransportClient::Create(
+                  &mConnection.transportClient)) != usf::kErrNone) {
+    LOGE("Failed to create a USF transport client: (err %d)",
+         static_cast<int>(err));
+  } else if (mConnection.transportClient == nullptr) {
+    LOGE("Init Failed: Created a NULL transport client!");
+  } else if (!connectToUsfWithRetry(mConnection.transportClient)) {
+    LOGE("Failed to  connect to USF transport server on %u retries",
+         kConnectRetries);
+  } else if ((err = usf::UsfTransportMgr::SetMsgHandler(
+                  usf::UsfMsgType_CHRE, UsfChreDaemon::usfMessageHandler,
+                  this)) != usf::kErrNone) {
+    LOGE("Failed to set Usf Message Handler");
+  } else if (!sendTimeSyncWithRetry(kMaxTimeSyncRetries, kTimeSyncRetryDelayUs,
+                                    true /* logOnError */)) {
+    LOGE("Failed to send initial time sync message");
+  } else {
+    mLogger = getLogMessageParser();
+    loadPreloadedNanoapps();
+    success = true;
+    LOGD("CHRE daemon initialized successfully");
+  }
+
+  return success;
+}
+
+void UsfChreDaemon::deinit() {
+  setShutdownRequested(true);
+  usf::UsfClientMgr::Deinit();
+}
+
+void UsfChreDaemon::run() {
+  constexpr char kChreSocketName[] = "chre";
+  auto serverCb = [&](uint16_t clientId, void *data, size_t len) {
+    sendMessageToChre(clientId, data, len);
+  };
+
+  mSocketServer.run(kChreSocketName, true /* allowSocketCreation */, serverCb);
+}
+
+usf::UsfErr UsfChreDaemon::sendUsfMessage(const uint8_t *data, size_t dataLen) {
+  usf::UsfTxMsg msg;
+
+  msg.SetMsgType(usf::UsfMsgType_CHRE);
+  msg.SetData(data, dataLen);
+
+  return mConnection.transportClient->SendMsg(&msg);
+}
+
+bool UsfChreDaemon::sendMessageToChre(uint16_t clientId, void *data,
+                                      size_t length) {
+  bool success = false;
+  usf::UsfErr err;
+
+  if (!HostProtocolHost::mutateHostClientId(data, length, clientId)) {
+    LOGE("Couldn't set host client ID in message container!");
+  } else {
+    LOGV("Delivering message from host (size %zu)", length);
+    if ((err = sendUsfMessage(static_cast<const uint8_t *>(data), length)) !=
+        usf::kErrNone) {
+      LOGE("Failed to deliver message from host to CHRE: %d",
+           static_cast<int>(err));
+    } else {
+      success = true;
+    }
+  }
+
+  return success;
+}
+
+// TODO(karthikmb): Consider moving platform independent parts of this
+// function to the base class, revisit when implementing the daemon for
+// another platform.
+void UsfChreDaemon::onMessageReceived(const unsigned char *messageBuffer,
+                                      size_t messageLen) {
+  mLogger.dump(messageBuffer, messageLen);
+
+  uint16_t hostClientId;
+  fbs::ChreMessage messageType;
+  if (!HostProtocolHost::extractHostClientIdAndType(
+          messageBuffer, messageLen, &hostClientId, &messageType)) {
+    LOGW(
+        "Failed to extract host client ID from message - sending "
+        "broadcast");
+    hostClientId = ::chre::kHostClientIdUnspecified;
+  }
+
+  if (messageType == fbs::ChreMessage::LogMessage) {
+    std::unique_ptr<fbs::MessageContainerT> container =
+        fbs::UnPackMessageContainer(messageBuffer);
+    const auto *logMessage = container->message.AsLogMessage();
+    const std::vector<int8_t> &logData = logMessage->buffer;
+
+    mLogger.log(reinterpret_cast<const uint8_t *>(logData.data()),
+                logData.size());
+  } else if (messageType == fbs::ChreMessage::TimeSyncRequest) {
+    sendTimeSync(true /* logOnError */);
+  } else if (messageType == fbs::ChreMessage::LowPowerMicAccessRequest) {
+    LOGD("LpmaRequest unsupported");
+  } else if (messageType == fbs::ChreMessage::LowPowerMicAccessRelease) {
+    LOGD("LpmaRelease unsupported");
+  } else if (hostClientId == kHostClientIdDaemon) {
+    handleDaemonMessage(messageBuffer);
+  } else if (hostClientId == ::chre::kHostClientIdUnspecified) {
+    mSocketServer.sendToAllClients(messageBuffer,
+                                   static_cast<size_t>(messageLen));
+  } else {
+    mSocketServer.sendToClientById(
+        messageBuffer, static_cast<size_t>(messageLen), hostClientId);
+  }
+}
+
+void UsfChreDaemon::handleDaemonMessage(const uint8_t *message) {
+  std::unique_ptr<fbs::MessageContainerT> container =
+      fbs::UnPackMessageContainer(message);
+  if (container->message.type != fbs::ChreMessage::LoadNanoappResponse) {
+    LOGE("Invalid message from CHRE directed to daemon");
+  } else {
+    const auto *response = container->message.AsLoadNanoappResponse();
+    std::unique_lock<std::mutex> lock(mPreloadedNanoappsMutex);
+
+    if (!mPreloadedNanoappPending) {
+      LOGE("Received nanoapp load response with no pending load");
+    } else if (mPreloadedNanoappPendingTransactionId !=
+               response->transaction_id) {
+      LOGE("Received nanoapp load response with invalid transaction id");
+    } else {
+      mPreloadedNanoappPending = false;
+    }
+
+    mPreloadedNanoappsCond.notify_all();
+  }
+}
+
+void UsfChreDaemon::loadPreloadedNanoapp(const std::string &directory,
+                                         const std::string &name,
+                                         uint32_t transactionId) {
+  std::vector<uint8_t> headerBuffer;
+  std::vector<uint8_t> nanoappBuffer;
+
+  std::string headerFilename = directory + "/" + name + ".napp_header";
+  std::string nanoappFilename = directory + "/" + name + ".so";
+
+  if (readFileContents(headerFilename, headerBuffer) &&
+      readFileContents(nanoappFilename, nanoappBuffer) &&
+      !loadNanoapp(headerBuffer, nanoappBuffer, transactionId)) {
+    LOGE("Failed to load nanoapp: '%s'", name.c_str());
+  }
+}
+
+bool UsfChreDaemon::readFileContents(const std::string &filename,
+                                     std::vector<uint8_t> &buffer) {
+  bool success = false;
+  std::ifstream file(filename.c_str(), std::ios::binary | std::ios::ate);
+  if (!file) {
+    LOGE("Couldn't open file '%s': %d (%s)", filename.c_str(), errno,
+         strerror(errno));
+  } else {
+    ssize_t size = file.tellg();
+    file.seekg(0, std::ios::beg);
+
+    buffer.resize(size);
+    if (!file.read(reinterpret_cast<char *>(buffer.data()), size)) {
+      LOGE("Couldn't read from file '%s': %d (%s)", filename.c_str(), errno,
+           strerror(errno));
+    } else {
+      success = true;
+    }
+  }
+
+  return success;
+}
+
+bool UsfChreDaemon::loadNanoapp(const std::vector<uint8_t> &header,
+                                const std::vector<uint8_t> &nanoapp,
+                                uint32_t transactionId) {
+  // This struct comes from build/build_template.mk and must not be modified.
+  // Refer to that file for more details.
+  struct NanoAppBinaryHeader {
+    uint32_t headerVersion;
+    uint32_t magic;
+    uint64_t appId;
+    uint32_t appVersion;
+    uint32_t flags;
+    uint64_t hwHubType;
+    uint8_t targetChreApiMajorVersion;
+    uint8_t targetChreApiMinorVersion;
+    uint8_t reserved[6];
+  } __attribute__((packed));
+
+  bool success = false;
+  if (header.size() != sizeof(NanoAppBinaryHeader)) {
+    LOGE("Header size mismatch");
+  } else {
+    // The header blob contains the struct above.
+    const auto *appHeader =
+        reinterpret_cast<const NanoAppBinaryHeader *>(header.data());
+
+    // Build the target API version from major and minor.
+    uint32_t targetApiVersion = (appHeader->targetChreApiMajorVersion << 24) |
+                                (appHeader->targetChreApiMinorVersion << 16);
+
+    success = sendFragmentedNanoappLoad(appHeader->appId, appHeader->appVersion,
+                                        targetApiVersion, nanoapp.data(),
+                                        nanoapp.size(), transactionId);
+  }
+
+  return success;
+}
+
+bool UsfChreDaemon::sendFragmentAndWaitOnResponse(
+    uint32_t transactionId, flatbuffers::FlatBufferBuilder &builder) {
+  bool success = true;
+  std::unique_lock<std::mutex> lock(mPreloadedNanoappsMutex);
+
+  mPreloadedNanoappPendingTransactionId = transactionId;
+  mPreloadedNanoappPending = sendMessageToChre(
+      kHostClientIdDaemon, builder.GetBufferPointer(), builder.GetSize());
+  if (!mPreloadedNanoappPending) {
+    LOGE("Failed to send nanoapp fragment");
+    success = false;
+  } else {
+    // 60s timeout for fragments. Set high for busy first bootups where the
+    // PALs can block CHRE initialization while other subsystems come up.
+    std::chrono::seconds timeout(60);
+    bool signaled = mPreloadedNanoappsCond.wait_for(
+        lock, timeout, [this] { return !mPreloadedNanoappPending; });
+
+    if (!signaled) {
+      LOGE("Nanoapp fragment load timed out");
+      success = false;
+    }
+  }
+  return success;
+}
+
+bool UsfChreDaemon::sendFragmentedNanoappLoad(
+    uint64_t appId, uint32_t appVersion, uint32_t appTargetApiVersion,
+    const uint8_t *appBinary, size_t appSize, uint32_t transactionId) {
+  // TODO: This is currently limited by the USF Message size, revisit
+  // and increase this when the USF message size increases.
+  constexpr size_t kFragmentSize = 512;
+  std::vector<uint8_t> binary(appSize);
+  std::copy(appBinary, appBinary + appSize, binary.begin());
+
+  FragmentedLoadTransaction transaction(transactionId, appId, appVersion,
+                                        appTargetApiVersion, binary,
+                                        kFragmentSize);
+
+  bool success = true;
+
+  while (success && !transaction.isComplete()) {
+    // Pad the builder to avoid allocation churn.
+    const auto &fragment = transaction.getNextRequest();
+    flatbuffers::FlatBufferBuilder builder(fragment.binary.size() + 128);
+    HostProtocolHost::encodeFragmentedLoadNanoappRequest(builder, fragment);
+    success = sendFragmentAndWaitOnResponse(transactionId, builder);
+  }
+
+  return success;
+}
+
+int64_t UsfChreDaemon::getTimeOffset(bool *success) {
+  LOGI("TODO: getTimeOffset is stubbed out, needs to be implemented");
+  *success = true;
+  return 0;
+}
+
+ChreLogMessageParserBase UsfChreDaemon::getLogMessageParser() {
+#ifdef CHRE_USE_TOKENIZED_LOGGING
+  return ChreTokenizedLogMessageParser();
+#else
+  return ChreLogMessageParserBase();
+#endif
+}
+
+usf::UsfErr UsfChreDaemon::usfMessageHandler(
+    usf::UsfTransport * /* transport */, const usf::UsfMsg *usfMsg, void *arg) {
+  usf::UsfErr err = usf::kErrInvalid;
+  auto *daemon = static_cast<UsfChreDaemon *>(arg);
+  if ((daemon != nullptr) && (usfMsg != nullptr)) {
+    const uint8_t *msgData = usfMsg->data()->data();
+    size_t msgLen = usfMsg->data()->size();
+    daemon->onMessageReceived(msgData, msgLen);
+  } else {
+    LOGE("Error Handling Usf Message");
+  }
+  return err;
+}
+
+}  // namespace chre
+}  // namespace android
diff --git a/host/usf_daemon/usf_daemon.h b/host/usf_daemon/usf_daemon.h
new file mode 100644
index 0000000..3c34e7c
--- /dev/null
+++ b/host/usf_daemon/usf_daemon.h
@@ -0,0 +1,166 @@
+/*
+ * 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_USF_DAEMON_H_
+#define CHRE_USF_DAEMON_H_
+
+#include "chre_host/daemon_base.h"
+#include "chre_host/socket_server.h"
+#ifdef CHRE_USE_TOKENIZED_LOGGING
+#include "chre_host/tokenized_log_message_parser.h"
+#else
+#include "chre_host/log_message_parser_base.h"
+#endif
+
+#include "usf/usf_transport_client.h"
+
+#include <utils/SystemClock.h>
+
+// Disable verbose logging
+// TODO: use property_get_bool to make verbose logging runtime configurable
+// #define LOG_NDEBUG 0
+
+namespace android {
+namespace chre {
+
+class UsfChreDaemon : public ChreDaemonBase {
+ public:
+  struct UsfServerConnection {
+    refcount::reffed_ptr<usf::UsfTransportClient> transportClient;
+    usf::UsfTransport *transport;
+    usf::UsfServerHandle serverHandle;
+  };
+
+  ~UsfChreDaemon() {
+    deinit();
+  }
+
+  /**
+   * Initializes the CHRE daemon, and creates a USF transport for
+   * communicating with CHRE
+   *
+   * @return true on successful init
+   */
+  bool init();
+
+  /**
+   * Starts a socket server receive loop for inbound messages
+   */
+  void run();
+
+  bool sendMessageToChre(uint16_t clientId, void *data, size_t length);
+
+  void onMessageReceived(const unsigned char *messageBuffer, size_t messageLen);
+
+  UsfServerConnection &getMutableServerConnection() {
+    return mConnection;
+  }
+
+ protected:
+  void loadPreloadedNanoapp(const std::string &directory,
+                            const std::string &name,
+                            uint32_t transactionId) override;
+
+  void handleDaemonMessage(const uint8_t *message) override;
+
+ private:
+  SocketServer mSocketServer;
+  ChreLogMessageParserBase mLogger;
+  UsfServerConnection mConnection;
+
+  //! The mutex used to guard state between the nanoapp messaging thread
+  //! and loading preloaded nanoapps.
+  std::mutex mPreloadedNanoappsMutex;
+
+  //! The condition variable used to wait for a nanoapp to finish loading.
+  std::condition_variable mPreloadedNanoappsCond;
+
+  //! Set to true when a preloaded nanoapp is pending load.
+  bool mPreloadedNanoappPending;
+
+  //! Set to the expected transaction ID for loading a nanoapp.
+  uint32_t mPreloadedNanoappPendingTransactionId;
+
+  /**
+   * Perform a graceful shutdown of the daemon
+   */
+  void deinit();
+
+  /**
+   * Platform specific getTimeOffset for the WHI Daemon
+   *
+   * @return clock drift offset in nanoseconds
+   */
+  int64_t getTimeOffset(bool *success);
+
+  /**
+   * Get the Log Message Parser configured for this platform
+   *
+   * @return An instance of a log message parser
+   */
+  ChreLogMessageParserBase getLogMessageParser();
+
+  /**
+   * Loads the supplied file into the provided buffer.
+   *
+   * @param filename The name of the file to load.
+   * @param buffer The buffer to load into.
+   * @return true if successful, false otherwise.
+   */
+  bool readFileContents(const std::string &filename,
+                        std::vector<uint8_t> &buffer);
+
+  /**
+   * Sends a preloaded nanoapp to CHRE.
+   *
+   * @param header The nanoapp header binary blob.
+   * @param nanoapp The nanoapp binary blob.
+   * @param transactionId The transaction ID to use when loading the app.
+   * @return true if succssful, false otherwise.
+   */
+  bool loadNanoapp(const std::vector<uint8_t> &header,
+                   const std::vector<uint8_t> &nanoapp, uint32_t transactionId);
+
+  /**
+   * Loads a nanoapp using fragments.
+   *
+   * @param appId The ID of the nanoapp to load.
+   * @param appVersion The version of the nanoapp to load.
+   * @param appTargetApiVersion The version of the CHRE API that the app
+   * targets.
+   * @param appBinary The application binary code.
+   * @param appSize The size of the appBinary.
+   * @param transactionId The transaction ID to use when loading.
+   * @return true if successful, false otherwise.
+   */
+  bool sendFragmentedNanoappLoad(uint64_t appId, uint32_t appVersion,
+                                 uint32_t appTargetApiVersion,
+                                 const uint8_t *appBinary, size_t appSize,
+                                 uint32_t transactionId);
+
+  static usf::UsfErr usfMessageHandler(usf::UsfTransport *transport,
+                                       const usf::UsfMsg *usfMsg, void *arg);
+
+  usf::UsfErr sendUsfMessage(const uint8_t *data, size_t dataLen);
+
+  bool sendFragmentAndWaitOnResponse(uint32_t transactionId,
+                                     flatbuffers::FlatBufferBuilder &builder);
+};
+
+}  // namespace chre
+}  // namespace android
+
+#endif  // CHRE_USF_DAEMON_H_
diff --git a/platform/aoc/chre_api_re.cc b/platform/aoc/chre_api_re.cc
new file mode 100644
index 0000000..00fa668
--- /dev/null
+++ b/platform/aoc/chre_api_re.cc
@@ -0,0 +1,36 @@
+/*
+ * 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 <cinttypes>
+
+#include "chre/platform/log.h"
+#include "chre/util/macros.h"
+#include "chre_api/chre/re.h"
+
+void chreLog(enum chreLogLevel level, const char *formatStr, ...) {
+  va_list args;
+  va_start(args, formatStr);
+
+  // TODO(karthikmb): Remove this once log buffering is implemented.
+  char logBuf[500];
+  va_list vsnargs;
+  va_copy(vsnargs, args);
+  vsnprintf(logBuf, sizeof(logBuf), formatStr, args);
+  va_end(vsnargs);
+  printf("CHRE: %s\n", logBuf);
+
+  chre::vaLog(level, formatStr, args);
+  va_end(args);
+}
diff --git a/platform/aoc/fatal_error.cc b/platform/aoc/fatal_error.cc
new file mode 100644
index 0000000..ae3903d
--- /dev/null
+++ b/platform/aoc/fatal_error.cc
@@ -0,0 +1,27 @@
+/*
+ * 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/target_platform/fatal_error.h"
+
+#include "chre/platform/shared/platform_log.h"
+
+namespace chre {
+
+void preFatalError() {
+  // TODO: stubbed out, Implement this.
+}
+
+}  // namespace chre
diff --git a/platform/aoc/host_link.cc b/platform/aoc/host_link.cc
new file mode 100644
index 0000000..57a173d
--- /dev/null
+++ b/platform/aoc/host_link.cc
@@ -0,0 +1,499 @@
+/*
+ * 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/platform/host_link.h"
+#include "chre/core/event_loop_manager.h"
+#include "chre/core/host_comms_manager.h"
+#include "chre/core/settings.h"
+#include "chre/platform/aoc/system_time.h"
+#include "chre/platform/freertos/dram_util.h"
+#include "chre/platform/shared/host_protocol_chre.h"
+#include "chre/platform/shared/nanoapp_load_manager.h"
+#include "chre/util/fixed_size_blocking_queue.h"
+#include "chre_api/chre/version.h"
+
+#include "usf/usf_transport.h"
+
+using flatbuffers::FlatBufferBuilder;
+
+namespace chre {
+
+namespace {
+
+//! The last time a time sync request message has been sent.
+//! TODO: Make this a member of HostLinkBase
+Nanoseconds gLastTimeSyncRequestNanos(0);
+
+//! Used to pass the client ID through the user data pointer in deferCallback
+union HostClientIdCallbackData {
+  uint16_t hostClientId;
+  void *ptr;
+};
+static_assert(sizeof(uint16_t) <= sizeof(void *),
+              "Pointer must at least fit a u16 for passing the host client ID");
+
+struct LoadNanoappCallbackData {
+  uint64_t appId;
+  uint32_t transactionId;
+  uint16_t hostClientId;
+  UniquePtr<Nanoapp> nanoapp;
+  uint32_t fragmentId;
+};
+
+/**
+ * Sends a request to the host for a time sync message.
+ */
+void sendTimeSyncRequest();
+
+// Forward declare the USF external message handler
+usf::UsfErr handleUsfMessage(usf::UsfTransport *transport,
+                             const usf::UsfMsg *msg, void *arg);
+
+// This class implements a basic wrapper for sending/receiving messages
+// over USF transports. It sets up a callback into the USF transport layer
+// for receiving messages on instantiation. The first message that we
+// receive from the USF transport layer includes a pointer to a 'transport'
+// abstraction, that can be used to send messages out of CHRE.
+// TODO: Revisit this implementation after the USF feature requests in
+// b/149318001 and b/149317051 are fulfilled
+class ChreUsfTransportManager {
+ public:
+  ChreUsfTransportManager() : mInitialized(false), mTransportHandle(nullptr) {
+    usf::UsfErr err = usf::UsfTransportMgr::SetMsgHandler(
+        usf::UsfMsgType::UsfMsgType_CHRE, handleUsfMessage, nullptr);
+    if (usf::kErrNone != err) {
+      FATAL_ERROR("Failed to set USF msg handler");
+    }
+  }
+
+  // Check if we've already received a message from the AP, since that's the
+  // only way we can send outgoing messages.
+  // AP (transport is valid).
+  // TODO (b/149317051) This needs to go away once USF exposes an API to
+  // acquire a transport.
+  void checkInit(usf::UsfTransport *transport) {
+    if (!mInitialized) {
+      if (transport == nullptr) {
+        FATAL_ERROR("Null transport at init, cannot send out messages!");
+      }
+      mTransportHandle = transport;
+      mInitialized = true;
+    }
+  }
+
+  bool send(uint8_t *data, size_t dataLen) {
+    usf::UsfErr err = usf::kErrFailed;
+
+    if (mInitialized) {
+      usf::UsfTxMsg msg;
+      msg.SetMsgType(usf::UsfMsgType_CHRE);
+      msg.SetData(data, dataLen);
+      err = mTransportHandle->SendMsg(&msg);
+    }
+
+    return (usf::kErrNone == err);
+  }
+
+ private:
+  bool mInitialized;
+  usf::UsfTransport *mTransportHandle;
+};
+
+ChreUsfTransportManager transportMgr;
+
+/**
+ * The USF external message handler function for CHRE, that
+ * is invoked on CHRE inbound messages from the AP
+ *
+ * @param transport A pointer to a transport that is used to send messages
+ * out of CHRE to the AP
+ * @param msg flatbuffer encoded message of type UsfMsgType_CHRE
+ * @param arg yields the message length when cast to size_t
+ * @return usf::kErrNone if success, an error code indicating the failure
+ * otherwise
+ */
+usf::UsfErr handleUsfMessage(usf::UsfTransport *transport,
+                             const usf::UsfMsg *msg, void * /* arg */) {
+  usf::UsfErr rc = usf::kErrFailed;
+
+  // check for initialization if this is the first message received
+  transportMgr.checkInit(transport);
+
+  if (msg == nullptr) {
+    return usf::kErrInvalid;
+
+  } else {
+    usf::UsfMsgType msgType = msg->msg_type();
+
+    if (msgType == usf::UsfMsgType_CHRE) {
+      auto *dataVector = msg->data();
+      if (dataVector != nullptr) {
+        size_t dataLen = dataVector->size();
+        bool success = HostProtocolChre::decodeMessageFromHost(
+            dataVector->data(), dataLen);
+        rc = (success == true) ? usf::kErrNone : usf::kErrFailed;
+      }
+    } else {
+      rc = usf::kErrInvalid;
+    }
+  }
+
+  // Opportunistically send a time sync message (1 hour period threshold)
+  constexpr Seconds kOpportunisticTimeSyncPeriod = Seconds(60 * 60 * 1);
+  if (SystemTime::getMonotonicTime() >
+      gLastTimeSyncRequestNanos + kOpportunisticTimeSyncPeriod) {
+    sendTimeSyncRequest();
+  }
+
+  return rc;
+}
+
+void sendTimeSyncRequest() {
+  constexpr size_t kInitialSize = 52;
+  flatbuffers::FlatBufferBuilder builder(kInitialSize);
+  HostProtocolChre::encodeTimeSyncRequest(builder);
+
+  transportMgr.send(builder.GetBufferPointer(), builder.GetSize());
+
+  gLastTimeSyncRequestNanos = SystemTime::getMonotonicTime();
+}
+
+void setTimeSyncRequestTimer(Nanoseconds delay) {
+  static TimerHandle sHandle;
+  static bool sHandleInitialized;
+
+  if (sHandleInitialized) {
+    EventLoopManagerSingleton::get()->cancelDelayedCallback(sHandle);
+  }
+
+  auto callback = [](uint16_t /* eventType */, void * /* data */) {
+    sendTimeSyncRequest();
+  };
+  sHandle = EventLoopManagerSingleton::get()->setDelayedCallback(
+      SystemCallbackType::TimerSyncRequest, nullptr /* data */, callback,
+      delay);
+  sHandleInitialized = true;
+}
+
+bool getSettingFromFbs(fbs::Setting setting, Setting *chreSetting) {
+  bool success = true;
+  switch (setting) {
+    case fbs::Setting::LOCATION:
+      *chreSetting = Setting::LOCATION;
+      break;
+    default:
+      LOGE("Unknown setting %" PRIu8, setting);
+      success = false;
+  }
+
+  return success;
+}
+
+bool getSettingStateFromFbs(fbs::SettingState state,
+                            SettingState *chreSettingState) {
+  bool success = true;
+  switch (state) {
+    case fbs::SettingState::DISABLED:
+      *chreSettingState = SettingState::DISABLED;
+      break;
+    case fbs::SettingState::ENABLED:
+      *chreSettingState = SettingState::ENABLED;
+      break;
+    default:
+      LOGE("Unknown state %" PRIu8, state);
+      success = false;
+  }
+
+  return success;
+}
+
+void sendDebugDumpData(uint16_t hostClientId, const char *debugStr,
+                       size_t debugStrSize) {
+  constexpr size_t kFixedSizePortion = 52;
+  flatbuffers::FlatBufferBuilder builder(kFixedSizePortion + debugStrSize);
+  HostProtocolChre::encodeDebugDumpData(builder, hostClientId, debugStr,
+                                        debugStrSize);
+
+  transportMgr.send(builder.GetBufferPointer(), builder.GetSize());
+}
+
+void sendDebugDumpResponse(uint16_t hostClientId, bool success,
+                           uint32_t dataCount) {
+  constexpr size_t kFixedSizePortion = 52;
+  flatbuffers::FlatBufferBuilder builder(kFixedSizePortion);
+  HostProtocolChre::encodeDebugDumpResponse(builder, hostClientId, success,
+                                            dataCount);
+  transportMgr.send(builder.GetBufferPointer(), builder.GetSize());
+}
+
+void constructNanoappListCallback(uint16_t /*eventType*/, void *deferCbData) {
+  HostClientIdCallbackData clientIdCbData;
+  clientIdCbData.ptr = deferCbData;
+
+  struct NanoappListData {
+    FlatBufferBuilder *builder;
+    DynamicVector<NanoappListEntryOffset> nanoappEntries;
+  };
+  NanoappListData cbData;
+
+  EventLoop &eventLoop = EventLoopManagerSingleton::get()->getEventLoop();
+  size_t expectedNanoappCount = eventLoop.getNanoappCount();
+  if (!cbData.nanoappEntries.reserve(expectedNanoappCount)) {
+    LOG_OOM();
+  } else {
+    constexpr size_t kFixedOverhead = 48;
+    constexpr size_t kPerNanoappSize = 32;
+    size_t initialBufferSize =
+        (kFixedOverhead + expectedNanoappCount * kPerNanoappSize);
+
+    flatbuffers::FlatBufferBuilder builder(initialBufferSize);
+    cbData.builder = &builder;
+
+    auto nanoappAdderCallback = [](const Nanoapp *nanoapp, void *data) {
+      auto *listData = static_cast<NanoappListData *>(data);
+      HostProtocolChre::addNanoappListEntry(
+          *(listData->builder), listData->nanoappEntries, nanoapp->getAppId(),
+          nanoapp->getAppVersion(), true /*enabled*/,
+          nanoapp->isSystemNanoapp());
+    };
+    eventLoop.forEachNanoapp(nanoappAdderCallback, &cbData);
+    HostProtocolChre::finishNanoappListResponse(builder, cbData.nanoappEntries,
+                                                clientIdCbData.hostClientId);
+    transportMgr.send(builder.GetBufferPointer(), builder.GetSize());
+  }
+}
+
+void sendFragmentResponse(uint16_t hostClientId, uint32_t transactionId,
+                          uint32_t fragmentId, bool success) {
+  constexpr size_t kInitialBufferSize = 52;
+  flatbuffers::FlatBufferBuilder builder(kInitialBufferSize);
+  HostProtocolChre::encodeLoadNanoappResponse(
+      builder, hostClientId, transactionId, success, fragmentId);
+
+  if (!transportMgr.send(builder.GetBufferPointer(), builder.GetSize())) {
+    LOGE(
+        "Failed to send fragment response for HostClientID: %x FragmentID: %x"
+        "transactionID: 0x%x",
+        hostClientId, fragmentId, transactionId);
+  }
+}
+
+void finishLoadingNanoappCallback(uint16_t /*eventType*/, void *data) {
+  DramGuard guard;
+
+  UniquePtr<LoadNanoappCallbackData> cbData(
+      static_cast<LoadNanoappCallbackData *>(data));
+  constexpr size_t kInitialBufferSize = 48;
+  flatbuffers::FlatBufferBuilder builder(kInitialBufferSize);
+
+  CHRE_ASSERT(cbData != nullptr);
+  LOGD("Finished loading nanoapp cb on fragment ID: %u", cbData->fragmentId);
+
+  EventLoop &eventLoop = EventLoopManagerSingleton::get()->getEventLoop();
+  bool success =
+      cbData->nanoapp->isLoaded() && eventLoop.startNanoapp(cbData->nanoapp);
+
+  sendFragmentResponse(cbData->hostClientId, cbData->transactionId,
+                       cbData->fragmentId, success);
+}
+
+}  // anonymous namespace
+
+void sendDebugDumpResultToHost(uint16_t hostClientId, const char *debugStr,
+                               size_t debugStrSize, bool complete,
+                               uint32_t dataCount) {
+  if (debugStrSize > 0) {
+    sendDebugDumpData(hostClientId, debugStr, debugStrSize);
+  }
+
+  if (complete) {
+    sendDebugDumpResponse(hostClientId, true /*success*/, dataCount);
+  }
+}
+
+void HostLink::flushMessagesSentByNanoapp(uint64_t /* appId */) {
+  // TODO: Implement this once USF supports this (b/149318001)
+}
+
+bool HostLink::sendMessage(const MessageToHost *message) {
+  constexpr size_t kFixedReserveSize = 80;
+  flatbuffers::FlatBufferBuilder builder(message->message.size() +
+                                         kFixedReserveSize);
+  HostProtocolChre::encodeNanoappMessage(
+      builder, message->appId, message->toHostData.messageType,
+      message->toHostData.hostEndpoint, message->message.data(),
+      message->message.size());
+
+  return transportMgr.send(builder.GetBufferPointer(), builder.GetSize());
+}
+
+void HostLink::sendLogMessage(const char *logMessage, size_t logMessageSize) {
+  constexpr size_t kInitialSize = 128;
+  flatbuffers::FlatBufferBuilder builder(logMessageSize + kInitialSize);
+  HostProtocolChre::encodeLogMessages(builder, logMessage, logMessageSize);
+
+  transportMgr.send(builder.GetBufferPointer(), builder.GetSize());
+}
+
+void HostMessageHandlers::handleDebugDumpRequest(uint16_t hostClientId) {
+  chre::EventLoopManagerSingleton::get()
+      ->getDebugDumpManager()
+      .onDebugDumpRequested(hostClientId);
+}
+
+void HostMessageHandlers::handleHubInfoRequest(uint16_t hostClientId) {
+  constexpr size_t kInitialBufferSize = 192;
+
+  constexpr char kHubName[] = "CHRE on AoC";
+  constexpr char kVendor[] = "Google";
+  constexpr char kToolchain[] =
+      "Clang " STRINGIFY(__clang_major__) "." STRINGIFY(
+          __clang_minor__) "." STRINGIFY(__clang_patchlevel__) ")";
+  constexpr uint32_t kLegacyPlatformVersion = 0;
+  constexpr uint32_t kLegacyToolchainVersion =
+      ((__clang_major__ & 0xFF) << 24) | ((__clang_minor__ & 0xFF) << 16) |
+      (__clang_patchlevel__ & 0xFFFF);
+  constexpr float kPeakMips = 800;
+  // TODO: The following need to be updated when we've measured the
+  // indicated power levels on the AoC
+  constexpr float kStoppedPower = 0;
+  constexpr float kSleepPower = 0;
+  constexpr float kPeakPower = 0;
+
+  flatbuffers::FlatBufferBuilder builder(kInitialBufferSize);
+  HostProtocolChre::encodeHubInfoResponse(
+      builder, kHubName, kVendor, kToolchain, kLegacyPlatformVersion,
+      kLegacyToolchainVersion, kPeakMips, kStoppedPower, kSleepPower,
+      kPeakPower, CHRE_MESSAGE_TO_HOST_MAX_SIZE, chreGetPlatformId(),
+      chreGetVersion(), hostClientId);
+
+  if (!transportMgr.send(builder.GetBufferPointer(), builder.GetSize())) {
+    LOGE("Failed to send Hub Info Response message");
+  }
+}
+
+void HostMessageHandlers::handleLoadNanoappRequest(
+    uint16_t hostClientId, uint32_t transactionId, uint64_t appId,
+    uint32_t appVersion, uint32_t targetApiVersion, const void *buffer,
+    size_t bufferLen, const char *appFileName, uint32_t fragmentId,
+    size_t appBinaryLen) {
+  DramGuard guard;
+
+  bool success = true;
+  static NanoappLoadManager sLoadManager;
+
+  if (fragmentId == 0 || fragmentId == 1) {
+    size_t totalAppBinaryLen = (fragmentId == 0) ? bufferLen : appBinaryLen;
+    LOGD("Load nanoapp request for app ID 0x%016" PRIx64 " ver 0x%" PRIx32
+         " target API 0x%08" PRIx32 " size %zu (txnId %" PRIu32
+         " client %" PRIu16 ")",
+         appId, appVersion, targetApiVersion, totalAppBinaryLen, transactionId,
+         hostClientId);
+
+    if (sLoadManager.hasPendingLoadTransaction()) {
+      FragmentedLoadInfo info = sLoadManager.getTransactionInfo();
+      sendFragmentResponse(info.hostClientId, info.transactionId,
+                           0 /* fragmentId */, false /* success */);
+      sLoadManager.markFailure();
+    }
+
+    success = sLoadManager.prepareForLoad(hostClientId, transactionId, appId,
+                                          appVersion, totalAppBinaryLen);
+  }
+
+  if (success) {
+    success = sLoadManager.copyNanoappFragment(
+        hostClientId, transactionId, (fragmentId == 0) ? 1 : fragmentId, buffer,
+        bufferLen);
+  } else {
+    LOGE("Failed to prepare for load");
+  }
+
+  if (sLoadManager.isLoadComplete()) {
+    LOGD("Load manager load complete...");
+    auto cbData = MakeUnique<LoadNanoappCallbackData>();
+    if (cbData.isNull()) {
+      LOG_OOM();
+    } else {
+      cbData->transactionId = transactionId;
+      cbData->hostClientId = hostClientId;
+      cbData->appId = appId;
+      cbData->fragmentId = fragmentId;
+      cbData->nanoapp = sLoadManager.releaseNanoapp();
+
+      // Note that if this fails, we'll generate the error response in
+      // the normal deferred callback
+      EventLoopManagerSingleton::get()->deferCallback(
+          SystemCallbackType::FinishLoadingNanoapp, cbData.release(),
+          finishLoadingNanoappCallback);
+    }
+  } else {
+    // send a response for this fragment
+    sendFragmentResponse(hostClientId, transactionId, fragmentId, success);
+  }
+}
+
+void HostMessageHandlers::handleNanoappListRequest(uint16_t hostClientId) {
+  LOGD("Nanoapp list request from client ID %" PRIu16, hostClientId);
+  HostClientIdCallbackData cbData = {};
+  cbData.hostClientId = hostClientId;
+  EventLoopManagerSingleton::get()->deferCallback(
+      SystemCallbackType::NanoappListResponse, cbData.ptr,
+      constructNanoappListCallback);
+}
+
+void HostMessageHandlers::handleNanoappMessage(uint64_t appId,
+                                               uint32_t messageType,
+                                               uint16_t hostEndpoint,
+                                               const void *messageData,
+                                               size_t messageDataLen) {
+  LOGD("Parsed nanoapp message from host: app ID 0x%016" PRIx64
+       " endpoint 0x%" PRIx16 " msgType %" PRIu32 " payload size %zu",
+       appId, hostEndpoint, messageType, messageDataLen);
+
+  HostCommsManager &hostCommsManager =
+      EventLoopManagerSingleton::get()->getHostCommsManager();
+  hostCommsManager.sendMessageToNanoappFromHost(
+      appId, messageType, hostEndpoint, messageData, messageDataLen);
+}
+
+void HostMessageHandlers::handleSettingChangeMessage(fbs::Setting setting,
+                                                     fbs::SettingState state) {
+  Setting chreSetting;
+  SettingState chreSettingState;
+  if (getSettingFromFbs(setting, &chreSetting) &&
+      getSettingStateFromFbs(state, &chreSettingState)) {
+    postSettingChange(chreSetting, chreSettingState);
+  }
+}
+
+void HostMessageHandlers::handleTimeSyncMessage(int64_t offset) {
+  setEstimatedHostTimeOffset(offset);
+
+  // Schedule a time sync request since offset may drift
+  constexpr Seconds kClockDriftTimeSyncPeriod =
+      Seconds(60 * 60 * 6);  // 6 hours
+  setTimeSyncRequestTimer(kClockDriftTimeSyncPeriod);
+}
+
+void HostMessageHandlers::handleUnloadNanoappRequest(
+    uint16_t /* hostClientId */, uint32_t /* transactionId */,
+    uint64_t /* appId */, bool /* allowSystemNanoappUnload */) {
+  // TODO: stubbed out, needs to be implemented
+  LOGI("UnloadNanoappRequest messages are currently unsupported");
+}
+
+}  // namespace chre
diff --git a/platform/aoc/include/chre/platform/aoc/memory.h b/platform/aoc/include/chre/platform/aoc/memory.h
new file mode 100644
index 0000000..89ad519
--- /dev/null
+++ b/platform/aoc/include/chre/platform/aoc/memory.h
@@ -0,0 +1,40 @@
+/*
+ * 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_PLATFORM_AOC_MEMORY_H_
+#define CHRE_PLATFORM_AOC_MEMORY_H_
+
+#include <cstddef>
+
+#include "chre/platform/freertos/memory.h"
+
+namespace chre {
+
+/**
+ * Memory allocation specifically using the DRAM heap. The semantics are the
+ * same as malloc.
+ */
+void *memoryAllocDram(size_t size);
+
+/**
+ * Memory free from memory allocated using the DRAM heap. The semantics are the
+ * same as free.
+ */
+void memoryFreeDram(void *pointer);
+
+}  // namespace chre
+
+#endif  // CHRE_PLATFORM_AOC_MEMORY_H_
diff --git a/platform/aoc/include/chre/platform/aoc/system_time.h b/platform/aoc/include/chre/platform/aoc/system_time.h
new file mode 100644
index 0000000..26c4fca
--- /dev/null
+++ b/platform/aoc/include/chre/platform/aoc/system_time.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2019 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_PLATFORM_AOC_SYSTEM_TIME_H_
+#define CHRE_PLATFORM_AOC_SYSTEM_TIME_H_
+
+#include <cstdint>
+
+namespace chre {
+
+/**
+ * Sets the estimated offset between the host and AoC clock.
+ *
+ * @param offset The current estimated offset in nanoseconds.
+ */
+void setEstimatedHostTimeOffset(int64_t offset);
+
+}  // namespace chre
+
+#endif  // CHRE_PLATFORM_AOC_SYSTEM_TIME_H_
diff --git a/platform/aoc/include/chre/target_platform/assert.h b/platform/aoc/include/chre/target_platform/assert.h
new file mode 100644
index 0000000..aec4e33
--- /dev/null
+++ b/platform/aoc/include/chre/target_platform/assert.h
@@ -0,0 +1,29 @@
+/*
+ * 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_PLATFORM_AOC_ASSERT_H_
+#define CHRE_PLATFORM_AOC_ASSERT_H_
+
+#include "chre/platform/fatal_error.h"
+
+#define CHRE_ASSERT(condition)                                            \
+  do {                                                                    \
+    if (!(condition)) {                                                   \
+      FATAL_ERROR("Assertion failure at %s:%d", CHRE_FILENAME, __LINE__); \
+    }                                                                     \
+  } while (0)
+
+#endif  // CHRE_PLATFORM_AOC_ASSERT_H_
diff --git a/platform/aoc/include/chre/target_platform/fatal_error.h b/platform/aoc/include/chre/target_platform/fatal_error.h
new file mode 100644
index 0000000..8a5c5c8
--- /dev/null
+++ b/platform/aoc/include/chre/target_platform/fatal_error.h
@@ -0,0 +1,32 @@
+/**
+ * Copyright 2019 Google LLC. All Rights Reserved
+ *
+ * @file fatal_error.h
+ *
+ * @brief Fatal Error Handling
+ */
+
+#ifndef CHRE_PLATFORM_AOC_FATAL_ERROR_H_
+#define CHRE_PLATFORM_AOC_FATAL_ERROR_H_
+
+#include <cstdlib>
+
+#define FATAL_ERROR_QUIT() \
+  do {                     \
+    chre::preFatalError(); \
+    abort();               \
+  } while (0)
+
+namespace chre {
+
+/**
+ * Do preparation for an impending fatal error including flushing logs.
+ *
+ * It must not be possible for FATAL_ERROR() to be called by this function or
+ * any of its callees.
+ */
+void preFatalError();
+
+}  // namespace chre
+
+#endif  // CHRE_PLATFORM_AOC_FATAL_ERROR_H_
diff --git a/platform/aoc/include/chre/target_platform/host_link_base.h b/platform/aoc/include/chre/target_platform/host_link_base.h
new file mode 100644
index 0000000..cbe7723
--- /dev/null
+++ b/platform/aoc/include/chre/target_platform/host_link_base.h
@@ -0,0 +1,35 @@
+/*
+ * 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_PLATFORM_AOC_HOST_LINK_BASE_H_
+#define CHRE_PLATFORM_AOC_HOST_LINK_BASE_H_
+
+namespace chre {
+
+/**
+ * Helper function to send debug dump result to host.
+ */
+void sendDebugDumpResultToHost(uint16_t hostClientId, const char *debugStr,
+                               size_t debugStrSize, bool complete,
+                               uint32_t dataCount);
+
+class HostLinkBase {
+  // TODO: Stubbed out, implement this
+};
+
+}  // namespace chre
+
+#endif  // CHRE_PLATFORM_AOC_HOST_LINK_BASE_H_
diff --git a/platform/aoc/include/chre/target_platform/log.h b/platform/aoc/include/chre/target_platform/log.h
new file mode 100644
index 0000000..35c95ef
--- /dev/null
+++ b/platform/aoc/include/chre/target_platform/log.h
@@ -0,0 +1,62 @@
+/*
+ * 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_PLATFORM_AOC_LOG_H_
+#define CHRE_PLATFORM_AOC_LOG_H_
+
+#include <chre.h>
+#include <stdio.h>
+
+#ifndef __FILENAME__
+#ifdef __BASE_FILE__
+#define __FILENAME__ __BASE_FILE__
+#else
+#define __FILENAME__ __FILE__
+#endif  // __BASE_FILE__
+#endif  // __FILE_NAME__
+
+#ifndef CHRE_DL_VERBOSE
+#define CHRE_DL_VERBOSE false
+#endif  // CHRE_DL_VERBOSE
+
+// TODO(b/149317051): The printf in the below macro is needed until CHRE can log
+// to the AP before the daemon has connected to AoC.
+#define CHRE_AOC_LOG(level, fmt, ...)                                       \
+  do {                                                                      \
+    CHRE_LOG_PREAMBLE                                                       \
+    chre::log(level, fmt, ##__VA_ARGS__);                                   \
+    printf("CHRE:%s:%d\t" fmt "\n", __FILENAME__, __LINE__, ##__VA_ARGS__); \
+    CHRE_LOG_EPILOGUE                                                       \
+  } while (0)
+
+#define LOGE(fmt, ...) CHRE_AOC_LOG(CHRE_LOG_ERROR, fmt, ##__VA_ARGS__)
+#define LOGW(fmt, ...) CHRE_AOC_LOG(CHRE_LOG_WARN, fmt, ##__VA_ARGS__)
+#define LOGI(fmt, ...) CHRE_AOC_LOG(CHRE_LOG_INFO, fmt, ##__VA_ARGS__)
+#define LOGD(fmt, ...) CHRE_AOC_LOG(CHRE_LOG_DEBUG, fmt, ##__VA_ARGS__)
+
+#if CHRE_DL_VERBOSE
+#define LOGV(fmt, ...) LOGD(fmt, ##__VA_ARGS__)
+#else
+#define LOGV(fmt, ...)
+#endif  // CHRE_DL_VERBOSE
+
+namespace chre {
+
+void log(enum chreLogLevel level, const char *formatStr, ...);
+void vaLog(enum chreLogLevel level, const char *format, va_list args);
+
+}  // namespace chre
+
+#endif  // CHRE_PLATFORM_AOC_LOG_H_
diff --git a/platform/aoc/include/chre/target_platform/platform_audio_base.h b/platform/aoc/include/chre/target_platform/platform_audio_base.h
new file mode 100644
index 0000000..a0cce31
--- /dev/null
+++ b/platform/aoc/include/chre/target_platform/platform_audio_base.h
@@ -0,0 +1,30 @@
+/*
+ * 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_PLATFORM_AOC_PLATFORM_AUDIO_BASE_H_
+#define CHRE_PLATFORM_AOC_PLATFORM_AUDIO_BASE_H_
+
+namespace chre {
+
+/**
+ * The base PlatformAudio class for AoC to inject platform
+ * specific functionality from.
+ */
+class PlatformAudioBase {};
+
+}  // namespace chre
+
+#endif  // CHRE_PLATFORM_AOC_PLATFORM_AUDIO_BASE_H_
diff --git a/platform/aoc/include/chre/target_platform/platform_log_base.h b/platform/aoc/include/chre/target_platform/platform_log_base.h
new file mode 100644
index 0000000..1d5657a
--- /dev/null
+++ b/platform/aoc/include/chre/target_platform/platform_log_base.h
@@ -0,0 +1,29 @@
+/*
+ * 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_PLATFORM_AOC_PLATFORM_LOG_BASE_H_
+#define CHRE_PLATFORM_AOC_PLATFORM_LOG_BASE_H_
+
+namespace chre {
+
+class PlatformLogBase {
+  // TODO: Stubbed out, implement this
+  // Can we EFWObject::PrintSet(printf) here instead of in the application?
+};
+
+}  // namespace chre
+
+#endif  // CHRE_PLATFORM_AOC_PLATFORM_LOG_BASE_H_
diff --git a/platform/aoc/include/chre/target_platform/power_control_manager_base.h b/platform/aoc/include/chre/target_platform/power_control_manager_base.h
new file mode 100644
index 0000000..78f79c4
--- /dev/null
+++ b/platform/aoc/include/chre/target_platform/power_control_manager_base.h
@@ -0,0 +1,27 @@
+/*
+ * 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_PLATFORM_AOC_POWER_CONTROL_MANAGER_BASE_H
+#define CHRE_PLATFORM_AOC_POWER_CONTROL_MANAGER_BASE_H
+
+namespace chre {
+
+// TODO: stubbed out, Implement this.
+class PowerControlManagerBase {};
+
+}  // namespace chre
+
+#endif  // CHRE_PLATFORM_AOC_POWER_CONTROL_MANAGER_BASE_H
diff --git a/platform/aoc/include/chre/target_platform/system_timer_base.h b/platform/aoc/include/chre/target_platform/system_timer_base.h
new file mode 100644
index 0000000..7ee5a57
--- /dev/null
+++ b/platform/aoc/include/chre/target_platform/system_timer_base.h
@@ -0,0 +1,70 @@
+/*
+ * 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_PLATFORM_AOC_SYSTEM_TIMER_BASE_H_
+#define CHRE_PLATFORM_AOC_SYSTEM_TIMER_BASE_H_
+
+#include <cstdint>
+
+#include "chre/platform/assert.h"
+#include "chre/util/time_impl.h"
+
+#include "efw/include/timer.h"
+
+#include "FreeRTOS.h"
+#include "task.h"
+
+namespace chre {
+
+/**
+ * The AOC platform base class for the SystemTimer. The AOC implementation uses
+ * a EFW timer.
+ */
+class SystemTimerBase {
+ protected:
+  // TODO(karthikmb/stange) - There is currently a limitation in EFW, where
+  // (because of a lack of hardware timer overflow management in software)
+  // the 'max' delay-ticks-from-now is limited to UINT32_MAX. So, we set
+  // our sync request timer to somewhere close to that. Once arbitrary
+  // delays are supported, this variable (and the following getter function)
+  // should go away. b/157537617 tracks the feature implementation.
+  // Please see the efw/src/timer.cc source file for a description of the
+  // magic numbers.
+  static constexpr uint64_t kAlmostMaxU32 = UINT32_MAX - 100;
+  static constexpr Nanoseconds kMaxSupportedDelayNs =
+      Nanoseconds(kAlmostMaxU32 * 15625 / 64);
+
+  //! The timer handle that is generated by Timer::EventAdd.
+  void *mTimerHandle;
+
+  //! Tracks whether the timer has been initialized correctly.
+  bool mInitialized = false;
+
+  //! A static method that is invoked by the underlying EFW timer.
+  static bool systemTimerNotifyCallback(void *context);
+
+  //! A FreeRTOS Thread to dispatch timer callbacks
+  static TaskHandle_t mTimerCbDispatchThreadHandle;
+
+  //! This function implements the timer callback dispatch thread.
+  // It blocks until it's woken up by the underlying system timer's ISR,
+  // then executes the CHRE timer callback from the dispatch thread context.
+  static void timerCallbackDispatch(void *context);
+};
+
+}  // namespace chre
+
+#endif  // CHRE_PLATFORM_AOC_SYSTEM_TIMER_BASE_H_
diff --git a/platform/aoc/log.cc b/platform/aoc/log.cc
new file mode 100644
index 0000000..8a6a5e5
--- /dev/null
+++ b/platform/aoc/log.cc
@@ -0,0 +1,62 @@
+/*
+ * 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/target_platform/log.h"
+
+#include "chre/core/event_loop_manager.h"
+#include "chre/platform/system_time.h"
+
+#include <endian.h>
+
+namespace chre {
+namespace {
+constexpr size_t kChreLogBufferSize = CHRE_MESSAGE_TO_HOST_MAX_SIZE;
+char logBuffer[kChreLogBufferSize];
+}  // namespace
+
+void log(enum chreLogLevel level, const char *formatStr, ...) {
+  va_list args;
+  va_start(args, formatStr);
+  vaLog(level, formatStr, args);
+  va_end(args);
+}
+
+// TODO: b/146164384 - We will need to batch logs rather than send them
+// one at a time to avoid waking the AP.
+void vaLog(enum chreLogLevel level, const char *format, va_list args) {
+  HostLink &hostLink =
+      EventLoopManagerSingleton::get()->getHostCommsManager().getHostLink();
+
+  // See host_messages.fbs for the log message format.
+  size_t logBufIndex = 0;
+  logBuffer[logBufIndex] = level + 1;
+  logBufIndex++;
+
+  uint64_t currentTimeNs = SystemTime::getMonotonicTime().toRawNanoseconds();
+  memcpy(&logBuffer[logBufIndex], &currentTimeNs, sizeof(uint64_t));
+  logBufIndex += sizeof(uint64_t);
+
+  int msgLen = vsnprintf(&logBuffer[logBufIndex],
+                         kChreLogBufferSize - logBufIndex, format, args);
+  if (msgLen >= 0) {
+    // msgLen doesn't include the terminating null char.
+    logBufIndex += msgLen + 1;
+
+    hostLink.sendLogMessage(logBuffer, logBufIndex);
+  }
+}
+
+}  // namespace chre
diff --git a/platform/aoc/memory.cc b/platform/aoc/memory.cc
new file mode 100644
index 0000000..f716468
--- /dev/null
+++ b/platform/aoc/memory.cc
@@ -0,0 +1,221 @@
+/*
+ * 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/platform/aoc/memory.h"
+#include "chre/platform/memory.h"
+#include "chre/platform/mutex.h"
+#include "chre/platform/shared/pal_system_api.h"
+
+#include "basic.h"
+#include "heap.h"
+#include "sysmem.h"
+
+#include <cstdlib>
+
+// TODO(b/152442881): Remove printf statements and replace with CHRE_ASSERT
+// when things are considered more stable.
+
+//! Beginning of the CHRE SRAM heap.
+extern uintptr_t __heap_chre_beg__;
+//! End of the CHRE SRAM heap.
+extern uintptr_t __heap_chre_end__;
+//! Beginning of the CHRE DRAM heap.
+extern uintptr_t __heap_chre_dram_beg__;
+//! End of the CHRE DRAM heap.
+extern uintptr_t __heap_chre_dram_end__;
+
+namespace chre {
+namespace {
+
+//! SRAM heap handle.
+void *gSramHeap = nullptr;
+//! SRAM heap mutex.
+Mutex gSramMutex;
+//! DRAM handle.
+void *gDramHeap = nullptr;
+//! DRAM mutex.
+Mutex gDramMutex;
+
+enum ChreHeap { DRAM, SRAM };
+
+//! Helper functions passed to EFW so it can lock when heap allocations / frees
+//! are performed.
+inline void LockMutex(void *mutex) {
+  static_cast<Mutex *>(mutex)->lock();
+}
+inline void UnlockMutex(void *mutex) {
+  static_cast<Mutex *>(mutex)->unlock();
+}
+
+void *GetSramHeap() {
+  if (gSramHeap == nullptr) {
+    auto heap_base = &__heap_chre_beg__;
+    auto heap_size = PTR_OFFSET_GET(&__heap_chre_end__, heap_base);
+
+    gSramHeap = HeapInit(heap_base, heap_size);
+    CHRE_ASSERT(gSramHeap != nullptr);
+    if (gSramHeap == nullptr) {
+      printf("CHRE: Failed to initialize SRAM heap\n");
+      return nullptr;
+    } else {
+      HeapLocking(gSramHeap, &gSramMutex, LockMutex, UnlockMutex);
+    }
+  }
+  return gSramHeap;
+}
+
+void *GetDramHeap() {
+  if (gDramHeap == nullptr) {
+    auto heap_base = &__heap_chre_dram_beg__;
+    auto heap_size = PTR_OFFSET_GET(&__heap_chre_dram_end__, heap_base);
+
+    gDramHeap = HeapInit(heap_base, heap_size);
+    CHRE_ASSERT(gDramHeap != nullptr);
+    if (gDramHeap == nullptr) {
+      printf("CHRE: Failed to initialize DRAM heap\n");
+      return nullptr;
+    } else {
+      HeapLocking(gDramHeap, &gDramMutex, LockMutex, UnlockMutex);
+    }
+  }
+  return gDramHeap;
+}
+
+void *GetHeap(ChreHeap heap) {
+  if (heap == ChreHeap::SRAM) {
+    return GetSramHeap();
+  } else if (heap == ChreHeap::DRAM) {
+    return GetDramHeap();
+  } else {
+    printf("CHRE: GetHeap given invalid heap\n");
+  }
+  return nullptr;
+}
+
+bool IsInHeap(ChreHeap heap, const void *pointer) {
+  void *handle = GetHeap(heap);
+  bool found = false;
+  if (handle != nullptr) {
+    const struct HEAP_STATS *stats = HeapStats(handle);
+    const uintptr_t heapBase = reinterpret_cast<uintptr_t>(stats->base);
+    const uintptr_t castPointer = reinterpret_cast<uintptr_t>(pointer);
+    found = castPointer >= heapBase && castPointer < (heapBase + stats->len);
+  }
+
+  return found;
+}
+
+void *GetHeapFromPointer(const void *pointer) {
+  if (IsInHeap(ChreHeap::SRAM, pointer)) {
+    return GetSramHeap();
+  }
+
+  if (IsInHeap(ChreHeap::DRAM, pointer)) {
+    return GetDramHeap();
+  }
+
+  return nullptr;
+}
+
+}  // namespace
+
+void *memoryAlloc(size_t size) {
+  void *ptr = nullptr;
+  void *handle = GetSramHeap();
+  if (handle != nullptr) {
+    ptr = HeapMalloc(handle, size);
+    if (ptr == nullptr) {
+      printf("CHRE: Failed to allocate memory in SRAM heap...trying DRAM\n");
+      // TODO: Crash if using DRAM memory too long
+      ptr = memoryAllocDram(size);
+    }
+  }
+
+  return ptr;
+}
+
+void *memoryAllocDramAligned(size_t alignment, size_t size) {
+  void *ptr = nullptr;
+  void *handle = GetDramHeap();
+
+  if (handle != nullptr) {
+    ptr = HeapAlignedAlloc(handle, alignment, size);
+    if (ptr == nullptr) {
+      printf("CHRE: Failed to allocate memory in DRAM heap\n");
+    }
+  }
+
+  return ptr;
+}
+
+void *memoryAllocDram(size_t size) {
+  void *ptr = nullptr;
+  void *handle = GetDramHeap();
+  if (handle != nullptr) {
+    ptr = HeapMalloc(handle, size);
+    if (ptr == nullptr) {
+      printf("CHRE: Failed to allocate memory in DRAM heap\n");
+    }
+  }
+
+  return ptr;
+}
+
+void memoryFree(void *pointer) {
+  if (pointer != nullptr) {
+    void *handle = GetHeapFromPointer(pointer);
+    if (handle == nullptr) {
+      printf("CHRE: Tried to free memory from a non-CHRE heap\n");
+    } else {
+      HeapFree(handle, pointer);
+    }
+  }
+}
+
+void memoryFreeDram(void *pointer) {
+  if (!IsInHeap(ChreHeap::DRAM, pointer)) {
+    printf(
+        "CHRE: Tried to free memory not in DRAM heap or DRAM heap not \
+            initialized\n");
+  } else {
+    HeapFree(GetDramHeap(), pointer);
+  }
+}
+
+bool requestDramAccess(bool enabled) {
+  int rc;
+  if (enabled) {
+    rc = SysMem::Instance()->MemoryRequest(SysMem::MIF, true);
+  } else {
+    rc = SysMem::Instance()->MemoryRelease(SysMem::MIF);
+  }
+
+  if (rc != 0) {
+    LOGE("Unable to change DRAM access to %d with error code %d", enabled, rc);
+  }
+
+  return rc == 0;
+}
+
+void *palSystemApiMemoryAlloc(size_t size) {
+  return memoryAlloc(size);
+}
+
+void palSystemApiMemoryFree(void *pointer) {
+  memoryFree(pointer);
+}
+
+}  // namespace chre
diff --git a/platform/aoc/platform_audio.cc b/platform/aoc/platform_audio.cc
new file mode 100644
index 0000000..5cf097c
--- /dev/null
+++ b/platform/aoc/platform_audio.cc
@@ -0,0 +1,56 @@
+/*
+ * 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/platform/platform_audio.h"
+#include "chre/platform/log.h"
+
+namespace chre {
+
+PlatformAudio::PlatformAudio() {}
+
+PlatformAudio::~PlatformAudio() {}
+
+void PlatformAudio::init() {
+  LOGE("Stubbed out, to be implemented");
+}
+
+size_t PlatformAudio::getSourceCount() {
+  LOGE("Stubbed out, to be implemented");
+  return 0;
+}
+
+bool PlatformAudio::getAudioSource(uint32_t /*handle*/,
+                                   struct chreAudioSource * /*source*/) const {
+  LOGE("Stubbed out, to be implemented");
+  return false;
+}
+
+void PlatformAudio::setHandleEnabled(uint32_t /*handle*/, bool /*enabled*/) {
+  LOGE("Stubbed out, to be implemented");
+}
+
+void PlatformAudio::cancelAudioDataEventRequest(uint32_t /*handle*/) {
+  LOGE("Stubbed out, to be implemented");
+}
+
+bool PlatformAudio::requestAudioDataEvent(uint32_t /*handle*/,
+                                          uint32_t /*numSamples*/,
+                                          Nanoseconds /*eventDelay*/) {
+  LOGE("Stubbed out, to be implemented");
+  return false;
+}
+
+}  // namespace chre
\ No newline at end of file
diff --git a/platform/aoc/power_control_manager.cc b/platform/aoc/power_control_manager.cc
new file mode 100644
index 0000000..d08ad6a
--- /dev/null
+++ b/platform/aoc/power_control_manager.cc
@@ -0,0 +1,30 @@
+/*
+ * 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/platform/power_control_manager.h"
+
+namespace chre {
+
+void PowerControlManager::postEventLoopProcess(size_t /* numPendingEvents */) {
+  // TODO: stubbed out, Implement this.
+}
+
+bool PowerControlManager::hostIsAwake() {
+  // TODO: stubbed out, Implement this.
+  return true;
+}
+
+}  // namespace chre
diff --git a/platform/aoc/system_time.cc b/platform/aoc/system_time.cc
new file mode 100644
index 0000000..ded9a63
--- /dev/null
+++ b/platform/aoc/system_time.cc
@@ -0,0 +1,42 @@
+/*
+ * 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/platform/system_time.h"
+#include "chre/platform/assert.h"
+#include "chre/platform/log.h"
+
+#include "efw/include/timer.h"
+
+namespace chre {
+
+namespace {
+
+int64_t gEstimatedHostTimeOffset = 0;
+
+}
+
+Nanoseconds SystemTime::getMonotonicTime() {
+  return Nanoseconds(Timer::Instance()->TimestampNanoseconds());
+}
+
+int64_t SystemTime::getEstimatedHostTimeOffset() {
+  return gEstimatedHostTimeOffset;
+}
+
+void setEstimatedHostTimeOffset(int64_t offset) {
+  gEstimatedHostTimeOffset = offset;
+}
+
+}  // namespace chre
diff --git a/platform/aoc/system_timer.cc b/platform/aoc/system_timer.cc
new file mode 100644
index 0000000..4f16543
--- /dev/null
+++ b/platform/aoc/system_timer.cc
@@ -0,0 +1,147 @@
+/*
+ * 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/platform/system_timer.h"
+#include "chre/platform/assert.h"
+#include "chre/platform/log.h"
+#include "chre/util/time.h"
+
+#include "efw/include/timer.h"
+
+namespace {
+
+// We work with both simulated (linux port of FreeRTOS), and real (a32)
+// target platforms. The timer dispatch thread is notifed from a
+// timer interrupt context, and there are context checks in the FreeRTOS code
+// (i.e. the xxGive and xxGiveFromISR are not interchangeable). Since there
+// are no interrupts in a simulated platform, we end up with two different
+// notification mechanisms that accomplish the same purpose.
+void wakeupDispatchThread(TaskHandle_t &handle) {
+#ifdef CHRE_PLATFORM_IS_SIMULATED
+  // no ISRs in simulated platforms!
+  xTaskNotifyGive(handle);
+#else
+  BaseType_t xHigherPriorityTaskWoken = pdFALSE;
+  vTaskNotifyGiveFromISR(handle, &xHigherPriorityTaskWoken);
+  portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
+#endif
+}
+
+}  // namespace
+
+namespace chre {
+
+TaskHandle_t SystemTimerBase::mTimerCbDispatchThreadHandle = NULL;
+
+bool SystemTimerBase::systemTimerNotifyCallback(void *context) {
+  SystemTimer *pTimer = static_cast<SystemTimer *>(context);
+  if (pTimer != nullptr) {
+    wakeupDispatchThread(mTimerCbDispatchThreadHandle);
+  }
+
+  // The EFW timer callback is setup in such a way that returning 'true'
+  // here reschedules the timer, while returning 'false' does not.
+  // Since we're interested in a one-shot timer, we return 'false' here.
+  return false;
+}
+
+void SystemTimerBase::timerCallbackDispatch(void *context) {
+  SystemTimer *pTimer = static_cast<SystemTimer *>(context);
+  if (pTimer == nullptr) {
+    FATAL_ERROR("Null System Timer");
+  }
+
+  LOGD("CHRE-AoC Timer Dispatch Thread started");
+
+  while (true) {
+    ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
+    if ((pTimer != nullptr) && (pTimer->mCallback != nullptr)) {
+      pTimer->mCallback(pTimer->mData);
+    }
+  }
+}
+
+SystemTimer::SystemTimer() {}
+
+SystemTimer::~SystemTimer() {
+  // cancel an existing timer if any
+  cancel();
+  // Delete the timer dispatch thread if it was created
+  if (mTimerCbDispatchThreadHandle != NULL) {
+    vTaskDelete(mTimerCbDispatchThreadHandle);
+  }
+}
+
+bool SystemTimer::init() {
+  BaseType_t rc =
+      xTaskCreate(timerCallbackDispatch, "TimerCbDispatch", 1024, this,
+                  tskIDLE_PRIORITY + 2, &mTimerCbDispatchThreadHandle);
+  if (pdTRUE == rc) {
+    mInitialized = true;
+  } else {
+    LOGE("Failed to create Timer Dispatch Thread");
+  }
+
+  return mInitialized;
+}
+
+bool SystemTimer::set(SystemTimerCallback *callback, void *data,
+                      Nanoseconds delay) {
+  bool success = false;
+
+  if (mInitialized) {
+    // TODO: b/146374655 - investigate/handle possible race condition here
+    mCallback = callback;
+    mData = data;
+
+    // TODO(karthikmb): The capping on the maximum delay is temporary,
+    // remove after b/157537617 is implemented. See the note on
+    // kMaxSupportedDelayNs for some additional context.
+    if (delay > kMaxSupportedDelayNs) {
+      delay = kMaxSupportedDelayNs;
+    }
+
+    Timer *timer = Timer::Instance();
+    int rc =
+        timer->EventAddAtOffset(timer->NsToTicks(delay.toRawNanoseconds()),
+                                systemTimerNotifyCallback, this, &mTimerHandle);
+
+    if (rc != 0) {
+      LOGE("Failed to set timer");
+    } else {
+      success = true;
+    }
+  }
+
+  return success;
+}
+
+bool SystemTimer::cancel() {
+  // TODO: test this
+  int rc = -1;
+  if (mTimerHandle != nullptr) {
+    rc = Timer::Instance()->EventRemove(mTimerHandle);
+  }
+
+  return (rc == 0) ? true : false;
+}
+
+bool SystemTimer::isActive() {
+  // TODO: stubbed out, Implement this.
+  return false;
+}
+
+}  // namespace chre
diff --git a/platform/freertos/context.cc b/platform/freertos/context.cc
new file mode 100644
index 0000000..8ee7448
--- /dev/null
+++ b/platform/freertos/context.cc
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2019 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/platform/context.h"
+#include "chre/target_platform/init.h"
+
+#include "FreeRTOS.h"
+#include "task.h"
+
+namespace chre {
+
+bool inEventLoopThread() {
+  TaskHandle_t evtLoopTaskHandle = xTaskGetHandle(freertos::getChreTaskName());
+  TaskHandle_t currentTaskHandle = xTaskGetCurrentTaskHandle();
+
+  return (evtLoopTaskHandle == currentTaskHandle);
+}
+
+}  // namespace chre
diff --git a/platform/freertos/dlfcn.cc b/platform/freertos/dlfcn.cc
new file mode 100644
index 0000000..e4ae647
--- /dev/null
+++ b/platform/freertos/dlfcn.cc
@@ -0,0 +1,58 @@
+/*
+ * 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/platform/freertos/dlfcn.h"
+
+#include "chre/platform/assert.h"
+#include "chre/platform/freertos/nanoapp_loader.h"
+#include "chre/platform/memory.h"
+#include "chre/util/unique_ptr.h"
+
+namespace chre {
+
+void *dlopenbuf(void *elfBinary) {
+  return NanoappLoader::create(elfBinary);
+}
+
+void *dlsym(void *handle, const char *symbol) {
+  LOGV("Attempting to find %s", symbol);
+
+  void *resolvedSymbol = nullptr;
+  auto *loader = reinterpret_cast<NanoappLoader *>(handle);
+  if (loader != nullptr) {
+    resolvedSymbol = loader->findSymbolByName(symbol);
+    LOGV("Found symbol at %p", resolvedSymbol);
+  }
+  return resolvedSymbol;
+}
+
+int dlclose(void *handle) {
+  int rv = -1;
+  UniquePtr<NanoappLoader> loader = static_cast<NanoappLoader *>(handle);
+
+  if (!loader.isNull()) {
+    loader->deinit();
+    rv = 0;
+  }
+
+  return rv;
+}
+
+const char *dlerror() {
+  return "Shared library load failed";
+}
+
+}  // namespace chre
diff --git a/platform/freertos/include/chre/platform/freertos/dlfcn.h b/platform/freertos/include/chre/platform/freertos/dlfcn.h
new file mode 100644
index 0000000..8cd3a18
--- /dev/null
+++ b/platform/freertos/include/chre/platform/freertos/dlfcn.h
@@ -0,0 +1,54 @@
+/*
+ * 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_PLATFORM_FREERTOS_DLFCN_H_
+#define CHRE_PLATFORM_FREERTOS_DLFCN_H_
+
+#include <cstdlib>
+
+namespace chre {
+
+/**
+ * This function parses, verifies, and loads a buffer containing an ELF
+ * file, and returns an opaque handle for symbol lookup via dlsym.
+ * Note that there is no requirement to pass in a 'buffer size' argument,
+ * since all the necessary information is gathered from the headers
+ * embedded in the elf file itself. The buffer is expected to contain the
+ * entire elf file in memory (cannot be a FILE pointer, for example).
+ *
+ * @param elfBinary is a buffer containing the elf file
+ */
+void *dlopenbuf(void *elfBinary);
+
+/**
+ * Returns a (function) pointer to the symbol named by the input argument.
+ *
+ * @return pointer to the symbol if it was found, nullptr if not found or
+ * the handle was invalid
+ */
+void *dlsym(void *handle, const char *symbol);
+
+/**
+ * Invalidate the handle used for symbol lookup, and free up any
+ * allocated memory.
+ *
+ * @return 0 on success
+ */
+int dlclose(void *handle);
+
+}  // namespace chre
+
+#endif  // CHRE_PLATFORM_FREERTOS_DLFCN_H_
diff --git a/platform/freertos/include/chre/platform/freertos/dram_util.h b/platform/freertos/include/chre/platform/freertos/dram_util.h
new file mode 100644
index 0000000..c5ecb8c
--- /dev/null
+++ b/platform/freertos/include/chre/platform/freertos/dram_util.h
@@ -0,0 +1,55 @@
+/*
+ * 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_PLATFORM_FREERTOS_DRAM_UTIL_H_
+#define CHRE_PLATFORM_FREERTOS_DRAM_UTIL_H_
+
+#include "chre/platform/freertos/memory.h"
+#include "chre/util/non_copyable.h"
+
+namespace chre {
+
+/**
+ * This is an RAII-style class that enables and disables the active request
+ * for DRAM following the scope of the guard. The concept is the same as
+ * std::lock_guard.
+ */
+class DramGuard : public NonCopyable {
+ public:
+  /**
+   * Constructs a DramGuard and enables access to DRAM.
+   */
+  DramGuard() {
+    // TODO(stange): Change to FATAL_ERROR once this is guaranteed.
+    if (!requestDramAccess(true)) {
+      LOGE("Unable to request DRAM access");
+    }
+  }
+
+  /**
+   * Deconstructs a DramGuard and disables the active request for DRAM.
+   */
+  ~DramGuard() {
+    if (!requestDramAccess(false)) {
+      // TODO(stange): Change to FATAL_ERROR once this is guaranteed.
+      LOGE("Unable to release DRAM access");
+    }
+  }
+};
+
+}  // namespace chre
+
+#endif  // CHRE_PLATFORM_FREERTOS_DRAM_UTIL_H_
diff --git a/platform/freertos/include/chre/platform/freertos/loader_util.h b/platform/freertos/include/chre/platform/freertos/loader_util.h
new file mode 100644
index 0000000..cc03bd5
--- /dev/null
+++ b/platform/freertos/include/chre/platform/freertos/loader_util.h
@@ -0,0 +1,236 @@
+/*
+ * 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_PLATFORM_FREERTOS_LOADER_UTIL_H_
+#define CHRE_PLATFORM_FREERTOS_LOADER_UTIL_H_
+
+// The below macros allow switching the ELF symbol type between 32/64-bit
+// depending on what the chipset supports.
+#ifndef ELFW
+#ifndef __WORDSIZE
+// Until we can get a hold of wordsize.h, we need to define it here.
+// Only 32-bit architectures currently supported.
+#ifndef __aarch64__
+#define __WORDSIZE 32
+#else
+#error "Only 32-bit architectures currently supported"
+#endif
+#endif
+// https://refspecs.linuxbase.org/elf/gabi4+/ch4.reloc.html
+#define ELF32_R_SYM(info) ((info) >> 8)
+#define ELF32_R_TYPE(info) ((unsigned char)(info))
+#define ELF32_R_INFO(sym, type) (((sym) << 8) + (unsigned char)(type))
+#define __ELF_NATIVE_CLASS __WORDSIZE
+#define ELFW(type) _ELFW(__ELF_NATIVE_CLASS, type)
+#define _ELFW(bits, type) __ELFW(bits, type)
+#define __ELFW(bits, type) ELF##bits##_##type
+#endif
+#define ELFW_R_TYPE(x) ELFW(R_TYPE)(x)
+#define ELFW_R_SYM(x) ELFW(R_SYM)(x)
+
+struct ExportedData {
+  void *data;
+  const char *dataName;
+};
+
+// The below is copied from bionic/libc/kernel/uapi/linux/elf.h
+// to avoid pulling those deps into the build.
+#if defined(__LP64__)
+#define ElfW(type) Elf64_##type
+#else
+#define ElfW(type) Elf32_##type
+#endif
+
+#define EM_ARM 40
+#define EI_MAG0 0
+#define EI_MAG1 1
+#define EI_MAG2 2
+#define EI_MAG3 3
+#define EI_CLASS 4
+#define EI_DATA 5
+#define EI_VERSION 6
+#define EI_OSABI 7
+#define EI_PAD 8
+#define ELFMAG0 0x7f
+#define ELFMAG1 'E'
+#define ELFMAG2 'L'
+#define ELFMAG3 'F'
+#define ELFMAG "\177ELF"
+#define SELFMAG 4
+#define ELFCLASSNONE 0
+#define ELFCLASS32 1
+#define ELFCLASS64 2
+#define ELFCLASSNUM 3
+#define ELFDATANONE 0
+#define ELFDATA2LSB 1
+#define ELFDATA2MSB 2
+#define EV_NONE 0
+#define EV_CURRENT 1
+#define EV_NUM 2
+#define ELFOSABI_NONE 0
+#define ELFOSABI_LINUX 3
+#define PT_NULL 0
+#define PT_LOAD 1
+#define PT_DYNAMIC 2
+#define PT_INTERP 3
+#define PT_NOTE 4
+#define PT_SHLIB 5
+#define PT_PHDR 6
+#define PT_TLS 7
+#define PT_LOOS 0x60000000
+#define PT_HIOS 0x6fffffff
+#define PT_LOPROC 0x70000000
+#define PT_HIPROC 0x7fffffff
+#define PT_GNU_EH_FRAME 0x6474e550
+#define PT_GNU_STACK (PT_LOOS + 0x474e551)
+#define PN_XNUM 0xffff
+#define ET_NONE 0
+#define ET_REL 1
+#define ET_EXEC 2
+#define ET_DYN 3
+#define ET_CORE 4
+#define ET_LOPROC 0xff00
+#define ET_HIPROC 0xffff
+#define DT_NULL 0
+#define DT_NEEDED 1
+#define DT_PLTRELSZ 2
+#define DT_PLTGOT 3
+#define DT_HASH 4
+#define DT_STRTAB 5
+#define DT_SYMTAB 6
+#define DT_RELA 7
+#define DT_RELASZ 8
+#define DT_RELAENT 9
+#define DT_STRSZ 10
+#define DT_SYMENT 11
+#define DT_INIT 12
+#define DT_FINI 13
+#define DT_SONAME 14
+#define DT_RPATH 15
+#define DT_SYMBOLIC 16
+#define DT_REL 17
+#define DT_RELSZ 18
+#define DT_RELENT 19
+#define DT_PLTREL 20
+#define DT_DEBUG 21
+#define DT_TEXTREL 22
+#define DT_JMPREL 23
+#define DT_ENCODING 32
+
+typedef __signed__ char __s8;
+typedef unsigned char __u8;
+typedef __signed__ short __s16;
+typedef unsigned short __u16;
+typedef __signed__ int __s32;
+typedef unsigned int __u32;
+typedef __signed__ long __s64;
+typedef unsigned long __u64;
+
+typedef __u32 Elf32_Addr;
+typedef __u16 Elf32_Half;
+typedef __u32 Elf32_Off;
+typedef __s32 Elf32_Sword;
+typedef __u32 Elf32_Word;
+
+#define EI_NIDENT 16
+typedef struct elf32_hdr {
+  unsigned char e_ident[EI_NIDENT];
+  Elf32_Half e_type;
+  Elf32_Half e_machine;
+  Elf32_Word e_version;
+  Elf32_Addr e_entry;
+  Elf32_Off e_phoff;
+  Elf32_Off e_shoff;
+  Elf32_Word e_flags;
+  Elf32_Half e_ehsize;
+  Elf32_Half e_phentsize;
+  Elf32_Half e_phnum;
+  Elf32_Half e_shentsize;
+  Elf32_Half e_shnum;
+  Elf32_Half e_shstrndx;
+} Elf32_Ehdr;
+
+typedef struct dynamic {
+  Elf32_Sword d_tag;
+  union {
+    Elf32_Sword d_val;
+    Elf32_Addr d_ptr;
+  } d_un;
+} Elf32_Dyn;
+
+typedef struct elf32_phdr {
+  Elf32_Word p_type;
+  Elf32_Off p_offset;
+  Elf32_Addr p_vaddr;
+  Elf32_Addr p_paddr;
+  Elf32_Word p_filesz;
+  Elf32_Word p_memsz;
+  Elf32_Word p_flags;
+  Elf32_Word p_align;
+} Elf32_Phdr;
+
+typedef struct elf32_shdr {
+  Elf32_Word sh_name;
+  Elf32_Word sh_type;
+  Elf32_Word sh_flags;
+  Elf32_Addr sh_addr;
+  Elf32_Off sh_offset;
+  Elf32_Word sh_size;
+  Elf32_Word sh_link;
+  Elf32_Word sh_info;
+  Elf32_Word sh_addralign;
+  Elf32_Word sh_entsize;
+} Elf32_Shdr;
+
+typedef struct elf32_rela {
+  Elf32_Addr r_offset;
+  Elf32_Word r_info;
+  Elf32_Sword r_addend;
+} Elf32_Rela;
+
+typedef struct elf32_rel {
+  Elf32_Addr r_offset;
+  Elf32_Word r_info;
+} Elf32_Rel;
+
+typedef struct elf32_sym {
+  Elf32_Word st_name;
+  Elf32_Addr st_value;
+  Elf32_Word st_size;
+  unsigned char st_info;
+  unsigned char st_other;
+  Elf32_Half st_shndx;
+} Elf32_Sym;
+
+// The following defines are copied from bionic's elf_arm.h header
+// at bionic/libc/kernel/uapi/linux/elf.h
+// Only the relocation types currently supported are copied.
+#define R_ARM_NONE 0
+#define R_ARM_COPY 20
+#define R_ARM_GLOB_DAT 21
+#define R_ARM_JUMP_SLOT 22
+#define R_ARM_RELATIVE 23
+
+// The following (legal values for segment flags) are copied from
+// bionic's elf.h
+/* http://www.sco.com/developers/gabi/latest/ch5.pheader.html */
+#define PF_X 0x1
+#define PF_W 0x2
+#define PF_R 0x4
+#define PF_MASKOS 0x0ff00000
+#define PF_MASKPROC 0xf0000000
+
+#endif  // CHRE_PLATFORM_FREERTOS_LOADER_UTIL_H_
diff --git a/platform/freertos/include/chre/platform/freertos/memory.h b/platform/freertos/include/chre/platform/freertos/memory.h
new file mode 100644
index 0000000..f320c93
--- /dev/null
+++ b/platform/freertos/include/chre/platform/freertos/memory.h
@@ -0,0 +1,60 @@
+/*
+ * 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_PLATFORM_FREERTOS_MEMORY_H_
+#define CHRE_PLATFORM_FREERTOS_MEMORY_H_
+
+#include <cstddef>
+
+namespace chre {
+
+/**
+ * Aligned memory allocation specifically using the DRAM heap. The semantics are
+ * the same as malloc.
+ *
+ * If DRAM or another large memory capacity region is not available, this will
+ * allocate from the same memory region as memoryAlloc.
+ */
+void *memoryAllocDramAligned(size_t alignment, size_t size);
+
+/**
+ * Memory allocation specifically using the DRAM heap. The semantics are the
+ * same as malloc.
+ *
+ * If DRAM or another large memory capacity region is not available, this will
+ * allocate from the same memory region as memoryAlloc.
+ */
+void *memoryAllocDram(size_t size);
+
+/**
+ * Memory free from memory allocated using the DRAM heap. The semantics are the
+ * same as free.
+ *
+ * If DRAM or another large memory capacity region is not available, this will
+ * free from the same memory region as memoryFree.
+ */
+void memoryFreeDram(void *pointer);
+
+/**
+ * Requests or releases access to DRAM or another large capacity region, if
+ * available. If not such region exists, this method should return true and be a
+ * no-op.
+ */
+bool requestDramAccess(bool enabled);
+
+}  // namespace chre
+
+#endif  // CHRE_PLATFORM_FREERTOS_MEMORY_H_
diff --git a/platform/freertos/include/chre/platform/freertos/nanoapp_loader.h b/platform/freertos/include/chre/platform/freertos/nanoapp_loader.h
new file mode 100644
index 0000000..186da4b
--- /dev/null
+++ b/platform/freertos/include/chre/platform/freertos/nanoapp_loader.h
@@ -0,0 +1,127 @@
+/*
+ * 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_PLATFORM_FREERTOS_NANOAPP_LOADER_H_
+#define CHRE_PLATFORM_FREERTOS_NANOAPP_LOADER_H_
+
+#include <cinttypes>
+#include <cstdlib>
+
+#include "chre/platform/freertos/loader_util.h"
+
+namespace chre {
+
+class NanoappLoader {
+ public:
+  NanoappLoader() = delete;
+
+  explicit NanoappLoader(void *elfInput) {
+    mBinary.rawLocation = elfInput;
+  }
+
+  /**
+   * Factory method to create a NanoappLoader Instance after loading
+   * the buffer containing the ELF binary.
+   *
+   * @return Class instance on successful load and verification,
+   * nullptr otherwise.
+   */
+  static void *create(void *elfInput);
+
+  bool init();
+  void deinit();
+
+  /**
+   * Method for pointer lookup by symbol name. Only function pointers
+   * are currently supported.
+   *
+   * @return function pointer on successful lookup, nullptr otherwise
+   */
+  void *findSymbolByName(const char *name);
+
+ private:
+  // TODO(stange): Store this elsewhere since the location will be invalid after
+  // loading is complete.
+  union Data {
+    uintptr_t location;
+    void *rawLocation;
+  };
+
+  using DynamicHeader = ElfW(Dyn);
+  using ElfAddr = ElfW(Addr);
+  using ElfHeader = ElfW(Ehdr);
+  using ElfRel = ElfW(Rel);  // Relocation table entry,
+                             // in section of type SHT_REL
+  using ElfRela = ElfW(Rela);
+  using ElfSym = ElfW(Sym);
+  using ElfWord = ElfW(Word);
+  using ProgramHeader = ElfW(Phdr);
+  using SectionHeader = ElfW(Shdr);
+
+  static constexpr const char *kSymTableName = ".symtab";
+  static constexpr const char *kStrTableName = ".strtab";
+  static constexpr const char *kInitArrayName = ".init_array";
+  static constexpr const char *kFiniArrayName = ".fini_array";
+  // For now, assume all segments are 4K aligned.
+  // TODO(karthikmb/stange): See about reducing this.
+  static constexpr size_t kBinaryAlignment = 4096;
+
+  char *mDynamicStringTablePtr;
+  char *mSectionNamesPtr;
+  char *mStringTablePtr;
+  uint8_t *mDynamicSymbolTablePtr;
+  uint8_t *mSymbolTablePtr;
+  size_t mDynamicSymbolTableSize;
+  size_t mNumProgramHeaders;
+  size_t mNumSectionHeaders;
+  size_t mSymbolTableSize;
+
+  Data mBinary;
+  Data mMapping;
+  DynamicHeader *mDynamicHeaderPtr;
+  ElfAddr mLoadBias;
+  ElfHeader mElfHeader;
+  ProgramHeader *mProgramHeadersPtr;
+  SectionHeader *mSectionHeadersPtr;
+  SectionHeader mStringTableHeader;
+  SectionHeader mSymbolTableHeader;
+
+  void callInitArray();
+  void callTerminatorArray();
+  bool createMappings();
+  bool copyAndVerifyHeaders();
+  bool fixRelocations();
+  bool initDynamicStringTable();
+  bool initDynamicSymbolTable();
+  bool resolveGot();
+  bool verifyElfHeader();
+  bool verifyProgramHeaders();
+  bool verifySectionHeaders();
+  const char *getDataName(size_t posInSymbolTable);
+  const char *getSectionHeaderName(size_t sh_name);
+  uintptr_t roundDownToAlign(uintptr_t virtualAddr);
+  void freeAllocatedData();
+  void mapBss(const ProgramHeader *header);
+  void *resolveData(size_t posInSymbolTable);
+  DynamicHeader *getDynamicHeader();
+  ProgramHeader *getFirstRoSegHeader();
+  SectionHeader *getSectionHeader(const char *headerName);
+  ElfWord getDynEntry(DynamicHeader *dyn, int field);
+};
+
+}  // namespace chre
+
+#endif  // CHRE_PLATFORM_FREERTOS_NANOAPP_LOADER_H_
diff --git a/platform/freertos/include/chre/target_platform/atomic_base.h b/platform/freertos/include/chre/target_platform/atomic_base.h
new file mode 100644
index 0000000..582d0ae
--- /dev/null
+++ b/platform/freertos/include/chre/target_platform/atomic_base.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2019 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_PLATFORM_FREERTOS_ATOMIC_BASE_H_
+#define CHRE_PLATFORM_FREERTOS_ATOMIC_BASE_H_
+
+#include <atomic>
+
+namespace chre {
+
+template <typename AtomicType>
+class AtomicBase {
+ protected:
+  std::atomic<AtomicType> mAtomic;
+};
+
+typedef AtomicBase<bool> AtomicBoolBase;
+typedef AtomicBase<uint32_t> AtomicUint32Base;
+
+}  // namespace chre
+
+#endif  // CHRE_PLATFORM_FREERTOS_ATOMIC_BASE_H_
diff --git a/platform/freertos/include/chre/target_platform/atomic_base_impl.h b/platform/freertos/include/chre/target_platform/atomic_base_impl.h
new file mode 100644
index 0000000..d44a197
--- /dev/null
+++ b/platform/freertos/include/chre/target_platform/atomic_base_impl.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2019 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_PLATFORM_FREERTOS_ATOMIC_BASE_IMPL_H_
+#define CHRE_PLATFORM_FREERTOS_ATOMIC_BASE_IMPL_H_
+
+#include "chre/platform/atomic.h"
+
+namespace chre {
+
+inline AtomicBool::AtomicBool(bool startingValue) {
+  std::atomic_init(&mAtomic, startingValue);
+}
+
+inline bool AtomicBool::operator=(bool desired) {
+  mAtomic = desired;
+  return desired;
+}
+
+inline bool AtomicBool::load() const {
+  return mAtomic.load();
+}
+
+inline void AtomicBool::store(bool desired) {
+  mAtomic.store(desired);
+}
+
+inline bool AtomicBool::exchange(bool desired) {
+  return mAtomic.exchange(desired);
+}
+
+inline AtomicUint32::AtomicUint32(uint32_t startingValue) {
+  std::atomic_init(&mAtomic, startingValue);
+}
+
+inline uint32_t AtomicUint32::operator=(uint32_t desired) {
+  mAtomic = desired;
+  return desired;
+}
+
+inline uint32_t AtomicUint32::load() const {
+  return mAtomic.load();
+}
+
+inline void AtomicUint32::store(uint32_t desired) {
+  mAtomic.store(desired);
+}
+
+inline uint32_t AtomicUint32::exchange(uint32_t desired) {
+  return mAtomic.exchange(desired);
+}
+
+inline uint32_t AtomicUint32::fetch_add(uint32_t arg) {
+  return mAtomic.fetch_add(arg);
+}
+
+inline uint32_t AtomicUint32::fetch_increment() {
+  return mAtomic.fetch_add(1);
+}
+
+inline uint32_t AtomicUint32::fetch_sub(uint32_t arg) {
+  return mAtomic.fetch_sub(arg);
+}
+
+inline uint32_t AtomicUint32::fetch_decrement() {
+  return mAtomic.fetch_sub(1);
+}
+
+}  // namespace chre
+
+#endif  // CHRE_PLATFORM_FREERTOS_ATOMIC_BASE_IMPL_H_
diff --git a/platform/freertos/include/chre/target_platform/condition_variable_base.h b/platform/freertos/include/chre/target_platform/condition_variable_base.h
new file mode 100644
index 0000000..9ad3c49
--- /dev/null
+++ b/platform/freertos/include/chre/target_platform/condition_variable_base.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2019 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_PLATFORM_FREERTOS_CONDITION_VARIABLE_BASE_H_
+#define CHRE_PLATFORM_FREERTOS_CONDITION_VARIABLE_BASE_H_
+
+#include "chre/platform/mutex.h"
+#include "chre/platform/system_timer.h"
+#include "chre/target_platform/fatal_error.h"
+
+#include "FreeRTOS.h"
+#include "semphr.h"
+
+namespace chre {
+
+/**
+ * @brief FreeRTOS implementation of the condition variable
+ *        using FreeRTOS primitives
+ *
+ * The following base class implements the CHRE ConditionVariable
+ * interface for FreeRTOS. Some points to be noted:
+ * - We have the benefit of not needing to support notify_all(),
+ *   as we only provide the notify_one() abstraction to common code.
+ * - We don't have the requirement where more than 1 thread can wait
+ *   on a given condition variable in parallel  (which kind of goes against the
+ *   CV name, but really we were looking for something that let us implement
+ *   @ref FixedSizeBlockingQueue while keeping familiarity to the C++11 thread
+ *   support library
+ * - Currently, there's exactly one user of the condition variable in the common
+ *   code, and that's the FixedSizeBlockingQueue used by the EventLoop. Hence,
+ *   we can codify assumptions that are well supported by the current code into
+ *   the API. One example of this would be ensuring the caller can handle
+ *   spurious wakeups (which is fine for CHRE) as the worst side effect of this
+ *   is an extra iteration of the while-empty-queue loop.
+ */
+class ConditionVariableBase {
+ protected:
+  // Since, per CHRE specification, only one thread is ever
+  // going to be blocked on this condition variable, all we
+  // need is a Binary Semaphore. Note that:
+  // - while std::condition_variable allows for multiple threads
+  //   to wait on the same condition variable object
+  //   concurrently, the CHRE platform implementation is only required
+  //   to allow for a single waiting thread.
+  // - The calling code has to allow for spurious wakeups
+
+  SemaphoreHandle_t mCvSemaphoreHandle;
+
+  /**
+   * Waits on a semaphore for a specified amount of timer ticks,
+   * locking the mutex before returning. If the timer ticks argument is
+   * 0, blocks indefinitely.
+   *
+   * @return true if the semaphore was successfully taken
+   */
+  bool waitWithTimeout(Mutex &mutex, const TickType_t &timeoutTicks) {
+    mutex.unlock();
+    BaseType_t rc = xSemaphoreTake(mCvSemaphoreHandle, timeoutTicks);
+    mutex.lock();
+
+    return (rc == pdTRUE);
+  }
+
+  /**
+   * Initialize a Static FreeRTOS semaphore. This function is called
+   * from the derived class constructor
+   */
+  void initStaticSemaphore() {
+    mCvSemaphoreHandle = xSemaphoreCreateBinaryStatic(&mCvStaticSemaphore);
+    if (mCvSemaphoreHandle == NULL) {
+      FATAL_ERROR("failed to create cv semaphore");
+    }
+  }
+
+ private:
+  StaticSemaphore_t mCvStaticSemaphore;
+};
+
+}  // namespace chre
+
+#endif  // CHRE_PLATFORM_FREERTOS_CONDITION_VARIABLE_BASE_H_
diff --git a/platform/freertos/include/chre/target_platform/condition_variable_impl.h b/platform/freertos/include/chre/target_platform/condition_variable_impl.h
new file mode 100644
index 0000000..32351ca
--- /dev/null
+++ b/platform/freertos/include/chre/target_platform/condition_variable_impl.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2019 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_PLATFORM_FREERTOS_CONDITION_VARIABLE_IMPL_H_
+#define CHRE_PLATFORM_FREERTOS_CONDITION_VARIABLE_IMPL_H_
+
+#include "chre/platform/condition_variable.h"
+
+namespace chre {
+
+inline ConditionVariable::ConditionVariable() {
+  initStaticSemaphore();
+}
+
+inline ConditionVariable::~ConditionVariable() {
+  if (mCvSemaphoreHandle != NULL) {
+    vSemaphoreDelete(mCvSemaphoreHandle);
+  }
+}
+
+inline void ConditionVariable::notify_one() {
+  xSemaphoreGive(mCvSemaphoreHandle);
+}
+
+inline void ConditionVariable::wait(Mutex &mutex) {
+  const TickType_t timeout = portMAX_DELAY;  // block indefinitely
+  waitWithTimeout(mutex, timeout);
+}
+
+inline bool ConditionVariable::wait_for(Mutex &mutex, Nanoseconds timeout) {
+  const TickType_t timeoutTicks = static_cast<TickType_t>(
+      Timer::Instance()->NsToTicks(timeout.toRawNanoseconds()));
+  return waitWithTimeout(mutex, timeoutTicks);
+}
+
+}  // namespace chre
+
+#endif  // CHRE_PLATFORM_FREERTOS_CONDITION_VARIABLE_IMPL_H_
diff --git a/platform/freertos/include/chre/target_platform/init.h b/platform/freertos/include/chre/target_platform/init.h
new file mode 100644
index 0000000..5eb90c9
--- /dev/null
+++ b/platform/freertos/include/chre/target_platform/init.h
@@ -0,0 +1,48 @@
+/*
+ * 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_PLATFORM_FREERTOS_INIT_H_
+#define CHRE_PLATFORM_FREERTOS_INIT_H_
+
+#include "FreeRTOS.h"
+
+namespace chre {
+namespace freertos {
+
+/**
+ * This init function spawns a (non-privileged) FreeRTOS task that
+ * initializes the CHRE core, loads any static nanoapps, and starts
+ * the CHRE event loop.
+ * The task attribute constants are located in the corresponding init.cc
+ * source file, in case they need to be altered. The defaults chosen are:
+ * - Task Stack Depth: 8K Words
+ * - Task Priority: 1 (idle_task + 1)
+ *
+ * @return pdPASS on success, a FreeRTOS error code otherwise.
+ */
+BaseType_t init();
+
+/**
+ * Delete the task spawned in the init function
+ */
+void deinit();
+
+const char *getChreTaskName();
+
+}  // namespace freertos
+}  // namespace chre
+
+#endif  // CHRE_PLATFORM_FREERTOS_INIT_H_
diff --git a/platform/freertos/include/chre/target_platform/mutex_base.h b/platform/freertos/include/chre/target_platform/mutex_base.h
new file mode 100644
index 0000000..d26170a
--- /dev/null
+++ b/platform/freertos/include/chre/target_platform/mutex_base.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2019 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_PLATFORM_FREERTOS_MUTEX_BASE_H_
+#define CHRE_PLATFORM_FREERTOS_MUTEX_BASE_H_
+
+#include "chre/platform/assert.h"
+#include "chre/platform/log.h"
+
+#include "FreeRTOS.h"
+#include "semphr.h"
+
+namespace chre {
+
+/**
+ * The FreeRTOS implementation of MutexBase
+ */
+class MutexBase {
+ protected:
+  SemaphoreHandle_t mSemaphoreHandle;
+
+  /**
+   * Initialize the mutex handle using a static semaphore
+   * to avoid heap allocations
+   */
+  void initStaticMutex() {
+    mSemaphoreHandle = xSemaphoreCreateMutexStatic(&mStaticSemaphore);
+    if (mSemaphoreHandle == NULL) {
+      FATAL_ERROR("Failed to initialize mutex");
+    }
+  }
+
+ private:
+  StaticSemaphore_t mStaticSemaphore;
+};
+
+}  // namespace chre
+
+#endif  // CHRE_PLATFORM_FREERTOS_MUTEX_BASE_H_
diff --git a/platform/freertos/include/chre/target_platform/mutex_base_impl.h b/platform/freertos/include/chre/target_platform/mutex_base_impl.h
new file mode 100644
index 0000000..23e957d
--- /dev/null
+++ b/platform/freertos/include/chre/target_platform/mutex_base_impl.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2019 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_PLATFORM_FREERTOS_MUTEX_BASE_IMPL_H_
+#define CHRE_PLATFORM_FREERTOS_MUTEX_BASE_IMPL_H_
+
+#include "chre/platform/mutex.h"
+
+namespace chre {
+
+inline Mutex::Mutex() {
+  initStaticMutex();
+}
+
+inline Mutex::~Mutex() {
+  if (mSemaphoreHandle) {
+    vSemaphoreDelete(mSemaphoreHandle);
+  }
+}
+
+inline void Mutex::lock() {
+  TickType_t blockForever = portMAX_DELAY;
+  if (pdTRUE != xSemaphoreTake(mSemaphoreHandle, blockForever)) {
+    LOGE("Failed to lock mutex");
+  }
+}
+
+inline bool Mutex::try_lock() {
+  TickType_t doNotBlock = static_cast<TickType_t>(0);
+  BaseType_t rv = xSemaphoreTake(mSemaphoreHandle, doNotBlock);
+
+  return (rv == pdTRUE) ? true : false;
+}
+
+inline void Mutex::unlock() {
+  if (pdTRUE != xSemaphoreGive(mSemaphoreHandle)) {
+    LOGE("Failed to properly unlock mutex!");
+  }
+}
+
+}  // namespace chre
+
+#endif  // CHRE_PLATFORM_FREERTOS_MUTEX_BASE_IMPL_H_
diff --git a/platform/freertos/include/chre/target_platform/platform_debug_dump_manager_base.h b/platform/freertos/include/chre/target_platform/platform_debug_dump_manager_base.h
new file mode 100644
index 0000000..5c2399c
--- /dev/null
+++ b/platform/freertos/include/chre/target_platform/platform_debug_dump_manager_base.h
@@ -0,0 +1,59 @@
+/*
+ * 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_PLATFORM_FREERTOS_PLATFORM_DEBUG_DUMP_MANAGER_BASE_H_
+#define CHRE_PLATFORM_FREERTOS_PLATFORM_DEBUG_DUMP_MANAGER_BASE_H_
+
+#include <cstdbool>
+#include <cstddef>
+#include <cstdint>
+
+namespace chre {
+
+/**
+ * FreeRTOS-specific debug dump functionality.
+ */
+class PlatformDebugDumpManagerBase {
+ public:
+  /**
+   * To be called when receiving a debug dump request from host.
+   *
+   * @param hostClientId The host client ID that requested the debug dump.
+   */
+  void onDebugDumpRequested(uint16_t hostClientId);
+
+  /**
+   * @see PlatformDebugDumpManager::sendDebugDump
+   */
+  void sendDebugDumpResult(const char *debugStr, size_t debugStrSize,
+                           bool complete);
+
+ protected:
+  //! Host client ID that triggered the debug dump process.
+  uint16_t mHostClientId = 0;
+
+  //! Number of times sendDebugDumpToHost called with debugStrSize > 0.
+  uint32_t mDataCount = 0;
+
+  //! Whenther the last debug dump session has been marked complete.
+  bool mComplete = true;
+
+  static constexpr size_t kDebugDumpStrMaxSize = CHRE_MESSAGE_TO_HOST_MAX_SIZE;
+};
+
+}  // namespace chre
+
+#endif  // CHRE_PLATFORM_SLPI_PLATFORM_DEBUG_DUMP_MANAGER_BASE_H_
diff --git a/platform/freertos/include/chre/target_platform/platform_nanoapp_base.h b/platform/freertos/include/chre/target_platform/platform_nanoapp_base.h
new file mode 100644
index 0000000..fbf9786
--- /dev/null
+++ b/platform/freertos/include/chre/target_platform/platform_nanoapp_base.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2019 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_PLATFORM_FREERTOS_PLATFORM_NANOAPP_BASE_H_
+#define CHRE_PLATFORM_FREERTOS_PLATFORM_NANOAPP_BASE_H_
+
+#include "chre/platform/shared/nanoapp_support_lib_dso.h"
+
+namespace chre {
+
+/**
+ * FREERTOS-specific nanoapp functionality.
+ */
+class PlatformNanoappBase {
+ public:
+  /**
+   * Associate this Nanoapp instance with a nanoapp that is statically built
+   * into the CHRE binary with the given app info structure.
+   */
+  void loadStatic(const struct chreNslNanoappInfo *appInfo);
+
+  /**
+   * @return true if the app's binary data is resident in memory or if the app's
+   *         filename is saved, i.e. all binary fragments are loaded through
+   *         copyNanoappFragment, loadFromFile/loadStatic() was successful
+   */
+  bool isLoaded() const;
+
+  /**
+   * Sets app info that will be used later when the app is loaded into the
+   * system.
+   *
+   * @param appId The unique app identifier associated with this binary
+   * @param appVersion An application-defined version number
+   * @param appFilename The filename of the app that should be loaded from disk
+   *
+   * @return true if the info was successfully stored
+   */
+  bool setAppInfo(uint64_t appId, uint32_t appVersion, const char *appFilename);
+
+  /**
+   * Reserves buffer space for a nanoapp's binary. This method should be called
+   * before copyNanoappFragment is called.
+   *
+   * @param appId The unique app identifier associated with this binary
+   * @param appVersion An application-defined version number
+   * @param appBinaryLen Size of appBinary, in bytes
+   *
+   * @return true if the allocation was successful, false otherwise
+   */
+  bool reserveBuffer(uint64_t appId, uint32_t appVersion, size_t appBinaryLen);
+
+  /**
+   * Copies the (possibly fragmented) application binary data into the allocated
+   * buffer, and updates the pointer to the next address to write into. The
+   * application may be invalid - full checking and initialization happens just
+   * before invoking start() nanoapp entry point.
+   *
+   * @param buffer The pointer to the buffer
+   * @param bufferSize The size of the buffer in bytes
+   *
+   * @return true if the reserved buffer did not overflow, false otherwise
+   */
+  bool copyNanoappFragment(const void *buffer, size_t bufferSize);
+
+ protected:
+  //! The app ID we received in the metadata alongside the nanoapp binary. This
+  //! is also included in (and checked against) mAppInfo.
+  uint64_t mExpectedAppId;
+
+  //! The application-defined version number we received in the metadata
+  //! alongside the nanoapp binary. This is also included in (and checked
+  //! against) mAppInfo.
+  uint32_t mExpectedAppVersion = 0;
+
+  //! Buffer containing the complete DSO binary - only populated if
+  //! copyNanoappFragment() was used to load this nanoapp
+  void *mAppBinary = nullptr;
+  size_t mAppBinaryLen = 0;
+
+  //! Null-terminated ASCII string containing the file name that contains the
+  //! app binary to be loaded. This is used over mAppBinary to load the nanoapp
+  //! if set.
+  char *mAppFilename = nullptr;
+
+  //! The dynamic shared object (DSO) handle returned by dlopenbuf()
+  void *mDsoHandle = nullptr;
+
+  //! Pointer to the app info structure within this nanoapp
+  const struct chreNslNanoappInfo *mAppInfo = nullptr;
+
+  //! Set to true if this app is built into the CHRE binary, and was loaded via
+  //! loadStatic(). In this case, the member variables above are not valid or
+  //! applicable.
+  bool mIsStatic = false;
+
+  //! The number of bytes of the binary that has been loaded so far.
+  size_t mBytesLoaded = 0;
+
+  /**
+   * Loads the nanoapp symbols from the currently loaded binary and verifies
+   * they match the expected information the nanoapp should have.
+   *
+   * @return true if the app info structure passed validation.
+   */
+  bool verifyNanoappInfo();
+
+  /**
+   * Calls through to openNanoappFromBuffer or openNanoappFromFile, depending on
+   * how this nanoapp was loaded.
+   */
+  bool openNanoapp();
+
+  /**
+   * Releases the DSO handle if it was active, by calling dlclose(). This will
+   * result in execution of any unload handlers in the nanoapp.
+   */
+  void closeNanoapp();
+};
+
+}  // namespace chre
+
+#endif  // CHRE_PLATFORM_FREERTOS_PLATFORM_NANOAPP_BASE_H_
diff --git a/platform/freertos/include/chre/target_platform/static_nanoapp_init.h b/platform/freertos/include/chre/target_platform/static_nanoapp_init.h
new file mode 100644
index 0000000..75d3531
--- /dev/null
+++ b/platform/freertos/include/chre/target_platform/static_nanoapp_init.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2019 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_PLATFORM_FREERTOS_STATIC_NANOAPP_INIT_H_
+#define CHRE_PLATFORM_FREERTOS_STATIC_NANOAPP_INIT_H_
+
+#include "chre/core/nanoapp.h"
+#include "chre/platform/fatal_error.h"
+#include "chre/util/unique_ptr.h"
+
+#define CHRE_STATIC_NANOAPP_INIT(appName, appId_, appVersion_)               \
+  namespace chre {                                                           \
+                                                                             \
+  UniquePtr<Nanoapp> initializeStaticNanoapp##appName() {                    \
+    UniquePtr<Nanoapp> nanoapp = MakeUnique<Nanoapp>();                      \
+    static struct chreNslNanoappInfo appInfo;                                \
+    appInfo.magic = CHRE_NSL_NANOAPP_INFO_MAGIC;                             \
+    appInfo.structMinorVersion = CHRE_NSL_NANOAPP_INFO_STRUCT_MINOR_VERSION; \
+    appInfo.targetApiVersion = CHRE_API_VERSION;                             \
+    appInfo.vendor = "Google"; /* TODO: make this configurable */            \
+    appInfo.name = #appName;                                                 \
+    appInfo.isSystemNanoapp = true;                                          \
+    appInfo.isTcmNanoapp = false;                                            \
+    appInfo.appId = appId_;                                                  \
+    appInfo.appVersion = appVersion_;                                        \
+    appInfo.entryPoints.start = nanoappStart;                                \
+    appInfo.entryPoints.handleEvent = nanoappHandleEvent;                    \
+    appInfo.entryPoints.end = nanoappEnd;                                    \
+    appInfo.appVersionString = "<undefined>";                                \
+    if (nanoapp.isNull()) {                                                  \
+      FATAL_ERROR("Failed to allocate nanoapp " #appName);                   \
+    } else {                                                                 \
+      nanoapp->loadStatic(&appInfo);                                         \
+    }                                                                        \
+                                                                             \
+    return nanoapp;                                                          \
+  }                                                                          \
+  } /* namespace chre */
+
+#endif  // CHRE_PLATFORM_FREERTOS_NANOAPP_INIT_H_
diff --git a/platform/freertos/init.cc b/platform/freertos/init.cc
new file mode 100644
index 0000000..451c032
--- /dev/null
+++ b/platform/freertos/init.cc
@@ -0,0 +1,73 @@
+/*
+ * 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/core/init.h"
+#include "chre/core/event_loop_manager.h"
+#include "chre/core/static_nanoapps.h"
+#include "chre/target_platform/init.h"
+
+#include "task.h"
+
+namespace chre {
+namespace freertos {
+namespace {
+
+constexpr configSTACK_DEPTH_TYPE kChreTaskStackDepthWords = 0x800;
+constexpr UBaseType_t kChreTaskPriority = tskIDLE_PRIORITY + 1;
+
+TaskHandle_t gChreTaskHandle;
+
+// This function is intended to be the task action function for FreeRTOS.
+// It Initializes CHRE, runs the event loop, and only exits if it receives
+// a message to shutdown. Note that depending on the hardware platform this
+// runs on, CHRE might create additional threads, which are cleaned up when
+// CHRE exits.
+void chreThreadEntry(void *context) {
+  chre::init();
+  chre::EventLoopManagerSingleton::get()->lateInit();
+  chre::loadStaticNanoapps();
+
+  chre::EventLoopManagerSingleton::get()->getEventLoop().run();
+
+  // we only get here if the CHRE EventLoop exited
+  chre::deinit();
+}
+
+}  // namespace
+
+BaseType_t init() {
+  BaseType_t rc = xTaskCreate(chreThreadEntry, freertos::getChreTaskName(),
+                              kChreTaskStackDepthWords, nullptr /* args */,
+                              kChreTaskPriority, &gChreTaskHandle);
+  CHRE_ASSERT(rc == pdPASS);
+  return rc;
+}
+
+void deinit() {
+  if (gChreTaskHandle != nullptr) {
+    chre::EventLoopManagerSingleton::get()->getEventLoop().stop();
+    vTaskDelete(gChreTaskHandle);
+    gChreTaskHandle = nullptr;
+  }
+}
+
+const char *getChreTaskName() {
+  static constexpr char kChreTaskName[] = "CHRE";
+  return kChreTaskName;
+}
+
+}  // namespace freertos
+}  // namespace chre
diff --git a/platform/freertos/memory.cc b/platform/freertos/memory.cc
new file mode 100644
index 0000000..ada6702
--- /dev/null
+++ b/platform/freertos/memory.cc
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2019 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/platform/memory.h"
+#include "chre/platform/shared/pal_system_api.h"
+
+#include <cstdlib>
+
+namespace chre {
+
+void *memoryAlloc(size_t size) {
+  return malloc(size);
+}
+
+void *palSystemApiMemoryAlloc(size_t size) {
+  return malloc(size);
+}
+
+void memoryFree(void *pointer) {
+  free(pointer);
+}
+
+void palSystemApiMemoryFree(void *pointer) {
+  free(pointer);
+}
+
+}  // namespace chre
diff --git a/platform/freertos/memory_manager.cc b/platform/freertos/memory_manager.cc
new file mode 100644
index 0000000..b465ca9
--- /dev/null
+++ b/platform/freertos/memory_manager.cc
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2019 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/platform/memory_manager.h"
+#include "chre/util/memory.h"
+
+namespace chre {
+
+void *MemoryManager::doAlloc(Nanoapp * /*app*/, uint32_t bytes) {
+  return chre::memoryAlloc(bytes);
+}
+
+void MemoryManager::doFree(Nanoapp * /*app*/, void *ptr) {
+  chre::memoryFree(ptr);
+}
+
+}  // namespace chre
diff --git a/platform/freertos/nanoapp_loader.cc b/platform/freertos/nanoapp_loader.cc
new file mode 100644
index 0000000..38c80bd
--- /dev/null
+++ b/platform/freertos/nanoapp_loader.cc
@@ -0,0 +1,693 @@
+/*
+ * 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 <cmath>
+#include <cstring>
+
+#include "chre/platform/freertos/nanoapp_loader.h"
+
+#include "ash.h"
+#include "chre.h"
+#include "chre/platform/assert.h"
+#include "chre/platform/freertos/memory.h"
+#include "chre/util/dynamic_vector.h"
+#include "chre/util/macros.h"
+
+#ifndef CHRE_LOADER_ARCH
+#define CHRE_LOADER_ARCH EM_ARM
+#endif  // CHRE_LOADER_ARCH
+
+namespace chre {
+namespace {
+struct ExportedData {
+  void *data;
+  const char *dataName;
+};
+
+// The new operator is used by singleton.h which causes the delete operator to
+// be undefined in nanoapp binaries even though it's unused. Define this in case
+// a nanoapp actually tries to use the operator.
+void deleteOverride(void *ptr) {
+  FATAL_ERROR("Nanoapp tried to free %p through delete operator", ptr);
+}
+
+// atexit is used to register functions that must be called when a binary is
+// removed from the system.
+// TODO(b/151847750): Support atexit to ensure nanoapps that call it are
+// properly destroyed before they are removed. Or, potentially see if atexit
+// can be replaced with a .fini_array section.
+int atexitOverride(void (*function)(void)) {
+  LOGE("atexit invoked with %p", function);
+  return -1;
+}
+
+// TODO(karthikmb/stange): While this array was hand-coded for simple
+// "hello-world" prototyping, the list of exported symbols must be
+// generated to minimize runtime errors and build breaks.
+ExportedData gExportedData[] = {
+    {(void *)ashLoadCalibrationParams, "ashLoadCalibrationParams"},
+    {(void *)ashSaveCalibrationParams, "ashSaveCalibrationParams"},
+    {(void *)ashSetCalibration, "ashSetCalibration"},
+    {(void *)atexitOverride, "atexit"},
+    {(void *)chreGetVersion, "chreGetVersion"},
+    {(void *)chreGetApiVersion, "chreGetApiVersion"},
+    {(void *)chreGetEstimatedHostTimeOffset, "chreGetEstimatedHostTimeOffset"},
+    {(void *)chreGetPlatformId, "chreGetPlatformId"},
+    {(void *)chreGetSensorSamplingStatus, "chreGetSensorSamplingStatus"},
+    {(void *)chreGetTime, "chreGetTime"},
+    {(void *)chreHeapAlloc, "chreHeapAlloc"},
+    {(void *)chreHeapFree, "chreHeapFree"},
+    {(void *)chreLog, "chreLog"},
+    {(void *)chreSendMessageToHostEndpoint, "chreSendMessageToHostEndpoint"},
+    {(void *)chreSensorConfigure, "chreSensorConfigure"},
+    {(void *)chreSensorFindDefault, "chreSensorFindDefault"},
+    {(void *)memcpy, "memcpy"},
+    {(void *)memset, "memset"},
+    {(void *)deleteOverride, "_ZdlPv"},
+    {(void *)sqrtf, "sqrtf"},
+};
+
+}  // namespace
+
+void *NanoappLoader::create(void *elfInput) {
+  void *instance = nullptr;
+  NanoappLoader *loader = memoryAlloc<NanoappLoader>(elfInput);
+  if (loader != nullptr) {
+    if (loader->init()) {
+      instance = loader;
+    } else {
+      memoryFree(loader);
+    }
+  } else {
+    LOG_OOM();
+  }
+  return instance;
+}
+
+bool NanoappLoader::init() {
+  bool success = false;
+  if (mBinary.rawLocation != nullptr) {
+    if (!copyAndVerifyHeaders()) {
+      LOGE("Failed to verify headers");
+    } else if (!createMappings()) {
+      LOGE("Failed to create mappings");
+    } else if (!initDynamicStringTable()) {
+      LOGE("Failed to initialize dynamic string table");
+    } else if (!initDynamicSymbolTable()) {
+      LOGE("Failed to initialize dynamic symbol table");
+    } else if (!fixRelocations()) {
+      LOGE("Failed to fix relocations");
+    } else if (!resolveGot()) {
+      LOGE("Failed to resolve GOT");
+    } else {
+      callInitArray();
+      success = true;
+    }
+  }
+
+  if (!success) {
+    freeAllocatedData();
+  }
+
+  return success;
+}
+
+void NanoappLoader::deinit() {
+  // TODO(karthikmb/stange): Ensure functions registered through atexit are
+  // called.
+  callTerminatorArray();
+  freeAllocatedData();
+}
+
+void *NanoappLoader::findSymbolByName(const char *name) {
+  void *symbol = nullptr;
+  uint8_t *index = mSymbolTablePtr;
+  while (index < (mSymbolTablePtr + mSymbolTableSize)) {
+    ElfSym *currSym = reinterpret_cast<ElfSym *>(index);
+    const char *symbolName = &mStringTablePtr[currSym->st_name];
+
+    if (strncmp(symbolName, name, strlen(name)) == 0) {
+      symbol = ((void *)(mMapping.location + currSym->st_value));
+      break;
+    }
+
+    index += sizeof(ElfSym);
+  }
+  return symbol;
+}
+
+void NanoappLoader::mapBss(const ProgramHeader *hdr) {
+  // if the memory size of this segment exceeds the file size zero fill the
+  // difference.
+  LOGV("Program Hdr mem sz: %zu file size: %zu", hdr->p_memsz, hdr->p_filesz);
+  if (hdr->p_memsz > hdr->p_filesz) {
+    ElfAddr endOfFile = hdr->p_vaddr + hdr->p_filesz + mLoadBias;
+    ElfAddr endOfMem = hdr->p_vaddr + hdr->p_memsz + mLoadBias;
+    if (endOfMem > endOfFile) {
+      auto deltaMem = endOfMem - endOfFile;
+      LOGV("Zeroing out %zu from page %p", deltaMem, endOfFile);
+      memset((void *)endOfFile, 0, deltaMem);
+    }
+  }
+}
+
+void NanoappLoader::callInitArray() {
+  // TODO(b/151847750): ELF can have other sections like .init, .preinit, .fini
+  // etc. Be sure to look for those if they end up being something that should
+  // be supported for nanoapps.
+
+  for (size_t i = 0; i < mNumSectionHeaders; ++i) {
+    const char *name = getSectionHeaderName(mSectionHeadersPtr[i].sh_name);
+    if (strncmp(name, kInitArrayName, strlen(kInitArrayName)) == 0) {
+      LOGV("Invoking init function");
+      ElfAddr *init_array = reinterpret_cast<ElfAddr *>(
+          mLoadBias + mSectionHeadersPtr[i].sh_addr);
+      ElfAddr offset = 0;
+      while (offset < mSectionHeadersPtr[i].sh_size) {
+        uintptr_t init_function =
+            reinterpret_cast<uintptr_t>(*init_array + offset);
+        ((void (*)())init_function)();
+        offset += sizeof(void *);
+      }
+      break;
+    }
+  }
+}
+
+uintptr_t NanoappLoader::roundDownToAlign(uintptr_t virtualAddr) {
+  return virtualAddr & -kBinaryAlignment;
+}
+
+void NanoappLoader::freeAllocatedData() {
+  memoryFree(mMapping.rawLocation);
+  memoryFree(mProgramHeadersPtr);
+  memoryFree(mSectionHeadersPtr);
+  memoryFree(mSectionNamesPtr);
+  memoryFree(mDynamicStringTablePtr);
+  memoryFree(mDynamicSymbolTablePtr);
+  memoryFree(mSymbolTablePtr);
+  memoryFree(mStringTablePtr);
+}
+
+bool NanoappLoader::verifyElfHeader() {
+  bool success = false;
+  if ((mElfHeader.e_ident[EI_MAG0] == ELFMAG0) &&
+      (mElfHeader.e_ident[EI_MAG1] == ELFMAG1) &&
+      (mElfHeader.e_ident[EI_MAG2] == ELFMAG2) &&
+      (mElfHeader.e_ident[EI_MAG3] == ELFMAG3) &&
+      (mElfHeader.e_ehsize == sizeof(mElfHeader)) &&
+      (mElfHeader.e_phentsize == sizeof(ProgramHeader)) &&
+      (mElfHeader.e_shentsize == sizeof(SectionHeader)) &&
+      (mElfHeader.e_shstrndx < mElfHeader.e_shnum) &&
+      (mElfHeader.e_version == EV_CURRENT) &&
+      (mElfHeader.e_machine == CHRE_LOADER_ARCH) &&
+      (mElfHeader.e_type == ET_DYN)) {
+    success = true;
+  }
+  return success;
+}
+
+bool NanoappLoader::verifyProgramHeaders() {
+  // This is a minimal check for now -
+  // there should be at least one load segment.
+  bool success = false;
+  for (size_t i = 0; i < mNumProgramHeaders; ++i) {
+    if (mProgramHeadersPtr[i].p_type == PT_LOAD) {
+      success = true;
+      break;
+    }
+  }
+  return success;
+}
+
+const char *NanoappLoader::getSectionHeaderName(size_t sh_name) {
+  if (sh_name == 0) {
+    return "";
+  }
+
+  return &mSectionNamesPtr[sh_name];
+}
+
+NanoappLoader::SectionHeader *NanoappLoader::getSectionHeader(
+    const char *headerName) {
+  SectionHeader *rv = nullptr;
+  for (size_t i = 0; i < mNumSectionHeaders; ++i) {
+    const char *name = getSectionHeaderName(mSectionHeadersPtr[i].sh_name);
+    if (strncmp(name, headerName, strlen(headerName)) == 0) {
+      rv = &mSectionHeadersPtr[i];
+      break;
+    }
+  }
+  return rv;
+}
+
+bool NanoappLoader::verifySectionHeaders() {
+  for (size_t i = 0; i < mNumSectionHeaders; ++i) {
+    const char *name = getSectionHeaderName(mSectionHeadersPtr[i].sh_name);
+
+    if (strncmp(name, kSymTableName, strlen(kSymTableName)) == 0) {
+      memcpy(&mSymbolTableHeader, &mSectionHeadersPtr[i],
+             sizeof(SectionHeader));
+    } else if (strncmp(name, kStrTableName, strlen(kStrTableName)) == 0) {
+      memcpy(&mStringTableHeader, &mSectionHeadersPtr[i],
+             sizeof(SectionHeader));
+    }
+  }
+
+  return true;
+}
+
+bool NanoappLoader::copyAndVerifyHeaders() {
+  size_t offset = 0;
+  bool success = false;
+  uint8_t *pDataBytes = static_cast<uint8_t *>(mBinary.rawLocation);
+
+  // Verify the ELF Header
+  memcpy(&mElfHeader, pDataBytes, sizeof(mElfHeader));
+  success = verifyElfHeader();
+
+  LOGV("Verified ELF header %d", success);
+
+  // Verify Program Headers
+  if (success) {
+    offset = mElfHeader.e_phoff;
+    size_t programHeadersSizeBytes = sizeof(ProgramHeader) * mElfHeader.e_phnum;
+    mProgramHeadersPtr =
+        static_cast<ProgramHeader *>(memoryAlloc(programHeadersSizeBytes));
+    if (mProgramHeadersPtr == nullptr) {
+      success = false;
+      LOG_OOM();
+    } else {
+      memcpy(mProgramHeadersPtr, (pDataBytes + offset),
+             programHeadersSizeBytes);
+      mNumProgramHeaders = mElfHeader.e_phnum;
+      success = verifyProgramHeaders();
+    }
+  }
+
+  LOGV("Verified Program headers %d", success);
+
+  // Load Section Headers
+  if (success) {
+    offset = mElfHeader.e_shoff;
+    size_t sectionHeaderSizeBytes = sizeof(SectionHeader) * mElfHeader.e_shnum;
+    mSectionHeadersPtr =
+        static_cast<SectionHeader *>(memoryAlloc(sectionHeaderSizeBytes));
+    if (mSectionHeadersPtr == nullptr) {
+      success = false;
+      LOG_OOM();
+    } else {
+      memcpy(mSectionHeadersPtr, (pDataBytes + offset), sectionHeaderSizeBytes);
+      mNumSectionHeaders = mElfHeader.e_shnum;
+    }
+  }
+
+  LOGV("Loaded section headers %d", success);
+
+  // Load section header names
+  if (success) {
+    SectionHeader &stringSection = mSectionHeadersPtr[mElfHeader.e_shstrndx];
+    size_t sectionSize = stringSection.sh_size;
+    mSectionNamesPtr = static_cast<char *>(memoryAlloc(sectionSize));
+    if (mSectionNamesPtr == nullptr) {
+      LOG_OOM();
+      success = false;
+    } else {
+      memcpy(mSectionNamesPtr,
+             (void *)(mBinary.location + stringSection.sh_offset), sectionSize);
+    }
+  }
+
+  LOGV("Loaded section header names %d", success);
+
+  success = verifySectionHeaders();
+  LOGV("Verified Section headers %d", success);
+
+  // Load symbol table
+  if (success) {
+    mSymbolTableSize = mSymbolTableHeader.sh_size;
+    if (mSymbolTableSize == 0) {
+      LOGE("No symbols to resolve");
+      success = false;
+    } else {
+      mSymbolTablePtr = static_cast<uint8_t *>(memoryAlloc(mSymbolTableSize));
+      if (mSymbolTablePtr == nullptr) {
+        LOG_OOM();
+        success = false;
+      } else {
+        memcpy(mSymbolTablePtr,
+               (void *)(mBinary.location + mSymbolTableHeader.sh_offset),
+               mSymbolTableSize);
+      }
+    }
+  }
+
+  LOGV("Loaded symbol table %d", success);
+
+  // Load string table
+  if (success) {
+    size_t stringTableSize = mStringTableHeader.sh_size;
+    if (mSymbolTableSize == 0) {
+      LOGE("No string table corresponding to symbols");
+      success = false;
+    } else {
+      mStringTablePtr = static_cast<char *>(memoryAlloc(stringTableSize));
+      if (mStringTablePtr == nullptr) {
+        LOG_OOM();
+        success = false;
+      } else {
+        memcpy(mStringTablePtr,
+               (void *)(mBinary.location + mStringTableHeader.sh_offset),
+               stringTableSize);
+      }
+    }
+  }
+
+  LOGV("Loaded string table %d", success);
+
+  return success;
+}
+
+bool NanoappLoader::createMappings() {
+  // ELF needs pt_load segments to be in contiguous ascending order of
+  // virtual addresses. So the first and last segs can be used to
+  // calculate the entire address span of the image.
+  const ProgramHeader *first = &mProgramHeadersPtr[0];
+  const ProgramHeader *last = &mProgramHeadersPtr[mElfHeader.e_phnum - 1];
+
+  // Find first load segment
+  while (first->p_type != PT_LOAD && first <= last) {
+    ++first;
+  }
+
+  bool success = false;
+  if (first->p_type != PT_LOAD) {
+    LOGE("Unable to find any load segments in the binary");
+  } else {
+    // Verify that the first load segment has a program header
+    // first byte of a valid load segment can't be greater than the
+    // program header offset
+    bool valid =
+        (first->p_offset < mElfHeader.e_phoff) &&
+        (first->p_filesz >
+         (mElfHeader.e_phoff + (mNumProgramHeaders * sizeof(ProgramHeader))));
+    if (!valid) {
+      LOGE("Load segment program header validation failed");
+    } else {
+      // Get the last load segment
+      while (last > first && last->p_type != PT_LOAD) --last;
+
+      size_t memorySpan = last->p_vaddr + last->p_memsz - first->p_vaddr;
+      LOGV("Nanoapp image Memory Span: %u", memorySpan);
+
+      mMapping.rawLocation =
+          memoryAllocDramAligned(kBinaryAlignment, memorySpan);
+      if (mMapping.rawLocation == nullptr) {
+        LOG_OOM();
+      } else {
+        LOGV("Starting location of mappings %p", data->mMapping.rawLocation);
+
+        // Calculate the load bias using the first load segment.
+        uintptr_t adjustedFirstLoadSegAddr = roundDownToAlign(first->p_vaddr);
+        mLoadBias = mMapping.location - adjustedFirstLoadSegAddr;
+        LOGV("Load bias is %" PRIu32, mLoadBias);
+
+        success = true;
+      }
+    }
+  }
+
+  if (success) {
+    // Map the remaining segments
+    for (const ProgramHeader *ph = first; ph <= last; ++ph) {
+      if (ph->p_type == PT_LOAD) {
+        ElfAddr segStart = ph->p_vaddr + mLoadBias;
+        ElfAddr startPage = roundDownToAlign(segStart);
+        ElfAddr phOffsetPage = roundDownToAlign(ph->p_offset);
+        ElfAddr binaryStartPage = mBinary.location + phOffsetPage;
+        size_t segmentLen = ph->p_filesz;
+
+        LOGV("Mapping start page %p from %p with length %zu", startPage,
+             (void *)binaryStartPage, segmentLen);
+        memcpy((void *)startPage, (void *)binaryStartPage, segmentLen);
+        mapBss(ph);
+      } else {
+        LOGE("Non-load segment found between load segments");
+        success = false;
+        break;
+      }
+    }
+  }
+
+  return success;
+}
+
+bool NanoappLoader::initDynamicStringTable() {
+  bool success = false;
+
+  SectionHeader *dynamicStringTablePtr = getSectionHeader(".dynstr");
+  CHRE_ASSERT(dynamicStringTablePtr != nullptr);
+  if (dynamicStringTablePtr != nullptr) {
+    size_t stringTableSize = dynamicStringTablePtr->sh_size;
+    mDynamicStringTablePtr = static_cast<char *>(memoryAlloc(stringTableSize));
+    if (mDynamicStringTablePtr == nullptr) {
+      LOG_OOM();
+    } else {
+      memcpy(mDynamicStringTablePtr,
+             (void *)(mBinary.location + dynamicStringTablePtr->sh_offset),
+             stringTableSize);
+      success = true;
+    }
+  }
+
+  return success;
+}
+
+bool NanoappLoader::initDynamicSymbolTable() {
+  bool success = false;
+  SectionHeader *dynamicSymbolTablePtr = getSectionHeader(".dynsym");
+  CHRE_ASSERT(dynamicSymbolTablePtr != nullptr);
+  if (dynamicSymbolTablePtr != nullptr) {
+    size_t sectionSize = dynamicSymbolTablePtr->sh_size;
+    mDynamicSymbolTablePtr = static_cast<uint8_t *>(memoryAlloc(sectionSize));
+    if (mDynamicSymbolTablePtr == nullptr) {
+      LOG_OOM();
+    } else {
+      memcpy(mDynamicSymbolTablePtr,
+             (void *)(mBinary.location + dynamicSymbolTablePtr->sh_offset),
+             sectionSize);
+      mDynamicSymbolTableSize = sectionSize;
+      success = true;
+    }
+  }
+
+  return success;
+}
+
+const char *NanoappLoader::getDataName(size_t posInSymbolTable) {
+  size_t sectionSize = mDynamicSymbolTableSize;
+  size_t numElements = sectionSize / sizeof(ElfSym);
+  CHRE_ASSERT(posInSymbolTable < numElements);
+  char *dataName = nullptr;
+  if (posInSymbolTable < numElements) {
+    ElfSym *sym = reinterpret_cast<ElfSym *>(
+        &mDynamicSymbolTablePtr[posInSymbolTable * sizeof(ElfSym)]);
+    dataName = &mDynamicStringTablePtr[sym->st_name];
+  }
+  return dataName;
+}
+
+void *NanoappLoader::resolveData(size_t posInSymbolTable) {
+  const char *dataName = getDataName(posInSymbolTable);
+
+  if (dataName != nullptr) {
+    LOGV("Resolving %s", dataName);
+
+    for (size_t i = 0; i < ARRAY_SIZE(gExportedData); i++) {
+      if (strncmp(dataName, gExportedData[i].dataName,
+                  strlen(gExportedData[i].dataName)) == 0) {
+        return gExportedData[i].data;
+      }
+    }
+
+    LOGE("%s not found!", dataName);
+  }
+
+  return nullptr;
+}
+
+NanoappLoader::DynamicHeader *NanoappLoader::getDynamicHeader() {
+  DynamicHeader *dyn = nullptr;
+  for (size_t i = 0; i < mNumProgramHeaders; ++i) {
+    if (mProgramHeadersPtr[i].p_type == PT_DYNAMIC) {
+      dyn = (DynamicHeader *)(mProgramHeadersPtr[i].p_vaddr + mLoadBias);
+      break;
+    }
+  }
+  return dyn;
+}
+
+NanoappLoader::ProgramHeader *NanoappLoader::getFirstRoSegHeader() {
+  // return the first read only segment found
+  ProgramHeader *ro = nullptr;
+  for (size_t i = 0; i < mNumProgramHeaders; ++i) {
+    if (!(mProgramHeadersPtr[i].p_flags & PF_W)) {
+      ro = &mProgramHeadersPtr[i];
+      break;
+    }
+  }
+  return ro;
+}
+
+NanoappLoader::ElfWord NanoappLoader::getDynEntry(DynamicHeader *dyn,
+                                                  int field) {
+  ElfWord rv = 0;
+
+  while (dyn->d_tag != DT_NULL) {
+    if (dyn->d_tag == field) {
+      rv = dyn->d_un.d_val;
+      break;
+    }
+    ++dyn;
+  }
+
+  return rv;
+}
+
+bool NanoappLoader::fixRelocations() {
+  ElfAddr *addr;
+  DynamicHeader *dyn = getDynamicHeader();
+  ProgramHeader *roSeg = getFirstRoSegHeader();
+
+  bool success = false;
+  if ((dyn == nullptr) || (roSeg == nullptr)) {
+    LOGE("Mandatory headers missing from shared object, aborting load");
+  } else if (getDynEntry(dyn, DT_RELA) != 0) {
+    LOGE("Elf binaries with a DT_RELA dynamic entry are unsupported");
+  } else {
+    ElfRel *reloc = (ElfRel *)(getDynEntry(dyn, DT_REL) + mBinary.location);
+    size_t relocSize = getDynEntry(dyn, DT_RELSZ);
+    size_t nRelocs = relocSize / sizeof(ElfRel);
+    LOGV("Relocation %zu entries in DT_REL table", nRelocs);
+
+    size_t i;
+    for (i = 0; i < nRelocs; ++i) {
+      ElfRel *curr = &reloc[i];
+      int relocType = ELFW_R_TYPE(curr->r_info);
+      switch (relocType) {
+        case R_ARM_RELATIVE:
+          LOGV("Resolving ARM_RELATIVE at offset %" PRIu32, curr->r_offset);
+          addr =
+              reinterpret_cast<ElfAddr *>(curr->r_offset + mMapping.location);
+          // TODO: When we move to DRAM allocations, we need to check if the
+          // above address is in a Read-Only section of memory, and give it
+          // temporary write permission if that is the case.
+          *addr += mMapping.location;
+          break;
+
+        case R_ARM_GLOB_DAT: {
+          LOGV("Resolving R_ARM_GLOB_DAT at offset %" PRIu32, curr->r_offset);
+          addr =
+              reinterpret_cast<ElfAddr *>(curr->r_offset + mMapping.location);
+          size_t posInSymbolTable = ELFW_R_SYM(curr->r_info);
+          void *resolved = resolveData(posInSymbolTable);
+          if (resolved == nullptr) {
+            LOGV("Failed to resolve global symbol(%d) at offset 0x%x", i,
+                 curr->r_offset);
+            return false;
+          }
+          // TODO: When we move to DRAM allocations, we need to check if the
+          // above address is in a Read-Only section of memory, and give it
+          // temporary write permission if that is the case.
+          *addr = reinterpret_cast<ElfAddr>(resolved);
+          break;
+        }
+
+        case R_ARM_COPY:
+          LOGE("R_ARM_COPY is an invalid relocation for shared libraries");
+          break;
+        default:
+          LOGE("Invalid relocation type %u", relocType);
+          break;
+      }
+    }
+
+    if (i != nRelocs) {
+      LOGE("Unable to resolve all symbols in the binary");
+    } else {
+      mDynamicHeaderPtr = dyn;
+      success = true;
+    }
+  }
+
+  return success;
+}
+
+bool NanoappLoader::resolveGot() {
+  ElfAddr *addr;
+  ElfRel *reloc =
+      (ElfRel *)(getDynEntry(mDynamicHeaderPtr, DT_JMPREL) + mMapping.location);
+  size_t relocSize = getDynEntry(mDynamicHeaderPtr, DT_PLTRELSZ);
+  size_t nRelocs = relocSize / sizeof(ElfRel);
+  LOGV("Resolving GOT with %zu relocations", nRelocs);
+
+  for (size_t i = 0; i < nRelocs; ++i) {
+    ElfRel *curr = &reloc[i];
+    int relocType = ELFW_R_TYPE(curr->r_info);
+
+    switch (relocType) {
+      case R_ARM_JUMP_SLOT: {
+        LOGV("Resolving ARM_JUMP_SLOT at offset %" PRIu32, curr->r_offset);
+        addr = reinterpret_cast<ElfAddr *>(curr->r_offset + mMapping.location);
+        size_t posInSymbolTable = ELFW_R_SYM(curr->r_info);
+        void *resolved = resolveData(posInSymbolTable);
+        if (resolved == nullptr) {
+          LOGV("Failed to resolve symbol(%d) at offset 0x%x", i,
+               curr->r_offset);
+          return false;
+        }
+        *addr = reinterpret_cast<ElfAddr>(resolved);
+        break;
+      }
+
+      default:
+        LOGE("Unsupported relocation type: %u for symbol %s", relocType,
+             getDataName(ELFW_R_SYM(curr->r_info)));
+        return false;
+    }
+  }
+  return true;
+}
+
+void NanoappLoader::callTerminatorArray() {
+  for (size_t i = 0; i < mNumSectionHeaders; ++i) {
+    const char *name = getSectionHeaderName(mSectionHeadersPtr[i].sh_name);
+    if (strncmp(name, kFiniArrayName, strlen(kFiniArrayName)) == 0) {
+      ElfAddr *fini_array = reinterpret_cast<ElfAddr *>(
+          mLoadBias + mSectionHeadersPtr[i].sh_addr);
+      ElfAddr offset = 0;
+      while (offset < mSectionHeadersPtr[i].sh_size) {
+        uintptr_t fini_function =
+            reinterpret_cast<uintptr_t>(*fini_array + offset);
+        ((void (*)())fini_function)();
+        offset += sizeof(void *);
+      }
+      break;
+    }
+  }
+}
+
+}  // namespace chre
diff --git a/platform/freertos/platform_debug_dump_manager.cc b/platform/freertos/platform_debug_dump_manager.cc
new file mode 100644
index 0000000..056817e
--- /dev/null
+++ b/platform/freertos/platform_debug_dump_manager.cc
@@ -0,0 +1,58 @@
+/*
+ * 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/platform/platform_debug_dump_manager.h"
+
+#include "chre/core/event_loop_manager.h"
+#include "chre/platform/log.h"
+#include "chre/target_platform/host_link_base.h"
+#include "chre/target_platform/platform_debug_dump_manager_base.h"
+
+#include <cstring>
+
+namespace chre {
+
+void PlatformDebugDumpManager::sendDebugDump(const char *debugStr,
+                                             bool complete) {
+  // DDM is guaranteed to call complete=true at the end of a debug dump session.
+  // However, sendDebugDumpResult may not get called with complete=true.
+  // Therefore, mDataCount has to be reset here instead of in
+  // sendDebugDumpResult(), to properly start the next debug dump session.
+  if (mComplete) {
+    mDataCount = 0;
+  }
+  mComplete = complete;
+
+  sendDebugDumpResult(debugStr, strlen(debugStr), complete);
+}
+
+void PlatformDebugDumpManagerBase::onDebugDumpRequested(uint16_t hostClientId) {
+  mHostClientId = hostClientId;
+
+  EventLoopManagerSingleton::get()->getDebugDumpManager().trigger();
+}
+
+void PlatformDebugDumpManagerBase::sendDebugDumpResult(const char *debugStr,
+                                                       size_t debugStrSize,
+                                                       bool complete) {
+  if (debugStrSize > 0) {
+    mDataCount++;
+  }
+  sendDebugDumpResultToHost(mHostClientId, debugStr, debugStrSize, complete,
+                            mDataCount);
+}
+
+}  // namespace chre
diff --git a/platform/freertos/platform_nanoapp.cc b/platform/freertos/platform_nanoapp.cc
new file mode 100644
index 0000000..d8ac3ec
--- /dev/null
+++ b/platform/freertos/platform_nanoapp.cc
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2019 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/platform/platform_nanoapp.h"
+#include "chre/platform/freertos/dlfcn.h"
+#include "chre/platform/freertos/dram_util.h"
+#include "chre/platform/freertos/memory.h"
+#include "chre/platform/freertos/nanoapp_loader.h"
+#include "chre/platform/shared/nanoapp_dso_util.h"
+
+#include <cinttypes>
+
+#include "chre/platform/assert.h"
+#include "chre/platform/log.h"
+#include "chre_api/chre/version.h"
+
+namespace chre {
+
+PlatformNanoapp::~PlatformNanoapp() {
+  if (mAppBinary != nullptr) {
+    memoryFreeDram(mAppBinary);
+  }
+}
+
+bool PlatformNanoapp::start() {
+  DramGuard guard;
+
+  bool success = false;
+  if (!openNanoapp()) {
+    LOGE("Failed to open nanoapp");
+  } else if (mAppInfo == nullptr) {
+    LOGE("Null app info!");
+  } else {
+    success = mAppInfo->entryPoints.start();
+  }
+  return success;
+}
+
+void PlatformNanoapp::handleEvent(uint32_t senderInstanceId, uint16_t eventType,
+                                  const void *eventData) {
+  DramGuard guard;
+
+  mAppInfo->entryPoints.handleEvent(senderInstanceId, eventType, eventData);
+}
+
+void PlatformNanoapp::end() {
+  DramGuard guard;
+
+  mAppInfo->entryPoints.end();
+}
+
+uint64_t PlatformNanoapp::getAppId() const {
+  return (mAppInfo != nullptr) ? mAppInfo->appId : mExpectedAppId;
+}
+
+uint32_t PlatformNanoapp::getAppVersion() const {
+  return (mAppInfo != nullptr) ? mAppInfo->appVersion : mExpectedAppVersion;
+}
+
+uint32_t PlatformNanoapp::getTargetApiVersion() const {
+  return (mAppInfo != nullptr) ? mAppInfo->targetApiVersion : 0;
+}
+
+bool PlatformNanoapp::isSystemNanoapp() const {
+  return (mAppInfo != nullptr && mAppInfo->isSystemNanoapp);
+}
+
+void PlatformNanoapp::logStateToBuffer(
+    DebugDumpWrapper & /* debugDump */) const {
+  // TODO: stubbed out, Implement this.
+}
+
+bool PlatformNanoappBase::isLoaded() const {
+  return (mIsStatic ||
+          ((mAppBinary != nullptr) && (mAppBinaryLen != 0) &&
+           (mBytesLoaded == mAppBinaryLen)) ||
+          (mDsoHandle != nullptr));
+}
+
+void PlatformNanoappBase::loadStatic(const struct chreNslNanoappInfo *appInfo) {
+  CHRE_ASSERT(!isLoaded());
+  mIsStatic = true;
+  mAppInfo = appInfo;
+}
+
+bool PlatformNanoappBase::reserveBuffer(uint64_t appId, uint32_t appVersion,
+                                        size_t appBinaryLen) {
+  CHRE_ASSERT(!isLoaded());
+
+  bool success = false;
+  mAppBinary = memoryAllocDram(appBinaryLen);
+
+  if (mAppBinary == nullptr) {
+    LOG_OOM();
+  } else {
+    mExpectedAppId = appId;
+    mExpectedAppVersion = appVersion;
+    mAppBinaryLen = appBinaryLen;
+    success = true;
+  }
+
+  return success;
+}
+
+bool PlatformNanoappBase::copyNanoappFragment(const void *buffer,
+                                              size_t bufferLen) {
+  CHRE_ASSERT(!isLoaded());
+
+  bool success = true;
+
+  if ((mBytesLoaded + bufferLen) > mAppBinaryLen) {
+    LOGE("Overflow: cannot load %zu bytes to %zu/%zu nanoapp binary buffer",
+         bufferLen, mBytesLoaded, mAppBinaryLen);
+    success = false;
+  } else {
+    uint8_t *binaryBuffer = static_cast<uint8_t *>(mAppBinary) + mBytesLoaded;
+    memcpy(binaryBuffer, buffer, bufferLen);
+    mBytesLoaded += bufferLen;
+  }
+
+  return success;
+}
+
+bool PlatformNanoappBase::verifyNanoappInfo() {
+  bool success = false;
+
+  if (mDsoHandle == nullptr) {
+    LOGE("No nanoapp info to verify");
+  } else {
+    mAppInfo = static_cast<const struct chreNslNanoappInfo *>(
+        dlsym(mDsoHandle, CHRE_NSL_DSO_NANOAPP_INFO_SYMBOL_NAME));
+    if (mAppInfo == nullptr) {
+      LOGE("Failed to find app info symbol");
+    } else {
+      success = validateAppInfo(mExpectedAppId, mExpectedAppVersion, mAppInfo);
+      if (!success) {
+        mAppInfo = nullptr;
+      } else {
+        LOGI("Successfully loaded nanoapp: %s (0x%016" PRIx64
+             ") version 0x%" PRIx32 " uimg %d system %d",
+             mAppInfo->name, mAppInfo->appId, mAppInfo->appVersion,
+             mAppInfo->isTcmNanoapp, mAppInfo->isSystemNanoapp);
+      }
+    }
+  }
+  return success;
+}
+
+bool PlatformNanoappBase::openNanoapp() {
+  bool success = false;
+  if (mIsStatic) {
+    success = true;
+  } else if (mAppBinary != nullptr) {
+    if (mDsoHandle == nullptr) {
+      mDsoHandle = dlopenbuf(mAppBinary);
+      if (mDsoHandle != nullptr) {
+        mAppInfo = static_cast<struct chreNslNanoappInfo *>(
+            dlsym(mDsoHandle, CHRE_NSL_DSO_NANOAPP_INFO_SYMBOL_NAME));
+
+        if (mAppInfo != nullptr) {
+          success =
+              validateAppInfo(mExpectedAppId, mExpectedAppVersion, mAppInfo);
+          if (!success) {
+            mAppInfo = nullptr;
+          } else {
+            LOGI("Successfully loaded nanoapp: %s (0x%016" PRIx64
+                 ") version 0x%" PRIx32 " uimg %d system %d",
+                 mAppInfo->name, mAppInfo->appId, mAppInfo->appVersion,
+                 mAppInfo->isTcmNanoapp, mAppInfo->isSystemNanoapp);
+          }
+        }
+      } else {
+        LOGE("Null DSO Handle!");
+      }
+    } else {
+      LOGE("Trying to reopen an existing buffer");
+    }
+  }
+
+  if (mAppBinary != nullptr) {
+    memoryFreeDram(mAppBinary);
+    mAppBinary = nullptr;
+  }
+
+  return success;
+}
+
+}  // namespace chre
diff --git a/platform/platform.mk b/platform/platform.mk
index 185886e..0be537e 100644
--- a/platform/platform.mk
+++ b/platform/platform.mk
@@ -26,6 +26,9 @@
 SLPI_CFLAGS += -I$(SLPI_PREFIX)/platform/inc/a1std
 SLPI_CFLAGS += -I$(SLPI_PREFIX)/platform/inc/stddef
 SLPI_CFLAGS += -I$(SLPI_PREFIX)/platform/rtld/inc
+SLPI_CFLAGS += -I$(SLPI_PREFIX)/ssc/goog/api
+SLPI_CFLAGS += -I$(SLPI_PREFIX)/ssc/inc
+SLPI_CFLAGS += -I$(SLPI_PREFIX)/ssc/inc/internal
 
 SLPI_CFLAGS += -Iplatform/shared/include
 SLPI_CFLAGS += -Iplatform/slpi/include
@@ -33,6 +36,10 @@
 # We use FlatBuffers in the SLPI platform layer
 SLPI_CFLAGS += $(FLATBUFFERS_CFLAGS)
 
+# Needed to define __SIZEOF_ATTR_THREAD in sns_osa_thread.h, included in
+# sns_memmgr.h.
+SLPI_CFLAGS += -DSSC_TARGET_HEXAGON
+
 ifneq ($(CHRE_ENABLE_ACCEL_CAL), false)
 SLPI_CFLAGS += -DCHRE_ENABLE_ACCEL_CAL
 endif
@@ -49,19 +56,12 @@
 SLPI_SEE_CFLAGS += -I$(SLPI_PREFIX)/qmimsgs/common/api
 SLPI_SEE_CFLAGS += -I$(SLPI_PREFIX)/ssc_api/pb
 SLPI_SEE_CFLAGS += -I$(SLPI_PREFIX)/ssc/framework/cm/inc
-SLPI_SEE_CFLAGS += -I$(SLPI_PREFIX)/ssc/goog/api
-SLPI_SEE_CFLAGS += -I$(SLPI_PREFIX)/ssc/inc
-SLPI_SEE_CFLAGS += -I$(SLPI_PREFIX)/ssc/inc/internal
 SLPI_SEE_CFLAGS += -I$(SLPI_PREFIX)/ssc/inc/utils/nanopb
 
 SLPI_SEE_CFLAGS += -Iplatform/slpi/see/include
 
 SLPI_SEE_CFLAGS += -DCHRE_SLPI_SEE
 
-# Needed to define __SIZEOF_ATTR_THREAD in sns_osa_thread.h, included in
-# sns_memmgr.h.
-SLPI_SEE_CFLAGS += -DSSC_TARGET_HEXAGON
-
 # Defined in slpi_proc/ssc/build/ssc.scons
 SLPI_SEE_CFLAGS += -DPB_FIELD_16BIT
 
@@ -146,6 +146,76 @@
 SLPI_SEE_QSK_SRCS += $(SLPI_PREFIX)/chre/chre/src/system/chre/platform/slpi/sns_qmi_client_alt.c
 SLPI_SEE_QMI_SRCS += $(SLPI_PREFIX)/chre/chre/src/system/chre/platform/slpi/sns_qmi_client.c
 
+# FreeRTOS-specific Source Files ###############################################
+
+FREERTOS_SRCS += platform/freertos/context.cc
+FREERTOS_SRCS += platform/freertos/dlfcn.cc
+FREERTOS_SRCS += platform/freertos/init.cc
+FREERTOS_SRCS += platform/freertos/memory_manager.cc
+FREERTOS_SRCS += platform/freertos/nanoapp_loader.cc
+FREERTOS_SRCS += platform/freertos/platform_debug_dump_manager.cc
+FREERTOS_SRCS += platform/freertos/platform_nanoapp.cc
+
+# Optional FreeRTOS-specific Source Files ######################################
+
+# memory.cc is only needed if the given platform doesn't have its own memory
+# allocation setup.
+FREERTOS_OPTIONAL_SRCS += platform/freertos/memory.cc
+
+# FreeRTOS-specific Compiler Flags #############################################
+FREERTOS_CFLAGS += -I$(AOC_TOP_DIR)/external/FreeRTOS/FreeRTOS/Source/include
+FREERTOS_CFLAGS += -Iplatform/freertos/include
+FREERTOS_CFLAGS += -Iplatform/shared/include
+
+# AoC-specific Source Files ####################################################
+
+AOC_SRCS += platform/aoc/chre_api_re.cc
+AOC_SRCS += platform/aoc/fatal_error.cc
+AOC_SRCS += platform/aoc/host_link.cc
+AOC_SRCS += platform/aoc/log.cc
+AOC_SRCS += platform/aoc/memory.cc
+AOC_SRCS += platform/aoc/power_control_manager.cc
+AOC_SRCS += platform/aoc/platform_audio.cc
+AOC_SRCS += platform/aoc/system_time.cc
+AOC_SRCS += platform/aoc/system_timer.cc
+AOC_SRCS += platform/shared/chre_api_audio.cc
+AOC_SRCS += platform/shared/chre_api_core.cc
+AOC_SRCS += platform/shared/chre_api_gnss.cc
+AOC_SRCS += platform/shared/chre_api_re.cc
+AOC_SRCS += platform/shared/chre_api_sensor.cc
+AOC_SRCS += platform/shared/chre_api_version.cc
+AOC_SRCS += platform/shared/chre_api_wifi.cc
+AOC_SRCS += platform/shared/chre_api_wwan.cc
+AOC_SRCS += platform/shared/host_protocol_chre.cc
+AOC_SRCS += platform/shared/host_protocol_common.cc
+AOC_SRCS += platform/shared/memory_manager.cc
+AOC_SRCS += platform/shared/nanoapp_load_manager.cc
+AOC_SRCS += platform/shared/pal_system_api.cc
+AOC_SRCS += platform/shared/pal_sensor_stub.cc
+AOC_SRCS += platform/shared/system_time.cc
+AOC_SRCS += platform/shared/nanoapp/nanoapp_dso_util.cc
+AOC_SRCS += platform/usf/platform_sensor.cc
+AOC_SRCS += platform/usf/platform_sensor_manager.cc
+AOC_SRCS += platform/usf/platform_sensor_type_helpers.cc
+AOC_SRCS += platform/usf/usf_helper.cc
+
+# AoC-specific Compiler Flags ##################################################
+AOC_CFLAGS += -Iplatform/aoc/include
+AOC_CFLAGS += -Iplatform/usf/include
+AOC_CFLAGS += -I$(AOC_TOP_DIR)/AOC
+AOC_CFLAGS += -I$(AOC_TOP_DIR)/AOC/efw/include
+AOC_CFLAGS += -I$(AOC_TOP_DIR)/AOC/libs/common/basic/include
+AOC_CFLAGS += -I$(AOC_TOP_DIR)/AOC/libs/common/libc/include
+AOC_CFLAGS += -I$(AOC_TOP_DIR)/AOC/os/common/include
+AOC_CFLAGS += -I$(AOC_TOP_DIR)/AOC/platform/common/include
+AOC_CFLAGS += -I$(AOC_TOP_DIR)/usf/core/include
+AOC_CFLAGS += -I$(AOC_TOP_DIR)/usf/core/fbs
+AOC_CFLAGS += -I$(AOC_TOP_DIR)/usf/pal/include
+AOC_CFLAGS += -I$(AOC_TOP_DIR)/usf/pal/efw/include
+
+# We use FlatBuffers in the AOC platform layer
+AOC_CFLAGS += $(FLATBUFFERS_CFLAGS)
+
 # Simulator-specific Compiler Flags ############################################
 
 SIM_CFLAGS += -Iplatform/shared/include
diff --git a/platform/shared/include/chre/platform/shared/generated/host_messages_generated.h b/platform/shared/include/chre/platform/shared/generated/host_messages_generated.h
index 15a9284..07a5c1f 100644
--- a/platform/shared/include/chre/platform/shared/generated/host_messages_generated.h
+++ b/platform/shared/include/chre/platform/shared/generated/host_messages_generated.h
@@ -10,66 +10,46 @@
 namespace fbs {
 
 struct NanoappMessage;
-struct NanoappMessageBuilder;
 
 struct HubInfoRequest;
-struct HubInfoRequestBuilder;
 
 struct HubInfoResponse;
-struct HubInfoResponseBuilder;
 
 struct NanoappListRequest;
-struct NanoappListRequestBuilder;
 
 struct NanoappListEntry;
-struct NanoappListEntryBuilder;
 
 struct NanoappListResponse;
-struct NanoappListResponseBuilder;
 
 struct LoadNanoappRequest;
-struct LoadNanoappRequestBuilder;
 
 struct LoadNanoappResponse;
-struct LoadNanoappResponseBuilder;
 
 struct UnloadNanoappRequest;
-struct UnloadNanoappRequestBuilder;
 
 struct UnloadNanoappResponse;
-struct UnloadNanoappResponseBuilder;
 
 struct LogMessage;
-struct LogMessageBuilder;
 
 struct TimeSyncMessage;
-struct TimeSyncMessageBuilder;
 
 struct DebugDumpRequest;
-struct DebugDumpRequestBuilder;
 
 struct DebugDumpData;
-struct DebugDumpDataBuilder;
 
 struct DebugDumpResponse;
-struct DebugDumpResponseBuilder;
 
 struct TimeSyncRequest;
-struct TimeSyncRequestBuilder;
 
 struct LowPowerMicAccessRequest;
-struct LowPowerMicAccessRequestBuilder;
 
 struct LowPowerMicAccessRelease;
-struct LowPowerMicAccessReleaseBuilder;
 
 struct SettingChangeMessage;
-struct SettingChangeMessageBuilder;
 
 struct HostAddress;
 
 struct MessageContainer;
-struct MessageContainerBuilder;
 
 /// An enum describing the setting type.
 enum class Setting : int8_t {
@@ -78,15 +58,8 @@
   MAX = LOCATION
 };
 
-inline const Setting (&EnumValuesSetting())[1] {
-  static const Setting values[] = {
-    Setting::LOCATION
-  };
-  return values;
-}
-
-inline const char * const *EnumNamesSetting() {
-  static const char * const names[2] = {
+inline const char **EnumNamesSetting() {
+  static const char *names[] = {
     "LOCATION",
     nullptr
   };
@@ -94,8 +67,7 @@
 }
 
 inline const char *EnumNameSetting(Setting e) {
-  if (flatbuffers::IsOutRange(e, Setting::LOCATION, Setting::LOCATION)) return "";
-  const size_t index = static_cast<size_t>(e);
+  const size_t index = static_cast<int>(e);
   return EnumNamesSetting()[index];
 }
 
@@ -107,16 +79,8 @@
   MAX = ENABLED
 };
 
-inline const SettingState (&EnumValuesSettingState())[2] {
-  static const SettingState values[] = {
-    SettingState::DISABLED,
-    SettingState::ENABLED
-  };
-  return values;
-}
-
-inline const char * const *EnumNamesSettingState() {
-  static const char * const names[3] = {
+inline const char **EnumNamesSettingState() {
+  static const char *names[] = {
     "DISABLED",
     "ENABLED",
     nullptr
@@ -125,8 +89,7 @@
 }
 
 inline const char *EnumNameSettingState(SettingState e) {
-  if (flatbuffers::IsOutRange(e, SettingState::DISABLED, SettingState::ENABLED)) return "";
-  const size_t index = static_cast<size_t>(e);
+  const size_t index = static_cast<int>(e);
   return EnumNamesSettingState()[index];
 }
 
@@ -156,33 +119,8 @@
   MAX = SettingChangeMessage
 };
 
-inline const ChreMessage (&EnumValuesChreMessage())[19] {
-  static const ChreMessage values[] = {
-    ChreMessage::NONE,
-    ChreMessage::NanoappMessage,
-    ChreMessage::HubInfoRequest,
-    ChreMessage::HubInfoResponse,
-    ChreMessage::NanoappListRequest,
-    ChreMessage::NanoappListResponse,
-    ChreMessage::LoadNanoappRequest,
-    ChreMessage::LoadNanoappResponse,
-    ChreMessage::UnloadNanoappRequest,
-    ChreMessage::UnloadNanoappResponse,
-    ChreMessage::LogMessage,
-    ChreMessage::TimeSyncMessage,
-    ChreMessage::DebugDumpRequest,
-    ChreMessage::DebugDumpData,
-    ChreMessage::DebugDumpResponse,
-    ChreMessage::TimeSyncRequest,
-    ChreMessage::LowPowerMicAccessRequest,
-    ChreMessage::LowPowerMicAccessRelease,
-    ChreMessage::SettingChangeMessage
-  };
-  return values;
-}
-
-inline const char * const *EnumNamesChreMessage() {
-  static const char * const names[20] = {
+inline const char **EnumNamesChreMessage() {
+  static const char *names[] = {
     "NONE",
     "NanoappMessage",
     "HubInfoRequest",
@@ -208,8 +146,7 @@
 }
 
 inline const char *EnumNameChreMessage(ChreMessage e) {
-  if (flatbuffers::IsOutRange(e, ChreMessage::NONE, ChreMessage::SettingChangeMessage)) return "";
-  const size_t index = static_cast<size_t>(e);
+  const size_t index = static_cast<int>(e);
   return EnumNamesChreMessage()[index];
 }
 
@@ -217,88 +154,91 @@
   static const ChreMessage enum_value = ChreMessage::NONE;
 };
 
-template<> struct ChreMessageTraits<chre::fbs::NanoappMessage> {
+template<> struct ChreMessageTraits<NanoappMessage> {
   static const ChreMessage enum_value = ChreMessage::NanoappMessage;
 };
 
-template<> struct ChreMessageTraits<chre::fbs::HubInfoRequest> {
+template<> struct ChreMessageTraits<HubInfoRequest> {
   static const ChreMessage enum_value = ChreMessage::HubInfoRequest;
 };
 
-template<> struct ChreMessageTraits<chre::fbs::HubInfoResponse> {
+template<> struct ChreMessageTraits<HubInfoResponse> {
   static const ChreMessage enum_value = ChreMessage::HubInfoResponse;
 };
 
-template<> struct ChreMessageTraits<chre::fbs::NanoappListRequest> {
+template<> struct ChreMessageTraits<NanoappListRequest> {
   static const ChreMessage enum_value = ChreMessage::NanoappListRequest;
 };
 
-template<> struct ChreMessageTraits<chre::fbs::NanoappListResponse> {
+template<> struct ChreMessageTraits<NanoappListResponse> {
   static const ChreMessage enum_value = ChreMessage::NanoappListResponse;
 };
 
-template<> struct ChreMessageTraits<chre::fbs::LoadNanoappRequest> {
+template<> struct ChreMessageTraits<LoadNanoappRequest> {
   static const ChreMessage enum_value = ChreMessage::LoadNanoappRequest;
 };
 
-template<> struct ChreMessageTraits<chre::fbs::LoadNanoappResponse> {
+template<> struct ChreMessageTraits<LoadNanoappResponse> {
   static const ChreMessage enum_value = ChreMessage::LoadNanoappResponse;
 };
 
-template<> struct ChreMessageTraits<chre::fbs::UnloadNanoappRequest> {
+template<> struct ChreMessageTraits<UnloadNanoappRequest> {
   static const ChreMessage enum_value = ChreMessage::UnloadNanoappRequest;
 };
 
-template<> struct ChreMessageTraits<chre::fbs::UnloadNanoappResponse> {
+template<> struct ChreMessageTraits<UnloadNanoappResponse> {
   static const ChreMessage enum_value = ChreMessage::UnloadNanoappResponse;
 };
 
-template<> struct ChreMessageTraits<chre::fbs::LogMessage> {
+template<> struct ChreMessageTraits<LogMessage> {
   static const ChreMessage enum_value = ChreMessage::LogMessage;
 };
 
-template<> struct ChreMessageTraits<chre::fbs::TimeSyncMessage> {
+template<> struct ChreMessageTraits<TimeSyncMessage> {
   static const ChreMessage enum_value = ChreMessage::TimeSyncMessage;
 };
 
-template<> struct ChreMessageTraits<chre::fbs::DebugDumpRequest> {
+template<> struct ChreMessageTraits<DebugDumpRequest> {
   static const ChreMessage enum_value = ChreMessage::DebugDumpRequest;
 };
 
-template<> struct ChreMessageTraits<chre::fbs::DebugDumpData> {
+template<> struct ChreMessageTraits<DebugDumpData> {
   static const ChreMessage enum_value = ChreMessage::DebugDumpData;
 };
 
-template<> struct ChreMessageTraits<chre::fbs::DebugDumpResponse> {
+template<> struct ChreMessageTraits<DebugDumpResponse> {
   static const ChreMessage enum_value = ChreMessage::DebugDumpResponse;
 };
 
-template<> struct ChreMessageTraits<chre::fbs::TimeSyncRequest> {
+template<> struct ChreMessageTraits<TimeSyncRequest> {
   static const ChreMessage enum_value = ChreMessage::TimeSyncRequest;
 };
 
-template<> struct ChreMessageTraits<chre::fbs::LowPowerMicAccessRequest> {
+template<> struct ChreMessageTraits<LowPowerMicAccessRequest> {
   static const ChreMessage enum_value = ChreMessage::LowPowerMicAccessRequest;
 };
 
-template<> struct ChreMessageTraits<chre::fbs::LowPowerMicAccessRelease> {
+template<> struct ChreMessageTraits<LowPowerMicAccessRelease> {
   static const ChreMessage enum_value = ChreMessage::LowPowerMicAccessRelease;
 };
 
-template<> struct ChreMessageTraits<chre::fbs::SettingChangeMessage> {
+template<> struct ChreMessageTraits<SettingChangeMessage> {
   static const ChreMessage enum_value = ChreMessage::SettingChangeMessage;
 };
 
 bool VerifyChreMessage(flatbuffers::Verifier &verifier, const void *obj, ChreMessage type);
 bool VerifyChreMessageVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types);
 
-FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(2) HostAddress FLATBUFFERS_FINAL_CLASS {
+MANUALLY_ALIGNED_STRUCT(2) HostAddress FLATBUFFERS_FINAL_CLASS {
  private:
   uint16_t client_id_;
 
  public:
   HostAddress() {
-    memset(static_cast<void *>(this), 0, sizeof(HostAddress));
+    memset(this, 0, sizeof(HostAddress));
+  }
+  HostAddress(const HostAddress &_o) {
+    memcpy(this, &_o, sizeof(HostAddress));
   }
   HostAddress(uint16_t _client_id)
       : client_id_(flatbuffers::EndianScalar(_client_id)) {
@@ -307,12 +247,11 @@
     return flatbuffers::EndianScalar(client_id_);
   }
 };
-FLATBUFFERS_STRUCT_END(HostAddress, 2);
+STRUCT_END(HostAddress, 2);
 
 /// Represents a message sent to/from a nanoapp from/to a client on the host
 struct NanoappMessage FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  typedef NanoappMessageBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_APP_ID = 4,
     VT_MESSAGE_TYPE = 6,
     VT_HOST_ENDPOINT = 8,
@@ -339,14 +278,13 @@
            VerifyField<uint64_t>(verifier, VT_APP_ID) &&
            VerifyField<uint32_t>(verifier, VT_MESSAGE_TYPE) &&
            VerifyField<uint16_t>(verifier, VT_HOST_ENDPOINT) &&
-           VerifyOffsetRequired(verifier, VT_MESSAGE) &&
-           verifier.VerifyVector(message()) &&
+           VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_MESSAGE) &&
+           verifier.Verify(message()) &&
            verifier.EndTable();
   }
 };
 
 struct NanoappMessageBuilder {
-  typedef NanoappMessage Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
   void add_app_id(uint64_t app_id) {
@@ -361,13 +299,13 @@
   void add_message(flatbuffers::Offset<flatbuffers::Vector<uint8_t>> message) {
     fbb_.AddOffset(NanoappMessage::VT_MESSAGE, message);
   }
-  explicit NanoappMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  NanoappMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   NanoappMessageBuilder &operator=(const NanoappMessageBuilder &);
   flatbuffers::Offset<NanoappMessage> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 4);
     auto o = flatbuffers::Offset<NanoappMessage>(end);
     fbb_.Required(o, NanoappMessage::VT_MESSAGE);
     return o;
@@ -394,17 +332,15 @@
     uint32_t message_type = 0,
     uint16_t host_endpoint = 65534,
     const std::vector<uint8_t> *message = nullptr) {
-  auto message__ = message ? _fbb.CreateVector<uint8_t>(*message) : 0;
   return chre::fbs::CreateNanoappMessage(
       _fbb,
       app_id,
       message_type,
       host_endpoint,
-      message__);
+      message ? _fbb.CreateVector<uint8_t>(*message) : 0);
 }
 
 struct HubInfoRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  typedef HubInfoRequestBuilder Builder;
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
            verifier.EndTable();
@@ -412,16 +348,15 @@
 };
 
 struct HubInfoRequestBuilder {
-  typedef HubInfoRequest Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
-  explicit HubInfoRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  HubInfoRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   HubInfoRequestBuilder &operator=(const HubInfoRequestBuilder &);
   flatbuffers::Offset<HubInfoRequest> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 0);
     auto o = flatbuffers::Offset<HubInfoRequest>(end);
     return o;
   }
@@ -434,8 +369,7 @@
 }
 
 struct HubInfoResponse FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  typedef HubInfoResponseBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_NAME = 4,
     VT_VENDOR = 6,
     VT_TOOLCHAIN = 8,
@@ -497,12 +431,12 @@
   }
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
-           VerifyOffset(verifier, VT_NAME) &&
-           verifier.VerifyVector(name()) &&
-           VerifyOffset(verifier, VT_VENDOR) &&
-           verifier.VerifyVector(vendor()) &&
-           VerifyOffset(verifier, VT_TOOLCHAIN) &&
-           verifier.VerifyVector(toolchain()) &&
+           VerifyField<flatbuffers::uoffset_t>(verifier, VT_NAME) &&
+           verifier.Verify(name()) &&
+           VerifyField<flatbuffers::uoffset_t>(verifier, VT_VENDOR) &&
+           verifier.Verify(vendor()) &&
+           VerifyField<flatbuffers::uoffset_t>(verifier, VT_TOOLCHAIN) &&
+           verifier.Verify(toolchain()) &&
            VerifyField<uint32_t>(verifier, VT_PLATFORM_VERSION) &&
            VerifyField<uint32_t>(verifier, VT_TOOLCHAIN_VERSION) &&
            VerifyField<float>(verifier, VT_PEAK_MIPS) &&
@@ -517,7 +451,6 @@
 };
 
 struct HubInfoResponseBuilder {
-  typedef HubInfoResponse Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
   void add_name(flatbuffers::Offset<flatbuffers::Vector<int8_t>> name) {
@@ -556,13 +489,13 @@
   void add_chre_platform_version(uint32_t chre_platform_version) {
     fbb_.AddElement<uint32_t>(HubInfoResponse::VT_CHRE_PLATFORM_VERSION, chre_platform_version, 0);
   }
-  explicit HubInfoResponseBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  HubInfoResponseBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   HubInfoResponseBuilder &operator=(const HubInfoResponseBuilder &);
   flatbuffers::Offset<HubInfoResponse> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 12);
     auto o = flatbuffers::Offset<HubInfoResponse>(end);
     return o;
   }
@@ -612,14 +545,11 @@
     uint32_t max_msg_len = 0,
     uint64_t platform_id = 0,
     uint32_t chre_platform_version = 0) {
-  auto name__ = name ? _fbb.CreateVector<int8_t>(*name) : 0;
-  auto vendor__ = vendor ? _fbb.CreateVector<int8_t>(*vendor) : 0;
-  auto toolchain__ = toolchain ? _fbb.CreateVector<int8_t>(*toolchain) : 0;
   return chre::fbs::CreateHubInfoResponse(
       _fbb,
-      name__,
-      vendor__,
-      toolchain__,
+      name ? _fbb.CreateVector<int8_t>(*name) : 0,
+      vendor ? _fbb.CreateVector<int8_t>(*vendor) : 0,
+      toolchain ? _fbb.CreateVector<int8_t>(*toolchain) : 0,
       platform_version,
       toolchain_version,
       peak_mips,
@@ -632,7 +562,6 @@
 }
 
 struct NanoappListRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  typedef NanoappListRequestBuilder Builder;
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
            verifier.EndTable();
@@ -640,16 +569,15 @@
 };
 
 struct NanoappListRequestBuilder {
-  typedef NanoappListRequest Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
-  explicit NanoappListRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  NanoappListRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   NanoappListRequestBuilder &operator=(const NanoappListRequestBuilder &);
   flatbuffers::Offset<NanoappListRequest> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 0);
     auto o = flatbuffers::Offset<NanoappListRequest>(end);
     return o;
   }
@@ -662,8 +590,7 @@
 }
 
 struct NanoappListEntry FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  typedef NanoappListEntryBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_APP_ID = 4,
     VT_VERSION = 6,
     VT_ENABLED = 8,
@@ -696,7 +623,6 @@
 };
 
 struct NanoappListEntryBuilder {
-  typedef NanoappListEntry Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
   void add_app_id(uint64_t app_id) {
@@ -711,13 +637,13 @@
   void add_is_system(bool is_system) {
     fbb_.AddElement<uint8_t>(NanoappListEntry::VT_IS_SYSTEM, static_cast<uint8_t>(is_system), 0);
   }
-  explicit NanoappListEntryBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  NanoappListEntryBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   NanoappListEntryBuilder &operator=(const NanoappListEntryBuilder &);
   flatbuffers::Offset<NanoappListEntry> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 4);
     auto o = flatbuffers::Offset<NanoappListEntry>(end);
     return o;
   }
@@ -738,36 +664,34 @@
 }
 
 struct NanoappListResponse FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  typedef NanoappListResponseBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_NANOAPPS = 4
   };
-  const flatbuffers::Vector<flatbuffers::Offset<chre::fbs::NanoappListEntry>> *nanoapps() const {
-    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<chre::fbs::NanoappListEntry>> *>(VT_NANOAPPS);
+  const flatbuffers::Vector<flatbuffers::Offset<NanoappListEntry>> *nanoapps() const {
+    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<NanoappListEntry>> *>(VT_NANOAPPS);
   }
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
-           VerifyOffsetRequired(verifier, VT_NANOAPPS) &&
-           verifier.VerifyVector(nanoapps()) &&
+           VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_NANOAPPS) &&
+           verifier.Verify(nanoapps()) &&
            verifier.VerifyVectorOfTables(nanoapps()) &&
            verifier.EndTable();
   }
 };
 
 struct NanoappListResponseBuilder {
-  typedef NanoappListResponse Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
-  void add_nanoapps(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<chre::fbs::NanoappListEntry>>> nanoapps) {
+  void add_nanoapps(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<NanoappListEntry>>> nanoapps) {
     fbb_.AddOffset(NanoappListResponse::VT_NANOAPPS, nanoapps);
   }
-  explicit NanoappListResponseBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  NanoappListResponseBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   NanoappListResponseBuilder &operator=(const NanoappListResponseBuilder &);
   flatbuffers::Offset<NanoappListResponse> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 1);
     auto o = flatbuffers::Offset<NanoappListResponse>(end);
     fbb_.Required(o, NanoappListResponse::VT_NANOAPPS);
     return o;
@@ -776,7 +700,7 @@
 
 inline flatbuffers::Offset<NanoappListResponse> CreateNanoappListResponse(
     flatbuffers::FlatBufferBuilder &_fbb,
-    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<chre::fbs::NanoappListEntry>>> nanoapps = 0) {
+    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<NanoappListEntry>>> nanoapps = 0) {
   NanoappListResponseBuilder builder_(_fbb);
   builder_.add_nanoapps(nanoapps);
   return builder_.Finish();
@@ -784,11 +708,10 @@
 
 inline flatbuffers::Offset<NanoappListResponse> CreateNanoappListResponseDirect(
     flatbuffers::FlatBufferBuilder &_fbb,
-    const std::vector<flatbuffers::Offset<chre::fbs::NanoappListEntry>> *nanoapps = nullptr) {
-  auto nanoapps__ = nanoapps ? _fbb.CreateVector<flatbuffers::Offset<chre::fbs::NanoappListEntry>>(*nanoapps) : 0;
+    const std::vector<flatbuffers::Offset<NanoappListEntry>> *nanoapps = nullptr) {
   return chre::fbs::CreateNanoappListResponse(
       _fbb,
-      nanoapps__);
+      nanoapps ? _fbb.CreateVector<flatbuffers::Offset<NanoappListEntry>>(*nanoapps) : 0);
 }
 
 /// Represents a request for loading a nanoapp.
@@ -830,8 +753,7 @@
 /// considered to have failed. If the request times out (e.g. the requestor
 /// process crashes), then the load request will be cancelled at CHRE and fail.
 struct LoadNanoappRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  typedef LoadNanoappRequestBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_TRANSACTION_ID = 4,
     VT_APP_ID = 6,
     VT_APP_VERSION = 8,
@@ -877,18 +799,17 @@
            VerifyField<uint64_t>(verifier, VT_APP_ID) &&
            VerifyField<uint32_t>(verifier, VT_APP_VERSION) &&
            VerifyField<uint32_t>(verifier, VT_TARGET_API_VERSION) &&
-           VerifyOffsetRequired(verifier, VT_APP_BINARY) &&
-           verifier.VerifyVector(app_binary()) &&
+           VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_APP_BINARY) &&
+           verifier.Verify(app_binary()) &&
            VerifyField<uint32_t>(verifier, VT_FRAGMENT_ID) &&
            VerifyField<uint32_t>(verifier, VT_TOTAL_APP_SIZE) &&
-           VerifyOffset(verifier, VT_APP_BINARY_FILE_NAME) &&
-           verifier.VerifyVector(app_binary_file_name()) &&
+           VerifyField<flatbuffers::uoffset_t>(verifier, VT_APP_BINARY_FILE_NAME) &&
+           verifier.Verify(app_binary_file_name()) &&
            verifier.EndTable();
   }
 };
 
 struct LoadNanoappRequestBuilder {
-  typedef LoadNanoappRequest Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
   void add_transaction_id(uint32_t transaction_id) {
@@ -915,13 +836,13 @@
   void add_app_binary_file_name(flatbuffers::Offset<flatbuffers::Vector<int8_t>> app_binary_file_name) {
     fbb_.AddOffset(LoadNanoappRequest::VT_APP_BINARY_FILE_NAME, app_binary_file_name);
   }
-  explicit LoadNanoappRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  LoadNanoappRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   LoadNanoappRequestBuilder &operator=(const LoadNanoappRequestBuilder &);
   flatbuffers::Offset<LoadNanoappRequest> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 8);
     auto o = flatbuffers::Offset<LoadNanoappRequest>(end);
     fbb_.Required(o, LoadNanoappRequest::VT_APP_BINARY);
     return o;
@@ -960,23 +881,20 @@
     uint32_t fragment_id = 0,
     uint32_t total_app_size = 0,
     const std::vector<int8_t> *app_binary_file_name = nullptr) {
-  auto app_binary__ = app_binary ? _fbb.CreateVector<uint8_t>(*app_binary) : 0;
-  auto app_binary_file_name__ = app_binary_file_name ? _fbb.CreateVector<int8_t>(*app_binary_file_name) : 0;
   return chre::fbs::CreateLoadNanoappRequest(
       _fbb,
       transaction_id,
       app_id,
       app_version,
       target_api_version,
-      app_binary__,
+      app_binary ? _fbb.CreateVector<uint8_t>(*app_binary) : 0,
       fragment_id,
       total_app_size,
-      app_binary_file_name__);
+      app_binary_file_name ? _fbb.CreateVector<int8_t>(*app_binary_file_name) : 0);
 }
 
 struct LoadNanoappResponse FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  typedef LoadNanoappResponseBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_TRANSACTION_ID = 4,
     VT_SUCCESS = 6,
     VT_FRAGMENT_ID = 8
@@ -1004,7 +922,6 @@
 };
 
 struct LoadNanoappResponseBuilder {
-  typedef LoadNanoappResponse Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
   void add_transaction_id(uint32_t transaction_id) {
@@ -1016,13 +933,13 @@
   void add_fragment_id(uint32_t fragment_id) {
     fbb_.AddElement<uint32_t>(LoadNanoappResponse::VT_FRAGMENT_ID, fragment_id, 0);
   }
-  explicit LoadNanoappResponseBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  LoadNanoappResponseBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   LoadNanoappResponseBuilder &operator=(const LoadNanoappResponseBuilder &);
   flatbuffers::Offset<LoadNanoappResponse> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 3);
     auto o = flatbuffers::Offset<LoadNanoappResponse>(end);
     return o;
   }
@@ -1041,8 +958,7 @@
 }
 
 struct UnloadNanoappRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  typedef UnloadNanoappRequestBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_TRANSACTION_ID = 4,
     VT_APP_ID = 6,
     VT_ALLOW_SYSTEM_NANOAPP_UNLOAD = 8
@@ -1068,7 +984,6 @@
 };
 
 struct UnloadNanoappRequestBuilder {
-  typedef UnloadNanoappRequest Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
   void add_transaction_id(uint32_t transaction_id) {
@@ -1080,13 +995,13 @@
   void add_allow_system_nanoapp_unload(bool allow_system_nanoapp_unload) {
     fbb_.AddElement<uint8_t>(UnloadNanoappRequest::VT_ALLOW_SYSTEM_NANOAPP_UNLOAD, static_cast<uint8_t>(allow_system_nanoapp_unload), 0);
   }
-  explicit UnloadNanoappRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  UnloadNanoappRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   UnloadNanoappRequestBuilder &operator=(const UnloadNanoappRequestBuilder &);
   flatbuffers::Offset<UnloadNanoappRequest> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 3);
     auto o = flatbuffers::Offset<UnloadNanoappRequest>(end);
     return o;
   }
@@ -1105,8 +1020,7 @@
 }
 
 struct UnloadNanoappResponse FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  typedef UnloadNanoappResponseBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_TRANSACTION_ID = 4,
     VT_SUCCESS = 6
   };
@@ -1125,7 +1039,6 @@
 };
 
 struct UnloadNanoappResponseBuilder {
-  typedef UnloadNanoappResponse Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
   void add_transaction_id(uint32_t transaction_id) {
@@ -1134,13 +1047,13 @@
   void add_success(bool success) {
     fbb_.AddElement<uint8_t>(UnloadNanoappResponse::VT_SUCCESS, static_cast<uint8_t>(success), 0);
   }
-  explicit UnloadNanoappResponseBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  UnloadNanoappResponseBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   UnloadNanoappResponseBuilder &operator=(const UnloadNanoappResponseBuilder &);
   flatbuffers::Offset<UnloadNanoappResponse> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 2);
     auto o = flatbuffers::Offset<UnloadNanoappResponse>(end);
     return o;
   }
@@ -1158,8 +1071,7 @@
 
 /// Represents log messages from CHRE.
 struct LogMessage FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  typedef LogMessageBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_BUFFER = 4
   };
   /// A buffer containing formatted log data. A flat array is used here to avoid
@@ -1180,26 +1092,25 @@
   }
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
-           VerifyOffset(verifier, VT_BUFFER) &&
-           verifier.VerifyVector(buffer()) &&
+           VerifyField<flatbuffers::uoffset_t>(verifier, VT_BUFFER) &&
+           verifier.Verify(buffer()) &&
            verifier.EndTable();
   }
 };
 
 struct LogMessageBuilder {
-  typedef LogMessage Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
   void add_buffer(flatbuffers::Offset<flatbuffers::Vector<int8_t>> buffer) {
     fbb_.AddOffset(LogMessage::VT_BUFFER, buffer);
   }
-  explicit LogMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  LogMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   LogMessageBuilder &operator=(const LogMessageBuilder &);
   flatbuffers::Offset<LogMessage> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 1);
     auto o = flatbuffers::Offset<LogMessage>(end);
     return o;
   }
@@ -1216,16 +1127,14 @@
 inline flatbuffers::Offset<LogMessage> CreateLogMessageDirect(
     flatbuffers::FlatBufferBuilder &_fbb,
     const std::vector<int8_t> *buffer = nullptr) {
-  auto buffer__ = buffer ? _fbb.CreateVector<int8_t>(*buffer) : 0;
   return chre::fbs::CreateLogMessage(
       _fbb,
-      buffer__);
+      buffer ? _fbb.CreateVector<int8_t>(*buffer) : 0);
 }
 
 /// Represents a message sent to CHRE to indicate AP timestamp for time sync
 struct TimeSyncMessage FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  typedef TimeSyncMessageBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_OFFSET = 4
   };
   /// Offset between AP and CHRE timestamp
@@ -1240,19 +1149,18 @@
 };
 
 struct TimeSyncMessageBuilder {
-  typedef TimeSyncMessage Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
   void add_offset(int64_t offset) {
     fbb_.AddElement<int64_t>(TimeSyncMessage::VT_OFFSET, offset, 0);
   }
-  explicit TimeSyncMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  TimeSyncMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   TimeSyncMessageBuilder &operator=(const TimeSyncMessageBuilder &);
   flatbuffers::Offset<TimeSyncMessage> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 1);
     auto o = flatbuffers::Offset<TimeSyncMessage>(end);
     return o;
   }
@@ -1271,7 +1179,6 @@
 /// DebugDumpData messages are generated, followed by a DebugDumpResponse
 /// indicating the completion of the operation.
 struct DebugDumpRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  typedef DebugDumpRequestBuilder Builder;
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
            verifier.EndTable();
@@ -1279,16 +1186,15 @@
 };
 
 struct DebugDumpRequestBuilder {
-  typedef DebugDumpRequest Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
-  explicit DebugDumpRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  DebugDumpRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   DebugDumpRequestBuilder &operator=(const DebugDumpRequestBuilder &);
   flatbuffers::Offset<DebugDumpRequest> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 0);
     auto o = flatbuffers::Offset<DebugDumpRequest>(end);
     return o;
   }
@@ -1301,8 +1207,7 @@
 }
 
 struct DebugDumpData FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  typedef DebugDumpDataBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_DEBUG_STR = 4
   };
   /// Null-terminated ASCII string containing debugging information
@@ -1311,26 +1216,25 @@
   }
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
-           VerifyOffset(verifier, VT_DEBUG_STR) &&
-           verifier.VerifyVector(debug_str()) &&
+           VerifyField<flatbuffers::uoffset_t>(verifier, VT_DEBUG_STR) &&
+           verifier.Verify(debug_str()) &&
            verifier.EndTable();
   }
 };
 
 struct DebugDumpDataBuilder {
-  typedef DebugDumpData Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
   void add_debug_str(flatbuffers::Offset<flatbuffers::Vector<int8_t>> debug_str) {
     fbb_.AddOffset(DebugDumpData::VT_DEBUG_STR, debug_str);
   }
-  explicit DebugDumpDataBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  DebugDumpDataBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   DebugDumpDataBuilder &operator=(const DebugDumpDataBuilder &);
   flatbuffers::Offset<DebugDumpData> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 1);
     auto o = flatbuffers::Offset<DebugDumpData>(end);
     return o;
   }
@@ -1347,15 +1251,13 @@
 inline flatbuffers::Offset<DebugDumpData> CreateDebugDumpDataDirect(
     flatbuffers::FlatBufferBuilder &_fbb,
     const std::vector<int8_t> *debug_str = nullptr) {
-  auto debug_str__ = debug_str ? _fbb.CreateVector<int8_t>(*debug_str) : 0;
   return chre::fbs::CreateDebugDumpData(
       _fbb,
-      debug_str__);
+      debug_str ? _fbb.CreateVector<int8_t>(*debug_str) : 0);
 }
 
 struct DebugDumpResponse FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  typedef DebugDumpResponseBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_SUCCESS = 4,
     VT_DATA_COUNT = 6
   };
@@ -1377,7 +1279,6 @@
 };
 
 struct DebugDumpResponseBuilder {
-  typedef DebugDumpResponse Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
   void add_success(bool success) {
@@ -1386,13 +1287,13 @@
   void add_data_count(uint32_t data_count) {
     fbb_.AddElement<uint32_t>(DebugDumpResponse::VT_DATA_COUNT, data_count, 0);
   }
-  explicit DebugDumpResponseBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  DebugDumpResponseBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   DebugDumpResponseBuilder &operator=(const DebugDumpResponseBuilder &);
   flatbuffers::Offset<DebugDumpResponse> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 2);
     auto o = flatbuffers::Offset<DebugDumpResponse>(end);
     return o;
   }
@@ -1411,7 +1312,6 @@
 /// A request from CHRE for host to initiate a time sync message
 /// (system feature, platform-specific - not all platforms necessarily use this)
 struct TimeSyncRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  typedef TimeSyncRequestBuilder Builder;
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
            verifier.EndTable();
@@ -1419,16 +1319,15 @@
 };
 
 struct TimeSyncRequestBuilder {
-  typedef TimeSyncRequest Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
-  explicit TimeSyncRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  TimeSyncRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   TimeSyncRequestBuilder &operator=(const TimeSyncRequestBuilder &);
   flatbuffers::Offset<TimeSyncRequest> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 0);
     auto o = flatbuffers::Offset<TimeSyncRequest>(end);
     return o;
   }
@@ -1445,7 +1344,6 @@
 /// SoundTrigger HAL) is needed to ensure this capability is powered up when
 /// CHRE needs it. The host does not send a response.
 struct LowPowerMicAccessRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  typedef LowPowerMicAccessRequestBuilder Builder;
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
            verifier.EndTable();
@@ -1453,16 +1351,15 @@
 };
 
 struct LowPowerMicAccessRequestBuilder {
-  typedef LowPowerMicAccessRequest Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
-  explicit LowPowerMicAccessRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  LowPowerMicAccessRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   LowPowerMicAccessRequestBuilder &operator=(const LowPowerMicAccessRequestBuilder &);
   flatbuffers::Offset<LowPowerMicAccessRequest> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 0);
     auto o = flatbuffers::Offset<LowPowerMicAccessRequest>(end);
     return o;
   }
@@ -1477,7 +1374,6 @@
 /// Notification from CHRE that it no longer needs direct access to low-power
 /// microphone data.
 struct LowPowerMicAccessRelease FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  typedef LowPowerMicAccessReleaseBuilder Builder;
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
            verifier.EndTable();
@@ -1485,16 +1381,15 @@
 };
 
 struct LowPowerMicAccessReleaseBuilder {
-  typedef LowPowerMicAccessRelease Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
-  explicit LowPowerMicAccessReleaseBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  LowPowerMicAccessReleaseBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   LowPowerMicAccessReleaseBuilder &operator=(const LowPowerMicAccessReleaseBuilder &);
   flatbuffers::Offset<LowPowerMicAccessRelease> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 0);
     auto o = flatbuffers::Offset<LowPowerMicAccessRelease>(end);
     return o;
   }
@@ -1508,18 +1403,17 @@
 
 /// Notification from the host that a system setting has changed
 struct SettingChangeMessage FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  typedef SettingChangeMessageBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_SETTING = 4,
     VT_STATE = 6
   };
   /// The setting that has changed
-  chre::fbs::Setting setting() const {
-    return static_cast<chre::fbs::Setting>(GetField<int8_t>(VT_SETTING, 0));
+  Setting setting() const {
+    return static_cast<Setting>(GetField<int8_t>(VT_SETTING, 0));
   }
   /// The new setting value
-  chre::fbs::SettingState state() const {
-    return static_cast<chre::fbs::SettingState>(GetField<int8_t>(VT_STATE, 0));
+  SettingState state() const {
+    return static_cast<SettingState>(GetField<int8_t>(VT_STATE, 0));
   }
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
@@ -1530,22 +1424,21 @@
 };
 
 struct SettingChangeMessageBuilder {
-  typedef SettingChangeMessage Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
-  void add_setting(chre::fbs::Setting setting) {
+  void add_setting(Setting setting) {
     fbb_.AddElement<int8_t>(SettingChangeMessage::VT_SETTING, static_cast<int8_t>(setting), 0);
   }
-  void add_state(chre::fbs::SettingState state) {
+  void add_state(SettingState state) {
     fbb_.AddElement<int8_t>(SettingChangeMessage::VT_STATE, static_cast<int8_t>(state), 0);
   }
-  explicit SettingChangeMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  SettingChangeMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   SettingChangeMessageBuilder &operator=(const SettingChangeMessageBuilder &);
   flatbuffers::Offset<SettingChangeMessage> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 2);
     auto o = flatbuffers::Offset<SettingChangeMessage>(end);
     return o;
   }
@@ -1553,8 +1446,8 @@
 
 inline flatbuffers::Offset<SettingChangeMessage> CreateSettingChangeMessage(
     flatbuffers::FlatBufferBuilder &_fbb,
-    chre::fbs::Setting setting = chre::fbs::Setting::LOCATION,
-    chre::fbs::SettingState state = chre::fbs::SettingState::DISABLED) {
+    Setting setting = Setting::LOCATION,
+    SettingState state = SettingState::DISABLED) {
   SettingChangeMessageBuilder builder_(_fbb);
   builder_.add_state(state);
   builder_.add_setting(setting);
@@ -1565,184 +1458,55 @@
 /// per FlatBuffers requirements, we can't use a union as the top-level
 /// structure (root type), so we must wrap it in a table.
 struct MessageContainer FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
-  typedef MessageContainerBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+  enum {
     VT_MESSAGE_TYPE = 4,
     VT_MESSAGE = 6,
     VT_HOST_ADDR = 8
   };
-  chre::fbs::ChreMessage message_type() const {
-    return static_cast<chre::fbs::ChreMessage>(GetField<uint8_t>(VT_MESSAGE_TYPE, 0));
+  ChreMessage message_type() const {
+    return static_cast<ChreMessage>(GetField<uint8_t>(VT_MESSAGE_TYPE, 0));
   }
   const void *message() const {
     return GetPointer<const void *>(VT_MESSAGE);
   }
-  template<typename T> const T *message_as() const;
-  const chre::fbs::NanoappMessage *message_as_NanoappMessage() const {
-    return message_type() == chre::fbs::ChreMessage::NanoappMessage ? static_cast<const chre::fbs::NanoappMessage *>(message()) : nullptr;
-  }
-  const chre::fbs::HubInfoRequest *message_as_HubInfoRequest() const {
-    return message_type() == chre::fbs::ChreMessage::HubInfoRequest ? static_cast<const chre::fbs::HubInfoRequest *>(message()) : nullptr;
-  }
-  const chre::fbs::HubInfoResponse *message_as_HubInfoResponse() const {
-    return message_type() == chre::fbs::ChreMessage::HubInfoResponse ? static_cast<const chre::fbs::HubInfoResponse *>(message()) : nullptr;
-  }
-  const chre::fbs::NanoappListRequest *message_as_NanoappListRequest() const {
-    return message_type() == chre::fbs::ChreMessage::NanoappListRequest ? static_cast<const chre::fbs::NanoappListRequest *>(message()) : nullptr;
-  }
-  const chre::fbs::NanoappListResponse *message_as_NanoappListResponse() const {
-    return message_type() == chre::fbs::ChreMessage::NanoappListResponse ? static_cast<const chre::fbs::NanoappListResponse *>(message()) : nullptr;
-  }
-  const chre::fbs::LoadNanoappRequest *message_as_LoadNanoappRequest() const {
-    return message_type() == chre::fbs::ChreMessage::LoadNanoappRequest ? static_cast<const chre::fbs::LoadNanoappRequest *>(message()) : nullptr;
-  }
-  const chre::fbs::LoadNanoappResponse *message_as_LoadNanoappResponse() const {
-    return message_type() == chre::fbs::ChreMessage::LoadNanoappResponse ? static_cast<const chre::fbs::LoadNanoappResponse *>(message()) : nullptr;
-  }
-  const chre::fbs::UnloadNanoappRequest *message_as_UnloadNanoappRequest() const {
-    return message_type() == chre::fbs::ChreMessage::UnloadNanoappRequest ? static_cast<const chre::fbs::UnloadNanoappRequest *>(message()) : nullptr;
-  }
-  const chre::fbs::UnloadNanoappResponse *message_as_UnloadNanoappResponse() const {
-    return message_type() == chre::fbs::ChreMessage::UnloadNanoappResponse ? static_cast<const chre::fbs::UnloadNanoappResponse *>(message()) : nullptr;
-  }
-  const chre::fbs::LogMessage *message_as_LogMessage() const {
-    return message_type() == chre::fbs::ChreMessage::LogMessage ? static_cast<const chre::fbs::LogMessage *>(message()) : nullptr;
-  }
-  const chre::fbs::TimeSyncMessage *message_as_TimeSyncMessage() const {
-    return message_type() == chre::fbs::ChreMessage::TimeSyncMessage ? static_cast<const chre::fbs::TimeSyncMessage *>(message()) : nullptr;
-  }
-  const chre::fbs::DebugDumpRequest *message_as_DebugDumpRequest() const {
-    return message_type() == chre::fbs::ChreMessage::DebugDumpRequest ? static_cast<const chre::fbs::DebugDumpRequest *>(message()) : nullptr;
-  }
-  const chre::fbs::DebugDumpData *message_as_DebugDumpData() const {
-    return message_type() == chre::fbs::ChreMessage::DebugDumpData ? static_cast<const chre::fbs::DebugDumpData *>(message()) : nullptr;
-  }
-  const chre::fbs::DebugDumpResponse *message_as_DebugDumpResponse() const {
-    return message_type() == chre::fbs::ChreMessage::DebugDumpResponse ? static_cast<const chre::fbs::DebugDumpResponse *>(message()) : nullptr;
-  }
-  const chre::fbs::TimeSyncRequest *message_as_TimeSyncRequest() const {
-    return message_type() == chre::fbs::ChreMessage::TimeSyncRequest ? static_cast<const chre::fbs::TimeSyncRequest *>(message()) : nullptr;
-  }
-  const chre::fbs::LowPowerMicAccessRequest *message_as_LowPowerMicAccessRequest() const {
-    return message_type() == chre::fbs::ChreMessage::LowPowerMicAccessRequest ? static_cast<const chre::fbs::LowPowerMicAccessRequest *>(message()) : nullptr;
-  }
-  const chre::fbs::LowPowerMicAccessRelease *message_as_LowPowerMicAccessRelease() const {
-    return message_type() == chre::fbs::ChreMessage::LowPowerMicAccessRelease ? static_cast<const chre::fbs::LowPowerMicAccessRelease *>(message()) : nullptr;
-  }
-  const chre::fbs::SettingChangeMessage *message_as_SettingChangeMessage() const {
-    return message_type() == chre::fbs::ChreMessage::SettingChangeMessage ? static_cast<const chre::fbs::SettingChangeMessage *>(message()) : nullptr;
-  }
   /// The originating or destination client ID on the host side, used to direct
   /// responses only to the client that sent the request. Although initially
   /// populated by the requesting client, this is enforced to be the correct
   /// value by the entity guarding access to CHRE.
   /// This is wrapped in a struct to ensure that it is always included when
   /// encoding the message, so it can be mutated by the host daemon.
-  const chre::fbs::HostAddress *host_addr() const {
-    return GetStruct<const chre::fbs::HostAddress *>(VT_HOST_ADDR);
+  const HostAddress *host_addr() const {
+    return GetStruct<const HostAddress *>(VT_HOST_ADDR);
   }
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
            VerifyField<uint8_t>(verifier, VT_MESSAGE_TYPE) &&
-           VerifyOffsetRequired(verifier, VT_MESSAGE) &&
+           VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_MESSAGE) &&
            VerifyChreMessage(verifier, message(), message_type()) &&
-           VerifyFieldRequired<chre::fbs::HostAddress>(verifier, VT_HOST_ADDR) &&
+           VerifyFieldRequired<HostAddress>(verifier, VT_HOST_ADDR) &&
            verifier.EndTable();
   }
 };
 
-template<> inline const chre::fbs::NanoappMessage *MessageContainer::message_as<chre::fbs::NanoappMessage>() const {
-  return message_as_NanoappMessage();
-}
-
-template<> inline const chre::fbs::HubInfoRequest *MessageContainer::message_as<chre::fbs::HubInfoRequest>() const {
-  return message_as_HubInfoRequest();
-}
-
-template<> inline const chre::fbs::HubInfoResponse *MessageContainer::message_as<chre::fbs::HubInfoResponse>() const {
-  return message_as_HubInfoResponse();
-}
-
-template<> inline const chre::fbs::NanoappListRequest *MessageContainer::message_as<chre::fbs::NanoappListRequest>() const {
-  return message_as_NanoappListRequest();
-}
-
-template<> inline const chre::fbs::NanoappListResponse *MessageContainer::message_as<chre::fbs::NanoappListResponse>() const {
-  return message_as_NanoappListResponse();
-}
-
-template<> inline const chre::fbs::LoadNanoappRequest *MessageContainer::message_as<chre::fbs::LoadNanoappRequest>() const {
-  return message_as_LoadNanoappRequest();
-}
-
-template<> inline const chre::fbs::LoadNanoappResponse *MessageContainer::message_as<chre::fbs::LoadNanoappResponse>() const {
-  return message_as_LoadNanoappResponse();
-}
-
-template<> inline const chre::fbs::UnloadNanoappRequest *MessageContainer::message_as<chre::fbs::UnloadNanoappRequest>() const {
-  return message_as_UnloadNanoappRequest();
-}
-
-template<> inline const chre::fbs::UnloadNanoappResponse *MessageContainer::message_as<chre::fbs::UnloadNanoappResponse>() const {
-  return message_as_UnloadNanoappResponse();
-}
-
-template<> inline const chre::fbs::LogMessage *MessageContainer::message_as<chre::fbs::LogMessage>() const {
-  return message_as_LogMessage();
-}
-
-template<> inline const chre::fbs::TimeSyncMessage *MessageContainer::message_as<chre::fbs::TimeSyncMessage>() const {
-  return message_as_TimeSyncMessage();
-}
-
-template<> inline const chre::fbs::DebugDumpRequest *MessageContainer::message_as<chre::fbs::DebugDumpRequest>() const {
-  return message_as_DebugDumpRequest();
-}
-
-template<> inline const chre::fbs::DebugDumpData *MessageContainer::message_as<chre::fbs::DebugDumpData>() const {
-  return message_as_DebugDumpData();
-}
-
-template<> inline const chre::fbs::DebugDumpResponse *MessageContainer::message_as<chre::fbs::DebugDumpResponse>() const {
-  return message_as_DebugDumpResponse();
-}
-
-template<> inline const chre::fbs::TimeSyncRequest *MessageContainer::message_as<chre::fbs::TimeSyncRequest>() const {
-  return message_as_TimeSyncRequest();
-}
-
-template<> inline const chre::fbs::LowPowerMicAccessRequest *MessageContainer::message_as<chre::fbs::LowPowerMicAccessRequest>() const {
-  return message_as_LowPowerMicAccessRequest();
-}
-
-template<> inline const chre::fbs::LowPowerMicAccessRelease *MessageContainer::message_as<chre::fbs::LowPowerMicAccessRelease>() const {
-  return message_as_LowPowerMicAccessRelease();
-}
-
-template<> inline const chre::fbs::SettingChangeMessage *MessageContainer::message_as<chre::fbs::SettingChangeMessage>() const {
-  return message_as_SettingChangeMessage();
-}
-
 struct MessageContainerBuilder {
-  typedef MessageContainer Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
-  void add_message_type(chre::fbs::ChreMessage message_type) {
+  void add_message_type(ChreMessage message_type) {
     fbb_.AddElement<uint8_t>(MessageContainer::VT_MESSAGE_TYPE, static_cast<uint8_t>(message_type), 0);
   }
   void add_message(flatbuffers::Offset<void> message) {
     fbb_.AddOffset(MessageContainer::VT_MESSAGE, message);
   }
-  void add_host_addr(const chre::fbs::HostAddress *host_addr) {
+  void add_host_addr(const HostAddress *host_addr) {
     fbb_.AddStruct(MessageContainer::VT_HOST_ADDR, host_addr);
   }
-  explicit MessageContainerBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+  MessageContainerBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
     start_ = fbb_.StartTable();
   }
   MessageContainerBuilder &operator=(const MessageContainerBuilder &);
   flatbuffers::Offset<MessageContainer> Finish() {
-    const auto end = fbb_.EndTable(start_);
+    const auto end = fbb_.EndTable(start_, 3);
     auto o = flatbuffers::Offset<MessageContainer>(end);
     fbb_.Required(o, MessageContainer::VT_MESSAGE);
     fbb_.Required(o, MessageContainer::VT_HOST_ADDR);
@@ -1752,9 +1516,9 @@
 
 inline flatbuffers::Offset<MessageContainer> CreateMessageContainer(
     flatbuffers::FlatBufferBuilder &_fbb,
-    chre::fbs::ChreMessage message_type = chre::fbs::ChreMessage::NONE,
+    ChreMessage message_type = ChreMessage::NONE,
     flatbuffers::Offset<void> message = 0,
-    const chre::fbs::HostAddress *host_addr = 0) {
+    const HostAddress *host_addr = 0) {
   MessageContainerBuilder builder_(_fbb);
   builder_.add_host_addr(host_addr);
   builder_.add_message(message);
@@ -1768,83 +1532,82 @@
       return true;
     }
     case ChreMessage::NanoappMessage: {
-      auto ptr = reinterpret_cast<const chre::fbs::NanoappMessage *>(obj);
+      auto ptr = reinterpret_cast<const NanoappMessage *>(obj);
       return verifier.VerifyTable(ptr);
     }
     case ChreMessage::HubInfoRequest: {
-      auto ptr = reinterpret_cast<const chre::fbs::HubInfoRequest *>(obj);
+      auto ptr = reinterpret_cast<const HubInfoRequest *>(obj);
       return verifier.VerifyTable(ptr);
     }
     case ChreMessage::HubInfoResponse: {
-      auto ptr = reinterpret_cast<const chre::fbs::HubInfoResponse *>(obj);
+      auto ptr = reinterpret_cast<const HubInfoResponse *>(obj);
       return verifier.VerifyTable(ptr);
     }
     case ChreMessage::NanoappListRequest: {
-      auto ptr = reinterpret_cast<const chre::fbs::NanoappListRequest *>(obj);
+      auto ptr = reinterpret_cast<const NanoappListRequest *>(obj);
       return verifier.VerifyTable(ptr);
     }
     case ChreMessage::NanoappListResponse: {
-      auto ptr = reinterpret_cast<const chre::fbs::NanoappListResponse *>(obj);
+      auto ptr = reinterpret_cast<const NanoappListResponse *>(obj);
       return verifier.VerifyTable(ptr);
     }
     case ChreMessage::LoadNanoappRequest: {
-      auto ptr = reinterpret_cast<const chre::fbs::LoadNanoappRequest *>(obj);
+      auto ptr = reinterpret_cast<const LoadNanoappRequest *>(obj);
       return verifier.VerifyTable(ptr);
     }
     case ChreMessage::LoadNanoappResponse: {
-      auto ptr = reinterpret_cast<const chre::fbs::LoadNanoappResponse *>(obj);
+      auto ptr = reinterpret_cast<const LoadNanoappResponse *>(obj);
       return verifier.VerifyTable(ptr);
     }
     case ChreMessage::UnloadNanoappRequest: {
-      auto ptr = reinterpret_cast<const chre::fbs::UnloadNanoappRequest *>(obj);
+      auto ptr = reinterpret_cast<const UnloadNanoappRequest *>(obj);
       return verifier.VerifyTable(ptr);
     }
     case ChreMessage::UnloadNanoappResponse: {
-      auto ptr = reinterpret_cast<const chre::fbs::UnloadNanoappResponse *>(obj);
+      auto ptr = reinterpret_cast<const UnloadNanoappResponse *>(obj);
       return verifier.VerifyTable(ptr);
     }
     case ChreMessage::LogMessage: {
-      auto ptr = reinterpret_cast<const chre::fbs::LogMessage *>(obj);
+      auto ptr = reinterpret_cast<const LogMessage *>(obj);
       return verifier.VerifyTable(ptr);
     }
     case ChreMessage::TimeSyncMessage: {
-      auto ptr = reinterpret_cast<const chre::fbs::TimeSyncMessage *>(obj);
+      auto ptr = reinterpret_cast<const TimeSyncMessage *>(obj);
       return verifier.VerifyTable(ptr);
     }
     case ChreMessage::DebugDumpRequest: {
-      auto ptr = reinterpret_cast<const chre::fbs::DebugDumpRequest *>(obj);
+      auto ptr = reinterpret_cast<const DebugDumpRequest *>(obj);
       return verifier.VerifyTable(ptr);
     }
     case ChreMessage::DebugDumpData: {
-      auto ptr = reinterpret_cast<const chre::fbs::DebugDumpData *>(obj);
+      auto ptr = reinterpret_cast<const DebugDumpData *>(obj);
       return verifier.VerifyTable(ptr);
     }
     case ChreMessage::DebugDumpResponse: {
-      auto ptr = reinterpret_cast<const chre::fbs::DebugDumpResponse *>(obj);
+      auto ptr = reinterpret_cast<const DebugDumpResponse *>(obj);
       return verifier.VerifyTable(ptr);
     }
     case ChreMessage::TimeSyncRequest: {
-      auto ptr = reinterpret_cast<const chre::fbs::TimeSyncRequest *>(obj);
+      auto ptr = reinterpret_cast<const TimeSyncRequest *>(obj);
       return verifier.VerifyTable(ptr);
     }
     case ChreMessage::LowPowerMicAccessRequest: {
-      auto ptr = reinterpret_cast<const chre::fbs::LowPowerMicAccessRequest *>(obj);
+      auto ptr = reinterpret_cast<const LowPowerMicAccessRequest *>(obj);
       return verifier.VerifyTable(ptr);
     }
     case ChreMessage::LowPowerMicAccessRelease: {
-      auto ptr = reinterpret_cast<const chre::fbs::LowPowerMicAccessRelease *>(obj);
+      auto ptr = reinterpret_cast<const LowPowerMicAccessRelease *>(obj);
       return verifier.VerifyTable(ptr);
     }
     case ChreMessage::SettingChangeMessage: {
-      auto ptr = reinterpret_cast<const chre::fbs::SettingChangeMessage *>(obj);
+      auto ptr = reinterpret_cast<const SettingChangeMessage *>(obj);
       return verifier.VerifyTable(ptr);
     }
-    default: return true;
+    default: return false;
   }
 }
 
 inline bool VerifyChreMessageVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types) {
-  if (!values || !types) return !values && !types;
   if (values->size() != types->size()) return false;
   for (flatbuffers::uoffset_t i = 0; i < values->size(); ++i) {
     if (!VerifyChreMessage(
@@ -1859,32 +1622,17 @@
   return flatbuffers::GetRoot<chre::fbs::MessageContainer>(buf);
 }
 
-inline const chre::fbs::MessageContainer *GetSizePrefixedMessageContainer(const void *buf) {
-  return flatbuffers::GetSizePrefixedRoot<chre::fbs::MessageContainer>(buf);
-}
-
 inline bool VerifyMessageContainerBuffer(
     flatbuffers::Verifier &verifier) {
   return verifier.VerifyBuffer<chre::fbs::MessageContainer>(nullptr);
 }
 
-inline bool VerifySizePrefixedMessageContainerBuffer(
-    flatbuffers::Verifier &verifier) {
-  return verifier.VerifySizePrefixedBuffer<chre::fbs::MessageContainer>(nullptr);
-}
-
 inline void FinishMessageContainerBuffer(
     flatbuffers::FlatBufferBuilder &fbb,
     flatbuffers::Offset<chre::fbs::MessageContainer> root) {
   fbb.Finish(root);
 }
 
-inline void FinishSizePrefixedMessageContainerBuffer(
-    flatbuffers::FlatBufferBuilder &fbb,
-    flatbuffers::Offset<chre::fbs::MessageContainer> root) {
-  fbb.FinishSizePrefixed(root);
-}
-
 }  // namespace fbs
 }  // namespace chre
 
diff --git a/platform/usf/include/chre/platform/usf/usf_helper.h b/platform/usf/include/chre/platform/usf/usf_helper.h
new file mode 100644
index 0000000..8b2305a
--- /dev/null
+++ b/platform/usf/include/chre/platform/usf/usf_helper.h
@@ -0,0 +1,340 @@
+/*
+ * 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_PLATFORM_USF_USF_HELPER_H_
+#define CHRE_PLATFORM_USF_USF_HELPER_H_
+
+#include "chre/core/sensor_type.h"
+#include "chre/platform/system_time.h"
+#include "chre/util/unique_ptr.h"
+
+#include "usf/error.h"
+#include "usf/fbs/usf_msg_sample_root_generated.h"
+#include "usf/reffed_ptr.h"
+#include "usf/usf_sensor.h"
+#include "usf/usf_sensor_req.h"
+#include "usf/usf_transport_client.h"
+
+namespace chre {
+
+struct SensorInfo {
+  //! Used to fill in the chreSensorDataHeader field. If the user of the helper
+  //! doesn't care about this field, then it can be set to 0.
+  uint32_t sensorHandle;
+
+  //! Sampling ID corresponding to the active subscription to this sensor, if
+  //! one exists. 0 otherwise.
+  uint32_t samplingId;
+};
+
+//! A callback interface for receiving UsfHelper data events and to allow the
+//! UsfHelper to ask for information.
+class UsfHelperCallbackInterface {
+ public:
+  //! Invoked from the USF worker thread to provide sensor data events. The
+  //! event data format is one of the chreSensorXXXData defined in the CHRE API,
+  //! implicitly specified by sensorType.
+  virtual void onSensorDataEvent(uint8_t sensorType,
+                                 UniquePtr<uint8_t> &&eventData) = 0;
+
+  /**
+   * Invoked by the USF Helper to obtain sensor info for a given sensor type.
+   *
+   * @param sensorType The sensor type for which info should be populated
+   * @param sensorInfo Non-null pointer that will be populated with sensor info
+   *     if this method is successful
+   * @return true if all sensor info was obtained.
+   */
+  virtual bool getSensorInfo(uint8_t sensorType, SensorInfo *sensorInfo) = 0;
+
+  //! Invoked from the USF worker thread to provide a sensor sampling status
+  //! update. All fields are guaranteed to be valid.
+  virtual void onSamplingStatusUpdate(
+      uint8_t sensorType, const usf::UsfSensorSamplingEvent *update) = 0;
+
+  //! Invoked from the USF worker thread to indicate that flushing the given
+  //! sensor has completed.
+  virtual void onFlushComplete(usf::UsfErr err, uint32_t requestId,
+                               void *cookie) = 0;
+
+  //! Invoked from the USF worker thread to provide a bias update.
+  virtual void onBiasUpdate(
+      uint8_t sensorType,
+      UniquePtr<struct chreSensorThreeAxisData> &&eventData) = 0;
+};
+
+//! Class that allows clients of UsfHelper that only want to listen for sensor
+//! events to implement only functions that relate to those events.
+class SensorEventCallbackInterface : public UsfHelperCallbackInterface {
+ public:
+  void onSamplingStatusUpdate(
+      uint8_t /*sensorType*/,
+      const usf::UsfSensorSamplingEvent * /*update*/) override {}
+
+  void onFlushComplete(usf::UsfErr /*err*/, uint32_t /*requestId*/,
+                       void * /*cookie*/) override {}
+
+  void onBiasUpdate(
+      uint8_t /*sensorType*/,
+      UniquePtr<struct chreSensorThreeAxisData> && /*eventData*/) override {}
+};
+
+//! Default timeout to wait for the USF transport client to return a response
+//! to a request
+constexpr Nanoseconds kDefaultUsfWaitTimeout = Seconds(5);
+
+/**
+ * Helper class used to abstract away most details of communicating with USF.
+ */
+class UsfHelper {
+ public:
+  ~UsfHelper();
+
+  //! Maps USF error codes to CHRE error codes.
+  static uint8_t usfErrorToChreError(usf::UsfErr err);
+
+  /**
+   * Initializes connection to USF.
+   *
+   * @param callback USF helper callback.
+   * @param worker USF worker pointer. If null, a new worker is created.
+   */
+  void init(UsfHelperCallbackInterface *callback,
+            usf::UsfWorker *worker = nullptr);
+
+  /**
+   * Retrieves the list of sensors available from USF.
+   *
+   * @param sensorList Non-null pointer to a UsfVector that will be populated
+   *     with all the available sensors from USF.
+   * @return true if the list of sensors was retrieved successfully.
+   */
+  bool getSensorList(
+      usf::UsfVector<refcount::reffed_ptr<usf::UsfSensor>> *sensorList);
+
+  /**
+   * Starts sampling sensor data from the given sensor.
+   *
+   * @param request The various parameters needed to issue the request to the
+   *     sensor.
+   * @param samplingId Non-null pointer that will be filled in with a valid
+   *     sampling ID if the request is issued successfully.
+   * @return true if the sensor request was issued successfully.
+   */
+  bool startSampling(usf::UsfStartSamplingReq *request, uint32_t *samplingId);
+
+  /**
+   * Reconfigures an existing sensor request.
+   *
+   * @param request The various parameters needed to issue the request to the
+   *     sensor.
+   * @return true if the sensor request was reconfigured successfully.
+   */
+  bool reconfigureSampling(usf::UsfReconfigSamplingReq *request);
+
+  /**
+   * Stops an active sensor request.
+   *
+   * @param request The various parameters needed to issue the request to the
+   *     sensor.
+   * @return true if the sensor request was stopped successfully.
+   */
+  bool stopSampling(usf::UsfStopSamplingReq *request);
+
+  /**
+   * Registers the helper for sensor sampling status updates from USF for the
+   * given sensor.
+   *
+   * @param sensor The sensor to listen to sampling status updates from.
+   * @return true if registration was successful.
+   */
+  bool registerForStatusUpdates(refcount::reffed_ptr<usf::UsfSensor> &sensor);
+
+  /**
+   * Registers the helper for bias updates from USF for the given sensor.
+   * This method is not idempotent meaning a call to unregisterForBiasUpdates
+   * must be made for the same sensor prior to another call to this method.
+   *
+   * @param sensor A non-null reffed_ptr to the sensor to listen for bias
+   *     updates from.
+   * @return true if registration was successful.
+   */
+  bool registerForBiasUpdates(
+      const refcount::reffed_ptr<usf::UsfSensor> &sensor);
+
+  /**
+   * Unregisters the helper from bias updates from USF for the given sensor.
+   * If not registered, this method is a no-op.
+   *
+   * @param sensor A non-null reffed_ptr to the sensor to stop listening to bias
+   *     updates from.
+   */
+  void unregisterForBiasUpdates(
+      const refcount::reffed_ptr<usf::UsfSensor> &sensor);
+
+  /**
+   * Obtains the latest three axis bias received from the given sensor, if
+   * available.
+   *
+   * @param sensor The USF sensor to obtain the latest bias values from.
+   * @param bias A non-null pointer that will be filled with the latest bias
+   *     values if available.
+   * @return true if a bias value was available for the given sensor.
+   */
+  bool getThreeAxisBias(const refcount::reffed_ptr<usf::UsfSensor> &sensor,
+                        struct chreSensorThreeAxisData *bias) const;
+
+  /**
+   * Flushes sensor data from the provided sensor asynchronously. Once all data
+   * has been flushed, {@link #onFlushCompleteEvent} will be invoked on the
+   * callback the helper was initialized with.
+   *
+   * @param usfSensorHandle The USF handle corresponding to the sensor to flush
+   * @param cookie A cookie that will be delivered when the flush has completed
+   * @param requestId The ID associated with this flush request, if it was
+   *     made successfully
+   * @return True if the flush request was successfully sent.
+   */
+  bool flushAsync(const usf::UsfServerHandle usfSensorHandle, void *cookie,
+                  uint32_t *requestId);
+
+  /**
+   * Used to process sensor samples delivered through a listener registered with
+   * USF.
+   *
+   * @param event Pointer containing a valid sensor sample
+   */
+  void processSensorSample(const usf::UsfMsgEvent *event);
+
+  /**
+   * Used to process a sensor sampling status update delivered through a
+   * listener registered with USF.
+   *
+   * @param update Update containing the latest state from USF.
+   */
+  void processStatusUpdate(const usf::UsfSensorSamplingEvent *update);
+
+  /**
+   * Process the bias update delivered through a listener registered with USF.
+   *
+   * @param update Update containing latest bias information for a sensor.
+   */
+  void processBiasUpdate(const usf::UsfSensorTransformConfigEvent *update);
+
+ private:
+  /**
+   * Disconnects from underlying services prior to shutdown
+   */
+  void deinit();
+
+  /**
+   * Sends a synchronous request to USF with any returned data stored in the
+   * given callback.
+   *
+   * @param req Request that should be issued to USF
+   * @param callback Helper callback function used to perform the synchronous
+   *     request and contains any response message after the method returns
+   * @return true if no errors were encountered issuing the request
+   */
+  bool sendUsfReqSync(usf::UsfReq *req, usf::UsfReqSyncCallback *callback);
+
+  /**
+   * Retrieves the response message from the synchronous callback. The memory
+   * associated with the message is owned by the callback itself and will be
+   * freed upon callback going out of scope.
+   *
+   * @param callback Synchronous callback previously used in a successful
+   *     sendUsfReqSync invocation
+   * @param respMsg Variable containing the response message if this method
+   *     succeeds
+   * @return true if the response message was decoded and verified successfully
+   *     and respMsg is valid.
+   */
+  template <class T>
+  bool getRespMsg(usf::UsfReqSyncCallback &callback, const T **respMsg);
+
+  /**
+   * Creates a CHRE sensor event from a USF sensor event
+   *
+   * @param sampleMsg Valid decoded USF sensor event
+   * @param sensorType CHRE sensor type corresponding to the event
+   * @param sensorSample Upon success, populated with a valid CHRE sensor event
+   * @return true if the USF sensor event corresponds to a valid, active
+   *     sampling request and event creation was successful
+   */
+  bool createSensorEvent(const usf::UsfMsgSampleBatch *sampleMsg,
+                         uint8_t sensorType, UniquePtr<uint8_t> &sensorSample);
+
+  /**
+   * Converts a USF bias update event into the chreSensorThreeAxisData format.
+   *
+   * @param update USF bias update that needs to be converted.
+   * @return If successful, contains a populated UniquePtr. Otherwise, the
+   *     UniquePtr will be set to nullptr.
+   */
+  UniquePtr<struct chreSensorThreeAxisData> convertUsfBiasUpdateToData(
+      const usf::UsfSensorTransformConfigEvent *update);
+
+  /**
+   * Get the index into the calibrated sensor data array for the given sensor
+   * type.
+   *
+   * @param usfSensorType The USF sensor type to obtain the index for.
+   * @return The index into the data array for the given sensor type. If the
+   *     sensor type isn't present in the array, kNumUsfCalSensors is returned.
+   */
+  static size_t getCalArrayIndex(const usf::UsfSensorType usfSensorType);
+
+  //! A struct to store a sensor's calibration data.
+  struct UsfCalData {
+    uint64_t timestamp;
+    float bias[3];
+    bool hasBias;
+  };
+
+  //! The list of calibrated USF sensors supported.
+  enum class UsfCalSensor : size_t {
+    AccelCal,
+    GyroCal,
+    MagCal,
+    NumCalSensors,
+  };
+
+  static constexpr size_t kNumUsfCalSensors =
+      static_cast<size_t>(UsfCalSensor::NumCalSensors);
+
+  //! Cal data of all the cal sensors.
+  UsfCalData mCalData[kNumUsfCalSensors] = {};
+
+  //! Client used to send messages to USF
+  refcount::reffed_ptr<usf::UsfTransportClient> mTransportClient;
+
+  //! UsfWorker used to dispatch messages to CHRE on its own thread
+  refcount::reffed_ptr<usf::UsfWorker> mWorker;
+
+  //! All registered USF event listeners.
+  DynamicVector<usf::UsfEventListener *> mUsfEventListeners;
+
+  //! Handle to the USF sensor manager
+  usf::UsfServerHandle mSensorMgrHandle;
+
+  //! Currently registered callback
+  UsfHelperCallbackInterface *mCallback = nullptr;
+};
+
+}  // namespace chre
+
+#endif  // CHRE_PLATFORM_USF_USF_HELPER_H_
diff --git a/platform/usf/include/chre/target_platform/platform_sensor_base.h b/platform/usf/include/chre/target_platform/platform_sensor_base.h
new file mode 100644
index 0000000..a209d36
--- /dev/null
+++ b/platform/usf/include/chre/target_platform/platform_sensor_base.h
@@ -0,0 +1,77 @@
+/*
+ * 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_PLATFORM_USF_PLATFORM_SENSOR_BASE_H_
+#define CHRE_PLATFORM_USF_PLATFORM_SENSOR_BASE_H_
+
+#include "chre/util/optional.h"
+
+#include "usf/usf.h"
+#include "usf/usf_sensor.h"
+
+namespace chre {
+
+//! The max length of sensorName
+constexpr size_t kSensorNameMaxLen = 64;
+
+class PlatformSensorBase {
+ public:
+  /**
+   * Initializes various members of PlatformSensorBase.
+   */
+  void initBase(refcount::reffed_ptr<usf::UsfSensor> &usfSensor,
+                uint8_t sensorType);
+
+  usf::UsfServerHandle getServerHandle() const {
+    return mUsfSensor->GetHandle();
+  }
+
+  bool isSamplingIdValid() const {
+    return mSamplingId.has_value();
+  }
+
+  void setSamplingIdInvalid() {
+    mSamplingId.reset();
+  }
+
+  void setSamplingId(uint32_t samplingId) {
+    mSamplingId = samplingId;
+  }
+
+  uint32_t getSamplingId() const {
+    return mSamplingId.value();
+  }
+
+  const refcount::reffed_ptr<usf::UsfSensor> &getUsfSensor() const {
+    return mUsfSensor;
+  }
+
+ protected:
+  //! The USF sensor instance for this sensor.
+  refcount::reffed_ptr<usf::UsfSensor> mUsfSensor;
+
+  //! The sampling ID of the active request with this sensor.
+  Optional<uint32_t> mSamplingId;
+
+  //! Sensor type of this sensor. Needed because USF shares the same sensor
+  //! type for two different CHRE sensors (ACCELEROMETER_TEMPERATURE and
+  //! GYROSCOPE_TEMPERATURE).
+  uint8_t mSensorType;
+};
+
+}  // namespace chre
+
+#endif  // CHRE_PLATFORM_USF_PLATFORM_SENSOR_BASE_H_
diff --git a/platform/usf/include/chre/target_platform/platform_sensor_manager_base.h b/platform/usf/include/chre/target_platform/platform_sensor_manager_base.h
new file mode 100644
index 0000000..2ddd277
--- /dev/null
+++ b/platform/usf/include/chre/target_platform/platform_sensor_manager_base.h
@@ -0,0 +1,59 @@
+/*
+ * 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_PLATFORM_USF_PLATFORM_SENSOR_MANAGER_BASE_H_
+#define CHRE_PLATFORM_USF_PLATFORM_SENSOR_MANAGER_BASE_H_
+
+#include "chre/platform/usf/usf_helper.h"
+#include "chre/util/unique_ptr.h"
+
+namespace chre {
+
+class PlatformSensorManagerBase : public UsfHelperCallbackInterface {
+ public:
+  void onSensorDataEvent(uint8_t sensorType,
+                         UniquePtr<uint8_t> &&eventData) override;
+
+  void onSamplingStatusUpdate(
+      uint8_t sensorType, const usf::UsfSensorSamplingEvent *update) override;
+
+  bool getSensorInfo(uint8_t sensorType, SensorInfo *sensorInfo) override;
+
+  void onFlushComplete(usf::UsfErr err, uint32_t requestId,
+                       void *cookie) override;
+
+  void onBiasUpdate(
+      uint8_t sensorType,
+      UniquePtr<struct chreSensorThreeAxisData> &&eventData) override;
+
+  /**
+   * Converts the given UsfSensor into one or more CHRE sensors and adds them
+   * to the given dynamic vector.
+   *
+   * @param usfSensor UsfSensor to be converted to one or more CHRE sensors
+   * @param chreSensors Dynamic vector that converted sensors must be added to
+   */
+  void addSensorsWithInfo(refcount::reffed_ptr<usf::UsfSensor> &usfSensor,
+                          DynamicVector<Sensor> *chreSensors);
+
+ protected:
+  //! Helper used to communicate with USF.
+  UsfHelper mHelper;
+};
+
+}  // namespace chre
+
+#endif  // CHRE_PLATFORM_USF_PLATFORM_SENSOR_MANAGER_BASE_H_
diff --git a/platform/usf/include/chre/target_platform/platform_sensor_type_helpers_base.h b/platform/usf/include/chre/target_platform/platform_sensor_type_helpers_base.h
new file mode 100644
index 0000000..670a5a7
--- /dev/null
+++ b/platform/usf/include/chre/target_platform/platform_sensor_type_helpers_base.h
@@ -0,0 +1,66 @@
+/*
+ * 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_TARGET_PLATFORM_SENSOR_TYPE_HELPERS_BASE_H_
+#define CHRE_TARGET_PLATFORM_SENSOR_TYPE_HELPERS_BASE_H_
+
+#include "usf/usf_sensor_defs.h"
+
+namespace chre {
+
+/**
+ * This SensorSampleType is designed to help classify sensor's data type in
+ * event handling.
+ * TODO: This is a placeholder for AOC and not fully implemented
+ */
+enum class SensorSampleType {
+  Byte,
+  Float,
+  Occurrence,
+  ThreeAxis,
+  Unknown,
+};
+
+/**
+ * Can be used to expose static methods to the PlatformSensorTypeHelpers class
+ * for use in working with vendor sensor types. Currently, this is stubbed out
+ * in the AOC implementation.
+ */
+class PlatformSensorTypeHelpersBase {
+ public:
+  /**
+   * Maps a sensorType to its SensorSampleType.
+   *
+   * @param sensorType The type of the sensor to obtain its SensorSampleType
+   *     for.
+   * @return The SensorSampleType of the sensorType.
+   */
+  static SensorSampleType getSensorSampleTypeFromSensorType(uint8_t sensorType);
+
+  /**
+   * @return Whether the given sensor type reports bias events.
+   */
+  static bool reportsBias(uint8_t sensorType);
+
+  //! Helper functions used to convert between USF and CHRE types
+  static usf::UsfSensorReportingMode getUsfReportingMode(ReportingMode mode);
+  static bool convertUsfToChreSensorType(usf::UsfSensorType usfSensorType,
+                                         uint8_t *chreSensorType);
+};
+
+}  // namespace chre
+
+#endif  // CHRE_TARGET_PLATFORM_SENSOR_TYPE_HELPERS_BASE_H_
diff --git a/platform/usf/platform_sensor.cc b/platform/usf/platform_sensor.cc
new file mode 100644
index 0000000..e4a310c
--- /dev/null
+++ b/platform/usf/platform_sensor.cc
@@ -0,0 +1,65 @@
+/*
+ * 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/platform/platform_sensor.h"
+
+#include "chre/core/sensor_type_helpers.h"
+
+namespace chre {
+
+void PlatformSensorBase::initBase(
+    refcount::reffed_ptr<usf::UsfSensor> &usfSensor, uint8_t sensorType) {
+  mUsfSensor = usfSensor;
+  mSensorType = sensorType;
+}
+
+uint8_t PlatformSensor::getSensorType() const {
+  return mSensorType;
+}
+
+uint64_t PlatformSensor::getMinInterval() const {
+  return SensorTypeHelpers::isOneShot(mSensorType)
+             ? CHRE_SENSOR_INTERVAL_DEFAULT
+             : mUsfSensor->GetMinDelayNs();
+  ;
+}
+
+bool PlatformSensor::reportsBiasEvents() const {
+  return PlatformSensorTypeHelpersBase::reportsBias(getSensorType());
+}
+
+bool PlatformSensor::supportsPassiveMode() const {
+  return true;
+}
+
+const char *PlatformSensor::getSensorName() const {
+  return SensorTypeHelpers::getSensorTypeName(getSensorType());
+}
+
+PlatformSensor::PlatformSensor(PlatformSensor &&other) {
+  *this = std::move(other);
+}
+
+PlatformSensor &PlatformSensor::operator=(PlatformSensor &&other) {
+  // Note: if this implementation is ever changed to depend on "this" containing
+  // initialized values, the move constructor implementation must be updated.
+  mUsfSensor = other.mUsfSensor;
+  mSensorType = other.mSensorType;
+
+  return *this;
+}
+
+}  // namespace chre
diff --git a/platform/usf/platform_sensor_manager.cc b/platform/usf/platform_sensor_manager.cc
new file mode 100644
index 0000000..ed48474
--- /dev/null
+++ b/platform/usf/platform_sensor_manager.cc
@@ -0,0 +1,313 @@
+/*
+ * 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/platform/platform_sensor_manager.h"
+
+#include "chre/core/event_loop_manager.h"
+#include "chre/util/nested_data_ptr.h"
+
+namespace chre {
+namespace {
+
+void addSensor(refcount::reffed_ptr<usf::UsfSensor> &usfSensor,
+               uint8_t sensorType, DynamicVector<Sensor> *chreSensors) {
+  if (!chreSensors->emplace_back()) {
+    FATAL_ERROR("Failed to allocate new sensor");
+  }
+
+  // The sensor base class must be initialized before the main Sensor init()
+  // can be invoked as init() is allowed to invoke base class methods.
+  chreSensors->back().initBase(usfSensor, sensorType);
+  chreSensors->back().init();
+
+  const Sensor &newSensor = chreSensors->back();
+  LOGI("%s, type %" PRIu8 ", minInterval %" PRIu64 " handle %" PRId32,
+       newSensor.getSensorName(), newSensor.getSensorType(),
+       newSensor.getMinInterval(), newSensor.getServerHandle());
+}
+
+ReportingMode getReportingMode(Sensor &sensor) {
+  if (sensor.isOneShot()) {
+    return ReportingMode::OneShot;
+  } else if (sensor.isOnChange()) {
+    return ReportingMode::OnChange;
+  } else {
+    return ReportingMode::Continuous;
+  }
+}
+
+void handleMissingSensor() {
+  // Try rebooting if a sensor is missing, which might help recover from a
+  // transient failure/race condition at startup. But to avoid endless crashes,
+  // only do this within 45 seconds of boot time - we rely on knowledge that
+  // getMonotonicTime() only resets when the device reboots and not from an SSR.
+#ifndef CHRE_LOG_ONLY_NO_SENSOR
+  if (SystemTime::getMonotonicTime() < (kDefaultUsfWaitTimeout + Seconds(15))) {
+    FATAL_ERROR("Missing required sensor(s)");
+  } else
+#endif
+  {
+    LOGE("Missing required sensor(s)");
+  }
+}
+
+}  // namespace
+
+PlatformSensorManager::~PlatformSensorManager() {}
+
+void PlatformSensorManager::init() {
+  mHelper.init(this);
+}
+
+DynamicVector<Sensor> PlatformSensorManager::getSensors() {
+  DynamicVector<Sensor> sensors;
+
+  usf::UsfVector<refcount::reffed_ptr<usf::UsfSensor>> sensorList;
+  if (mHelper.getSensorList(&sensorList)) {
+    for (size_t i = 0; i < sensorList.size(); i++) {
+      refcount::reffed_ptr<usf::UsfSensor> &sensor = sensorList[i];
+      addSensorsWithInfo(sensor, &sensors);
+    }
+  }
+
+  // TODO: Determine how many sensors are expected to be available through USF.
+  if (sensors.empty()) {
+    handleMissingSensor();
+  }
+
+  return sensors;
+}
+
+bool PlatformSensorManager::configureSensor(Sensor &sensor,
+                                            const SensorRequest &request) {
+  bool success = false;
+
+  if (request.getMode() == SensorMode::Off && !sensor.isSamplingIdValid()) {
+    // If no existing sampling ID exists and the sensor should be turned off,
+    // return true. This can happen when the core platform tries to remove a
+    // request for a one-shot sensor after it fires which automatically happens
+    // inside USF.
+    success = true;
+  } else if (request.getMode() == SensorMode::Off) {
+    usf::UsfStopSamplingReq usfReq;
+    usfReq.SetReqType(usf::UsfMsgReqType_STOP_SAMPLING);
+    usfReq.SetServerHandle(sensor.getServerHandle());
+    usfReq.SetSamplingId(sensor.getSamplingId());
+
+    if (mHelper.stopSampling(&usfReq)) {
+      sensor.setSamplingIdInvalid();
+      success = true;
+    }
+  } else if (sensor.isSamplingIdValid()) {
+    // TODO: See if a reconfigure request can be the same as reissuing a start
+    // request.
+    usf::UsfReconfigSamplingReq usfReq;
+    usfReq.SetReqType(usf::UsfMsgReqType_RECONFIG_SAMPLING);
+    usfReq.SetServerHandle(sensor.getServerHandle());
+    usfReq.SetSamplingId(sensor.getSamplingId());
+    usfReq.SetPeriodNs(request.getInterval().toRawNanoseconds());
+    usfReq.SetMaxLatencyNs(
+        sensor.isContinuous() ? request.getLatency().toRawNanoseconds() : 0);
+
+    success = mHelper.reconfigureSampling(&usfReq);
+  } else {
+    usf::UsfStartSamplingReq usfReq;
+    usfReq.SetReqType(usf::UsfMsgReqType_START_SAMPLING);
+    usfReq.SetServerHandle(sensor.getServerHandle());
+    // TODO(147438885): Make setting the reporting mode of a sensor optional
+    usfReq.SetReportingMode(PlatformSensorTypeHelpersBase::getUsfReportingMode(
+        getReportingMode(sensor)));
+    usfReq.SetPeriodNs(request.getInterval().toRawNanoseconds());
+    usfReq.SetMaxLatencyNs(
+        sensor.isContinuous() ? request.getLatency().toRawNanoseconds() : 0);
+    usfReq.SetPassive(sensorModeIsPassive(request.getMode()));
+    usf::UsfSensorTransformLevel transformLevel =
+        sensor.isCalibrated() ? usf::kUsfSensorTransformLevelAll
+                              : usf::kUsfSensorTransformEnvCompensation;
+    usfReq.SetTransformLevel(transformLevel);
+
+    uint32_t samplingId;
+    if (mHelper.startSampling(&usfReq, &samplingId)) {
+      sensor.setSamplingId(samplingId);
+      success = true;
+    }
+  }
+
+  return success;
+}
+
+bool PlatformSensorManager::configureBiasEvents(const Sensor &sensor,
+                                                bool enable,
+                                                uint64_t /* latencyNs */) {
+  bool success = true;
+  if (enable) {
+    success = mHelper.registerForBiasUpdates(sensor.getUsfSensor());
+  } else {
+    // Unconditional success for unregistering
+    mHelper.unregisterForBiasUpdates(sensor.getUsfSensor());
+  }
+
+  return success;
+}
+
+bool PlatformSensorManager::getThreeAxisBias(
+    const Sensor &sensor, struct chreSensorThreeAxisData *bias) const {
+  bool success = sensor.reportsBiasEvents();
+  if (success) {
+    if (!mHelper.getThreeAxisBias(sensor.getUsfSensor(), bias)) {
+      // Set to zero bias + unknown accuracy per CHRE API requirements.
+      memset(bias, 0, sizeof(chreSensorThreeAxisData));
+      bias->header.readingCount = 1;
+      bias->header.accuracy = CHRE_SENSOR_ACCURACY_UNKNOWN;
+    }
+
+    // Overwrite sensorHandle to match the request type.
+    getSensorRequestManager().getSensorHandle(sensor.getSensorType(),
+                                              &bias->header.sensorHandle);
+  }
+  return success;
+}
+
+bool PlatformSensorManager::flush(const Sensor &sensor,
+                                  uint32_t *flushRequestId) {
+  NestedDataPtr<uint32_t> cookie(sensor.getSensorType());
+  return mHelper.flushAsync(sensor.getServerHandle(), cookie.dataPtr,
+                            flushRequestId);
+}
+
+void PlatformSensorManager::releaseSamplingStatusUpdate(
+    struct chreSensorSamplingStatus *status) {
+  memoryFree(status);
+}
+
+void PlatformSensorManager::releaseSensorDataEvent(void *data) {
+  memoryFree(data);
+}
+
+void PlatformSensorManager::releaseBiasEvent(void *biasData) {
+  memoryFree(biasData);
+}
+
+void PlatformSensorManagerBase::onSamplingStatusUpdate(
+    uint8_t sensorType, const usf::UsfSensorSamplingEvent *update) {
+  uint32_t sensorHandle;
+  if (getSensorRequestManager().getSensorHandle(sensorType, &sensorHandle)) {
+    // Memory will be freed via releaseSamplingStatusUpdate once core framework
+    // performs its updates.
+    auto statusUpdate = MakeUniqueZeroFill<struct chreSensorSamplingStatus>();
+    if (statusUpdate.isNull()) {
+      LOG_OOM();
+    } else {
+      statusUpdate->interval = update->GetPeriodNs();
+      statusUpdate->latency = update->GetMaxLatencyNs();
+      statusUpdate->enabled = update->GetActive();
+      getSensorRequestManager().handleSamplingStatusUpdate(
+          sensorHandle, statusUpdate.release());
+    }
+  }
+}
+
+bool PlatformSensorManagerBase::getSensorInfo(uint8_t sensorType,
+                                              SensorInfo *sensorInfo) {
+  bool success = false;
+
+  if (getSensorRequestManager().getSensorHandle(sensorType,
+                                                &sensorInfo->sensorHandle)) {
+    Sensor *sensor =
+        getSensorRequestManager().getSensor(sensorInfo->sensorHandle);
+    if (sensor != nullptr && sensor->isSamplingIdValid()) {
+      success = true;
+      sensorInfo->samplingId = sensor->getSamplingId();
+    } else {
+      sensorInfo->sensorHandle = 0;
+    }
+  }
+  return success;
+}
+
+void PlatformSensorManagerBase::onSensorDataEvent(
+    uint8_t sensorType, UniquePtr<uint8_t> &&eventData) {
+  uint32_t sensorHandle;
+  if (getSensorRequestManager().getSensorHandle(sensorType, &sensorHandle)) {
+    Sensor *sensor = getSensorRequestManager().getSensor(sensorHandle);
+    // Invalidate the sampling ID for one shot sensors after they've fired since
+    // USF automatically removes the sampling ID from its list.
+    if (sensor->isOneShot()) {
+      sensor->setSamplingIdInvalid();
+    }
+
+    getSensorRequestManager().handleSensorDataEvent(sensorHandle,
+                                                    eventData.release());
+  }
+}
+
+void PlatformSensorManagerBase::onFlushComplete(usf::UsfErr err,
+                                                uint32_t requestId,
+                                                void *cookie) {
+  NestedDataPtr<uint32_t> nestedSensorType;
+  nestedSensorType.dataPtr = cookie;
+
+  uint32_t sensorHandle;
+  if (getSensorRequestManager().getSensorHandle(nestedSensorType.data,
+                                                &sensorHandle)) {
+    getSensorRequestManager().handleFlushCompleteEvent(
+        sensorHandle, requestId, UsfHelper::usfErrorToChreError(err));
+  }
+}
+
+void PlatformSensorManagerBase::onBiasUpdate(
+    uint8_t sensorType, UniquePtr<struct chreSensorThreeAxisData> &&eventData) {
+  uint32_t sensorHandle;
+  if (getSensorRequestManager().getSensorHandle(sensorType, &sensorHandle)) {
+    eventData->header.sensorHandle = sensorHandle;
+    getSensorRequestManager().handleBiasEvent(sensorHandle,
+                                              eventData.release());
+  }
+}
+
+void PlatformSensorManagerBase::addSensorsWithInfo(
+    refcount::reffed_ptr<usf::UsfSensor> &usfSensor,
+    DynamicVector<Sensor> *chreSensors) {
+  uint8_t sensorType;
+  if (PlatformSensorTypeHelpersBase::convertUsfToChreSensorType(
+          usfSensor->GetType(), &sensorType)) {
+    // Only register for a USF sensor once. If it maps to multiple sensors,
+    // code down the line will handle sending multiple updates.
+    if (!mHelper.registerForStatusUpdates(usfSensor)) {
+      LOGE("Failed to register for status updates for %s",
+           usfSensor->GetName());
+    }
+
+    addSensor(usfSensor, sensorType, chreSensors);
+
+    // USF shares the same sensor type for calibrated and uncalibrated sensors
+    // so populate a calibrated / uncalibrated sensor for known calibrated
+    // sensor types
+    uint8_t uncalibratedType =
+        SensorTypeHelpers::toUncalibratedSensorType(sensorType);
+    if (uncalibratedType != sensorType) {
+      addSensor(usfSensor, uncalibratedType, chreSensors);
+    }
+
+    // USF shares a sensor type for both gyro and accel temp.
+    if (sensorType == CHRE_SENSOR_TYPE_GYROSCOPE_TEMPERATURE) {
+      addSensor(usfSensor, CHRE_SENSOR_TYPE_ACCELEROMETER_TEMPERATURE,
+                chreSensors);
+    }
+  }
+}
+
+}  // namespace chre
diff --git a/platform/usf/platform_sensor_type_helpers.cc b/platform/usf/platform_sensor_type_helpers.cc
new file mode 100644
index 0000000..d1524ef
--- /dev/null
+++ b/platform/usf/platform_sensor_type_helpers.cc
@@ -0,0 +1,166 @@
+/*
+ * 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/platform/platform_sensor_type_helpers.h"
+#include "chre/target_platform/assert.h"
+
+#ifdef CHREX_SENSOR_SUPPORT
+#include "chre/extensions/platform/vendor_sensor_types.h"
+#endif  // CHREX_SENSOR_SUPPORT
+
+namespace chre {
+
+ReportingMode PlatformSensorTypeHelpers::getVendorSensorReportingMode(
+    uint8_t /* sensorType */) {
+  // TODO: Stubbed out, implement this
+  return ReportingMode::Continuous;
+}
+
+bool PlatformSensorTypeHelpers::getVendorSensorIsCalibrated(
+    uint8_t /* sensorType */) {
+  // TODO: Stubbed out, implement this
+  return false;
+}
+
+bool PlatformSensorTypeHelpers::getVendorSensorBiasEventType(
+    uint8_t /* sensorType */, uint16_t * /* eventType */) {
+  // TODO: Stubbed out, implement this
+  return false;
+}
+
+const char *PlatformSensorTypeHelpers::getVendorSensorTypeName(
+    uint8_t /* sensorType */) {
+  // TODO: Stubbed out, implement this
+  return "";
+}
+
+size_t PlatformSensorTypeHelpers::getVendorSensorLastEventSize(
+    uint8_t /* sensorType */) {
+  // TODO: Stubbed out, implement this
+  return 0;
+}
+
+void PlatformSensorTypeHelpers::getVendorLastSample(
+    uint8_t /* sensorType */, const ChreSensorData * /* event */,
+    ChreSensorData * /* lastEvent */) {
+  // TODO: Stubbed out, implement this
+}
+
+bool PlatformSensorTypeHelpersBase::reportsBias(uint8_t sensorType) {
+  switch (sensorType) {
+    case CHRE_SENSOR_TYPE_ACCELEROMETER:
+    case CHRE_SENSOR_TYPE_GYROSCOPE:
+    case CHRE_SENSOR_TYPE_GEOMAGNETIC_FIELD:
+    case CHRE_SENSOR_TYPE_UNCALIBRATED_ACCELEROMETER:
+    case CHRE_SENSOR_TYPE_UNCALIBRATED_GYROSCOPE:
+    case CHRE_SENSOR_TYPE_UNCALIBRATED_GEOMAGNETIC_FIELD:
+      return true;
+    default:
+      return false;
+  }
+}
+
+SensorSampleType
+PlatformSensorTypeHelpersBase::getSensorSampleTypeFromSensorType(
+    uint8_t sensorType) {
+  switch (sensorType) {
+    case CHRE_SENSOR_TYPE_ACCELEROMETER:
+    case CHRE_SENSOR_TYPE_GYROSCOPE:
+    case CHRE_SENSOR_TYPE_GEOMAGNETIC_FIELD:
+    case CHRE_SENSOR_TYPE_UNCALIBRATED_ACCELEROMETER:
+    case CHRE_SENSOR_TYPE_UNCALIBRATED_GYROSCOPE:
+    case CHRE_SENSOR_TYPE_UNCALIBRATED_GEOMAGNETIC_FIELD:
+      return SensorSampleType::ThreeAxis;
+    case CHRE_SENSOR_TYPE_PRESSURE:
+    case CHRE_SENSOR_TYPE_LIGHT:
+    case CHRE_SENSOR_TYPE_ACCELEROMETER_TEMPERATURE:
+    case CHRE_SENSOR_TYPE_GYROSCOPE_TEMPERATURE:
+    case CHRE_SENSOR_TYPE_GEOMAGNETIC_FIELD_TEMPERATURE:
+      return SensorSampleType::Float;
+    case CHRE_SENSOR_TYPE_INSTANT_MOTION_DETECT:
+    case CHRE_SENSOR_TYPE_STATIONARY_DETECT:
+    case CHRE_SENSOR_TYPE_STEP_DETECT:
+      return SensorSampleType::Occurrence;
+    case CHRE_SENSOR_TYPE_PROXIMITY:
+      return SensorSampleType::Byte;
+    default:
+#ifdef CHREX_SENSOR_SUPPORT
+      return extension::vendorSensorSampleTypeFromSensorType(sensorType);
+#else
+      // Update implementation to prevent undefined from being used.
+      CHRE_ASSERT(false);
+      return SensorSampleType::Unknown;
+#endif
+  }
+}
+
+usf::UsfSensorReportingMode PlatformSensorTypeHelpersBase::getUsfReportingMode(
+    ReportingMode mode) {
+  if (mode == ReportingMode::OnChange) {
+    return usf::kUsfSensorReportOnChange;
+  } else if (mode == ReportingMode::OneShot) {
+    return usf::kUsfSensorReportOneShot;
+  } else {
+    return usf::kUsfSensorReportContinuous;
+  }
+}
+
+bool PlatformSensorTypeHelpersBase::convertUsfToChreSensorType(
+    usf::UsfSensorType usfSensorType, uint8_t *chreSensorType) {
+  bool success = true;
+  switch (usfSensorType) {
+    case usf::UsfSensorType::kUsfSensorAccelerometer:
+      *chreSensorType = CHRE_SENSOR_TYPE_ACCELEROMETER;
+      break;
+    case usf::UsfSensorType::kUsfSensorGyroscope:
+      *chreSensorType = CHRE_SENSOR_TYPE_GYROSCOPE;
+      break;
+    case usf::UsfSensorType::kUsfSensorProx:
+      *chreSensorType = CHRE_SENSOR_TYPE_PROXIMITY;
+      break;
+    case usf::UsfSensorType::kUsfSensorBaro:
+      *chreSensorType = CHRE_SENSOR_TYPE_PRESSURE;
+      break;
+    case usf::UsfSensorType::kUsfSensorMag:
+      *chreSensorType = CHRE_SENSOR_TYPE_GEOMAGNETIC_FIELD;
+      break;
+    case usf::UsfSensorType::kUsfSensorMagTemp:
+      *chreSensorType = CHRE_SENSOR_TYPE_GEOMAGNETIC_FIELD_TEMPERATURE;
+      break;
+    case usf::UsfSensorType::kUsfSensorImuTemp:
+      *chreSensorType = CHRE_SENSOR_TYPE_GYROSCOPE_TEMPERATURE;
+      break;
+    case usf::UsfSensorType::kUsfSensorAmbientLight:
+      *chreSensorType = CHRE_SENSOR_TYPE_LIGHT;
+      break;
+    case usf::UsfSensorType::kUsfSensorMotionDetect:
+      *chreSensorType = CHRE_SENSOR_TYPE_INSTANT_MOTION_DETECT;
+      break;
+    case usf::UsfSensorType::kUsfSensorStationaryDetect:
+      *chreSensorType = CHRE_SENSOR_TYPE_STATIONARY_DETECT;
+      break;
+    case usf::UsfSensorType::kUsfSensorStepDetector:
+      *chreSensorType = CHRE_SENSOR_TYPE_STEP_DETECT;
+      break;
+    default:
+      // Don't print anything as USF exposes sensor types CHRE doesn't care
+      // about (e.g. Camera Vsync, and color)
+      success = false;
+      break;
+  }
+  return success;
+}
+
+}  // namespace chre
diff --git a/platform/usf/usf_helper.cc b/platform/usf/usf_helper.cc
new file mode 100644
index 0000000..45c1629
--- /dev/null
+++ b/platform/usf/usf_helper.cc
@@ -0,0 +1,656 @@
+/*
+ * 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/platform/usf/usf_helper.h"
+
+#include <cinttypes>
+
+#include "chre/core/sensor_type_helpers.h"
+#include "chre/util/macros.h"
+
+#include "usf/fbs/usf_msg_event_root_generated.h"
+#include "usf/fbs/usf_msg_sample_batch_root_generated.h"
+#include "usf/fbs/usf_msg_sensor_info_resp_root_generated.h"
+#include "usf/fbs/usf_msg_sensor_list_resp_root_generated.h"
+#include "usf/fbs/usf_msg_start_sampling_resp_root_generated.h"
+#include "usf/usf.h"
+#include "usf/usf_device.h"
+#include "usf/usf_flatbuffers.h"
+#include "usf/usf_sensor_defs.h"
+#include "usf/usf_sensor_mgr.h"
+#include "usf/usf_time.h"
+#include "usf/usf_work.h"
+
+using usf::UsfErr;
+using usf::UsfErr::kErrNone;
+
+#define LOG_USF_ERR(x) LOGE("USF failure %" PRIu8 ": line %d", x, __LINE__)
+
+namespace chre {
+namespace {
+
+//! Callback data delivered to async callback from USF. This struct must be
+//! freed using memoryFree.
+struct AsyncCallbackData {
+  UsfHelperCallbackInterface *callback;
+  void *cookie;
+};
+
+void eventHandler(void *context, usf::UsfEvent *event) {
+  const usf::UsfMsgEvent *msgEvent =
+      static_cast<usf::UsfTransportMsgEvent *>(event)->GetMsgEvent();
+
+  if (msgEvent != nullptr) {
+    auto *mgr = static_cast<UsfHelper *>(context);
+
+    switch (msgEvent->event_type()) {
+      case usf::UsfMsgEventType_kSample:
+        mgr->processSensorSample(msgEvent);
+        break;
+      default:
+        LOGD("Received unknown event type %" PRIu8, msgEvent->event_type());
+        break;
+    }
+  }
+}
+
+void statusUpdateHandler(void *context, usf::UsfEvent *event) {
+  const usf::UsfSensorSamplingEvent *updateEvent =
+      static_cast<usf::UsfSensorSamplingEvent *>(event);
+
+  if (updateEvent != nullptr) {
+    auto *mgr = static_cast<UsfHelper *>(context);
+    mgr->processStatusUpdate(updateEvent);
+  }
+}
+
+void biasUpdateHandler(void *context, usf::UsfEvent *event) {
+  const auto *updateEvent =
+      static_cast<usf::UsfSensorTransformConfigEvent *>(event);
+
+  if (updateEvent != nullptr) {
+    auto *mgr = static_cast<UsfHelper *>(context);
+    mgr->processBiasUpdate(updateEvent);
+  }
+}
+
+void asyncCallback(usf::UsfReq *req, const usf::UsfResp *resp, void *data) {
+  auto callbackData = static_cast<AsyncCallbackData *>(data);
+  callbackData->callback->onFlushComplete(resp->GetErr(), req->GetReqId(),
+                                          callbackData->cookie);
+
+  memoryFree(data);
+  memoryFree(req);
+}
+
+void *allocateEvent(uint8_t sensorType, size_t numSamples) {
+  SensorSampleType sampleType =
+      PlatformSensorTypeHelpers::getSensorSampleTypeFromSensorType(sensorType);
+  size_t sampleSize = 0;
+  switch (sampleType) {
+    case SensorSampleType::ThreeAxis:
+      sampleSize =
+          sizeof(chreSensorThreeAxisData::chreSensorThreeAxisSampleData);
+      break;
+    case SensorSampleType::Float:
+      sampleSize = sizeof(chreSensorFloatData::chreSensorFloatSampleData);
+      break;
+    case SensorSampleType::Byte:
+      sampleSize = sizeof(chreSensorByteData::chreSensorByteSampleData);
+      break;
+    case SensorSampleType::Occurrence:
+      sampleSize =
+          sizeof(chreSensorOccurrenceData::chreSensorOccurrenceSampleData);
+      break;
+    default:
+      LOGE("Unhandled SensorSampleType for SensorType %" PRIu8,
+           static_cast<uint8_t>(sensorType));
+      sampleType = SensorSampleType::Unknown;
+  }
+
+  size_t memorySize =
+      (sampleType == SensorSampleType::Unknown)
+          ? 0
+          : (sizeof(chreSensorDataHeader) + numSamples * sampleSize);
+  void *event = (memorySize == 0) ? nullptr : memoryAlloc(memorySize);
+
+  if (event == nullptr && memorySize != 0) {
+    LOG_OOM();
+  }
+  return event;
+}
+
+/**
+ * Allocates the memory and sets up the chreSensorDataHeader used to deliver
+ * the sensor samples to nanoapps.
+ *
+ * @param numSamples The number of samples there should be space for in the
+ *     sensor event
+ * @param sensorHandle The handle to the sensor that produced the events
+ * @param sensor The CHRE sensor instance for the sensor that produced the
+ *     events
+ * @param sensorSamples A non-null UniquePtr used to hold the sensor samples
+ * @return If successful, sensorSamples will point to valid memory that
+ *     contains a valid chreSensorDataHeader and enough space to store all
+ *     sensor samples
+ */
+bool prepareSensorEvent(size_t numSamples, uint32_t sensorHandle,
+                        uint8_t sensorType, UniquePtr<uint8_t> &sensorSamples) {
+  bool success = false;
+
+  UniquePtr<uint8_t> buf(
+      static_cast<uint8_t *>(allocateEvent(sensorType, numSamples)));
+  sensorSamples = std::move(buf);
+
+  if (!sensorSamples.isNull()) {
+    success = true;
+
+    auto *header =
+        reinterpret_cast<chreSensorDataHeader *>(sensorSamples.get());
+    header->sensorHandle = sensorHandle;
+    header->readingCount = numSamples;
+    // TODO(b/150308661): Populate this
+    header->accuracy = CHRE_SENSOR_ACCURACY_UNKNOWN;
+    header->reserved = 0;
+  }
+
+  return success;
+}
+
+/**
+ * Populates CHRE sensor sample structure using USF sensor samples.
+ *
+ * @param sampleMsg The USF message that contains sensor samples
+ * @param sensor The CHRE sensor instance for the sensor that produced the
+ *     events
+ * @param sensorSample Reference to a UniquePtr instance that points to non-null
+ *     memory that will be populated with sensor samples
+ */
+void populateSensorEvent(const usf::UsfMsgSampleBatch *sampleMsg,
+                         uint8_t sensorType, UniquePtr<uint8_t> &sensorSample) {
+  uint64_t prevSampleTimeNs = 0;
+
+  for (size_t i = 0; i < sampleMsg->sample_list()->size(); i++) {
+    const float *sensorVal =
+        sampleMsg->sample_list()->Get(i)->samples()->data();
+
+    SensorSampleType sampleType =
+        PlatformSensorTypeHelpers::getSensorSampleTypeFromSensorType(
+            sensorType);
+
+    uint32_t *timestampDelta = nullptr;
+    switch (sampleType) {
+      case SensorSampleType::ThreeAxis: {
+        auto *event =
+            reinterpret_cast<chreSensorThreeAxisData *>(sensorSample.get());
+
+        // TODO(b/143139477): Apply calibration to data from these sensors
+        for (size_t valIndex = 0; valIndex < 3; valIndex++) {
+          event->readings[i].values[valIndex] = sensorVal[valIndex];
+        }
+        timestampDelta = &event->readings[i].timestampDelta;
+        break;
+      }
+      case SensorSampleType::Float: {
+        auto *event =
+            reinterpret_cast<chreSensorFloatData *>(sensorSample.get());
+        event->readings[i].value = sensorVal[0];
+        timestampDelta = &event->readings[i].timestampDelta;
+        break;
+      }
+      case SensorSampleType::Byte: {
+        auto *event =
+            reinterpret_cast<chreSensorByteData *>(sensorSample.get());
+        event->readings[i].value = 0;
+        event->readings[i].isNear = (sensorVal[0] > 0.5f);
+        timestampDelta = &event->readings[i].timestampDelta;
+        break;
+      }
+      case SensorSampleType::Occurrence: {
+        // Occurrence samples don't store any readings
+        auto *event =
+            reinterpret_cast<chreSensorOccurrenceData *>(sensorSample.get());
+        timestampDelta = &event->readings[0].timestampDelta;
+        break;
+      }
+      default:
+        LOGE("Invalid sample type %" PRIu8, static_cast<uint8_t>(sampleType));
+    }
+
+    // First sample determines the base timestamp for all other sensor samples
+    uint64_t timestampNsHigh =
+        sampleMsg->sample_list()->Get(i)->timestamp_ns_hi();
+    uint64_t sampleTimestampNs =
+        (timestampNsHigh << 32) |
+        sampleMsg->sample_list()->Get(i)->timestamp_ns_lo();
+
+    if (i == 0) {
+      auto *header =
+          reinterpret_cast<chreSensorDataHeader *>(sensorSample.get());
+      header->baseTimestamp = sampleTimestampNs;
+      if (timestampDelta != nullptr) {
+        *timestampDelta = 0;
+      }
+    } else {
+      uint64_t delta = sampleTimestampNs - prevSampleTimeNs;
+      if (delta > UINT32_MAX) {
+        LOGE("Sensor %" PRIu8 " timestampDelta overflow: prev %" PRIu64
+             " curr %" PRIu64,
+             sensorType, prevSampleTimeNs, sampleTimestampNs);
+        delta = UINT32_MAX;
+      }
+      *timestampDelta = static_cast<uint32_t>(delta);
+    }
+
+    prevSampleTimeNs = sampleTimestampNs;
+  }
+}
+
+}  // namespace
+
+UsfHelper::~UsfHelper() {
+  deinit();
+}
+
+uint8_t UsfHelper::usfErrorToChreError(UsfErr err) {
+  switch (err) {
+    case UsfErr::kErrNone:
+      return CHRE_ERROR_NONE;
+    case UsfErr::kErrNotSupported:
+      return CHRE_ERROR_NOT_SUPPORTED;
+    case UsfErr::kErrMemAlloc:
+      return CHRE_ERROR_NO_MEMORY;
+    case UsfErr::kErrNotAvailable:
+      return CHRE_ERROR_BUSY;
+    case UsfErr::kErrTimedOut:
+      return CHRE_ERROR_TIMEOUT;
+    default:
+      return CHRE_ERROR;
+  }
+}
+
+void UsfHelper::init(UsfHelperCallbackInterface *callback,
+                     usf::UsfWorker *worker) {
+  usf::UsfDeviceMgr::GetDeviceProbeCompletePrecondition()->Wait();
+
+  UsfErr err = kErrNone;
+  if (worker != nullptr) {
+    mWorker.reset(worker, refcount::RefTakingMode::kCreate);
+  } else {
+    err = usf::UsfWorkMgr::CreateWorker(&mWorker);
+  }
+
+  if (!mUsfEventListeners.emplace_back()) {
+    LOG_OOM();
+    deinit();
+  } else if ((err != kErrNone) ||
+             ((err = usf::UsfTransportClient::Create(
+                   &mTransportClient, usf::kUsfHeapLowPower)) != kErrNone) ||
+             ((err = mTransportClient->Connect()) != kErrNone) ||
+             ((err = mTransportClient->GetMsgEventType()->AddListener(
+                   mWorker.get(), eventHandler, this,
+                   &mUsfEventListeners.back())) != kErrNone) ||
+             ((err = usf::UsfClientGetServer(mTransportClient.get(),
+                                             &usf::kUsfSensorMgrServerUuid,
+                                             &mSensorMgrHandle)) != kErrNone)) {
+    LOG_USF_ERR(err);
+    deinit();
+  } else {
+    mCallback = callback;
+  }
+}
+
+bool UsfHelper::getSensorList(
+    usf::UsfVector<refcount::reffed_ptr<usf::UsfSensor>> *sensorList) {
+  UsfErr err = usf::UsfSensorMgr::GetSensorList(sensorList);
+  if (err != kErrNone) {
+    LOG_USF_ERR(err);
+  }
+  return err == kErrNone;
+}
+
+void UsfHelper::deinit() {
+  for (usf::UsfEventListener *listener : mUsfEventListeners) {
+    listener->event_type->RemoveListener(listener);
+  }
+
+  if (mWorker.get() != nullptr) {
+    mWorker->Stop();
+    mWorker.reset();
+  }
+
+  if (mTransportClient.get() != nullptr) {
+    mTransportClient->Disconnect();
+    mTransportClient.reset();
+  }
+}
+
+bool UsfHelper::startSampling(usf::UsfStartSamplingReq *request,
+                              uint32_t *samplingId) {
+  bool success = false;
+
+  usf::UsfReqSyncCallback callback;
+  const usf::UsfMsgStartSamplingResp *resp;
+  if (sendUsfReqSync(request, &callback) && getRespMsg(callback, &resp)) {
+    *samplingId = resp->sampling_id();
+    success = true;
+  }
+
+  return success;
+}
+
+bool UsfHelper::reconfigureSampling(usf::UsfReconfigSamplingReq *request) {
+  usf::UsfReqSyncCallback callback;
+  return sendUsfReqSync(request, &callback);
+}
+
+bool UsfHelper::stopSampling(usf::UsfStopSamplingReq *request) {
+  usf::UsfReqSyncCallback callback;
+  return sendUsfReqSync(request, &callback);
+}
+
+bool UsfHelper::registerForStatusUpdates(
+    refcount::reffed_ptr<usf::UsfSensor> &sensor) {
+  bool success = false;
+  if (!mUsfEventListeners.emplace_back()) {
+    LOG_OOM();
+  } else {
+    UsfErr err = sensor->GetSamplingEventType()->AddListener(
+        mWorker.get(), statusUpdateHandler, this, &mUsfEventListeners.back());
+    success = (err == kErrNone);
+    if (!success) {
+      LOG_USF_ERR(err);
+    }
+  }
+
+  return success;
+}
+
+bool UsfHelper::registerForBiasUpdates(
+    const refcount::reffed_ptr<usf::UsfSensor> &sensor) {
+  // TODO(b/147595659): Obtain the latest bias values when registering for bias
+  // updates to ensure chreSensorGetThreeAxisBias doesn't return stale values.
+  bool success = false;
+  if (!mUsfEventListeners.emplace_back()) {
+    LOG_OOM();
+  } else {
+    UsfErr err = sensor->GetTransformConfigEventType()->AddListener(
+        mWorker.get(), biasUpdateHandler, this, &mUsfEventListeners.back());
+    success = (err == kErrNone);
+    if (!success) {
+      LOG_USF_ERR(err);
+    }
+  }
+
+  return success;
+}
+
+void UsfHelper::unregisterForBiasUpdates(
+    const refcount::reffed_ptr<usf::UsfSensor> &sensor) {
+  for (size_t i = 0; i < mUsfEventListeners.size(); i++) {
+    usf::UsfEventListener *listener = mUsfEventListeners[i];
+    if (listener->event_type.get() == sensor->GetTransformConfigEventType()) {
+      listener->event_type->RemoveListener(listener);
+      mUsfEventListeners.erase(i);
+      break;
+    }
+  }
+}
+
+bool UsfHelper::getThreeAxisBias(
+    const refcount::reffed_ptr<usf::UsfSensor> &sensor,
+    struct chreSensorThreeAxisData *bias) const {
+  bool success = false;
+  size_t index = getCalArrayIndex(sensor->GetType());
+  if (bias != nullptr && index < kNumUsfCalSensors) {
+    const UsfCalData &data = mCalData[index];
+    if (data.hasBias) {
+      bias->header.baseTimestamp = data.timestamp;
+      bias->header.readingCount = 1;
+      // TODO(150308661): Provide accuracy value
+      bias->header.reserved = 0;
+      for (size_t i = 0; i < ARRAY_SIZE(data.bias); i++) {
+        bias->readings[0].bias[i] = data.bias[i];
+      }
+      bias->readings[0].timestampDelta = 0;
+      success = true;
+    }
+  }
+
+  return success;
+}
+
+bool UsfHelper::flushAsync(const usf::UsfServerHandle usfSensorHandle,
+                           void *cookie, uint32_t *requestId) {
+  bool success = false;
+  auto req = MakeUnique<usf::UsfReq>();
+  auto callbackData = MakeUnique<AsyncCallbackData>();
+  if (req.isNull() || callbackData.isNull()) {
+    LOG_OOM();
+  } else {
+    req->SetReqType(usf::UsfMsgReqType_FLUSH_SAMPLES);
+    req->SetServerHandle(usfSensorHandle);
+    callbackData->callback = mCallback;
+    callbackData->cookie = cookie;
+
+    UsfErr err = mTransportClient->SendRequest(req.get(), asyncCallback,
+                                               callbackData.get());
+    success = (err == kErrNone);
+    if (!success) {
+      LOG_USF_ERR(err);
+    } else {
+      *requestId = req->GetReqId();
+      req.release();
+      callbackData.release();
+    }
+  }
+
+  return success;
+}
+
+void UsfHelper::processSensorSample(const usf::UsfMsgEvent *event) {
+  const usf::UsfMsgSampleBatch *sampleMsg;
+  UniquePtr<uint8_t> sensorSample;
+  uint8_t sensorType;
+
+  UsfErr err;
+  if ((err = usf::UsfMsgGet(event->data(), usf::GetUsfMsgSampleBatch,
+                            usf::VerifyUsfMsgSampleBatchBuffer, &sampleMsg)) !=
+      kErrNone) {
+    LOG_USF_ERR(err);
+  } else if (sampleMsg->sample_list()->size() == 0) {
+    LOGE("Received empty sample batch");
+  } else {
+    auto usfType = static_cast<usf::UsfSensorType>(sampleMsg->sensor_type());
+
+    if (PlatformSensorTypeHelpersBase::convertUsfToChreSensorType(
+            usfType, &sensorType) &&
+        !createSensorEvent(sampleMsg, sensorType, sensorSample)) {
+      // USF shares the same sensor type between calibrated and uncalibrated
+      // sensors. Try the uncalibrated type to see if the sampling ID matches.
+      uint8_t uncalType =
+          SensorTypeHelpers::toUncalibratedSensorType(sensorType);
+      if (uncalType != sensorType) {
+        sensorType = uncalType;
+        createSensorEvent(sampleMsg, uncalType, sensorSample);
+        // USF shares a sensor type for both gyro and accel temp.
+      } else if (sensorType == CHRE_SENSOR_TYPE_GYROSCOPE_TEMPERATURE) {
+        createSensorEvent(sampleMsg, CHRE_SENSOR_TYPE_ACCELEROMETER_TEMPERATURE,
+                          sensorSample);
+      }
+    }
+  }
+
+  if (!sensorSample.isNull() && mCallback != nullptr) {
+    mCallback->onSensorDataEvent(sensorType, std::move(sensorSample));
+  }
+}
+
+void UsfHelper::processStatusUpdate(const usf::UsfSensorSamplingEvent *update) {
+  // TODO(stange): See if the latest status can be shared among sensor types
+  // with the same underlying physical sensor to avoid allocating multiple
+  // updates.
+  uint8_t sensorType;
+  if (PlatformSensorTypeHelpersBase::convertUsfToChreSensorType(
+          update->GetSensor()->GetType(), &sensorType)) {
+    mCallback->onSamplingStatusUpdate(sensorType, update);
+
+    // USF shares the same sensor type for calibrated and uncalibrated sensors
+    // so populate a calibrated / uncalibrated sensor for known calibrated
+    // sensor types
+    uint8_t uncalibratedType =
+        SensorTypeHelpers::toUncalibratedSensorType(sensorType);
+    if (uncalibratedType != sensorType) {
+      mCallback->onSamplingStatusUpdate(uncalibratedType, update);
+    }
+
+    // USF shares a sensor type for both gyro and accel temp.
+    if (sensorType == CHRE_SENSOR_TYPE_GYROSCOPE_TEMPERATURE) {
+      mCallback->onSamplingStatusUpdate(
+          CHRE_SENSOR_TYPE_ACCELEROMETER_TEMPERATURE, update);
+    }
+  }
+}
+
+void UsfHelper::processBiasUpdate(
+    const usf::UsfSensorTransformConfigEvent *update) {
+  uint8_t sensorType;
+  if (PlatformSensorTypeHelpersBase::convertUsfToChreSensorType(
+          update->GetSensor()->GetType(), &sensorType)) {
+    UniquePtr<struct chreSensorThreeAxisData> biasData =
+        convertUsfBiasUpdateToData(update);
+    if (!biasData.isNull()) {
+      // USF shares the same sensor type for calibrated and uncalibrated sensors
+      // so populate a calibrated / uncalibrated sensor for known calibrated
+      // sensor types
+      uint8_t uncalibratedType =
+          SensorTypeHelpers::toUncalibratedSensorType(sensorType);
+      if (uncalibratedType != sensorType) {
+        auto uncalBiasData =
+            MakeUniqueZeroFill<struct chreSensorThreeAxisData>();
+        if (uncalBiasData.isNull()) {
+          LOG_OOM();
+        } else {
+          *uncalBiasData = *biasData;
+          mCallback->onBiasUpdate(uncalibratedType, std::move(uncalBiasData));
+        }
+      }
+      mCallback->onBiasUpdate(sensorType, std::move(biasData));
+    }
+  }
+}
+
+bool UsfHelper::createSensorEvent(const usf::UsfMsgSampleBatch *sampleMsg,
+                                  uint8_t sensorType,
+                                  UniquePtr<uint8_t> &sensorSample) {
+  bool success = false;
+
+  SensorInfo info;
+  if (mCallback != nullptr && mCallback->getSensorInfo(sensorType, &info) &&
+      (info.samplingId == sampleMsg->sampling_id())) {
+    if (prepareSensorEvent(sampleMsg->sample_list()->size(), info.sensorHandle,
+                           sensorType, sensorSample)) {
+      populateSensorEvent(sampleMsg, sensorType, sensorSample);
+      success = true;
+    }
+  }
+
+  return success;
+}
+
+bool UsfHelper::sendUsfReqSync(usf::UsfReq *req,
+                               usf::UsfReqSyncCallback *callback) {
+  UsfErr err = mTransportClient->SendRequest(
+      req, usf::UsfReqSyncCallback::Callback, callback);
+  if (err != kErrNone) {
+    LOG_USF_ERR(err);
+  } else {
+    // TODO: Provide a different timeout for operations we expect to take longer
+    // e.g. initial sensor discovery.
+    callback->Wait(kDefaultUsfWaitTimeout.toRawNanoseconds());
+    if ((err = callback->GetResp()->GetErr()) != kErrNone) {
+      LOG_USF_ERR(err);
+    }
+  }
+
+  return err == kErrNone;
+}
+
+template <class T>
+bool UsfHelper::getRespMsg(usf::UsfReqSyncCallback &callback,
+                           const T **respMsg) {
+  UsfErr err = usf::UsfRespGetMsg(callback.GetResp(), respMsg);
+  if (err != kErrNone) {
+    LOG_USF_ERR(err);
+  }
+
+  return err == kErrNone;
+}
+
+UniquePtr<struct chreSensorThreeAxisData> UsfHelper::convertUsfBiasUpdateToData(
+    const usf::UsfSensorTransformConfigEvent *update) {
+  UniquePtr<struct chreSensorThreeAxisData> biasData;
+  size_t index = getCalArrayIndex(update->GetSensor()->GetType());
+  if (index < kNumUsfCalSensors) {
+    UsfCalData &data = mCalData[index];
+    UsfErr err = usf::UsfTimeMgr::GetAndroidTimeNs(&data.timestamp);
+    if (err != kErrNone) {
+      LOG_USF_ERR(err);
+    }
+    data.hasBias = true;
+    for (size_t i = 0; i < ARRAY_SIZE(data.bias); i++) {
+      data.bias[i] = update->GetOffset()[i];
+    }
+
+    biasData = MakeUniqueZeroFill<struct chreSensorThreeAxisData>();
+    if (biasData.isNull()) {
+      LOG_OOM();
+    } else {
+      biasData->header.baseTimestamp = data.timestamp;
+      biasData->header.readingCount = 1;
+      // TODO(150308661): Provide accuracy value
+      biasData->header.reserved = 0;
+      for (size_t i = 0; i < ARRAY_SIZE(data.bias); i++) {
+        biasData->readings[0].bias[i] = data.bias[i];
+      }
+      biasData->readings[0].timestampDelta = 0;
+    }
+  }
+
+  return biasData;
+}
+
+size_t UsfHelper::getCalArrayIndex(const usf::UsfSensorType usfSensorType) {
+  UsfCalSensor index;
+  switch (usfSensorType) {
+    case usf::UsfSensorType::kUsfSensorAccelerometer:
+      index = UsfCalSensor::AccelCal;
+      break;
+    case usf::UsfSensorType::kUsfSensorGyroscope:
+      index = UsfCalSensor::GyroCal;
+      break;
+    case usf::UsfSensorType::kUsfSensorMag:
+      index = UsfCalSensor::MagCal;
+      break;
+    default:
+      index = UsfCalSensor::NumCalSensors;
+      break;
+  }
+
+  return static_cast<size_t>(index);
+}
+
+}  // namespace chre
diff --git a/util/include/chre/util/macros.h b/util/include/chre/util/macros.h
index 92160b8..8a87050 100644
--- a/util/include/chre/util/macros.h
+++ b/util/include/chre/util/macros.h
@@ -24,14 +24,21 @@
 /**
  * Obtains the number of elements in a C-style array.
  */
+#ifndef ARRAY_SIZE
 #define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
+#endif
+
+#ifndef ARRAY_END
 #define ARRAY_END(array) (array + ARRAY_SIZE(array))
+#endif
 
 /**
  * Performs macro expansion then converts the value into a string literal
  */
+#ifndef STRINGIFY
 #define STRINGIFY(x) STRINGIFY2(x)
 #define STRINGIFY2(x) #x
+#endif
 
 // Compiler-specific functionality
 #if defined(__clang__) || defined(__GNUC__)