Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6bda6397 authored by Amy Zhang's avatar Amy Zhang
Browse files

Move testing ts on Cuttlefish under /data/ directory

/data directory is a proper place for test pusher to adb push the ts
during run time. It saves image size comparing to bundle the ts during
compiling.

Files under the /data directory could only be passed around by fd
instead of directly opening. This CL also changes the way the DVR VTS
reads the ts.

Also for virtual frontend, to read the shell data file, we need the
DVR playback to input the data when testing frontend.
This CL also changes the way default implementation reads the data -
from the dvr playback fmq.

Test: atest VtsHalTvTunerV1_0TargetTest
Bug: 153366959
Change-Id: I72a98e4c4c0328206da106fb1c3459745c1644b7
parent 154d45d7
Loading
Loading
Loading
Loading
+69 −67
Original line number Diff line number Diff line
@@ -48,8 +48,6 @@ Return<Result> Demux::setFrontendDataSource(uint32_t frontendId) {
        return Result::INVALID_STATE;
    }

    mFrontendSourceFile = mFrontend->getSourceFile();

    mTunerService->setFrontendAsDemuxSource(frontendId, mDemuxId);

    return Result::SUCCESS;
@@ -62,8 +60,6 @@ Return<void> Demux::openFilter(const DemuxFilterType& type, uint32_t bufferSize,
    uint32_t filterId;
    filterId = ++mLastUsedFilterId;

    mUsedFilterIds.insert(filterId);

    if (cb == nullptr) {
        ALOGW("[Demux] callback can't be null");
        _hidl_cb(Result::INVALID_ARGUMENT, new Filter());
@@ -82,8 +78,13 @@ Return<void> Demux::openFilter(const DemuxFilterType& type, uint32_t bufferSize,
        mPcrFilterIds.insert(filterId);
    }
    bool result = true;
    if (mDvr != nullptr && mDvr->getType() == DvrType::PLAYBACK) {
        result = mDvr->addPlaybackFilter(filter);
    if (!filter->isRecordFilter()) {
        // Only save non-record filters for now. Record filters are saved when the
        // IDvr.attacheFilter is called.
        mPlaybackFilterIds.insert(filterId);
        if (mDvrPlayback != nullptr) {
            result = mDvrPlayback->addPlaybackFilter(filterId, filter);
        }
    }

    _hidl_cb(result ? Result::SUCCESS : Result::INVALID_ARGUMENT, filter);
@@ -154,7 +155,13 @@ Return<void> Demux::getAvSyncTime(AvSyncHwId avSyncHwId, getAvSyncTime_cb _hidl_
Return<Result> Demux::close() {
    ALOGV("%s", __FUNCTION__);

    mUsedFilterIds.clear();
    set<uint32_t>::iterator it;
    for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
        mDvrPlayback->removePlaybackFilter(*it);
    }
    mPlaybackFilterIds.clear();
    mRecordFilterIds.clear();
    mFilters.clear();
    mLastUsedFilterId = -1;

    return Result::SUCCESS;
@@ -170,15 +177,38 @@ Return<void> Demux::openDvr(DvrType type, uint32_t bufferSize, const sp<IDvrCall
        return Void();
    }

    mDvr = new Dvr(type, bufferSize, cb, this);
    set<uint32_t>::iterator it;
    switch (type) {
        case DvrType::PLAYBACK:
            mDvrPlayback = new Dvr(type, bufferSize, cb, this);
            if (!mDvrPlayback->createDvrMQ()) {
                _hidl_cb(Result::UNKNOWN_ERROR, mDvrPlayback);
                return Void();
            }

            for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
                if (!mDvrPlayback->addPlaybackFilter(*it, mFilters[*it])) {
                    ALOGE("[Demux] Can't get filter info for DVR playback");
                    _hidl_cb(Result::UNKNOWN_ERROR, mDvrPlayback);
                    return Void();
                }
            }

    if (!mDvr->createDvrMQ()) {
        _hidl_cb(Result::UNKNOWN_ERROR, mDvr);
            _hidl_cb(Result::SUCCESS, mDvrPlayback);
            return Void();
        case DvrType::RECORD:
            mDvrRecord = new Dvr(type, bufferSize, cb, this);
            if (!mDvrRecord->createDvrMQ()) {
                _hidl_cb(Result::UNKNOWN_ERROR, mDvrRecord);
                return Void();
            }

    _hidl_cb(Result::SUCCESS, mDvr);
            _hidl_cb(Result::SUCCESS, mDvrRecord);
            return Void();
        default:
            _hidl_cb(Result::INVALID_ARGUMENT, nullptr);
            return Void();
    }
}

Return<Result> Demux::connectCiCam(uint32_t ciCamId) {
@@ -198,8 +228,10 @@ Return<Result> Demux::disconnectCiCam() {
Result Demux::removeFilter(uint32_t filterId) {
    ALOGV("%s", __FUNCTION__);

    // resetFilterRecords(filterId);
    mUsedFilterIds.erase(filterId);
    if (mDvrPlayback != nullptr) {
        mDvrPlayback->removePlaybackFilter(filterId);
    }
    mPlaybackFilterIds.erase(filterId);
    mRecordFilterIds.erase(filterId);
    mFilters.erase(filterId);

@@ -212,7 +244,7 @@ void Demux::startBroadcastTsFilter(vector<uint8_t> data) {
    if (DEBUG_DEMUX) {
        ALOGW("[Demux] start ts filter pid: %d", pid);
    }
    for (it = mUsedFilterIds.begin(); it != mUsedFilterIds.end(); it++) {
    for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
        if (pid == mFilters[*it]->getTpid()) {
            mFilters[*it]->updateFilterOutput(data);
        }
@@ -233,7 +265,7 @@ bool Demux::startBroadcastFilterDispatcher() {
    set<uint32_t>::iterator it;

    // Handle the output data per filter type
    for (it = mUsedFilterIds.begin(); it != mUsedFilterIds.end(); it++) {
    for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
        if (mFilters[*it]->startFilterHandler() != Result::SUCCESS) {
            return false;
        }
@@ -280,58 +312,27 @@ void* Demux::__threadLoopFrontend(void* user) {
void Demux::frontendInputThreadLoop() {
    std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
    mFrontendInputThreadRunning = true;
    mKeepFetchingDataFromFrontend = true;

    // open the stream and get its length
    std::ifstream inputData(mFrontendSourceFile, std::ifstream::binary);
    // TODO take the packet size from the frontend setting
    int packetSize = 188;
    int writePacketAmount = 6;
    char* buffer = new char[packetSize];
    ALOGW("[Demux] Frontend input thread loop start %s", mFrontendSourceFile.c_str());
    if (!inputData.is_open()) {
        mFrontendInputThreadRunning = false;
        ALOGW("[Demux] Error %s", strerror(errno));
    }

    while (mFrontendInputThreadRunning) {
        // move the stream pointer for packet size * 6 every read until the end
        while (mKeepFetchingDataFromFrontend) {
            for (int i = 0; i < writePacketAmount; i++) {
                inputData.read(buffer, packetSize);
                if (!inputData) {
                    mKeepFetchingDataFromFrontend = false;
                    mFrontendInputThreadRunning = false;
        uint32_t efState = 0;
        status_t status = mDvrPlayback->getDvrEventFlag()->wait(
                static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY), &efState, WAIT_TIMEOUT,
                true /* retry on spurious wake */);
        if (status != OK) {
            ALOGD("[Demux] wait for data ready on the playback FMQ");
            continue;
        }
        // Our current implementation filter the data and write it into the filter FMQ immediately
        // after the DATA_READY from the VTS/framework
        if (!mDvrPlayback->readPlaybackFMQ(true /*isVirtualFrontend*/, mIsRecording) ||
            !mDvrPlayback->startFilterDispatcher(true /*isVirtualFrontend*/, mIsRecording)) {
            ALOGE("[Demux] playback data failed to be filtered. Ending thread");
            break;
        }
                // filter and dispatch filter output
                vector<uint8_t> byteBuffer;
                byteBuffer.resize(packetSize);
                for (int index = 0; index < byteBuffer.size(); index++) {
                    byteBuffer[index] = static_cast<uint8_t>(buffer[index]);
                }
                if (mIsRecording) {
                    // Feed the data into the Dvr recording input
                    sendFrontendInputToRecord(byteBuffer);
                } else {
                    // Feed the data into the broadcast demux filter
                    startBroadcastTsFilter(byteBuffer);
                }
            }
            if (mIsRecording) {
                // Dispatch the data into the broadcasting filters.
                startRecordFilterDispatcher();
            } else {
                // Dispatch the data into the broadcasting filters.
                startBroadcastFilterDispatcher();
            }
            usleep(100);
        }
    }

    mFrontendInputThreadRunning = false;
    ALOGW("[Demux] Frontend Input thread end.");
    delete[] buffer;
    inputData.close();
}

void Demux::stopFrontendInput() {
@@ -346,18 +347,19 @@ void Demux::setIsRecording(bool isRecording) {
}

bool Demux::attachRecordFilter(int filterId) {
    if (mFilters[filterId] == nullptr || mDvr == nullptr) {
    if (mFilters[filterId] == nullptr || mDvrRecord == nullptr ||
        !mFilters[filterId]->isRecordFilter()) {
        return false;
    }

    mRecordFilterIds.insert(filterId);
    mFilters[filterId]->attachFilterToRecord(mDvr);
    mFilters[filterId]->attachFilterToRecord(mDvrRecord);

    return true;
}

bool Demux::detachRecordFilter(int filterId) {
    if (mFilters[filterId] == nullptr || mDvr == nullptr) {
    if (mFilters[filterId] == nullptr || mDvrRecord == nullptr) {
        return false;
    }

+16 −15
Original line number Diff line number Diff line
@@ -91,13 +91,23 @@ class Demux : public IDemux {
    void setIsRecording(bool isRecording);
    void startFrontendInputLoop();

    /**
     * A dispatcher to read and dispatch input data to all the started filters.
     * Each filter handler handles the data filtering/output writing/filterEvent updating.
     * Note that recording filters are not included.
     */
    bool startBroadcastFilterDispatcher();
    void startBroadcastTsFilter(vector<uint8_t> data);

    void sendFrontendInputToRecord(vector<uint8_t> data);
    bool startRecordFilterDispatcher();

  private:
    // Tuner service
    sp<Tuner> mTunerService;

    // Frontend source
    sp<Frontend> mFrontend;
    string mFrontendSourceFile;

    // A struct that passes the arguments to a newly created filter thread
    struct ThreadArgs {
@@ -117,16 +127,6 @@ class Demux : public IDemux {
     */
    void deleteEventFlag();
    bool readDataFromMQ();
    /**
     * A dispatcher to read and dispatch input data to all the started filters.
     * Each filter handler handles the data filtering/output writing/filterEvent updating.
     * Note that recording filters are not included.
     */
    bool startBroadcastFilterDispatcher();
    void startBroadcastTsFilter(vector<uint8_t> data);

    void sendFrontendInputToRecord(vector<uint8_t> data);
    bool startRecordFilterDispatcher();

    uint32_t mDemuxId;
    uint32_t mCiCamId;
@@ -137,17 +137,17 @@ class Demux : public IDemux {
     */
    uint32_t mLastUsedFilterId = -1;
    /**
     * Record all the used filter Ids.
     * Record all the used playback filter Ids.
     * Any removed filter id should be removed from this set.
     */
    set<uint32_t> mUsedFilterIds;
    set<uint32_t> mPlaybackFilterIds;
    /**
     * Record all the attached record filter Ids.
     * Any removed filter id should be removed from this set.
     */
    set<uint32_t> mRecordFilterIds;
    /**
     * A list of created FilterMQ ptrs.
     * A list of created Filter sp.
     * The array number is the filter ID.
     */
    std::map<uint32_t, sp<Filter>> mFilters;
@@ -155,7 +155,8 @@ class Demux : public IDemux {
    /**
     * Local reference to the opened DVR object.
     */
    sp<Dvr> mDvr;
    sp<Dvr> mDvrPlayback;
    sp<Dvr> mDvrRecord;

    // Thread handlers
    pthread_t mFrontendInputThread;
+33 −36
Original line number Diff line number Diff line
@@ -70,8 +70,7 @@ Return<Result> Dvr::attachFilter(const sp<IFilter>& filter) {
        return status;
    }

    // check if the attached filter is a record filter
    mFilters[filterId] = filter;
    // TODO check if the attached filter is a record filter
    if (!mDemux->attachRecordFilter(filterId)) {
        return Result::INVALID_ARGUMENT;
    }
@@ -94,20 +93,9 @@ Return<Result> Dvr::detachFilter(const sp<IFilter>& filter) {
        return status;
    }

    std::map<uint32_t, sp<IFilter>>::iterator it;

    it = mFilters.find(filterId);
    if (it != mFilters.end()) {
        mFilters.erase(filterId);
    if (!mDemux->detachRecordFilter(filterId)) {
        return Result::INVALID_ARGUMENT;
    }
    }

    // If all the filters are detached, record can't be started
    if (mFilters.empty()) {
        mIsRecordFilterAttached = false;
    }

    return Result::SUCCESS;
}
@@ -183,6 +171,10 @@ bool Dvr::createDvrMQ() {
    return true;
}

EventFlag* Dvr::getDvrEventFlag() {
    return mDvrEventFlag;
}

void* Dvr::__threadLoopPlayback(void* user) {
    Dvr* const self = static_cast<Dvr*>(user);
    self->playbackThreadLoop();
@@ -205,8 +197,9 @@ void Dvr::playbackThreadLoop() {
        }
        // Our current implementation filter the data and write it into the filter FMQ immediately
        // after the DATA_READY from the VTS/framework
        if (!readPlaybackFMQ() || !startFilterDispatcher()) {
            ALOGD("[Dvr] playback data failed to be filtered. Ending thread");
        if (!readPlaybackFMQ(false /*isVirtualFrontend*/, false /*isRecording*/) ||
            !startFilterDispatcher(false /*isVirtualFrontend*/, false /*isRecording*/)) {
            ALOGE("[Dvr] playback data failed to be filtered. Ending thread");
            break;
        }

@@ -245,7 +238,7 @@ PlaybackStatus Dvr::checkPlaybackStatusChange(uint32_t availableToWrite, uint32_
    return mPlaybackStatus;
}

bool Dvr::readPlaybackFMQ() {
bool Dvr::readPlaybackFMQ(bool isVirtualFrontend, bool isRecording) {
    // Read playback data from the input FMQ
    int size = mDvrMQ->availableToRead();
    int playbackPacketSize = mDvrSettings.playback().packetSize;
@@ -256,8 +249,16 @@ bool Dvr::readPlaybackFMQ() {
        if (!mDvrMQ->read(dataOutputBuffer.data(), playbackPacketSize)) {
            return false;
        }
        if (isVirtualFrontend) {
            if (isRecording) {
                mDemux->sendFrontendInputToRecord(dataOutputBuffer);
            } else {
                mDemux->startBroadcastTsFilter(dataOutputBuffer);
            }
        } else {
            startTpidFilter(dataOutputBuffer);
        }
    }

    return true;
}
@@ -275,7 +276,15 @@ void Dvr::startTpidFilter(vector<uint8_t> data) {
    }
}

bool Dvr::startFilterDispatcher() {
bool Dvr::startFilterDispatcher(bool isVirtualFrontend, bool isRecording) {
    if (isVirtualFrontend) {
        if (isRecording) {
            return mDemux->startRecordFilterDispatcher();
        } else {
            return mDemux->startBroadcastFilterDispatcher();
        }
    }

    std::map<uint32_t, sp<IFilter>>::iterator it;
    // Handle the output data per filter type
    for (it = mFilters.begin(); it != mFilters.end(); it++) {
@@ -329,27 +338,15 @@ RecordStatus Dvr::checkRecordStatusChange(uint32_t availableToWrite, uint32_t av
    return mRecordStatus;
}

bool Dvr::addPlaybackFilter(sp<IFilter> filter) {
    uint32_t filterId;
    Result status;

    filter->getId([&](Result result, uint32_t id) {
        filterId = id;
        status = result;
    });

    if (status != Result::SUCCESS) {
        return false;
    }

bool Dvr::addPlaybackFilter(uint32_t filterId, sp<IFilter> filter) {
    mFilters[filterId] = filter;
    return true;
}

DvrType Dvr::getType() {
    return mType;
bool Dvr::removePlaybackFilter(uint32_t filterId) {
    mFilters.erase(filterId);
    return true;
}

}  // namespace implementation
}  // namespace V1_0
}  // namespace tuner
+5 −8
Original line number Diff line number Diff line
@@ -81,8 +81,11 @@ class Dvr : public IDvr {
    bool createDvrMQ();
    void sendBroadcastInputToDvrRecord(vector<uint8_t> byteBuffer);
    bool writeRecordFMQ(const std::vector<uint8_t>& data);
    DvrType getType();
    bool addPlaybackFilter(sp<IFilter> filter);
    bool addPlaybackFilter(uint32_t filterId, sp<IFilter> filter);
    bool removePlaybackFilter(uint32_t filterId);
    bool readPlaybackFMQ(bool isVirtualFrontend, bool isRecording);
    bool startFilterDispatcher(bool isVirtualFrontend, bool isRecording);
    EventFlag* getDvrEventFlag();

  private:
    // Demux service
@@ -105,9 +108,7 @@ class Dvr : public IDvr {
     * A dispatcher to read and dispatch input data to all the started filters.
     * Each filter handler handles the data filtering/output writing/filterEvent updating.
     */
    bool readPlaybackFMQ();
    void startTpidFilter(vector<uint8_t> data);
    bool startFilterDispatcher();
    static void* __threadLoopPlayback(void* user);
    static void* __threadLoopRecord(void* user);
    void playbackThreadLoop();
@@ -123,7 +124,6 @@ class Dvr : public IDvr {

    // Thread handlers
    pthread_t mDvrThread;
    pthread_t mBroadcastInputThread;

    // FMQ status local records
    PlaybackStatus mPlaybackStatus;
@@ -132,7 +132,6 @@ class Dvr : public IDvr {
     * If a specific filter's writing loop is still running
     */
    bool mDvrThreadRunning;
    bool mBroadcastInputThreadRunning;
    bool mKeepFetchingDataFromFrontend;
    /**
     * Lock to protect writes to the FMQs
@@ -143,7 +142,6 @@ class Dvr : public IDvr {
     */
    std::mutex mPlaybackStatusLock;
    std::mutex mRecordStatusLock;
    std::mutex mBroadcastInputThreadLock;
    std::mutex mDvrThreadLock;

    const bool DEBUG_DVR = false;
@@ -151,7 +149,6 @@ class Dvr : public IDvr {
    // Booleans to check if recording is running.
    // Recording is ready when both of the following are set to true.
    bool mIsRecordStarted = false;
    bool mIsRecordFilterAttached = false;
};

}  // namespace implementation
+7 −7
Original line number Diff line number Diff line
@@ -47,12 +47,18 @@ Filter::Filter(DemuxFilterType type, uint32_t filterId, uint32_t bufferSize,
            if (mType.subType.tsFilterType() == DemuxTsFilterType::PCR) {
                mIsPcrFilter = true;
            }
            if (mType.subType.tsFilterType() == DemuxTsFilterType::RECORD) {
                mIsRecordFilter = true;
            }
            break;
        case DemuxFilterMainType::MMTP:
            if (mType.subType.mmtpFilterType() == DemuxMmtpFilterType::AUDIO ||
                mType.subType.mmtpFilterType() == DemuxMmtpFilterType::VIDEO) {
                mIsMediaFilter = true;
            }
            if (mType.subType.mmtpFilterType() == DemuxMmtpFilterType::RECORD) {
                mIsRecordFilter = true;
            }
            break;
        case DemuxFilterMainType::IP:
            break;
@@ -535,12 +541,6 @@ Result Filter::startMediaFilterHandler() {
}

Result Filter::startRecordFilterHandler() {
    /*DemuxFilterTsRecordEvent tsRecordEvent;
    tsRecordEvent.pid.tPid(0);
    tsRecordEvent.indexMask.tsIndexMask(0x01);
    mFilterEvent.events.resize(1);
    mFilterEvent.events[0].tsRecord(tsRecordEvent);
*/
    std::lock_guard<std::mutex> lock(mRecordFilterOutputLock);
    if (mRecordFilterOutput.empty()) {
        return Result::SUCCESS;
@@ -567,7 +567,7 @@ Result Filter::startTemiFilterHandler() {

bool Filter::writeSectionsAndCreateEvent(vector<uint8_t> data) {
    // TODO check how many sections has been read
    ALOGD("[Filter] section hander");
    ALOGD("[Filter] section handler");
    std::lock_guard<std::mutex> lock(mFilterEventLock);
    if (!writeDataToFilterMQ(data)) {
        return false;
Loading