1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "media_omx_hidl_audio_dec_test"
18#ifdef __LP64__
19#define OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
20#endif
21
22#include <android-base/logging.h>
23
24#include <android/hardware/media/omx/1.0/IOmx.h>
25#include <android/hardware/media/omx/1.0/IOmxNode.h>
26#include <android/hardware/media/omx/1.0/IOmxObserver.h>
27#include <android/hardware/media/omx/1.0/types.h>
28#include <android/hidl/allocator/1.0/IAllocator.h>
29#include <android/hidl/memory/1.0/IMapper.h>
30#include <android/hidl/memory/1.0/IMemory.h>
31
32using ::android::hardware::media::omx::V1_0::IOmx;
33using ::android::hardware::media::omx::V1_0::IOmxObserver;
34using ::android::hardware::media::omx::V1_0::IOmxNode;
35using ::android::hardware::media::omx::V1_0::Message;
36using ::android::hardware::media::omx::V1_0::CodecBuffer;
37using ::android::hardware::media::omx::V1_0::PortMode;
38using ::android::hidl::allocator::V1_0::IAllocator;
39using ::android::hidl::memory::V1_0::IMemory;
40using ::android::hidl::memory::V1_0::IMapper;
41using ::android::hardware::Return;
42using ::android::hardware::Void;
43using ::android::hardware::hidl_vec;
44using ::android::hardware::hidl_string;
45using ::android::sp;
46
47#include <VtsHalHidlTargetTestBase.h>
48#include <getopt.h>
49#include <media_audio_hidl_test_common.h>
50#include <media_hidl_test_common.h>
51#include <fstream>
52
53static ComponentTestEnvironment* gEnv = nullptr;
54
55// audio decoder test fixture class
56class AudioDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
57   private:
58    typedef ::testing::VtsHalHidlTargetTestBase Super;
59   public:
60    ::std::string getTestCaseInfo() const override {
61        return ::std::string() +
62                "Component: " + gEnv->getComponent().c_str() + " | " +
63                "Role: " + gEnv->getRole().c_str() + " | " +
64                "Instance: " + gEnv->getInstance().c_str() + " | " +
65                "Res: " + gEnv->getRes().c_str();
66    }
67
68    virtual void SetUp() override {
69        Super::SetUp();
70        disableTest = false;
71        android::hardware::media::omx::V1_0::Status status;
72        omx = Super::getService<IOmx>(gEnv->getInstance());
73        ASSERT_NE(omx, nullptr);
74        observer =
75            new CodecObserver([this](Message msg, const BufferInfo* buffer) {
76                handleMessage(msg, buffer);
77            });
78        ASSERT_NE(observer, nullptr);
79        if (strncmp(gEnv->getComponent().c_str(), "OMX.", 4) != 0)
80            disableTest = true;
81        EXPECT_TRUE(omx->allocateNode(
82                           gEnv->getComponent(), observer,
83                           [&](android::hardware::media::omx::V1_0::Status _s,
84                               sp<IOmxNode> const& _nl) {
85                               status = _s;
86                               this->omxNode = _nl;
87                           })
88                        .isOk());
89        if (status == android::hardware::media::omx::V1_0::Status::NAME_NOT_FOUND) {
90            disableTest = true;
91            std::cout << "[   WARN   ] Test Disabled, component not present\n";
92            return;
93        }
94        ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
95        ASSERT_NE(omxNode, nullptr);
96        ASSERT_NE(gEnv->getRole().empty(), true) << "Invalid Component Role";
97        struct StringToName {
98            const char* Name;
99            standardComp CompName;
100        };
101        const StringToName kStringToName[] = {
102            {"mp3", mp3}, {"amrnb", amrnb},       {"amrwb", amrwb},
103            {"aac", aac}, {"vorbis", vorbis},     {"opus", opus},
104            {"pcm", pcm}, {"g711alaw", g711alaw}, {"g711mlaw", g711mlaw},
105            {"gsm", gsm}, {"raw", raw},           {"flac", flac},
106        };
107        const size_t kNumStringToName =
108            sizeof(kStringToName) / sizeof(kStringToName[0]);
109        const char* pch;
110        char substring[OMX_MAX_STRINGNAME_SIZE];
111        strcpy(substring, gEnv->getRole().c_str());
112        pch = strchr(substring, '.');
113        ASSERT_NE(pch, nullptr);
114        compName = unknown_comp;
115        for (size_t i = 0; i < kNumStringToName; ++i) {
116            if (!strcasecmp(pch + 1, kStringToName[i].Name)) {
117                compName = kStringToName[i].CompName;
118                break;
119            }
120        }
121        if (compName == unknown_comp) disableTest = true;
122        struct CompToCoding {
123            standardComp CompName;
124            OMX_AUDIO_CODINGTYPE eEncoding;
125        };
126        static const CompToCoding kCompToCoding[] = {
127            {mp3, OMX_AUDIO_CodingMP3},
128            {amrnb, OMX_AUDIO_CodingAMR},
129            {amrwb, OMX_AUDIO_CodingAMR},
130            {aac, OMX_AUDIO_CodingAAC},
131            {vorbis, OMX_AUDIO_CodingVORBIS},
132            {pcm, OMX_AUDIO_CodingPCM},
133            {opus, (OMX_AUDIO_CODINGTYPE)OMX_AUDIO_CodingAndroidOPUS},
134            {g711alaw, OMX_AUDIO_CodingG711},
135            {g711mlaw, OMX_AUDIO_CodingG711},
136            {gsm, OMX_AUDIO_CodingGSMFR},
137            {raw, OMX_AUDIO_CodingPCM},
138            {flac, OMX_AUDIO_CodingFLAC},
139        };
140        static const size_t kNumCompToCoding =
141            sizeof(kCompToCoding) / sizeof(kCompToCoding[0]);
142        size_t i;
143        for (i = 0; i < kNumCompToCoding; ++i) {
144            if (kCompToCoding[i].CompName == compName) {
145                eEncoding = kCompToCoding[i].eEncoding;
146                break;
147            }
148        }
149        if (i == kNumCompToCoding) disableTest = true;
150        eosFlag = false;
151        framesReceived = 0;
152        timestampUs = 0;
153        timestampDevTest = false;
154        if (disableTest) std::cout << "[   WARN   ] Test Disabled \n";
155    }
156
157    virtual void TearDown() override {
158        if (omxNode != nullptr) {
159            // If you have encountered a fatal failure, it is possible that
160            // freeNode() will not go through. Instead of hanging the app.
161            // let it pass through and report errors
162            if (::testing::Test::HasFatalFailure()) return;
163            EXPECT_TRUE((omxNode->freeNode()).isOk());
164            omxNode = nullptr;
165        }
166        Super::TearDown();
167    }
168
169    // callback function to process messages received by onMessages() from IL
170    // client.
171    void handleMessage(Message msg, const BufferInfo* buffer) {
172        (void)buffer;
173        if (msg.type == Message::Type::FILL_BUFFER_DONE) {
174            if (msg.data.extendedBufferData.flags & OMX_BUFFERFLAG_EOS) {
175                eosFlag = true;
176            }
177            if (msg.data.extendedBufferData.rangeLength != 0) {
178                framesReceived += 1;
179                // For decoder components current timestamp always exceeds
180                // previous timestamp
181                EXPECT_GE(msg.data.extendedBufferData.timestampUs, timestampUs);
182                timestampUs = msg.data.extendedBufferData.timestampUs;
183                // Test if current timestamp is among the list of queued
184                // timestamps
185                if (timestampDevTest) {
186                    bool tsHit = false;
187                    android::List<uint64_t>::iterator it =
188                        timestampUslist.begin();
189                    while (it != timestampUslist.end()) {
190                        if (*it == timestampUs) {
191                            timestampUslist.erase(it);
192                            tsHit = true;
193                            break;
194                        }
195                        it++;
196                    }
197                    if (tsHit == false) {
198                        if (timestampUslist.empty() == false) {
199                            EXPECT_EQ(tsHit, true)
200                                << "TimeStamp not recognized";
201                        } else {
202                            std::cout << "[   INFO   ] Received non-zero "
203                                         "output / TimeStamp not recognized \n";
204                        }
205                    }
206                }
207#define WRITE_OUTPUT 0
208#if WRITE_OUTPUT
209                static int count = 0;
210                FILE* ofp = nullptr;
211                if (count)
212                    ofp = fopen("out.bin", "ab");
213                else
214                    ofp = fopen("out.bin", "wb");
215                if (ofp != nullptr) {
216                    fwrite(static_cast<void*>(buffer->mMemory->getPointer()),
217                           sizeof(char),
218                           msg.data.extendedBufferData.rangeLength, ofp);
219                    fclose(ofp);
220                    count++;
221                }
222#endif
223            }
224        }
225    }
226
227    enum standardComp {
228        mp3,
229        amrnb,
230        amrwb,
231        aac,
232        vorbis,
233        opus,
234        pcm,
235        g711alaw,
236        g711mlaw,
237        gsm,
238        raw,
239        flac,
240        unknown_comp,
241    };
242
243    sp<IOmx> omx;
244    sp<CodecObserver> observer;
245    sp<IOmxNode> omxNode;
246    standardComp compName;
247    OMX_AUDIO_CODINGTYPE eEncoding;
248    bool disableTest;
249    bool eosFlag;
250    uint32_t framesReceived;
251    uint64_t timestampUs;
252    ::android::List<uint64_t> timestampUslist;
253    bool timestampDevTest;
254
255   protected:
256    static void description(const std::string& description) {
257        RecordProperty("description", description);
258    }
259};
260
261// Set Default port param.
262void setDefaultPortParam(
263    sp<IOmxNode> omxNode, OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE eEncoding,
264    int32_t nChannels = 2, int32_t nSampleRate = 44100,
265    OMX_AUDIO_PCMMODETYPE ePCMMode = OMX_AUDIO_PCMModeLinear,
266    OMX_NUMERICALDATATYPE eNumData = OMX_NumericalDataSigned,
267    int32_t nBitPerSample = 16) {
268    android::hardware::media::omx::V1_0::Status status;
269
270    OMX_PARAM_PORTDEFINITIONTYPE portDef;
271    status = getPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex,
272                          &portDef);
273    EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
274
275    portDef.format.audio.bFlagErrorConcealment = OMX_TRUE;
276    portDef.format.audio.eEncoding = eEncoding;
277    status = setPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex,
278                          &portDef);
279    EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
280
281    switch ((int)eEncoding) {
282        case OMX_AUDIO_CodingPCM:
283            setupPCMPort(omxNode, portIndex, nChannels, eNumData, nBitPerSample,
284                         nSampleRate, ePCMMode);
285            break;
286        case OMX_AUDIO_CodingAAC:
287            setupAACPort(omxNode, portIndex, OMX_AUDIO_AACObjectNull,
288                         OMX_AUDIO_AACStreamFormatMP4FF, nChannels, 0,
289                         nSampleRate);
290        default:
291            break;
292    }
293}
294
295// In decoder components, often the input port parameters get updated upon
296// parsing the header of elementary stream. Client needs to collect this
297// information to reconfigure other ports that share data with this input
298// port.
299void getInputChannelInfo(sp<IOmxNode> omxNode, OMX_U32 kPortIndexInput,
300                         OMX_AUDIO_CODINGTYPE eEncoding, int32_t* nChannels,
301                         int32_t* nSampleRate) {
302    android::hardware::media::omx::V1_0::Status status;
303    *nChannels = 0;
304    *nSampleRate = 0;
305
306    switch ((int)eEncoding) {
307        case OMX_AUDIO_CodingGSMFR:
308        case OMX_AUDIO_CodingG711:
309        case OMX_AUDIO_CodingPCM: {
310            OMX_AUDIO_PARAM_PCMMODETYPE param;
311            status = getPortParam(omxNode, OMX_IndexParamAudioPcm,
312                                  kPortIndexInput, &param);
313            ASSERT_EQ(status,
314                      ::android::hardware::media::omx::V1_0::Status::OK);
315            *nChannels = param.nChannels;
316            *nSampleRate = param.nSamplingRate;
317            break;
318        }
319        case OMX_AUDIO_CodingMP3: {
320            OMX_AUDIO_PARAM_MP3TYPE param;
321            status = getPortParam(omxNode, OMX_IndexParamAudioMp3,
322                                  kPortIndexInput, &param);
323            ASSERT_EQ(status,
324                      ::android::hardware::media::omx::V1_0::Status::OK);
325            *nChannels = param.nChannels;
326            *nSampleRate = param.nSampleRate;
327            break;
328        }
329        case OMX_AUDIO_CodingAndroidOPUS: {
330            OMX_AUDIO_PARAM_ANDROID_OPUSTYPE param;
331            status = getPortParam(omxNode,
332                                  (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus,
333                                  kPortIndexInput, &param);
334            ASSERT_EQ(status,
335                      ::android::hardware::media::omx::V1_0::Status::OK);
336            *nChannels = param.nChannels;
337            *nSampleRate = param.nSampleRate;
338            break;
339        }
340        case OMX_AUDIO_CodingVORBIS: {
341            OMX_AUDIO_PARAM_VORBISTYPE param;
342            status = getPortParam(omxNode, OMX_IndexParamAudioVorbis,
343                                  kPortIndexInput, &param);
344            ASSERT_EQ(status,
345                      ::android::hardware::media::omx::V1_0::Status::OK);
346            *nChannels = param.nChannels;
347            *nSampleRate = param.nSampleRate;
348            break;
349        }
350        case OMX_AUDIO_CodingAMR: {
351            OMX_AUDIO_PARAM_AMRTYPE param;
352            status = getPortParam(omxNode, OMX_IndexParamAudioAmr,
353                                  kPortIndexInput, &param);
354            ASSERT_EQ(status,
355                      ::android::hardware::media::omx::V1_0::Status::OK);
356            *nChannels = param.nChannels;
357            // NOTE: For amrnb sample rate is 8k and amrwb sample rate is 16k.
358            // There is no nSampleRate field in OMX_AUDIO_PARAM_AMRTYPE. Just
359            // return 8k to avoid returning uninit variable.
360            *nSampleRate = 8000;
361            break;
362        }
363        case OMX_AUDIO_CodingAAC: {
364            OMX_AUDIO_PARAM_AACPROFILETYPE param;
365            status = getPortParam(omxNode, OMX_IndexParamAudioAac,
366                                  kPortIndexInput, &param);
367            ASSERT_EQ(status,
368                      ::android::hardware::media::omx::V1_0::Status::OK);
369            *nChannels = param.nChannels;
370            *nSampleRate = param.nSampleRate;
371            break;
372        }
373        case OMX_AUDIO_CodingFLAC: {
374            OMX_AUDIO_PARAM_FLACTYPE param;
375            status = getPortParam(omxNode, OMX_IndexParamAudioFlac,
376                                  kPortIndexInput, &param);
377            ASSERT_EQ(status,
378                      ::android::hardware::media::omx::V1_0::Status::OK);
379            *nChannels = param.nChannels;
380            *nSampleRate = param.nSampleRate;
381            break;
382        }
383        default:
384            ASSERT_TRUE(false);
385            break;
386    }
387}
388
389// LookUpTable of clips and metadata for component testing
390void GetURLForComponent(AudioDecHidlTest::standardComp comp, char* mURL,
391                        char* info) {
392    struct CompToURL {
393        AudioDecHidlTest::standardComp comp;
394        const char* mURL;
395        const char* info;
396    };
397    static const CompToURL kCompToURL[] = {
398        {AudioDecHidlTest::standardComp::mp3,
399         "bbb_mp3_stereo_192kbps_48000hz.mp3",
400         "bbb_mp3_stereo_192kbps_48000hz.info"},
401        {AudioDecHidlTest::standardComp::aac,
402         "bbb_aac_stereo_128kbps_48000hz.aac",
403         "bbb_aac_stereo_128kbps_48000hz.info"},
404        {AudioDecHidlTest::standardComp::amrnb,
405         "sine_amrnb_1ch_12kbps_8000hz.amrnb",
406         "sine_amrnb_1ch_12kbps_8000hz.info"},
407        {AudioDecHidlTest::standardComp::amrwb,
408         "bbb_amrwb_1ch_14kbps_16000hz.amrwb",
409         "bbb_amrwb_1ch_14kbps_16000hz.info"},
410        {AudioDecHidlTest::standardComp::vorbis,
411         "bbb_vorbis_stereo_128kbps_48000hz.vorbis",
412         "bbb_vorbis_stereo_128kbps_48000hz.info"},
413        {AudioDecHidlTest::standardComp::opus,
414         "bbb_opus_stereo_128kbps_48000hz.opus",
415         "bbb_opus_stereo_128kbps_48000hz.info"},
416        {AudioDecHidlTest::standardComp::g711alaw, "bbb_g711alaw_1ch_8khz.raw",
417         "bbb_g711alaw_1ch_8khz.info"},
418        {AudioDecHidlTest::standardComp::g711mlaw, "bbb_g711mulaw_1ch_8khz.raw",
419         "bbb_g711mulaw_1ch_8khz.info"},
420        {AudioDecHidlTest::standardComp::gsm, "bbb_gsm_1ch_8khz_13kbps.raw",
421         "bbb_gsm_1ch_8khz_13kbps.info"},
422        {AudioDecHidlTest::standardComp::raw, "bbb_raw_1ch_8khz_s32le.raw",
423         "bbb_raw_1ch_8khz_s32le.info"},
424        {AudioDecHidlTest::standardComp::flac,
425         "bbb_flac_stereo_680kbps_48000hz.flac",
426         "bbb_flac_stereo_680kbps_48000hz.info"},
427    };
428
429    for (size_t i = 0; i < sizeof(kCompToURL) / sizeof(kCompToURL[0]); ++i) {
430        if (kCompToURL[i].comp == comp) {
431            strcat(mURL, kCompToURL[i].mURL);
432            strcat(info, kCompToURL[i].info);
433            return;
434        }
435    }
436}
437
438// port settings reconfiguration during runtime. reconfigures sample rate and
439// number
440typedef struct {
441    OMX_AUDIO_CODINGTYPE eEncoding;
442    AudioDecHidlTest::standardComp comp;
443} packedArgs;
444void portReconfiguration(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
445                         android::Vector<BufferInfo>* iBuffer,
446                         android::Vector<BufferInfo>* oBuffer,
447                         OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput,
448                         Message msg, PortMode oPortMode, void* args) {
449    android::hardware::media::omx::V1_0::Status status;
450    packedArgs* audioArgs = static_cast<packedArgs*>(args);
451    OMX_AUDIO_CODINGTYPE eEncoding = audioArgs->eEncoding;
452    AudioDecHidlTest::standardComp comp = audioArgs->comp;
453    (void)oPortMode;
454
455    if (msg.data.eventData.event == OMX_EventPortSettingsChanged) {
456        ASSERT_EQ(msg.data.eventData.data1, kPortIndexOutput);
457
458        status = omxNode->sendCommand(toRawCommandType(OMX_CommandPortDisable),
459                                      kPortIndexOutput);
460        ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
461
462        status =
463            observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
464        if (status == android::hardware::media::omx::V1_0::Status::TIMED_OUT) {
465            for (size_t i = 0; i < oBuffer->size(); ++i) {
466                // test if client got all its buffers back
467                EXPECT_EQ((*oBuffer)[i].owner, client);
468                // free the buffers
469                status =
470                    omxNode->freeBuffer(kPortIndexOutput, (*oBuffer)[i].id);
471                ASSERT_EQ(status,
472                          android::hardware::media::omx::V1_0::Status::OK);
473            }
474            status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer,
475                                              oBuffer);
476            ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
477            ASSERT_EQ(msg.type, Message::Type::EVENT);
478            ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
479            ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortDisable);
480            ASSERT_EQ(msg.data.eventData.data2, kPortIndexOutput);
481
482            // set Port Params
483            int32_t nChannels;
484            int32_t nSampleRate;
485            ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(
486                omxNode, kPortIndexInput, eEncoding, &nChannels, &nSampleRate));
487            // Configure output port
488            // SPECIAL CASE: Soft Vorbis, Opus and Raw Decoders do not offer way
489            // to configure output PCM port. The port undergoes auto
490            // configuration internally basing on parsed elementary stream
491            // information.
492            if (comp != AudioDecHidlTest::standardComp::vorbis &&
493                comp != AudioDecHidlTest::standardComp::opus &&
494                comp != AudioDecHidlTest::standardComp::raw) {
495                setDefaultPortParam(omxNode, kPortIndexOutput,
496                                    OMX_AUDIO_CodingPCM, nChannels,
497                                    nSampleRate);
498            }
499
500            // If you can disable a port, then you should be able to enable it
501            // as well
502            status = omxNode->sendCommand(
503                toRawCommandType(OMX_CommandPortEnable), kPortIndexOutput);
504            ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
505
506            // do not enable the port until all the buffers are supplied
507            status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer,
508                                              oBuffer);
509            ASSERT_EQ(status,
510                      android::hardware::media::omx::V1_0::Status::TIMED_OUT);
511
512            ASSERT_NO_FATAL_FAILURE(
513                allocatePortBuffers(omxNode, oBuffer, kPortIndexOutput));
514            status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer,
515                                              oBuffer);
516            ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
517            ASSERT_EQ(msg.type, Message::Type::EVENT);
518            ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortEnable);
519            ASSERT_EQ(msg.data.eventData.data2, kPortIndexOutput);
520
521            // dispatch output buffers
522            for (size_t i = 0; i < oBuffer->size(); i++) {
523                ASSERT_NO_FATAL_FAILURE(
524                    dispatchOutputBuffer(omxNode, oBuffer, i));
525            }
526        } else {
527            ASSERT_TRUE(false);
528        }
529    } else {
530        ASSERT_TRUE(false);
531    }
532}
533
534// blocking call to ensures application to Wait till all the inputs are consumed
535void waitOnInputConsumption(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
536                            android::Vector<BufferInfo>* iBuffer,
537                            android::Vector<BufferInfo>* oBuffer,
538                            OMX_AUDIO_CODINGTYPE eEncoding,
539                            OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput,
540                            AudioDecHidlTest::standardComp comp) {
541    android::hardware::media::omx::V1_0::Status status;
542    Message msg;
543    int timeOut = TIMEOUT_COUNTER_Q;
544
545    while (timeOut--) {
546        size_t i = 0;
547        status =
548            observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_Q, iBuffer, oBuffer);
549        if (status == android::hardware::media::omx::V1_0::Status::OK) {
550            ASSERT_EQ(msg.type, Message::Type::EVENT);
551            packedArgs audioArgs = {eEncoding, comp};
552            ASSERT_NO_FATAL_FAILURE(
553                portReconfiguration(omxNode, observer, iBuffer, oBuffer,
554                                    kPortIndexInput, kPortIndexOutput, msg,
555                                    PortMode::PRESET_BYTE_BUFFER, &audioArgs));
556        }
557        // status == TIMED_OUT, it could be due to process time being large
558        // than DEFAULT_TIMEOUT or component needs output buffers to start
559        // processing.
560        for (; i < iBuffer->size(); i++) {
561            if ((*iBuffer)[i].owner != client) break;
562        }
563        if (i == iBuffer->size()) break;
564
565        // Dispatch an output buffer assuming outQueue.empty() is true
566        size_t index;
567        if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
568            ASSERT_NO_FATAL_FAILURE(
569                dispatchOutputBuffer(omxNode, oBuffer, index));
570            timeOut = TIMEOUT_COUNTER_Q;
571        }
572    }
573}
574
575// Decode N Frames
576void decodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
577                   android::Vector<BufferInfo>* iBuffer,
578                   android::Vector<BufferInfo>* oBuffer,
579                   OMX_AUDIO_CODINGTYPE eEncoding, OMX_U32 kPortIndexInput,
580                   OMX_U32 kPortIndexOutput, std::ifstream& eleStream,
581                   android::Vector<FrameData>* Info, int offset, int range,
582                   AudioDecHidlTest::standardComp comp, bool signalEOS = true) {
583    android::hardware::media::omx::V1_0::Status status;
584    Message msg;
585    size_t index;
586    uint32_t flags = 0;
587    int frameID = offset;
588    int timeOut = TIMEOUT_COUNTER_Q;
589    bool iQueued, oQueued;
590
591    while (1) {
592        iQueued = oQueued = false;
593        status =
594            observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_Q, iBuffer, oBuffer);
595        // Port Reconfiguration
596        if (status == android::hardware::media::omx::V1_0::Status::OK &&
597            msg.type == Message::Type::EVENT) {
598            packedArgs audioArgs = {eEncoding, comp};
599            ASSERT_NO_FATAL_FAILURE(
600                portReconfiguration(omxNode, observer, iBuffer, oBuffer,
601                                    kPortIndexInput, kPortIndexOutput, msg,
602                                    PortMode::PRESET_BYTE_BUFFER, &audioArgs));
603        }
604
605        if (frameID == (int)Info->size() || frameID == (offset + range)) break;
606
607        // Dispatch input buffer
608        if ((index = getEmptyBufferID(iBuffer)) < iBuffer->size()) {
609            char* ipBuffer = static_cast<char*>(
610                static_cast<void*>((*iBuffer)[index].mMemory->getPointer()));
611            ASSERT_LE((*Info)[frameID].bytesCount,
612                      static_cast<int>((*iBuffer)[index].mMemory->getSize()));
613            eleStream.read(ipBuffer, (*Info)[frameID].bytesCount);
614            ASSERT_EQ(eleStream.gcount(), (*Info)[frameID].bytesCount);
615            flags = (*Info)[frameID].flags;
616            // Indicate to omx core that the buffer contains a full frame worth
617            // of data
618            flags |= OMX_BUFFERFLAG_ENDOFFRAME;
619            // Indicate the omx core that this is the last buffer it needs to
620            // process
621            if (signalEOS && ((frameID == (int)Info->size() - 1) ||
622                              (frameID == (offset + range - 1))))
623                flags |= OMX_BUFFERFLAG_EOS;
624            ASSERT_NO_FATAL_FAILURE(dispatchInputBuffer(
625                omxNode, iBuffer, index, (*Info)[frameID].bytesCount, flags,
626                (*Info)[frameID].timestamp));
627            frameID++;
628            iQueued = true;
629        }
630        // Dispatch output buffer
631        if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
632            ASSERT_NO_FATAL_FAILURE(
633                dispatchOutputBuffer(omxNode, oBuffer, index));
634            oQueued = true;
635        }
636        // Reset Counters when either input or output buffer is dispatched
637        if (iQueued || oQueued)
638            timeOut = TIMEOUT_COUNTER_Q;
639        else
640            timeOut--;
641        if (timeOut == 0) {
642            ASSERT_TRUE(false) << "Wait on Input/Output is found indefinite";
643        }
644    }
645}
646
647// set component role
648TEST_F(AudioDecHidlTest, SetRole) {
649    description("Test Set Component Role");
650    if (disableTest) return;
651    android::hardware::media::omx::V1_0::Status status;
652    status = setRole(omxNode, gEnv->getRole().c_str());
653    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
654}
655
656// port format enumeration
657TEST_F(AudioDecHidlTest, EnumeratePortFormat) {
658    description("Test Component on Mandatory Port Parameters (Port Format)");
659    if (disableTest) return;
660    android::hardware::media::omx::V1_0::Status status;
661    uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
662    status = setRole(omxNode, gEnv->getRole().c_str());
663    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
664    OMX_PORT_PARAM_TYPE params;
665    status = getParam(omxNode, OMX_IndexParamAudioInit, &params);
666    if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
667        ASSERT_EQ(params.nPorts, 2U);
668        kPortIndexInput = params.nStartPortNumber;
669        kPortIndexOutput = kPortIndexInput + 1;
670    }
671    status = setAudioPortFormat(omxNode, kPortIndexInput, eEncoding);
672    EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
673    status = setAudioPortFormat(omxNode, kPortIndexOutput, OMX_AUDIO_CodingPCM);
674    EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
675}
676
677// test port settings reconfiguration, elementary stream decode and timestamp
678// deviation
679TEST_F(AudioDecHidlTest, DecodeTest) {
680    description("Tests Port Reconfiguration, Decode and timestamp deviation");
681    if (disableTest) return;
682    android::hardware::media::omx::V1_0::Status status;
683    uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
684    status = setRole(omxNode, gEnv->getRole().c_str());
685    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
686    OMX_PORT_PARAM_TYPE params;
687    status = getParam(omxNode, OMX_IndexParamAudioInit, &params);
688    if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
689        ASSERT_EQ(params.nPorts, 2U);
690        kPortIndexInput = params.nStartPortNumber;
691        kPortIndexOutput = kPortIndexInput + 1;
692    }
693    char mURL[512], info[512];
694    strcpy(mURL, gEnv->getRes().c_str());
695    strcpy(info, gEnv->getRes().c_str());
696    GetURLForComponent(compName, mURL, info);
697
698    std::ifstream eleStream, eleInfo;
699
700    eleInfo.open(info);
701    ASSERT_EQ(eleInfo.is_open(), true);
702    android::Vector<FrameData> Info;
703    int bytesCount = 0;
704    uint32_t flags = 0;
705    uint32_t timestamp = 0;
706    timestampDevTest = false;
707    while (1) {
708        if (!(eleInfo >> bytesCount)) break;
709        eleInfo >> flags;
710        eleInfo >> timestamp;
711        Info.push_back({bytesCount, flags, timestamp});
712        if (timestampDevTest && (flags != OMX_BUFFERFLAG_CODECCONFIG))
713            timestampUslist.push_back(timestamp);
714    }
715    eleInfo.close();
716
717    int32_t nChannels, nSampleRate;
718    // Configure input port
719    setDefaultPortParam(omxNode, kPortIndexInput, eEncoding);
720    if (compName == raw)
721        setDefaultPortParam(omxNode, kPortIndexInput, eEncoding, 1, 8000,
722                            OMX_AUDIO_PCMModeLinear, OMX_NumericalDataSigned,
723                            32);
724    ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(
725        omxNode, kPortIndexInput, eEncoding, &nChannels, &nSampleRate));
726    // Configure output port
727    // SPECIAL CASE: Soft Vorbis, Opus and Raw Decoders do not offer way to
728    // configure output PCM port. The port undergoes auto configuration
729    // internally basing on parsed elementary stream information.
730    if (compName != vorbis && compName != opus && compName != raw) {
731        setDefaultPortParam(omxNode, kPortIndexOutput, OMX_AUDIO_CodingPCM,
732                            nChannels, nSampleRate);
733    }
734
735    android::Vector<BufferInfo> iBuffer, oBuffer;
736
737    // set state to idle
738    ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(omxNode, observer, &iBuffer,
739                                                    &oBuffer, kPortIndexInput,
740                                                    kPortIndexOutput));
741    // set state to executing
742    ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
743    // Port Reconfiguration
744    eleStream.open(mURL, std::ifstream::binary);
745    ASSERT_EQ(eleStream.is_open(), true);
746    ASSERT_NO_FATAL_FAILURE(decodeNFrames(
747        omxNode, observer, &iBuffer, &oBuffer, eEncoding, kPortIndexInput,
748        kPortIndexOutput, eleStream, &Info, 0, (int)Info.size(), compName));
749    eleStream.close();
750    ASSERT_NO_FATAL_FAILURE(
751        waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
752                               kPortIndexInput, kPortIndexOutput, compName));
753    packedArgs audioArgs = {eEncoding, compName};
754    ASSERT_NO_FATAL_FAILURE(testEOS(
755        omxNode, observer, &iBuffer, &oBuffer, false, eosFlag, nullptr,
756        portReconfiguration, kPortIndexInput, kPortIndexOutput, &audioArgs));
757    if (timestampDevTest) EXPECT_EQ(timestampUslist.empty(), true);
758    // set state to idle
759    ASSERT_NO_FATAL_FAILURE(
760        changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
761    // set state to executing
762    ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
763                                                    &oBuffer, kPortIndexInput,
764                                                    kPortIndexOutput));
765}
766
767// end of sequence test
768TEST_F(AudioDecHidlTest, EOSTest_M) {
769    description("Test end of stream monkeying");
770    if (disableTest) return;
771    android::hardware::media::omx::V1_0::Status status;
772    uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
773    status = setRole(omxNode, gEnv->getRole().c_str());
774    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
775    OMX_PORT_PARAM_TYPE params;
776    status = getParam(omxNode, OMX_IndexParamAudioInit, &params);
777    if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
778        ASSERT_EQ(params.nPorts, 2U);
779        kPortIndexInput = params.nStartPortNumber;
780        kPortIndexOutput = kPortIndexInput + 1;
781    }
782
783    int32_t nChannels, nSampleRate;
784    // Configure input port
785    setDefaultPortParam(omxNode, kPortIndexInput, eEncoding);
786    if (compName == raw)
787        setDefaultPortParam(omxNode, kPortIndexInput, eEncoding, 1, 8000,
788                            OMX_AUDIO_PCMModeLinear, OMX_NumericalDataSigned,
789                            32);
790    ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(
791        omxNode, kPortIndexInput, eEncoding, &nChannels, &nSampleRate));
792    // Configure output port
793    // SPECIAL CASE: Soft Vorbis, Opus and Raw Decoders do not offer way to
794    // configure output PCM port. The port undergoes auto configuration
795    // internally basing on parsed elementary stream information.
796    if (compName != vorbis && compName != opus && compName != raw) {
797        setDefaultPortParam(omxNode, kPortIndexOutput, OMX_AUDIO_CodingPCM,
798                            nChannels, nSampleRate);
799    }
800
801    android::Vector<BufferInfo> iBuffer, oBuffer;
802
803    // set state to idle
804    ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(omxNode, observer, &iBuffer,
805                                                    &oBuffer, kPortIndexInput,
806                                                    kPortIndexOutput));
807    // set state to executing
808    ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
809
810    // request EOS at the start
811    packedArgs audioArgs = {eEncoding, compName};
812    ASSERT_NO_FATAL_FAILURE(testEOS(
813        omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, nullptr,
814        portReconfiguration, kPortIndexInput, kPortIndexOutput, &audioArgs));
815    ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
816                                       kPortIndexInput, kPortIndexOutput));
817    EXPECT_GE(framesReceived, 0U);
818    framesReceived = 0;
819    timestampUs = 0;
820
821    // set state to idle
822    ASSERT_NO_FATAL_FAILURE(
823        changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
824
825    // set state to executing
826    ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
827                                                    &oBuffer, kPortIndexInput,
828                                                    kPortIndexOutput));
829}
830
831// end of sequence test
832TEST_F(AudioDecHidlTest, ThumbnailTest) {
833    description("Test Request for thumbnail");
834    if (disableTest) return;
835    android::hardware::media::omx::V1_0::Status status;
836    uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
837    status = setRole(omxNode, gEnv->getRole().c_str());
838    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
839    OMX_PORT_PARAM_TYPE params;
840    status = getParam(omxNode, OMX_IndexParamAudioInit, &params);
841    if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
842        ASSERT_EQ(params.nPorts, 2U);
843        kPortIndexInput = params.nStartPortNumber;
844        kPortIndexOutput = kPortIndexInput + 1;
845    }
846    char mURL[512], info[512];
847    strcpy(mURL, gEnv->getRes().c_str());
848    strcpy(info, gEnv->getRes().c_str());
849    GetURLForComponent(compName, mURL, info);
850
851    std::ifstream eleStream, eleInfo;
852
853    eleInfo.open(info);
854    ASSERT_EQ(eleInfo.is_open(), true);
855    android::Vector<FrameData> Info;
856    int bytesCount = 0;
857    uint32_t flags = 0;
858    uint32_t timestamp = 0;
859    while (1) {
860        if (!(eleInfo >> bytesCount)) break;
861        eleInfo >> flags;
862        eleInfo >> timestamp;
863        Info.push_back({bytesCount, flags, timestamp});
864    }
865    eleInfo.close();
866
867    int32_t nChannels, nSampleRate;
868    // Configure input port
869    setDefaultPortParam(omxNode, kPortIndexInput, eEncoding);
870    if (compName == raw)
871        setDefaultPortParam(omxNode, kPortIndexInput, eEncoding, 1, 8000,
872                            OMX_AUDIO_PCMModeLinear, OMX_NumericalDataSigned,
873                            32);
874    ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(
875        omxNode, kPortIndexInput, eEncoding, &nChannels, &nSampleRate));
876    // Configure output port
877    // SPECIAL CASE: Soft Vorbis, Opus and Raw Decoders do not offer way to
878    // configure output PCM port. The port undergoes auto configuration
879    // internally basing on parsed elementary stream information.
880    if (compName != vorbis && compName != opus && compName != raw) {
881        setDefaultPortParam(omxNode, kPortIndexOutput, OMX_AUDIO_CodingPCM,
882                            nChannels, nSampleRate);
883    }
884
885    android::Vector<BufferInfo> iBuffer, oBuffer;
886
887    // set state to idle
888    ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(omxNode, observer, &iBuffer,
889                                                    &oBuffer, kPortIndexInput,
890                                                    kPortIndexOutput));
891    // set state to executing
892    ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
893
894    // request EOS for thumbnail
895    // signal EOS flag with last frame
896    size_t i = 0;
897    while (!(Info[i].flags & OMX_BUFFERFLAG_SYNCFRAME)) i++;
898    eleStream.open(mURL, std::ifstream::binary);
899    ASSERT_EQ(eleStream.is_open(), true);
900    ASSERT_NO_FATAL_FAILURE(decodeNFrames(
901        omxNode, observer, &iBuffer, &oBuffer, eEncoding, kPortIndexInput,
902        kPortIndexOutput, eleStream, &Info, 0, i + 1, compName));
903    eleStream.close();
904    ASSERT_NO_FATAL_FAILURE(
905        waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
906                               kPortIndexInput, kPortIndexOutput, compName));
907    packedArgs audioArgs = {eEncoding, compName};
908    ASSERT_NO_FATAL_FAILURE(testEOS(
909        omxNode, observer, &iBuffer, &oBuffer, false, eosFlag, nullptr,
910        portReconfiguration, kPortIndexInput, kPortIndexOutput, &audioArgs));
911    ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
912                                       kPortIndexInput, kPortIndexOutput));
913    EXPECT_GE(framesReceived, 1U);
914    framesReceived = 0;
915    timestampUs = 0;
916
917    // signal EOS flag after last frame
918    eleStream.open(mURL, std::ifstream::binary);
919    ASSERT_EQ(eleStream.is_open(), true);
920    ASSERT_NO_FATAL_FAILURE(decodeNFrames(
921        omxNode, observer, &iBuffer, &oBuffer, eEncoding, kPortIndexInput,
922        kPortIndexOutput, eleStream, &Info, 0, i + 1, compName, false));
923    eleStream.close();
924    ASSERT_NO_FATAL_FAILURE(
925        waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
926                               kPortIndexInput, kPortIndexOutput, compName));
927    ASSERT_NO_FATAL_FAILURE(testEOS(
928        omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, nullptr,
929        portReconfiguration, kPortIndexInput, kPortIndexOutput, &audioArgs));
930    ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
931                                       kPortIndexInput, kPortIndexOutput));
932    EXPECT_GE(framesReceived, 1U);
933    framesReceived = 0;
934    timestampUs = 0;
935
936    // set state to idle
937    ASSERT_NO_FATAL_FAILURE(
938        changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
939    // set state to executing
940    ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
941                                                    &oBuffer, kPortIndexInput,
942                                                    kPortIndexOutput));
943}
944
945// end of sequence test
946TEST_F(AudioDecHidlTest, SimpleEOSTest) {
947    description("Test end of stream");
948    if (disableTest) return;
949    android::hardware::media::omx::V1_0::Status status;
950    uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
951    status = setRole(omxNode, gEnv->getRole().c_str());
952    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
953    OMX_PORT_PARAM_TYPE params;
954    status = getParam(omxNode, OMX_IndexParamAudioInit, &params);
955    if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
956        ASSERT_EQ(params.nPorts, 2U);
957        kPortIndexInput = params.nStartPortNumber;
958        kPortIndexOutput = kPortIndexInput + 1;
959    }
960    char mURL[512], info[512];
961    strcpy(mURL, gEnv->getRes().c_str());
962    strcpy(info, gEnv->getRes().c_str());
963    GetURLForComponent(compName, mURL, info);
964
965    std::ifstream eleStream, eleInfo;
966
967    eleInfo.open(info);
968    ASSERT_EQ(eleInfo.is_open(), true);
969    android::Vector<FrameData> Info;
970    int bytesCount = 0;
971    uint32_t flags = 0;
972    uint32_t timestamp = 0;
973    while (1) {
974        if (!(eleInfo >> bytesCount)) break;
975        eleInfo >> flags;
976        eleInfo >> timestamp;
977        Info.push_back({bytesCount, flags, timestamp});
978    }
979    eleInfo.close();
980
981    int32_t nChannels, nSampleRate;
982    // Configure input port
983    setDefaultPortParam(omxNode, kPortIndexInput, eEncoding);
984    if (compName == raw)
985        setDefaultPortParam(omxNode, kPortIndexInput, eEncoding, 1, 8000,
986                            OMX_AUDIO_PCMModeLinear, OMX_NumericalDataSigned,
987                            32);
988    ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(
989        omxNode, kPortIndexInput, eEncoding, &nChannels, &nSampleRate));
990    // Configure output port
991    // SPECIAL CASE: Soft Vorbis, Opus and Raw Decoders do not offer way to
992    // configure output PCM port. The port undergoes auto configuration
993    // internally basing on parsed elementary stream information.
994    if (compName != vorbis && compName != opus && compName != raw) {
995        setDefaultPortParam(omxNode, kPortIndexOutput, OMX_AUDIO_CodingPCM,
996                            nChannels, nSampleRate);
997    }
998
999    android::Vector<BufferInfo> iBuffer, oBuffer;
1000
1001    // set state to idle
1002    ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(omxNode, observer, &iBuffer,
1003                                                    &oBuffer, kPortIndexInput,
1004                                                    kPortIndexOutput));
1005    // set state to executing
1006    ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
1007
1008    // request EOS at the end
1009    eleStream.open(mURL, std::ifstream::binary);
1010    ASSERT_EQ(eleStream.is_open(), true);
1011    ASSERT_NO_FATAL_FAILURE(decodeNFrames(omxNode, observer, &iBuffer, &oBuffer,
1012                                          eEncoding, kPortIndexInput,
1013                                          kPortIndexOutput, eleStream, &Info, 0,
1014                                          (int)Info.size(), compName, false));
1015    eleStream.close();
1016    ASSERT_NO_FATAL_FAILURE(
1017        waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
1018                               kPortIndexInput, kPortIndexOutput, compName));
1019    packedArgs audioArgs = {eEncoding, compName};
1020    ASSERT_NO_FATAL_FAILURE(testEOS(
1021        omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, nullptr,
1022        portReconfiguration, kPortIndexInput, kPortIndexOutput, &audioArgs));
1023    ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
1024                                       kPortIndexInput, kPortIndexOutput));
1025    framesReceived = 0;
1026    timestampUs = 0;
1027
1028    // set state to idle
1029    ASSERT_NO_FATAL_FAILURE(
1030        changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
1031    // set state to executing
1032    ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
1033                                                    &oBuffer, kPortIndexInput,
1034                                                    kPortIndexOutput));
1035}
1036
1037// test input/output port flush
1038TEST_F(AudioDecHidlTest, FlushTest) {
1039    description("Test Flush");
1040    if (disableTest) return;
1041    android::hardware::media::omx::V1_0::Status status;
1042    uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
1043    status = setRole(omxNode, gEnv->getRole().c_str());
1044    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1045    OMX_PORT_PARAM_TYPE params;
1046    status = getParam(omxNode, OMX_IndexParamAudioInit, &params);
1047    if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
1048        ASSERT_EQ(params.nPorts, 2U);
1049        kPortIndexInput = params.nStartPortNumber;
1050        kPortIndexOutput = kPortIndexInput + 1;
1051    }
1052    char mURL[512], info[512];
1053    strcpy(mURL, gEnv->getRes().c_str());
1054    strcpy(info, gEnv->getRes().c_str());
1055    GetURLForComponent(compName, mURL, info);
1056
1057    std::ifstream eleStream, eleInfo;
1058
1059    eleInfo.open(info);
1060    ASSERT_EQ(eleInfo.is_open(), true);
1061    android::Vector<FrameData> Info;
1062    int bytesCount = 0;
1063    uint32_t flags = 0;
1064    uint32_t timestamp = 0;
1065    while (1) {
1066        if (!(eleInfo >> bytesCount)) break;
1067        eleInfo >> flags;
1068        eleInfo >> timestamp;
1069        Info.push_back({bytesCount, flags, timestamp});
1070    }
1071    eleInfo.close();
1072
1073    int32_t nChannels, nSampleRate;
1074    // Configure input port
1075    setDefaultPortParam(omxNode, kPortIndexInput, eEncoding);
1076    if (compName == raw)
1077        setDefaultPortParam(omxNode, kPortIndexInput, eEncoding, 1, 8000,
1078                            OMX_AUDIO_PCMModeLinear, OMX_NumericalDataSigned,
1079                            32);
1080    ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(
1081        omxNode, kPortIndexInput, eEncoding, &nChannels, &nSampleRate));
1082    // Configure output port
1083    // SPECIAL CASE: Soft Vorbis, Opus and Raw Decoders do not offer way to
1084    // configure output PCM port. The port undergoes auto configuration
1085    // internally basing on parsed elementary stream information.
1086    if (compName != vorbis && compName != opus && compName != raw) {
1087        setDefaultPortParam(omxNode, kPortIndexOutput, OMX_AUDIO_CodingPCM,
1088                            nChannels, nSampleRate);
1089    }
1090
1091    android::Vector<BufferInfo> iBuffer, oBuffer;
1092
1093    // set state to idle
1094    ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(omxNode, observer, &iBuffer,
1095                                                    &oBuffer, kPortIndexInput,
1096                                                    kPortIndexOutput));
1097    // set state to executing
1098    ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
1099
1100    // Decode 128 frames and flush. here 128 is chosen to ensure there is a key
1101    // frame after this so that the below section can be convered for all
1102    // components
1103    int nFrames = 128;
1104    eleStream.open(mURL, std::ifstream::binary);
1105    ASSERT_EQ(eleStream.is_open(), true);
1106    ASSERT_NO_FATAL_FAILURE(decodeNFrames(
1107        omxNode, observer, &iBuffer, &oBuffer, eEncoding, kPortIndexInput,
1108        kPortIndexOutput, eleStream, &Info, 0, nFrames, compName, false));
1109    ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
1110                                       kPortIndexInput, kPortIndexOutput));
1111    framesReceived = 0;
1112
1113    // Seek to next key frame and start decoding till the end
1114    int index = nFrames;
1115    bool keyFrame = false;
1116    while (index < (int)Info.size()) {
1117        if ((Info[index].flags & OMX_BUFFERFLAG_SYNCFRAME) ==
1118            OMX_BUFFERFLAG_SYNCFRAME) {
1119            timestampUs = Info[index - 1].timestamp;
1120            keyFrame = true;
1121            break;
1122        }
1123        eleStream.ignore(Info[index].bytesCount);
1124        index++;
1125    }
1126    if (keyFrame) {
1127        ASSERT_NO_FATAL_FAILURE(
1128            decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
1129                          kPortIndexInput, kPortIndexOutput, eleStream, &Info,
1130                          index, Info.size() - index, compName, false));
1131    }
1132    ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
1133                                       kPortIndexInput, kPortIndexOutput));
1134    framesReceived = 0;
1135
1136    // set state to idle
1137    ASSERT_NO_FATAL_FAILURE(
1138        changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
1139    // set state to executing
1140    ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
1141                                                    &oBuffer, kPortIndexInput,
1142                                                    kPortIndexOutput));
1143}
1144
1145int main(int argc, char** argv) {
1146    gEnv = new ComponentTestEnvironment();
1147    ::testing::AddGlobalTestEnvironment(gEnv);
1148    ::testing::InitGoogleTest(&argc, argv);
1149    gEnv->init(&argc, argv);
1150    int status = gEnv->initFromOptions(argc, argv);
1151    if (status == 0) {
1152        status = RUN_ALL_TESTS();
1153        ALOGI("Test result = %d", status);
1154    }
1155    return status;
1156}
1157