blob: 6662637d548a7ca688206706f2845ac2efb435ba [file] [log] [blame]
/*
* Copyright 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <fcntl.h>
#include <fmq/AidlMessageQueue.h>
#include <gtest/gtest.h>
#include <log/log.h>
#include <utils/Condition.h>
#include <utils/Mutex.h>
#include <atomic>
#include <fstream>
#include <iostream>
#include <map>
#include <thread>
#include <aidl/android/hardware/tv/tuner/BnDvrCallback.h>
#include <aidl/android/hardware/tv/tuner/IDvr.h>
#include <aidl/android/hardware/tv/tuner/ITuner.h>
#include "FilterTests.h"
using ::aidl::android::hardware::common::fmq::MQDescriptor;
using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
using ::android::AidlMessageQueue;
using ::android::Condition;
using ::android::Mutex;
using ::android::hardware::EventFlag;
using namespace aidl::android::hardware::tv::tuner;
using namespace std;
#define WAIT_TIMEOUT 3000000000
class DvrCallback : public BnDvrCallback {
public:
virtual ::ndk::ScopedAStatus onRecordStatus(RecordStatus status) override {
ALOGD("[vts] record status %hhu", status);
switch (status) {
case RecordStatus::DATA_READY:
break;
case RecordStatus::LOW_WATER:
break;
case RecordStatus::HIGH_WATER:
case RecordStatus::OVERFLOW:
ALOGD("[vts] record overflow. Flushing.");
EXPECT_TRUE(mDvr) << "Dvr callback is not set with an IDvr";
if (mDvr) {
ndk::ScopedAStatus result = mDvr->flush();
ALOGD("[vts] Flushing result %s.", result.getMessage());
}
break;
}
return ndk::ScopedAStatus::ok();
}
virtual ::ndk::ScopedAStatus onPlaybackStatus(PlaybackStatus status) override {
// android::Mutex::Autolock autoLock(mMsgLock);
ALOGD("[vts] playback status %d", status);
switch (status) {
case PlaybackStatus::SPACE_EMPTY:
case PlaybackStatus::SPACE_ALMOST_EMPTY:
ALOGD("[vts] keep playback inputing %d", status);
mKeepWritingPlaybackFMQ = true;
break;
case PlaybackStatus::SPACE_ALMOST_FULL:
case PlaybackStatus::SPACE_FULL:
ALOGD("[vts] stop playback inputing %d", status);
mKeepWritingPlaybackFMQ = false;
break;
}
return ndk::ScopedAStatus::ok();
}
void stopPlaybackThread();
void testRecordOutput();
void stopRecordThread();
void startPlaybackInputThread(string& dataInputFile, PlaybackSettings& settings,
MQDesc& playbackMQDescriptor);
void startRecordOutputThread(RecordSettings recordSettings, MQDesc& recordMQDescriptor);
static void* __threadLoopPlayback(void* user);
static void* __threadLoopRecord(void* threadArgs);
void playbackThreadLoop();
void recordThreadLoop();
bool readRecordFMQ();
void setDvr(std::shared_ptr<IDvr> dvr) { mDvr = dvr; }
private:
struct RecordThreadArgs {
DvrCallback* user;
RecordSettings* recordSettings;
bool* keepReadingRecordFMQ;
};
// uint16_t mDataLength = 0;
std::vector<int8_t> mDataOutputBuffer;
std::map<uint32_t, std::unique_ptr<FilterMQ>> mFilterMQ;
std::unique_ptr<FilterMQ> mPlaybackMQ;
std::unique_ptr<FilterMQ> mRecordMQ;
std::map<uint32_t, EventFlag*> mFilterMQEventFlag;
android::Mutex mMsgLock;
android::Condition mMsgCondition;
std::atomic<bool> mKeepWritingPlaybackFMQ = true;
std::atomic<bool> mKeepReadingRecordFMQ = true;
std::atomic<bool> mPlaybackThreadRunning;
std::atomic<bool> mRecordThreadRunning;
std::thread mPlaybackThread;
std::thread mRecordThread;
string mInputDataFile;
PlaybackSettings mPlaybackSettings;
std::shared_ptr<IDvr> mDvr = nullptr;
// int mPidFilterOutputCount = 0;
};
class DvrTests {
public:
void setService(std::shared_ptr<ITuner> tuner) { mService = tuner; }
void setDemux(std::shared_ptr<IDemux> demux) { mDemux = demux; }
void startPlaybackInputThread(string& dataInputFile, PlaybackSettings& settings) {
mDvrPlaybackCallback->startPlaybackInputThread(dataInputFile, settings,
mDvrPlaybackMQDescriptor);
};
void startRecordOutputThread(RecordSettings settings) {
mDvrRecordCallback->startRecordOutputThread(settings, mDvrRecordMQDescriptor);
};
void stopPlaybackThread() { mDvrPlaybackCallback->stopPlaybackThread(); }
void testRecordOutput() { mDvrRecordCallback->testRecordOutput(); }
void stopRecordThread() { mDvrRecordCallback->stopRecordThread(); }
AssertionResult openDvrInDemux(DvrType type, int32_t bufferSize);
AssertionResult configDvrPlayback(DvrSettings setting);
AssertionResult configDvrRecord(DvrSettings setting);
AssertionResult getDvrPlaybackMQDescriptor();
AssertionResult getDvrRecordMQDescriptor();
AssertionResult attachFilterToDvr(std::shared_ptr<IFilter> filter);
AssertionResult detachFilterToDvr(std::shared_ptr<IFilter> filter);
AssertionResult stopDvrPlayback();
AssertionResult startDvrPlayback();
AssertionResult stopDvrRecord();
AssertionResult startDvrRecord();
void closeDvrPlayback();
void closeDvrRecord();
protected:
static AssertionResult failure() { return ::testing::AssertionFailure(); }
static AssertionResult success() { return ::testing::AssertionSuccess(); }
std::shared_ptr<ITuner> mService;
std::shared_ptr<IDvr> mDvrPlayback;
std::shared_ptr<IDvr> mDvrRecord;
std::shared_ptr<IDemux> mDemux;
std::shared_ptr<DvrCallback> mDvrPlaybackCallback;
std::shared_ptr<DvrCallback> mDvrRecordCallback;
MQDesc mDvrPlaybackMQDescriptor;
MQDesc mDvrRecordMQDescriptor;
};