1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
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 
16 #ifndef SESSION_PROCESSOR_H
17 #define SESSION_PROCESSOR_H
18 
19 #include <thread>
20 #include <mutex>
21 #include <condition_variable>
22 #include <queue>
23 #include <functional>
24 #include "audio_policy_server.h"
25 #include "audio_info.h"
26 
27 namespace OHOS {
28 namespace AudioStandard {
29 struct SessionEvent {
30     enum class Type {
31         ADD,
32         REMOVE,
33         CLOSE_WAKEUP_SOURCE,
34     };
35 
36     SessionEvent() = delete;
37 
38     Type type;
39     uint64_t sessionID;
40     SessionInfo sessionInfo_ = {};
41 };
42 
43 class SessionProcessor {
44 public:
45     DISALLOW_COPY_AND_MOVE(SessionProcessor);
46 
SessionProcessor(std::function<void (const uint64_t,const int32_t)> processorSessionRemoved,std::function<void (SessionEvent)> processorSessionAdded,std::function<void (const uint64_t)> processorCloseWakeupSource)47     SessionProcessor(std::function<void(const uint64_t, const int32_t)> processorSessionRemoved,
48         std::function<void(SessionEvent)> processorSessionAdded,
49         std::function<void(const uint64_t)> processorCloseWakeupSource)
50         : processorSessionRemoved_(processorSessionRemoved), processorSessionAdded_(processorSessionAdded),
51         processorCloseWakeupSource_(processorCloseWakeupSource)
52     {
53     }
54 
~SessionProcessor()55     ~SessionProcessor()
56     {
57         Stop();
58     }
59 
Post(const SessionEvent event)60     void Post(const SessionEvent event)
61     {
62         std::unique_lock<std::mutex> lock(mutex_);
63         sessionEvents_.emplace(event);
64         cv_.notify_one();
65     }
66 
Start()67     void Start()
68     {
69         std::unique_lock<std::mutex> lock(mutex_);
70         if (exitLoop_ == false) {
71             AUDIO_INFO_LOG("exitLoop_ == false return");
72             return;
73         } else if (started_ == true) {
74             AUDIO_INFO_LOG("started_ == false return");
75             return;
76         }
77         exitLoop_ = false;
78         started_ = true;
79         loopThread_ = std::thread{[this] { this->Loop(); }};
80         AUDIO_INFO_LOG("Start end");
81     }
82 
Stop()83     void Stop()
84     {
85         {
86             std::unique_lock<std::mutex> lock(mutex_);
87             exitLoop_ = true;
88         }
89         cv_.notify_one();
90         if (loopThread_.joinable()) {
91             loopThread_.join();
92         }
93         AUDIO_INFO_LOG("Stop end");
94     }
95 
96 private:
ProcessSessionEvent(SessionEvent event,const int32_t zoneID)97     void ProcessSessionEvent(SessionEvent event, const int32_t zoneID)
98     {
99         switch (event.type) {
100             case SessionEvent::Type::REMOVE :
101                 processorSessionRemoved_(event.sessionID, zoneID);
102                 break;
103             case SessionEvent::Type::ADD :
104                 processorSessionAdded_(event);
105                 break;
106             case SessionEvent::Type::CLOSE_WAKEUP_SOURCE :
107                 processorCloseWakeupSource_(event.sessionID);
108                 break;
109             default:
110                 break;
111         }
112     }
113 
Loop()114     void Loop()
115     {
116         std::unique_lock<std::mutex> lock(mutex_);
117         while (!exitLoop_) {
118             while (sessionEvents_.size() > 0) {
119                 auto frontEvent = sessionEvents_.front();
120                 sessionEvents_.pop();
121                 lock.unlock();
122                 ProcessSessionEvent(frontEvent, 0);
123                 lock.lock();
124             }
125             cv_.wait(lock, [this] {
126                 bool res = (sessionEvents_.size() > 0 || exitLoop_);
127                 return res;
128             });
129         }
130         started_ = false;
131         AUDIO_INFO_LOG("Loop exit");
132         return;
133     }
134 
135     bool exitLoop_ = true;
136     bool started_ = false;
137     std::thread loopThread_;
138     std::mutex mutex_;
139     std::condition_variable cv_;
140     std::queue<SessionEvent> sessionEvents_;
141     std::function<void(const uint64_t, const int32_t)> processorSessionRemoved_;
142     std::function<void(SessionEvent)> processorSessionAdded_;
143     std::function<void(const uint64_t)> processorCloseWakeupSource_;
144 };
145 } // namespace AudioStandard
146 } // namespace OHOS
147 #endif // SESSION_PROCESSOR_H