• R/O
  • HTTP
  • SSH
  • HTTPS

提交

標籤
無標籤

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

hardware/libaudio


Commit MetaInfo

修訂cfde6b1213e204bb8eca55ce16b1a26d4d0eef0b (tree)
時間2013-01-16 10:51:18
作者Chih-Wei Huang <cwhuang@linu...>
CommiterChih-Wei Huang

Log Message

audio hal for jb-x86

Import from device/asus/grouper/audio of AOSP.

Change Summary

差異

--- a/Android.mk
+++ b/Android.mk
@@ -1,4 +1,4 @@
1-# Copyright (C) 2011 The Android-x86 Open Source Project
1+# Copyright (C) 2011-2013 The Android-x86 Open Source Project
22 #
33 # Licensed under the Apache License, Version 2.0 (the "License");
44 # you may not use this file except in compliance with the License.
@@ -11,3 +11,28 @@
1111 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212 # See the License for the specific language governing permissions and
1313 # limitations under the License.
14+
15+LOCAL_PATH := $(call my-dir)
16+
17+include $(CLEAR_VARS)
18+
19+LOCAL_MODULE := audio.primary.x86
20+LOCAL_MODULE_TAGS := optional
21+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
22+LOCAL_SHARED_LIBRARIES := \
23+ liblog \
24+ libcutils \
25+ libtinyalsa \
26+ libaudioutils \
27+ libexpat \
28+
29+LOCAL_SRC_FILES := \
30+ audio_hw.c \
31+ audio_route.c
32+
33+LOCAL_C_INCLUDES := \
34+ external/expat/lib \
35+ external/tinyalsa/include \
36+ $(call include-path-for, audio-utils)
37+
38+include $(BUILD_SHARED_LIBRARY)
--- /dev/null
+++ b/alsa.mk
@@ -0,0 +1,54 @@
1+#
2+# Copyright (C) 2012 The Android-x86 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+
11+TARGET_ALSA_CONF_DIR := system/usr/share/alsa
12+LOCAL_ALSA_CONF_DIR := external/alsa-lib/src/conf
13+
14+copy_conf := \
15+ alsa.conf \
16+ pcm/dsnoop.conf \
17+ pcm/modem.conf \
18+ pcm/dpl.conf \
19+ pcm/default.conf \
20+ pcm/surround51.conf \
21+ pcm/surround41.conf \
22+ pcm/surround50.conf \
23+ pcm/dmix.conf \
24+ pcm/center_lfe.conf \
25+ pcm/surround40.conf \
26+ pcm/side.conf \
27+ pcm/iec958.conf \
28+ pcm/rear.conf \
29+ pcm/surround71.conf \
30+ pcm/front.conf \
31+ cards/aliases.conf
32+
33+LOCAL_ALSA_INIT_DIR := external/alsa-utils/alsactl/init
34+
35+copy_init := \
36+ 00main \
37+ default \
38+ hda \
39+ help \
40+ info \
41+ test
42+
43+PRODUCT_COPY_FILES := \
44+ $(foreach f,$(copy_conf),$(LOCAL_ALSA_CONF_DIR)/$(f):$(TARGET_ALSA_CONF_DIR)/$(f)) \
45+ $(foreach f,$(copy_init),$(LOCAL_ALSA_INIT_DIR)/$(f):$(TARGET_ALSA_CONF_DIR)/init/$(f)) \
46+ $(if $(wildcard $(PRODUCT_DIR)audio_policy.conf),$(PRODUCT_DIR),$(LOCAL_PATH)/)audio_policy.conf:system/etc/audio_policy.conf \
47+
48+PRODUCT_PACKAGES := \
49+ alsa_amixer \
50+ alsa_aplay \
51+ alsa_ctl \
52+ audio.primary.x86 \
53+ audio.a2dp.default \
54+ audio_policy.default \
--- /dev/null
+++ b/asound.conf
@@ -0,0 +1,177 @@
1+# Android ALSA configuration file
2+
3+#
4+# Mixer Devices
5+#
6+ctl.AndroidPlayback {
7+ type hw
8+ card 0
9+ device 0
10+}
11+
12+ctl.AndroidPlayback_Widi-Loopback {
13+ type hw
14+ card Loopback
15+ device 0
16+}
17+
18+ctl.AndroidRecord {
19+ type hw
20+ card 0
21+ device 0
22+}
23+
24+ctl.AndroidPlayback_HDMIAudio {
25+ type hw
26+ card 0
27+ device 0
28+}
29+
30+#
31+# Playback Devices
32+#
33+pcm.AndroidPlayback {
34+ type plug
35+ slave.pcm "both"
36+}
37+
38+pcm.AndroidPlayback_Speaker_normal {
39+ type plug
40+ slave.pcm "speaker"
41+}
42+
43+pcm.AndroidPlayback_Headset_normal {
44+ type plug
45+ slave.pcm "headphone"
46+}
47+
48+pcm.both {
49+ type hooks
50+ slave.pcm {
51+ type hw
52+ card 0
53+ device 0
54+ }
55+ hooks.0 {
56+ type ctl_elems
57+ hook_args [
58+ {name "Speaker Mux Playback Route" value [1 1]}
59+ {name "Mode Playback Route" value 0}
60+ {name "Playback Switch" value 1}
61+ ]
62+ }
63+}
64+
65+pcm.speaker {
66+ type hooks
67+ slave.pcm {
68+ type hw
69+ card 0
70+ device 0
71+ }
72+ hooks.0 {
73+ type ctl_elems
74+ hook_args [
75+ {name "Speaker Mux Playback Route" value [1 1]}
76+ {name "Mode Playback Route" value 0}
77+ {name "Playback Switch" value 0}
78+ ]
79+ }
80+}
81+
82+pcm.headphone {
83+ type hooks
84+ slave.pcm {
85+ type hw
86+ card 0
87+ device 0
88+ }
89+ hooks.0 {
90+ type ctl_elems
91+ hook_args [
92+ {name "Speaker Mux Playback Route" value [0 0]}
93+ {name "Mode Playback Route" value 0}
94+ {name "Playback Switch" value 1}
95+ ]
96+ }
97+}
98+
99+#
100+# HDMI routing
101+#
102+pcm.HDMIAudio {
103+ type hw
104+ card 0
105+ device 0
106+}
107+
108+pcm.AndroidPlayback_HDMIAudio {
109+ type linear
110+ slave {
111+ pcm HDMIAudio
112+ format S24_LE
113+ }
114+}
115+
116+pcm.AndroidPlayback_HDMIAudio_normal {
117+ type linear
118+ slave {
119+ pcm HDMIAudio
120+ format S24_LE
121+ }
122+}
123+
124+#
125+# WIDI routing
126+#
127+pcm.AndroidPlayback_Widi-Loopback{
128+ type plug
129+ slave.pcm "loopback_sink"
130+}
131+
132+pcm.AndroidPlayback_Widi-Loopback_normal{
133+ type plug
134+ slave.pcm "loopback_sink"
135+}
136+
137+pcm.loopback_sink {
138+ type hw
139+ card Loopback
140+ device 0
141+ subdevice 0
142+}
143+
144+#
145+# Capture device
146+#
147+pcm.AndroidCapture {
148+ type hooks
149+ slave.pcm {
150+ type hw
151+ card 0
152+ device 0
153+ }
154+ hooks.0 {
155+ type ctl_elems
156+ hook_args [
157+ {name "DMIC12 Capture Route" value 1}
158+ {name "DMIC34 Capture Route" value 1}
159+ {name "Txpath1 Capture Route" value 0}
160+ {name "Txpath2 Capture Route" value 2}
161+ {name "Txpath3 Capture Route" value 6}
162+ {name "Txpath4 Capture Route" value 6}
163+ ]
164+ }
165+}
166+
167+
168+
169+#
170+# WIDI
171+#
172+pcm.loopback_src {
173+ type hw
174+ card Loopback
175+ device 1
176+ subdevice 0
177+}
--- /dev/null
+++ b/audio_hw.c
@@ -0,0 +1,1274 @@
1+/*
2+ * Copyright (C) 2012 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 "audio_hw_primary"
18+/*#define LOG_NDEBUG 0*/
19+
20+#include <errno.h>
21+#include <pthread.h>
22+#include <stdint.h>
23+#include <stdlib.h>
24+#include <sys/time.h>
25+
26+#include <cutils/log.h>
27+#include <cutils/properties.h>
28+#include <cutils/str_parms.h>
29+
30+#include <hardware/audio.h>
31+#include <hardware/hardware.h>
32+
33+#include <system/audio.h>
34+
35+#include <tinyalsa/asoundlib.h>
36+
37+#include <audio_utils/resampler.h>
38+
39+#include "audio_route.h"
40+
41+#define PCM_CARD 0
42+#define PCM_DEVICE 0
43+#define PCM_DEVICE_SCO 2
44+
45+#define OUT_PERIOD_SIZE 512
46+#define OUT_SHORT_PERIOD_COUNT 2
47+#define OUT_LONG_PERIOD_COUNT 8
48+#define OUT_SAMPLING_RATE 44100
49+
50+#define IN_PERIOD_SIZE 1024
51+#define IN_PERIOD_COUNT 4
52+#define IN_SAMPLING_RATE 44100
53+
54+#define SCO_PERIOD_SIZE 256
55+#define SCO_PERIOD_COUNT 4
56+#define SCO_SAMPLING_RATE 8000
57+
58+/* minimum sleep time in out_write() when write threshold is not reached */
59+#define MIN_WRITE_SLEEP_US 2000
60+#define MAX_WRITE_SLEEP_US ((OUT_PERIOD_SIZE * OUT_SHORT_PERIOD_COUNT * 1000000) \
61+ / OUT_SAMPLING_RATE)
62+
63+enum {
64+ OUT_BUFFER_TYPE_UNKNOWN,
65+ OUT_BUFFER_TYPE_SHORT,
66+ OUT_BUFFER_TYPE_LONG,
67+};
68+
69+struct pcm_config pcm_config_out = {
70+ .channels = 2,
71+ .rate = OUT_SAMPLING_RATE,
72+ .period_size = OUT_PERIOD_SIZE,
73+ .period_count = OUT_LONG_PERIOD_COUNT,
74+ .format = PCM_FORMAT_S16_LE,
75+ .start_threshold = OUT_PERIOD_SIZE * OUT_SHORT_PERIOD_COUNT,
76+};
77+
78+struct pcm_config pcm_config_in = {
79+ .channels = 2,
80+ .rate = IN_SAMPLING_RATE,
81+ .period_size = IN_PERIOD_SIZE,
82+ .period_count = IN_PERIOD_COUNT,
83+ .format = PCM_FORMAT_S16_LE,
84+ .start_threshold = 1,
85+ .stop_threshold = (IN_PERIOD_SIZE * IN_PERIOD_COUNT),
86+};
87+
88+struct pcm_config pcm_config_sco = {
89+ .channels = 1,
90+ .rate = SCO_SAMPLING_RATE,
91+ .period_size = SCO_PERIOD_SIZE,
92+ .period_count = SCO_PERIOD_COUNT,
93+ .format = PCM_FORMAT_S16_LE,
94+};
95+
96+struct audio_device {
97+ struct audio_hw_device hw_device;
98+
99+ pthread_mutex_t lock; /* see note below on mutex acquisition order */
100+ unsigned int out_device;
101+ unsigned int in_device;
102+ bool standby;
103+ bool mic_mute;
104+ struct audio_route *ar;
105+ int orientation;
106+ bool screen_off;
107+
108+ struct stream_out *active_out;
109+ struct stream_in *active_in;
110+};
111+
112+struct stream_out {
113+ struct audio_stream_out stream;
114+
115+ pthread_mutex_t lock; /* see note below on mutex acquisition order */
116+ struct pcm *pcm;
117+ struct pcm_config *pcm_config;
118+ bool standby;
119+
120+ struct resampler_itfe *resampler;
121+ int16_t *buffer;
122+ size_t buffer_frames;
123+
124+ int write_threshold;
125+ int cur_write_threshold;
126+ int buffer_type;
127+
128+ struct audio_device *dev;
129+};
130+
131+struct stream_in {
132+ struct audio_stream_in stream;
133+
134+ pthread_mutex_t lock; /* see note below on mutex acquisition order */
135+ struct pcm *pcm;
136+ struct pcm_config *pcm_config;
137+ bool standby;
138+
139+ unsigned int requested_rate;
140+ struct resampler_itfe *resampler;
141+ struct resampler_buffer_provider buf_provider;
142+ int16_t *buffer;
143+ size_t buffer_size;
144+ size_t frames_in;
145+ int read_status;
146+
147+ struct audio_device *dev;
148+};
149+
150+enum {
151+ ORIENTATION_LANDSCAPE,
152+ ORIENTATION_PORTRAIT,
153+ ORIENTATION_SQUARE,
154+ ORIENTATION_UNDEFINED,
155+};
156+
157+static uint32_t out_get_sample_rate(const struct audio_stream *stream);
158+static size_t out_get_buffer_size(const struct audio_stream *stream);
159+static audio_format_t out_get_format(const struct audio_stream *stream);
160+static uint32_t in_get_sample_rate(const struct audio_stream *stream);
161+static size_t in_get_buffer_size(const struct audio_stream *stream);
162+static audio_format_t in_get_format(const struct audio_stream *stream);
163+static int get_next_buffer(struct resampler_buffer_provider *buffer_provider,
164+ struct resampler_buffer* buffer);
165+static void release_buffer(struct resampler_buffer_provider *buffer_provider,
166+ struct resampler_buffer* buffer);
167+
168+/*
169+ * NOTE: when multiple mutexes have to be acquired, always take the
170+ * audio_device mutex first, followed by the stream_in and/or
171+ * stream_out mutexes.
172+ */
173+
174+/* Helper functions */
175+
176+static void select_devices(struct audio_device *adev)
177+{
178+ int headphone_on;
179+ int speaker_on;
180+ int docked;
181+ int main_mic_on;
182+
183+ headphone_on = adev->out_device & (AUDIO_DEVICE_OUT_WIRED_HEADSET |
184+ AUDIO_DEVICE_OUT_WIRED_HEADPHONE);
185+ speaker_on = adev->out_device & AUDIO_DEVICE_OUT_SPEAKER;
186+ docked = adev->out_device & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
187+ main_mic_on = adev->in_device & AUDIO_DEVICE_IN_BUILTIN_MIC;
188+
189+ reset_mixer_state(adev->ar);
190+
191+ if (speaker_on)
192+ audio_route_apply_path(adev->ar, "speaker");
193+ if (headphone_on)
194+ audio_route_apply_path(adev->ar, "headphone");
195+ if (docked)
196+ audio_route_apply_path(adev->ar, "dock");
197+ if (main_mic_on) {
198+ if (adev->orientation == ORIENTATION_LANDSCAPE)
199+ audio_route_apply_path(adev->ar, "main-mic-left");
200+ else
201+ audio_route_apply_path(adev->ar, "main-mic-top");
202+ }
203+
204+ update_mixer_state(adev->ar);
205+
206+ ALOGV("hp=%c speaker=%c dock=%c main-mic=%c", headphone_on ? 'y' : 'n',
207+ speaker_on ? 'y' : 'n', docked ? 'y' : 'n', main_mic_on ? 'y' : 'n');
208+}
209+
210+/* must be called with hw device and output stream mutexes locked */
211+static void do_out_standby(struct stream_out *out)
212+{
213+ struct audio_device *adev = out->dev;
214+
215+ if (!out->standby) {
216+ pcm_close(out->pcm);
217+ out->pcm = NULL;
218+ adev->active_out = NULL;
219+ if (out->resampler) {
220+ release_resampler(out->resampler);
221+ out->resampler = NULL;
222+ }
223+ if (out->buffer) {
224+ free(out->buffer);
225+ out->buffer = NULL;
226+ }
227+ out->standby = true;
228+ }
229+}
230+
231+/* must be called with hw device and input stream mutexes locked */
232+static void do_in_standby(struct stream_in *in)
233+{
234+ struct audio_device *adev = in->dev;
235+
236+ if (!in->standby) {
237+ pcm_close(in->pcm);
238+ in->pcm = NULL;
239+ adev->active_in = NULL;
240+ if (in->resampler) {
241+ release_resampler(in->resampler);
242+ in->resampler = NULL;
243+ }
244+ if (in->buffer) {
245+ free(in->buffer);
246+ in->buffer = NULL;
247+ }
248+ in->standby = true;
249+ }
250+}
251+
252+/* must be called with hw device and output stream mutexes locked */
253+static int start_output_stream(struct stream_out *out)
254+{
255+ struct audio_device *adev = out->dev;
256+ unsigned int device;
257+ int ret;
258+
259+ /*
260+ * Due to the lack of sample rate converters in the SoC,
261+ * it greatly simplifies things to have only the main
262+ * (speaker/headphone) PCM or the BC SCO PCM open at
263+ * the same time.
264+ */
265+ if (adev->out_device & AUDIO_DEVICE_OUT_ALL_SCO) {
266+ device = PCM_DEVICE_SCO;
267+ out->pcm_config = &pcm_config_sco;
268+ } else {
269+ device = PCM_DEVICE;
270+ out->pcm_config = &pcm_config_out;
271+ out->buffer_type = OUT_BUFFER_TYPE_UNKNOWN;
272+ }
273+
274+ /*
275+ * All open PCMs can only use a single group of rates at once:
276+ * Group 1: 11.025, 22.05, 44.1
277+ * Group 2: 8, 16, 32, 48
278+ * Group 1 is used for digital audio playback since 44.1 is
279+ * the most common rate, but group 2 is required for SCO.
280+ */
281+ if (adev->active_in) {
282+ struct stream_in *in = adev->active_in;
283+ pthread_mutex_lock(&in->lock);
284+ if (((out->pcm_config->rate % 8000 == 0) &&
285+ (in->pcm_config->rate % 8000) != 0) ||
286+ ((out->pcm_config->rate % 11025 == 0) &&
287+ (in->pcm_config->rate % 11025) != 0))
288+ do_in_standby(in);
289+ pthread_mutex_unlock(&in->lock);
290+ }
291+
292+ out->pcm = pcm_open(PCM_CARD, device, PCM_OUT | PCM_NORESTART, out->pcm_config);
293+
294+ if (out->pcm && !pcm_is_ready(out->pcm)) {
295+ ALOGE("pcm_open(out) failed: %s", pcm_get_error(out->pcm));
296+ pcm_close(out->pcm);
297+ return -ENOMEM;
298+ }
299+
300+ /*
301+ * If the stream rate differs from the PCM rate, we need to
302+ * create a resampler.
303+ */
304+ if (out_get_sample_rate(&out->stream.common) != out->pcm_config->rate) {
305+ ret = create_resampler(out_get_sample_rate(&out->stream.common),
306+ out->pcm_config->rate,
307+ out->pcm_config->channels,
308+ RESAMPLER_QUALITY_DEFAULT,
309+ NULL,
310+ &out->resampler);
311+ out->buffer_frames = (pcm_config_out.period_size * out->pcm_config->rate) /
312+ out_get_sample_rate(&out->stream.common) + 1;
313+
314+ out->buffer = malloc(pcm_frames_to_bytes(out->pcm, out->buffer_frames));
315+ }
316+
317+ adev->active_out = out;
318+
319+ return 0;
320+}
321+
322+/* must be called with hw device and input stream mutexes locked */
323+static int start_input_stream(struct stream_in *in)
324+{
325+ struct audio_device *adev = in->dev;
326+ unsigned int device;
327+ int ret;
328+
329+ /*
330+ * Due to the lack of sample rate converters in the SoC,
331+ * it greatly simplifies things to have only the main
332+ * mic PCM or the BC SCO PCM open at the same time.
333+ */
334+ if (adev->in_device & AUDIO_DEVICE_IN_ALL_SCO) {
335+ device = PCM_DEVICE_SCO;
336+ in->pcm_config = &pcm_config_sco;
337+ } else {
338+ device = PCM_DEVICE;
339+ in->pcm_config = &pcm_config_in;
340+ }
341+
342+ /*
343+ * All open PCMs can only use a single group of rates at once:
344+ * Group 1: 11.025, 22.05, 44.1
345+ * Group 2: 8, 16, 32, 48
346+ * Group 1 is used for digital audio playback since 44.1 is
347+ * the most common rate, but group 2 is required for SCO.
348+ */
349+ if (adev->active_out) {
350+ struct stream_out *out = adev->active_out;
351+ pthread_mutex_lock(&out->lock);
352+ if (((in->pcm_config->rate % 8000 == 0) &&
353+ (out->pcm_config->rate % 8000) != 0) ||
354+ ((in->pcm_config->rate % 11025 == 0) &&
355+ (out->pcm_config->rate % 11025) != 0))
356+ do_out_standby(out);
357+ pthread_mutex_unlock(&out->lock);
358+ }
359+
360+ in->pcm = pcm_open(PCM_CARD, device, PCM_IN, in->pcm_config);
361+
362+ if (in->pcm && !pcm_is_ready(in->pcm)) {
363+ ALOGE("pcm_open(in) failed: %s", pcm_get_error(in->pcm));
364+ pcm_close(in->pcm);
365+ return -ENOMEM;
366+ }
367+
368+ /*
369+ * If the stream rate differs from the PCM rate, we need to
370+ * create a resampler.
371+ */
372+ if (in_get_sample_rate(&in->stream.common) != in->pcm_config->rate) {
373+ in->buf_provider.get_next_buffer = get_next_buffer;
374+ in->buf_provider.release_buffer = release_buffer;
375+
376+ ret = create_resampler(in->pcm_config->rate,
377+ in_get_sample_rate(&in->stream.common),
378+ 1,
379+ RESAMPLER_QUALITY_DEFAULT,
380+ &in->buf_provider,
381+ &in->resampler);
382+ }
383+ in->buffer_size = pcm_frames_to_bytes(in->pcm,
384+ in->pcm_config->period_size);
385+ in->buffer = malloc(in->buffer_size);
386+ in->frames_in = 0;
387+
388+ adev->active_in = in;
389+
390+ return 0;
391+}
392+
393+static int get_next_buffer(struct resampler_buffer_provider *buffer_provider,
394+ struct resampler_buffer* buffer)
395+{
396+ struct stream_in *in;
397+
398+ if (buffer_provider == NULL || buffer == NULL)
399+ return -EINVAL;
400+
401+ in = (struct stream_in *)((char *)buffer_provider -
402+ offsetof(struct stream_in, buf_provider));
403+
404+ if (in->pcm == NULL) {
405+ buffer->raw = NULL;
406+ buffer->frame_count = 0;
407+ in->read_status = -ENODEV;
408+ return -ENODEV;
409+ }
410+
411+ if (in->frames_in == 0) {
412+ in->read_status = pcm_read(in->pcm,
413+ (void*)in->buffer,
414+ in->buffer_size);
415+ if (in->read_status != 0) {
416+ ALOGE("get_next_buffer() pcm_read error %d", in->read_status);
417+ buffer->raw = NULL;
418+ buffer->frame_count = 0;
419+ return in->read_status;
420+ }
421+ in->frames_in = in->pcm_config->period_size;
422+ if (in->pcm_config->channels == 2) {
423+ unsigned int i;
424+
425+ /* Discard right channel */
426+ for (i = 1; i < in->frames_in; i++)
427+ in->buffer[i] = in->buffer[i * 2];
428+ }
429+ }
430+
431+ buffer->frame_count = (buffer->frame_count > in->frames_in) ?
432+ in->frames_in : buffer->frame_count;
433+ buffer->i16 = in->buffer + (in->pcm_config->period_size - in->frames_in);
434+
435+ return in->read_status;
436+
437+}
438+
439+static void release_buffer(struct resampler_buffer_provider *buffer_provider,
440+ struct resampler_buffer* buffer)
441+{
442+ struct stream_in *in;
443+
444+ if (buffer_provider == NULL || buffer == NULL)
445+ return;
446+
447+ in = (struct stream_in *)((char *)buffer_provider -
448+ offsetof(struct stream_in, buf_provider));
449+
450+ in->frames_in -= buffer->frame_count;
451+}
452+
453+/* read_frames() reads frames from kernel driver, down samples to capture rate
454+ * if necessary and output the number of frames requested to the buffer specified */
455+static ssize_t read_frames(struct stream_in *in, void *buffer, ssize_t frames)
456+{
457+ ssize_t frames_wr = 0;
458+
459+ while (frames_wr < frames) {
460+ size_t frames_rd = frames - frames_wr;
461+ if (in->resampler != NULL) {
462+ in->resampler->resample_from_provider(in->resampler,
463+ (int16_t *)((char *)buffer +
464+ frames_wr * audio_stream_frame_size(&in->stream.common)),
465+ &frames_rd);
466+ } else {
467+ struct resampler_buffer buf = {
468+ { raw : NULL, },
469+ frame_count : frames_rd,
470+ };
471+ get_next_buffer(&in->buf_provider, &buf);
472+ if (buf.raw != NULL) {
473+ memcpy((char *)buffer +
474+ frames_wr * audio_stream_frame_size(&in->stream.common),
475+ buf.raw,
476+ buf.frame_count * audio_stream_frame_size(&in->stream.common));
477+ frames_rd = buf.frame_count;
478+ }
479+ release_buffer(&in->buf_provider, &buf);
480+ }
481+ /* in->read_status is updated by getNextBuffer() also called by
482+ * in->resampler->resample_from_provider() */
483+ if (in->read_status != 0)
484+ return in->read_status;
485+
486+ frames_wr += frames_rd;
487+ }
488+ return frames_wr;
489+}
490+
491+/* API functions */
492+
493+static uint32_t out_get_sample_rate(const struct audio_stream *stream)
494+{
495+ return pcm_config_out.rate;
496+}
497+
498+static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
499+{
500+ return -ENOSYS;
501+}
502+
503+static size_t out_get_buffer_size(const struct audio_stream *stream)
504+{
505+ return pcm_config_out.period_size *
506+ audio_stream_frame_size((struct audio_stream *)stream);
507+}
508+
509+static uint32_t out_get_channels(const struct audio_stream *stream)
510+{
511+ return AUDIO_CHANNEL_OUT_STEREO;
512+}
513+
514+static audio_format_t out_get_format(const struct audio_stream *stream)
515+{
516+ return AUDIO_FORMAT_PCM_16_BIT;
517+}
518+
519+static int out_set_format(struct audio_stream *stream, audio_format_t format)
520+{
521+ return -ENOSYS;
522+}
523+
524+static int out_standby(struct audio_stream *stream)
525+{
526+ struct stream_out *out = (struct stream_out *)stream;
527+
528+ pthread_mutex_lock(&out->dev->lock);
529+ pthread_mutex_lock(&out->lock);
530+ do_out_standby(out);
531+ pthread_mutex_unlock(&out->lock);
532+ pthread_mutex_unlock(&out->dev->lock);
533+
534+ return 0;
535+}
536+
537+static int out_dump(const struct audio_stream *stream, int fd)
538+{
539+ return 0;
540+}
541+
542+static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
543+{
544+ struct stream_out *out = (struct stream_out *)stream;
545+ struct audio_device *adev = out->dev;
546+ struct str_parms *parms;
547+ char value[32];
548+ int ret;
549+ unsigned int val;
550+
551+ parms = str_parms_create_str(kvpairs);
552+
553+ ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING,
554+ value, sizeof(value));
555+ pthread_mutex_lock(&adev->lock);
556+ if (ret >= 0) {
557+ val = atoi(value);
558+ if ((adev->out_device != val) && (val != 0)) {
559+ /*
560+ * If SCO is turned on/off, we need to put audio into standby
561+ * because SCO uses a different PCM.
562+ */
563+ if ((val & AUDIO_DEVICE_OUT_ALL_SCO) ^
564+ (adev->out_device & AUDIO_DEVICE_OUT_ALL_SCO)) {
565+ pthread_mutex_lock(&out->lock);
566+ do_out_standby(out);
567+ pthread_mutex_unlock(&out->lock);
568+ }
569+
570+ adev->out_device = val;
571+ select_devices(adev);
572+ }
573+ }
574+ pthread_mutex_unlock(&adev->lock);
575+
576+ str_parms_destroy(parms);
577+ return ret;
578+}
579+
580+static char * out_get_parameters(const struct audio_stream *stream, const char *keys)
581+{
582+ return strdup("");
583+}
584+
585+static uint32_t out_get_latency(const struct audio_stream_out *stream)
586+{
587+ struct stream_out *out = (struct stream_out *)stream;
588+ struct audio_device *adev = out->dev;
589+ size_t period_count;
590+
591+ pthread_mutex_lock(&adev->lock);
592+
593+ if (adev->screen_off && !adev->active_in && !(adev->out_device & AUDIO_DEVICE_OUT_ALL_SCO))
594+ period_count = OUT_LONG_PERIOD_COUNT;
595+ else
596+ period_count = OUT_SHORT_PERIOD_COUNT;
597+
598+ pthread_mutex_unlock(&adev->lock);
599+
600+ return (pcm_config_out.period_size * period_count * 1000) / pcm_config_out.rate;
601+}
602+
603+static int out_set_volume(struct audio_stream_out *stream, float left,
604+ float right)
605+{
606+ return -ENOSYS;
607+}
608+
609+static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
610+ size_t bytes)
611+{
612+ int ret = 0;
613+ struct stream_out *out = (struct stream_out *)stream;
614+ struct audio_device *adev = out->dev;
615+ size_t frame_size = audio_stream_frame_size(&out->stream.common);
616+ int16_t *in_buffer = (int16_t *)buffer;
617+ size_t in_frames = bytes / frame_size;
618+ size_t out_frames;
619+ int buffer_type;
620+ int kernel_frames;
621+ bool sco_on;
622+
623+ /*
624+ * acquiring hw device mutex systematically is useful if a low
625+ * priority thread is waiting on the output stream mutex - e.g.
626+ * executing out_set_parameters() while holding the hw device
627+ * mutex
628+ */
629+ pthread_mutex_lock(&adev->lock);
630+ pthread_mutex_lock(&out->lock);
631+ if (out->standby) {
632+ ret = start_output_stream(out);
633+ if (ret != 0) {
634+ pthread_mutex_unlock(&adev->lock);
635+ goto exit;
636+ }
637+ out->standby = false;
638+ }
639+ buffer_type = (adev->screen_off && !adev->active_in) ?
640+ OUT_BUFFER_TYPE_LONG : OUT_BUFFER_TYPE_SHORT;
641+ sco_on = (adev->out_device & AUDIO_DEVICE_OUT_ALL_SCO);
642+ pthread_mutex_unlock(&adev->lock);
643+
644+ /* detect changes in screen ON/OFF state and adapt buffer size
645+ * if needed. Do not change buffer size when routed to SCO device. */
646+ if (!sco_on && (buffer_type != out->buffer_type)) {
647+ size_t period_count;
648+
649+ if (buffer_type == OUT_BUFFER_TYPE_LONG)
650+ period_count = OUT_LONG_PERIOD_COUNT;
651+ else
652+ period_count = OUT_SHORT_PERIOD_COUNT;
653+
654+ out->write_threshold = out->pcm_config->period_size * period_count;
655+ /* reset current threshold if exiting standby */
656+ if (out->buffer_type == OUT_BUFFER_TYPE_UNKNOWN)
657+ out->cur_write_threshold = out->write_threshold;
658+ out->buffer_type = buffer_type;
659+ }
660+
661+ /* Reduce number of channels, if necessary */
662+ if (popcount(out_get_channels(&stream->common)) >
663+ (int)out->pcm_config->channels) {
664+ unsigned int i;
665+
666+ /* Discard right channel */
667+ for (i = 1; i < in_frames; i++)
668+ in_buffer[i] = in_buffer[i * 2];
669+
670+ /* The frame size is now half */
671+ frame_size /= 2;
672+ }
673+
674+ /* Change sample rate, if necessary */
675+ if (out_get_sample_rate(&stream->common) != out->pcm_config->rate) {
676+ out_frames = out->buffer_frames;
677+ out->resampler->resample_from_input(out->resampler,
678+ in_buffer, &in_frames,
679+ out->buffer, &out_frames);
680+ in_buffer = out->buffer;
681+ } else {
682+ out_frames = in_frames;
683+ }
684+
685+ if (!sco_on) {
686+ int total_sleep_time_us = 0;
687+ size_t period_size = out->pcm_config->period_size;
688+
689+ /* do not allow more than out->cur_write_threshold frames in kernel
690+ * pcm driver buffer */
691+ do {
692+ struct timespec time_stamp;
693+ if (pcm_get_htimestamp(out->pcm,
694+ (unsigned int *)&kernel_frames,
695+ &time_stamp) < 0)
696+ break;
697+ kernel_frames = pcm_get_buffer_size(out->pcm) - kernel_frames;
698+
699+ if (kernel_frames > out->cur_write_threshold) {
700+ int sleep_time_us =
701+ (int)(((int64_t)(kernel_frames - out->cur_write_threshold)
702+ * 1000000) / out->pcm_config->rate);
703+ if (sleep_time_us < MIN_WRITE_SLEEP_US)
704+ break;
705+ total_sleep_time_us += sleep_time_us;
706+ if (total_sleep_time_us > MAX_WRITE_SLEEP_US) {
707+ ALOGW("out_write() limiting sleep time %d to %d",
708+ total_sleep_time_us, MAX_WRITE_SLEEP_US);
709+ sleep_time_us = MAX_WRITE_SLEEP_US -
710+ (total_sleep_time_us - sleep_time_us);
711+ }
712+ usleep(sleep_time_us);
713+ }
714+
715+ } while ((kernel_frames > out->cur_write_threshold) &&
716+ (total_sleep_time_us <= MAX_WRITE_SLEEP_US));
717+
718+ /* do not allow abrupt changes on buffer size. Increasing/decreasing
719+ * the threshold by steps of 1/4th of the buffer size keeps the write
720+ * time within a reasonable range during transitions.
721+ * Also reset current threshold just above current filling status when
722+ * kernel buffer is really depleted to allow for smooth catching up with
723+ * target threshold.
724+ */
725+ if (out->cur_write_threshold > out->write_threshold) {
726+ out->cur_write_threshold -= period_size / 4;
727+ if (out->cur_write_threshold < out->write_threshold) {
728+ out->cur_write_threshold = out->write_threshold;
729+ }
730+ } else if (out->cur_write_threshold < out->write_threshold) {
731+ out->cur_write_threshold += period_size / 4;
732+ if (out->cur_write_threshold > out->write_threshold) {
733+ out->cur_write_threshold = out->write_threshold;
734+ }
735+ } else if ((kernel_frames < out->write_threshold) &&
736+ ((out->write_threshold - kernel_frames) >
737+ (int)(period_size * OUT_SHORT_PERIOD_COUNT))) {
738+ out->cur_write_threshold = (kernel_frames / period_size + 1) * period_size;
739+ out->cur_write_threshold += period_size / 4;
740+ }
741+ }
742+
743+ ret = pcm_write(out->pcm, in_buffer, out_frames * frame_size);
744+ if (ret == -EPIPE) {
745+ /* In case of underrun, don't sleep since we want to catch up asap */
746+ pthread_mutex_unlock(&out->lock);
747+ return ret;
748+ }
749+
750+exit:
751+ pthread_mutex_unlock(&out->lock);
752+
753+ if (ret != 0) {
754+ usleep(bytes * 1000000 / audio_stream_frame_size(&stream->common) /
755+ out_get_sample_rate(&stream->common));
756+ }
757+
758+ return bytes;
759+}
760+
761+static int out_get_render_position(const struct audio_stream_out *stream,
762+ uint32_t *dsp_frames)
763+{
764+ return -EINVAL;
765+}
766+
767+static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
768+{
769+ return 0;
770+}
771+
772+static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
773+{
774+ return 0;
775+}
776+
777+static int out_get_next_write_timestamp(const struct audio_stream_out *stream,
778+ int64_t *timestamp)
779+{
780+ return -EINVAL;
781+}
782+
783+/** audio_stream_in implementation **/
784+static uint32_t in_get_sample_rate(const struct audio_stream *stream)
785+{
786+ struct stream_in *in = (struct stream_in *)stream;
787+
788+ return in->requested_rate;
789+}
790+
791+static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
792+{
793+ return 0;
794+}
795+
796+static size_t in_get_buffer_size(const struct audio_stream *stream)
797+{
798+ struct stream_in *in = (struct stream_in *)stream;
799+ size_t size;
800+
801+ /*
802+ * take resampling into account and return the closest majoring
803+ * multiple of 16 frames, as audioflinger expects audio buffers to
804+ * be a multiple of 16 frames
805+ */
806+ size = (in->pcm_config->period_size * in_get_sample_rate(stream)) /
807+ in->pcm_config->rate;
808+ size = ((size + 15) / 16) * 16;
809+
810+ return size * audio_stream_frame_size((struct audio_stream *)stream);
811+}
812+
813+static uint32_t in_get_channels(const struct audio_stream *stream)
814+{
815+ return AUDIO_CHANNEL_IN_MONO;
816+}
817+
818+static audio_format_t in_get_format(const struct audio_stream *stream)
819+{
820+ return AUDIO_FORMAT_PCM_16_BIT;
821+}
822+
823+static int in_set_format(struct audio_stream *stream, audio_format_t format)
824+{
825+ return -ENOSYS;
826+}
827+
828+static int in_standby(struct audio_stream *stream)
829+{
830+ struct stream_in *in = (struct stream_in *)stream;
831+
832+ pthread_mutex_lock(&in->dev->lock);
833+ pthread_mutex_lock(&in->lock);
834+ do_in_standby(in);
835+ pthread_mutex_unlock(&in->lock);
836+ pthread_mutex_unlock(&in->dev->lock);
837+
838+ return 0;
839+}
840+
841+static int in_dump(const struct audio_stream *stream, int fd)
842+{
843+ return 0;
844+}
845+
846+static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
847+{
848+ struct stream_in *in = (struct stream_in *)stream;
849+ struct audio_device *adev = in->dev;
850+ struct str_parms *parms;
851+ char value[32];
852+ int ret;
853+ unsigned int val;
854+
855+ parms = str_parms_create_str(kvpairs);
856+
857+ ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING,
858+ value, sizeof(value));
859+ pthread_mutex_lock(&adev->lock);
860+ if (ret >= 0) {
861+ val = atoi(value) & ~AUDIO_DEVICE_BIT_IN;
862+ if ((adev->in_device != val) && (val != 0)) {
863+ /*
864+ * If SCO is turned on/off, we need to put audio into standby
865+ * because SCO uses a different PCM.
866+ */
867+ if ((val & AUDIO_DEVICE_IN_ALL_SCO) ^
868+ (adev->in_device & AUDIO_DEVICE_IN_ALL_SCO)) {
869+ pthread_mutex_lock(&in->lock);
870+ do_in_standby(in);
871+ pthread_mutex_unlock(&in->lock);
872+ }
873+
874+ adev->in_device = val;
875+ select_devices(adev);
876+ }
877+ }
878+ pthread_mutex_unlock(&adev->lock);
879+
880+ str_parms_destroy(parms);
881+ return ret;
882+}
883+
884+static char * in_get_parameters(const struct audio_stream *stream,
885+ const char *keys)
886+{
887+ return strdup("");
888+}
889+
890+static int in_set_gain(struct audio_stream_in *stream, float gain)
891+{
892+ return 0;
893+}
894+
895+static ssize_t in_read(struct audio_stream_in *stream, void* buffer,
896+ size_t bytes)
897+{
898+ int ret = 0;
899+ struct stream_in *in = (struct stream_in *)stream;
900+ struct audio_device *adev = in->dev;
901+ size_t frames_rq = bytes / audio_stream_frame_size(&stream->common);
902+
903+ /*
904+ * acquiring hw device mutex systematically is useful if a low
905+ * priority thread is waiting on the input stream mutex - e.g.
906+ * executing in_set_parameters() while holding the hw device
907+ * mutex
908+ */
909+ pthread_mutex_lock(&adev->lock);
910+ pthread_mutex_lock(&in->lock);
911+ if (in->standby) {
912+ ret = start_input_stream(in);
913+ if (ret == 0)
914+ in->standby = 0;
915+ }
916+ pthread_mutex_unlock(&adev->lock);
917+
918+ if (ret < 0)
919+ goto exit;
920+
921+ /*if (in->num_preprocessors != 0) {
922+ ret = process_frames(in, buffer, frames_rq);
923+ } else */if (in->resampler != NULL) {
924+ ret = read_frames(in, buffer, frames_rq);
925+ } else if (in->pcm_config->channels == 2) {
926+ /*
927+ * If the PCM is stereo, capture twice as many frames and
928+ * discard the right channel.
929+ */
930+ unsigned int i;
931+ int16_t *in_buffer = (int16_t *)buffer;
932+
933+ ret = pcm_read(in->pcm, in->buffer, bytes * 2);
934+
935+ /* Discard right channel */
936+ for (i = 0; i < frames_rq; i++)
937+ in_buffer[i] = in->buffer[i * 2];
938+ } else {
939+ ret = pcm_read(in->pcm, buffer, bytes);
940+ }
941+
942+ if (ret > 0)
943+ ret = 0;
944+
945+ /*
946+ * Instead of writing zeroes here, we could trust the hardware
947+ * to always provide zeroes when muted.
948+ */
949+ if (ret == 0 && adev->mic_mute)
950+ memset(buffer, 0, bytes);
951+
952+exit:
953+ if (ret < 0)
954+ usleep(bytes * 1000000 / audio_stream_frame_size(&stream->common) /
955+ in_get_sample_rate(&stream->common));
956+
957+ pthread_mutex_unlock(&in->lock);
958+ return bytes;
959+}
960+
961+static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
962+{
963+ return 0;
964+}
965+
966+static int in_add_audio_effect(const struct audio_stream *stream,
967+ effect_handle_t effect)
968+{
969+ return 0;
970+}
971+
972+static int in_remove_audio_effect(const struct audio_stream *stream,
973+ effect_handle_t effect)
974+{
975+ return 0;
976+}
977+
978+
979+static int adev_open_output_stream(struct audio_hw_device *dev,
980+ audio_io_handle_t handle,
981+ audio_devices_t devices,
982+ audio_output_flags_t flags,
983+ struct audio_config *config,
984+ struct audio_stream_out **stream_out)
985+{
986+ struct audio_device *adev = (struct audio_device *)dev;
987+ struct stream_out *out;
988+ int ret;
989+
990+ out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
991+ if (!out)
992+ return -ENOMEM;
993+
994+ out->stream.common.get_sample_rate = out_get_sample_rate;
995+ out->stream.common.set_sample_rate = out_set_sample_rate;
996+ out->stream.common.get_buffer_size = out_get_buffer_size;
997+ out->stream.common.get_channels = out_get_channels;
998+ out->stream.common.get_format = out_get_format;
999+ out->stream.common.set_format = out_set_format;
1000+ out->stream.common.standby = out_standby;
1001+ out->stream.common.dump = out_dump;
1002+ out->stream.common.set_parameters = out_set_parameters;
1003+ out->stream.common.get_parameters = out_get_parameters;
1004+ out->stream.common.add_audio_effect = out_add_audio_effect;
1005+ out->stream.common.remove_audio_effect = out_remove_audio_effect;
1006+ out->stream.get_latency = out_get_latency;
1007+ out->stream.set_volume = out_set_volume;
1008+ out->stream.write = out_write;
1009+ out->stream.get_render_position = out_get_render_position;
1010+ out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
1011+
1012+ out->dev = adev;
1013+
1014+ config->format = out_get_format(&out->stream.common);
1015+ config->channel_mask = out_get_channels(&out->stream.common);
1016+ config->sample_rate = out_get_sample_rate(&out->stream.common);
1017+
1018+ out->standby = true;
1019+
1020+ *stream_out = &out->stream;
1021+ return 0;
1022+
1023+err_open:
1024+ free(out);
1025+ *stream_out = NULL;
1026+ return ret;
1027+}
1028+
1029+static void adev_close_output_stream(struct audio_hw_device *dev,
1030+ struct audio_stream_out *stream)
1031+{
1032+ out_standby(&stream->common);
1033+ free(stream);
1034+}
1035+
1036+static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
1037+{
1038+ struct audio_device *adev = (struct audio_device *)dev;
1039+ struct str_parms *parms;
1040+ char *str;
1041+ char value[32];
1042+ int ret;
1043+
1044+ parms = str_parms_create_str(kvpairs);
1045+ ret = str_parms_get_str(parms, "orientation", value, sizeof(value));
1046+ if (ret >= 0) {
1047+ int orientation;
1048+
1049+ if (strcmp(value, "landscape") == 0)
1050+ orientation = ORIENTATION_LANDSCAPE;
1051+ else if (strcmp(value, "portrait") == 0)
1052+ orientation = ORIENTATION_PORTRAIT;
1053+ else if (strcmp(value, "square") == 0)
1054+ orientation = ORIENTATION_SQUARE;
1055+ else
1056+ orientation = ORIENTATION_UNDEFINED;
1057+
1058+ pthread_mutex_lock(&adev->lock);
1059+ if (orientation != adev->orientation) {
1060+ adev->orientation = orientation;
1061+ /*
1062+ * Orientation changes can occur with the input device
1063+ * closed so we must call select_devices() here to set
1064+ * up the mixer. This is because select_devices() will
1065+ * not be called when the input device is opened if no
1066+ * other input parameter is changed.
1067+ */
1068+ select_devices(adev);
1069+ }
1070+ pthread_mutex_unlock(&adev->lock);
1071+ }
1072+
1073+ ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
1074+ if (ret >= 0) {
1075+ if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
1076+ adev->screen_off = false;
1077+ else
1078+ adev->screen_off = true;
1079+ }
1080+
1081+ str_parms_destroy(parms);
1082+ return ret;
1083+}
1084+
1085+static char * adev_get_parameters(const struct audio_hw_device *dev,
1086+ const char *keys)
1087+{
1088+ return strdup("");
1089+}
1090+
1091+static int adev_init_check(const struct audio_hw_device *dev)
1092+{
1093+ return 0;
1094+}
1095+
1096+static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
1097+{
1098+ return -ENOSYS;
1099+}
1100+
1101+static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
1102+{
1103+ return -ENOSYS;
1104+}
1105+
1106+static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
1107+{
1108+ return 0;
1109+}
1110+
1111+static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
1112+{
1113+ struct audio_device *adev = (struct audio_device *)dev;
1114+
1115+ adev->mic_mute = state;
1116+
1117+ return 0;
1118+}
1119+
1120+static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
1121+{
1122+ struct audio_device *adev = (struct audio_device *)dev;
1123+
1124+ *state = adev->mic_mute;
1125+
1126+ return 0;
1127+}
1128+
1129+static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
1130+ const struct audio_config *config)
1131+{
1132+ size_t size;
1133+
1134+ /*
1135+ * take resampling into account and return the closest majoring
1136+ * multiple of 16 frames, as audioflinger expects audio buffers to
1137+ * be a multiple of 16 frames
1138+ */
1139+ size = (pcm_config_in.period_size * config->sample_rate) / pcm_config_in.rate;
1140+ size = ((size + 15) / 16) * 16;
1141+
1142+ return (size * popcount(config->channel_mask) *
1143+ audio_bytes_per_sample(config->format));
1144+}
1145+
1146+static int adev_open_input_stream(struct audio_hw_device *dev,
1147+ audio_io_handle_t handle,
1148+ audio_devices_t devices,
1149+ struct audio_config *config,
1150+ struct audio_stream_in **stream_in)
1151+{
1152+ struct audio_device *adev = (struct audio_device *)dev;
1153+ struct stream_in *in;
1154+ int ret;
1155+
1156+ *stream_in = NULL;
1157+
1158+ /* Respond with a request for mono if a different format is given. */
1159+ if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
1160+ config->channel_mask = AUDIO_CHANNEL_IN_MONO;
1161+ return -EINVAL;
1162+ }
1163+
1164+ in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
1165+ if (!in)
1166+ return -ENOMEM;
1167+
1168+ in->stream.common.get_sample_rate = in_get_sample_rate;
1169+ in->stream.common.set_sample_rate = in_set_sample_rate;
1170+ in->stream.common.get_buffer_size = in_get_buffer_size;
1171+ in->stream.common.get_channels = in_get_channels;
1172+ in->stream.common.get_format = in_get_format;
1173+ in->stream.common.set_format = in_set_format;
1174+ in->stream.common.standby = in_standby;
1175+ in->stream.common.dump = in_dump;
1176+ in->stream.common.set_parameters = in_set_parameters;
1177+ in->stream.common.get_parameters = in_get_parameters;
1178+ in->stream.common.add_audio_effect = in_add_audio_effect;
1179+ in->stream.common.remove_audio_effect = in_remove_audio_effect;
1180+ in->stream.set_gain = in_set_gain;
1181+ in->stream.read = in_read;
1182+ in->stream.get_input_frames_lost = in_get_input_frames_lost;
1183+
1184+ in->dev = adev;
1185+ in->standby = true;
1186+ in->requested_rate = config->sample_rate;
1187+ in->pcm_config = &pcm_config_in; /* default PCM config */
1188+
1189+ *stream_in = &in->stream;
1190+ return 0;
1191+}
1192+
1193+static void adev_close_input_stream(struct audio_hw_device *dev,
1194+ struct audio_stream_in *stream)
1195+{
1196+ struct stream_in *in = (struct stream_in *)stream;
1197+
1198+ in_standby(&stream->common);
1199+ free(stream);
1200+}
1201+
1202+static int adev_dump(const audio_hw_device_t *device, int fd)
1203+{
1204+ return 0;
1205+}
1206+
1207+static int adev_close(hw_device_t *device)
1208+{
1209+ struct audio_device *adev = (struct audio_device *)device;
1210+
1211+ audio_route_free(adev->ar);
1212+
1213+ free(device);
1214+ return 0;
1215+}
1216+
1217+static int adev_open(const hw_module_t* module, const char* name,
1218+ hw_device_t** device)
1219+{
1220+ struct audio_device *adev;
1221+ int ret;
1222+
1223+ if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)
1224+ return -EINVAL;
1225+
1226+ adev = calloc(1, sizeof(struct audio_device));
1227+ if (!adev)
1228+ return -ENOMEM;
1229+
1230+ adev->hw_device.common.tag = HARDWARE_DEVICE_TAG;
1231+ adev->hw_device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
1232+ adev->hw_device.common.module = (struct hw_module_t *) module;
1233+ adev->hw_device.common.close = adev_close;
1234+
1235+ adev->hw_device.init_check = adev_init_check;
1236+ adev->hw_device.set_voice_volume = adev_set_voice_volume;
1237+ adev->hw_device.set_master_volume = adev_set_master_volume;
1238+ adev->hw_device.set_mode = adev_set_mode;
1239+ adev->hw_device.set_mic_mute = adev_set_mic_mute;
1240+ adev->hw_device.get_mic_mute = adev_get_mic_mute;
1241+ adev->hw_device.set_parameters = adev_set_parameters;
1242+ adev->hw_device.get_parameters = adev_get_parameters;
1243+ adev->hw_device.get_input_buffer_size = adev_get_input_buffer_size;
1244+ adev->hw_device.open_output_stream = adev_open_output_stream;
1245+ adev->hw_device.close_output_stream = adev_close_output_stream;
1246+ adev->hw_device.open_input_stream = adev_open_input_stream;
1247+ adev->hw_device.close_input_stream = adev_close_input_stream;
1248+ adev->hw_device.dump = adev_dump;
1249+
1250+ adev->ar = audio_route_init();
1251+ adev->orientation = ORIENTATION_UNDEFINED;
1252+ adev->out_device = AUDIO_DEVICE_OUT_SPEAKER;
1253+ adev->in_device = AUDIO_DEVICE_IN_BUILTIN_MIC & ~AUDIO_DEVICE_BIT_IN;
1254+
1255+ *device = &adev->hw_device.common;
1256+
1257+ return 0;
1258+}
1259+
1260+static struct hw_module_methods_t hal_module_methods = {
1261+ .open = adev_open,
1262+};
1263+
1264+struct audio_module HAL_MODULE_INFO_SYM = {
1265+ .common = {
1266+ .tag = HARDWARE_MODULE_TAG,
1267+ .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
1268+ .hal_api_version = HARDWARE_HAL_API_VERSION,
1269+ .id = AUDIO_HARDWARE_MODULE_ID,
1270+ .name = "Grouper audio HW HAL",
1271+ .author = "The Android Open Source Project",
1272+ .methods = &hal_module_methods,
1273+ },
1274+};
--- /dev/null
+++ b/audio_policy.conf
@@ -0,0 +1,68 @@
1+# Global configuration section: lists input and output devices always present on the device
2+# as well as the output device selected by default.
3+# Devices are designated by a string that corresponds to the enum in audio.h
4+
5+global_configuration {
6+ attached_output_devices AUDIO_DEVICE_OUT_SPEAKER
7+ default_output_device AUDIO_DEVICE_OUT_SPEAKER
8+ attached_input_devices AUDIO_DEVICE_IN_BUILTIN_MIC
9+}
10+
11+# audio hardware module section: contains descriptors for all audio hw modules present on the
12+# device. Each hw module node is named after the corresponding hw module library base name.
13+# For instance, "primary" corresponds to audio.primary.<device>.so.
14+# The "primary" module is mandatory and must include at least one output with
15+# AUDIO_OUTPUT_FLAG_PRIMARY flag.
16+# Each module descriptor contains one or more output profile descriptors and zero or more
17+# input profile descriptors. Each profile lists all the parameters supported by a given output
18+# or input stream category.
19+# The "channel_masks", "formats", "devices" and "flags" are specified using strings corresponding
20+# to enums in audio.h and audio_policy.h. They are concatenated by use of "|" without space or "\n".
21+
22+audio_hw_modules {
23+ primary {
24+ outputs {
25+ primary {
26+ sampling_rates 44100
27+ channel_masks AUDIO_CHANNEL_OUT_STEREO
28+ formats AUDIO_FORMAT_PCM_16_BIT
29+ devices AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|AUDIO_DEVICE_OUT_ALL_SCO
30+ flags AUDIO_OUTPUT_FLAG_PRIMARY
31+ }
32+ }
33+ inputs {
34+ primary {
35+ sampling_rates 8000|11025|16000|22050|24000|32000|44100|48000
36+ channel_masks AUDIO_CHANNEL_IN_MONO|AUDIO_CHANNEL_IN_STEREO
37+ formats AUDIO_FORMAT_PCM_16_BIT
38+ devices AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET|AUDIO_DEVICE_IN_WIRED_HEADSET
39+ }
40+ }
41+ }
42+ a2dp {
43+ outputs {
44+ a2dp {
45+ sampling_rates 44100
46+ channel_masks AUDIO_CHANNEL_OUT_STEREO
47+ formats AUDIO_FORMAT_PCM_16_BIT
48+ devices AUDIO_DEVICE_OUT_ALL_A2DP
49+ }
50+ }
51+ }
52+ usb {
53+ outputs {
54+ usb_accessory {
55+ sampling_rates 44100
56+ channel_masks AUDIO_CHANNEL_OUT_STEREO
57+ formats AUDIO_FORMAT_PCM_16_BIT
58+ devices AUDIO_DEVICE_OUT_USB_ACCESSORY
59+ }
60+ usb_device {
61+ sampling_rates 44100
62+ channel_masks AUDIO_CHANNEL_OUT_STEREO
63+ formats AUDIO_FORMAT_PCM_16_BIT
64+ devices AUDIO_DEVICE_OUT_USB_DEVICE
65+ }
66+ }
67+ }
68+}
--- /dev/null
+++ b/audio_route.c
@@ -0,0 +1,494 @@
1+/*
2+ * Copyright (C) 2012 The Android Open Source Project
3+ * Inspired by TinyHW, written by Mark Brown at Wolfson Micro
4+ *
5+ * Licensed under the Apache License, Version 2.0 (the "License");
6+ * you may not use this file except in compliance with the License.
7+ * You may obtain a copy of the License at
8+ *
9+ * http://www.apache.org/licenses/LICENSE-2.0
10+ *
11+ * Unless required by applicable law or agreed to in writing, software
12+ * distributed under the License is distributed on an "AS IS" BASIS,
13+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+ * See the License for the specific language governing permissions and
15+ * limitations under the License.
16+ */
17+
18+#define LOG_TAG "audio_hw_primary"
19+/*#define LOG_NDEBUG 0*/
20+
21+#include <errno.h>
22+#include <expat.h>
23+#include <stdbool.h>
24+#include <stdio.h>
25+
26+#include <cutils/log.h>
27+
28+#include <tinyalsa/asoundlib.h>
29+
30+#define BUF_SIZE 1024
31+#define MIXER_XML_PATH "/system/etc/mixer_paths.xml"
32+#define INITIAL_MIXER_PATH_SIZE 8
33+
34+#define MIXER_CARD 1
35+
36+struct mixer_state {
37+ struct mixer_ctl *ctl;
38+ int old_value;
39+ int new_value;
40+ int reset_value;
41+};
42+
43+struct mixer_setting {
44+ struct mixer_ctl *ctl;
45+ int value;
46+};
47+
48+struct mixer_path {
49+ char *name;
50+ unsigned int size;
51+ unsigned int length;
52+ struct mixer_setting *setting;
53+};
54+
55+struct audio_route {
56+ struct mixer *mixer;
57+ unsigned int num_mixer_ctls;
58+ struct mixer_state *mixer_state;
59+
60+ unsigned int mixer_path_size;
61+ unsigned int num_mixer_paths;
62+ struct mixer_path *mixer_path;
63+};
64+
65+struct config_parse_state {
66+ struct audio_route *ar;
67+ struct mixer_path *path;
68+ int level;
69+};
70+
71+/* path functions */
72+
73+static void path_free(struct audio_route *ar)
74+{
75+ unsigned int i;
76+
77+ for (i = 0; i < ar->num_mixer_paths; i++) {
78+ if (ar->mixer_path[i].name)
79+ free(ar->mixer_path[i].name);
80+ if (ar->mixer_path[i].setting)
81+ free(ar->mixer_path[i].setting);
82+ }
83+ free(ar->mixer_path);
84+}
85+
86+static struct mixer_path *path_get_by_name(struct audio_route *ar,
87+ const char *name)
88+{
89+ unsigned int i;
90+
91+ for (i = 0; i < ar->num_mixer_paths; i++)
92+ if (strcmp(ar->mixer_path[i].name, name) == 0)
93+ return &ar->mixer_path[i];
94+
95+ return NULL;
96+}
97+
98+static struct mixer_path *path_create(struct audio_route *ar, const char *name)
99+{
100+ struct mixer_path *new_mixer_path = NULL;
101+
102+ if (path_get_by_name(ar, name)) {
103+ ALOGE("Path name '%s' already exists", name);
104+ return NULL;
105+ }
106+
107+ /* check if we need to allocate more space for mixer paths */
108+ if (ar->mixer_path_size <= ar->num_mixer_paths) {
109+ if (ar->mixer_path_size == 0)
110+ ar->mixer_path_size = INITIAL_MIXER_PATH_SIZE;
111+ else
112+ ar->mixer_path_size *= 2;
113+
114+ new_mixer_path = realloc(ar->mixer_path, ar->mixer_path_size *
115+ sizeof(struct mixer_path));
116+ if (new_mixer_path == NULL) {
117+ ALOGE("Unable to allocate more paths");
118+ return NULL;
119+ } else {
120+ ar->mixer_path = new_mixer_path;
121+ }
122+ }
123+
124+ /* initialise the new mixer path */
125+ ar->mixer_path[ar->num_mixer_paths].name = strdup(name);
126+ ar->mixer_path[ar->num_mixer_paths].size = 0;
127+ ar->mixer_path[ar->num_mixer_paths].length = 0;
128+ ar->mixer_path[ar->num_mixer_paths].setting = NULL;
129+
130+ /* return the mixer path just added, then increment number of them */
131+ return &ar->mixer_path[ar->num_mixer_paths++];
132+}
133+
134+static bool path_setting_exists(struct mixer_path *path,
135+ struct mixer_setting *setting)
136+{
137+ unsigned int i;
138+
139+ for (i = 0; i < path->length; i++)
140+ if (path->setting[i].ctl == setting->ctl)
141+ return true;
142+
143+ return false;
144+}
145+
146+static int path_add_setting(struct mixer_path *path,
147+ struct mixer_setting *setting)
148+{
149+ struct mixer_setting *new_path_setting;
150+
151+ if (path_setting_exists(path, setting)) {
152+ ALOGE("Duplicate path setting '%s'",
153+ mixer_ctl_get_name(setting->ctl));
154+ return -1;
155+ }
156+
157+ /* check if we need to allocate more space for path settings */
158+ if (path->size <= path->length) {
159+ if (path->size == 0)
160+ path->size = INITIAL_MIXER_PATH_SIZE;
161+ else
162+ path->size *= 2;
163+
164+ new_path_setting = realloc(path->setting,
165+ path->size * sizeof(struct mixer_setting));
166+ if (new_path_setting == NULL) {
167+ ALOGE("Unable to allocate more path settings");
168+ return -1;
169+ } else {
170+ path->setting = new_path_setting;
171+ }
172+ }
173+
174+ /* initialise the new path setting */
175+ path->setting[path->length].ctl = setting->ctl;
176+ path->setting[path->length].value = setting->value;
177+ path->length++;
178+
179+ return 0;
180+}
181+
182+static int path_add_path(struct mixer_path *path, struct mixer_path *sub_path)
183+{
184+ unsigned int i;
185+
186+ for (i = 0; i < sub_path->length; i++)
187+ if (path_add_setting(path, &sub_path->setting[i]) < 0)
188+ return -1;
189+
190+ return 0;
191+}
192+
193+static void path_print(struct mixer_path *path)
194+{
195+ unsigned int i;
196+
197+ ALOGV("Path: %s, length: %d", path->name, path->length);
198+ for (i = 0; i < path->length; i++)
199+ ALOGV(" %d: %s -> %d", i, mixer_ctl_get_name(path->setting[i].ctl),
200+ path->setting[i].value);
201+}
202+
203+static int path_apply(struct audio_route *ar, struct mixer_path *path)
204+{
205+ unsigned int i;
206+ unsigned int j;
207+
208+ for (i = 0; i < path->length; i++) {
209+ struct mixer_ctl *ctl = path->setting[i].ctl;
210+
211+ /* locate the mixer ctl in the list */
212+ for (j = 0; j < ar->num_mixer_ctls; j++) {
213+ if (ar->mixer_state[j].ctl == ctl)
214+ break;
215+ }
216+
217+ /* apply the new value */
218+ ar->mixer_state[j].new_value = path->setting[i].value;
219+ }
220+
221+ return 0;
222+}
223+
224+/* mixer helper function */
225+static int mixer_enum_string_to_value(struct mixer_ctl *ctl, const char *string)
226+{
227+ unsigned int i;
228+
229+ /* Search the enum strings for a particular one */
230+ for (i = 0; i < mixer_ctl_get_num_enums(ctl); i++) {
231+ if (strcmp(mixer_ctl_get_enum_string(ctl, i), string) == 0)
232+ break;
233+ }
234+
235+ return i;
236+}
237+
238+static void start_tag(void *data, const XML_Char *tag_name,
239+ const XML_Char **attr)
240+{
241+ const XML_Char *attr_name = NULL;
242+ const XML_Char *attr_value = NULL;
243+ struct config_parse_state *state = data;
244+ struct audio_route *ar = state->ar;
245+ unsigned int i;
246+ struct mixer_ctl *ctl;
247+ int value;
248+ struct mixer_setting mixer_setting;
249+
250+ /* Get name, type and value attributes (these may be empty) */
251+ for (i = 0; attr[i]; i += 2) {
252+ if (strcmp(attr[i], "name") == 0)
253+ attr_name = attr[i + 1];
254+ else if (strcmp(attr[i], "value") == 0)
255+ attr_value = attr[i + 1];
256+ }
257+
258+ /* Look at tags */
259+ if (strcmp(tag_name, "path") == 0) {
260+ if (attr_name == NULL) {
261+ ALOGE("Unnamed path!");
262+ } else {
263+ if (state->level == 1) {
264+ /* top level path: create and stash the path */
265+ state->path = path_create(ar, (char *)attr_name);
266+ } else {
267+ /* nested path */
268+ struct mixer_path *sub_path = path_get_by_name(ar, attr_name);
269+ path_add_path(state->path, sub_path);
270+ }
271+ }
272+ }
273+
274+ else if (strcmp(tag_name, "ctl") == 0) {
275+ /* Obtain the mixer ctl and value */
276+ ctl = mixer_get_ctl_by_name(ar->mixer, attr_name);
277+ switch (mixer_ctl_get_type(ctl)) {
278+ case MIXER_CTL_TYPE_BOOL:
279+ case MIXER_CTL_TYPE_INT:
280+ value = atoi((char *)attr_value);
281+ break;
282+ case MIXER_CTL_TYPE_ENUM:
283+ value = mixer_enum_string_to_value(ctl, (char *)attr_value);
284+ break;
285+ default:
286+ value = 0;
287+ break;
288+ }
289+
290+ if (state->level == 1) {
291+ /* top level ctl (initial setting) */
292+
293+ /* locate the mixer ctl in the list */
294+ for (i = 0; i < ar->num_mixer_ctls; i++) {
295+ if (ar->mixer_state[i].ctl == ctl)
296+ break;
297+ }
298+
299+ /* apply the new value */
300+ ar->mixer_state[i].new_value = value;
301+ } else {
302+ /* nested ctl (within a path) */
303+ mixer_setting.ctl = ctl;
304+ mixer_setting.value = value;
305+ path_add_setting(state->path, &mixer_setting);
306+ }
307+ }
308+
309+ state->level++;
310+}
311+
312+static void end_tag(void *data, const XML_Char *tag_name)
313+{
314+ struct config_parse_state *state = data;
315+
316+ state->level--;
317+}
318+
319+static int alloc_mixer_state(struct audio_route *ar)
320+{
321+ unsigned int i;
322+
323+ ar->num_mixer_ctls = mixer_get_num_ctls(ar->mixer);
324+ ar->mixer_state = malloc(ar->num_mixer_ctls * sizeof(struct mixer_state));
325+ if (!ar->mixer_state)
326+ return -1;
327+
328+ for (i = 0; i < ar->num_mixer_ctls; i++) {
329+ ar->mixer_state[i].ctl = mixer_get_ctl(ar->mixer, i);
330+ /* only get value 0, assume multiple ctl values are the same */
331+ ar->mixer_state[i].old_value = mixer_ctl_get_value(ar->mixer_state[i].ctl, 0);
332+ ar->mixer_state[i].new_value = ar->mixer_state[i].old_value;
333+ }
334+
335+ return 0;
336+}
337+
338+static void free_mixer_state(struct audio_route *ar)
339+{
340+ free(ar->mixer_state);
341+ ar->mixer_state = NULL;
342+}
343+
344+void update_mixer_state(struct audio_route *ar)
345+{
346+ unsigned int i;
347+ unsigned int j;
348+
349+ for (i = 0; i < ar->num_mixer_ctls; i++) {
350+ /* if the value has changed, update the mixer */
351+ if (ar->mixer_state[i].old_value != ar->mixer_state[i].new_value) {
352+ /* set all ctl values the same */
353+ for (j = 0; j < mixer_ctl_get_num_values(ar->mixer_state[i].ctl); j++)
354+ mixer_ctl_set_value(ar->mixer_state[i].ctl, j,
355+ ar->mixer_state[i].new_value);
356+ ar->mixer_state[i].old_value = ar->mixer_state[i].new_value;
357+ }
358+ }
359+}
360+
361+/* saves the current state of the mixer, for resetting all controls */
362+static void save_mixer_state(struct audio_route *ar)
363+{
364+ unsigned int i;
365+
366+ for (i = 0; i < ar->num_mixer_ctls; i++) {
367+ /* only get value 0, assume multiple ctl values are the same */
368+ ar->mixer_state[i].reset_value = mixer_ctl_get_value(ar->mixer_state[i].ctl, 0);
369+ }
370+}
371+
372+/* this resets all mixer settings to the saved values */
373+void reset_mixer_state(struct audio_route *ar)
374+{
375+ unsigned int i;
376+
377+ /* load all of the saved values */
378+ for (i = 0; i < ar->num_mixer_ctls; i++)
379+ ar->mixer_state[i].new_value = ar->mixer_state[i].reset_value;
380+}
381+
382+void audio_route_apply_path(struct audio_route *ar, const char *name)
383+{
384+ struct mixer_path *path;
385+
386+ if (!ar) {
387+ ALOGE("invalid audio_route");
388+ return;
389+ }
390+
391+ path = path_get_by_name(ar, name);
392+ if (!path) {
393+ ALOGE("unable to find path '%s'", name);
394+ return;
395+ }
396+
397+ path_apply(ar, path);
398+}
399+
400+struct audio_route *audio_route_init(void)
401+{
402+ struct config_parse_state state;
403+ XML_Parser parser;
404+ FILE *file;
405+ int bytes_read;
406+ void *buf;
407+ int i;
408+ struct mixer_path *path;
409+ struct audio_route *ar;
410+
411+ ar = calloc(1, sizeof(struct audio_route));
412+ if (!ar)
413+ goto err_calloc;
414+
415+ ar->mixer = mixer_open(MIXER_CARD);
416+ if (!ar->mixer) {
417+ ALOGE("Unable to open the mixer, aborting.");
418+ goto err_mixer_open;
419+ }
420+
421+ ar->mixer_path = NULL;
422+ ar->mixer_path_size = 0;
423+ ar->num_mixer_paths = 0;
424+
425+ /* allocate space for and read current mixer settings */
426+ if (alloc_mixer_state(ar) < 0)
427+ goto err_mixer_state;
428+
429+ file = fopen(MIXER_XML_PATH, "r");
430+ if (!file) {
431+ ALOGE("Failed to open %s", MIXER_XML_PATH);
432+ goto err_fopen;
433+ }
434+
435+ parser = XML_ParserCreate(NULL);
436+ if (!parser) {
437+ ALOGE("Failed to create XML parser");
438+ goto err_parser_create;
439+ }
440+
441+ memset(&state, 0, sizeof(state));
442+ state.ar = ar;
443+ XML_SetUserData(parser, &state);
444+ XML_SetElementHandler(parser, start_tag, end_tag);
445+
446+ for (;;) {
447+ buf = XML_GetBuffer(parser, BUF_SIZE);
448+ if (buf == NULL)
449+ goto err_parse;
450+
451+ bytes_read = fread(buf, 1, BUF_SIZE, file);
452+ if (bytes_read < 0)
453+ goto err_parse;
454+
455+ if (XML_ParseBuffer(parser, bytes_read,
456+ bytes_read == 0) == XML_STATUS_ERROR) {
457+ ALOGE("Error in mixer xml (%s)", MIXER_XML_PATH);
458+ goto err_parse;
459+ }
460+
461+ if (bytes_read == 0)
462+ break;
463+ }
464+
465+ /* apply the initial mixer values, and save them so we can reset the
466+ mixer to the original values */
467+ update_mixer_state(ar);
468+ save_mixer_state(ar);
469+
470+ XML_ParserFree(parser);
471+ fclose(file);
472+ return ar;
473+
474+err_parse:
475+ XML_ParserFree(parser);
476+err_parser_create:
477+ fclose(file);
478+err_fopen:
479+ free_mixer_state(ar);
480+err_mixer_state:
481+ mixer_close(ar->mixer);
482+err_mixer_open:
483+ free(ar);
484+ ar = NULL;
485+err_calloc:
486+ return NULL;
487+}
488+
489+void audio_route_free(struct audio_route *ar)
490+{
491+ free_mixer_state(ar);
492+ mixer_close(ar->mixer);
493+ free(ar);
494+}
--- /dev/null
+++ b/audio_route.h
@@ -0,0 +1,33 @@
1+/*
2+ * Copyright (C) 2012 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+#ifndef AUDIO_ROUTE_H
18+#define AUDIO_ROUTE_H
19+
20+/* Initialises and frees the audio routes */
21+struct audio_route *audio_route_init(void);
22+void audio_route_free(struct audio_route *ar);
23+
24+/* Applies an audio route path by name */
25+void audio_route_apply_path(struct audio_route *ar, const char *name);
26+
27+/* Resets the mixer back to its initial state */
28+void reset_mixer_state(struct audio_route *ar);
29+
30+/* Updates the mixer with any changed values */
31+void update_mixer_state(struct audio_route *ar);
32+
33+#endif