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