Bug 1194721: Add poll interface and module for Gonk sensors, r=gsvelto
authorThomas Zimmermann <tdz@users.sourceforge.net>
Thu, 04 Feb 2016 12:35:13 +0100
changeset 308816 dd570dc405ce3297eac2b8158fbe74010adeeab1
parent 308815 8dd47c4c4cd663c086b8e162c720fe930283abb1
child 308817 303d6630e6986c63a52316c6fdd13ebfdf92e93d
push idunknown
push userunknown
push dateunknown
reviewersgsvelto
bugs1194721
milestone47.0a1
Bug 1194721: Add poll interface and module for Gonk sensors, r=gsvelto The sensor daemon's poll service reads events from the device's sensors. This patch adds Gecko support for this service. Gecko receives information about existing sensors and can subscribe to sensor events. Events will be delivered for each enabled sensor.
hal/gonk/GonkSensorsPollInterface.cpp
hal/gonk/GonkSensorsPollInterface.h
hal/moz.build
new file mode 100644
--- /dev/null
+++ b/hal/gonk/GonkSensorsPollInterface.cpp
@@ -0,0 +1,430 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "GonkSensorsPollInterface.h"
+#include "HalLog.h"
+
+namespace mozilla {
+namespace hal {
+
+using namespace mozilla::ipc;
+
+//
+// GonkSensorsPollResultHandler
+//
+
+void
+GonkSensorsPollResultHandler::OnError(SensorsError aError)
+{
+  HAL_ERR("Received error code %d", static_cast<int>(aError));
+}
+
+void
+GonkSensorsPollResultHandler::EnableSensor()
+{ }
+
+void
+GonkSensorsPollResultHandler::DisableSensor()
+{ }
+
+void
+GonkSensorsPollResultHandler::SetPeriod()
+{ }
+
+GonkSensorsPollResultHandler::~GonkSensorsPollResultHandler()
+{ }
+
+//
+// GonkSensorsPollNotificationHandler
+//
+
+void
+GonkSensorsPollNotificationHandler::ErrorNotification(SensorsError aError)
+{
+  HAL_ERR("Received error code %d", static_cast<int>(aError));
+}
+
+void
+GonkSensorsPollNotificationHandler::SensorDetectedNotification(
+  int32_t aId,
+  SensorsType aType,
+  float aRange,
+  float aResolution,
+  float aPower,
+  int32_t aMinPeriod,
+  int32_t aMaxPeriod,
+  SensorsTriggerMode aTriggerMode,
+  SensorsDeliveryMode aDeliveryMode)
+{ }
+
+void
+GonkSensorsPollNotificationHandler::SensorLostNotification(int32_t aId)
+{ }
+
+void
+GonkSensorsPollNotificationHandler::EventNotification(int32_t aId,
+                                                  const SensorsEvent& aEvent)
+{ }
+
+GonkSensorsPollNotificationHandler::~GonkSensorsPollNotificationHandler()
+{ }
+
+//
+// GonkSensorsPollModule
+//
+
+GonkSensorsPollModule::GonkSensorsPollModule()
+  : mProtocolVersion(0)
+{ }
+
+GonkSensorsPollModule::~GonkSensorsPollModule()
+{ }
+
+nsresult
+GonkSensorsPollModule::SetProtocolVersion(unsigned long aProtocolVersion)
+{
+  if ((aProtocolVersion < MIN_PROTOCOL_VERSION) ||
+      (aProtocolVersion > MAX_PROTOCOL_VERSION)) {
+    HAL_ERR("Sensors Poll protocol version %lu not supported",
+            aProtocolVersion);
+    return NS_ERROR_ILLEGAL_VALUE;
+  }
+  mProtocolVersion = aProtocolVersion;
+  return NS_OK;
+}
+
+void
+GonkSensorsPollModule::HandleSvc(const DaemonSocketPDUHeader& aHeader,
+                             DaemonSocketPDU& aPDU,
+                             DaemonSocketResultHandler* aRes)
+{
+  static void (GonkSensorsPollModule::* const HandleOp[])(
+    const DaemonSocketPDUHeader&, DaemonSocketPDU&,
+    DaemonSocketResultHandler*) = {
+    [0] = &GonkSensorsPollModule::HandleRsp,
+    [1] = &GonkSensorsPollModule::HandleNtf
+  };
+
+  MOZ_ASSERT(!NS_IsMainThread()); // I/O thread
+
+  // Negate twice to map bit to 0/1
+  unsigned long isNtf = !!(aHeader.mOpcode & 0x80);
+
+  (this->*(HandleOp[isNtf]))(aHeader, aPDU, aRes);
+}
+
+// Commands
+//
+
+nsresult
+GonkSensorsPollModule::EnableSensorCmd(int32_t aId, GonkSensorsPollResultHandler* aRes)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  nsAutoPtr<DaemonSocketPDU> pdu(
+    new DaemonSocketPDU(SERVICE_ID, OPCODE_ENABLE_SENSOR, 0));
+
+  nsresult rv = PackPDU(aId, *pdu);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  rv = Send(pdu, aRes);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  Unused << pdu.forget();
+  return NS_OK;
+}
+
+nsresult
+GonkSensorsPollModule::DisableSensorCmd(int32_t aId, GonkSensorsPollResultHandler* aRes)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  nsAutoPtr<DaemonSocketPDU> pdu(
+    new DaemonSocketPDU(SERVICE_ID, OPCODE_DISABLE_SENSOR, 0));
+
+  nsresult rv = PackPDU(aId, *pdu);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  rv = Send(pdu, aRes);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  Unused << pdu.forget();
+  return NS_OK;
+}
+
+nsresult
+GonkSensorsPollModule::SetPeriodCmd(int32_t aId, uint64_t aPeriod,
+                                GonkSensorsPollResultHandler* aRes)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  nsAutoPtr<DaemonSocketPDU> pdu(
+    new DaemonSocketPDU(SERVICE_ID, OPCODE_SET_PERIOD, 0));
+
+  nsresult rv = PackPDU(aId, *pdu);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  rv = PackPDU(aPeriod, *pdu);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  rv = Send(pdu, aRes);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  Unused << pdu.forget();
+  return NS_OK;
+}
+
+// Responses
+//
+
+void
+GonkSensorsPollModule::ErrorRsp(
+  const DaemonSocketPDUHeader& aHeader,
+  DaemonSocketPDU& aPDU, GonkSensorsPollResultHandler* aRes)
+{
+  ErrorRunnable::Dispatch(
+    aRes, &GonkSensorsPollResultHandler::OnError, UnpackPDUInitOp(aPDU));
+}
+
+void
+GonkSensorsPollModule::EnableSensorRsp(
+  const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU,
+  GonkSensorsPollResultHandler* aRes)
+{
+  ResultRunnable::Dispatch(
+    aRes, &GonkSensorsPollResultHandler::EnableSensor, UnpackPDUInitOp(aPDU));
+}
+
+void
+GonkSensorsPollModule::DisableSensorRsp(
+  const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU,
+  GonkSensorsPollResultHandler* aRes)
+{
+  ResultRunnable::Dispatch(
+    aRes, &GonkSensorsPollResultHandler::DisableSensor, UnpackPDUInitOp(aPDU));
+}
+
+void
+GonkSensorsPollModule::SetPeriodRsp(
+  const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU,
+  GonkSensorsPollResultHandler* aRes)
+{
+  ResultRunnable::Dispatch(
+    aRes, &GonkSensorsPollResultHandler::SetPeriod, UnpackPDUInitOp(aPDU));
+}
+
+void
+GonkSensorsPollModule::HandleRsp(
+  const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU,
+  DaemonSocketResultHandler* aRes)
+{
+  static void (GonkSensorsPollModule::* const sHandleRsp[])(
+    const DaemonSocketPDUHeader&, DaemonSocketPDU&,
+    GonkSensorsPollResultHandler*) = {
+    [OPCODE_ERROR] = &GonkSensorsPollModule::ErrorRsp,
+    [OPCODE_ENABLE_SENSOR] = &GonkSensorsPollModule::EnableSensorRsp,
+    [OPCODE_DISABLE_SENSOR] = &GonkSensorsPollModule::DisableSensorRsp,
+    [OPCODE_SET_PERIOD] = &GonkSensorsPollModule::SetPeriodRsp,
+  };
+
+  MOZ_ASSERT(!NS_IsMainThread()); // I/O thread
+
+  if (!(aHeader.mOpcode < MOZ_ARRAY_LENGTH(sHandleRsp)) ||
+      !sHandleRsp[aHeader.mOpcode]) {
+    HAL_ERR("Sensors poll response opcode %d unknown", aHeader.mOpcode);
+    return;
+  }
+
+  RefPtr<GonkSensorsPollResultHandler> res =
+    static_cast<GonkSensorsPollResultHandler*>(aRes);
+
+  if (!res) {
+    return; // Return early if no result handler has been set for response
+  }
+
+  (this->*(sHandleRsp[aHeader.mOpcode]))(aHeader, aPDU, res);
+}
+
+// Notifications
+//
+
+// Returns the current notification handler to a notification runnable
+class GonkSensorsPollModule::NotificationHandlerWrapper final
+{
+public:
+  typedef GonkSensorsPollNotificationHandler ObjectType;
+
+  static ObjectType* GetInstance()
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+
+    return sNotificationHandler;
+  }
+
+  static GonkSensorsPollNotificationHandler* sNotificationHandler;
+};
+
+GonkSensorsPollNotificationHandler*
+  GonkSensorsPollModule::NotificationHandlerWrapper::sNotificationHandler;
+
+void
+GonkSensorsPollModule::ErrorNtf(
+  const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
+{
+  ErrorNotification::Dispatch(
+    &GonkSensorsPollNotificationHandler::ErrorNotification,
+    UnpackPDUInitOp(aPDU));
+}
+
+void
+GonkSensorsPollModule::SensorDetectedNtf(
+  const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
+{
+  SensorDetectedNotification::Dispatch(
+    &GonkSensorsPollNotificationHandler::SensorDetectedNotification,
+    UnpackPDUInitOp(aPDU));
+}
+
+void
+GonkSensorsPollModule::SensorLostNtf(
+  const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
+{
+  SensorLostNotification::Dispatch(
+    &GonkSensorsPollNotificationHandler::SensorLostNotification,
+    UnpackPDUInitOp(aPDU));
+}
+
+void
+GonkSensorsPollModule::EventNtf(
+  const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
+{
+  EventNotification::Dispatch(
+    &GonkSensorsPollNotificationHandler::EventNotification,
+    UnpackPDUInitOp(aPDU));
+}
+
+void
+GonkSensorsPollModule::HandleNtf(
+  const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU,
+  DaemonSocketResultHandler* aRes)
+{
+  static void (GonkSensorsPollModule::* const sHandleNtf[])(
+    const DaemonSocketPDUHeader&, DaemonSocketPDU&) = {
+    [0] = &GonkSensorsPollModule::ErrorNtf,
+    [1] = &GonkSensorsPollModule::SensorDetectedNtf,
+    [2] = &GonkSensorsPollModule::SensorLostNtf,
+    [3] = &GonkSensorsPollModule::EventNtf
+  };
+
+  MOZ_ASSERT(!NS_IsMainThread());
+
+  uint8_t index = aHeader.mOpcode - 0x80;
+
+  if (!(index < MOZ_ARRAY_LENGTH(sHandleNtf)) || !sHandleNtf[index]) {
+    HAL_ERR("Sensors poll notification opcode %d unknown", aHeader.mOpcode);
+    return;
+  }
+
+  (this->*(sHandleNtf[index]))(aHeader, aPDU);
+}
+
+//
+// GonkSensorsPollInterface
+//
+
+GonkSensorsPollInterface::GonkSensorsPollInterface(
+  GonkSensorsPollModule* aModule)
+  : mModule(aModule)
+{ }
+
+GonkSensorsPollInterface::~GonkSensorsPollInterface()
+{ }
+
+void
+GonkSensorsPollInterface::SetNotificationHandler(
+  GonkSensorsPollNotificationHandler* aNotificationHandler)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  GonkSensorsPollModule::NotificationHandlerWrapper::sNotificationHandler =
+    aNotificationHandler;
+}
+
+nsresult
+GonkSensorsPollInterface::SetProtocolVersion(unsigned long aProtocolVersion)
+{
+  MOZ_ASSERT(mModule);
+
+  return mModule->SetProtocolVersion(aProtocolVersion);
+}
+
+void
+GonkSensorsPollInterface::EnableSensor(int32_t aId,
+                                       GonkSensorsPollResultHandler* aRes)
+{
+  MOZ_ASSERT(mModule);
+
+  nsresult rv = mModule->EnableSensorCmd(aId, aRes);
+  if (NS_FAILED(rv)) {
+    DispatchError(aRes, rv);
+  }
+}
+
+void
+GonkSensorsPollInterface::DisableSensor(int32_t aId,
+                                        GonkSensorsPollResultHandler* aRes)
+{
+  MOZ_ASSERT(mModule);
+
+  nsresult rv = mModule->DisableSensorCmd(aId, aRes);
+  if (NS_FAILED(rv)) {
+    DispatchError(aRes, rv);
+  }
+}
+
+void
+GonkSensorsPollInterface::SetPeriod(int32_t aId, uint64_t aPeriod,
+                                    GonkSensorsPollResultHandler* aRes)
+{
+  MOZ_ASSERT(mModule);
+
+  nsresult rv = mModule->SetPeriodCmd(aId, aPeriod, aRes);
+  if (NS_FAILED(rv)) {
+    DispatchError(aRes, rv);
+  }
+}
+
+void
+GonkSensorsPollInterface::DispatchError(
+  GonkSensorsPollResultHandler* aRes, SensorsError aError)
+{
+  DaemonResultRunnable1<GonkSensorsPollResultHandler, void,
+                        SensorsError, SensorsError>::Dispatch(
+    aRes, &GonkSensorsPollResultHandler::OnError,
+    ConstantInitOp1<SensorsError>(aError));
+}
+
+void
+GonkSensorsPollInterface::DispatchError(
+  GonkSensorsPollResultHandler* aRes, nsresult aRv)
+{
+  SensorsError error;
+
+  if (NS_FAILED(Convert(aRv, error))) {
+    error = SENSORS_ERROR_FAIL;
+  }
+  DispatchError(aRes, error);
+}
+
+} // namespace hal
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/hal/gonk/GonkSensorsPollInterface.h
@@ -0,0 +1,343 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * The poll interface gives yo access to the Sensors daemon's Poll service,
+ * which handles sensors. The poll service will inform you when sensors are
+ * detected or removed from the system. You can activate (or deactivate)
+ * existing sensors and poll will deliver the sensors' events.
+ *
+ * All public methods and callback methods run on the main thread.
+ */
+
+#ifndef hal_gonk_GonkSensorsPollInterface_h
+#define hal_gonk_GonkSensorsPollInterface_h
+
+#include <mozilla/ipc/DaemonRunnables.h>
+#include <mozilla/ipc/DaemonSocketMessageHandlers.h>
+#include "SensorsTypes.h"
+
+namespace mozilla {
+namespace ipc {
+
+class DaemonSocketPDU;
+class DaemonSocketPDUHeader;
+
+}
+}
+
+namespace mozilla {
+namespace hal {
+
+class SensorsInterface;
+
+using mozilla::ipc::DaemonSocketPDU;
+using mozilla::ipc::DaemonSocketPDUHeader;
+using mozilla::ipc::DaemonSocketResultHandler;
+
+/**
+ * This class is the result-handler interface for the Sensors
+ * Poll interface. Methods always run on the main thread.
+ */
+class GonkSensorsPollResultHandler : public DaemonSocketResultHandler
+{
+public:
+
+  /**
+   * Called if a poll command failed.
+   *
+   * @param aError The error code.
+   */
+  virtual void OnError(SensorsError aError);
+
+  /**
+   * The callback method for |GonkSensorsPollInterface::EnableSensor|.
+   */
+  virtual void EnableSensor();
+
+  /**
+   * The callback method for |GonkSensorsPollInterface::DisableSensor|.
+   */
+  virtual void DisableSensor();
+
+  /**
+   * The callback method for |GonkSensorsPollInterface::SetPeriod|.
+   */
+  virtual void SetPeriod();
+
+protected:
+  virtual ~GonkSensorsPollResultHandler();
+};
+
+/**
+ * This is the notification-handler interface. Implement this classes
+ * methods to handle event and notifications from the sensors daemon.
+ */
+class GonkSensorsPollNotificationHandler
+{
+public:
+
+  /**
+   * The notification handler for errors. You'll receive this call if
+   * there's been a critical error in the daemon. Either try to handle
+   * the error, or restart the daemon.
+   *
+   * @param aError The error code.
+   */
+  virtual void ErrorNotification(SensorsError aError);
+
+  /**
+   * This methods gets call when a new sensor has been detected.
+   *
+   * @param aId The sensor's id.
+   * @param aType The sensor's type.
+   * @param aRange The sensor's maximum value.
+   * @param aResolution The minimum difference between two consecutive values.
+   * @param aPower The sensor's power consumption (in mA).
+   * @param aMinPeriod The minimum time between two events (in ns).
+   * @param aMaxPeriod The maximum time between two events (in ns).
+   * @param aTriggerMode The sensor's mode for triggering events.
+   * @param aDeliveryMode The sensor's urgency for event delivery.
+   */
+  virtual void SensorDetectedNotification(int32_t aId, SensorsType aType,
+                                          float aRange, float aResolution,
+                                          float aPower, int32_t aMinPeriod,
+                                          int32_t aMaxPeriod,
+                                          SensorsTriggerMode aTriggerMode,
+                                          SensorsDeliveryMode aDeliveryMode);
+
+  /**
+   * This methods gets call when an existing sensor has been removed.
+   *
+   * @param aId The sensor's id.
+   */
+  virtual void SensorLostNotification(int32_t aId);
+
+  /**
+   * This is the callback methods for sensor events. Only activated sensors
+   * generate events. All sensors are disabled by default. The actual data
+   * of the event depends on the sensor type.
+   *
+   * @param aId The sensor's id.
+   * @param aEvent The event's data.
+   */
+  virtual void EventNotification(int32_t aId, const SensorsEvent& aEvent);
+
+protected:
+  virtual ~GonkSensorsPollNotificationHandler();
+};
+
+/**
+ * This is the module class for the Sensors poll component. It handles PDU
+ * packing and unpacking. Methods are either executed on the main thread or
+ * the I/O thread.
+ *
+ * This is an internal class, use |GonkSensorsPollInterface| instead.
+ */
+class GonkSensorsPollModule
+{
+public:
+  class NotificationHandlerWrapper;
+
+  enum {
+    SERVICE_ID = 0x01
+  };
+
+  enum {
+    OPCODE_ERROR = 0x00,
+    OPCODE_ENABLE_SENSOR = 0x01,
+    OPCODE_DISABLE_SENSOR = 0x02,
+    OPCODE_SET_PERIOD = 0x03
+  };
+
+  enum {
+    MIN_PROTOCOL_VERSION = 1,
+    MAX_PROTOCOL_VERSION = 1
+  };
+
+  virtual nsresult Send(DaemonSocketPDU* aPDU,
+                        DaemonSocketResultHandler* aRes) = 0;
+
+  nsresult SetProtocolVersion(unsigned long aProtocolVersion);
+
+  //
+  // Commands
+  //
+
+  nsresult EnableSensorCmd(int32_t aId,
+                           GonkSensorsPollResultHandler* aRes);
+
+  nsresult DisableSensorCmd(int32_t aId,
+                            GonkSensorsPollResultHandler* aRes);
+
+  nsresult SetPeriodCmd(int32_t aId, uint64_t aPeriod,
+                        GonkSensorsPollResultHandler* aRes);
+
+protected:
+  GonkSensorsPollModule();
+  virtual ~GonkSensorsPollModule();
+
+  void HandleSvc(const DaemonSocketPDUHeader& aHeader,
+                 DaemonSocketPDU& aPDU,
+                 DaemonSocketResultHandler* aRes);
+
+private:
+
+  //
+  // Responses
+  //
+
+  typedef mozilla::ipc::DaemonResultRunnable0<
+    GonkSensorsPollResultHandler, void>
+    ResultRunnable;
+
+  typedef mozilla::ipc::DaemonResultRunnable1<
+    GonkSensorsPollResultHandler, void, SensorsError, SensorsError>
+    ErrorRunnable;
+
+  void ErrorRsp(const DaemonSocketPDUHeader& aHeader,
+                DaemonSocketPDU& aPDU,
+                GonkSensorsPollResultHandler* aRes);
+
+  void EnableSensorRsp(const DaemonSocketPDUHeader& aHeader,
+                       DaemonSocketPDU& aPDU,
+                       GonkSensorsPollResultHandler* aRes);
+
+  void DisableSensorRsp(const DaemonSocketPDUHeader& aHeader,
+                        DaemonSocketPDU& aPDU,
+                        GonkSensorsPollResultHandler* aRes);
+
+  void SetPeriodRsp(const DaemonSocketPDUHeader& aHeader,
+                    DaemonSocketPDU& aPDU,
+                    GonkSensorsPollResultHandler* aRes);
+
+  void HandleRsp(const DaemonSocketPDUHeader& aHeader,
+                 DaemonSocketPDU& aPDU,
+                 DaemonSocketResultHandler* aRes);
+
+  //
+  // Notifications
+  //
+
+  typedef mozilla::ipc::DaemonNotificationRunnable1<
+    NotificationHandlerWrapper, void, SensorsError>
+    ErrorNotification;
+
+  typedef mozilla::ipc::DaemonNotificationRunnable9<
+    NotificationHandlerWrapper, void, int32_t, SensorsType,
+    float, float, float, int32_t, int32_t, SensorsTriggerMode,
+    SensorsDeliveryMode>
+    SensorDetectedNotification;
+
+  typedef mozilla::ipc::DaemonNotificationRunnable1<
+    NotificationHandlerWrapper, void, int32_t>
+    SensorLostNotification;
+
+  typedef mozilla::ipc::DaemonNotificationRunnable2<
+    NotificationHandlerWrapper, void, int32_t, SensorsEvent, int32_t,
+    const SensorsEvent&>
+    EventNotification;
+
+  class SensorDetectedInitOp;
+  class SensorLostInitOp;
+  class EventInitOp;
+
+  void ErrorNtf(const DaemonSocketPDUHeader& aHeader,
+                DaemonSocketPDU& aPDU);
+
+  void SensorDetectedNtf(const DaemonSocketPDUHeader& aHeader,
+                         DaemonSocketPDU& aPDU);
+
+  void SensorLostNtf(const DaemonSocketPDUHeader& aHeader,
+                     DaemonSocketPDU& aPDU);
+
+  void EventNtf(const DaemonSocketPDUHeader& aHeader,
+                DaemonSocketPDU& aPDU);
+
+  void HandleNtf(const DaemonSocketPDUHeader& aHeader,
+                 DaemonSocketPDU& aPDU,
+                 DaemonSocketResultHandler* aRes);
+
+private:
+  unsigned long mProtocolVersion;
+};
+
+/**
+ * This class implements the public interface to the Sensors poll
+ * component. Use |SensorsInterface::GetPollInterface| to retrieve
+ * an instance. All methods run on the main thread.
+ */
+class GonkSensorsPollInterface final
+{
+public:
+  friend class GonkSensorsInterface;
+
+  /**
+   * This method sets the notification handler for poll notifications. Call
+   * this method immediately after registering the module. Otherwise you won't
+   * be able able to receive poll notifications. You may not free the handler
+   * class while the poll component is regsitered.
+   *
+   * @param aNotificationHandler An instance of a poll notification handler.
+   */
+  void SetNotificationHandler(
+    GonkSensorsPollNotificationHandler* aNotificationHandler);
+
+  /**
+   * This method sets the protocol version. You should set it to the
+   * value that has been returned from the backend when registering the
+   * Poll service. You cannot send or receive messages before setting
+   * the protocol version.
+   *
+   * @param aProtocolVersion
+   * @return NS_OK for supported versions, or an XPCOM error code otherwise.
+   */
+  nsresult SetProtocolVersion(unsigned long aProtocolVersion);
+
+  /**
+   * Enables an existing sensor. The sensor id will have been delivered in
+   * a SensorDetectedNotification.
+   *
+   * @param aId The sensor's id.
+   * @param aRes The result handler.
+   */
+  void EnableSensor(int32_t aId, GonkSensorsPollResultHandler* aRes);
+
+  /**
+   * Disables an existing sensor. The sensor id will have been delivered in
+   * a SensorDetectedNotification.
+   *
+   * @param aId The sensor's id.
+   * @param aRes The result handler.
+   */
+  void DisableSensor(int32_t aId, GonkSensorsPollResultHandler* aRes);
+
+  /**
+   * Sets the period for a sensor. The sensor id will have been delivered in
+   * a SensorDetectedNotification. The value for the period should be between
+   * the sensor's minimum and maximum period.
+   *
+   * @param aId The sensor's id.
+   * @param aPeriod The sensor's new period.
+   * @param aRes The result handler.
+   */
+  void SetPeriod(int32_t aId, uint64_t aPeriod, GonkSensorsPollResultHandler* aRes);
+
+  ~GonkSensorsPollInterface();
+
+private:
+  GonkSensorsPollInterface(GonkSensorsPollModule* aModule);
+
+  void DispatchError(GonkSensorsPollResultHandler* aRes, SensorsError aError);
+  void DispatchError(GonkSensorsPollResultHandler* aRes, nsresult aRv);
+
+  GonkSensorsPollModule* mModule;
+};
+
+} // hal
+} // namespace mozilla
+
+#endif // hal_gonk_GonkSensorsPollInterface_h
--- a/hal/moz.build
+++ b/hal/moz.build
@@ -47,16 +47,17 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'andr
         'android/AndroidHal.cpp',
     ]
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
     UNIFIED_SOURCES += [
         'gonk/GonkDiskSpaceWatcher.cpp',
         'gonk/GonkFMRadio.cpp',
         'gonk/GonkSensor.cpp',
         'gonk/GonkSensorsHelpers.cpp',
+        'gonk/GonkSensorsPollInterface.cpp',
         'gonk/GonkSensorsRegistryInterface.cpp',
         'gonk/GonkSwitch.cpp',
         'gonk/SystemService.cpp',
         'gonk/UeventPoller.cpp',
         'linux/LinuxMemory.cpp',
         'linux/LinuxPower.cpp',
     ]
     # GonkHal.cpp cannot be built in unified mode because it relies on HalImpl.h.