blob: 56fdd23951c6af21fa7f6ae91c0c2a810359c2ed [file] [log] [blame]
Mikhail Naganov43a85cf2023-07-24 11:44:50 -07001/*
2 * Copyright (C) 2023 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
Mikhail Naganov92166142024-10-09 18:10:44 -070017/**
18 ** This class is deprecated because its use causes threading issues
19 ** with the FMQ due to change of threads reading and writing into FMQ.
20 **
21 ** DO NOT USE. These files will be removed.
22 **/
23
Mikhail Naganov43a85cf2023-07-24 11:44:50 -070024#pragma once
25
Mikhail Naganov92166142024-10-09 18:10:44 -070026#include "core-impl/Stream.h"
Mikhail Naganov43a85cf2023-07-24 11:44:50 -070027
Mikhail Naganov92166142024-10-09 18:10:44 -070028namespace aidl::android::hardware::audio::core::deprecated {
Mikhail Naganov43a85cf2023-07-24 11:44:50 -070029
Mikhail Naganov0faf3392023-08-02 12:24:15 -070030// 'StreamSwitcher' is an implementation of 'StreamCommonInterface' which allows
Mikhail Naganov43a85cf2023-07-24 11:44:50 -070031// dynamically switching the underlying stream implementation based on currently
32// connected devices. This is achieved by replacing inheritance from
33// 'StreamCommonImpl' with owning an instance of it. StreamSwitcher must be
34// extended in order to supply the logic for choosing the stream
35// implementation. When there are no connected devices, for instance, upon the
36// creation, the StreamSwitcher engages an instance of a stub stream in order to
37// keep serving requests coming via 'StreamDescriptor'.
38//
39// StreamSwitcher implements the 'IStreamCommon' interface directly, with
40// necessary delegation to the current stream implementation. While the stub
41// stream is engaged, any requests made via 'IStreamCommon' (parameters, effects
42// setting, etc) are postponed and only delivered on device connection change
43// to the "real" stream implementation provided by the extending class. This is why
44// the behavior of StreamSwitcher in the "stub" state is not identical to behavior
45// of 'StreamStub'. It can become a full substitute for 'StreamStub' once
46// device connection change event occurs and the extending class returns
47// 'LEAVE_CURRENT_STREAM' from 'switchCurrentStream' method.
48//
49// There is a natural limitation that the current stream implementation may only
50// be switched when the stream is in the 'STANDBY' state. Thus, when the event
51// to switch the stream occurs, the current stream is stopped and joined, and
52// its last state is validated. Since the change of the set of connected devices
53// normally occurs on patch updates, if the stream was not in standby, this is
54// reported to the caller of 'IModule.setAudioPatch' as the 'EX_ILLEGAL_STATE'
55// error.
56//
57// The simplest use case, when the implementor just needs to emulate the legacy HAL API
58// behavior of receiving the connected devices upon stream creation, the implementation
59// of the extending class can look as follows. We assume that 'StreamLegacy' implementation
60// is the one requiring to know connected devices on creation:
61//
62// class StreamLegacy : public StreamCommonImpl {
63// public:
64// StreamLegacy(StreamContext* context, const Metadata& metadata,
65// const std::vector<AudioDevice>& devices);
66// };
67//
68// class StreamOutLegacy final : public StreamOut, public StreamSwitcher {
69// public:
70// StreamOutLegacy(StreamContext&& context, metatadata etc.)
71// private:
72// DeviceSwitchBehavior switchCurrentStream(const std::vector<AudioDevice>&) override {
73// // This implementation effectively postpones stream creation until
74// // receiving the first call to 'setConnectedDevices' with a non-empty list.
75// return isStubStream() ? DeviceSwitchBehavior::CREATE_NEW_STREAM :
76// DeviceSwitchBehavior::USE_CURRENT_STREAM;
77// }
78// std::unique_ptr<StreamCommonInterfaceEx> createNewStream(
79// const std::vector<AudioDevice>& devices,
80// StreamContext* context, const Metadata& metadata) override {
81// return std::unique_ptr<StreamCommonInterfaceEx>(new InnerStreamWrapper<StreamLegacy>(
82// context, metadata, devices));
83// }
84// void onClose(StreamDescriptor::State) override { defaultOnClose(); }
85// }
86//
87
88class StreamCommonInterfaceEx : virtual public StreamCommonInterface {
89 public:
90 virtual StreamDescriptor::State getStatePriorToClosing() const = 0;
91};
92
93template <typename T>
94class InnerStreamWrapper : public T, public StreamCommonInterfaceEx {
95 public:
Shraddha Basantwani035beba2023-07-28 12:55:25 +000096 template <typename... Args>
97 InnerStreamWrapper(Args&&... args) : T(std::forward<Args>(args)...) {}
Mikhail Naganov43a85cf2023-07-24 11:44:50 -070098 StreamDescriptor::State getStatePriorToClosing() const override { return mStatePriorToClosing; }
99
100 private:
101 // Do not need to do anything on close notification from the inner stream
102 // because StreamSwitcher handles IStreamCommon::close by itself.
103 void onClose(StreamDescriptor::State statePriorToClosing) override {
104 mStatePriorToClosing = statePriorToClosing;
105 }
106
107 StreamDescriptor::State mStatePriorToClosing = StreamDescriptor::State::STANDBY;
108};
109
110class StreamSwitcher : virtual public StreamCommonInterface {
111 public:
112 StreamSwitcher(StreamContext* context, const Metadata& metadata);
113
114 ndk::ScopedAStatus close() override;
115 ndk::ScopedAStatus prepareToClose() override;
116 ndk::ScopedAStatus updateHwAvSyncId(int32_t in_hwAvSyncId) override;
117 ndk::ScopedAStatus getVendorParameters(const std::vector<std::string>& in_ids,
118 std::vector<VendorParameter>* _aidl_return) override;
119 ndk::ScopedAStatus setVendorParameters(const std::vector<VendorParameter>& in_parameters,
120 bool in_async) override;
121 ndk::ScopedAStatus addEffect(
122 const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_effect)
123 override;
124 ndk::ScopedAStatus removeEffect(
125 const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_effect)
126 override;
127
128 ndk::ScopedAStatus getStreamCommonCommon(std::shared_ptr<IStreamCommon>* _aidl_return) override;
129 ndk::ScopedAStatus updateMetadataCommon(const Metadata& metadata) override;
130
131 ndk::ScopedAStatus initInstance(
132 const std::shared_ptr<StreamCommonInterface>& delegate) override;
133 const StreamContext& getContext() const override;
134 bool isClosed() const override;
135 const ConnectedDevices& getConnectedDevices() const override;
136 ndk::ScopedAStatus setConnectedDevices(
137 const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices)
138 override;
Ram Mohan18f0d512023-07-01 00:47:09 +0530139 ndk::ScopedAStatus bluetoothParametersUpdated() override;
Weilin Xua33bb5e2024-10-02 17:16:42 +0000140 ndk::ScopedAStatus setGain(float gain) override;
Mikhail Naganov43a85cf2023-07-24 11:44:50 -0700141
142 protected:
143 // Since switching a stream requires closing down the current stream, StreamSwitcher
144 // asks the extending class its intent on the connected devices change.
145 enum DeviceSwitchBehavior {
146 // Continue using the current stream implementation. If it's the stub implementation,
147 // StreamSwitcher starts treating the stub stream as a "real" implementation,
148 // without effectively closing it and starting again.
149 USE_CURRENT_STREAM,
150 // This is the normal case when the extending class provides a "real" implementation
151 // which is not a stub implementation.
152 CREATE_NEW_STREAM,
153 // This is the case when the extending class wants to revert back to the initial
154 // condition of using a stub stream provided by the StreamSwitcher. This behavior
155 // is only allowed when the list of connected devices is empty.
156 SWITCH_TO_STUB_STREAM,
157 // Use when the set of devices is not supported by the extending class. This returns
158 // 'EX_UNSUPPORTED_OPERATION' from 'setConnectedDevices'.
159 UNSUPPORTED_DEVICES,
160 };
161 // StreamSwitcher will call these methods from 'setConnectedDevices'. If the switch behavior
162 // is 'CREATE_NEW_STREAM', the 'createwNewStream' function will be called (with the same
163 // device vector) for obtaining a new stream implementation, assuming that closing
164 // the current stream was a success.
165 virtual DeviceSwitchBehavior switchCurrentStream(
166 const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) = 0;
167 virtual std::unique_ptr<StreamCommonInterfaceEx> createNewStream(
168 const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices,
169 StreamContext* context, const Metadata& metadata) = 0;
170 virtual void onClose(StreamDescriptor::State streamPriorToClosing) = 0;
171
172 bool isStubStream() const { return mIsStubStream; }
173 StreamCommonInterfaceEx* getCurrentStream() const { return mStream.get(); }
174
175 private:
176 using VndParam = std::pair<std::vector<VendorParameter>, bool /*isAsync*/>;
177
178 static constexpr bool isValidClosingStreamState(StreamDescriptor::State state) {
179 return state == StreamDescriptor::State::STANDBY || state == StreamDescriptor::State::ERROR;
180 }
181
182 ndk::ScopedAStatus closeCurrentStream(bool validateStreamState);
183
184 // StreamSwitcher does not own the context.
185 StreamContext* mContext;
186 Metadata mMetadata;
187 ChildInterface<StreamCommonDelegator> mCommon;
188 // The current stream.
189 std::unique_ptr<StreamCommonInterfaceEx> mStream;
190 // Indicates whether 'mCurrentStream' is a stub stream implementation
191 // maintained by StreamSwitcher until the extending class provides a "real"
192 // implementation. The invariant of this state is that there are no connected
193 // devices.
194 bool mIsStubStream = true;
195 // Storage for the data from commands received via 'IStreamCommon'.
196 std::optional<int32_t> mHwAvSyncId;
197 std::vector<VndParam> mMissedParameters;
198 std::vector<std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>> mEffects;
Ram Mohan18f0d512023-07-01 00:47:09 +0530199 bool mBluetoothParametersUpdated = false;
Mikhail Naganov43a85cf2023-07-24 11:44:50 -0700200};
201
Mikhail Naganov92166142024-10-09 18:10:44 -0700202} // namespace aidl::android::hardware::audio::core::deprecated