1 // Copyright (C) 2021 The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #pragma once 16 17 #include <atomic> 18 #include <mutex> 19 20 // clang-format off 21 #include PATH(android/hardware/audio/FILE_VERSION/IStreamOut.h) 22 // clang-format on 23 24 #include <android-base/thread_annotations.h> 25 #include <fmq/EventFlag.h> 26 #include <fmq/MessageQueue.h> 27 #include <hidl/MQDescriptor.h> 28 #include <inttypes.h> 29 #include <utils/Thread.h> 30 31 #include "AidlTypes.h" 32 33 using android::sp; 34 using android::Thread; 35 using android::hardware::EventFlag; 36 using android::hardware::kSynchronizedReadWrite; 37 using android::hardware::MessageQueue; 38 using namespace android::hardware::audio::common::CPP_VERSION; 39 using namespace android::hardware::audio::CPP_VERSION; 40 41 namespace audio_proxy::service { 42 43 class BusOutputStream; 44 45 class WriteThread : public Thread { 46 public: 47 using CommandMQ = 48 MessageQueue<IStreamOut::WriteCommand, kSynchronizedReadWrite>; 49 using DataMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>; 50 using StatusMQ = 51 MessageQueue<IStreamOut::WriteStatus, kSynchronizedReadWrite>; 52 53 // WriteThread's lifespan never exceeds StreamOut's lifespan. 54 WriteThread(std::shared_ptr<BusOutputStream> stream, CommandMQ* commandMQ, 55 DataMQ* dataMQ, StatusMQ* statusMQ, EventFlag* eventFlag, 56 uint32_t latencyMs); 57 58 ~WriteThread() override; 59 60 void stop(); 61 62 void updateOutputStream(std::shared_ptr<BusOutputStream> stream); 63 64 std::pair<uint64_t, TimeSpec> getPresentationPosition(); 65 66 private: 67 bool threadLoop() override; 68 69 // The following function is called on the thread and it will modify the 70 // variables which may be read from another thread. 71 IStreamOut::WriteStatus doWrite(BusOutputStream* stream); 72 73 // The following function is called on the thread and only read variable 74 // that is written on the same thread, so there's no need to lock the 75 // resources. 76 IStreamOut::WriteStatus doGetPresentationPosition() const 77 NO_THREAD_SAFETY_ANALYSIS; 78 79 IStreamOut::WriteStatus doGetLatency() const; 80 81 // Write 0 buffer to {@param stream} for latest presentation info. 82 void queryPresentationPosition(BusOutputStream* stream); 83 84 // Update presentation position info after writing to {@param stream}. Caller 85 // should validate the {@param status}. 86 void updatePresentationPosition(const AidlWriteStatus& status, 87 BusOutputStream* stream); 88 89 std::atomic<bool> mStop = false; 90 91 std::mutex mStreamLock; 92 std::shared_ptr<BusOutputStream> mStream GUARDED_BY(mStreamLock); 93 94 CommandMQ* const mCommandMQ; 95 DataMQ* const mDataMQ; 96 StatusMQ* const mStatusMQ; 97 EventFlag* const mEventFlag; 98 99 // Latency in ms, used in HIDL API getLatency. 100 const uint32_t mLatencyMs; 101 102 // Count for consecutive FMQ command that is not WRITE. 103 int64_t mNonWriteCommandCount = 0; 104 105 // Presentation position information. 106 std::mutex mPositionLock; 107 uint64_t mPresentationFramesOffset GUARDED_BY(mPositionLock) = 0; 108 uint64_t mPresentationFrames GUARDED_BY(mPositionLock) = 0; 109 TimeSpec mPresentationTimestamp GUARDED_BY(mPositionLock) = {0, 0}; 110 uint64_t mTotalWrittenFrames GUARDED_BY(mPositionLock) = 0; 111 }; 112 113 } // namespace audio_proxy::service