VirtualBox

Changeset 89383 in vbox for trunk/src


Ignore:
Timestamp:
May 31, 2021 7:26:13 AM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
144734
Message:

Audio/ValKit: More validation / test set handling code. bugref:10008

Location:
trunk/src/VBox
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • TabularUnified trunk/src/VBox/Devices/Audio/AudioTest.cpp

    r89316 r89383  
    2727#include <iprt/buildconfig.h>
    2828#include <iprt/dir.h>
     29#include <iprt/env.h>
    2930#include <iprt/file.h>
    3031#include <iprt/formats/riff.h>
     
    606607    AssertReturn(pszTag && strlen(pszTag) <= AUDIOTEST_TAG_MAX, VERR_INVALID_PARAMETER);
    607608
    608     char szPath[RTPATH_MAX];
    609 
    610     int rc = RTPathTemp(szPath, sizeof(szPath));
    611     AssertRCReturn(rc, rc);
    612     rc = AudioTestPathCreate(szPath, sizeof(szPath), pszTag);
    613     AssertRCReturn(rc, rc);
    614 
    615     return RTStrCopy(pszPath, cbPath, szPath);
     609    char szTemp[RTPATH_MAX];
     610    int rc = RTEnvGetEx(RTENV_DEFAULT, "TESTBOX_PATH_SCRATCH", szTemp, sizeof(szTemp), NULL);
     611    if (RT_FAILURE(rc))
     612    {
     613        rc = RTPathTemp(szTemp, sizeof(szTemp));
     614        AssertRCReturn(rc, rc);
     615    }
     616
     617    rc = AudioTestPathCreate(szTemp, sizeof(szTemp), pszTag);
     618    AssertRCReturn(rc, rc);
     619
     620    return RTStrCopy(pszPath, cbPath, szTemp);
    616621}
    617622
     
    12241229}
    12251230
     1231static int audioTestVerifyIniValue(PAUDIOTESTSET pSetA, PAUDIOTESTSET pSetB,
     1232                                   const char *pszSec, const char *pszKey, const char *pszVal)
     1233{
     1234    char szValA[_1K];
     1235    int rc = RTIniFileQueryValue(pSetA->f.hIniFile, pszSec, pszKey, szValA, sizeof(szValA), NULL);
     1236    if (RT_FAILURE(rc))
     1237        return rc;
     1238    char szValB[_1K];
     1239    rc = RTIniFileQueryValue(pSetB->f.hIniFile, pszSec, pszKey, szValB, sizeof(szValB), NULL);
     1240    if (RT_FAILURE(rc))
     1241        return rc;
     1242
     1243    if (RTStrCmp(szValA, szValB))
     1244        return VERR_WRONG_TYPE; /** @todo Fudge! */
     1245
     1246    if (pszVal)
     1247    {
     1248        if (RTStrCmp(szValA, pszVal))
     1249            return VERR_WRONG_TYPE; /** @todo Fudge! */
     1250    }
     1251
     1252    return rc;
     1253}
     1254
    12261255/**
    12271256 * Verifies an opened audio test set.
    12281257 *
    12291258 * @returns VBox status code.
    1230  * @param   pSet                Test set to verify.
    1231  * @param   pszTag              Tag to use for verification purpose.
     1259 * @param   pSetA               Test set A to verify.
     1260 * @param   pSetB               Test set to verify test set A with.
    12321261 * @param   pErrDesc            Where to return the test verification errors.
    12331262 *
     
    12351264 *          actual return code.
    12361265 */
    1237 int AudioTestSetVerify(PAUDIOTESTSET pSet, const char *pszTag, PAUDIOTESTERRORDESC pErrDesc)
    1238 {
    1239     AssertReturn(audioTestManifestIsOpen(pSet), VERR_WRONG_ORDER);
     1266int AudioTestSetVerify(PAUDIOTESTSET pSetA, PAUDIOTESTSET pSetB, PAUDIOTESTERRORDESC pErrDesc)
     1267{
     1268    AssertReturn(audioTestManifestIsOpen(pSetA), VERR_WRONG_ORDER);
     1269    AssertReturn(audioTestManifestIsOpen(pSetB), VERR_WRONG_ORDER);
    12401270
    12411271    /* We ASSUME the caller has not init'd pErrDesc. */
    12421272    audioTestErrorDescInit(pErrDesc);
    12431273
    1244     char szVal[_1K]; /** @todo Enough, too much? */
    1245 
    1246     int rc2 = RTIniFileQueryValue(pSet->f.hIniFile, AUDIOTEST_INI_SEC_HDR_STR, "tag", szVal, sizeof(szVal), NULL);
    1247     if (   RT_FAILURE(rc2)
    1248         || RTStrICmp(pszTag, szVal))
    1249         audioTestErrorDescAdd(pErrDesc, "Tag '%s' does not match with manifest's tag '%s'", pszTag, szVal);
     1274    int rc;
     1275
     1276#define VERIFY_VALUE(a_Sec, a_Key, a_Val, ...) \
     1277    rc = audioTestVerifyIniValue(pSetA, pSetB, a_Sec, a_Key, a_Val); \
     1278    if (RT_FAILURE(rc)) \
     1279        return audioTestErrorDescAdd(pErrDesc, (__VA_ARGS__));
     1280
     1281    /*
     1282     * Compare obvious values first.
     1283     */
     1284    VERIFY_VALUE("header",   "magic",        "vkat_ini",    "Manifest magic wrong");
     1285    VERIFY_VALUE("header",   "ver",          "1"       ,    "Manifest version wrong");
     1286    VERIFY_VALUE("header",   "tag",          NULL,          "Manifest tags don't match");
     1287    VERIFY_VALUE("header",   "test_count",   NULL,          "Test counts don't match");
     1288    VERIFY_VALUE("header",   "obj_count",    NULL,          "Object counts don't match");
     1289
     1290#undef VERIFY_VALUE
    12501291
    12511292    /* Only return critical stuff not related to actual testing here. */
  • TabularUnified trunk/src/VBox/Devices/Audio/AudioTest.h

    r89316 r89383  
    337337int    AudioTestSetPack(PAUDIOTESTSET pSet, const char *pszOutDir, char *pszFileName, size_t cbFileName);
    338338int    AudioTestSetUnpack(const char *pszFile, const char *pszOutDir);
    339 int    AudioTestSetVerify(PAUDIOTESTSET pSet, const char *pszTag, PAUDIOTESTERRORDESC pErrDesc);
     339int    AudioTestSetVerify(PAUDIOTESTSET pSetA, PAUDIOTESTSET pSetB, PAUDIOTESTERRORDESC pErrDesc);
    340340
    341341bool   AudioTestErrorDescFailed(PAUDIOTESTERRORDESC pErr);
  • TabularUnified trunk/src/VBox/Devices/Audio/DrvHostAudioValidationKit.cpp

    r89308 r89383  
    4949    /** The stream's acquired configuration. */
    5050    PDMAUDIOSTREAMCFG       Cfg;
    51     /** Audio file to dump output to or read input from. */
    52     PAUDIOHLPFILE           pFile;
    53     /** Text file to store timing of audio buffers submittions. */
    54     PRTSTREAM               pFileTiming;
    55     /** Timestamp of the first play or record request. */
    56     uint64_t                tsStarted;
    57     /** Total number of frames played or recorded so far. */
    58     uint32_t                cFramesSinceStarted;
    59     union
    60     {
    61         struct
    62         {
    63             /** Timestamp of last captured samples. */
    64             uint64_t        tsLastCaptured;
    65         } In;
    66         struct
    67         {
    68             /** Timestamp of last played samples. */
    69             uint64_t        tsLastPlayed;
    70             uint8_t        *pbPlayBuffer;
    71             uint32_t        cbPlayBuffer;
    72         } Out;
    73     };
    7451} VALKITAUDIOSTREAM;
    7552/** Pointer to a Validation Kit stream. */
     
    212189                                             PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
    213190{
    214     RT_NOREF(pThis, pCfgAcq);
    215 
    216     /* Use the test box scratch dir if we're running in such an
    217        environment, otherwise just dump the output in the temp
    218        directory. */
    219     char szTemp[RTPATH_MAX];
    220     int rc = RTEnvGetEx(RTENV_DEFAULT, "TESTBOX_PATH_SCRATCH", szTemp, sizeof(szTemp), NULL);
    221     if (RT_FAILURE(rc))
    222     {
    223         rc = RTPathTemp(szTemp, sizeof(szTemp));
    224         if (RT_SUCCESS(rc))
    225             rc = RTPathAppend(szTemp, sizeof(szTemp), "VBoxAudioValKit");
    226         AssertRCReturn(rc, rc);
    227     }
    228 
    229     /* Get down to things that may fail and need cleanup. */
    230     pStreamDbg->tsStarted           = 0;
    231     pStreamDbg->cFramesSinceStarted = 0;
    232     pStreamDbg->Out.tsLastPlayed    = 0;
    233     pStreamDbg->Out.cbPlayBuffer    = PDMAudioPropsFramesToBytes(&pCfgReq->Props, pCfgReq->Backend.cFramesBufferSize);
    234     pStreamDbg->Out.pbPlayBuffer    = (uint8_t *)RTMemAlloc(pStreamDbg->Out.cbPlayBuffer);
    235     AssertReturn(pStreamDbg->Out.pbPlayBuffer, VERR_NO_MEMORY);
    236 
    237     rc = AudioHlpFileCreateAndOpenEx(&pStreamDbg->pFile, AUDIOHLPFILETYPE_WAV, szTemp, "ValKit",
    238                                      pThis->pDrvIns->iInstance, AUDIOHLPFILENAME_FLAGS_NONE, AUDIOHLPFILE_FLAGS_NONE,
    239                                      &pCfgReq->Props, AUDIOHLPFILE_DEFAULT_OPEN_FLAGS);
    240     if (RT_SUCCESS(rc))
    241     {
    242         rc = RTPathAppend(szTemp, sizeof(szTemp), "ValKitTimings.txt");
    243         if (RT_SUCCESS(rc))
    244         {
    245             rc = RTStrmOpen(szTemp, "w", &pStreamDbg->pFileTiming);
    246             if (RT_SUCCESS(rc))
    247             {
    248                 RTStrmPrintf(pStreamDbg->pFileTiming, "# %uHz %uch %ubit\n",
    249                              PDMAudioPropsHz(&pCfgReq->Props),
    250                              PDMAudioPropsChannels(&pCfgReq->Props),
    251                              PDMAudioPropsSampleBits(&pCfgReq->Props));
    252                 return VINF_SUCCESS;
    253             }
    254 
    255             LogRel(("ValKitAudio: Opening output file '%s' failed: %Rrc\n", szTemp, rc));
    256         }
    257         else
    258             LogRel(("ValKitAudio: Constructing timing file path: %Rrc\n", rc));
    259 
    260         AudioHlpFileDestroy(pStreamDbg->pFile);
    261         pStreamDbg->pFile = NULL;
    262     }
    263     else
    264         LogRel(("ValKitAudio: Creating output file 'ValKit' in '%s' failed: %Rrc\n", szTemp, rc));
    265 
    266     RTMemFree(pStreamDbg->Out.pbPlayBuffer);
    267     pStreamDbg->Out.pbPlayBuffer = NULL;
    268     return rc;
     191    RT_NOREF(pThis, pStreamDbg, pCfgReq, pCfgAcq);
     192
     193    return VINF_SUCCESS;
    269194}
    270195
     
    276201                                                           PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
    277202{
    278     PDRVHOSTVALKITAUDIO pThis       = RT_FROM_MEMBER(pInterface, DRVHOSTVALKITAUDIO, IHostAudio);
     203    PDRVHOSTVALKITAUDIO pThis      = RT_FROM_MEMBER(pInterface, DRVHOSTVALKITAUDIO, IHostAudio);
    279204    PVALKITAUDIOSTREAM  pStreamDbg = (PVALKITAUDIOSTREAM)pStream;
    280205    AssertPtrReturn(pStreamDbg, VERR_INVALID_POINTER);
     
    302227    AssertPtrReturn(pStreamDbg, VERR_INVALID_POINTER);
    303228
    304     if (   pStreamDbg->Cfg.enmDir == PDMAUDIODIR_OUT
    305         && pStreamDbg->Out.pbPlayBuffer)
    306     {
    307         RTMemFree(pStreamDbg->Out.pbPlayBuffer);
    308         pStreamDbg->Out.pbPlayBuffer = NULL;
    309     }
    310 
    311     if (pStreamDbg->pFile)
    312     {
    313         size_t cbDataSize = AudioHlpFileGetDataSize(pStreamDbg->pFile);
    314         if (cbDataSize)
    315             LogRel(("ValKitAudio: Created output file '%s' (%zu bytes)\n", pStreamDbg->pFile->szName, cbDataSize));
    316 
    317         AudioHlpFileDestroy(pStreamDbg->pFile);
    318         pStreamDbg->pFile = NULL;
    319     }
    320 
    321     if (pStreamDbg->pFileTiming)
    322     {
    323         RTStrmClose(pStreamDbg->pFileTiming);
    324         pStreamDbg->pFileTiming = NULL;
    325     }
    326 
    327229    return VINF_SUCCESS;
    328230}
     
    348250    PVALKITAUDIOSTREAM pStreamDbg = (PVALKITAUDIOSTREAM)pStream;
    349251    AssertPtrReturn(pStreamDbg, VERR_INVALID_POINTER);
    350 
    351     if (pStreamDbg->pFileTiming)
    352         RTStrmFlush(pStreamDbg->pFileTiming);
    353252
    354253    return VINF_SUCCESS;
     
    429328    PDRVHOSTVALKITAUDIO pThis      = RT_FROM_MEMBER(pInterface, DRVHOSTVALKITAUDIO, IHostAudio);
    430329    PVALKITAUDIOSTREAM  pStreamDbg = (PVALKITAUDIOSTREAM)pStream;
    431     RT_NOREF(pThis);
    432 
    433     uint64_t cNsSinceStart;
    434     if (pStreamDbg->tsStarted != 0)
    435         cNsSinceStart = RTTimeNanoTS() - pStreamDbg->tsStarted;
    436     else
    437     {
    438         pStreamDbg->tsStarted = RTTimeNanoTS();
    439         cNsSinceStart = 0;
    440     }
    441 
    442     // Microseconds are used everythere below
    443     uint32_t const cFrames = PDMAudioPropsBytesToFrames(&pStreamDbg->Cfg.Props, cbBuf);
    444     RTStrmPrintf(pStreamDbg->pFileTiming, "%d %d %d %d\n",
    445                  // Host time elapsed since Guest submitted the first buffer for playback:
    446                  (uint32_t)(cNsSinceStart / 1000),
    447                  // how long all the samples submitted previously were played:
    448                  (uint32_t)(pStreamDbg->cFramesSinceStarted * 1.0E6 / pStreamDbg->Cfg.Props.uHz),
    449                  // how long a new uSamplesReady samples should/will be played:
    450                  (uint32_t)(cFrames * 1.0E6 / pStreamDbg->Cfg.Props.uHz),
    451                  cFrames);
    452 
    453     pStreamDbg->cFramesSinceStarted += cFrames;
    454 
    455     /* Remember when samples were consumed. */
    456     // pStreamDbg->Out.tsLastPlayed = PDMDrvHlpTMGetVirtualTime(pThis->pDrvIns);
    457 
    458     int rc2 = AudioHlpFileWrite(pStreamDbg->pFile, pvBuf, cbBuf, 0 /* fFlags */);
    459     if (RT_FAILURE(rc2))
    460         LogRel(("ValKitAudio: Writing output failed with %Rrc\n", rc2));
    461 
    462     *pcbWritten = cbBuf;
     330    RT_NOREF(pThis, pStreamDbg, pvBuf, cbBuf);
     331
     332    *pcbWritten = 0;
    463333    return VINF_SUCCESS;
    464334}
  • TabularUnified trunk/src/VBox/ValidationKit/utils/audio/vkat.cpp

    r89380 r89383  
    22162216*********************************************************************************************************************************/
    22172217
    2218 /**
    2219  * Verifies one single test set.
    2220  *
    2221  * @returns VBox status code.
    2222  * @param   pszPath             Absolute path to test set.
    2223  * @param   pszTag              Tag of test set to verify. Optional and can be NULL.
    2224  */
    2225 static int audioVerifyOne(const char *pszPath, const char *pszTag)
    2226 {
    2227     RTTestSubF(g_hTest, "Verifying test set ...");
    2228 
    2229     RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Using tag '%s'\n", pszTag ? pszTag : "default");
    2230     RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Opening archive '%s'\n", pszPath);
    2231 
    2232     int rc = VINF_SUCCESS;
     2218static int audioVerifyOpenTestSet(const char *pszPathSet, PAUDIOTESTSET pSet)
     2219{
     2220    int rc;
    22332221
    22342222    char szPathExtracted[RTPATH_MAX];
    2235     const bool fPacked = AudioTestSetIsPacked(pszPath);
     2223
     2224    RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Opening test set '%s'\n", pszPathSet);
     2225
     2226    const bool fPacked = AudioTestSetIsPacked(pszPathSet);
    22362227    if (fPacked)
    22372228    {
     2229        RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Test set is an archive and needs to be unpacked\n");
     2230
    22382231        char szPathTemp[RTPATH_MAX];
    22392232        rc = RTPathTemp(szPathTemp, sizeof(szPathTemp));
     
    22492242                {
    22502243                    RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Unpacking archive to '%s'\n", szPathExtracted);
    2251                     rc = AudioTestSetUnpack(pszPath, szPathExtracted);
     2244                    rc = AudioTestSetUnpack(pszPathSet, szPathExtracted);
    22522245                    if (RT_SUCCESS(rc))
    22532246                        RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Archive successfully unpacked\n");
     
    22562249        }
    22572250    }
     2251    else
     2252        rc = VINF_SUCCESS;
     2253
     2254    if (RT_SUCCESS(rc))
     2255        rc = AudioTestSetOpen(pSet, fPacked ? szPathExtracted : pszPathSet);
    22582256
    22592257    if (RT_FAILURE(rc))
    2260     {
    22612258        RTTestFailed(g_hTest, "Unable to open / unpack test set archive: %Rrc", rc);
    2262         return rc;
    2263     }
    2264 
    2265     AUDIOTESTSET tstSet;
    2266     rc = AudioTestSetOpen(&tstSet, fPacked ? szPathExtracted : pszPath);
     2259
     2260    return rc;
     2261}
     2262
     2263/**
     2264 * Verifies one single test set.
     2265 *
     2266 * @returns VBox status code.
     2267 * @param   pszPathSetA         Absolute path to test set A.
     2268 * @param   pszPathSetB         Absolute path to test set B.
     2269 */
     2270static int audioVerifyOne(const char *pszPathSetA, const char *pszPathSetB)
     2271{
     2272    RTTestSubF(g_hTest, "Verifying");
     2273    RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Verifying test set '%s' with test set '%s'\n", pszPathSetA, pszPathSetB);
     2274
     2275    AUDIOTESTSET SetA, SetB;
     2276    int rc = audioVerifyOpenTestSet(pszPathSetA, &SetA);
    22672277    if (RT_SUCCESS(rc))
     2278        rc = audioVerifyOpenTestSet(pszPathSetB, &SetB);
     2279
     2280    if (RT_SUCCESS(rc))
    22682281    {
    22692282        AUDIOTESTERRORDESC errDesc;
    2270         rc = AudioTestSetVerify(&tstSet, pszTag ? pszTag : "default", &errDesc);
     2283        rc = AudioTestSetVerify(&SetA, &SetB, &errDesc);
    22712284        if (RT_SUCCESS(rc))
    22722285        {
     
    22762289                PAUDIOTESTERRORENTRY pErrEntry;
    22772290                RTListForEach(&errDesc.List, pErrEntry, AUDIOTESTERRORENTRY, Node)
    2278                 {
    22792291                    RTTestFailed(g_hTest, pErrEntry->szDesc);
    2280                 }
    22812292            }
    22822293            else
    2283                 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Verification successful");
     2294                RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Verification successful\n");
    22842295
    22852296            AudioTestErrorDescDestroy(&errDesc);
     
    22872298        else
    22882299            RTTestFailed(g_hTest, "Verification failed with %Rrc", rc);
    2289 
    2290         AudioTestSetClose(&tstSet);
    2291     }
    2292     else
    2293         RTTestFailed(g_hTest, "Opening test set '%s' (tag '%s') failed, rc=%Rrc\n", pszPath, pszTag, rc);
     2300    }
     2301
     2302    AudioTestSetClose(&SetA);
     2303    AudioTestSetClose(&SetB);
    22942304
    22952305    RTTestSubDone(g_hTest);
     
    23092319     * Parse options and process arguments.
    23102320     */
    2311     const char   *pszTag   = NULL; /* Custom tag to use. Can be NULL if not being used. */
    2312     unsigned      iTestSet = 0;
     2321    char     *pszSetA = NULL;
     2322    char     *pszSetB = NULL;
     2323    unsigned iTestSet = 0;
    23132324
    23142325    int           rc;
     
    23192330        {
    23202331            case VKAT_VERIFY_OPT_TAG:
    2321                 pszTag = ValueUnion.psz;
    2322                 if (g_uVerbosity > 0)
    2323                     RTMsgInfo("Using tag '%s'\n", pszTag);
    23242332                break;
    23252333
    23262334            case VINF_GETOPT_NOT_OPTION:
     2335            {
     2336                char **ppszSet = iTestSet == 0 ? &pszSetA : &pszSetB;
     2337
    23272338                if (iTestSet == 0)
    23282339                    RTTestBanner(g_hTest);
    2329                 audioVerifyOne(ValueUnion.psz, pszTag);
     2340
     2341                *ppszSet = RTStrDup(ValueUnion.psz);
     2342                AssertPtrReturn(*ppszSet, RTEXITCODE_FAILURE);
     2343
    23302344                iTestSet++;
    23312345                break;
     2346            }
    23322347
    23332348            AUDIO_TEST_COMMON_OPTION_CASES(ValueUnion);
     
    23382353    }
    23392354
     2355    if (!iTestSet)
     2356        return RTMsgErrorExitFailure("At least one test set must be specified");
     2357
     2358    if (iTestSet > 2)
     2359        return RTMsgErrorExitFailure("Only two test sets can be verified at one time");
     2360
    23402361    /*
    2341      * If no paths given, default to the current directory.
     2362     * If only test set A is given, default to the current directory
     2363     * for test set B.
    23422364     */
    2343     if (iTestSet == 0)
    2344     {
    2345         if (iTestSet == 0)
    2346             RTTestBanner(g_hTest);
     2365    if (iTestSet == 1)
     2366    {
    23472367        char szDirCur[RTPATH_MAX];
    2348         int rc2 = RTPathGetCurrent(szDirCur, sizeof(szDirCur));
    2349         if (RT_FAILURE(rc2))
    2350             RTTestFailed(g_hTest, "Failed to retrieve current directory: %Rrc", rc2);
    2351         rc = audioVerifyOne(RT_SUCCESS(rc2) ? szDirCur : ".", pszTag);
    2352     }
     2368        rc = RTPathGetCurrent(szDirCur, sizeof(szDirCur));
     2369        if (RT_SUCCESS(rc))
     2370        {
     2371            Assert(pszSetB == NULL);
     2372            pszSetB = RTStrDup(szDirCur);
     2373            AssertPtrReturn(pszSetB, RTEXITCODE_FAILURE);
     2374        }
     2375        else
     2376            RTTestFailed(g_hTest, "Failed to retrieve current directory: %Rrc", rc);
     2377    }
     2378
     2379    if (RT_SUCCESS(rc))
     2380        rc = audioVerifyOne(pszSetA, pszSetB);
     2381
     2382    RTStrFree(pszSetA);
     2383    RTStrFree(pszSetB);
    23532384
    23542385    /*
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette