Merge "Use vendor variant of libstagefright_foundation." into oc-dr1-dev
diff --git a/camera/device/1.0/default/CameraDevice.cpp b/camera/device/1.0/default/CameraDevice.cpp
index 6f4e70f..c53c0d8 100644
--- a/camera/device/1.0/default/CameraDevice.cpp
+++ b/camera/device/1.0/default/CameraDevice.cpp
@@ -116,7 +116,7 @@
     Mutex::Autolock _l(mLock);
     if (mDevice != nullptr) {
         ALOGW("%s: camera %s is deleted while open", __FUNCTION__, mCameraId.c_str());
-        close();
+        closeLocked();
     }
     mHalPreviewWindow.cleanUpCirculatingBuffers();
 }
@@ -130,7 +130,7 @@
     }
     if (!connected) {
         ALOGW("%s: camera %s is disconneted. Closing", __FUNCTION__, mCameraId.c_str());
-        close();
+        closeLocked();
     }
     return;
 }
@@ -982,8 +982,13 @@
 }
 
 Return<void> CameraDevice::close() {
-    ALOGI("Closing camera %s", mCameraId.c_str());
     Mutex::Autolock _l(mLock);
+    closeLocked();
+    return Void();
+}
+
+void CameraDevice::closeLocked() {
+    ALOGI("Closing camera %s", mCameraId.c_str());
     if(mDevice) {
         int rc = mDevice->common.close(&mDevice->common);
         if (rc != OK) {
@@ -991,7 +996,6 @@
         }
         mDevice = nullptr;
     }
-    return Void();
 }
 
 }  // namespace implementation
diff --git a/camera/device/1.0/default/CameraDevice_1_0.h b/camera/device/1.0/default/CameraDevice_1_0.h
index 0e5a49b..c078596 100644
--- a/camera/device/1.0/default/CameraDevice_1_0.h
+++ b/camera/device/1.0/default/CameraDevice_1_0.h
@@ -222,6 +222,7 @@
     static status_t getStatusT(const Status& s);
 
     Status initStatus() const;
+    void closeLocked();
 };
 
 }  // namespace implementation
diff --git a/current.txt b/current.txt
index 9b17dae..64fafbf 100644
--- a/current.txt
+++ b/current.txt
@@ -101,7 +101,7 @@
 4f6dedbcdd21c309dfc650acea81a096d6b242493ffe49c8d61bd3c43aad354e android.hardware.graphics.common@1.0::types
 b3aac6c3817f039964fcd62268274b3039e17bd7d0d5b40b4d1d1c7b19a1f866 android.hardware.graphics.composer@2.1::IComposer
 b19d00eb8a8b3b0034a0321f22e8f32162bf4c2aebbce6da22c025f56e459ea2 android.hardware.graphics.composer@2.1::IComposerCallback
-e992684e690dfe67a8cbeab5005bfa3fa9c2bf3d4b0b75657fb1f0c2d5dd2bae android.hardware.graphics.composer@2.1::IComposerClient
+61ee43ffe6fb6dbe8b22dc17c51ff3d5ba703fc6029cba211f901f3d79c8a72d android.hardware.graphics.composer@2.1::IComposerClient
 1c98c2f5154345312ec054871792a2982ec5f3e2bc2abfb61a10c0b517978e20 android.hardware.graphics.composer@2.1::types
 a695898589e1ef15b2b2510f11edd6aafac9918d9cf8d74b4b6143b309dee542 android.hardware.graphics.mapper@2.0::IMapper
 28507d385a3dd224bf3c32f1bfd9f96092c4701b9c1cc66caa578fc3efc97877 android.hardware.graphics.mapper@2.0::types
diff --git a/graphics/composer/2.1/IComposerClient.hal b/graphics/composer/2.1/IComposerClient.hal
index 85572d4..f2ff932 100644
--- a/graphics/composer/2.1/IComposerClient.hal
+++ b/graphics/composer/2.1/IComposerClient.hal
@@ -1117,6 +1117,7 @@
         VALIDATE_DISPLAY                   = 0x203 << OPCODE_SHIFT,
         ACCEPT_DISPLAY_CHANGES             = 0x204 << OPCODE_SHIFT,
         PRESENT_DISPLAY                    = 0x205 << OPCODE_SHIFT,
+        PRESENT_OR_VALIDATE_DISPLAY        = 0x206 << OPCODE_SHIFT,
 
         /** layer commands (VALIDATE_DISPLAY not required) */
         SET_LAYER_CURSOR_POSITION          = 0x300 << OPCODE_SHIFT,
@@ -1135,6 +1136,7 @@
         SET_LAYER_TRANSFORM                = 0x408 << OPCODE_SHIFT,
         SET_LAYER_VISIBLE_REGION           = 0x409 << OPCODE_SHIFT,
         SET_LAYER_Z_ORDER                  = 0x40a << OPCODE_SHIFT,
+        SET_PRESENT_OR_VALIDATE_DISPLAY_RESULT = 0x40b << OPCODE_SHIFT,
 
         /** 0x800 - 0xfff are reserved for vendor extensions */
         /** 0x1000 - 0xffff are reserved */
diff --git a/graphics/composer/2.1/default/ComposerClient.cpp b/graphics/composer/2.1/default/ComposerClient.cpp
index ce4e17f..5a96e29 100644
--- a/graphics/composer/2.1/default/ComposerClient.cpp
+++ b/graphics/composer/2.1/default/ComposerClient.cpp
@@ -562,6 +562,8 @@
         return parseSetOutputBuffer(length);
     case IComposerClient::Command::VALIDATE_DISPLAY:
         return parseValidateDisplay(length);
+    case IComposerClient::Command::PRESENT_OR_VALIDATE_DISPLAY:
+        return parsePresentOrValidateDisplay(length);
     case IComposerClient::Command::ACCEPT_DISPLAY_CHANGES:
         return parseAcceptDisplayChanges(length);
     case IComposerClient::Command::PRESENT_DISPLAY:
@@ -739,6 +741,47 @@
     return true;
 }
 
+bool ComposerClient::CommandReader::parsePresentOrValidateDisplay(uint16_t length)
+{
+    if (length != CommandWriterBase::kPresentOrValidateDisplayLength) {
+        return false;
+    }
+
+    // First try to Present as is.
+    int presentFence = -1;
+    std::vector<Layer> layers;
+    std::vector<int> fences;
+    auto err = mHal.presentDisplay(mDisplay, &presentFence, &layers, &fences);
+    if (err == Error::NONE) {
+        mWriter.setPresentOrValidateResult(1);
+        mWriter.setPresentFence(presentFence);
+        mWriter.setReleaseFences(layers, fences);
+        return true;
+    }
+
+    // Present has failed. We need to fallback to validate
+    std::vector<Layer> changedLayers;
+    std::vector<IComposerClient::Composition> compositionTypes;
+    uint32_t displayRequestMask = 0x0;
+    std::vector<Layer> requestedLayers;
+    std::vector<uint32_t> requestMasks;
+
+    err = mHal.validateDisplay(mDisplay, &changedLayers,
+                               &compositionTypes, &displayRequestMask,
+                               &requestedLayers, &requestMasks);
+    if (err == Error::NONE) {
+        mWriter.setPresentOrValidateResult(0);
+        mWriter.setChangedCompositionTypes(changedLayers,
+                                           compositionTypes);
+        mWriter.setDisplayRequests(displayRequestMask,
+                                   requestedLayers, requestMasks);
+    } else {
+        mWriter.setError(getCommandLoc(), err);
+    }
+
+    return true;
+}
+
 bool ComposerClient::CommandReader::parseAcceptDisplayChanges(uint16_t length)
 {
     if (length != CommandWriterBase::kAcceptDisplayChangesLength) {
diff --git a/graphics/composer/2.1/default/ComposerClient.h b/graphics/composer/2.1/default/ComposerClient.h
index 3d10f80..ee825fe 100644
--- a/graphics/composer/2.1/default/ComposerClient.h
+++ b/graphics/composer/2.1/default/ComposerClient.h
@@ -141,6 +141,7 @@
         bool parseSetClientTarget(uint16_t length);
         bool parseSetOutputBuffer(uint16_t length);
         bool parseValidateDisplay(uint16_t length);
+        bool parsePresentOrValidateDisplay(uint16_t length);
         bool parseAcceptDisplayChanges(uint16_t length);
         bool parsePresentDisplay(uint16_t length);
         bool parseSetLayerCursorPosition(uint16_t length);
diff --git a/graphics/composer/2.1/default/IComposerCommandBuffer.h b/graphics/composer/2.1/default/IComposerCommandBuffer.h
index fb78ef8..9ee5f4f 100644
--- a/graphics/composer/2.1/default/IComposerCommandBuffer.h
+++ b/graphics/composer/2.1/default/IComposerCommandBuffer.h
@@ -152,6 +152,13 @@
         endCommand();
     }
 
+    static constexpr uint32_t kPresentOrValidateDisplayResultLength = 1;
+    void setPresentOrValidateResult(uint32_t  state) {
+       beginCommand(IComposerClient::Command::SET_PRESENT_OR_VALIDATE_DISPLAY_RESULT, kPresentOrValidateDisplayResultLength);
+       write(state);
+       endCommand();
+    }
+
     void setChangedCompositionTypes(const std::vector<Layer>& layers,
             const std::vector<IComposerClient::Composition>& types)
     {
@@ -284,6 +291,14 @@
         endCommand();
     }
 
+    static constexpr uint16_t kPresentOrValidateDisplayLength = 0;
+    void presentOrvalidateDisplay()
+    {
+        beginCommand(IComposerClient::Command::PRESENT_OR_VALIDATE_DISPLAY,
+                     kPresentOrValidateDisplayLength);
+        endCommand();
+    }
+
     static constexpr uint16_t kAcceptDisplayChangesLength = 0;
     void acceptDisplayChanges()
     {
diff --git a/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp
index 9854947..78353ea 100644
--- a/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -247,34 +247,47 @@
     return retval;
 }
 
-string rsa_key = hex2str("30820275020100300d06092a864886f70d01010105000482025f3082025b"
-                         "02010002818100c6095409047d8634812d5a218176e45c41d60a75b13901"
-                         "f234226cffe776521c5a77b9e389417b71c0b6a44d13afe4e4a2805d46c9"
-                         "da2935adb1ff0c1f24ea06e62b20d776430a4d435157233c6f916783c30e"
-                         "310fcbd89b85c2d56771169785ac12bca244abda72bfb19fc44d27c81e1d"
-                         "92de284f4061edfd99280745ea6d2502030100010281801be0f04d9cae37"
-                         "18691f035338308e91564b55899ffb5084d2460e6630257e05b3ceab0297"
-                         "2dfabcd6ce5f6ee2589eb67911ed0fac16e43a444b8c861e544a05933657"
-                         "72f8baf6b22fc9e3c5f1024b063ac080a7b2234cf8aee8f6c47bbf4fd3ac"
-                         "e7240290bef16c0b3f7f3cdd64ce3ab5912cf6e32f39ab188358afcccd80"
-                         "81024100e4b49ef50f765d3b24dde01aceaaf130f2c76670a91a61ae08af"
-                         "497b4a82be6dee8fcdd5e3f7ba1cfb1f0c926b88f88c92bfab137fba2285"
-                         "227b83c342ff7c55024100ddabb5839c4c7f6bf3d4183231f005b31aa58a"
-                         "ffdda5c79e4cce217f6bc930dbe563d480706c24e9ebfcab28a6cdefd324"
-                         "b77e1bf7251b709092c24ff501fd91024023d4340eda3445d8cd26c14411"
-                         "da6fdca63c1ccd4b80a98ad52b78cc8ad8beb2842c1d280405bc2f6c1bea"
-                         "214a1d742ab996b35b63a82a5e470fa88dbf823cdd02401b7b57449ad30d"
-                         "1518249a5f56bb98294d4b6ac12ffc86940497a5a5837a6cf946262b4945"
-                         "26d328c11e1126380fde04c24f916dec250892db09a6d77cdba351024077"
-                         "62cd8f4d050da56bd591adb515d24d7ccd32cca0d05f866d583514bd7324"
-                         "d5f33645e8ed8b4a1cb3cc4a1d67987399f2a09f5b3fb68c88d5e5d90ac3"
-                         "3492d6");
+string rsa_key = hex2str(
+    "30820275020100300d06092a864886f70d01010105000482025f3082025b"
+    "02010002818100c6095409047d8634812d5a218176e45c41d60a75b13901"
+    "f234226cffe776521c5a77b9e389417b71c0b6a44d13afe4e4a2805d46c9"
+    "da2935adb1ff0c1f24ea06e62b20d776430a4d435157233c6f916783c30e"
+    "310fcbd89b85c2d56771169785ac12bca244abda72bfb19fc44d27c81e1d"
+    "92de284f4061edfd99280745ea6d2502030100010281801be0f04d9cae37"
+    "18691f035338308e91564b55899ffb5084d2460e6630257e05b3ceab0297"
+    "2dfabcd6ce5f6ee2589eb67911ed0fac16e43a444b8c861e544a05933657"
+    "72f8baf6b22fc9e3c5f1024b063ac080a7b2234cf8aee8f6c47bbf4fd3ac"
+    "e7240290bef16c0b3f7f3cdd64ce3ab5912cf6e32f39ab188358afcccd80"
+    "81024100e4b49ef50f765d3b24dde01aceaaf130f2c76670a91a61ae08af"
+    "497b4a82be6dee8fcdd5e3f7ba1cfb1f0c926b88f88c92bfab137fba2285"
+    "227b83c342ff7c55024100ddabb5839c4c7f6bf3d4183231f005b31aa58a"
+    "ffdda5c79e4cce217f6bc930dbe563d480706c24e9ebfcab28a6cdefd324"
+    "b77e1bf7251b709092c24ff501fd91024023d4340eda3445d8cd26c14411"
+    "da6fdca63c1ccd4b80a98ad52b78cc8ad8beb2842c1d280405bc2f6c1bea"
+    "214a1d742ab996b35b63a82a5e470fa88dbf823cdd02401b7b57449ad30d"
+    "1518249a5f56bb98294d4b6ac12ffc86940497a5a5837a6cf946262b4945"
+    "26d328c11e1126380fde04c24f916dec250892db09a6d77cdba351024077"
+    "62cd8f4d050da56bd591adb515d24d7ccd32cca0d05f866d583514bd7324"
+    "d5f33645e8ed8b4a1cb3cc4a1d67987399f2a09f5b3fb68c88d5e5d90ac3"
+    "3492d6");
 
-string ec_key = hex2str("308187020100301306072a8648ce3d020106082a8648ce3d030107046d30"
-                        "6b0201010420737c2ecd7b8d1940bf2930aa9b4ed3ff941eed09366bc032"
-                        "99986481f3a4d859a14403420004bf85d7720d07c25461683bc648b4778a"
-                        "9a14dd8a024e3bdd8c7ddd9ab2b528bbc7aa1b51f14ebbbb0bd0ce21bcc4"
-                        "1c6eb00083cf3376d11fd44949e0b2183bfe");
+string ec_256_key = hex2str(
+    "308187020100301306072a8648ce3d020106082a8648ce3d030107046d30"
+    "6b0201010420737c2ecd7b8d1940bf2930aa9b4ed3ff941eed09366bc032"
+    "99986481f3a4d859a14403420004bf85d7720d07c25461683bc648b4778a"
+    "9a14dd8a024e3bdd8c7ddd9ab2b528bbc7aa1b51f14ebbbb0bd0ce21bcc4"
+    "1c6eb00083cf3376d11fd44949e0b2183bfe");
+
+string ec_521_key = hex2str(
+    "3081EE020100301006072A8648CE3D020106052B810400230481D63081D3"
+    "02010104420011458C586DB5DAA92AFAB03F4FE46AA9D9C3CE9A9B7A006A"
+    "8384BEC4C78E8E9D18D7D08B5BCFA0E53C75B064AD51C449BAE0258D54B9"
+    "4B1E885DED08ED4FB25CE9A1818903818600040149EC11C6DF0FA122C6A9"
+    "AFD9754A4FA9513A627CA329E349535A5629875A8ADFBE27DCB932C05198"
+    "6377108D054C28C6F39B6F2C9AF81802F9F326B842FF2E5F3C00AB7635CF"
+    "B36157FC0882D574A10D839C1A0C049DC5E0D775E2EE50671A208431BB45"
+    "E78E70BEFE930DB34818EE4D5C26259F5C6B8E28A652950F9F88D7B4B2C9"
+    "D9");
 
 struct RSA_Delete {
     void operator()(RSA* p) { RSA_free(p); }
@@ -2385,14 +2398,14 @@
 /*
  * ImportKeyTest.EcdsaSuccess
  *
- * Verifies that importing and using an ECDSA key pair works correctly.
+ * Verifies that importing and using an ECDSA P-256 key pair works correctly.
  */
 TEST_F(ImportKeyTest, EcdsaSuccess) {
     ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
                                            .Authorization(TAG_NO_AUTH_REQUIRED)
                                            .EcdsaSigningKey(256)
                                            .Digest(Digest::SHA_2_256),
-                                       KeyFormat::PKCS8, ec_key))
+                                       KeyFormat::PKCS8, ec_256_key))
         << "(Possibly b/33945114)";
 
     CheckKm0CryptoParam(TAG_ALGORITHM, Algorithm::EC);
@@ -2409,6 +2422,32 @@
 }
 
 /*
+ * ImportKeyTest.Ecdsa521Success
+ *
+ * Verifies that importing and using an ECDSA P-521 key pair works correctly.
+ */
+TEST_F(ImportKeyTest, Ecdsa521Success) {
+    ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+                                           .Authorization(TAG_NO_AUTH_REQUIRED)
+                                           .EcdsaSigningKey(521)
+                                           .Digest(Digest::SHA_2_256),
+                                       KeyFormat::PKCS8, ec_521_key))
+        << "(Possibly b/33945114)";
+
+    CheckKm0CryptoParam(TAG_ALGORITHM, Algorithm::EC);
+    CheckKm0CryptoParam(TAG_KEY_SIZE, 521U);
+    CheckKm1CryptoParam(TAG_DIGEST, Digest::SHA_2_256);
+    CheckKm2CryptoParam(TAG_EC_CURVE, EcCurve::P_521);
+
+    CheckOrigin();
+
+    string message(32, 'a');
+    auto params = AuthorizationSetBuilder().Digest(Digest::SHA_2_256);
+    string signature = SignMessage(message, params);
+    VerifyMessage(message, signature, params);
+}
+
+/*
  * ImportKeyTest.EcdsaSizeMismatch
  *
  * Verifies that importing an ECDSA key pair with a size that doesn't match the key fails in the
@@ -2419,7 +2458,7 @@
               ImportKey(AuthorizationSetBuilder()
                             .EcdsaSigningKey(224 /* Doesn't match key */)
                             .Digest(Digest::NONE),
-                        KeyFormat::PKCS8, ec_key));
+                        KeyFormat::PKCS8, ec_256_key));
 }
 
 /*
@@ -2438,7 +2477,7 @@
               ImportKey(AuthorizationSetBuilder()
                             .EcdsaSigningKey(EcCurve::P_224 /* Doesn't match key */)
                             .Digest(Digest::NONE),
-                        KeyFormat::PKCS8, ec_key))
+                        KeyFormat::PKCS8, ec_256_key))
         << "(Possibly b/36233241)";
 }
 
diff --git a/power/1.0/vts/functional/VtsHalPowerV1_0TargetTest.cpp b/power/1.0/vts/functional/VtsHalPowerV1_0TargetTest.cpp
index c94fa4f..da49dfc 100644
--- a/power/1.0/vts/functional/VtsHalPowerV1_0TargetTest.cpp
+++ b/power/1.0/vts/functional/VtsHalPowerV1_0TargetTest.cpp
@@ -77,6 +77,7 @@
   if (fd1 < 0 || fd2 < 0) {
     // Files don't exist, so skip the rest of the test case
     SUCCEED();
+    return;
   }
 
   char old_governor[80];
diff --git a/wifi/offload/1.0/IOffload.hal b/wifi/offload/1.0/IOffload.hal
index 7ad902c..4819519 100644
--- a/wifi/offload/1.0/IOffload.hal
+++ b/wifi/offload/1.0/IOffload.hal
@@ -25,21 +25,28 @@
      *
      * @param ScanParam paramters for scanning
      * @param ScanFilter settings to filter scan result
-     * @return boolean status indicating success (true) when configuration
-     *            is applied or failure (false) for invalid configuration
+     * @return OffloadStatus indicating status of operation provided by this API
+     * If OffloadStatusCode::OK is returned, the operation was successful
+     * If OffloadStatusCode::NO_CONNECTION is returned, connection to the hardware is lost
+     * If OffloadStatusCode::ERROR is returned, requested operation could not be completed
      */
     @entry
     @callflow(next={"setEventCallback", "subscribeScanResults"})
-    configureScans(ScanParam param, ScanFilter filter);
+    configureScans(ScanParam param, ScanFilter filter) generates (OffloadStatus status);
 
     /**
      * Get scan statistics
      *
+     * @return OffloadStatus indicating status of operation provided by this API
      * @return ScanStats statistics of scans performed
+     * If OffloadStatusCode::OK is returned, the operation was successful
+     * If OffloadStatusCode::NO_CONNECTION is returned, connection to the hardware is lost
+     * If OffloadStatusCode::ERROR is returned, requested operation could not be completed
+     * If OffloadStatusCode::TIMEOUT is returned, time out waiting for the requested data
      */
     @exit
     @callflow(next={"subscribeScanResults", "unsubscribeScanResults", "getScanStats"})
-    getScanStats() generates (ScanStats scanStats);
+    getScanStats() generates (OffloadStatus status, ScanStats scanStats);
 
     /**
      * Subscribe to asynchronous scan events sent by offload module. This enables
@@ -50,9 +57,13 @@
      *
      * @param delayMs an integer expressing the minimum delay in mS after
      *        subscribing when scan results must be delivered to the client
+     * @return OffloadStatus indicating status of operation provided by this API
+     * If OffloadStatusCode::OK is returned, the operation was successful
+     * If OffloadStatusCode::NO_CONNECTION is returned, connection to the hardware is lost
+     * If OffloadStatusCode::ERROR is returned, requested operation could not be completed
      */
     @callflow(next={"unsubscribeScanResults", "getScanStats"})
-    subscribeScanResults(uint32_t delayMs);
+    subscribeScanResults(uint32_t delayMs) generates (OffloadStatus status);
 
     /**
      * Unsubscribe to scan events sent by the offload module, hence disabling scans.
diff --git a/wifi/offload/1.0/types.hal b/wifi/offload/1.0/types.hal
index 38d5eda..234f3fc 100644
--- a/wifi/offload/1.0/types.hal
+++ b/wifi/offload/1.0/types.hal
@@ -202,18 +202,25 @@
 /**
  * Defines a list of return codes to indicate status of Offload HAL
  */
-enum OffloadStatus : uint32_t {
+enum OffloadStatusCode : uint32_t {
     /* No error */
-    OFFLOAD_STATUS_OK,
+    OK,
     /* No Connection to underlying implementation */
-    OFFLOAD_STATUS_NO_CONNECTION,
+    NO_CONNECTION,
     /* Operation timeout */
-    OFFLOAD_STATUS_TIMEOUT,
+    TIMEOUT,
     /* Other errors */
-    OFFLOAD_STATUS_ERROR
+    ERROR
 };
 
-
+/**
+ * Generic structures to return the status of an operation
+ */
+struct OffloadStatus {
+  OffloadStatusCode code;
+  /* Error message */
+  string description;
+};
 
 
 
diff --git a/wifi/offload/1.0/vts/functional/VtsHalWifiOffloadV1_0TargetTest.cpp b/wifi/offload/1.0/vts/functional/VtsHalWifiOffloadV1_0TargetTest.cpp
index 3020542..55f5a87 100644
--- a/wifi/offload/1.0/vts/functional/VtsHalWifiOffloadV1_0TargetTest.cpp
+++ b/wifi/offload/1.0/vts/functional/VtsHalWifiOffloadV1_0TargetTest.cpp
@@ -26,6 +26,8 @@
 
 #include <vector>
 
+#include "hidl_call_util.h"
+
 using ::android::hardware::wifi::offload::V1_0::IOffload;
 using ::android::hardware::wifi::offload::V1_0::IOffloadCallback;
 using ::android::hardware::wifi::offload::V1_0::ScanResult;
@@ -33,6 +35,7 @@
 using ::android::hardware::wifi::offload::V1_0::ScanFilter;
 using ::android::hardware::wifi::offload::V1_0::ScanStats;
 using ::android::hardware::wifi::offload::V1_0::OffloadStatus;
+using ::android::hardware::wifi::offload::V1_0::OffloadStatusCode;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
 using ::android::hardware::hidl_vec;
@@ -89,7 +92,7 @@
             return Void();
         };
 
-        Return<void> onError(OffloadStatus status) {
+        Return<void> onError(const OffloadStatus& status) override {
             OffloadCallbackArgs args;
             args.error_code_ = status;
             NotifyFromCallback(kOffloadCallbackSendError, args);
@@ -106,15 +109,15 @@
  */
 TEST_F(WifiOffloadHidlTest, setEventCallback) {
     auto returnObject = wifi_offload_->setEventCallback(wifi_offload_cb_);
-    ASSERT_EQ(returnObject.isOk(), true);
+    ASSERT_EQ(true, returnObject.isOk());
 }
 
 /*
  * Verify that subscribeScanResults method returns without errors
  */
 TEST_F(WifiOffloadHidlTest, subscribeScanResults) {
-    auto returnObject = wifi_offload_->subscribeScanResults(0);
-    ASSERT_EQ(returnObject.isOk(), true);
+    const auto& result = HIDL_INVOKE(wifi_offload_, subscribeScanResults, 0);
+    ASSERT_EQ(OffloadStatusCode::OK, result.code);
 }
 
 /*
@@ -122,7 +125,7 @@
  */
 TEST_F(WifiOffloadHidlTest, unsubscribeScanResults) {
     auto returnObject = wifi_offload_->unsubscribeScanResults();
-    ASSERT_EQ(returnObject.isOk(), true);
+    ASSERT_EQ(true, returnObject.isOk());
 }
 
 /*
@@ -131,21 +134,18 @@
 TEST_F(WifiOffloadHidlTest, configureScans) {
     ScanParam* pScanParam = new ScanParam();
     ScanFilter* pScanFilter = new ScanFilter();
-    auto returnObject =
-        wifi_offload_->configureScans(*pScanParam, *pScanFilter);
-    ASSERT_EQ(returnObject.isOk(), true);
+    const auto& result =
+        HIDL_INVOKE(wifi_offload_, configureScans, *pScanParam, *pScanFilter);
+    ASSERT_EQ(OffloadStatusCode::OK, result.code);
 }
 
 /*
  * Verify that getScanStats returns without any errors
  */
 TEST_F(WifiOffloadHidlTest, getScanStats) {
-    ScanStats* pScanStats = new ScanStats();
-    const auto& returnObject =
-        wifi_offload_->getScanStats([pScanStats](ScanStats scanStats) -> void {
-            *pScanStats = std::move(scanStats);
-        });
-    ASSERT_EQ(returnObject.isOk(), true);
+    const auto& result = HIDL_INVOKE(wifi_offload_, getScanStats);
+    OffloadStatus status = result.first;
+    ASSERT_EQ(OffloadStatusCode::OK, status.code);
 }
 
 /*
@@ -167,7 +167,7 @@
     wifi_offload_cb_->onScanResult(scan_results);
     auto res =
         wifi_offload_cb_->WaitForCallback(kOffloadCallbackSendScanResult);
-    ASSERT_EQ(res.no_timeout, true);
+    ASSERT_EQ(true, res.no_timeout);
 }
 
 /*
@@ -175,9 +175,10 @@
  */
 TEST_F(WifiOffloadHidlTest, getError) {
     wifi_offload_->setEventCallback(wifi_offload_cb_);
-    wifi_offload_cb_->onError(OffloadStatus::OFFLOAD_STATUS_ERROR);
+    OffloadStatus status = {OffloadStatusCode::ERROR, ""};
+    wifi_offload_cb_->onError(status);
     auto res = wifi_offload_cb_->WaitForCallback(kOffloadCallbackSendError);
-    ASSERT_EQ(res.no_timeout, true);
+    ASSERT_EQ(true, res.no_timeout);
 }
 
 // A class for test environment setup
diff --git a/wifi/offload/1.0/vts/functional/hidl_call_util.h b/wifi/offload/1.0/vts/functional/hidl_call_util.h
new file mode 100644
index 0000000..f3ca517
--- /dev/null
+++ b/wifi/offload/1.0/vts/functional/hidl_call_util.h
@@ -0,0 +1,123 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <functional>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+
+#include <VtsHalHidlTargetTestBase.h>
+
+namespace {
+namespace detail {
+template <typename>
+struct functionArgSaver;
+
+// Provides a std::function that takes one argument, and a buffer
+// wherein the function will store its argument. The buffer has
+// the same type as the argument, but with const and reference
+// modifiers removed.
+template <typename ArgT>
+struct functionArgSaver<std::function<void(ArgT)>> final {
+    using StorageT = typename std::remove_const<
+        typename std::remove_reference<ArgT>::type>::type;
+
+    std::function<void(ArgT)> saveArgs = [this](ArgT arg) {
+        this->saved_values = arg;
+    };
+
+    StorageT saved_values;
+};
+
+// Provides a std::function that takes two arguments, and a buffer
+// wherein the function will store its arguments. The buffer is a
+// std::pair, whose elements have the same types as the arguments
+// (but with const and reference modifiers removed).
+template <typename Arg1T, typename Arg2T>
+struct functionArgSaver<std::function<void(Arg1T, Arg2T)>> final {
+    using StorageT =
+        std::pair<typename std::remove_const<
+                      typename std::remove_reference<Arg1T>::type>::type,
+                  typename std::remove_const<
+                      typename std::remove_reference<Arg2T>::type>::type>;
+
+    std::function<void(Arg1T, Arg2T)> saveArgs = [this](Arg1T arg1,
+                                                        Arg2T arg2) {
+        this->saved_values = {arg1, arg2};
+    };
+
+    StorageT saved_values;
+};
+
+// Provides a std::function that takes three or more arguments, and a
+// buffer wherein the function will store its arguments. The buffer is a
+// std::tuple whose elements have the same types as the arguments (but
+// with const and reference modifiers removed).
+template <typename... ArgT>
+struct functionArgSaver<std::function<void(ArgT...)>> final {
+    using StorageT = std::tuple<typename std::remove_const<
+        typename std::remove_reference<ArgT>::type>::type...>;
+
+    std::function<void(ArgT...)> saveArgs = [this](ArgT... arg) {
+        this->saved_values = {arg...};
+    };
+
+    StorageT saved_values;
+};
+
+// Invokes |method| on |object|, providing |method| a CallbackT as the
+// final argument. Returns a copy of the parameters that |method| provided
+// to CallbackT. (The parameters are returned by value.)
+template <typename CallbackT, typename MethodT, typename ObjectT,
+          typename... ArgT>
+typename functionArgSaver<CallbackT>::StorageT invokeMethod(
+    MethodT method, ObjectT object, ArgT&&... methodArg) {
+    functionArgSaver<CallbackT> result_buffer;
+    const auto& res = ((*object).*method)(std::forward<ArgT>(methodArg)...,
+                                          result_buffer.saveArgs);
+    EXPECT_TRUE(res.isOk());
+    return result_buffer.saved_values;
+}
+}  // namespace detail
+}  // namespace
+
+// Invokes |method| on |strong_pointer|, passing provided arguments through to
+// |method|.
+//
+// Returns either:
+// - A copy of the result callback parameter (for callbacks with a single
+//   parameter), OR
+// - A pair containing a copy of the result callback parameters (for callbacks
+//   with two parameters), OR
+// - A tuple containing a copy of the result callback paramters (for callbacks
+//   with three or more parameters).
+//
+// Example usage:
+//   EXPECT_EQ(WifiStatusCode::SUCCESS,
+//       HIDL_INVOKE(strong_pointer, methodReturningWifiStatus).code);
+//   EXPECT_EQ(WifiStatusCode::SUCCESS,
+//       HIDL_INVOKE(strong_pointer, methodReturningWifiStatusAndOneMore)
+//         .first.code);
+//   EXPECT_EQ(WifiStatusCode::SUCCESS, std::get<0>(
+//       HIDL_INVOKE(strong_pointer, methodReturningWifiStatusAndTwoMore))
+//         .code);
+#define HIDL_INVOKE(strong_pointer, method, ...)                              \
+    (detail::invokeMethod<                                                    \
+        std::remove_reference<decltype(*strong_pointer)>::type::method##_cb>( \
+        &std::remove_reference<decltype(*strong_pointer)>::type::method,      \
+        strong_pointer, ##__VA_ARGS__))