1 /* 2 * Copyright 2020 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 #include <android-base/logging.h> 18 #include <android/hardware/tv/tuner/1.0/IDvr.h> 19 #include <android/hardware/tv/tuner/1.0/IDvrCallback.h> 20 #include <android/hardware/tv/tuner/1.0/ITuner.h> 21 #include <android/hardware/tv/tuner/1.0/types.h> 22 #include <fcntl.h> 23 #include <fmq/MessageQueue.h> 24 #include <gtest/gtest.h> 25 #include <hidl/HidlSupport.h> 26 #include <hidl/Status.h> 27 #include <utils/Condition.h> 28 #include <utils/Mutex.h> 29 #include <fstream> 30 #include <iostream> 31 #include <map> 32 33 #include "FilterTests.h" 34 35 using android::Condition; 36 using android::Mutex; 37 using android::sp; 38 using android::hardware::EventFlag; 39 using android::hardware::kSynchronizedReadWrite; 40 using android::hardware::MessageQueue; 41 using android::hardware::MQDescriptorSync; 42 using android::hardware::Return; 43 using android::hardware::Void; 44 using android::hardware::tv::tuner::V1_0::DemuxFilterStatus; 45 using android::hardware::tv::tuner::V1_0::DvrSettings; 46 using android::hardware::tv::tuner::V1_0::DvrType; 47 using android::hardware::tv::tuner::V1_0::IDvr; 48 using android::hardware::tv::tuner::V1_0::IDvrCallback; 49 using android::hardware::tv::tuner::V1_0::ITuner; 50 using android::hardware::tv::tuner::V1_0::PlaybackSettings; 51 using android::hardware::tv::tuner::V1_0::PlaybackStatus; 52 using android::hardware::tv::tuner::V1_0::RecordSettings; 53 using android::hardware::tv::tuner::V1_0::RecordStatus; 54 using android::hardware::tv::tuner::V1_0::Result; 55 56 using namespace std; 57 58 #define WAIT_TIMEOUT 3000000000 59 60 class DvrCallback : public IDvrCallback { 61 public: onRecordStatus(DemuxFilterStatus status)62 virtual Return<void> onRecordStatus(DemuxFilterStatus status) override { 63 ALOGD("[vts] record status %hhu", status); 64 switch (status) { 65 case DemuxFilterStatus::DATA_READY: 66 break; 67 case DemuxFilterStatus::LOW_WATER: 68 break; 69 case DemuxFilterStatus::HIGH_WATER: 70 case DemuxFilterStatus::OVERFLOW: 71 ALOGD("[vts] record overflow. Flushing."); 72 EXPECT_TRUE(mDvr) << "Dvr callback is not set with an IDvr"; 73 if (mDvr) { 74 Result result = mDvr->flush(); 75 ALOGD("[vts] Flushing result %d.", result); 76 } 77 break; 78 } 79 return Void(); 80 } 81 onPlaybackStatus(PlaybackStatus status)82 virtual Return<void> onPlaybackStatus(PlaybackStatus status) override { 83 // android::Mutex::Autolock autoLock(mMsgLock); 84 ALOGD("[vts] playback status %d", status); 85 switch (status) { 86 case PlaybackStatus::SPACE_EMPTY: 87 case PlaybackStatus::SPACE_ALMOST_EMPTY: 88 ALOGD("[vts] keep playback inputing %d", status); 89 mKeepWritingPlaybackFMQ = true; 90 break; 91 case PlaybackStatus::SPACE_ALMOST_FULL: 92 case PlaybackStatus::SPACE_FULL: 93 ALOGD("[vts] stop playback inputing %d", status); 94 mKeepWritingPlaybackFMQ = false; 95 break; 96 } 97 return Void(); 98 } 99 100 void stopPlaybackThread(); 101 void testRecordOutput(); 102 void stopRecordThread(); 103 104 void startPlaybackInputThread(string& dataInputFile, PlaybackSettings& settings, 105 MQDesc& playbackMQDescriptor); 106 void startRecordOutputThread(RecordSettings recordSettings, MQDesc& recordMQDescriptor); 107 static void* __threadLoopPlayback(void* user); 108 static void* __threadLoopRecord(void* threadArgs); 109 void playbackThreadLoop(); 110 void recordThreadLoop(RecordSettings* recordSetting, bool* keepWritingPlaybackFMQ); 111 112 bool readRecordFMQ(); 113 setDvr(sp<IDvr> dvr)114 void setDvr(sp<IDvr> dvr) { mDvr = dvr; } 115 116 private: 117 struct RecordThreadArgs { 118 DvrCallback* user; 119 RecordSettings* recordSettings; 120 bool* keepReadingRecordFMQ; 121 }; 122 // uint16_t mDataLength = 0; 123 std::vector<uint8_t> mDataOutputBuffer; 124 125 std::map<uint32_t, std::unique_ptr<FilterMQ>> mFilterMQ; 126 std::unique_ptr<FilterMQ> mPlaybackMQ; 127 std::unique_ptr<FilterMQ> mRecordMQ; 128 std::map<uint32_t, EventFlag*> mFilterMQEventFlag; 129 130 android::Mutex mMsgLock; 131 android::Mutex mPlaybackThreadLock; 132 android::Mutex mRecordThreadLock; 133 android::Condition mMsgCondition; 134 135 bool mKeepWritingPlaybackFMQ = true; 136 bool mKeepReadingRecordFMQ = true; 137 bool mPlaybackThreadRunning; 138 bool mRecordThreadRunning; 139 pthread_t mPlaybackThread; 140 pthread_t mRecordThread; 141 string mInputDataFile; 142 PlaybackSettings mPlaybackSettings; 143 144 sp<IDvr> mDvr = nullptr; 145 146 // int mPidFilterOutputCount = 0; 147 }; 148 149 class DvrTests { 150 public: setService(sp<ITuner> tuner)151 void setService(sp<ITuner> tuner) { mService = tuner; } setDemux(sp<IDemux> demux)152 void setDemux(sp<IDemux> demux) { mDemux = demux; } 153 startPlaybackInputThread(string & dataInputFile,PlaybackSettings & settings)154 void startPlaybackInputThread(string& dataInputFile, PlaybackSettings& settings) { 155 mDvrPlaybackCallback->startPlaybackInputThread(dataInputFile, settings, 156 mDvrPlaybackMQDescriptor); 157 }; 158 startRecordOutputThread(RecordSettings settings)159 void startRecordOutputThread(RecordSettings settings) { 160 mDvrRecordCallback->startRecordOutputThread(settings, mDvrRecordMQDescriptor); 161 }; 162 stopPlaybackThread()163 void stopPlaybackThread() { mDvrPlaybackCallback->stopPlaybackThread(); } testRecordOutput()164 void testRecordOutput() { mDvrRecordCallback->testRecordOutput(); } stopRecordThread()165 void stopRecordThread() { mDvrRecordCallback->stopRecordThread(); } 166 167 AssertionResult openDvrInDemux(DvrType type, uint32_t bufferSize); 168 AssertionResult configDvrPlayback(DvrSettings setting); 169 AssertionResult configDvrRecord(DvrSettings setting); 170 AssertionResult getDvrPlaybackMQDescriptor(); 171 AssertionResult getDvrRecordMQDescriptor(); 172 AssertionResult attachFilterToDvr(sp<IFilter> filter); 173 AssertionResult detachFilterToDvr(sp<IFilter> filter); 174 AssertionResult stopDvrPlayback(); 175 AssertionResult startDvrPlayback(); 176 AssertionResult stopDvrRecord(); 177 AssertionResult startDvrRecord(); 178 void closeDvrPlayback(); 179 void closeDvrRecord(); 180 181 protected: failure()182 static AssertionResult failure() { return ::testing::AssertionFailure(); } 183 success()184 static AssertionResult success() { return ::testing::AssertionSuccess(); } 185 186 sp<ITuner> mService; 187 sp<IDvr> mDvrPlayback; 188 sp<IDvr> mDvrRecord; 189 sp<IDemux> mDemux; 190 sp<DvrCallback> mDvrPlaybackCallback; 191 sp<DvrCallback> mDvrRecordCallback; 192 MQDesc mDvrPlaybackMQDescriptor; 193 MQDesc mDvrRecordMQDescriptor; 194 }; 195