Bug 1194721: Add helpers for Gonk sensors daemon, r=gsvelto
☠☠ backed out by b3b46679b8f3 ☠ ☠
authorThomas Zimmermann <tdz@users.sourceforge.net>
Wed, 03 Feb 2016 15:16:00 +0100
changeset 282888 2a7dbf51f1e88b7beb90296368f8fd1a4abc4630
parent 282887 2a5cf57e8b6782cab4cb3cb6e0faef42e88dcfb1
child 282889 f817794c422b93f894d7c09e3c9e2e6aa1a657ef
push idunknown
push userunknown
push dateunknown
reviewersgsvelto
bugs1194721
milestone47.0a1
Bug 1194721: Add helpers for Gonk sensors daemon, r=gsvelto This patch adds helpers for using the Gonk sensors daemon. The types and functions allow for packing and unpacking messages of the daemon's IPC protocol.
hal/gonk/GonkSensorsHelpers.cpp
hal/gonk/GonkSensorsHelpers.h
hal/gonk/SensorsTypes.h
hal/moz.build
ipc/hal/DaemonSocketPDUHelpers.h
new file mode 100644
--- /dev/null
+++ b/hal/gonk/GonkSensorsHelpers.cpp
@@ -0,0 +1,112 @@
+/* -*- 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 "GonkSensorsHelpers.h"
+
+namespace mozilla {
+namespace hal {
+
+//
+// Unpacking
+//
+
+nsresult
+UnpackPDU(DaemonSocketPDU& aPDU, SensorsEvent& aOut)
+{
+  nsresult rv = UnpackPDU(aPDU, aOut.mType);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  rv = UnpackPDU(aPDU, aOut.mTimestamp);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  rv = UnpackPDU(aPDU, aOut.mStatus);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  size_t i = 0;
+
+  switch (aOut.mType) {
+    case SENSORS_TYPE_MAGNETIC_FIELD_UNCALIBRATED:
+    case SENSORS_TYPE_GYROSCOPE_UNCALIBRATED:
+      /* 6 data values */
+      rv = UnpackPDU(aPDU, aOut.mData.mFloat[i++]);
+      if (NS_FAILED(rv)) {
+        return rv;
+      }
+      /* fall through */
+    case SENSORS_TYPE_ROTATION_VECTOR:
+    case SENSORS_TYPE_GAME_ROTATION_VECTOR:
+    case SENSORS_TYPE_GEOMAGNETIC_ROTATION_VECTOR:
+      /* 5 data values */
+      rv = UnpackPDU(aPDU, aOut.mData.mFloat[i++]);
+      if (NS_FAILED(rv)) {
+        return rv;
+      }
+      rv = UnpackPDU(aPDU, aOut.mData.mFloat[i++]);
+      if (NS_FAILED(rv)) {
+        return rv;
+      }
+      /* fall through */
+    case SENSORS_TYPE_ACCELEROMETER:
+    case SENSORS_TYPE_GEOMAGNETIC_FIELD:
+    case SENSORS_TYPE_ORIENTATION:
+    case SENSORS_TYPE_GYROSCOPE:
+    case SENSORS_TYPE_GRAVITY:
+    case SENSORS_TYPE_LINEAR_ACCELERATION:
+      /* 3 data values */
+      rv = UnpackPDU(aPDU, aOut.mData.mFloat[i++]);
+      if (NS_FAILED(rv)) {
+        return rv;
+      }
+      rv = UnpackPDU(aPDU, aOut.mData.mFloat[i++]);
+      if (NS_FAILED(rv)) {
+        return rv;
+      }
+      /* fall through */
+    case SENSORS_TYPE_LIGHT:
+    case SENSORS_TYPE_PRESSURE:
+    case SENSORS_TYPE_TEMPERATURE:
+    case SENSORS_TYPE_PROXIMITY:
+    case SENSORS_TYPE_RELATIVE_HUMIDITY:
+    case SENSORS_TYPE_AMBIENT_TEMPERATURE:
+    case SENSORS_TYPE_HEART_RATE:
+    case SENSORS_TYPE_TILT_DETECTOR:
+    case SENSORS_TYPE_WAKE_GESTURE:
+    case SENSORS_TYPE_GLANCE_GESTURE:
+    case SENSORS_TYPE_PICK_UP_GESTURE:
+    case SENSORS_TYPE_WRIST_TILT_GESTURE:
+    case SENSORS_TYPE_SIGNIFICANT_MOTION:
+    case SENSORS_TYPE_STEP_DETECTED:
+      /* 1 data value */
+      rv = UnpackPDU(aPDU, aOut.mData.mFloat[i++]);
+      if (NS_FAILED(rv)) {
+        return rv;
+      }
+      break;
+    case SENSORS_TYPE_STEP_COUNTER:
+      /* 1 data value */
+      rv = UnpackPDU(aPDU, aOut.mData.mUint[0]);
+      if (NS_FAILED(rv)) {
+        return rv;
+      }
+      break;
+    default:
+      if (MOZ_HAL_IPC_UNPACK_WARN_IF(true, SensorsEvent)) {
+        return NS_ERROR_ILLEGAL_VALUE;
+      }
+  }
+  rv = UnpackPDU(aPDU, aOut.mDeliveryMode);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  return NS_OK;
+}
+
+} // namespace hal
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/hal/gonk/GonkSensorsHelpers.h
@@ -0,0 +1,226 @@
+/* -*- 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/. */
+
+#ifndef hal_gonk_GonkSensorsHelpers_h
+#define hal_gonk_GonkSensorsHelpers_h
+
+#include <mozilla/ipc/DaemonSocketPDU.h>
+#include <mozilla/ipc/DaemonSocketPDUHelpers.h>
+#include "SensorsTypes.h"
+
+namespace mozilla {
+namespace hal {
+
+using mozilla::ipc::DaemonSocketPDU;
+using mozilla::ipc::DaemonSocketPDUHeader;
+using mozilla::ipc::DaemonSocketPDUHelpers::Convert;
+using mozilla::ipc::DaemonSocketPDUHelpers::PackPDU;
+using mozilla::ipc::DaemonSocketPDUHelpers::UnpackPDU;
+
+using namespace mozilla::ipc::DaemonSocketPDUHelpers;
+
+//
+// Conversion
+//
+// The functions below convert the input value to the output value's
+// type and perform extension tests on the validity of the result. On
+// success the output value will be returned in |aOut|. The functions
+// return NS_OK on success, or an XPCOM error code otherwise.
+//
+// See the documentation of the HAL IPC framework for more information
+// on conversion functions.
+//
+
+nsresult
+Convert(int32_t aIn, SensorsStatus& aOut)
+{
+  static const uint8_t sStatus[] = {
+    [0] = SENSORS_STATUS_NO_CONTACT, // '-1'
+    [1] = SENSORS_STATUS_UNRELIABLE, // '0'
+    [2] = SENSORS_STATUS_ACCURACY_LOW, // '1'
+    [3] = SENSORS_STATUS_ACCURACY_MEDIUM, // '2'
+    [4] = SENSORS_STATUS_ACCURACY_HIGH // '3'
+  };
+  static const int8_t sOffset = -1; // '-1' is the lower bound of the status
+
+  if (MOZ_HAL_IPC_CONVERT_WARN_IF(aIn < sOffset, int32_t, SensorsStatus) ||
+      MOZ_HAL_IPC_CONVERT_WARN_IF(
+        aIn >= (static_cast<ssize_t>(MOZ_ARRAY_LENGTH(sStatus)) + sOffset),
+        int32_t, SensorsStatus)) {
+    return NS_ERROR_ILLEGAL_VALUE;
+  }
+  aOut = static_cast<SensorsStatus>(sStatus[aIn - sOffset]);
+  return NS_OK;
+}
+
+nsresult
+Convert(uint8_t aIn, SensorsDeliveryMode& aOut)
+{
+  static const uint8_t sMode[] = {
+    [0x00] = SENSORS_DELIVERY_MODE_BEST_EFFORT,
+    [0x01] = SENSORS_DELIVERY_MODE_IMMEDIATE
+  };
+  if (MOZ_HAL_IPC_CONVERT_WARN_IF(
+        aIn >= MOZ_ARRAY_LENGTH(sMode), uint8_t, SensorsDeliveryMode)) {
+    return NS_ERROR_ILLEGAL_VALUE;
+  }
+  aOut = static_cast<SensorsDeliveryMode>(sMode[aIn]);
+  return NS_OK;
+}
+
+nsresult
+Convert(uint8_t aIn, SensorsError& aOut)
+{
+  static const uint8_t sError[] = {
+    [0x00] = SENSORS_ERROR_NONE,
+    [0x01] = SENSORS_ERROR_FAIL,
+    [0x02] = SENSORS_ERROR_NOT_READY,
+    [0x03] = SENSORS_ERROR_NOMEM,
+    [0x04] = SENSORS_ERROR_BUSY,
+    [0x05] = SENSORS_ERROR_DONE,
+    [0x06] = SENSORS_ERROR_UNSUPPORTED,
+    [0x07] = SENSORS_ERROR_PARM_INVALID
+  };
+  if (MOZ_HAL_IPC_CONVERT_WARN_IF(
+        aIn >= MOZ_ARRAY_LENGTH(sError), uint8_t, SensorsError)) {
+    return NS_ERROR_ILLEGAL_VALUE;
+  }
+  aOut = static_cast<SensorsError>(sError[aIn]);
+  return NS_OK;
+}
+
+nsresult
+Convert(uint8_t aIn, SensorsTriggerMode& aOut)
+{
+  static const uint8_t sMode[] = {
+    [0x00] = SENSORS_TRIGGER_MODE_CONTINUOUS,
+    [0x01] = SENSORS_TRIGGER_MODE_ON_CHANGE,
+    [0x02] = SENSORS_TRIGGER_MODE_ONE_SHOT,
+    [0x03] = SENSORS_TRIGGER_MODE_SPECIAL
+  };
+  if (MOZ_HAL_IPC_CONVERT_WARN_IF(
+        aIn >= MOZ_ARRAY_LENGTH(sMode), uint8_t, SensorsTriggerMode)) {
+    return NS_ERROR_ILLEGAL_VALUE;
+  }
+  aOut = static_cast<SensorsTriggerMode>(sMode[aIn]);
+  return NS_OK;
+}
+
+nsresult
+Convert(uint32_t aIn, SensorsType& aOut)
+{
+  static const uint8_t sType[] = {
+    [0x00] = 0, // invalid, required by gcc
+    [0x01] = SENSORS_TYPE_ACCELEROMETER,
+    [0x02] = SENSORS_TYPE_GEOMAGNETIC_FIELD,
+    [0x03] = SENSORS_TYPE_ORIENTATION,
+    [0x04] = SENSORS_TYPE_GYROSCOPE,
+    [0x05] = SENSORS_TYPE_LIGHT,
+    [0x06] = SENSORS_TYPE_PRESSURE,
+    [0x07] = SENSORS_TYPE_TEMPERATURE,
+    [0x08] = SENSORS_TYPE_PROXIMITY,
+    [0x09] = SENSORS_TYPE_GRAVITY,
+    [0x0a] = SENSORS_TYPE_LINEAR_ACCELERATION,
+    [0x0b] = SENSORS_TYPE_ROTATION_VECTOR,
+    [0x0c] = SENSORS_TYPE_RELATIVE_HUMIDITY,
+    [0x0d] = SENSORS_TYPE_AMBIENT_TEMPERATURE,
+    [0x0e] = SENSORS_TYPE_MAGNETIC_FIELD_UNCALIBRATED,
+    [0x0f] = SENSORS_TYPE_GAME_ROTATION_VECTOR,
+    [0x10] = SENSORS_TYPE_GYROSCOPE_UNCALIBRATED,
+    [0x11] = SENSORS_TYPE_SIGNIFICANT_MOTION,
+    [0x12] = SENSORS_TYPE_STEP_DETECTED,
+    [0x13] = SENSORS_TYPE_STEP_COUNTER,
+    [0x14] = SENSORS_TYPE_GEOMAGNETIC_ROTATION_VECTOR,
+    [0x15] = SENSORS_TYPE_HEART_RATE,
+    [0x16] = SENSORS_TYPE_TILT_DETECTOR,
+    [0x17] = SENSORS_TYPE_WAKE_GESTURE,
+    [0x18] = SENSORS_TYPE_GLANCE_GESTURE,
+    [0x19] = SENSORS_TYPE_PICK_UP_GESTURE,
+    [0x1a] = SENSORS_TYPE_WRIST_TILT_GESTURE
+  };
+  if (MOZ_HAL_IPC_CONVERT_WARN_IF(
+        !aIn, uint32_t, SensorsType) ||
+      MOZ_HAL_IPC_CONVERT_WARN_IF(
+        aIn >= MOZ_ARRAY_LENGTH(sType), uint32_t, SensorsType)) {
+    return NS_ERROR_ILLEGAL_VALUE;
+  }
+  aOut = static_cast<SensorsType>(sType[aIn]);
+  return NS_OK;
+}
+
+nsresult
+Convert(nsresult aIn, SensorsError& aOut)
+{
+  if (NS_SUCCEEDED(aIn)) {
+    aOut = SENSORS_ERROR_NONE;
+  } else if (aIn == NS_ERROR_OUT_OF_MEMORY) {
+    aOut = SENSORS_ERROR_NOMEM;
+  } else if (aIn == NS_ERROR_ILLEGAL_VALUE) {
+    aOut = SENSORS_ERROR_PARM_INVALID;
+  } else {
+    aOut = SENSORS_ERROR_FAIL;
+  }
+  return NS_OK;
+}
+
+//
+// Packing
+//
+// Pack functions store a value in PDU. See the documentation of the
+// HAL IPC framework for more information.
+//
+// There are currently no sensor-specific pack functions necessary. If
+// you add one, put it below.
+//
+
+//
+// Unpacking
+//
+// Unpack function retrieve a value from a PDU. The functions return
+// NS_OK on success, or an XPCOM error code otherwise. On sucess, the
+// returned value is stored in the second argument |aOut|.
+//
+// See the documentation of the HAL IPC framework for more information
+// on unpack functions.
+//
+
+nsresult
+UnpackPDU(DaemonSocketPDU& aPDU, SensorsDeliveryMode& aOut)
+{
+  return UnpackPDU(aPDU, UnpackConversion<uint8_t, SensorsDeliveryMode>(aOut));
+}
+
+nsresult
+UnpackPDU(DaemonSocketPDU& aPDU, SensorsError& aOut)
+{
+  return UnpackPDU(aPDU, UnpackConversion<uint8_t, SensorsError>(aOut));
+}
+
+nsresult
+UnpackPDU(DaemonSocketPDU& aPDU, SensorsEvent& aOut);
+
+nsresult
+UnpackPDU(DaemonSocketPDU& aPDU, SensorsStatus& aOut)
+{
+  return UnpackPDU(aPDU, UnpackConversion<int32_t, SensorsStatus>(aOut));
+}
+
+nsresult
+UnpackPDU(DaemonSocketPDU& aPDU, SensorsTriggerMode& aOut)
+{
+  return UnpackPDU(aPDU, UnpackConversion<uint8_t, SensorsTriggerMode>(aOut));
+}
+
+nsresult
+UnpackPDU(DaemonSocketPDU& aPDU, SensorsType& aOut)
+{
+  return UnpackPDU(aPDU, UnpackConversion<uint32_t, SensorsType>(aOut));
+}
+
+} // namespace hal
+} // namespace mozilla
+
+#endif // hal_gonk_GonkSensorsHelpers_h
new file mode 100644
--- /dev/null
+++ b/hal/gonk/SensorsTypes.h
@@ -0,0 +1,140 @@
+/* -*- 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/. */
+
+#ifndef hal_gonk_SensorsTypes_h
+#define hal_gonk_SensorsTypes_h
+
+namespace mozilla {
+namespace hal {
+
+enum SensorsDeliveryMode {
+  SENSORS_DELIVERY_MODE_BEST_EFFORT,
+  SENSORS_DELIVERY_MODE_IMMEDIATE
+};
+
+enum SensorsError {
+  SENSORS_ERROR_NONE,
+  SENSORS_ERROR_FAIL,
+  SENSORS_ERROR_NOT_READY,
+  SENSORS_ERROR_NOMEM,
+  SENSORS_ERROR_BUSY,
+  SENSORS_ERROR_DONE,
+  SENSORS_ERROR_UNSUPPORTED,
+  SENSORS_ERROR_PARM_INVALID
+};
+
+enum SensorsStatus {
+  SENSORS_STATUS_NO_CONTACT,
+  SENSORS_STATUS_UNRELIABLE,
+  SENSORS_STATUS_ACCURACY_LOW,
+  SENSORS_STATUS_ACCURACY_MEDIUM,
+  SENSORS_STATUS_ACCURACY_HIGH
+};
+
+enum SensorsTriggerMode {
+  SENSORS_TRIGGER_MODE_CONTINUOUS,
+  SENSORS_TRIGGER_MODE_ON_CHANGE,
+  SENSORS_TRIGGER_MODE_ONE_SHOT,
+  SENSORS_TRIGGER_MODE_SPECIAL
+};
+
+enum SensorsType {
+  SENSORS_TYPE_ACCELEROMETER,
+  SENSORS_TYPE_GEOMAGNETIC_FIELD,
+  SENSORS_TYPE_ORIENTATION,
+  SENSORS_TYPE_GYROSCOPE,
+  SENSORS_TYPE_LIGHT,
+  SENSORS_TYPE_PRESSURE,
+  SENSORS_TYPE_TEMPERATURE,
+  SENSORS_TYPE_PROXIMITY,
+  SENSORS_TYPE_GRAVITY,
+  SENSORS_TYPE_LINEAR_ACCELERATION,
+  SENSORS_TYPE_ROTATION_VECTOR,
+  SENSORS_TYPE_RELATIVE_HUMIDITY,
+  SENSORS_TYPE_AMBIENT_TEMPERATURE,
+  SENSORS_TYPE_MAGNETIC_FIELD_UNCALIBRATED,
+  SENSORS_TYPE_GAME_ROTATION_VECTOR,
+  SENSORS_TYPE_GYROSCOPE_UNCALIBRATED,
+  SENSORS_TYPE_SIGNIFICANT_MOTION,
+  SENSORS_TYPE_STEP_DETECTED,
+  SENSORS_TYPE_STEP_COUNTER,
+  SENSORS_TYPE_GEOMAGNETIC_ROTATION_VECTOR,
+  SENSORS_TYPE_HEART_RATE,
+  SENSORS_TYPE_TILT_DETECTOR,
+  SENSORS_TYPE_WAKE_GESTURE,
+  SENSORS_TYPE_GLANCE_GESTURE,
+  SENSORS_TYPE_PICK_UP_GESTURE,
+  SENSORS_TYPE_WRIST_TILT_GESTURE,
+  SENSORS_NUM_TYPES
+};
+
+struct SensorsEvent {
+  SensorsType mType;
+  SensorsStatus mStatus;
+  SensorsDeliveryMode mDeliveryMode;
+  int64_t mTimestamp;
+  union {
+    float mFloat[6];
+    uint64_t mUint[1];
+  } mData;
+};
+
+/**
+ * |SensorsSensor| represents a device sensor; either single or composite.
+ */
+struct SensorsSensor {
+  SensorsSensor(int32_t aId, SensorsType aType,
+                float aRange, float aResolution,
+                float aPower, int32_t aMinPeriod,
+                int32_t aMaxPeriod,
+                SensorsTriggerMode aTriggerMode,
+                SensorsDeliveryMode aDeliveryMode)
+    : mId(aId)
+    , mType(aType)
+    , mRange(aRange)
+    , mResolution(aResolution)
+    , mPower(aPower)
+    , mMinPeriod(aMinPeriod)
+    , mMaxPeriod(aMaxPeriod)
+    , mTriggerMode(aTriggerMode)
+    , mDeliveryMode(aDeliveryMode)
+  { }
+
+  int32_t mId;
+  SensorsType mType;
+  float mRange;
+  float mResolution;
+  float mPower;
+  int32_t mMinPeriod;
+  int32_t mMaxPeriod;
+  SensorsTriggerMode mTriggerMode;
+  SensorsDeliveryMode mDeliveryMode;
+};
+
+/**
+ * |SensorClass| represents the status of a specific sensor type.
+ */
+struct SensorsSensorClass {
+  SensorsSensorClass()
+    : mActivated(0)
+    , mMinValue(0)
+    , mMaxValue(0)
+  { }
+
+  void UpdateFromSensor(const SensorsSensor& aSensor)
+  {
+    mMaxValue = std::max(aSensor.mRange, mMaxValue);
+  }
+
+  uint32_t mActivated;
+  float mMinValue;
+  float mMaxValue;
+};
+
+} // namespace hal
+} // namespace mozilla
+
+#endif // hal_gonk_SensorsTypes_h
--- a/hal/moz.build
+++ b/hal/moz.build
@@ -46,16 +46,17 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'andr
     SOURCES += [
         'android/AndroidHal.cpp',
     ]
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
     UNIFIED_SOURCES += [
         'gonk/GonkDiskSpaceWatcher.cpp',
         'gonk/GonkFMRadio.cpp',
         'gonk/GonkSensor.cpp',
+        'gonk/GonkSensorsHelpers.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.
     SOURCES += [
--- a/ipc/hal/DaemonSocketPDUHelpers.h
+++ b/ipc/hal/DaemonSocketPDUHelpers.h
@@ -1137,16 +1137,146 @@ public:
     }
     rv = UnpackPDU(pdu, aArg6);
     if (NS_FAILED(rv)) {
       return rv;
     }
     WarnAboutTrailingData();
     return NS_OK;
   }
+
+  template<typename T1, typename T2, typename T3, typename T4, typename T5,
+           typename T6, typename T7>
+  nsresult operator () (T1& aArg1, T2& aArg2, T3& aArg3, T4& aArg4,
+                        T5& aArg5, T6& aArg6, T7& aArg7) const
+  {
+    DaemonSocketPDU& pdu = GetPDU();
+
+    nsresult rv = UnpackPDU(pdu, aArg1);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    rv = UnpackPDU(pdu, aArg2);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    rv = UnpackPDU(pdu, aArg3);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    rv = UnpackPDU(pdu, aArg4);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    rv = UnpackPDU(pdu, aArg5);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    rv = UnpackPDU(pdu, aArg6);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    rv = UnpackPDU(pdu, aArg7);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    WarnAboutTrailingData();
+    return NS_OK;
+  }
+
+  template<typename T1, typename T2, typename T3, typename T4, typename T5,
+           typename T6, typename T7, typename T8>
+  nsresult operator () (T1& aArg1, T2& aArg2, T3& aArg3, T4& aArg4,
+                        T5& aArg5, T6& aArg6, T7& aArg7, T8& aArg8) const
+  {
+    DaemonSocketPDU& pdu = GetPDU();
+
+    nsresult rv = UnpackPDU(pdu, aArg1);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    rv = UnpackPDU(pdu, aArg2);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    rv = UnpackPDU(pdu, aArg3);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    rv = UnpackPDU(pdu, aArg4);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    rv = UnpackPDU(pdu, aArg5);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    rv = UnpackPDU(pdu, aArg6);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    rv = UnpackPDU(pdu, aArg7);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    rv = UnpackPDU(pdu, aArg8);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    WarnAboutTrailingData();
+    return NS_OK;
+  }
+
+  template<typename T1, typename T2, typename T3, typename T4, typename T5,
+           typename T6, typename T7, typename T8, typename T9>
+  nsresult operator () (T1& aArg1, T2& aArg2, T3& aArg3, T4& aArg4,
+                        T5& aArg5, T6& aArg6, T7& aArg7, T8& aArg8,
+                        T9& aArg9) const
+  {
+    DaemonSocketPDU& pdu = GetPDU();
+
+    nsresult rv = UnpackPDU(pdu, aArg1);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    rv = UnpackPDU(pdu, aArg2);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    rv = UnpackPDU(pdu, aArg3);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    rv = UnpackPDU(pdu, aArg4);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    rv = UnpackPDU(pdu, aArg5);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    rv = UnpackPDU(pdu, aArg6);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    rv = UnpackPDU(pdu, aArg7);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    rv = UnpackPDU(pdu, aArg8);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    rv = UnpackPDU(pdu, aArg9);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    WarnAboutTrailingData();
+    return NS_OK;
+  }
 };
 
 } // namespace DaemonSocketPDUHelpers
 
 } // namespace ipc
 } // namespace mozilla
 
 #endif // mozilla_ipc_DaemonSocketPDUHelpers_h