ALSAMixer.cpp revision 4113f34dfbaa8d82a5e1ef0265e916317161984d
14765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev/* ALSAMixer.cpp 24765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ** 34765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ** Copyright 2008-2010 Wind River Systems 44765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ** 54765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ** Licensed under the Apache License, Version 2.0 (the "License"); 64765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ** you may not use this file except in compliance with the License. 74765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ** You may obtain a copy of the License at 84765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ** 94765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ** http://www.apache.org/licenses/LICENSE-2.0 104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ** 114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ** Unless required by applicable law or agreed to in writing, software 124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ** distributed under the License is distributed on an "AS IS" BASIS, 134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ** See the License for the specific language governing permissions and 154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ** limitations under the License. 164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev */ 174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <errno.h> 194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <stdarg.h> 204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <sys/stat.h> 214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <fcntl.h> 224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <stdlib.h> 234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <unistd.h> 244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <dlfcn.h> 254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#define LOG_TAG "AudioHardwareALSA" 274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <utils/Log.h> 284113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev 294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <utils/String8.h> 304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <cutils/properties.h> 324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <media/AudioRecord.h> 334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <hardware_legacy/power.h> 344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include "AudioHardwareALSA.h" 364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#define SND_MIXER_VOL_RANGE_MIN (0) 384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#define SND_MIXER_VOL_RANGE_MAX (100) 394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#define ALSA_NAME_MAX 128 414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#define ALSA_STRCAT(x,y) \ 434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (strlen(x) + strlen(y) < ALSA_NAME_MAX) \ 444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev strcat(x, y); 454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevnamespace android 474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// ---------------------------------------------------------------------------- 504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstruct mixer_info_t; 524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstruct alsa_properties_t 544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev const AudioSystem::audio_devices device; 564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev const char *propName; 574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev const char *propDefault; 584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mixer_info_t *mInfo; 594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}; 604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#define ALSA_PROP(dev, name, out, in) \ 624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev {\ 634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev {dev, "alsa.mixer.playback." name, out, NULL},\ 644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev {dev, "alsa.mixer.capture." name, in, NULL}\ 654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic alsa_properties_t 684765c439491ddda3de658e62cc4a64d10e726b34Iliyan MalchevmixerMasterProp[SND_PCM_STREAM_LAST+1] = 694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ALSA_PROP(AudioSystem::DEVICE_OUT_ALL, "master", "PCM", "Capture"); 704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic alsa_properties_t 724765c439491ddda3de658e62cc4a64d10e726b34Iliyan MalchevmixerProp[][SND_PCM_STREAM_LAST+1] = { 734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ALSA_PROP(AudioSystem::DEVICE_OUT_EARPIECE, "earpiece", "Earpiece", "Capture"), 744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ALSA_PROP(AudioSystem::DEVICE_OUT_SPEAKER, "speaker", "Speaker", ""), 754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ALSA_PROP(AudioSystem::DEVICE_OUT_WIRED_HEADSET, "headset", "Headphone", "Capture"), 764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ALSA_PROP(AudioSystem::DEVICE_OUT_BLUETOOTH_SCO, "bluetooth.sco", "Bluetooth", "Bluetooth Capture"), 774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ALSA_PROP(AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP, "bluetooth.a2dp", "Bluetooth A2DP", "Bluetooth A2DP Capture"), 784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ALSA_PROP(static_cast<AudioSystem::audio_devices>(0), "", NULL, NULL) 794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}; 804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstruct mixer_info_t 824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mixer_info_t() : 844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev elem(0), 854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev min(SND_MIXER_VOL_RANGE_MIN), 864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev max(SND_MIXER_VOL_RANGE_MAX), 874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mute(false) 884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev { 894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_mixer_elem_t *elem; 924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev long min; 934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev long max; 944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev long volume; 954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev bool mute; 964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev char name[ALSA_NAME_MAX]; 974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}; 984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic int initMixer (snd_mixer_t **mixer, const char *name) 1004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 1014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev int err; 1024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if ((err = snd_mixer_open(mixer, 0)) < 0) { 1044113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGE("Unable to open mixer: %s", snd_strerror(err)); 1054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return err; 1064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if ((err = snd_mixer_attach(*mixer, name)) < 0) { 1094113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGW("Unable to attach mixer to device %s: %s", 1104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev name, snd_strerror(err)); 1114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if ((err = snd_mixer_attach(*mixer, "hw:00")) < 0) { 1134113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGE("Unable to attach mixer to device default: %s", 1144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_strerror(err)); 1154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_mixer_close (*mixer); 1174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev *mixer = NULL; 1184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return err; 1194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if ((err = snd_mixer_selem_register(*mixer, NULL, NULL)) < 0) { 1234113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGE("Unable to register mixer elements: %s", snd_strerror(err)); 1244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_mixer_close (*mixer); 1254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev *mixer = NULL; 1264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return err; 1274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev // Get the mixer controls from the kernel 1304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if ((err = snd_mixer_load(*mixer)) < 0) { 1314113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGE("Unable to load mixer elements: %s", snd_strerror(err)); 1324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_mixer_close (*mixer); 1334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev *mixer = NULL; 1344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return err; 1354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return 0; 1384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 1394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevtypedef int (*hasVolume_t)(snd_mixer_elem_t*); 1414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic const hasVolume_t hasVolume[] = { 1434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_mixer_selem_has_playback_volume, 1444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_mixer_selem_has_capture_volume 1454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}; 1464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevtypedef int (*getVolumeRange_t)(snd_mixer_elem_t*, long int*, long int*); 1484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic const getVolumeRange_t getVolumeRange[] = { 1504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_mixer_selem_get_playback_volume_range, 1514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_mixer_selem_get_capture_volume_range 1524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}; 1534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevtypedef int (*setVolume_t)(snd_mixer_elem_t*, long int); 1554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic const setVolume_t setVol[] = { 1574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_mixer_selem_set_playback_volume_all, 1584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_mixer_selem_set_capture_volume_all 1594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}; 1604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1614765c439491ddda3de658e62cc4a64d10e726b34Iliyan MalchevALSAMixer::ALSAMixer() 1624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 1634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev int err; 1644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev initMixer (&mMixer[SND_PCM_STREAM_PLAYBACK], "AndroidOut"); 1664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev initMixer (&mMixer[SND_PCM_STREAM_CAPTURE], "AndroidIn"); 1674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_mixer_selem_id_t *sid; 1694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_mixer_selem_id_alloca(&sid); 1704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev for (int i = 0; i <= SND_PCM_STREAM_LAST; i++) { 1724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (!mMixer[i]) continue; 1744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mixer_info_t *info = mixerMasterProp[i].mInfo = new mixer_info_t; 1764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev property_get (mixerMasterProp[i].propName, 1784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev info->name, 1794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mixerMasterProp[i].propDefault); 1804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev for (snd_mixer_elem_t *elem = snd_mixer_first_elem(mMixer[i]); 1824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev elem; 1834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev elem = snd_mixer_elem_next(elem)) { 1844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (!snd_mixer_selem_is_active(elem)) 1864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev continue; 1874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_mixer_selem_get_id(elem, sid); 1894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev // Find PCM playback volume control element. 1914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev const char *elementName = snd_mixer_selem_id_get_name(sid); 1924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (info->elem == NULL && 1944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev strcmp(elementName, info->name) == 0 && 1954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev hasVolume[i] (elem)) { 1964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev info->elem = elem; 1984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev getVolumeRange[i] (elem, &info->min, &info->max); 1994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev info->volume = info->max; 2004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev setVol[i] (elem, info->volume); 2014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (i == SND_PCM_STREAM_PLAYBACK && 2024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_mixer_selem_has_playback_switch (elem)) 2034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_mixer_selem_set_playback_switch_all (elem, 1); 2044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 2054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2084113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGV("Mixer: master '%s' %s.", info->name, info->elem ? "found" : "not found"); 2094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev for (int j = 0; mixerProp[j][i].device; j++) { 2114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mixer_info_t *info = mixerProp[j][i].mInfo = new mixer_info_t; 2134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev property_get (mixerProp[j][i].propName, 2154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev info->name, 2164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mixerProp[j][i].propDefault); 2174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev for (snd_mixer_elem_t *elem = snd_mixer_first_elem(mMixer[i]); 2194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev elem; 2204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev elem = snd_mixer_elem_next(elem)) { 2214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (!snd_mixer_selem_is_active(elem)) 2234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev continue; 2244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_mixer_selem_get_id(elem, sid); 2264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev // Find PCM playback volume control element. 2284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev const char *elementName = snd_mixer_selem_id_get_name(sid); 2294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (info->elem == NULL && 2314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev strcmp(elementName, info->name) == 0 && 2324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev hasVolume[i] (elem)) { 2334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev info->elem = elem; 2354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev getVolumeRange[i] (elem, &info->min, &info->max); 2364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev info->volume = info->max; 2374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev setVol[i] (elem, info->volume); 2384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (i == SND_PCM_STREAM_PLAYBACK && 2394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_mixer_selem_has_playback_switch (elem)) 2404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_mixer_selem_set_playback_switch_all (elem, 1); 2414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 2424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2444113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGV("Mixer: route '%s' %s.", info->name, info->elem ? "found" : "not found"); 2454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2474113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGV("mixer initialized."); 2484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 2494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2504765c439491ddda3de658e62cc4a64d10e726b34Iliyan MalchevALSAMixer::~ALSAMixer() 2514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 2524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev for (int i = 0; i <= SND_PCM_STREAM_LAST; i++) { 2534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (mMixer[i]) snd_mixer_close (mMixer[i]); 2544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (mixerMasterProp[i].mInfo) { 2554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev delete mixerMasterProp[i].mInfo; 2564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mixerMasterProp[i].mInfo = NULL; 2574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev for (int j = 0; mixerProp[j][i].device; j++) { 2594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (mixerProp[j][i].mInfo) { 2604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev delete mixerProp[j][i].mInfo; 2614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mixerProp[j][i].mInfo = NULL; 2624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2654113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGV("mixer destroyed."); 2664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 2674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatus_t ALSAMixer::setMasterVolume(float volume) 2694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 2704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mixer_info_t *info = mixerMasterProp[SND_PCM_STREAM_PLAYBACK].mInfo; 2714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (!info || !info->elem) return INVALID_OPERATION; 2724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev long minVol = info->min; 2744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev long maxVol = info->max; 2754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev // Make sure volume is between bounds. 2774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev long vol = minVol + volume * (maxVol - minVol); 2784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (vol > maxVol) vol = maxVol; 2794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (vol < minVol) vol = minVol; 2804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev info->volume = vol; 2824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_mixer_selem_set_playback_volume_all (info->elem, vol); 2834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return NO_ERROR; 2854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 2864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatus_t ALSAMixer::setMasterGain(float gain) 2884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 2894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mixer_info_t *info = mixerMasterProp[SND_PCM_STREAM_CAPTURE].mInfo; 2904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (!info || !info->elem) return INVALID_OPERATION; 2914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev long minVol = info->min; 2934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev long maxVol = info->max; 2944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev // Make sure volume is between bounds. 2964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev long vol = minVol + gain * (maxVol - minVol); 2974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (vol > maxVol) vol = maxVol; 2984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (vol < minVol) vol = minVol; 2994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev info->volume = vol; 3014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_mixer_selem_set_capture_volume_all (info->elem, vol); 3024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return NO_ERROR; 3044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 3054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatus_t ALSAMixer::setVolume(uint32_t device, float left, float right) 3074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 3084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev for (int j = 0; mixerProp[j][SND_PCM_STREAM_PLAYBACK].device; j++) 3094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (mixerProp[j][SND_PCM_STREAM_PLAYBACK].device & device) { 3104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mixer_info_t *info = mixerProp[j][SND_PCM_STREAM_PLAYBACK].mInfo; 3124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (!info || !info->elem) return INVALID_OPERATION; 3134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev long minVol = info->min; 3154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev long maxVol = info->max; 3164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev // Make sure volume is between bounds. 3184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev long vol = minVol + left * (maxVol - minVol); 3194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (vol > maxVol) vol = maxVol; 3204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (vol < minVol) vol = minVol; 3214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev info->volume = vol; 3234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_mixer_selem_set_playback_volume_all (info->elem, vol); 3244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return NO_ERROR; 3274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 3284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatus_t ALSAMixer::setGain(uint32_t device, float gain) 3304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 3314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev for (int j = 0; mixerProp[j][SND_PCM_STREAM_CAPTURE].device; j++) 3324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (mixerProp[j][SND_PCM_STREAM_CAPTURE].device & device) { 3334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mixer_info_t *info = mixerProp[j][SND_PCM_STREAM_CAPTURE].mInfo; 3354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (!info || !info->elem) return INVALID_OPERATION; 3364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev long minVol = info->min; 3384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev long maxVol = info->max; 3394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev // Make sure volume is between bounds. 3414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev long vol = minVol + gain * (maxVol - minVol); 3424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (vol > maxVol) vol = maxVol; 3434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (vol < minVol) vol = minVol; 3444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev info->volume = vol; 3464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_mixer_selem_set_capture_volume_all (info->elem, vol); 3474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return NO_ERROR; 3504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 3514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatus_t ALSAMixer::setCaptureMuteState(uint32_t device, bool state) 3534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 3544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev for (int j = 0; mixerProp[j][SND_PCM_STREAM_CAPTURE].device; j++) 3554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (mixerProp[j][SND_PCM_STREAM_CAPTURE].device & device) { 3564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mixer_info_t *info = mixerProp[j][SND_PCM_STREAM_CAPTURE].mInfo; 3584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (!info || !info->elem) return INVALID_OPERATION; 3594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (snd_mixer_selem_has_capture_switch (info->elem)) { 3614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev int err = snd_mixer_selem_set_capture_switch_all (info->elem, static_cast<int>(!state)); 3634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (err < 0) { 3644113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGE("Unable to %s capture mixer switch %s", 3654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev state ? "enable" : "disable", info->name); 3664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return INVALID_OPERATION; 3674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev info->mute = state; 3714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return NO_ERROR; 3744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 3754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatus_t ALSAMixer::getCaptureMuteState(uint32_t device, bool *state) 3774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 3784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (!state) return BAD_VALUE; 3794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev for (int j = 0; mixerProp[j][SND_PCM_STREAM_CAPTURE].device; j++) 3814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (mixerProp[j][SND_PCM_STREAM_CAPTURE].device & device) { 3824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mixer_info_t *info = mixerProp[j][SND_PCM_STREAM_CAPTURE].mInfo; 3844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (!info || !info->elem) return INVALID_OPERATION; 3854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev *state = info->mute; 3874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return NO_ERROR; 3884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return BAD_VALUE; 3914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 3924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatus_t ALSAMixer::setPlaybackMuteState(uint32_t device, bool state) 3944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 3954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev for (int j = 0; mixerProp[j][SND_PCM_STREAM_PLAYBACK].device; j++) 3964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (mixerProp[j][SND_PCM_STREAM_PLAYBACK].device & device) { 3974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mixer_info_t *info = mixerProp[j][SND_PCM_STREAM_PLAYBACK].mInfo; 3994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (!info || !info->elem) return INVALID_OPERATION; 4004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 4014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (snd_mixer_selem_has_playback_switch (info->elem)) { 4024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 4034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev int err = snd_mixer_selem_set_playback_switch_all (info->elem, static_cast<int>(!state)); 4044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (err < 0) { 4054113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGE("Unable to %s playback mixer switch %s", 4064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev state ? "enable" : "disable", info->name); 4074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return INVALID_OPERATION; 4084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 4094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 4104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 4114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev info->mute = state; 4124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 4134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 4144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return NO_ERROR; 4154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 4164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 4174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatus_t ALSAMixer::getPlaybackMuteState(uint32_t device, bool *state) 4184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 4194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (!state) return BAD_VALUE; 4204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 4214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev for (int j = 0; mixerProp[j][SND_PCM_STREAM_PLAYBACK].device; j++) 4224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (mixerProp[j][SND_PCM_STREAM_PLAYBACK].device & device) { 4234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 4244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mixer_info_t *info = mixerProp[j][SND_PCM_STREAM_PLAYBACK].mInfo; 4254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (!info || !info->elem) return INVALID_OPERATION; 4264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 4274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev *state = info->mute; 4284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return NO_ERROR; 4294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 4304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 4314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return BAD_VALUE; 4324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 4334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 4344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}; // namespace android 435