Deduces function signature in thunk

This has been a dream of mine for years. I wanted to remove the explicit
function signatures from day one, but with c++0x it just wasn't
possible. Today, we realize a newer C++, and a brighter world.

Test: build and boot pie
Change-Id: I183be73ece7b6d39630b25ef8fa1f5d4f5a15a2d
diff --git a/common/libs/threads/Android.bp b/common/libs/threads/Android.bp
index dece9ae..7c89060 100644
--- a/common/libs/threads/Android.bp
+++ b/common/libs/threads/Android.bp
@@ -22,5 +22,6 @@
         "cuttlefish_time",
         "libbase",
     ],
+    cpp_std: "c++17",
     defaults: ["cuttlefish_host_only"],
 }
diff --git a/common/libs/threads/cuttlefish_thread_test.cpp b/common/libs/threads/cuttlefish_thread_test.cpp
index 513262e..e63d60c 100644
--- a/common/libs/threads/cuttlefish_thread_test.cpp
+++ b/common/libs/threads/cuttlefish_thread_test.cpp
@@ -52,10 +52,8 @@
 
   void Run() {
     {
-      ScopedThread thread_a(
-          MutexTestThunker<void*()>::call<&MutexTest::FastThread>, this);
-      ScopedThread thread_b(
-          MutexTestThunker<void*()>::call<&MutexTest::SlowThread>, this);
+      ScopedThread thread_a(cvd::thunk<void, &MutexTest::FastThread>, this);
+      ScopedThread thread_b(cvd::thunk<void, &MutexTest::SlowThread>, this);
     }
     LOG(INFO) << "MutexTest: completed at stage "
               << stage_
@@ -64,9 +62,6 @@
   }
 
 protected:
-  template <typename F> struct MutexTestThunker :
-  ThunkerBase<void, MutexTest, F>{};
-
   void* FastThread() {
     mutex_.Lock();
     CHECK(busy_ == NULL);
@@ -111,11 +106,11 @@
   void Run() {
     {
       ScopedThread thread_s(
-          Thunker<void*()>::call<&NotifyOneTest::SignalThread>, this);
+          cvd::thunk<void, &NotifyOneTest::SignalThread>, this);
       ScopedThread thread_w1(
-          Thunker<void*()>::call<&NotifyOneTest::WaitThread>, this);
+          cvd::thunk<void, &NotifyOneTest::WaitThread>, this);
       ScopedThread thread_w2(
-          Thunker<void*()>::call<&NotifyOneTest::WaitThread>, this);
+          cvd::thunk<void, &NotifyOneTest::WaitThread>, this);
     }
     LOG(INFO) << "NotifyOneTest: completed, signalled "
               << signalled_
@@ -124,9 +119,6 @@
   }
 
 protected:
-  template <typename F> struct Thunker :
-  ThunkerBase<void, NotifyOneTest, F>{};
-
   void* SignalThread() {
     SleepUntil(MonotonicTimePoint::Now() + Milliseconds(100));
     mutex_.Lock();
@@ -164,20 +156,17 @@
   void Run() {
     {
       ScopedThread thread_s(
-          Thunker<void*()>::call<&NotifyAllTest::SignalThread>, this);
+          cvd::thunk<void, &NotifyAllTest::SignalThread>, this);
       ScopedThread thread_w1(
-          Thunker<void*()>::call<&NotifyAllTest::WaitThread>, this);
+          cvd::thunk<void, &NotifyAllTest::WaitThread>, this);
       ScopedThread thread_w2(
-          Thunker<void*()>::call<&NotifyAllTest::WaitThread>, this);
+          cvd::thunk<void, &NotifyAllTest::WaitThread>, this);
     }
     printf("NotifyAllTest: completed, signalled %d (%s)\n",
            signalled_, (signalled_ == 2) ? "PASSED" : "FAILED");
   }
 
 protected:
-  template <typename F> struct Thunker :
-  ThunkerBase<void, NotifyAllTest, F>{};
-
   void* SignalThread() {
     SleepUntil(MonotonicTimePoint::Now() + Milliseconds(100));
     mutex_.Lock();
@@ -211,18 +200,15 @@
     start_ = MonotonicTimePoint::Now();
     {
       ScopedThread thread_s(
-          Thunker<void*()>::call<&WaitUntilTest::SignalThread>, this);
+          cvd::thunk<void, &WaitUntilTest::SignalThread>, this);
       ScopedThread thread_w2(
-          Thunker<void*()>::call<&WaitUntilTest::WaitThread>, this);
+          cvd::thunk<void, &WaitUntilTest::WaitThread>, this);
     }
     printf("WaitUntilTest: completed, stage %d (%s)\n",
            stage_, (stage_ == FINISHED) ? "PASSED" : "FAILED");
   }
 
 protected:
-  template <typename F> struct Thunker :
-  ThunkerBase<void, WaitUntilTest, F>{};
-
   void* SignalThread() {
     SleepUntil(start_ + Milliseconds(200));
     mutex_.Lock();
diff --git a/common/libs/threads/thunkers.h b/common/libs/threads/thunkers.h
index e935b6a..bb97174 100644
--- a/common/libs/threads/thunkers.h
+++ b/common/libs/threads/thunkers.h
@@ -16,20 +16,39 @@
 #ifndef CUTTLEFISH_COMMON_COMMON_LIBS_THREADS_THUNKERS_H_
 #define CUTTLEFISH_COMMON_COMMON_LIBS_THREADS_THUNKERS_H_
 
-template <typename HalType, typename Impl, typename F>
-struct ThunkerBase;
+namespace cvd {
+namespace internal {
+
+template <typename HalType, typename F>
+struct ThunkerImpl;
 
 template <typename HalType, typename Impl, typename R, typename... Args>
-struct ThunkerBase<HalType, Impl, R(Args...)> {
+struct ThunkerImpl<HalType, R (Impl::*)(Args...)> {
   template <R (Impl::*MemFn)(Args...)>
   static R call(HalType* in, Args... args) {
     return (reinterpret_cast<Impl*>(in)->*MemFn)(args...);
   }
+};
 
+template <typename HalType, typename Impl, typename R, typename... Args>
+struct ThunkerImpl<HalType, R (Impl::*)(Args...) const> {
   template <R (Impl::*MemFn)(Args...) const>
   static R call(const HalType* in, Args... args) {
     return (reinterpret_cast<const Impl*>(in)->*MemFn)(args...);
   }
 };
 
+template <typename HalType, auto MemFunc>
+struct Thunker {
+  static constexpr auto call =
+      ThunkerImpl<HalType, decltype(MemFunc)>::template call<MemFunc>;
+};
+
+}  // namespace internal
+
+template <typename HalType, auto MemFunc>
+constexpr auto thunk = internal::Thunker<HalType, MemFunc>::call;
+
+}  // namespace cvd
+
 #endif
diff --git a/guest/hals/audio/Android.mk b/guest/hals/audio/Android.mk
index 3af6e0f..dab1bcd 100644
--- a/guest/hals/audio/Android.mk
+++ b/guest/hals/audio/Android.mk
@@ -55,7 +55,7 @@
     $(VSOC_STLPORT_STATIC_LIBS)
 
 LOCAL_CFLAGS := \
-    -Wall -Werror \
+    -Wall -Werror -std=c++17 \
     $(VSOC_VERSION_CFLAGS)
 
 
diff --git a/guest/hals/audio/vsoc_audio.cpp b/guest/hals/audio/vsoc_audio.cpp
index 38352ff..9386c6a 100644
--- a/guest/hals/audio/vsoc_audio.cpp
+++ b/guest/hals/audio/vsoc_audio.cpp
@@ -41,15 +41,6 @@
 
 namespace cvd {
 
-namespace {
-template <typename F> struct HWDeviceThunker :
-  ThunkerBase<hw_device_t, GceAudio, F>{};
-template <typename F> struct AudioThunker :
-  ThunkerBase<audio_hw_device, GceAudio, F>{};
-template <typename F> struct AudioThreadThunker :
-  ThunkerBase<void, GceAudio, F>{};
-}
-
 GceAudio::~GceAudio() { }
 
 int GceAudio::Close() {
@@ -299,7 +290,7 @@
   rval->common.tag = HARDWARE_DEVICE_TAG;
   rval->common.version = version_;
   rval->common.module = const_cast<hw_module_t *>(module);
-  rval->common.close = HWDeviceThunker<int()>::call<&GceAudio::Close>;
+  rval->common.close = cvd::thunk<hw_device_t, &GceAudio::Close>;
 
 #if !defined(AUDIO_DEVICE_API_VERSION_2_0)
   // This HAL entry is supported only on AUDIO_DEVICE_API_VERSION_1_0.
@@ -308,51 +299,45 @@
   // Skipping the assignment is ok: the memset in the constructor already
   // put a NULL here.
   rval->get_supported_devices =
-      AudioThunker<uint32_t()>::call<&GceAudio::GetSupportedDevices>;
+      cvd::thunk<audio_hw_device, &GceAudio::GetSupportedDevices>;
 #endif
-  rval->init_check = AudioThunker<int()>::call<&GceAudio::InitCheck>;
+  rval->init_check = cvd::thunk<audio_hw_device, &GceAudio::InitCheck>;
 
   rval->set_voice_volume =
-      AudioThunker<int(float)>::call<&GceAudio::SetVoiceVolume>;
+      cvd::thunk<audio_hw_device, &GceAudio::SetVoiceVolume>;
   rval->set_master_volume =
-      AudioThunker<int(float)>::call<&GceAudio::SetMasterVolume>;
+      cvd::thunk<audio_hw_device, &GceAudio::SetMasterVolume>;
   rval->get_master_volume =
-      AudioThunker<int(float*)>::call<&GceAudio::GetMasterVolume>;
+      cvd::thunk<audio_hw_device, &GceAudio::GetMasterVolume>;
 
 #if defined(AUDIO_DEVICE_API_VERSION_2_0)
   rval->set_master_mute =
-      AudioThunker<int(bool)>::call<&GceAudio::SetMasterMute>;
+      cvd::thunk<audio_hw_device, &GceAudio::SetMasterMute>;
   rval->get_master_mute =
-      AudioThunker<int(bool*)>::call<&GceAudio::GetMasterMute>;
+      cvd::thunk<audio_hw_device, &GceAudio::GetMasterMute>;
 #endif
 
-  rval->set_mode = AudioThunker<int(audio_mode_t)>::call<&GceAudio::SetMode>;
-  rval->set_mic_mute = AudioThunker<int(bool)>::call<&GceAudio::SetMicMute>;
-  rval->get_mic_mute =
-      AudioThunker<int(bool*)>::call<&GceAudio::GetMicMute>;
+  rval->set_mode = cvd::thunk<audio_hw_device, &GceAudio::SetMode>;
+  rval->set_mic_mute = cvd::thunk<audio_hw_device, &GceAudio::SetMicMute>;
+  rval->get_mic_mute = cvd::thunk<audio_hw_device, &GceAudio::GetMicMute>;
 
-  rval->set_parameters =
-      AudioThunker<int(const char*)>::call<&GceAudio::SetParameters>;
-  rval->get_parameters =
-      AudioThunker<char*(const char*)>::call<&GceAudio::GetParameters>;
+  rval->set_parameters = cvd::thunk<audio_hw_device, &GceAudio::SetParameters>;
+  rval->get_parameters = cvd::thunk<audio_hw_device, &GceAudio::GetParameters>;
 
   rval->get_input_buffer_size =
-      AudioThunker<size_t(const audio_config*)>::call<
-        &GceAudio::GetInputBufferSize>;
+      cvd::thunk<audio_hw_device, &GceAudio::GetInputBufferSize>;
 
   rval->open_input_stream =
-      AudioThunker<GceAudio::OpenInputStreamHAL_t>::call<
-        &GceAudio::OpenInputStreamCurrentHAL>;
+      cvd::thunk<audio_hw_device, &GceAudio::OpenInputStreamCurrentHAL>;
   rval->close_input_stream =
-      AudioThunker<void(audio_stream_in*)>::call<&GceAudio::CloseInputStream>;
+      cvd::thunk<audio_hw_device, &GceAudio::CloseInputStream>;
 
   rval->open_output_stream =
-      AudioThunker<GceAudio::OpenOutputStreamHAL_t>::call<
-        &GceAudio::OpenOutputStreamCurrentHAL>;
+      cvd::thunk<audio_hw_device, &GceAudio::OpenOutputStreamCurrentHAL>;
   rval->close_output_stream =
-      AudioThunker<void(audio_stream_out*)>::call<&GceAudio::CloseOutputStream>;
+      cvd::thunk<audio_hw_device, &GceAudio::CloseOutputStream>;
 
-  rval->dump = AudioThunker<int(int)>::call<&GceAudio::Dump>;
+  rval->dump = cvd::thunk<audio_hw_device, &GceAudio::Dump>;
 
   *device = &rval->common;
   return 0;
diff --git a/guest/hals/audio/vsoc_audio_input_stream.cpp b/guest/hals/audio/vsoc_audio_input_stream.cpp
index 4c91237..4ed2c9a 100644
--- a/guest/hals/audio/vsoc_audio_input_stream.cpp
+++ b/guest/hals/audio/vsoc_audio_input_stream.cpp
@@ -32,13 +32,6 @@
 
 namespace cvd {
 
-namespace {
-template <typename F> struct Thunker :
-  ThunkerBase<audio_stream, GceAudioInputStream, F>{};
-template <typename F> struct InThunker :
-  ThunkerBase<audio_stream_in, GceAudioInputStream, F>{};
-}
-
 #if defined(AUDIO_DEVICE_API_VERSION_3_0)
 static inline size_t GceAudioFrameSize(const audio_stream_in* s) {
   return audio_stream_in_frame_size(s);
@@ -63,36 +56,30 @@
       gain_(0.0),
       device_(devices) {
   common.get_sample_rate =
-      Thunker<uint32_t()>::call<&GceAudioInputStream::GetSampleRate>;
+      cvd::thunk<audio_stream, &GceAudioInputStream::GetSampleRate>;
   common.set_sample_rate =
-      Thunker<int(uint32_t)>::call<&GceAudioInputStream::SetSampleRate>;
+      cvd::thunk<audio_stream, &GceAudioInputStream::SetSampleRate>;
   common.get_buffer_size =
-      Thunker<size_t()>::call<&GceAudioInputStream::GetBufferSize>;
+      cvd::thunk<audio_stream, &GceAudioInputStream::GetBufferSize>;
   common.get_channels =
-      Thunker<audio_channel_mask_t()>::call<&GceAudioInputStream::GetChannels>;
-  common.get_device =
-      Thunker<audio_devices_t()>::call<&GceAudioInputStream::GetDevice>;
-  common.set_device =
-      Thunker<int(audio_devices_t)>::call<&GceAudioInputStream::SetDevice>;
-  common.get_format =
-      Thunker<audio_format_t()>::call<&GceAudioInputStream::GetFormat>;
-  common.set_format =
-      Thunker<int(audio_format_t)>::call<&GceAudioInputStream::SetFormat>;
-  common.standby =
-      Thunker<int()>::call<&GceAudioInputStream::Standby>;
-  common.dump =
-      Thunker<int(int)>::call<&GceAudioInputStream::Dump>;
+      cvd::thunk<audio_stream, &GceAudioInputStream::GetChannels>;
+  common.get_device = cvd::thunk<audio_stream, &GceAudioInputStream::GetDevice>;
+  common.set_device = cvd::thunk<audio_stream, &GceAudioInputStream::SetDevice>;
+  common.get_format = cvd::thunk<audio_stream, &GceAudioInputStream::GetFormat>;
+  common.set_format = cvd::thunk<audio_stream, &GceAudioInputStream::SetFormat>;
+  common.standby = cvd::thunk<audio_stream, &GceAudioInputStream::Standby>;
+  common.dump = cvd::thunk<audio_stream, &GceAudioInputStream::Dump>;
   common.set_parameters = GceAudio::SetStreamParameters;
   common.get_parameters =
-      Thunker<char*(const char *)>::call<&GceAudioInputStream::GetParameters>;
+      cvd::thunk<audio_stream, &GceAudioInputStream::GetParameters>;
   common.add_audio_effect =
-      Thunker<int(effect_handle_t)>::call<&GceAudioInputStream::AddAudioEffect>;
-  common.remove_audio_effect = Thunker<int(effect_handle_t)>::call<
+      cvd::thunk<audio_stream, &GceAudioInputStream::AddAudioEffect>;
+  common.remove_audio_effect = cvd::thunk<audio_stream,
     &GceAudioInputStream::RemoveAudioEffect>;
-  set_gain = InThunker<int(float)>::call<&GceAudioInputStream::SetGain>;
-  read = InThunker<ssize_t(void*, size_t)>::call<
+  set_gain = cvd::thunk<audio_stream_in, &GceAudioInputStream::SetGain>;
+  read = cvd::thunk<audio_stream_in,
     &GceAudioInputStream::Read>;
-  get_input_frames_lost = InThunker<uint32_t()>::call<
+  get_input_frames_lost = cvd::thunk<audio_stream_in,
     &GceAudioInputStream::GetInputFramesLost>;
   frame_size_ = GceAudioFrameSize(this);
   buffer_model_.reset(
diff --git a/guest/hals/audio/vsoc_audio_output_stream.cpp b/guest/hals/audio/vsoc_audio_output_stream.cpp
index b78351e..39a8fc7 100644
--- a/guest/hals/audio/vsoc_audio_output_stream.cpp
+++ b/guest/hals/audio/vsoc_audio_output_stream.cpp
@@ -53,14 +53,6 @@
 const size_t GceAudioOutputStream::kOutBufferSize;
 const size_t GceAudioOutputStream::kOutLatency;
 
-namespace {
-template <typename F> struct Thunker :
-  ThunkerBase<audio_stream, GceAudioOutputStream, F>{};
-
-template <typename F> struct OutThunker :
-  ThunkerBase<audio_stream_out, GceAudioOutputStream, F>{};
-}
-
 GceAudioOutputStream::GceAudioOutputStream(GceAudio* dev) :
     audio_stream_out(),
     dev_(dev),
@@ -285,50 +277,38 @@
       0;
 #endif
   out->common.get_sample_rate =
-      Thunker<uint32_t()>::call<&GceAudioOutputStream::GetSampleRate>;
+      cvd::thunk<audio_stream, &GceAudioOutputStream::GetSampleRate>;
   out->common.set_sample_rate =
-      Thunker<int(uint32_t)>::call<&GceAudioOutputStream::SetSampleRate>;
+      cvd::thunk<audio_stream, &GceAudioOutputStream::SetSampleRate>;
   out->common.get_buffer_size =
-      Thunker<size_t()>::call<&GceAudioOutputStream::GetBufferSize>;
+      cvd::thunk<audio_stream, &GceAudioOutputStream::GetBufferSize>;
   out->common.get_channels =
-      Thunker<audio_channel_mask_t()>::call<
-        &GceAudioOutputStream::GetChannels>;
-  out->common.get_format = Thunker<audio_format_t()>::call<
-    &GceAudioOutputStream::GetFormat>;
-  out->common.set_format = Thunker<int(audio_format_t)>::call<
-    &GceAudioOutputStream::SetFormat>;
-  out->common.standby = Thunker<int()>::call<&GceAudioOutputStream::Standby>;
-  out->common.dump = Thunker<int(int)>::call<&GceAudioOutputStream::Dump>;
-  out->common.get_device = Thunker<audio_devices_t()>::call<
-    &GceAudioOutputStream::GetDevice>;
-  out->common.set_device = Thunker<int(audio_devices_t)>::call<
-    &GceAudioOutputStream::SetDevice>;
+      cvd::thunk<audio_stream, &GceAudioOutputStream::GetChannels>;
+  out->common.get_format = cvd::thunk<audio_stream, &GceAudioOutputStream::GetFormat>;
+  out->common.set_format = cvd::thunk<audio_stream, &GceAudioOutputStream::SetFormat>;
+  out->common.standby = cvd::thunk<audio_stream, &GceAudioOutputStream::Standby>;
+  out->common.dump = cvd::thunk<audio_stream, &GceAudioOutputStream::Dump>;
+  out->common.get_device = cvd::thunk<audio_stream, &GceAudioOutputStream::GetDevice>;
+  out->common.set_device = cvd::thunk<audio_stream, &GceAudioOutputStream::SetDevice>;
   out->common.set_parameters =
-      Thunker<int(const char*)>::call<
-      &GceAudioOutputStream::SetParameters>;
+      cvd::thunk<audio_stream, &GceAudioOutputStream::SetParameters>;
   out->common.get_parameters =
-      Thunker<char*(const char *)>::call<
-        &GceAudioOutputStream::GetParameters>;
+      cvd::thunk<audio_stream, &GceAudioOutputStream::GetParameters>;
   out->common.add_audio_effect =
-      Thunker<int(effect_handle_t)>::call<
-        &GceAudioOutputStream::AddAudioEffect>;
+      cvd::thunk<audio_stream, &GceAudioOutputStream::AddAudioEffect>;
   out->common.remove_audio_effect =
-      Thunker<int(effect_handle_t)>::call<
-        &GceAudioOutputStream::RemoveAudioEffect>;
+      cvd::thunk<audio_stream, &GceAudioOutputStream::RemoveAudioEffect>;
+
   out->get_latency =
-      OutThunker<uint32_t()>::call<
-        &GceAudioOutputStream::GetLatency>;
+      cvd::thunk<audio_stream_out, &GceAudioOutputStream::GetLatency>;
   out->set_volume =
-      OutThunker<int(float, float)>::call<&GceAudioOutputStream::SetVolume>;
+      cvd::thunk<audio_stream_out, &GceAudioOutputStream::SetVolume>;
   out->write =
-      OutThunker<ssize_t(const void*, size_t)>::call<
-        &GceAudioOutputStream::Write>;
+      cvd::thunk<audio_stream_out, &GceAudioOutputStream::Write>;
   out->get_render_position =
-      OutThunker<int(uint32_t*)>::call<
-        &GceAudioOutputStream::GetRenderPosition>;
+      cvd::thunk<audio_stream_out, &GceAudioOutputStream::GetRenderPosition>;
   out->get_next_write_timestamp =
-      OutThunker<int(int64_t*)>::call<
-        &GceAudioOutputStream::GetNextWriteTimestamp>;
+      cvd::thunk<audio_stream_out, &GceAudioOutputStream::GetNextWriteTimestamp>;
   out->device_ = devices;
   out->frame_size_ = GceAudioFrameSize(out.get());
 
diff --git a/guest/hals/sensors/Android.mk b/guest/hals/sensors/Android.mk
index 8dd8a52..cdef117 100644
--- a/guest/hals/sensors/Android.mk
+++ b/guest/hals/sensors/Android.mk
@@ -44,6 +44,7 @@
 
 LOCAL_CFLAGS := -DLOG_TAG=\"VSoC-Sensors\" \
     $(VSOC_VERSION_CFLAGS) \
+    -std=c++17 \
     -Werror -Wall -Wno-missing-field-initializers -Wno-unused-parameter
 
 LOCAL_C_INCLUDES := \
diff --git a/guest/hals/sensors/vsoc_sensors.cpp b/guest/hals/sensors/vsoc_sensors.cpp
index 86809a0..336cd65 100644
--- a/guest/hals/sensors/vsoc_sensors.cpp
+++ b/guest/hals/sensors/vsoc_sensors.cpp
@@ -40,17 +40,6 @@
 
 namespace cvd {
 
-namespace {
-template <typename F>
-struct HWDeviceThunker : ThunkerBase<hw_device_t, GceSensors, F> {};
-template <typename F>
-struct SensorsThunker : ThunkerBase<sensors_poll_device_t, GceSensors, F> {};
-template <typename F>
-struct SensorsThunker1 : ThunkerBase<sensors_poll_device_1, GceSensors, F> {};
-template <typename F>
-struct SensorsThreadThunker : ThunkerBase<void, GceSensors, F> {};
-}
-
 int GceSensors::total_sensor_count_ = -1;
 SensorInfo* GceSensors::sensor_infos_ = NULL;
 const int GceSensors::kInjectedEventWaitPeriods = 3;
@@ -111,28 +100,28 @@
     rval->common.tag = HARDWARE_DEVICE_TAG;
     rval->common.version = VSOC_SENSOR_DEVICE_VERSION;
     rval->common.module = (struct hw_module_t*)module;
-    rval->common.close = HWDeviceThunker<int()>::call<&GceSensors::Close>;
-    rval->poll =
-        SensorsThunker<int(sensors_event_t*, int)>::call<&GceSensors::Poll>;
-    rval->activate = SensorsThunker<int(int, int)>::call<&GceSensors::Activate>;
-    rval->setDelay =
-        SensorsThunker<int(int, int64_t)>::call<&GceSensors::SetDelay>;
+    rval->common.close = cvd::thunk<hw_device_t, &GceSensors::Close>;
+
+    rval->poll = cvd::thunk<sensors_poll_device_t, &GceSensors::Poll>;
+    rval->activate = cvd::thunk<sensors_poll_device_t, &GceSensors::Activate>;
+    rval->setDelay = cvd::thunk<sensors_poll_device_t, &GceSensors::SetDelay>;
 #if VSOC_SENSORS_DEVICE_API_VERSION_ATLEAST(1_0)
-    rval->batch = SensorsThunker1<int(int, int, int64_t,
-                                      int64_t)>::call<&GceSensors::Batch>;
+
+    rval->batch = cvd::thunk<sensors_poll_device_1, &GceSensors::Batch>;
 #endif
 #if VSOC_SENSORS_DEVICE_API_VERSION_ATLEAST(1_1)
-    rval->flush = SensorsThunker1<int(int)>::call<&GceSensors::Flush>;
+    rval->flush = cvd::thunk<sensors_poll_device_1, &GceSensors::Flush>;
 #endif
 #if VSOC_SENSORS_DEVICE_API_VERSION_ATLEAST(1_4)
-    rval->inject_sensor_data = SensorsThunker1<int(
-        const sensors_event_t*)>::call<&GceSensors::InjectSensorData>;
+    rval->inject_sensor_data =
+        cvd::thunk<sensors_poll_device_1, &GceSensors::InjectSensorData>;
 #endif
 
     // Spawn a thread to listen for incoming data from the remoter.
     int err = pthread_create(
         &rval->receiver_thread_, NULL,
-        SensorsThreadThunker<void*()>::call<&GceSensors::Receiver>, rval);
+        cvd::thunk<void, &GceSensors::Receiver>,
+        rval);
     if (err) {
       ALOGE("GceSensors::%s: Unable to start receiver thread (%s)",
             __FUNCTION__, strerror(err));