blob: 21062565b232b2804b9a61d78c6f0c4585b12af7 [file] [log] [blame]
Mikhail Naganov10548292016-10-31 10:39:47 -07001/*
2 * Copyright (C) 2016 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#define LOG_TAG "StreamOutHAL"
18
19#include <hardware/audio.h>
20#include <utils/Log.h>
21
22#include "StreamOut.h"
23
24namespace android {
25namespace hardware {
26namespace audio {
27namespace V2_0 {
28namespace implementation {
29
30StreamOut::StreamOut(audio_hw_device_t* device, audio_stream_out_t* stream)
31 : mDevice(device), mStream(stream), mStreamCommon(new Stream(&stream->common)) {
32}
33
34StreamOut::~StreamOut() {
35 mCallback.clear();
36 mDevice->close_output_stream(mDevice, mStream);
37 mStream = nullptr;
38 mDevice = nullptr;
39}
40
41// Methods from ::android::hardware::audio::V2_0::IStream follow.
42Return<uint64_t> StreamOut::getFrameSize() {
43 return audio_stream_out_frame_size(mStream);
44}
45
46Return<uint64_t> StreamOut::getFrameCount() {
47 return mStreamCommon->getFrameCount();
48}
49
50Return<uint64_t> StreamOut::getBufferSize() {
51 return mStreamCommon->getBufferSize();
52}
53
54Return<uint32_t> StreamOut::getSampleRate() {
55 return mStreamCommon->getSampleRate();
56}
57
58Return<void> StreamOut::getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb) {
59 return mStreamCommon->getSupportedSampleRates(_hidl_cb);
60}
61
62Return<Result> StreamOut::setSampleRate(uint32_t sampleRateHz) {
63 return mStreamCommon->setSampleRate(sampleRateHz);
64}
65
66Return<AudioChannelMask> StreamOut::getChannelMask() {
67 return mStreamCommon->getChannelMask();
68}
69
70Return<void> StreamOut::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) {
71 return mStreamCommon->getSupportedChannelMasks(_hidl_cb);
72}
73
74Return<Result> StreamOut::setChannelMask(AudioChannelMask mask) {
75 return mStreamCommon->setChannelMask(mask);
76}
77
78Return<AudioFormat> StreamOut::getFormat() {
79 return mStreamCommon->getFormat();
80}
81
82Return<void> StreamOut::getSupportedFormats(getSupportedFormats_cb _hidl_cb) {
83 return mStreamCommon->getSupportedFormats(_hidl_cb);
84}
85
86Return<Result> StreamOut::setFormat(AudioFormat format) {
87 return mStreamCommon->setFormat(format);
88}
89
90Return<void> StreamOut::getAudioProperties(getAudioProperties_cb _hidl_cb) {
91 return mStreamCommon->getAudioProperties(_hidl_cb);
92}
93
94Return<Result> StreamOut::addEffect(uint64_t effectId) {
95 return mStreamCommon->addEffect(effectId);
96}
97
98Return<Result> StreamOut::removeEffect(uint64_t effectId) {
99 return mStreamCommon->removeEffect(effectId);
100}
101
102Return<Result> StreamOut::standby() {
103 return mStreamCommon->standby();
104}
105
106Return<AudioDevice> StreamOut::getDevice() {
107 return mStreamCommon->getDevice();
108}
109
110Return<Result> StreamOut::setDevice(const DeviceAddress& address) {
111 return mStreamCommon->setDevice(address);
112}
113
114Return<Result> StreamOut::setConnectedState(const DeviceAddress& address, bool connected) {
115 return mStreamCommon->setConnectedState(address, connected);
116}
117
118Return<Result> StreamOut::setHwAvSync(uint32_t hwAvSync) {
119 return mStreamCommon->setHwAvSync(hwAvSync);
120}
121
122Return<void> StreamOut::getParameters(
123 const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) {
124 return mStreamCommon->getParameters(keys, _hidl_cb);
125}
126
127Return<Result> StreamOut::setParameters(const hidl_vec<ParameterValue>& parameters) {
128 return mStreamCommon->setParameters(parameters);
129}
130
Martijn Coenen70b9a152016-11-18 15:29:32 +0100131Return<void> StreamOut::debugDump(const hidl_handle& fd) {
Mikhail Naganov10548292016-10-31 10:39:47 -0700132 return mStreamCommon->debugDump(fd);
133}
134
135
136// Methods from ::android::hardware::audio::V2_0::IStreamOut follow.
137Return<uint32_t> StreamOut::getLatency() {
138 return mStream->get_latency(mStream);
139}
140
141Return<Result> StreamOut::setVolume(float left, float right) {
142 Result retval(Result::NOT_SUPPORTED);
143 if (mStream->set_volume != NULL) {
144 retval = mStreamCommon->analyzeStatus(
145 "set_volume", mStream->set_volume(mStream, left, right));
146 }
147 return retval;
148}
149
150Return<void> StreamOut::write(const hidl_vec<uint8_t>& data, write_cb _hidl_cb) {
151 // TODO(mnaganov): Replace with FMQ version.
152 Result retval(Result::OK);
153 uint64_t written = 0;
154 ssize_t writeResult = mStream->write(mStream, &data[0], data.size());
155 if (writeResult >= 0) {
156 written = writeResult;
157 } else {
158 retval = mStreamCommon->analyzeStatus("write", writeResult);
159 written = 0;
160 }
161 _hidl_cb(retval, written);
162 return Void();
163}
164
165Return<void> StreamOut::getRenderPosition(getRenderPosition_cb _hidl_cb) {
166 uint32_t halDspFrames;
167 Result retval = mStreamCommon->analyzeStatus(
168 "get_render_position", mStream->get_render_position(mStream, &halDspFrames));
169 _hidl_cb(retval, halDspFrames);
170 return Void();
171}
172
173Return<void> StreamOut::getNextWriteTimestamp(getNextWriteTimestamp_cb _hidl_cb) {
174 Result retval(Result::NOT_SUPPORTED);
175 int64_t timestampUs = 0;
176 if (mStream->get_next_write_timestamp != NULL) {
177 retval = mStreamCommon->analyzeStatus(
178 "get_next_write_timestamp",
179 mStream->get_next_write_timestamp(mStream, &timestampUs));
180 }
181 _hidl_cb(retval, timestampUs);
182 return Void();
183}
184
185Return<Result> StreamOut::setCallback(const sp<IStreamOutCallback>& callback) {
186 if (mStream->set_callback == NULL) return Result::NOT_SUPPORTED;
187 int result = mStream->set_callback(mStream, StreamOut::asyncCallback, this);
188 if (result == 0) {
189 mCallback = callback;
190 }
191 return mStreamCommon->analyzeStatus("set_callback", result);
192}
193
194// static
195int StreamOut::asyncCallback(stream_callback_event_t event, void*, void *cookie) {
196 wp<StreamOut> weakSelf(reinterpret_cast<StreamOut*>(cookie));
197 sp<StreamOut> self = weakSelf.promote();
198 if (self == 0) return 0;
199 sp<IStreamOutCallback> callback = self->mCallback.promote();
200 if (callback == 0) return 0;
201 ALOGV("asyncCallback() event %d", event);
202 switch (event) {
203 case STREAM_CBK_EVENT_WRITE_READY:
204 callback->onWriteReady();
205 break;
206 case STREAM_CBK_EVENT_DRAIN_READY:
207 callback->onDrainReady();
208 break;
209 case STREAM_CBK_EVENT_ERROR:
210 callback->onError();
211 break;
212 default:
213 ALOGW("asyncCallback() unknown event %d", event);
214 break;
215 }
216 return 0;
217}
218
219Return<void> StreamOut::supportsPauseAndResume(supportsPauseAndResume_cb _hidl_cb) {
220 _hidl_cb(mStream->pause != NULL, mStream->resume != NULL);
221 return Void();
222}
223
224Return<Result> StreamOut::pause() {
225 return mStream->pause != NULL ?
226 mStreamCommon->analyzeStatus("pause", mStream->pause(mStream)) :
227 Result::NOT_SUPPORTED;
228}
229
230Return<Result> StreamOut::resume() {
231 return mStream->resume != NULL ?
232 mStreamCommon->analyzeStatus("resume", mStream->resume(mStream)) :
233 Result::NOT_SUPPORTED;
234}
235
236Return<bool> StreamOut::supportsDrain() {
237 return mStream->drain != NULL;
238}
239
240Return<Result> StreamOut::drain(AudioDrain type) {
241 return mStream->drain != NULL ?
242 mStreamCommon->analyzeStatus(
243 "drain", mStream->drain(mStream, static_cast<audio_drain_type_t>(type))) :
244 Result::NOT_SUPPORTED;
245}
246
247Return<Result> StreamOut::flush() {
248 return mStream->flush != NULL ?
249 mStreamCommon->analyzeStatus("flush", mStream->flush(mStream)) :
250 Result::NOT_SUPPORTED;
251}
252
253Return<void> StreamOut::getPresentationPosition(getPresentationPosition_cb _hidl_cb) {
254 Result retval(Result::NOT_SUPPORTED);
255 uint64_t frames = 0;
256 TimeSpec timeStamp = { 0, 0 };
257 if (mStream->get_presentation_position != NULL) {
258 struct timespec halTimeStamp;
259 retval = mStreamCommon->analyzeStatus(
260 "get_presentation_position",
261 mStream->get_presentation_position(mStream, &frames, &halTimeStamp));
262 if (retval == Result::OK) {
263 timeStamp.tvSec = halTimeStamp.tv_sec;
264 timeStamp.tvNSec = halTimeStamp.tv_nsec;
265 }
266 }
267 _hidl_cb(retval, frames, timeStamp);
268 return Void();
269}
270
271} // namespace implementation
272} // namespace V2_0
273} // namespace audio
274} // namespace hardware
275} // namespace android