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