Index: trunk/src/VBox/ValidationKit/utils/audio/vkat.cpp
===================================================================
--- trunk/src/VBox/ValidationKit/utils/audio/vkat.cpp	(revision 89584)
+++ trunk/src/VBox/ValidationKit/utils/audio/vkat.cpp	(revision 89614)
@@ -545,7 +545,31 @@
             if (RT_SUCCESS(rc))
                 rc = rc2;
+
             rc2 = AudioTestSvcClientTestSetEnd(&pTstEnv->u.Host.AtsClValKit, szTagHost);
             if (RT_SUCCESS(rc))
                 rc = rc2;
+
+            if (RT_SUCCESS(rc))
+            {
+                /*
+                 * Download guest test set to host.
+                 */
+                char szFileName[RTPATH_MAX];
+                if (RTStrPrintf2(szFileName, sizeof(szFileName), "%s.tar.gz", szTagGuest))
+                {
+                    char szFilePath[RTPATH_MAX];
+                    rc2 = RTPathJoin(szFilePath, sizeof(szFilePath), pTstEnv->szPathOut, szFileName);
+                    if (RT_SUCCESS(rc2))
+                    {
+                        RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Downloading guest test set to '%s'\n", szFilePath);
+                        rc2 = AudioTestSvcClientTestSetDownload(&pTstEnv->u.Host.AtsClGuest, szTagGuest, szFilePath);
+                    }
+                }
+                else
+                    rc2 = VERR_BUFFER_OVERFLOW;
+
+                if (RT_SUCCESS(rc))
+                    rc = rc2;
+            }
         }
     }
Index: trunk/src/VBox/ValidationKit/utils/audio/vkatCommon.cpp
===================================================================
--- trunk/src/VBox/ValidationKit/utils/audio/vkatCommon.cpp	(revision 89584)
+++ trunk/src/VBox/ValidationKit/utils/audio/vkatCommon.cpp	(revision 89614)
@@ -64,5 +64,11 @@
 typedef struct ATSCALLBACKCTX
 {
+    /** The test environment bound to this context. */
     PAUDIOTESTENV pTstEnv;
+    /** Absolute path to the packed up test set archive.
+     *  Keep it simple for now and only support one (open) archive at a time. */
+    char          szTestSetArchive[RTPATH_MAX];
+    /** File handle to the (opened) test set archive for reading. */
+    RTFILE        hTestSetArchive;
 } ATSCALLBACKCTX;
 typedef ATSCALLBACKCTX *PATSCALLBACKCTX;
@@ -421,5 +427,6 @@
     RTTestPrintf(g_hTest, RTTESTLVL_DEBUG, "Ending test set '%s'\n", pszTag);
 
-    return audioTestEnvPrologue(pTstEnv);
+    /* Pack up everything to be ready for transmission. */
+    return audioTestEnvPrologue(pTstEnv, true /* fPack */, pCtx->szTestSetArchive, sizeof(pCtx->szTestSetArchive));
 }
 
@@ -507,4 +514,53 @@
     else
         RTTestFailed(g_hTest, "Error creating input stream, rc=%Rrc\n", rc);
+
+    return rc;
+}
+
+/** @copydoc ATSCALLBACKS::pfnTestSetSendBegin */
+static DECLCALLBACK(int) audioTestGstAtsTestSetSendBeginCallback(void const *pvUser, const char *pszTag)
+{
+    RT_NOREF(pszTag);
+
+    PATSCALLBACKCTX pCtx = (PATSCALLBACKCTX)pvUser;
+
+    if (!RTFileExists(pCtx->szTestSetArchive)) /* Has the archive successfully been created yet? */
+        return VERR_WRONG_ORDER;
+
+    int rc = RTFileOpen(&pCtx->hTestSetArchive, pCtx->szTestSetArchive, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
+    if (RT_SUCCESS(rc))
+    {
+        uint64_t uSize;
+        rc = RTFileQuerySize(pCtx->hTestSetArchive, &uSize);
+        if (RT_SUCCESS(rc))
+            RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Sending test set '%s' (%zu bytes)\n", pCtx->szTestSetArchive, uSize);
+    }
+
+    return rc;
+}
+
+/** @copydoc ATSCALLBACKS::pfnTestSetSendRead */
+static DECLCALLBACK(int) audioTestGstAtsTestSetSendReadCallback(void const *pvUser,
+                                                                const char *pszTag, void *pvBuf, size_t cbBuf, size_t *pcbRead)
+{
+    RT_NOREF(pszTag);
+
+    PATSCALLBACKCTX pCtx = (PATSCALLBACKCTX)pvUser;
+
+    return RTFileRead(pCtx->hTestSetArchive, pvBuf, cbBuf, pcbRead);
+}
+
+/** @copydoc ATSCALLBACKS::pfnTestSetSendEnd */
+static DECLCALLBACK(int) audioTestGstAtsTestSetSendEndCallback(void const *pvUser, const char *pszTag)
+{
+    RT_NOREF(pszTag);
+
+    PATSCALLBACKCTX pCtx = (PATSCALLBACKCTX)pvUser;
+
+    int rc = RTFileClose(pCtx->hTestSetArchive);
+    if (RT_SUCCESS(rc))
+    {
+        pCtx->hTestSetArchive = NIL_RTFILE;
+    }
 
     return rc;
@@ -658,9 +714,12 @@
 
         ATSCALLBACKS Callbacks;
-        Callbacks.pfnTestSetBegin = audioTestGstAtsTestSetBeginCallback;
-        Callbacks.pfnTestSetEnd   = audioTestGstAtsTestSetEndCallback;
-        Callbacks.pfnTonePlay     = audioTestGstAtsTonePlayCallback;
-        Callbacks.pfnToneRecord   = audioTestGstAtsToneRecordCallback;
-        Callbacks.pvUser          = &Ctx;
+        Callbacks.pfnTestSetBegin     = audioTestGstAtsTestSetBeginCallback;
+        Callbacks.pfnTestSetEnd       = audioTestGstAtsTestSetEndCallback;
+        Callbacks.pfnTonePlay         = audioTestGstAtsTonePlayCallback;
+        Callbacks.pfnToneRecord       = audioTestGstAtsToneRecordCallback;
+        Callbacks.pfnTestSetSendBegin = audioTestGstAtsTestSetSendBeginCallback;
+        Callbacks.pfnTestSetSendRead  = audioTestGstAtsTestSetSendReadCallback;
+        Callbacks.pfnTestSetSendEnd   = audioTestGstAtsTestSetSendEndCallback;
+        Callbacks.pvUser              = &Ctx;
 
         /*
@@ -725,16 +784,23 @@
  * @returns VBox status code.
  * @param   pTstEnv             Test environment to handle.
- */
-int audioTestEnvPrologue(PAUDIOTESTENV pTstEnv)
+ * @param   fPack               Whether to pack the test set up before destroying / wiping it.
+ * @param   pszPackFile         Where to store the packed test set file on success. Can be NULL if \a fPack is \c false.
+ * @param   cbPackFile          Size (in bytes) of \a pszPackFile. Can be 0 if \a fPack is \c false.
+ */
+int audioTestEnvPrologue(PAUDIOTESTENV pTstEnv, bool fPack, char *pszPackFile, size_t cbPackFile)
 {
     /* Close the test set first. */
     AudioTestSetClose(&pTstEnv->Set);
 
-    /* Before destroying the test environment, pack up the test set so
-     * that it's ready for transmission. */
-    char szFileOut[RTPATH_MAX];
-    int rc = AudioTestSetPack(&pTstEnv->Set, pTstEnv->szPathOut, szFileOut, sizeof(szFileOut));
-    if (RT_SUCCESS(rc))
-        RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Test set packed up to '%s'\n", szFileOut);
+    int rc = VINF_SUCCESS;
+
+    if (fPack)
+    {
+        /* Before destroying the test environment, pack up the test set so
+         * that it's ready for transmission. */
+        rc = AudioTestSetPack(&pTstEnv->Set, pTstEnv->szPathOut, pszPackFile, cbPackFile);
+        if (RT_SUCCESS(rc))
+            RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Test set packed up to '%s'\n", pszPackFile);
+    }
 
     /* ignore rc */ AudioTestSetWipe(&pTstEnv->Set);
Index: trunk/src/VBox/ValidationKit/utils/audio/vkatInternal.h
===================================================================
--- trunk/src/VBox/ValidationKit/utils/audio/vkatInternal.h	(revision 89584)
+++ trunk/src/VBox/ValidationKit/utils/audio/vkatInternal.h	(revision 89614)
@@ -420,5 +420,5 @@
 int         audioTestEnvInit(PAUDIOTESTENV pTstEnv, PCPDMDRVREG pDrvReg, bool fWithDrvAudio, const char *pszHostTcpAddr, uint32_t uHostTcpPort, const char *pszGuestTcpAddr, uint32_t uGuestTcpPort);
 void        audioTestEnvDestroy(PAUDIOTESTENV pTstEnv);
-int         audioTestEnvPrologue(PAUDIOTESTENV pTstEnv);
+int         audioTestEnvPrologue(PAUDIOTESTENV pTstEnv, bool fPack, char *pszFilePath, size_t cbFilePath);
 
 void        audioTestParmsInit(PAUDIOTESTPARMS pTstParms);
