Bug 1194721: Add helpers for Gonk sensors daemon, r=gsvelto
authorThomas Zimmermann <tdz@users.sourceforge.net>
Thu, 04 Feb 2016 12:35:13 +0100
changeset 283050 67a40851409d512802f7fca7bb89013674dba6a8
parent 283049 fdb592d6e508458b5ab78985e775e3bca6f0212a
child 283051 8dd47c4c4cd663c086b8e162c720fe930283abb1
push id71404
push usertdz@users.sourceforge.net
push dateThu, 04 Feb 2016 11:35:49 +0000
treeherdermozilla-inbound@df9079dc3f01 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgsvelto
bugs1194721
milestone47.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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