• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 "StreamHalLocal"
18 //#define LOG_NDEBUG 0
19 
20 #include <hardware/audio.h>
21 #include <utils/Log.h>
22 
23 #include "DeviceHalLocal.h"
24 #include "StreamHalLocal.h"
25 
26 namespace android {
27 
StreamHalLocal(audio_stream_t * stream,sp<DeviceHalLocal> device)28 StreamHalLocal::StreamHalLocal(audio_stream_t *stream, sp<DeviceHalLocal> device)
29         : mDevice(device),
30           mStream(stream) {
31     // Instrument audio signal power logging.
32     // Note: This assumes channel mask, format, and sample rate do not change after creation.
33     if (mStream != nullptr && mStreamPowerLog.isUserDebugOrEngBuild()) {
34         mStreamPowerLog.init(mStream->get_sample_rate(mStream),
35                 mStream->get_channels(mStream),
36                 mStream->get_format(mStream));
37     }
38 }
39 
~StreamHalLocal()40 StreamHalLocal::~StreamHalLocal() {
41     mStream = 0;
42     mDevice.clear();
43 }
44 
getSampleRate(uint32_t * rate)45 status_t StreamHalLocal::getSampleRate(uint32_t *rate) {
46     *rate = mStream->get_sample_rate(mStream);
47     return OK;
48 }
49 
getBufferSize(size_t * size)50 status_t StreamHalLocal::getBufferSize(size_t *size) {
51     *size = mStream->get_buffer_size(mStream);
52     return OK;
53 }
54 
getChannelMask(audio_channel_mask_t * mask)55 status_t StreamHalLocal::getChannelMask(audio_channel_mask_t *mask) {
56     *mask = mStream->get_channels(mStream);
57     return OK;
58 }
59 
getFormat(audio_format_t * format)60 status_t StreamHalLocal::getFormat(audio_format_t *format) {
61     *format = mStream->get_format(mStream);
62     return OK;
63 }
64 
getAudioProperties(uint32_t * sampleRate,audio_channel_mask_t * mask,audio_format_t * format)65 status_t StreamHalLocal::getAudioProperties(
66         uint32_t *sampleRate, audio_channel_mask_t *mask, audio_format_t *format) {
67     *sampleRate = mStream->get_sample_rate(mStream);
68     *mask = mStream->get_channels(mStream);
69     *format = mStream->get_format(mStream);
70     return OK;
71 }
72 
setParameters(const String8 & kvPairs)73 status_t StreamHalLocal::setParameters(const String8& kvPairs) {
74     return mStream->set_parameters(mStream, kvPairs.string());
75 }
76 
getParameters(const String8 & keys,String8 * values)77 status_t StreamHalLocal::getParameters(const String8& keys, String8 *values) {
78     char *halValues = mStream->get_parameters(mStream, keys.string());
79     if (halValues != NULL) {
80         values->setTo(halValues);
81         free(halValues);
82     } else {
83         values->clear();
84     }
85     return OK;
86 }
87 
addEffect(sp<EffectHalInterface>)88 status_t StreamHalLocal::addEffect(sp<EffectHalInterface>) {
89     LOG_ALWAYS_FATAL("Local streams can not have effects");
90     return INVALID_OPERATION;
91 }
92 
removeEffect(sp<EffectHalInterface>)93 status_t StreamHalLocal::removeEffect(sp<EffectHalInterface>) {
94     LOG_ALWAYS_FATAL("Local streams can not have effects");
95     return INVALID_OPERATION;
96 }
97 
standby()98 status_t StreamHalLocal::standby() {
99     return mStream->standby(mStream);
100 }
101 
dump(int fd)102 status_t StreamHalLocal::dump(int fd) {
103     status_t status = mStream->dump(mStream, fd);
104     mStreamPowerLog.dump(fd);
105     return status;
106 }
107 
setHalThreadPriority(int)108 status_t StreamHalLocal::setHalThreadPriority(int) {
109     // Don't need to do anything as local hal is executed by audioflinger directly
110     // on the same thread.
111     return OK;
112 }
113 
StreamOutHalLocal(audio_stream_out_t * stream,sp<DeviceHalLocal> device)114 StreamOutHalLocal::StreamOutHalLocal(audio_stream_out_t *stream, sp<DeviceHalLocal> device)
115         : StreamHalLocal(&stream->common, device), mStream(stream) {
116 }
117 
~StreamOutHalLocal()118 StreamOutHalLocal::~StreamOutHalLocal() {
119     mCallback.clear();
120     mDevice->closeOutputStream(mStream);
121     mStream = 0;
122 }
123 
getFrameSize(size_t * size)124 status_t StreamOutHalLocal::getFrameSize(size_t *size) {
125     *size = audio_stream_out_frame_size(mStream);
126     return OK;
127 }
128 
getLatency(uint32_t * latency)129 status_t StreamOutHalLocal::getLatency(uint32_t *latency) {
130     *latency = mStream->get_latency(mStream);
131     return OK;
132 }
133 
setVolume(float left,float right)134 status_t StreamOutHalLocal::setVolume(float left, float right) {
135     if (mStream->set_volume == NULL) return INVALID_OPERATION;
136     return mStream->set_volume(mStream, left, right);
137 }
138 
write(const void * buffer,size_t bytes,size_t * written)139 status_t StreamOutHalLocal::write(const void *buffer, size_t bytes, size_t *written) {
140     ssize_t writeResult = mStream->write(mStream, buffer, bytes);
141     if (writeResult > 0) {
142         *written = writeResult;
143         mStreamPowerLog.log(buffer, *written);
144         return OK;
145     } else {
146         *written = 0;
147         return writeResult;
148     }
149 }
150 
getRenderPosition(uint32_t * dspFrames)151 status_t StreamOutHalLocal::getRenderPosition(uint32_t *dspFrames) {
152     return mStream->get_render_position(mStream, dspFrames);
153 }
154 
getNextWriteTimestamp(int64_t * timestamp)155 status_t StreamOutHalLocal::getNextWriteTimestamp(int64_t *timestamp) {
156     if (mStream->get_next_write_timestamp == NULL) return INVALID_OPERATION;
157     return mStream->get_next_write_timestamp(mStream, timestamp);
158 }
159 
setCallback(wp<StreamOutHalInterfaceCallback> callback)160 status_t StreamOutHalLocal::setCallback(wp<StreamOutHalInterfaceCallback> callback) {
161     if (mStream->set_callback == NULL) return INVALID_OPERATION;
162     status_t result = mStream->set_callback(mStream, StreamOutHalLocal::asyncCallback, this);
163     if (result == OK) {
164         mCallback = callback;
165     }
166     return result;
167 }
168 
169 // static
asyncCallback(stream_callback_event_t event,void *,void * cookie)170 int StreamOutHalLocal::asyncCallback(stream_callback_event_t event, void*, void *cookie) {
171     // We act as if we gave a wp<StreamOutHalLocal> to HAL. This way we should handle
172     // correctly the case when the callback is invoked while StreamOutHalLocal's destructor is
173     // already running, because the destructor is invoked after the refcount has been atomically
174     // decremented.
175     wp<StreamOutHalLocal> weakSelf(static_cast<StreamOutHalLocal*>(cookie));
176     sp<StreamOutHalLocal> self = weakSelf.promote();
177     if (self == 0) return 0;
178     sp<StreamOutHalInterfaceCallback> callback = self->mCallback.promote();
179     if (callback == 0) return 0;
180     ALOGV("asyncCallback() event %d", event);
181     switch (event) {
182         case STREAM_CBK_EVENT_WRITE_READY:
183             callback->onWriteReady();
184             break;
185         case STREAM_CBK_EVENT_DRAIN_READY:
186             callback->onDrainReady();
187             break;
188         case STREAM_CBK_EVENT_ERROR:
189             callback->onError();
190             break;
191         default:
192             ALOGW("asyncCallback() unknown event %d", event);
193             break;
194     }
195     return 0;
196 }
197 
supportsPauseAndResume(bool * supportsPause,bool * supportsResume)198 status_t StreamOutHalLocal::supportsPauseAndResume(bool *supportsPause, bool *supportsResume) {
199     *supportsPause = mStream->pause != NULL;
200     *supportsResume = mStream->resume != NULL;
201     return OK;
202 }
203 
pause()204 status_t StreamOutHalLocal::pause() {
205     if (mStream->pause == NULL) return INVALID_OPERATION;
206     return mStream->pause(mStream);
207 }
208 
resume()209 status_t StreamOutHalLocal::resume() {
210     if (mStream->resume == NULL) return INVALID_OPERATION;
211     return mStream->resume(mStream);
212 }
213 
supportsDrain(bool * supportsDrain)214 status_t StreamOutHalLocal::supportsDrain(bool *supportsDrain) {
215     *supportsDrain = mStream->drain != NULL;
216     return OK;
217 }
218 
drain(bool earlyNotify)219 status_t StreamOutHalLocal::drain(bool earlyNotify) {
220     if (mStream->drain == NULL) return INVALID_OPERATION;
221     return mStream->drain(mStream, earlyNotify ? AUDIO_DRAIN_EARLY_NOTIFY : AUDIO_DRAIN_ALL);
222 }
223 
flush()224 status_t StreamOutHalLocal::flush() {
225     if (mStream->flush == NULL) return INVALID_OPERATION;
226     return mStream->flush(mStream);
227 }
228 
getPresentationPosition(uint64_t * frames,struct timespec * timestamp)229 status_t StreamOutHalLocal::getPresentationPosition(uint64_t *frames, struct timespec *timestamp) {
230     if (mStream->get_presentation_position == NULL) return INVALID_OPERATION;
231     return mStream->get_presentation_position(mStream, frames, timestamp);
232 }
233 
updateSourceMetadata(const SourceMetadata & sourceMetadata)234 status_t StreamOutHalLocal::updateSourceMetadata(const SourceMetadata& sourceMetadata) {
235     if (mStream->update_source_metadata == nullptr) {
236         return INVALID_OPERATION;
237     }
238     const source_metadata_t metadata {
239         .track_count = sourceMetadata.tracks.size(),
240         // const cast is fine as it is in a const structure
241         .tracks = const_cast<playback_track_metadata*>(sourceMetadata.tracks.data()),
242     };
243     mStream->update_source_metadata(mStream, &metadata);
244     return OK;
245 }
246 
start()247 status_t StreamOutHalLocal::start() {
248     if (mStream->start == NULL) return INVALID_OPERATION;
249     return mStream->start(mStream);
250 }
251 
stop()252 status_t StreamOutHalLocal::stop() {
253     if (mStream->stop == NULL) return INVALID_OPERATION;
254     return mStream->stop(mStream);
255 }
256 
createMmapBuffer(int32_t minSizeFrames,struct audio_mmap_buffer_info * info)257 status_t StreamOutHalLocal::createMmapBuffer(int32_t minSizeFrames,
258                                   struct audio_mmap_buffer_info *info) {
259     if (mStream->create_mmap_buffer == NULL) return INVALID_OPERATION;
260     return mStream->create_mmap_buffer(mStream, minSizeFrames, info);
261 }
262 
getMmapPosition(struct audio_mmap_position * position)263 status_t StreamOutHalLocal::getMmapPosition(struct audio_mmap_position *position) {
264     if (mStream->get_mmap_position == NULL) return INVALID_OPERATION;
265     return mStream->get_mmap_position(mStream, position);
266 }
267 
StreamInHalLocal(audio_stream_in_t * stream,sp<DeviceHalLocal> device)268 StreamInHalLocal::StreamInHalLocal(audio_stream_in_t *stream, sp<DeviceHalLocal> device)
269         : StreamHalLocal(&stream->common, device), mStream(stream) {
270 }
271 
~StreamInHalLocal()272 StreamInHalLocal::~StreamInHalLocal() {
273     mDevice->closeInputStream(mStream);
274     mStream = 0;
275 }
276 
getFrameSize(size_t * size)277 status_t StreamInHalLocal::getFrameSize(size_t *size) {
278     *size = audio_stream_in_frame_size(mStream);
279     return OK;
280 }
281 
setGain(float gain)282 status_t StreamInHalLocal::setGain(float gain) {
283     return mStream->set_gain(mStream, gain);
284 }
285 
read(void * buffer,size_t bytes,size_t * read)286 status_t StreamInHalLocal::read(void *buffer, size_t bytes, size_t *read) {
287     ssize_t readResult = mStream->read(mStream, buffer, bytes);
288     if (readResult > 0) {
289         *read = readResult;
290         mStreamPowerLog.log( buffer, *read);
291         return OK;
292     } else {
293         *read = 0;
294         return readResult;
295     }
296 }
297 
getInputFramesLost(uint32_t * framesLost)298 status_t StreamInHalLocal::getInputFramesLost(uint32_t *framesLost) {
299     *framesLost = mStream->get_input_frames_lost(mStream);
300     return OK;
301 }
302 
getCapturePosition(int64_t * frames,int64_t * time)303 status_t StreamInHalLocal::getCapturePosition(int64_t *frames, int64_t *time) {
304     if (mStream->get_capture_position == NULL) return INVALID_OPERATION;
305     return mStream->get_capture_position(mStream, frames, time);
306 }
307 
updateSinkMetadata(const SinkMetadata & sinkMetadata)308 status_t StreamInHalLocal::updateSinkMetadata(const SinkMetadata& sinkMetadata) {
309     if (mStream->update_sink_metadata == nullptr) {
310         return INVALID_OPERATION;
311     }
312     const sink_metadata_t metadata {
313         .track_count = sinkMetadata.tracks.size(),
314         // const cast is fine as it is in a const structure
315         .tracks = const_cast<record_track_metadata*>(sinkMetadata.tracks.data()),
316     };
317     mStream->update_sink_metadata(mStream, &metadata);
318     return OK;
319 }
320 
start()321 status_t StreamInHalLocal::start() {
322     if (mStream->start == NULL) return INVALID_OPERATION;
323     return mStream->start(mStream);
324 }
325 
stop()326 status_t StreamInHalLocal::stop() {
327     if (mStream->stop == NULL) return INVALID_OPERATION;
328     return mStream->stop(mStream);
329 }
330 
createMmapBuffer(int32_t minSizeFrames,struct audio_mmap_buffer_info * info)331 status_t StreamInHalLocal::createMmapBuffer(int32_t minSizeFrames,
332                                   struct audio_mmap_buffer_info *info) {
333     if (mStream->create_mmap_buffer == NULL) return INVALID_OPERATION;
334     return mStream->create_mmap_buffer(mStream, minSizeFrames, info);
335 }
336 
getMmapPosition(struct audio_mmap_position * position)337 status_t StreamInHalLocal::getMmapPosition(struct audio_mmap_position *position) {
338     if (mStream->get_mmap_position == NULL) return INVALID_OPERATION;
339     return mStream->get_mmap_position(mStream, position);
340 }
341 
getActiveMicrophones(std::vector<media::MicrophoneInfo> * microphones __unused)342 status_t StreamInHalLocal::getActiveMicrophones(
343         std::vector<media::MicrophoneInfo> *microphones __unused) {
344     return INVALID_OPERATION;
345 }
346 
347 } // namespace android
348