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_component_test"
18#include <android-base/logging.h>
19
20#include <android/hardware/media/omx/1.0/IOmx.h>
21#include <android/hardware/media/omx/1.0/IOmxNode.h>
22#include <android/hardware/media/omx/1.0/IOmxObserver.h>
23#include <android/hardware/media/omx/1.0/types.h>
24#include <android/hidl/allocator/1.0/IAllocator.h>
25#include <android/hidl/memory/1.0/IMapper.h>
26#include <android/hidl/memory/1.0/IMemory.h>
27
28using ::android::hardware::media::omx::V1_0::IOmx;
29using ::android::hardware::media::omx::V1_0::IOmxObserver;
30using ::android::hardware::media::omx::V1_0::IOmxNode;
31using ::android::hardware::media::omx::V1_0::Message;
32using ::android::hardware::media::omx::V1_0::CodecBuffer;
33using ::android::hardware::media::omx::V1_0::PortMode;
34using ::android::hidl::allocator::V1_0::IAllocator;
35using ::android::hidl::memory::V1_0::IMemory;
36using ::android::hidl::memory::V1_0::IMapper;
37using ::android::hardware::Return;
38using ::android::hardware::Void;
39using ::android::hardware::hidl_vec;
40using ::android::hardware::hidl_string;
41using ::android::sp;
42
43#include <VtsHalHidlTargetTestBase.h>
44#include <getopt.h>
45#include <media_hidl_test_common.h>
46
47// A class for test environment setup
48class ComponentTestEnvironment : public ::testing::Environment {
49   public:
50    virtual void SetUp() {}
51    virtual void TearDown() {}
52
53    ComponentTestEnvironment() : instance("default") {}
54
55    void setInstance(const char* _instance) { instance = _instance; }
56
57    void setComponent(const char* _component) { component = _component; }
58
59    void setRole(const char* _role) { role = _role; }
60
61    const hidl_string getInstance() const { return instance; }
62
63    const hidl_string getComponent() const { return component; }
64
65    const hidl_string getRole() const { return role; }
66
67    int initFromOptions(int argc, char** argv) {
68        static struct option options[] = {
69            {"instance", required_argument, 0, 'I'},
70            {"component", required_argument, 0, 'C'},
71            {"role", required_argument, 0, 'R'},
72            {0, 0, 0, 0}};
73
74        while (true) {
75            int index = 0;
76            int c = getopt_long(argc, argv, "I:C:R:", options, &index);
77            if (c == -1) {
78                break;
79            }
80
81            switch (c) {
82                case 'I':
83                    setInstance(optarg);
84                    break;
85                case 'C':
86                    setComponent(optarg);
87                    break;
88                case 'R':
89                    setRole(optarg);
90                    break;
91                case '?':
92                    break;
93            }
94        }
95
96        if (optind < argc) {
97            fprintf(stderr,
98                    "unrecognized option: %s\n\n"
99                    "usage: %s <gtest options> <test options>\n\n"
100                    "test options are:\n\n"
101                    "-I, --instance: HAL instance to test\n"
102                    "-C, --component: OMX component to test\n"
103                    "-R, --Role: OMX component Role\n",
104                    argv[optind ?: 1], argv[0]);
105            return 2;
106        }
107        return 0;
108    }
109
110   private:
111    hidl_string instance;
112    hidl_string component;
113    hidl_string role;
114};
115
116static ComponentTestEnvironment* gEnv = nullptr;
117
118// generic component test fixture class
119class ComponentHidlTest : public ::testing::VtsHalHidlTargetTestBase {
120   public:
121    virtual void SetUp() override {
122        disableTest = false;
123        android::hardware::media::omx::V1_0::Status status;
124        omx = ::testing::VtsHalHidlTargetTestBase::getService<IOmx>(
125            gEnv->getInstance());
126        ASSERT_NE(omx, nullptr);
127        observer = new CodecObserver(nullptr);
128        ASSERT_NE(observer, nullptr);
129        if (strncmp(gEnv->getComponent().c_str(), "OMX.", 4) != 0)
130            disableTest = true;
131        EXPECT_TRUE(omx->allocateNode(
132                           gEnv->getComponent(), observer,
133                           [&](android::hardware::media::omx::V1_0::Status _s,
134                               sp<IOmxNode> const& _nl) {
135                               status = _s;
136                               this->omxNode = _nl;
137                           })
138                        .isOk());
139        ASSERT_NE(omxNode, nullptr);
140        ASSERT_NE(gEnv->getRole().empty(), true) << "Invalid Component Role";
141        struct StringToClass {
142            const char* Class;
143            standardCompClass CompClass;
144        };
145        const StringToClass kStringToClass[] = {
146            {"audio_decoder", audio_decoder},
147            {"audio_encoder", audio_encoder},
148            {"video_decoder", video_decoder},
149            {"video_encoder", video_encoder},
150        };
151        const size_t kNumStringToClass =
152            sizeof(kStringToClass) / sizeof(kStringToClass[0]);
153        const char* pch;
154        char substring[OMX_MAX_STRINGNAME_SIZE];
155        strcpy(substring, gEnv->getRole().c_str());
156        pch = strchr(substring, '.');
157        ASSERT_NE(pch, nullptr) << "Invalid Component Role";
158        substring[pch - substring] = '\0';
159        compClass = unknown_class;
160        for (size_t i = 0; i < kNumStringToClass; ++i) {
161            if (!strcasecmp(substring, kStringToClass[i].Class)) {
162                compClass = kStringToClass[i].CompClass;
163                break;
164            }
165        }
166        if (compClass == unknown_class) disableTest = true;
167        isSecure = false;
168        size_t suffixLen = strlen(".secure");
169        if (strlen(gEnv->getComponent().c_str()) >= suffixLen) {
170            isSecure =
171                !strcmp(gEnv->getComponent().c_str() +
172                            strlen(gEnv->getComponent().c_str()) - suffixLen,
173                        ".secure");
174        }
175        if (disableTest) std::cerr << "[          ] Warning !  Test Disabled\n";
176    }
177
178    virtual void TearDown() override {
179        if (omxNode != nullptr) {
180            EXPECT_TRUE((omxNode->freeNode()).isOk());
181            omxNode = nullptr;
182        }
183    }
184
185    enum standardCompClass {
186        audio_decoder,
187        audio_encoder,
188        video_decoder,
189        video_encoder,
190        unknown_class,
191    };
192
193    sp<IOmx> omx;
194    sp<CodecObserver> observer;
195    sp<IOmxNode> omxNode;
196    standardCompClass compClass;
197    bool isSecure;
198    bool disableTest;
199
200   protected:
201    static void description(const std::string& description) {
202        RecordProperty("description", description);
203    }
204};
205
206// Random Index used for monkey testing while get/set parameters
207#define RANDOM_INDEX 1729
208
209void initPortMode(PortMode* pm, bool isSecure,
210                  ComponentHidlTest::standardCompClass compClass) {
211    pm[0] = PortMode::PRESET_BYTE_BUFFER;
212    pm[1] = PortMode::PRESET_BYTE_BUFFER;
213    if (isSecure) {
214        switch (compClass) {
215            case ComponentHidlTest::video_decoder:
216                pm[0] = PortMode::PRESET_SECURE_BUFFER;
217                break;
218            case ComponentHidlTest::video_encoder:
219                pm[1] = PortMode::PRESET_SECURE_BUFFER;
220                break;
221            default:
222                break;
223        }
224    }
225    return;
226}
227
228// get/set video component port format
229Return<android::hardware::media::omx::V1_0::Status> setVideoPortFormat(
230    sp<IOmxNode> omxNode, OMX_U32 portIndex,
231    OMX_VIDEO_CODINGTYPE eCompressionFormat, OMX_COLOR_FORMATTYPE eColorFormat,
232    OMX_U32 xFramerate) {
233    OMX_U32 index = 0;
234    OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat;
235    std::vector<OMX_COLOR_FORMATTYPE> arrColorFormat;
236    std::vector<OMX_VIDEO_CODINGTYPE> arrCompressionFormat;
237    android::hardware::media::omx::V1_0::Status status;
238
239    while (1) {
240        portFormat.nIndex = index;
241        status = getPortParam(omxNode, OMX_IndexParamVideoPortFormat, portIndex,
242                              &portFormat);
243        if (status != ::android::hardware::media::omx::V1_0::Status::OK) break;
244        if (eCompressionFormat == OMX_VIDEO_CodingUnused)
245            arrColorFormat.push_back(portFormat.eColorFormat);
246        else
247            arrCompressionFormat.push_back(portFormat.eCompressionFormat);
248        index++;
249        if (index == 512) {
250            // enumerated way too many formats, highly unusual for this to
251            // happen.
252            EXPECT_LE(index, 512U)
253                << "Expecting OMX_ErrorNoMore but not received";
254            break;
255        }
256    }
257    if (!index) return status;
258    if (eCompressionFormat == OMX_VIDEO_CodingUnused) {
259        for (index = 0; index < arrColorFormat.size(); index++) {
260            if (arrColorFormat[index] == eColorFormat) {
261                portFormat.eColorFormat = arrColorFormat[index];
262                break;
263            }
264        }
265        if (index == arrColorFormat.size()) {
266            ALOGE("setting default color format %x", (int)arrColorFormat[0]);
267            portFormat.eColorFormat = arrColorFormat[0];
268        }
269        portFormat.eCompressionFormat = OMX_VIDEO_CodingUnused;
270    } else {
271        for (index = 0; index < arrCompressionFormat.size(); index++) {
272            if (arrCompressionFormat[index] == eCompressionFormat) {
273                portFormat.eCompressionFormat = arrCompressionFormat[index];
274                break;
275            }
276        }
277        if (index == arrCompressionFormat.size()) {
278            ALOGE("setting default compression format %x",
279                  (int)arrCompressionFormat[0]);
280            portFormat.eCompressionFormat = arrCompressionFormat[0];
281        }
282        portFormat.eColorFormat = OMX_COLOR_FormatUnused;
283    }
284    // In setParam call nIndex shall be ignored as per omx-il specification.
285    // see how this holds up by corrupting nIndex
286    portFormat.nIndex = RANDOM_INDEX;
287    portFormat.xFramerate = xFramerate;
288    status = setPortParam(omxNode, OMX_IndexParamVideoPortFormat, portIndex,
289                          &portFormat);
290    return status;
291}
292
293// get/set audio component port format
294Return<android::hardware::media::omx::V1_0::Status> setAudioPortFormat(
295    sp<IOmxNode> omxNode, OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE eEncoding) {
296    OMX_U32 index = 0;
297    OMX_AUDIO_PARAM_PORTFORMATTYPE portFormat;
298    std::vector<OMX_AUDIO_CODINGTYPE> arrEncoding;
299    android::hardware::media::omx::V1_0::Status status;
300
301    while (1) {
302        portFormat.nIndex = index;
303        status = getPortParam(omxNode, OMX_IndexParamAudioPortFormat, portIndex,
304                              &portFormat);
305        if (status != ::android::hardware::media::omx::V1_0::Status::OK) break;
306        arrEncoding.push_back(portFormat.eEncoding);
307        index++;
308        if (index == 512) {
309            // enumerated way too many formats, highly unusual for this to
310            // happen.
311            EXPECT_LE(index, 512U)
312                << "Expecting OMX_ErrorNoMore but not received";
313            break;
314        }
315    }
316    if (!index) return status;
317    for (index = 0; index < arrEncoding.size(); index++) {
318        if (arrEncoding[index] == eEncoding) {
319            portFormat.eEncoding = arrEncoding[index];
320            break;
321        }
322    }
323    if (index == arrEncoding.size()) {
324        ALOGE("setting default Port format %x", (int)arrEncoding[0]);
325        portFormat.eEncoding = arrEncoding[0];
326    }
327    // In setParam call nIndex shall be ignored as per omx-il specification.
328    // see how this holds up by corrupting nIndex
329    portFormat.nIndex = RANDOM_INDEX;
330    status = setPortParam(omxNode, OMX_IndexParamAudioPortFormat, portIndex,
331                          &portFormat);
332    return status;
333}
334
335// test dispatch message API call
336TEST_F(ComponentHidlTest, dispatchMsg) {
337    description("test dispatch message API call");
338    if (disableTest) return;
339    android::hardware::media::omx::V1_0::Status status;
340    Message msgin, msgout;
341
342    msgin.type = Message::Type::EVENT;
343    msgin.data.eventData.event = OMX_EventError;
344    msgin.data.eventData.data1 = 0xdeaf;
345    msgin.data.eventData.data2 = 0xd00d;
346    msgin.data.eventData.data3 = 0x01ce;
347    msgin.data.eventData.data4 = 0xfa11;
348    status = omxNode->dispatchMessage(msgin);
349    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
350    status = observer->dequeueMessage(&msgout, DEFAULT_TIMEOUT);
351    EXPECT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
352    EXPECT_EQ(msgout.type, msgin.type);
353    EXPECT_EQ(msgout.data.eventData.event, msgin.data.eventData.event);
354    EXPECT_EQ(msgout.data.eventData.data1, msgin.data.eventData.data1);
355    EXPECT_EQ(msgout.data.eventData.data2, msgin.data.eventData.data2);
356    EXPECT_EQ(msgout.data.eventData.data3, msgin.data.eventData.data3);
357    EXPECT_EQ(msgout.data.eventData.data4, msgin.data.eventData.data4);
358}
359
360// set component role
361TEST_F(ComponentHidlTest, SetRole) {
362    description("Test Set Component Role");
363    if (disableTest) return;
364    android::hardware::media::omx::V1_0::Status status;
365    status = setRole(omxNode, gEnv->getRole().c_str());
366    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
367}
368
369// port indices enumeration
370TEST_F(ComponentHidlTest, DISABLED_GetPortIndices) {
371    description("Test Component on Mandatory Port Parameters (Port Indices)");
372    if (disableTest) return;
373    android::hardware::media::omx::V1_0::Status status;
374    OMX_PORT_PARAM_TYPE params;
375
376    status = setRole(omxNode, gEnv->getRole().c_str());
377    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
378
379    // Get Number of Ports and their Indices for all Domains
380    // (Audio/Video/Image/Other)
381    // All standard OMX components shall support following OMX Index types
382    status = getParam(omxNode, OMX_IndexParamAudioInit, &params);
383    EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
384    status = getParam(omxNode, OMX_IndexParamVideoInit, &params);
385    EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
386    status = getParam(omxNode, OMX_IndexParamImageInit, &params);
387    EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
388    status = getParam(omxNode, OMX_IndexParamOtherInit, &params);
389    EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
390}
391
392// port format enumeration
393TEST_F(ComponentHidlTest, DISABLED_EnumeratePortFormat) {
394    description("Test Component on Mandatory Port Parameters (Port Format)");
395    if (disableTest) return;
396    android::hardware::media::omx::V1_0::Status status;
397    uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
398
399    status = setRole(omxNode, gEnv->getRole().c_str());
400    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
401    OMX_PORT_PARAM_TYPE params;
402    if (compClass == audio_decoder || compClass == audio_encoder) {
403        status = getParam(omxNode, OMX_IndexParamAudioInit, &params);
404    } else {
405        status = getParam(omxNode, OMX_IndexParamVideoInit, &params);
406    }
407    if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
408        ASSERT_EQ(params.nPorts, 2U);
409        kPortIndexInput = params.nStartPortNumber;
410        kPortIndexOutput = kPortIndexInput + 1;
411    }
412
413    OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatYUV420Planar;
414    OMX_U32 xFramerate = 24U << 16;
415
416    // Enumerate Port Format
417    if (compClass == audio_encoder) {
418        status =
419            setAudioPortFormat(omxNode, kPortIndexInput, OMX_AUDIO_CodingPCM);
420        EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
421        status = setAudioPortFormat(omxNode, kPortIndexOutput,
422                                    OMX_AUDIO_CodingAutoDetect);
423        EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
424    } else if (compClass == audio_decoder) {
425        status = setAudioPortFormat(omxNode, kPortIndexInput,
426                                    OMX_AUDIO_CodingAutoDetect);
427        EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
428        status =
429            setAudioPortFormat(omxNode, kPortIndexOutput, OMX_AUDIO_CodingPCM);
430        EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
431    } else if (compClass == video_encoder) {
432        status =
433            setVideoPortFormat(omxNode, kPortIndexInput, OMX_VIDEO_CodingUnused,
434                               eColorFormat, xFramerate);
435        EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
436        status = setVideoPortFormat(omxNode, kPortIndexOutput,
437                                    OMX_VIDEO_CodingAutoDetect,
438                                    OMX_COLOR_FormatUnused, 0U);
439        EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
440    } else {
441        status = setVideoPortFormat(omxNode, kPortIndexInput,
442                                    OMX_VIDEO_CodingAutoDetect,
443                                    OMX_COLOR_FormatUnused, 0U);
444        EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
445        status = setVideoPortFormat(omxNode, kPortIndexOutput,
446                                    OMX_VIDEO_CodingUnused, eColorFormat,
447                                    xFramerate);
448        EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
449    }
450}
451
452// get/set default port settings of a component
453TEST_F(ComponentHidlTest, DISABLED_SetDefaultPortParams) {
454    description(
455        "Test Component on Mandatory Port Parameters (Port Definition)");
456    if (disableTest) return;
457    android::hardware::media::omx::V1_0::Status status;
458    uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
459
460    status = setRole(omxNode, gEnv->getRole().c_str());
461    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
462    OMX_PORT_PARAM_TYPE params;
463    if (compClass == audio_decoder || compClass == audio_encoder) {
464        status = getParam(omxNode, OMX_IndexParamAudioInit, &params);
465    } else {
466        status = getParam(omxNode, OMX_IndexParamVideoInit, &params);
467    }
468    if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
469        ASSERT_EQ(params.nPorts, 2U);
470        kPortIndexInput = params.nStartPortNumber;
471        kPortIndexOutput = kPortIndexInput + 1;
472    }
473
474    for (size_t i = kPortIndexInput; i < kPortIndexOutput; i++) {
475        OMX_PARAM_PORTDEFINITIONTYPE portDef;
476        status =
477            getPortParam(omxNode, OMX_IndexParamPortDefinition, i, &portDef);
478        EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
479        if (status == android::hardware::media::omx::V1_0::Status::OK) {
480            EXPECT_EQ(portDef.eDir, i - kPortIndexInput);  // OMX_DirInput
481            EXPECT_EQ(portDef.bEnabled, OMX_TRUE);
482            EXPECT_EQ(portDef.bPopulated, OMX_FALSE);
483            EXPECT_GE(portDef.nBufferCountMin, 1U);
484            EXPECT_GE(portDef.nBufferCountActual, portDef.nBufferCountMin);
485            if (compClass == audio_encoder || compClass == audio_decoder) {
486                EXPECT_EQ(portDef.eDomain, OMX_PortDomainAudio);
487            } else if (compClass == video_encoder ||
488                       compClass == video_decoder) {
489                EXPECT_EQ(portDef.eDomain, OMX_PortDomainVideo);
490            }
491            OMX_PARAM_PORTDEFINITIONTYPE mirror = portDef;
492
493            // nBufferCountActual >= nBufferCountMin
494            portDef.nBufferCountActual = portDef.nBufferCountMin - 1;
495            status = setPortParam(omxNode, OMX_IndexParamPortDefinition, i,
496                                  &portDef);
497            EXPECT_NE(status,
498                      ::android::hardware::media::omx::V1_0::Status::OK);
499
500            // Edit Read-Only fields.
501            portDef = mirror;
502            portDef.eDir = static_cast<OMX_DIRTYPE>(RANDOM_INDEX);
503            setPortParam(omxNode, OMX_IndexParamPortDefinition, i, &portDef);
504            getPortParam(omxNode, OMX_IndexParamPortDefinition, i, &portDef);
505            EXPECT_EQ(portDef.eDir, mirror.eDir);
506            setPortParam(omxNode, OMX_IndexParamPortDefinition, i, &mirror);
507
508            portDef = mirror;
509            portDef.nBufferSize >>= 1;
510            setPortParam(omxNode, OMX_IndexParamPortDefinition, i, &portDef);
511            getPortParam(omxNode, OMX_IndexParamPortDefinition, i, &portDef);
512            EXPECT_EQ(portDef.nBufferSize, mirror.nBufferSize);
513            setPortParam(omxNode, OMX_IndexParamPortDefinition, i, &mirror);
514
515            portDef = mirror;
516            portDef.nBufferCountMin += 1;
517            setPortParam(omxNode, OMX_IndexParamPortDefinition, i, &portDef);
518            getPortParam(omxNode, OMX_IndexParamPortDefinition, i, &portDef);
519            EXPECT_EQ(portDef.nBufferCountMin, mirror.nBufferCountMin);
520            setPortParam(omxNode, OMX_IndexParamPortDefinition, i, &mirror);
521
522            portDef = mirror;
523            portDef.nBufferCountActual += 1;
524            status = setPortParam(omxNode, OMX_IndexParamPortDefinition, i,
525                                  &portDef);
526            if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
527                status = getPortParam(omxNode, OMX_IndexParamPortDefinition, i,
528                                      &portDef);
529                EXPECT_EQ(portDef.nBufferCountActual,
530                          mirror.nBufferCountActual + 1);
531            }
532
533            portDef = mirror;
534            portDef.nBufferSize = mirror.nBufferSize << 1;
535            status = setPortParam(omxNode, OMX_IndexParamPortDefinition, i,
536                                  &portDef);
537            if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
538                status = getPortParam(omxNode, OMX_IndexParamPortDefinition, i,
539                                      &portDef);
540                if (portDef.nBufferSize != mirror.nBufferSize) {
541                    std::cout
542                        << "[          ] Warning ! Component input port does "
543                           "not  preserve Read-Only fields \n";
544                }
545            }
546        }
547    }
548}
549
550// populate port test
551TEST_F(ComponentHidlTest, DISABLED_PopulatePort) {
552    description("Verify bPopulated field of a component port");
553    if (disableTest || isSecure) return;
554    android::hardware::media::omx::V1_0::Status status;
555    OMX_U32 portBase = 0;
556
557    status = setRole(omxNode, gEnv->getRole().c_str());
558    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
559    OMX_PORT_PARAM_TYPE params;
560    if (compClass == audio_decoder || compClass == audio_encoder) {
561        status = getParam(omxNode, OMX_IndexParamAudioInit, &params);
562    } else {
563        status = getParam(omxNode, OMX_IndexParamVideoInit, &params);
564    }
565    if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
566        ASSERT_EQ(params.nPorts, 2U);
567        portBase = params.nStartPortNumber;
568    }
569
570    sp<IAllocator> allocator = IAllocator::getService("ashmem");
571    EXPECT_NE(allocator.get(), nullptr);
572
573    OMX_PARAM_PORTDEFINITIONTYPE portDef;
574    status =
575        getPortParam(omxNode, OMX_IndexParamPortDefinition, portBase, &portDef);
576    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
577    ASSERT_EQ(portDef.bPopulated, OMX_FALSE);
578
579    android::Vector<BufferInfo> pBuffer;
580    pBuffer.clear();
581    uint32_t nBufferSize = portDef.nBufferSize >> 1;
582
583    for (size_t i = 0; i < portDef.nBufferCountActual; i++) {
584        BufferInfo buffer;
585        buffer.owner = client;
586        buffer.omxBuffer.type = CodecBuffer::Type::SHARED_MEM;
587        buffer.omxBuffer.attr.preset.rangeOffset = 0;
588        buffer.omxBuffer.attr.preset.rangeLength = 0;
589        bool success = false;
590        allocator->allocate(
591            nBufferSize,
592            [&success, &buffer](bool _s,
593                                ::android::hardware::hidl_memory const& mem) {
594                success = _s;
595                buffer.omxBuffer.sharedMemory = mem;
596            });
597        ASSERT_EQ(success, true);
598        ASSERT_EQ(buffer.omxBuffer.sharedMemory.size(), nBufferSize);
599
600        omxNode->useBuffer(
601            portBase, buffer.omxBuffer,
602            [&status, &buffer](android::hardware::media::omx::V1_0::Status _s,
603                               uint32_t id) {
604                status = _s;
605                buffer.id = id;
606            });
607        pBuffer.push(buffer);
608        ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
609    }
610
611    status =
612        getPortParam(omxNode, OMX_IndexParamPortDefinition, portBase, &portDef);
613    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
614    // A port is populated when all of the buffers indicated by
615    // nBufferCountActual with a size of at least nBufferSizehave been
616    // allocated on the port.
617    ASSERT_EQ(portDef.bPopulated, OMX_FALSE);
618}
619
620// Flush test
621TEST_F(ComponentHidlTest, Flush) {
622    description("Test Flush");
623    if (disableTest) return;
624    android::hardware::media::omx::V1_0::Status status;
625    uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
626    Message msg;
627
628    status = setRole(omxNode, gEnv->getRole().c_str());
629    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
630    OMX_PORT_PARAM_TYPE params;
631    if (compClass == audio_decoder || compClass == audio_encoder) {
632        status = getParam(omxNode, OMX_IndexParamAudioInit, &params);
633    } else {
634        status = getParam(omxNode, OMX_IndexParamVideoInit, &params);
635    }
636    if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
637        ASSERT_EQ(params.nPorts, 2U);
638        kPortIndexInput = params.nStartPortNumber;
639        kPortIndexOutput = kPortIndexInput + 1;
640    }
641
642    android::Vector<BufferInfo> iBuffer, oBuffer;
643
644    // set port mode
645    PortMode portMode[2];
646    initPortMode(portMode, isSecure, compClass);
647    status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
648    EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
649    status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
650    EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
651
652    // set state to idle
653    changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
654                            kPortIndexInput, kPortIndexOutput, portMode);
655    // set state to executing
656    changeStateIdletoExecute(omxNode, observer);
657    // dispatch buffers
658    for (size_t i = 0; i < oBuffer.size(); i++) {
659        dispatchOutputBuffer(omxNode, &oBuffer, i, portMode[1]);
660    }
661    // flush port
662    flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
663               kPortIndexOutput);
664    // TODO: Sending empty input buffers is slightly tricky.
665    // Components sometimes process input buffers even when output buffers are
666    // not dispatched. For instance Parsing sequence header does not require
667    // output buffers. In such instances sending 0 size input buffers might
668    // make component to send error events. so lets skip this aspect of testing.
669    // dispatch buffers
670    //    for (size_t i = 0; i < iBuffer.size(); i++) {
671    //        dispatchInputBuffer(omxNode, &iBuffer, i, 0, 0, 0, portMode[0]);
672    //    }
673    //    // flush ports
674    //    flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
675    //               kPortIndexOutput);
676    // set state to idle
677    changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
678    // set state to loaded
679    changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
680                            kPortIndexInput, kPortIndexOutput);
681}
682
683// state transitions test
684TEST_F(ComponentHidlTest, StateTransitions) {
685    description("Test State Transitions Loaded<->Idle<->Execute");
686    if (disableTest) return;
687    android::hardware::media::omx::V1_0::Status status;
688    uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
689    Message msg;
690
691    status = setRole(omxNode, gEnv->getRole().c_str());
692    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
693    OMX_PORT_PARAM_TYPE params;
694    if (compClass == audio_decoder || compClass == audio_encoder) {
695        status = getParam(omxNode, OMX_IndexParamAudioInit, &params);
696    } else {
697        status = getParam(omxNode, OMX_IndexParamVideoInit, &params);
698    }
699    if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
700        ASSERT_EQ(params.nPorts, 2U);
701        kPortIndexInput = params.nStartPortNumber;
702        kPortIndexOutput = kPortIndexInput + 1;
703    }
704
705    android::Vector<BufferInfo> iBuffer, oBuffer;
706
707    // set port mode
708    PortMode portMode[2];
709    initPortMode(portMode, isSecure, compClass);
710    status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
711    EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
712    status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
713    EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
714
715    // set state to idle
716    changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
717                            kPortIndexInput, kPortIndexOutput, portMode);
718    // set state to executing
719    changeStateIdletoExecute(omxNode, observer);
720    // dispatch buffers
721    for (size_t i = 0; i < oBuffer.size(); i++) {
722        dispatchOutputBuffer(omxNode, &oBuffer, i, portMode[1]);
723    }
724    // set state to idle
725    changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
726    //    // set state to executing
727    //    changeStateIdletoExecute(omxNode, observer);
728    //    // TODO: Sending empty input buffers is slightly tricky.
729    //    // dispatch buffers
730    //    for (size_t i = 0; i < iBuffer.size(); i++) {
731    //        dispatchInputBuffer(omxNode, &iBuffer, i, 0, 0, 0, portMode[0]);
732    //    }
733    //    // set state to idle
734    //    changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
735    // set state to loaded
736    changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
737                            kPortIndexInput, kPortIndexOutput);
738}
739
740// state transitions test - monkeying
741TEST_F(ComponentHidlTest, DISABLED_StateTransitions_M) {
742    description("Test State Transitions monkeying");
743    if (disableTest || isSecure) return;
744    android::hardware::media::omx::V1_0::Status status;
745    uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
746    Message msg;
747
748    status = setRole(omxNode, gEnv->getRole().c_str());
749    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
750    OMX_PORT_PARAM_TYPE params;
751    if (compClass == audio_decoder || compClass == audio_encoder) {
752        status = getParam(omxNode, OMX_IndexParamAudioInit, &params);
753    } else {
754        status = getParam(omxNode, OMX_IndexParamVideoInit, &params);
755    }
756    if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
757        ASSERT_EQ(params.nPorts, 2U);
758        kPortIndexInput = params.nStartPortNumber;
759        kPortIndexOutput = kPortIndexInput + 1;
760    }
761
762    android::Vector<BufferInfo> iBuffer, oBuffer;
763
764    // set state to loaded ; receive error OMX_ErrorSameState
765    status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
766                                  OMX_StateLoaded);
767    EXPECT_NE(status, android::hardware::media::omx::V1_0::Status::OK);
768
769    // set state to executing ; receive error OMX_ErrorIncorrectStateTransition
770    status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
771                                  OMX_StateExecuting);
772    EXPECT_NE(status, android::hardware::media::omx::V1_0::Status::OK);
773
774    // set state to idle
775    changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
776                            kPortIndexInput, kPortIndexOutput);
777
778    // set state to idle ; receive error OMX_ErrorSameState
779    status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
780                                  OMX_StateIdle);
781    EXPECT_NE(status, android::hardware::media::omx::V1_0::Status::OK);
782
783    // set state to executing
784    changeStateIdletoExecute(omxNode, observer);
785
786    // set state to executing ; receive error OMX_ErrorSameState
787    status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
788                                  OMX_StateExecuting);
789    EXPECT_NE(status, android::hardware::media::omx::V1_0::Status::OK);
790
791    // set state to Loaded ; receive error OMX_ErrorIncorrectStateTransition
792    status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
793                                  OMX_StateLoaded);
794    EXPECT_NE(status, android::hardware::media::omx::V1_0::Status::OK);
795
796    // set state to Idle
797    changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
798
799    // set state to Loaded
800    changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
801                            kPortIndexInput, kPortIndexOutput);
802}
803
804// port enable disable test
805TEST_F(ComponentHidlTest, DISABLED_PortEnableDisable_Loaded) {
806    description("Test Port Enable and Disable (Component State :: Loaded)");
807    if (disableTest) return;
808    android::hardware::media::omx::V1_0::Status status;
809    OMX_U32 portBase = 0;
810    Message msg;
811    status = setRole(omxNode, gEnv->getRole().c_str());
812    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
813    OMX_PORT_PARAM_TYPE params;
814    if (compClass == audio_decoder || compClass == audio_encoder) {
815        status = getParam(omxNode, OMX_IndexParamAudioInit, &params);
816    } else {
817        status = getParam(omxNode, OMX_IndexParamVideoInit, &params);
818    }
819    if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
820        ASSERT_EQ(params.nPorts, 2U);
821        portBase = params.nStartPortNumber;
822    }
823
824    for (size_t i = portBase; i < portBase + 2; i++) {
825        status =
826            omxNode->sendCommand(toRawCommandType(OMX_CommandPortDisable), i);
827        ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
828        status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT);
829        ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
830        ASSERT_EQ(msg.type, Message::Type::EVENT);
831        if (msg.data.eventData.event == OMX_EventCmdComplete) {
832            ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortDisable);
833            ASSERT_EQ(msg.data.eventData.data2, i);
834            // If you can disable a port, then you should be able to enable it
835            // as well
836            status = omxNode->sendCommand(
837                toRawCommandType(OMX_CommandPortEnable), i);
838            ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
839            status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT);
840            ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
841            ASSERT_EQ(msg.type, Message::Type::EVENT);
842            ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortEnable);
843            ASSERT_EQ(msg.data.eventData.data2, i);
844        } else if (msg.data.eventData.event == OMX_EventError) {
845            ALOGE("Port %d Disabling failed with error %d", (int)i,
846                  (int)msg.data.eventData.event);
847        } else {
848            // something unexpected happened
849            ASSERT_TRUE(false);
850        }
851    }
852}
853
854// port enable disable test
855TEST_F(ComponentHidlTest, PortEnableDisable_Idle) {
856    description("Test Port Enable and Disable (Component State :: Idle)");
857    if (disableTest) return;
858    android::hardware::media::omx::V1_0::Status status;
859    uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
860    OMX_U32 portBase = 0;
861    Message msg;
862    status = setRole(omxNode, gEnv->getRole().c_str());
863    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
864    OMX_PORT_PARAM_TYPE params;
865    if (compClass == audio_decoder || compClass == audio_encoder) {
866        status = getParam(omxNode, OMX_IndexParamAudioInit, &params);
867    } else {
868        status = getParam(omxNode, OMX_IndexParamVideoInit, &params);
869    }
870    if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
871        ASSERT_EQ(params.nPorts, 2U);
872        portBase = params.nStartPortNumber;
873    }
874    kPortIndexInput = portBase;
875    kPortIndexOutput = portBase + 1;
876
877    // Component State :: Idle
878    android::Vector<BufferInfo> pBuffer[2];
879
880    // set port mode
881    PortMode portMode[2];
882    initPortMode(portMode, isSecure, compClass);
883    status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
884    EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
885    status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
886    EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
887
888    // set state to idle
889    changeStateLoadedtoIdle(omxNode, observer, &pBuffer[0], &pBuffer[1],
890                            kPortIndexInput, kPortIndexOutput, portMode);
891
892    for (size_t i = portBase; i < portBase + 2; i++) {
893        status =
894            omxNode->sendCommand(toRawCommandType(OMX_CommandPortDisable), i);
895        ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
896
897        status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, &pBuffer[0],
898                                          &pBuffer[1]);
899        if (status == android::hardware::media::omx::V1_0::Status::OK) {
900            ASSERT_EQ(msg.type, Message::Type::EVENT);
901            if (msg.data.eventData.event == OMX_EventCmdComplete) {
902                // do not disable the port until all the buffers are freed
903                ASSERT_TRUE(false);
904            } else if (msg.data.eventData.event == OMX_EventError) {
905                ALOGE("Port %d Disabling failed with error %d", (int)i,
906                      (int)msg.data.eventData.event);
907            } else {
908                // something unexpected happened
909                ASSERT_TRUE(false);
910            }
911        } else if (status ==
912                   android::hardware::media::omx::V1_0::Status::TIMED_OUT) {
913            for (size_t j = 0; j < pBuffer[i - portBase].size(); ++j) {
914                status = omxNode->freeBuffer(i, pBuffer[i - portBase][j].id);
915                ASSERT_EQ(status,
916                          android::hardware::media::omx::V1_0::Status::OK);
917            }
918
919            status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
920                                              &pBuffer[0], &pBuffer[1]);
921            ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
922            ASSERT_EQ(msg.type, Message::Type::EVENT);
923            ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
924            ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortDisable);
925            ASSERT_EQ(msg.data.eventData.data2, i);
926
927            // If you can disable a port, then you should be able to enable it
928            // as well
929            status = omxNode->sendCommand(
930                toRawCommandType(OMX_CommandPortEnable), i);
931            ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
932
933            // do not enable the port until all the buffers are supplied
934            status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
935                                              &pBuffer[0], &pBuffer[1]);
936            ASSERT_EQ(status,
937                      android::hardware::media::omx::V1_0::Status::TIMED_OUT);
938
939            allocatePortBuffers(omxNode, &pBuffer[i - portBase], i,
940                                portMode[i - portBase]);
941            status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
942                                              &pBuffer[0], &pBuffer[1]);
943            ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
944            ASSERT_EQ(msg.type, Message::Type::EVENT);
945            ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortEnable);
946            ASSERT_EQ(msg.data.eventData.data2, i);
947        } else {
948            // something unexpected happened
949            ASSERT_TRUE(false);
950        }
951    }
952
953    // set state to Loaded
954    changeStateIdletoLoaded(omxNode, observer, &pBuffer[0], &pBuffer[1],
955                            kPortIndexInput, kPortIndexOutput);
956}
957
958// port enable disable test
959TEST_F(ComponentHidlTest, PortEnableDisable_Execute) {
960    description("Test Port Enable and Disable (Component State :: Execute)");
961    if (disableTest) return;
962    android::hardware::media::omx::V1_0::Status status;
963    uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
964    OMX_U32 portBase = 0;
965    Message msg;
966    status = setRole(omxNode, gEnv->getRole().c_str());
967    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
968    OMX_PORT_PARAM_TYPE params;
969    if (compClass == audio_decoder || compClass == audio_encoder) {
970        status = getParam(omxNode, OMX_IndexParamAudioInit, &params);
971    } else {
972        status = getParam(omxNode, OMX_IndexParamVideoInit, &params);
973    }
974    if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
975        ASSERT_EQ(params.nPorts, 2U);
976        portBase = params.nStartPortNumber;
977    }
978    kPortIndexInput = portBase;
979    kPortIndexOutput = portBase + 1;
980
981    // Component State :: Idle
982    android::Vector<BufferInfo> pBuffer[2];
983
984    // set port mode
985    PortMode portMode[2];
986    initPortMode(portMode, isSecure, compClass);
987    status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
988    EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
989    status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
990    EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
991
992    // set state to idle
993    changeStateLoadedtoIdle(omxNode, observer, &pBuffer[0], &pBuffer[1],
994                            kPortIndexInput, kPortIndexOutput, portMode);
995
996    // set state to executing
997    changeStateIdletoExecute(omxNode, observer);
998
999    // dispatch buffers
1000    for (size_t i = 0; i < pBuffer[1].size(); i++) {
1001        dispatchOutputBuffer(omxNode, &pBuffer[1], i, portMode[1]);
1002    }
1003
1004    for (size_t i = portBase; i < portBase + 2; i++) {
1005        status =
1006            omxNode->sendCommand(toRawCommandType(OMX_CommandPortDisable), i);
1007        ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
1008
1009        status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, &pBuffer[0],
1010                                          &pBuffer[1]);
1011        if (status == android::hardware::media::omx::V1_0::Status::OK) {
1012            ASSERT_EQ(msg.type, Message::Type::EVENT);
1013            if (msg.data.eventData.event == OMX_EventCmdComplete) {
1014                // do not disable the port until all the buffers are freed
1015                ASSERT_TRUE(false);
1016            } else if (msg.data.eventData.event == OMX_EventError) {
1017                ALOGE("Port %d Disabling failed with error %d", (int)i,
1018                      (int)msg.data.eventData.event);
1019            } else {
1020                // something unexpected happened
1021                ASSERT_TRUE(false);
1022            }
1023        } else if (status ==
1024                   android::hardware::media::omx::V1_0::Status::TIMED_OUT) {
1025            for (size_t j = 0; j < pBuffer[i - portBase].size(); ++j) {
1026                // test if client got all its buffers back
1027                EXPECT_EQ(pBuffer[i - portBase][j].owner, client);
1028                // free the buffers
1029                status = omxNode->freeBuffer(i, pBuffer[i - portBase][j].id);
1030                ASSERT_EQ(status,
1031                          android::hardware::media::omx::V1_0::Status::OK);
1032            }
1033
1034            status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
1035                                              &pBuffer[0], &pBuffer[1]);
1036            ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
1037            ASSERT_EQ(msg.type, Message::Type::EVENT);
1038            ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
1039            ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortDisable);
1040            ASSERT_EQ(msg.data.eventData.data2, i);
1041
1042            // If you can disable a port, then you should be able to enable it
1043            // as well
1044            status = omxNode->sendCommand(
1045                toRawCommandType(OMX_CommandPortEnable), i);
1046            ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
1047
1048            // do not enable the port until all the buffers are supplied
1049            status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
1050                                              &pBuffer[0], &pBuffer[1]);
1051            ASSERT_EQ(status,
1052                      android::hardware::media::omx::V1_0::Status::TIMED_OUT);
1053
1054            allocatePortBuffers(omxNode, &pBuffer[i - portBase], i,
1055                                portMode[i - portBase]);
1056            status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
1057                                              &pBuffer[0], &pBuffer[1]);
1058            ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
1059            ASSERT_EQ(msg.type, Message::Type::EVENT);
1060            ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortEnable);
1061            ASSERT_EQ(msg.data.eventData.data2, i);
1062        } else {
1063            // something unexpected happened
1064            ASSERT_TRUE(false);
1065        }
1066    }
1067
1068    // set state to Idle
1069    changeStateExecutetoIdle(omxNode, observer, &pBuffer[0], &pBuffer[1]);
1070
1071    // set state to Loaded
1072    changeStateIdletoLoaded(omxNode, observer, &pBuffer[0], &pBuffer[1],
1073                            kPortIndexInput, kPortIndexOutput);
1074}
1075
1076// port enable disable test - monkeying
1077TEST_F(ComponentHidlTest, DISABLED_PortEnableDisable_M) {
1078    description(
1079        "Test Port Enable and Disable Monkeying (Component State :: Loaded)");
1080    if (disableTest || isSecure) return;
1081    android::hardware::media::omx::V1_0::Status status;
1082    OMX_U32 portBase = 0;
1083    Message msg;
1084    status = setRole(omxNode, gEnv->getRole().c_str());
1085    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1086    OMX_PORT_PARAM_TYPE params;
1087    if (compClass == audio_decoder || compClass == audio_encoder) {
1088        status = getParam(omxNode, OMX_IndexParamAudioInit, &params);
1089    } else {
1090        status = getParam(omxNode, OMX_IndexParamVideoInit, &params);
1091    }
1092    if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
1093        ASSERT_EQ(params.nPorts, 2U);
1094        portBase = params.nStartPortNumber;
1095    }
1096
1097    // disable invalid port, expecting OMX_ErrorBadPortIndex
1098    status = omxNode->sendCommand(toRawCommandType(OMX_CommandPortDisable),
1099                                  RANDOM_INDEX);
1100    ASSERT_NE(status, android::hardware::media::omx::V1_0::Status::OK);
1101
1102    // enable invalid port, expecting OMX_ErrorBadPortIndex
1103    status = omxNode->sendCommand(toRawCommandType(OMX_CommandPortEnable),
1104                                  RANDOM_INDEX);
1105    ASSERT_NE(status, android::hardware::media::omx::V1_0::Status::OK);
1106
1107    // disable all ports
1108    status =
1109        omxNode->sendCommand(toRawCommandType(OMX_CommandPortDisable), OMX_ALL);
1110    ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
1111    for (size_t i = 0; i < 2; i++) {
1112        status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT);
1113        ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
1114        ASSERT_EQ(msg.type, Message::Type::EVENT);
1115        if (msg.data.eventData.event == OMX_EventCmdComplete) {
1116            ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortDisable);
1117            if (msg.data.eventData.data2 != portBase ||
1118                msg.data.eventData.data2 != portBase + 1)
1119                EXPECT_TRUE(false);
1120        } else if (msg.data.eventData.event == OMX_EventError) {
1121            ALOGE("Port %d Disabling failed with error %d", (int)i,
1122                  (int)msg.data.eventData.event);
1123        } else {
1124            // something unexpected happened
1125            ASSERT_TRUE(false);
1126        }
1127    }
1128
1129    // enable all ports
1130    status =
1131        omxNode->sendCommand(toRawCommandType(OMX_CommandPortEnable), OMX_ALL);
1132    ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
1133    for (size_t i = 0; i < 2; i++) {
1134        status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT);
1135        ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
1136        ASSERT_EQ(msg.type, Message::Type::EVENT);
1137        if (msg.data.eventData.event == OMX_EventCmdComplete) {
1138            ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortEnable);
1139            if (msg.data.eventData.data2 != portBase ||
1140                msg.data.eventData.data2 != portBase + 1)
1141                EXPECT_TRUE(false);
1142        } else if (msg.data.eventData.event == OMX_EventError) {
1143            ALOGE("Port %d Enabling failed with error %d", (int)i,
1144                  (int)msg.data.eventData.event);
1145        } else {
1146            // something unexpected happened
1147            ASSERT_TRUE(false);
1148        }
1149    }
1150}
1151
1152int main(int argc, char** argv) {
1153    gEnv = new ComponentTestEnvironment();
1154    ::testing::AddGlobalTestEnvironment(gEnv);
1155    ::testing::InitGoogleTest(&argc, argv);
1156    int status = gEnv->initFromOptions(argc, argv);
1157    if (status == 0) {
1158        status = RUN_ALL_TESTS();
1159        ALOGI("Test result = %d", status);
1160    }
1161    return status;
1162}
1163