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 #include "BusStreamProvider.h"
16
17 #include <android-base/logging.h>
18
19 #include <algorithm>
20
21 #include "DummyBusOutputStream.h"
22 #include "RemoteBusOutputStream.h"
23
24 using aidl::device::google::atv::audio_proxy::IOutputStream;
25
26 namespace audio_proxy::service {
27
setStreamProvider(std::shared_ptr<IStreamProvider> provider)28 void BusStreamProvider::setStreamProvider(
29 std::shared_ptr<IStreamProvider> provider) {
30 std::lock_guard<std::mutex> lock(mLock);
31 cleanStreamOutList_Locked();
32 mStreamProvider = std::move(provider);
33
34 for (auto& weakStream : mStreamOutList) {
35 if (sp<StreamOutImpl> stream = weakStream.promote()) {
36 auto oldOutputStream = stream->getOutputStream();
37 auto outputStream = openOutputStream_Locked(
38 oldOutputStream->getAddress(), oldOutputStream->getConfig(),
39 oldOutputStream->getFlags(),
40 oldOutputStream->getConfig().bufferSizeBytes,
41 oldOutputStream->getConfig().latencyMs);
42 stream->updateOutputStream(std::move(outputStream));
43 }
44 }
45 }
46
getStreamProvider()47 std::shared_ptr<IStreamProvider> BusStreamProvider::getStreamProvider() {
48 std::lock_guard<std::mutex> lock(mLock);
49 return mStreamProvider;
50 }
51
openOutputStream(const std::string & address,const AidlAudioConfig & config,int32_t flags,int64_t bufferSizeBytes,int32_t latencyMs)52 std::shared_ptr<BusOutputStream> BusStreamProvider::openOutputStream(
53 const std::string& address, const AidlAudioConfig& config, int32_t flags,
54 int64_t bufferSizeBytes, int32_t latencyMs) {
55 std::lock_guard<std::mutex> lock(mLock);
56 return openOutputStream_Locked(address, config, flags, bufferSizeBytes,
57 latencyMs);
58 }
59
onStreamOutCreated(wp<StreamOutImpl> stream)60 void BusStreamProvider::onStreamOutCreated(wp<StreamOutImpl> stream) {
61 std::lock_guard<std::mutex> lock(mLock);
62 cleanStreamOutList_Locked();
63 mStreamOutList.emplace_back(std::move(stream));
64 }
65
openOutputStream_Locked(const std::string & address,const AidlAudioConfig & config,int32_t flags,int64_t bufferSizeBytes,int32_t latencyMs)66 std::shared_ptr<BusOutputStream> BusStreamProvider::openOutputStream_Locked(
67 const std::string& address, const AidlAudioConfig& config, int32_t flags,
68 int64_t bufferSizeBytes, int32_t latencyMs) {
69 AidlAudioConfig newConfig = config;
70 newConfig.bufferSizeBytes = bufferSizeBytes;
71 newConfig.latencyMs = latencyMs;
72
73 if (!mStreamProvider) {
74 return std::make_shared<DummyBusOutputStream>(address, newConfig, flags);
75 }
76
77 std::shared_ptr<IOutputStream> stream;
78 ndk::ScopedAStatus status =
79 mStreamProvider->openOutputStream(address, config, flags, &stream);
80 if (!status.isOk() || !stream) {
81 LOG(ERROR) << "Failed to open output stream, status " << status.getStatus();
82 return std::make_shared<DummyBusOutputStream>(address, newConfig, flags);
83 }
84
85 int64_t aidlBufferSizeInBytes = -1;
86 if (stream->getBufferSizeBytes(&aidlBufferSizeInBytes).isOk() &&
87 aidlBufferSizeInBytes > 0) {
88 newConfig.bufferSizeBytes = aidlBufferSizeInBytes;
89 }
90
91 int32_t aidlLatencyMs = -1;
92 if (stream->getLatencyMs(&aidlLatencyMs).isOk() && aidlLatencyMs > 0) {
93 newConfig.latencyMs = aidlLatencyMs;
94 }
95
96 return std::make_shared<RemoteBusOutputStream>(std::move(stream), address,
97 newConfig, flags);
98 }
99
cleanAndCountStreamOuts()100 size_t BusStreamProvider::cleanAndCountStreamOuts() {
101 std::lock_guard<std::mutex> lock(mLock);
102 cleanStreamOutList_Locked();
103 return mStreamOutList.size();
104 }
105
cleanStreamOutList_Locked()106 void BusStreamProvider::cleanStreamOutList_Locked() {
107 auto it = mStreamOutList.begin();
108 while (it != mStreamOutList.end()) {
109 if (!it->promote()) {
110 it = mStreamOutList.erase(it);
111 } else {
112 ++it;
113 }
114 }
115 }
116
117 } // namespace audio_proxy::service