1 /*
2  * Copyright (C) 2021 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 "AudioControlServer.h"
18 
19 #include <deque>
20 #include <string>
21 #include <thread>
22 
23 #include <android-base/logging.h>
24 #include <android-base/parseint.h>
25 #include <android-base/strings.h>
26 #include <grpc++/grpc++.h>
27 
28 #include <aidl/android/hardware/automotive/audiocontrol/AudioFocusChange.h>
29 #include <aidl/android/hardware/automotive/audiocontrol/BnAudioControl.h>
30 #include <aidl/android/hardware/automotive/audiocontrol/DuckingInfo.h>
31 #include <aidl/android/hardware/automotive/audiocontrol/IFocusListener.h>
32 
33 #include <android_audio_policy_configuration_V7_0.h>
34 
35 #include "AudioFocusControl.grpc.pb.h"
36 #include "AudioFocusControl.pb.h"
37 #include "libandroid_audio_controller/utils.h"
38 
39 using std::literals::chrono_literals::operator""s;
40 
41 namespace xsd {
42 using namespace ::android::audio::policy::configuration::V7_0;
43 }
44 
45 using xsd::AudioUsage;
46 
47 namespace aidl::android::hardware::automotive::audiocontrol {
48 
49 class AudioControlServerImpl : public AudioControlServer,
50                                audio_focus_control_proto::AudioFocusControlServer::Service {
51   public:
52     explicit AudioControlServerImpl(const std::string& addr);
53 
54     ~AudioControlServerImpl();
55 
RegisterFocusListener(std::shared_ptr<IFocusListener> focusListener)56     close_handle_func_t RegisterFocusListener(std::shared_ptr<IFocusListener> focusListener) override {
57         std::lock_guard<std::mutex> lock(mFocusListenerMutex);
58         mFocusListener = focusListener;
59 
60         return [this, focusListener]() {
61             std::lock_guard<std::mutex> lock(mFocusListenerMutex);
62             if (mFocusListener == focusListener) {
63                 mFocusListener = nullptr;
64             }
65         };
66     }
67 
68     grpc::Status AudioRequests(::grpc::ServerContext* context,
69                                const audio_focus_control_proto::AudioFocusControlMessage* message,
70                                ::google::protobuf::Empty*) override;
71 
72     void Start() override;
73 
74     void Join() override;
75 
76   private:
77     void RequestWorker();
78 
79     void CheckSessionHeartbeats(std::chrono::steady_clock::time_point current_timestamp);
80 
81     void HandleHeartbeat(aafc_session_id_t session,
82                          std::chrono::steady_clock::time_point timestamp);
83 
84     void HandleAcquiring(audio_focus_control_proto::AudioFocusRequest&& acquire_request,
85                          std::chrono::steady_clock::time_point timestamp);
86 
87     void HandleReleasing(aafc_session_id_t release_session);
88 
89     void RequestAudioFocus(aafc_audio_usage_t usage, aafc_zone_id_t zone,
90                            AudioFocusChange focus_change);
91 
92     void AbandonAudioFocus(aafc_audio_usage_t usage, aafc_zone_id_t zone);
93 
94     using grpc_request_t = audio_focus_control_proto::AudioFocusControlMessage;
95     using focus_listener_request_key_t = std::pair<aafc_audio_usage_t, aafc_zone_id_t>;
96 
97     struct AudioFocusSession {
98         audio_focus_control_proto::AudioFocusRequest mRequest;
99         std::chrono::steady_clock::time_point mLastHeartbeat;
100 
101         focus_listener_request_key_t GetRequestKey() const;
102         AudioFocusChange GetFocusChange() const;
103     };
104 
105     using session_pool_t = std::map<aafc_session_id_t, AudioFocusSession>;
106 
107     // data members
108 
109     std::string mServiceAddr;
110     std::unique_ptr<::grpc::Server> mGrpcServer;
111     std::shared_ptr<IFocusListener> mFocusListener{nullptr};
112 
113     // grpc request queue
114     std::deque<grpc_request_t> mRequestQueue;
115 
116     // On the focus listener side, the usage/zone pair is used as the key,
117     // and acquiring focus multiple times on the same usage and zone will
118     // be treated as once, so we have to maintain the "sessions" and ref count
119     // by ourselves here.
120     //
121     // Active audio focus sessions from grpc clients
122     session_pool_t mSessionPool;
123 
124     // ref counts of usage/zone pair
125     std::map<focus_listener_request_key_t, unsigned> mAudioFocusCount;
126 
127     std::atomic<bool> mShutdownFlag{false};
128     std::thread mRequestWorker;
129 
130     mutable std::mutex mFocusListenerMutex;
131     mutable std::mutex mRequestQueueMutex;
132 
133     std::condition_variable mRequestQueueCV;
134 };
135 
getServerCredentials()136 static std::shared_ptr<::grpc::ServerCredentials> getServerCredentials() {
137     // TODO(chenhaosjtuacm): get secured credentials here
138     return ::grpc::InsecureServerCredentials();
139 }
140 
AudioControlServerImpl(const std::string & addr)141 AudioControlServerImpl::AudioControlServerImpl(const std::string& addr) : mServiceAddr(addr) {}
142 
~AudioControlServerImpl()143 AudioControlServerImpl::~AudioControlServerImpl() {
144     mShutdownFlag.store(true);
145     if (mRequestWorker.joinable()) {
146         mRequestWorker.join();
147     }
148 }
149 
Start()150 void AudioControlServerImpl::Start() {
151     if (mGrpcServer) {
152         LOG(WARNING) << __func__ << ": GRPC Server is running.";
153         return;
154     }
155 
156     ::grpc::ServerBuilder builder;
157     builder.RegisterService(this);
158     builder.AddListeningPort(mServiceAddr, getServerCredentials());
159 
160     mGrpcServer = builder.BuildAndStart();
161 
162     if (!mGrpcServer) {
163         LOG(ERROR) << __func__ << ": failed to create the GRPC server, "
164                    << "please make sure the configuration and permissions are correct.";
165         return;
166     }
167 
168     mRequestWorker = std::thread(std::bind(&AudioControlServerImpl::RequestWorker, this));
169 }
170 
Join()171 void AudioControlServerImpl::Join() {
172     if (!mGrpcServer) {
173         LOG(WARNING) << __func__ << ": GRPC Server is not running.";
174         return;
175     }
176     mGrpcServer->Wait();
177 }
178 
AudioRequests(::grpc::ServerContext * context,const audio_focus_control_proto::AudioFocusControlMessage * message,::google::protobuf::Empty *)179 grpc::Status AudioControlServerImpl::AudioRequests(
180         ::grpc::ServerContext* context,
181         const audio_focus_control_proto::AudioFocusControlMessage* message,
182         ::google::protobuf::Empty*) {
183     {
184         std::lock_guard<std::mutex> lock(mRequestQueueMutex);
185         mRequestQueue.emplace_back(*message);
186     }
187     mRequestQueueCV.notify_all();
188     return ::grpc::Status::OK;
189 }
190 
RequestWorker()191 void AudioControlServerImpl::RequestWorker() {
192     constexpr auto kCheckHeartbeatFreq = 1s;
193     auto nextHeartbeatCheckTime = std::chrono::steady_clock::now();
194     while (!mShutdownFlag.load()) {
195         std::optional<grpc_request_t> message;
196         {
197             std::unique_lock<std::mutex> lock(mRequestQueueMutex);
198             if (mRequestQueue.empty()) {
199                 mRequestQueueCV.wait_until(lock, nextHeartbeatCheckTime,
200                                            [this]() { return !mRequestQueue.empty(); });
201             }
202             if (!mRequestQueue.empty()) {
203                 message = std::move(*mRequestQueue.begin());
204                 mRequestQueue.pop_front();
205             }
206         }
207 
208         auto current_timestamp = std::chrono::steady_clock::now();
209         if (message) {
210             for (auto&& active_session : message->active_sessions()) {
211                 HandleHeartbeat(active_session, current_timestamp);
212             }
213 
214             for (auto&& acquire_request : *message->mutable_acquire_requests()) {
215                 HandleAcquiring(std::move(acquire_request), current_timestamp);
216             }
217 
218             for (auto&& release_session : message->release_requests()) {
219                 HandleReleasing(release_session);
220             }
221         }
222         if (current_timestamp >= nextHeartbeatCheckTime) {
223             nextHeartbeatCheckTime += kCheckHeartbeatFreq;
224             CheckSessionHeartbeats(current_timestamp);
225         }
226     }
227 }
228 
HandleHeartbeat(aafc_session_id_t session,std::chrono::steady_clock::time_point timestamp)229 void AudioControlServerImpl::HandleHeartbeat(aafc_session_id_t session,
230                                              std::chrono::steady_clock::time_point timestamp) {
231     auto session_search = mSessionPool.find(session);
232     if (session_search == mSessionPool.end()) {
233         LOG(ERROR) << __func__ << ": unknown session ID: " << session;
234         return;
235     }
236     auto& session_info = session_search->second;
237     session_info.mLastHeartbeat = timestamp;
238 }
239 
HandleAcquiring(audio_focus_control_proto::AudioFocusRequest && acquire_request,std::chrono::steady_clock::time_point timestamp)240 void AudioControlServerImpl::HandleAcquiring(
241         audio_focus_control_proto::AudioFocusRequest&& acquire_request,
242         std::chrono::steady_clock::time_point timestamp) {
243     const auto session_id = acquire_request.session_id();
244     const auto session_emplace = mSessionPool.emplace(
245             session_id, AudioFocusSession{std::move(acquire_request), timestamp});
246     if (session_emplace.second == false) {
247         LOG(ERROR) << __func__ << ": duplicate session ID: " << session_id;
248         return;
249     }
250 
251     const auto& session_emplace_iter = session_emplace.first;
252     const auto& session_info = session_emplace_iter->second;
253     const auto request_key = session_info.GetRequestKey();
254     const auto focus_change = session_info.GetFocusChange();
255     const auto ref_count_search = mAudioFocusCount.find(request_key);
256     const auto& [audio_usage, zone_id] = request_key;
257     LOG(DEBUG) << __func__ << ": acquiring: " << toString(static_cast<AudioUsage>(audio_usage))
258                << " " << zone_id << " " << toString(focus_change);
259 
260     const bool not_found = ref_count_search == mAudioFocusCount.end();
261     const bool count_zero = !not_found && ref_count_search->second == 0;
262 
263     if (count_zero) {
264         LOG(WARNING) << __func__ << ": unexcepted unremoved zero ref count, treating as missing.";
265     }
266 
267     if (not_found || count_zero) {
268         mAudioFocusCount[request_key] = 1;
269         RequestAudioFocus(audio_usage, zone_id, focus_change);
270     } else {
271         ++ref_count_search->second;
272     }
273 }
274 
HandleReleasing(aafc_session_id_t release_session)275 void AudioControlServerImpl::HandleReleasing(aafc_session_id_t release_session) {
276     const auto session_search = mSessionPool.find(release_session);
277     if (session_search == mSessionPool.end()) {
278         LOG(ERROR) << __func__ << ": unknown session ID: " << release_session;
279         return;
280     }
281     const auto& session_info = session_search->second;
282     const auto request_key = session_info.GetRequestKey();
283     const auto& [audio_usage, zone_id] = request_key;
284     mSessionPool.erase(session_search);
285     LOG(DEBUG) << __func__ << ": releasing: " << toString(static_cast<AudioUsage>(audio_usage))
286                << " " << zone_id;
287 
288     const auto ref_count_search = mAudioFocusCount.find(request_key);
289     if (ref_count_search == mAudioFocusCount.end()) {
290         LOG(ERROR) << __func__ << ": unknown request, audio usage: "
291                    << toString(static_cast<AudioUsage>(audio_usage)) << ", zone: " << zone_id;
292         return;
293     }
294     auto& request_ref_count = ref_count_search->second;
295     if (--request_ref_count == 0) {
296         AbandonAudioFocus(audio_usage, zone_id);
297         mAudioFocusCount.erase(ref_count_search);
298     }
299 }
300 
RequestAudioFocus(aafc_audio_usage_t usage,aafc_zone_id_t zone,AudioFocusChange focus_change)301 void AudioControlServerImpl::RequestAudioFocus(aafc_audio_usage_t usage, aafc_zone_id_t zone,
302                                                AudioFocusChange focus_change) {
303     std::lock_guard<std::mutex> lock(mFocusListenerMutex);
304     auto listener = mFocusListener;
305     const auto audio_usage = static_cast<AudioUsage>(usage);
306     LOG(DEBUG) << __func__
307                << ": requesting focus, usage: " << toString(audio_usage)
308                << ", zone: " << zone
309                << ", focus change: " << toString(static_cast<AudioFocusChange>(focus_change));
310     if (!listener) {
311         LOG(ERROR) << __func__ << ": audio focus listener has not been registered.";
312         return;
313     }
314     listener->requestAudioFocus(toString(audio_usage), zone, focus_change);
315 }
316 
AbandonAudioFocus(aafc_audio_usage_t usage,aafc_zone_id_t zone)317 void AudioControlServerImpl::AbandonAudioFocus(aafc_audio_usage_t usage, aafc_zone_id_t zone) {
318     std::lock_guard<std::mutex> lock(mFocusListenerMutex);
319     auto listener = mFocusListener;
320     const auto audio_usage = static_cast<AudioUsage>(usage);
321     LOG(DEBUG) << __func__
322                << ": abandoning focus, usage: " << toString(audio_usage)
323                << ", zone: " << zone;
324     if (!listener) {
325         LOG(ERROR) << __func__ << ": audio focus listener has not been registered.";
326         return;
327     }
328     listener->abandonAudioFocus(toString(audio_usage), zone);
329 }
330 
CheckSessionHeartbeats(std::chrono::steady_clock::time_point current_timestamp)331 void AudioControlServerImpl::CheckSessionHeartbeats(
332         std::chrono::steady_clock::time_point current_timestamp) {
333     constexpr auto kSessionHeartbeatTimeout = 5s;
334     const auto timestamp_to_sec = [](auto&& timestamp) {
335         return std::chrono::duration_cast<std::chrono::duration<double>>(
336                        timestamp.time_since_epoch())
337                 .count();
338     };
339 
340     constexpr size_t max_timeout_session_num = 256;
341     std::array<aafc_session_id_t, max_timeout_session_num> timeout_sessions;
342     size_t num_of_timeout_sessions = 0;
343 
344     for (auto&& current_session : mSessionPool) {
345         const auto& current_session_id = current_session.first;
346         const auto& current_session_info = current_session.second;
347         if (current_session_info.mLastHeartbeat + kSessionHeartbeatTimeout < current_timestamp) {
348             if (num_of_timeout_sessions >= max_timeout_session_num) {
349                 LOG(ERROR) << __func__ << ": timeout session number exceeds the limit: "
350                            << max_timeout_session_num;
351                 break;
352             }
353             LOG(WARNING) << __func__ << ": timeout on session " << current_session_id
354                          << ", last heartbeat at "
355                          << timestamp_to_sec(current_session_info.mLastHeartbeat)
356                          << ", current timestamp is " << timestamp_to_sec(current_timestamp)
357                          << ", timeout limit " << kSessionHeartbeatTimeout.count() << "s";
358             timeout_sessions[num_of_timeout_sessions++] = current_session_id;
359         }
360     }
361 
362     for (int i = 0; i < num_of_timeout_sessions; ++i) {
363         HandleReleasing(timeout_sessions[i]);
364     }
365 }
366 
367 AudioControlServerImpl::focus_listener_request_key_t
GetRequestKey() const368 AudioControlServerImpl::AudioFocusSession::GetRequestKey() const {
369     return {mRequest.audio_usage(), mRequest.zone_id()};
370 }
371 
GetFocusChange() const372 AudioFocusChange AudioControlServerImpl::AudioFocusSession::GetFocusChange() const {
373     constexpr auto cast_to_bitfield = [](auto&& focus_change) {
374         return static_cast<AudioFocusChange>(focus_change);
375     };
376     if (!mRequest.is_transient()) {
377         return cast_to_bitfield(AudioFocusChange::GAIN);
378     }
379     if (mRequest.is_exclusive()) {
380         return cast_to_bitfield(AudioFocusChange::GAIN_TRANSIENT_EXCLUSIVE);
381     }
382     if (mRequest.allow_duck()) {
383         return cast_to_bitfield(AudioFocusChange::GAIN_TRANSIENT_MAY_DUCK);
384     }
385     return cast_to_bitfield(AudioFocusChange::GAIN_TRANSIENT);
386 }
387 
MakeAudioControlServer(const std::string & addr)388 std::unique_ptr<AudioControlServer> MakeAudioControlServer(const std::string& addr) {
389     return std::make_unique<AudioControlServerImpl>(addr);
390 }
391 
392 }  // namespace aidl::android::hardware::automotive::audiocontrol
393