summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Laurent <elaurent@google.com>2009-07-17 12:17:14 -0700
committerEric Laurent <elaurent@google.com>2009-07-23 06:03:39 -0700
commitc2f1f07084818942352c6bbfb36af9b6b330eb4e (patch)
tree88ac93be41edadd8cbfe6448e1421d5165883f59
parenta64c8c79af1a15911c55306d83a797fa50969f77 (diff)
downloadframeworks_av-c2f1f07084818942352c6bbfb36af9b6b330eb4e.zip
frameworks_av-c2f1f07084818942352c6bbfb36af9b6b330eb4e.tar.gz
frameworks_av-c2f1f07084818942352c6bbfb36af9b6b330eb4e.tar.bz2
Fix issue 1795088 Improve audio routing code
Initial commit for review. Integrated comments after patch set 1 review. Fixed lockup in AudioFlinger::ThreadBase::exit() Fixed lockup when playing tone with AudioPlocyService startTone()
-rw-r--r--include/media/AudioRecord.h57
-rw-r--r--include/media/AudioSystem.h398
-rw-r--r--include/media/AudioTrack.h25
-rw-r--r--include/media/IAudioFlinger.h56
-rw-r--r--include/media/IAudioFlingerClient.h6
-rw-r--r--include/media/IAudioPolicyService.h90
-rw-r--r--include/private/media/AudioTrackShared.h13
-rw-r--r--media/libmedia/Android.mk3
-rw-r--r--media/libmedia/AudioRecord.cpp90
-rw-r--r--media/libmedia/AudioSystem.cpp742
-rw-r--r--media/libmedia/AudioTrack.cpp189
-rw-r--r--media/libmedia/IAudioFlinger.cpp382
-rw-r--r--media/libmedia/IAudioFlingerClient.cpp45
-rw-r--r--media/libmedia/IAudioPolicyService.cpp423
-rw-r--r--media/libmedia/JetPlayer.cpp2
-rw-r--r--media/libmedia/ToneGenerator.cpp2
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.cpp16
-rw-r--r--media/mediaserver/main_mediaserver.cpp2
18 files changed, 2080 insertions, 461 deletions
diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h
index 83ff508..503cb31 100644
--- a/include/media/AudioRecord.h
+++ b/include/media/AudioRecord.h
@@ -39,21 +39,10 @@ class AudioRecord
{
public:
- // input sources values must always be defined in the range
- // [AudioRecord::DEFAULT_INPUT, AudioRecord::NUM_INPUT_SOURCES[
- enum input_source {
- DEFAULT_INPUT =-1,
- MIC_INPUT = 0,
- VOICE_UPLINK_INPUT = 1,
- VOICE_DOWNLINK_INPUT = 2,
- VOICE_CALL_INPUT = 3,
- NUM_INPUT_SOURCES
- };
-
static const int DEFAULT_SAMPLE_RATE = 8000;
/* Events used by AudioRecord callback function (callback_t).
- *
+ *
* to keep in sync with frameworks/base/media/java/android/media/AudioRecord.java
*/
enum event_type {
@@ -61,7 +50,7 @@ public:
EVENT_OVERRUN = 1, // PCM buffer overrun occured.
EVENT_MARKER = 2, // Record head is at the specified marker position
// (See setMarkerPosition()).
- EVENT_NEW_POS = 3, // Record head is at a new position
+ EVENT_NEW_POS = 3, // Record head is at a new position
// (See setPositionUpdatePeriod()).
};
@@ -123,11 +112,11 @@ public:
*
* Parameters:
*
- * inputSource: Select the audio input to record to (e.g. AudioRecord::MIC_INPUT).
+ * inputSource: Select the audio input to record to (e.g. AUDIO_SOURCE_DEFAULT).
* sampleRate: Track sampling rate in Hz.
- * format: PCM sample format (e.g AudioSystem::PCM_16_BIT for signed
+ * format: Audio format (e.g AudioSystem::PCM_16_BIT for signed
* 16 bits per sample).
- * channelCount: Number of PCM channels (e.g 2 for stereo).
+ * channels: Channel mask: see AudioSystem::audio_channels.
* frameCount: Total size of track PCM buffer in frames. This defines the
* latency of the track.
* flags: A bitmask of acoustic values from enum record_flags. It enables
@@ -148,7 +137,7 @@ public:
AudioRecord(int inputSource,
uint32_t sampleRate = 0,
int format = 0,
- int channelCount = 0,
+ uint32_t channels = AudioSystem::CHANNEL_IN_MONO,
int frameCount = 0,
uint32_t flags = 0,
callback_t cbf = 0,
@@ -166,14 +155,14 @@ public:
* Returned status (from utils/Errors.h) can be:
* - NO_ERROR: successful intialization
* - INVALID_OPERATION: AudioRecord is already intitialized or record device is already in use
- * - BAD_VALUE: invalid parameter (channelCount, format, sampleRate...)
+ * - BAD_VALUE: invalid parameter (channels, format, sampleRate...)
* - NO_INIT: audio server or audio hardware not initialized
* - PERMISSION_DENIED: recording is not allowed for the requesting process
* */
status_t set(int inputSource = 0,
uint32_t sampleRate = 0,
int format = 0,
- int channelCount = 0,
+ uint32_t channels = AudioSystem::CHANNEL_IN_MONO,
int frameCount = 0,
uint32_t flags = 0,
callback_t cbf = 0,
@@ -199,6 +188,7 @@ public:
int format() const;
int channelCount() const;
+ int channels() const;
uint32_t frameCount() const;
int frameSize() const;
int inputSource() const;
@@ -222,8 +212,8 @@ public:
/* Sets marker position. When record reaches the number of frames specified,
* a callback with event type EVENT_MARKER is called. Calling setMarkerPosition
- * with marker == 0 cancels marker notification callback.
- * If the AudioRecord has been opened with no callback function associated,
+ * with marker == 0 cancels marker notification callback.
+ * If the AudioRecord has been opened with no callback function associated,
* the operation will fail.
*
* Parameters:
@@ -238,10 +228,10 @@ public:
status_t getMarkerPosition(uint32_t *marker);
- /* Sets position update period. Every time the number of frames specified has been recorded,
- * a callback with event type EVENT_NEW_POS is called.
- * Calling setPositionUpdatePeriod with updatePeriod == 0 cancels new position notification
- * callback.
+ /* Sets position update period. Every time the number of frames specified has been recorded,
+ * a callback with event type EVENT_NEW_POS is called.
+ * Calling setPositionUpdatePeriod with updatePeriod == 0 cancels new position notification
+ * callback.
* If the AudioRecord has been opened with no callback function associated,
* the operation will fail.
*
@@ -257,8 +247,8 @@ public:
status_t getPositionUpdatePeriod(uint32_t *updatePeriod);
- /* Gets record head position. The position is the total number of frames
- * recorded since record start.
+ /* Gets record head position. The position is the total number of frames
+ * recorded since record start.
*
* Parameters:
*
@@ -270,8 +260,16 @@ public:
*/
status_t getPosition(uint32_t *position);
-
-
+ /* returns a handle on the audio input used by this AudioRecord.
+ *
+ * Parameters:
+ * none.
+ *
+ * Returned value:
+ * handle on audio hardware input
+ */
+ audio_io_handle_t getInput() { return mInput; }
+
/* obtains a buffer of "frameCount" frames. The buffer must be
* filled entirely. If the track is stopped, obtainBuffer() returns
* STOPPED instead of NO_ERROR as long as there are buffers availlable,
@@ -342,6 +340,7 @@ private:
bool mMarkerReached;
uint32_t mNewPosition;
uint32_t mUpdatePeriod;
+ audio_io_handle_t mInput;
};
}; // namespace android
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index 3a3a714..0ea04a4 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -24,36 +24,130 @@
namespace android {
typedef void (*audio_error_callback)(status_t err);
+typedef void * audio_io_handle_t;
+
+class IAudioPolicyService;
+class String8;
class AudioSystem
{
public:
enum stream_type {
- DEFAULT =-1,
- VOICE_CALL = 0,
- SYSTEM = 1,
- RING = 2,
- MUSIC = 3,
- ALARM = 4,
- NOTIFICATION = 5,
- BLUETOOTH_SCO = 6,
+ DEFAULT =-1,
+ VOICE_CALL = 0,
+ SYSTEM = 1,
+ RING = 2,
+ MUSIC = 3,
+ ALARM = 4,
+ NOTIFICATION = 5,
+ BLUETOOTH_SCO = 6,
ENFORCED_AUDIBLE = 7, // Sounds that cannot be muted by user and must be routed to speaker
+ DTMF = 8,
+ TTS = 9,
NUM_STREAM_TYPES
};
- enum audio_output_type {
- AUDIO_OUTPUT_DEFAULT =-1,
- AUDIO_OUTPUT_HARDWARE = 0,
- AUDIO_OUTPUT_A2DP = 1,
- NUM_AUDIO_OUTPUT_TYPES
+ // Audio sub formats (see AudioSystem::audio_format).
+ enum pcm_sub_format {
+ PCM_SUB_16_BIT = 0x1, // must be 1 for backward compatibility
+ PCM_SUB_8_BIT = 0x2, // must be 2 for backward compatibility
+ };
+
+ // MP3 sub format field definition : can use 11 LSBs in the same way as MP3 frame header to specify
+ // bit rate, stereo mode, version...
+ enum mp3_sub_format {
+ //TODO
+ };
+
+ // AMR NB/WB sub format field definition: specify frame block interleaving, bandwidth efficient or octet aligned,
+ // encoding mode for recording...
+ enum amr_sub_format {
+ //TODO
+ };
+
+ // AAC sub format field definition: specify profile or bitrate for recording...
+ enum aac_sub_format {
+ //TODO
};
+ // VORBIS sub format field definition: specify quality for recording...
+ enum vorbis_sub_format {
+ //TODO
+ };
+
+ // Audio format consists in a main format field (upper 8 bits) and a sub format field (lower 24 bits).
+ // The main format indicates the main codec type. The sub format field indicates options and parameters
+ // for each format. The sub format is mainly used for record to indicate for instance the requested bitrate
+ // or profile. It can also be used for certain formats to give informations not present in the encoded
+ // audio stream (e.g. octet alignement for AMR).
enum audio_format {
- FORMAT_DEFAULT = 0,
- PCM_16_BIT,
- PCM_8_BIT,
- INVALID_FORMAT
+ INVALID_FORMAT = -1,
+ FORMAT_DEFAULT = 0,
+ PCM = 0x00000000, // must be 0 for backward compatibility
+ MP3 = 0x01000000,
+ AMR_NB = 0x02000000,
+ AMR_WB = 0x03000000,
+ AAC = 0x04000000,
+ HE_AAC_V1 = 0x05000000,
+ HE_AAC_V2 = 0x06000000,
+ VORBIS = 0x07000000,
+ MAIN_FORMAT_MASK = 0xFF000000,
+ SUB_FORMAT_MASK = 0x00FFFFFF,
+ // Aliases
+ PCM_16_BIT = (PCM|PCM_SUB_16_BIT),
+ PCM_8_BIT = (PCM|PCM_SUB_8_BIT)
+ };
+
+
+ // Channel mask definitions must be kept in sync with JAVA values in /media/java/android/media/AudioFormat.java
+ enum audio_channels {
+ // output channels
+ CHANNEL_OUT_FRONT_LEFT = 0x1,
+ CHANNEL_OUT_FRONT_RIGHT = 0x2,
+ CHANNEL_OUT_FRONT_CENTER = 0x4,
+ CHANNEL_OUT_LOW_FREQUENCY = 0x8,
+ CHANNEL_OUT_BACK_LEFT = 0x10,
+ CHANNEL_OUT_BACK_RIGHT = 0x20,
+ CHANNEL_OUT_FRONT_LEFT_OF_CENTER = 0x40,
+ CHANNEL_OUT_FRONT_RIGHT_OF_CENTER = 0x80,
+ CHANNEL_OUT_BACK_CENTER = 0x100,
+ CHANNEL_OUT_MONO = CHANNEL_OUT_FRONT_LEFT,
+ CHANNEL_OUT_STEREO = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT),
+ CHANNEL_OUT_QUAD = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
+ CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT),
+ CHANNEL_OUT_SURROUND = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
+ CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_BACK_CENTER),
+ CHANNEL_OUT_5POINT1 = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
+ CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT),
+ CHANNEL_OUT_7POINT1 = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
+ CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT |
+ CHANNEL_OUT_FRONT_LEFT_OF_CENTER | CHANNEL_OUT_FRONT_RIGHT_OF_CENTER),
+ CHANNEL_OUT_ALL = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
+ CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT |
+ CHANNEL_OUT_FRONT_LEFT_OF_CENTER | CHANNEL_OUT_FRONT_RIGHT_OF_CENTER | CHANNEL_OUT_BACK_CENTER),
+
+ // input channels
+ CHANNEL_IN_LEFT = 0x10000,
+ CHANNEL_IN_RIGHT = 0x20000,
+ CHANNEL_IN_FRONT = 0x40000,
+ CHANNEL_IN_BACK = 0x80000,
+ CHANNEL_IN_LEFT_PROCESSED = 0x100000,
+ CHANNEL_IN_RIGHT_PROCESSED = 0x200000,
+ CHANNEL_IN_FRONT_PROCESSED = 0x400000,
+ CHANNEL_IN_BACK_PROCESSED = 0x800000,
+ CHANNEL_IN_PRESSURE = 0x1000000,
+ CHANNEL_IN_X_AXIS = 0x2000000,
+ CHANNEL_IN_Y_AXIS = 0x4000000,
+ CHANNEL_IN_Z_AXIS = 0x8000000,
+ CHANNEL_IN_VOICE_UPLINK = 0x10000000,
+ CHANNEL_IN_VOICE_DNLINK = 0x20000000,
+ CHANNEL_IN_MONO = CHANNEL_IN_FRONT,
+ CHANNEL_IN_STEREO = (CHANNEL_IN_LEFT | CHANNEL_IN_RIGHT),
+ CHANNEL_IN_ALL = (CHANNEL_IN_LEFT | CHANNEL_IN_RIGHT | CHANNEL_IN_FRONT | CHANNEL_IN_BACK|
+ CHANNEL_IN_LEFT_PROCESSED | CHANNEL_IN_RIGHT_PROCESSED | CHANNEL_IN_FRONT_PROCESSED | CHANNEL_IN_BACK_PROCESSED|
+ CHANNEL_IN_PRESSURE | CHANNEL_IN_X_AXIS | CHANNEL_IN_Y_AXIS | CHANNEL_IN_Z_AXIS |
+ CHANNEL_IN_VOICE_UPLINK | CHANNEL_IN_VOICE_DNLINK)
};
enum audio_mode {
@@ -65,15 +159,6 @@ public:
NUM_MODES // not a valid entry, denotes end-of-list
};
- enum audio_routes {
- ROUTE_EARPIECE = (1 << 0),
- ROUTE_SPEAKER = (1 << 1),
- ROUTE_BLUETOOTH_SCO = (1 << 2),
- ROUTE_HEADSET = (1 << 3),
- ROUTE_BLUETOOTH_A2DP = (1 << 4),
- ROUTE_ALL = -1UL,
- };
-
enum audio_in_acoustics {
AGC_ENABLE = 0x0001,
AGC_DISABLE = 0,
@@ -87,36 +172,37 @@ public:
* only privileged processes can have access to them
*/
- // routing helper functions
- static status_t speakerphone(bool state);
- static status_t isSpeakerphoneOn(bool* state);
- static status_t bluetoothSco(bool state);
- static status_t isBluetoothScoOn(bool* state);
+ // mute/unmute microphone
static status_t muteMicrophone(bool state);
static status_t isMicrophoneMuted(bool *state);
+ // set/get master volume
static status_t setMasterVolume(float value);
- static status_t setMasterMute(bool mute);
static status_t getMasterVolume(float* volume);
+ // mute/unmute audio outputs
+ static status_t setMasterMute(bool mute);
static status_t getMasterMute(bool* mute);
- static status_t setStreamVolume(int stream, float value);
+ // set/get stream volume on specified output
+ static status_t setStreamVolume(int stream, float value, void *output);
+ static status_t getStreamVolume(int stream, float* volume, void *output);
+
+ // mute/unmute stream
static status_t setStreamMute(int stream, bool mute);
- static status_t getStreamVolume(int stream, float* volume);
static status_t getStreamMute(int stream, bool* mute);
+ // set audio mode in audio hardware (see AudioSystem::audio_mode)
static status_t setMode(int mode);
- static status_t getMode(int* mode);
-
- static status_t setRouting(int mode, uint32_t routes, uint32_t mask);
- static status_t getRouting(int mode, uint32_t* routes);
+ // returns true if tracks are active on AudioSystem::MUSIC stream
static status_t isMusicActive(bool *state);
- // Temporary interface, do not use
- // TODO: Replace with a more generic key:value get/set mechanism
- static status_t setParameter(const char* key, const char* value);
-
+ // set/get audio hardware parameters. The function accepts a list of parameters
+ // key value pairs in the form: key1=value1;key2=value2;...
+ // Some keys are reserved for standard parameters (See AudioParameter class).
+ static status_t setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs);
+ static String8 getParameters(audio_io_handle_t ioHandle, const String8& keys);
+
static void setErrorCallback(audio_error_callback cb);
// helper function to obtain AudioFlinger service handle
@@ -130,47 +216,247 @@ public:
static status_t getOutputLatency(uint32_t* latency, int stream = DEFAULT);
static bool routedToA2dpOutput(int streamType);
-
- static status_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount,
+
+ static status_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount,
size_t* buffSize);
+
+ //
+ // AudioPolicyService interface
+ //
+
+ enum audio_devices {
+ // output devices
+ DEVICE_OUT_EARPIECE = 0x1,
+ DEVICE_OUT_SPEAKER = 0x2,
+ DEVICE_OUT_WIRED_HEADSET = 0x4,
+ DEVICE_OUT_WIRED_HEADPHONE = 0x8,
+ DEVICE_OUT_BLUETOOTH_SCO = 0x10,
+ DEVICE_OUT_BLUETOOTH_SCO_HEADSET = 0x20,
+ DEVICE_OUT_BLUETOOTH_SCO_CARKIT = 0x40,
+ DEVICE_OUT_BLUETOOTH_A2DP = 0x80,
+ DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100,
+ DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 0x200,
+ DEVICE_OUT_AUX_DIGITAL = 0x400,
+ DEVICE_OUT_FM_HEADPHONE = 0x800,
+ DEVICE_OUT_FM_SPEAKER = 0x1000,
+ DEVICE_OUT_TTY = 0x2000,
+ DEVICE_OUT_DEFAULT = 0x8000,
+ DEVICE_OUT_ALL = (DEVICE_OUT_EARPIECE | DEVICE_OUT_SPEAKER | DEVICE_OUT_WIRED_HEADSET |
+ DEVICE_OUT_WIRED_HEADPHONE | DEVICE_OUT_BLUETOOTH_SCO | DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
+ DEVICE_OUT_BLUETOOTH_SCO_CARKIT | DEVICE_OUT_BLUETOOTH_A2DP | DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
+ DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER | DEVICE_OUT_AUX_DIGITAL | DEVICE_OUT_FM_HEADPHONE |
+ DEVICE_OUT_FM_SPEAKER | DEVICE_OUT_TTY | DEVICE_OUT_DEFAULT),
+
+ // input devices
+ DEVICE_IN_COMMUNICATION = 0x10000,
+ DEVICE_IN_AMBIENT = 0x20000,
+ DEVICE_IN_BUILTIN_MIC = 0x40000,
+ DEVICE_IN_BLUETOOTH_SCO_HEADSET = 0x80000,
+ DEVICE_IN_WIRED_HEADSET = 0x100000,
+ DEVICE_IN_AUX_DIGITAL = 0x200000,
+ DEVICE_IN_VOICE_CALL = 0x400000,
+ DEVICE_IN_DEFAULT = 0x80000000,
+
+ DEVICE_IN_ALL = (DEVICE_IN_COMMUNICATION | DEVICE_IN_AMBIENT | DEVICE_IN_BUILTIN_MIC |
+ DEVICE_IN_BLUETOOTH_SCO_HEADSET | DEVICE_IN_WIRED_HEADSET | DEVICE_IN_AUX_DIGITAL |
+ DEVICE_IN_VOICE_CALL| DEVICE_IN_DEFAULT)
+ };
+
+ // device connection states used for setDeviceConnectionState()
+ enum device_connection_state {
+ DEVICE_STATE_UNAVAILABLE,
+ DEVICE_STATE_AVAILABLE,
+ NUM_DEVICE_STATES
+ };
+
+ // request to open a direct output with getOutput() (by opposition to sharing an output with other AudioTracks)
+ enum output_flags {
+ OUTPUT_FLAG_INDIRECT = 0x0,
+ OUTPUT_FLAG_DIRECT = 0x1
+ };
+
+ // device categories used for setForceUse()
+ enum forced_config {
+ FORCE_NONE,
+ FORCE_SPEAKER,
+ FORCE_HEADPHONES,
+ FORCE_BT_SCO,
+ FORCE_BT_A2DP,
+ FORCE_WIRED_ACCESSORY,
+ NUM_FORCE_CONFIG,
+ FORCE_DEFAULT = FORCE_NONE
+ };
+
+ // usages used for setForceUse()
+ enum force_use {
+ FOR_COMMUNICATION,
+ FOR_MEDIA,
+ FOR_RECORD,
+ NUM_FORCE_USE
+ };
+
+ // types of io configuration change events received with ioConfigChanged()
+ enum io_config_event {
+ OUTPUT_OPENED,
+ OUTPUT_CLOSED,
+ OUTPUT_CONFIG_CHANGED,
+ INPUT_OPENED,
+ INPUT_CLOSED,
+ INPUT_CONFIG_CHANGED,
+ STREAM_CONFIG_CHANGED,
+ NUM_CONFIG_EVENTS
+ };
+
+ // audio output descritor used to cache output configurations in client process to avoid frequent calls
+ // through IAudioFlinger
+ class OutputDescriptor {
+ public:
+ OutputDescriptor()
+ : samplingRate(0), format(0), channels(0), frameCount(0), latency(0) {}
+
+ uint32_t samplingRate;
+ int32_t format;
+ int32_t channels;
+ size_t frameCount;
+ uint32_t latency;
+ };
+
+ //
+ // IAudioPolicyService interface (see AudioPolicyInterface for method descriptions)
+ //
+ static status_t setDeviceConnectionState(audio_devices device, device_connection_state state, const char *device_address);
+ static device_connection_state getDeviceConnectionState(audio_devices device, const char *device_address);
+ static status_t setPhoneState(int state);
+ static status_t setRingerMode(uint32_t mode, uint32_t mask);
+ static status_t setForceUse(force_use usage, forced_config config);
+ static forced_config getForceUse(force_use usage);
+ static audio_io_handle_t getOutput(stream_type stream,
+ uint32_t samplingRate = 0,
+ uint32_t format = FORMAT_DEFAULT,
+ uint32_t channels = CHANNEL_OUT_STEREO,
+ output_flags flags = OUTPUT_FLAG_INDIRECT);
+ static status_t startOutput(audio_io_handle_t output, AudioSystem::stream_type stream);
+ static status_t stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream);
+ static void releaseOutput(audio_io_handle_t output);
+ static audio_io_handle_t getInput(int inputSource,
+ uint32_t samplingRate = 0,
+ uint32_t format = FORMAT_DEFAULT,
+ uint32_t channels = CHANNEL_IN_MONO,
+ audio_in_acoustics acoustics = (audio_in_acoustics)0);
+ static status_t startInput(audio_io_handle_t input);
+ static status_t stopInput(audio_io_handle_t input);
+ static void releaseInput(audio_io_handle_t input);
+ static status_t initStreamVolume(stream_type stream,
+ int indexMin,
+ int indexMax);
+ static status_t setStreamVolumeIndex(stream_type stream, int index);
+ static status_t getStreamVolumeIndex(stream_type stream, int *index);
+
+ static const sp<IAudioPolicyService>& get_audio_policy_service();
+
// ----------------------------------------------------------------------------
+ static uint32_t popCount(uint32_t u);
+ static bool isOutputDevice(audio_devices device);
+ static bool isInputDevice(audio_devices device);
+ static bool isA2dpDevice(audio_devices device);
+ static bool isBluetoothScoDevice(audio_devices device);
+ static bool isLowVisibility(stream_type stream);
+ static bool isOutputChannel(uint32_t channel);
+ static bool isInputChannel(uint32_t channel);
+ static bool isValidFormat(uint32_t format);
+ static bool isLinearPCM(uint32_t format);
+
private:
class AudioFlingerClient: public IBinder::DeathRecipient, public BnAudioFlingerClient
{
public:
- AudioFlingerClient() {
+ AudioFlingerClient() {
}
-
+
// DeathRecipient
virtual void binderDied(const wp<IBinder>& who);
-
+
// IAudioFlingerClient
- virtual void a2dpEnabledChanged(bool enabled);
-
+
+ // indicate a change in the configuration of an output or input: keeps the cached
+ // values for output/input parameters upto date in client process
+ virtual void ioConfigChanged(int event, void *param1, void *param2);
};
- static int getOutput(int streamType);
- static sp<AudioFlingerClient> gAudioFlingerClient;
+ class AudioPolicyServiceClient: public IBinder::DeathRecipient
+ {
+ public:
+ AudioPolicyServiceClient() {
+ }
+ // DeathRecipient
+ virtual void binderDied(const wp<IBinder>& who);
+ };
+
+ static sp<AudioFlingerClient> gAudioFlingerClient;
+ static sp<AudioPolicyServiceClient> gAudioPolicyServiceClient;
friend class AudioFlingerClient;
+ friend class AudioPolicyServiceClient;
static Mutex gLock;
static sp<IAudioFlinger> gAudioFlinger;
static audio_error_callback gAudioErrorCallback;
- static int gOutSamplingRate[NUM_AUDIO_OUTPUT_TYPES];
- static int gOutFrameCount[NUM_AUDIO_OUTPUT_TYPES];
- static uint32_t gOutLatency[NUM_AUDIO_OUTPUT_TYPES];
- static bool gA2dpEnabled;
-
+
static size_t gInBuffSize;
// previous parameters for recording buffer size queries
static uint32_t gPrevInSamplingRate;
static int gPrevInFormat;
static int gPrevInChannelCount;
+ static sp<IAudioPolicyService> gAudioPolicyService;
+
+ // mapping between stream types and outputs
+ static DefaultKeyedVector<int, audio_io_handle_t> gStreamOutputMap;
+ // list of output descritor containing cached parameters (sampling rate, framecount, channel count...)
+ static DefaultKeyedVector<audio_io_handle_t, OutputDescriptor *> gOutputs;
+};
+
+class AudioParameter {
+
+public:
+ AudioParameter() {}
+ AudioParameter(const String8& keyValuePairs);
+ virtual ~AudioParameter();
+
+ // reserved parameter keys for changeing standard parameters with setParameters() function.
+ // Using these keys is mandatory for AudioFlinger to properly monitor audio output/input
+ // configuration changes and act accordingly.
+ // keyRouting: to change audio routing, value is an int in AudioSystem::audio_devices
+ // keySamplingRate: to change sampling rate routing, value is an int
+ // keyFormat: to change audio format, value is an int in AudioSystem::audio_format
+ // keyChannels: to change audio channel configuration, value is an int in AudioSystem::audio_channels
+ // keyFrameCount: to change audio output frame count, value is an int
+ static const char *keyRouting;
+ static const char *keySamplingRate;
+ static const char *keyFormat;
+ static const char *keyChannels;
+ static const char *keyFrameCount;
+
+ String8 toString();
+
+ status_t add(const String8& key, const String8& value);
+ status_t addInt(const String8& key, const int value);
+ status_t addFloat(const String8& key, const float value);
+
+ status_t remove(const String8& key);
+
+ status_t get(const String8& key, String8& value);
+ status_t getInt(const String8& key, int& value);
+ status_t getFloat(const String8& key, float& value);
+
+ size_t size() { return mParameters.size(); }
+
+private:
+ String8 mKeyValuePairs;
+ KeyedVector <String8, String8> mParameters;
};
}; // namespace android
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index 2e1fbda..981c2f6 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -117,9 +117,9 @@ public:
* streamType: Select the type of audio stream this track is attached to
* (e.g. AudioSystem::MUSIC).
* sampleRate: Track sampling rate in Hz.
- * format: PCM sample format (e.g AudioSystem::PCM_16_BIT for signed
+ * format: Audio format (e.g AudioSystem::PCM_16_BIT for signed
* 16 bits per sample).
- * channelCount: Number of PCM channels (e.g 2 for stereo).
+ * channels: Channel mask: see AudioSystem::audio_channels.
* frameCount: Total size of track PCM buffer in frames. This defines the
* latency of the track.
* flags: Reserved for future use.
@@ -133,7 +133,7 @@ public:
AudioTrack( int streamType,
uint32_t sampleRate = 0,
int format = 0,
- int channelCount = 0,
+ int channels = 0,
int frameCount = 0,
uint32_t flags = 0,
callback_t cbf = 0,
@@ -152,7 +152,7 @@ public:
AudioTrack( int streamType,
uint32_t sampleRate = 0,
int format = 0,
- int channelCount = 0,
+ int channels = 0,
const sp<IMemory>& sharedBuffer = 0,
uint32_t flags = 0,
callback_t cbf = 0,
@@ -169,13 +169,13 @@ public:
* Returned status (from utils/Errors.h) can be:
* - NO_ERROR: successful intialization
* - INVALID_OPERATION: AudioTrack is already intitialized
- * - BAD_VALUE: invalid parameter (channelCount, format, sampleRate...)
+ * - BAD_VALUE: invalid parameter (channels, format, sampleRate...)
* - NO_INIT: audio server or audio hardware not initialized
* */
status_t set(int streamType =-1,
uint32_t sampleRate = 0,
int format = 0,
- int channelCount = 0,
+ int channels = 0,
int frameCount = 0,
uint32_t flags = 0,
callback_t cbf = 0,
@@ -330,6 +330,16 @@ public:
*/
status_t reload();
+ /* returns a handle on the audio output used by this AudioTrack.
+ *
+ * Parameters:
+ * none.
+ *
+ * Returned value:
+ * handle on audio hardware output
+ */
+ audio_io_handle_t getOutput();
+
/* obtains a buffer of "frameCount" frames. The buffer must be
* filled entirely. If the track is stopped, obtainBuffer() returns
* STOPPED instead of NO_ERROR as long as there are buffers availlable,
@@ -387,7 +397,6 @@ private:
sp<AudioTrackThread> mAudioTrackThread;
float mVolume[2];
- uint32_t mSampleRate;
uint32_t mFrameCount;
audio_track_cblk_t* mCblk;
@@ -395,6 +404,7 @@ private:
uint8_t mFormat;
uint8_t mChannelCount;
uint8_t mMuted;
+ uint32_t mChannels;
status_t mStatus;
uint32_t mLatency;
@@ -410,6 +420,7 @@ private:
bool mMarkerReached;
uint32_t mNewPosition;
uint32_t mUpdatePeriod;
+ uint32_t mFlags;
};
diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h
index bac3d29..26e6972 100644
--- a/include/media/IAudioFlinger.h
+++ b/include/media/IAudioFlinger.h
@@ -27,7 +27,7 @@
#include <media/IAudioTrack.h>
#include <media/IAudioRecord.h>
#include <media/IAudioFlingerClient.h>
-
+#include <utils/String8.h>
namespace android {
@@ -50,11 +50,12 @@ public:
int frameCount,
uint32_t flags,
const sp<IMemory>& sharedBuffer,
+ void *output,
status_t *status) = 0;
virtual sp<IAudioRecord> openRecord(
pid_t pid,
- int inputSource,
+ void *input,
uint32_t sampleRate,
int format,
int channelCount,
@@ -65,11 +66,11 @@ public:
/* query the audio hardware state. This state never changes,
* and therefore can be cached.
*/
- virtual uint32_t sampleRate(int output) const = 0;
- virtual int channelCount(int output) const = 0;
- virtual int format(int output) const = 0;
- virtual size_t frameCount(int output) const = 0;
- virtual uint32_t latency(int output) const = 0;
+ virtual uint32_t sampleRate(void *output) const = 0;
+ virtual int channelCount(void *output) const = 0;
+ virtual int format(void *output) const = 0;
+ virtual size_t frameCount(void *output) const = 0;
+ virtual uint32_t latency(void *output) const = 0;
/* set/get the audio hardware state. This will probably be used by
* the preference panel, mostly.
@@ -83,19 +84,14 @@ public:
/* set/get stream type state. This will probably be used by
* the preference panel, mostly.
*/
- virtual status_t setStreamVolume(int stream, float value) = 0;
+ virtual status_t setStreamVolume(int stream, float value, void *output) = 0;
virtual status_t setStreamMute(int stream, bool muted) = 0;
- virtual float streamVolume(int stream) const = 0;
+ virtual float streamVolume(int stream, void *output) const = 0;
virtual bool streamMute(int stream) const = 0;
- // set/get audio routing
- virtual status_t setRouting(int mode, uint32_t routes, uint32_t mask) = 0;
- virtual uint32_t getRouting(int mode) const = 0;
-
- // set/get audio mode
+ // set audio mode
virtual status_t setMode(int mode) = 0;
- virtual int getMode() const = 0;
// mic mute/state
virtual status_t setMicMute(bool state) = 0;
@@ -104,22 +100,34 @@ public:
// is a music stream active?
virtual bool isMusicActive() const = 0;
- // pass a generic configuration parameter to libaudio
- // Temporary interface, do not use
- // TODO: Replace with a more generic key:value get/set mechanism
- virtual status_t setParameter(const char* key, const char* value) = 0;
+ virtual status_t setParameters(void *ioHandle, const String8& keyValuePairs) = 0;
+ virtual String8 getParameters(void *ioHandle, const String8& keys) = 0;
// register a current process for audio output change notifications
virtual void registerClient(const sp<IAudioFlingerClient>& client) = 0;
// retrieve the audio recording buffer size
virtual size_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount) = 0;
-
- // force AudioFlinger thread out of standby
- virtual void wakeUp() = 0;
- // is A2DP output enabled
- virtual bool isA2dpEnabled() const = 0;
+ virtual void *openOutput(uint32_t *pDevices,
+ uint32_t *pSamplingRate,
+ uint32_t *pFormat,
+ uint32_t *pChannels,
+ uint32_t *pLatencyMs,
+ uint32_t flags) = 0;
+ virtual void *openDuplicateOutput(void *output1, void *output2) = 0;
+ virtual status_t closeOutput(void *output) = 0;
+ virtual status_t suspendOutput(void *output) = 0;
+ virtual status_t restoreOutput(void *output) = 0;
+
+ virtual void *openInput(uint32_t *pDevices,
+ uint32_t *pSamplingRate,
+ uint32_t *pFormat,
+ uint32_t *pChannels,
+ uint32_t acoustics) = 0;
+ virtual status_t closeInput(void *input) = 0;
+
+ virtual status_t setStreamOutput(uint32_t stream, void *output) = 0;
};
diff --git a/include/media/IAudioFlingerClient.h b/include/media/IAudioFlingerClient.h
index 383ec0c..78142ce 100644
--- a/include/media/IAudioFlingerClient.h
+++ b/include/media/IAudioFlingerClient.h
@@ -20,7 +20,7 @@
#include <utils/RefBase.h>
#include <binder/IInterface.h>
-
+#include <utils/KeyedVector.h>
namespace android {
@@ -31,8 +31,8 @@ class IAudioFlingerClient : public IInterface
public:
DECLARE_META_INTERFACE(AudioFlingerClient);
- // Notifies a change of audio output from/to hardware to/from A2DP.
- virtual void a2dpEnabledChanged(bool enabled) = 0;
+ // Notifies a change of audio input/output configuration.
+ virtual void ioConfigChanged(int event, void *param1, void *param2) = 0;
};
diff --git a/include/media/IAudioPolicyService.h b/include/media/IAudioPolicyService.h
new file mode 100644
index 0000000..4804bbd
--- /dev/null
+++ b/include/media/IAudioPolicyService.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_IAUDIOPOLICYSERVICE_H
+#define ANDROID_IAUDIOPOLICYSERVICE_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <utils/RefBase.h>
+#include <utils/Errors.h>
+#include <binder/IInterface.h>
+#include <media/AudioSystem.h>
+
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+class IAudioPolicyService : public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(AudioPolicyService);
+
+ //
+ // IAudioPolicyService interface (see AudioPolicyInterface for method descriptions)
+ //
+ virtual status_t setDeviceConnectionState(AudioSystem::audio_devices device,
+ AudioSystem::device_connection_state state,
+ const char *device_address) = 0;
+ virtual AudioSystem::device_connection_state getDeviceConnectionState(AudioSystem::audio_devices device,
+ const char *device_address) = 0;
+ virtual status_t setPhoneState(int state) = 0;
+ virtual status_t setRingerMode(uint32_t mode, uint32_t mask) = 0;
+ virtual status_t setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config) = 0;
+ virtual AudioSystem::forced_config getForceUse(AudioSystem::force_use usage) = 0;
+ virtual audio_io_handle_t getOutput(AudioSystem::stream_type stream,
+ uint32_t samplingRate = 0,
+ uint32_t format = AudioSystem::FORMAT_DEFAULT,
+ uint32_t channels = 0,
+ AudioSystem::output_flags flags = AudioSystem::OUTPUT_FLAG_INDIRECT) = 0;
+ virtual status_t startOutput(audio_io_handle_t output, AudioSystem::stream_type stream) = 0;
+ virtual status_t stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream) = 0;
+ virtual void releaseOutput(audio_io_handle_t output) = 0;
+ virtual audio_io_handle_t getInput(int inputSource,
+ uint32_t samplingRate = 0,
+ uint32_t format = AudioSystem::FORMAT_DEFAULT,
+ uint32_t channels = 0,
+ AudioSystem::audio_in_acoustics acoustics = (AudioSystem::audio_in_acoustics)0) = 0;
+ virtual status_t startInput(audio_io_handle_t input) = 0;
+ virtual status_t stopInput(audio_io_handle_t input) = 0;
+ virtual void releaseInput(audio_io_handle_t input) = 0;
+ virtual status_t initStreamVolume(AudioSystem::stream_type stream,
+ int indexMin,
+ int indexMax) = 0;
+ virtual status_t setStreamVolumeIndex(AudioSystem::stream_type stream, int index) = 0;
+ virtual status_t getStreamVolumeIndex(AudioSystem::stream_type stream, int *index) = 0;
+};
+
+
+// ----------------------------------------------------------------------------
+
+class BnAudioPolicyService : public BnInterface<IAudioPolicyService>
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_IAUDIOPOLICYSERVICE_H
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index 496a739..8e2db20 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -55,17 +55,18 @@ struct audio_track_cblk_t
uint32_t volumeLR;
};
uint32_t sampleRate;
+ // NOTE: audio_track_cblk_t::frameSize is not equal to AudioTrack::frameSize() for
+ // 8 bit PCM data: in this case, mCblk->frameSize is based on a sample size of
+ // 16 bit because data is converted to 16 bit before being stored in buffer
+ uint32_t frameSize;
uint8_t channels;
uint8_t flowControlFlag; // underrun (out) or overrrun (in) indication
uint8_t out; // out equals 1 for AudioTrack and 0 for AudioRecord
- uint8_t forceReady;
+ uint8_t forceReady;
uint16_t bufferTimeoutMs; // Maximum cumulated timeout before restarting audioflinger
uint16_t waitTimeMs; // Cumulated wait time
- // Padding ensuring that data buffer starts on a cache line boundary (32 bytes).
- // See AudioFlinger::TrackBase constructor
- int32_t Padding[1];
- // Cache line boundary
-
+ // Cache line boundary (32 bytes)
+
audio_track_cblk_t();
uint32_t stepUser(uint32_t frameCount);
bool stepServer(uint32_t frameCount);
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 07c81f7..9d442c3 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -20,7 +20,8 @@ LOCAL_SRC_FILES:= \
mediametadataretriever.cpp \
ToneGenerator.cpp \
JetPlayer.cpp \
- IOMX.cpp
+ IOMX.cpp \
+ IAudioPolicyService.cpp
LOCAL_SHARED_LIBRARIES := \
libui libcutils libutils libbinder libsonivox
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index 0a6f4f7..5e35564 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -28,6 +28,7 @@
#include <media/AudioSystem.h>
#include <media/AudioRecord.h>
+#include <media/mediarecorder.h>
#include <binder/IServiceManager.h>
#include <utils/Log.h>
@@ -45,7 +46,7 @@ namespace android {
// ---------------------------------------------------------------------------
AudioRecord::AudioRecord()
- : mStatus(NO_INIT)
+ : mStatus(NO_INIT), mInput(0)
{
}
@@ -53,15 +54,15 @@ AudioRecord::AudioRecord(
int inputSource,
uint32_t sampleRate,
int format,
- int channelCount,
+ uint32_t channels,
int frameCount,
uint32_t flags,
callback_t cbf,
void* user,
int notificationFrames)
- : mStatus(NO_INIT)
+ : mStatus(NO_INIT), mInput(0)
{
- mStatus = set(inputSource, sampleRate, format, channelCount,
+ mStatus = set(inputSource, sampleRate, format, channels,
frameCount, flags, cbf, user, notificationFrames);
}
@@ -78,6 +79,7 @@ AudioRecord::~AudioRecord()
}
mAudioRecord.clear();
IPCThreadState::self()->flushCommands();
+ AudioSystem::releaseInput(mInput);
}
}
@@ -85,7 +87,7 @@ status_t AudioRecord::set(
int inputSource,
uint32_t sampleRate,
int format,
- int channelCount,
+ uint32_t channels,
int frameCount,
uint32_t flags,
callback_t cbf,
@@ -94,7 +96,7 @@ status_t AudioRecord::set(
bool threadCanCallJava)
{
- LOGV("set(): sampleRate %d, channelCount %d, frameCount %d",sampleRate, channelCount, frameCount);
+ LOGV("set(): sampleRate %d, channels %d, frameCount %d",sampleRate, channels, frameCount);
if (mAudioRecord != 0) {
return INVALID_OPERATION;
}
@@ -104,8 +106,8 @@ status_t AudioRecord::set(
return NO_INIT;
}
- if (inputSource == DEFAULT_INPUT) {
- inputSource = MIC_INPUT;
+ if (inputSource == AUDIO_SOURCE_DEFAULT) {
+ inputSource = AUDIO_SOURCE_MIC;
}
if (sampleRate == 0) {
@@ -115,15 +117,21 @@ status_t AudioRecord::set(
if (format == 0) {
format = AudioSystem::PCM_16_BIT;
}
- if (channelCount == 0) {
- channelCount = 1;
+ // validate parameters
+ if (!AudioSystem::isValidFormat(format)) {
+ LOGE("Invalid format");
+ return BAD_VALUE;
}
- // validate parameters
- if (format != AudioSystem::PCM_16_BIT) {
+ if (!AudioSystem::isInputChannel(channels)) {
return BAD_VALUE;
}
- if (channelCount != 1 && channelCount != 2) {
+ int channelCount = AudioSystem::popCount(channels);
+
+ mInput = AudioSystem::getInput(inputSource,
+ sampleRate, format, channels, (AudioSystem::audio_in_acoustics)flags);
+ if (mInput == 0) {
+ LOGE("Could not get audio output for stream type %d", inputSource);
return BAD_VALUE;
}
@@ -132,14 +140,22 @@ status_t AudioRecord::set(
if (AudioSystem::getInputBufferSize(sampleRate, format, channelCount, &inputBuffSizeInBytes)
!= NO_ERROR) {
LOGE("AudioSystem could not query the input buffer size.");
- return NO_INIT;
+ return NO_INIT;
}
+
if (inputBuffSizeInBytes == 0) {
LOGE("Recording parameters are not supported: sampleRate %d, channelCount %d, format %d",
sampleRate, channelCount, format);
return BAD_VALUE;
}
+
int frameSizeInBytes = channelCount * (format == AudioSystem::PCM_16_BIT ? 2 : 1);
+ if (AudioSystem::isLinearPCM(format)) {
+ frameSizeInBytes = channelCount * (format == AudioSystem::PCM_16_BIT ? sizeof(int16_t) : sizeof(int8_t));
+ } else {
+ frameSizeInBytes = sizeof(int8_t);
+ }
+
// We use 2* size of input buffer for ping pong use of record buffer.
int minFrameCount = 2 * inputBuffSizeInBytes / frameSizeInBytes;
@@ -157,11 +173,11 @@ status_t AudioRecord::set(
// open record channel
status_t status;
- sp<IAudioRecord> record = audioFlinger->openRecord(getpid(), inputSource,
+ sp<IAudioRecord> record = audioFlinger->openRecord(getpid(), mInput,
sampleRate, format,
channelCount,
frameCount,
- ((uint16_t)flags) << 16,
+ ((uint16_t)flags) << 16,
&status);
if (record == 0) {
LOGE("AudioFlinger could not create record track, status: %d", status);
@@ -188,7 +204,7 @@ status_t AudioRecord::set(
mFormat = format;
// Update buffer size in case it has been limited by AudioFlinger during track creation
mFrameCount = mCblk->frameCount;
- mChannelCount = channelCount;
+ mChannelCount = (uint8_t)channelCount;
mActive = 0;
mCbf = cbf;
mNotificationFrames = notificationFrames;
@@ -234,7 +250,11 @@ uint32_t AudioRecord::frameCount() const
int AudioRecord::frameSize() const
{
- return channelCount()*((format() == AudioSystem::PCM_8_BIT) ? sizeof(uint8_t) : sizeof(int16_t));
+ if (AudioSystem::isLinearPCM(mFormat)) {
+ return channelCount()*((format() == AudioSystem::PCM_8_BIT) ? sizeof(uint8_t) : sizeof(int16_t));
+ } else {
+ return sizeof(uint8_t);
+ }
}
int AudioRecord::inputSource() const
@@ -262,15 +282,18 @@ status_t AudioRecord::start()
}
if (android_atomic_or(1, &mActive) == 0) {
- mNewPosition = mCblk->user + mUpdatePeriod;
- mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
- mCblk->waitTimeMs = 0;
- if (t != 0) {
- t->run("ClientRecordThread", THREAD_PRIORITY_AUDIO_CLIENT);
- } else {
- setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT);
+ ret = AudioSystem::startInput(mInput);
+ if (ret == NO_ERROR) {
+ mNewPosition = mCblk->user + mUpdatePeriod;
+ mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
+ mCblk->waitTimeMs = 0;
+ if (t != 0) {
+ t->run("ClientRecordThread", THREAD_PRIORITY_AUDIO_CLIENT);
+ } else {
+ setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT);
+ }
+ ret = mAudioRecord->start();
}
- ret = mAudioRecord->start();
}
if (t != 0) {
@@ -301,6 +324,7 @@ status_t AudioRecord::stop()
} else {
setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL);
}
+ AudioSystem::stopInput(mInput);
}
if (t != 0) {
@@ -421,7 +445,7 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
"this shouldn't happen (user=%08x, server=%08x)", cblk->user, cblk->server);
cblk->waitTimeMs = 0;
-
+
if (framesReq > framesReady) {
framesReq = framesReady;
}
@@ -437,7 +461,7 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
audioBuffer->channelCount= mChannelCount;
audioBuffer->format = mFormat;
audioBuffer->frameCount = framesReq;
- audioBuffer->size = framesReq*mChannelCount*sizeof(int16_t);
+ audioBuffer->size = framesReq*cblk->frameSize;
audioBuffer->raw = (int8_t*)cblk->buffer(u);
active = mActive;
return active ? status_t(NO_ERROR) : status_t(STOPPED);
@@ -468,7 +492,7 @@ ssize_t AudioRecord::read(void* buffer, size_t userSize)
do {
- audioBuffer.frameCount = userSize/mChannelCount/sizeof(int16_t);
+ audioBuffer.frameCount = userSize/frameSize();
// Calling obtainBuffer() with a negative wait count causes
// an (almost) infinite wait time.
@@ -519,8 +543,8 @@ bool AudioRecord::processAudioBuffer(const sp<ClientRecordThread>& thread)
do {
audioBuffer.frameCount = frames;
- // Calling obtainBuffer() with a wait count of 1
- // limits wait time to WAIT_PERIOD_MS. This prevents from being
+ // Calling obtainBuffer() with a wait count of 1
+ // limits wait time to WAIT_PERIOD_MS. This prevents from being
// stuck here not being able to handle timed events (position, markers).
status_t err = obtainBuffer(&audioBuffer, 1);
if (err < NO_ERROR) {
@@ -548,14 +572,14 @@ bool AudioRecord::processAudioBuffer(const sp<ClientRecordThread>& thread)
if (readSize > reqSize) readSize = reqSize;
audioBuffer.size = readSize;
- audioBuffer.frameCount = readSize/mChannelCount/sizeof(int16_t);
+ audioBuffer.frameCount = readSize/frameSize();
frames -= audioBuffer.frameCount;
releaseBuffer(&audioBuffer);
} while (frames);
-
+
// Manage overrun callback
if (mActive && (mCblk->framesAvailable_l() == 0)) {
LOGV("Overrun user: %x, server: %x, flowControlFlag %d", mCblk->user, mCblk->server, mCblk->flowControlFlag);
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index 86d0542..1fc1024 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -20,8 +20,18 @@
#include <utils/Log.h>
#include <binder/IServiceManager.h>
#include <media/AudioSystem.h>
+#include <media/IAudioPolicyService.h>
#include <math.h>
+// ----------------------------------------------------------------------------
+// the sim build doesn't have gettid
+
+#ifndef HAVE_GETTID
+# define gettid getpid
+#endif
+
+// ----------------------------------------------------------------------------
+
namespace android {
// client singleton for AudioFlinger binder interface
@@ -30,10 +40,9 @@ sp<IAudioFlinger> AudioSystem::gAudioFlinger;
sp<AudioSystem::AudioFlingerClient> AudioSystem::gAudioFlingerClient;
audio_error_callback AudioSystem::gAudioErrorCallback = NULL;
// Cached values
-int AudioSystem::gOutSamplingRate[NUM_AUDIO_OUTPUT_TYPES];
-int AudioSystem::gOutFrameCount[NUM_AUDIO_OUTPUT_TYPES];
-uint32_t AudioSystem::gOutLatency[NUM_AUDIO_OUTPUT_TYPES];
-bool AudioSystem::gA2dpEnabled;
+DefaultKeyedVector<int, audio_io_handle_t> AudioSystem::gStreamOutputMap(0);
+DefaultKeyedVector<audio_io_handle_t, AudioSystem::OutputDescriptor *> AudioSystem::gOutputs(0);
+
// Cached values for recording queries
uint32_t AudioSystem::gPrevInSamplingRate = 16000;
int AudioSystem::gPrevInFormat = AudioSystem::PCM_16_BIT;
@@ -65,42 +74,10 @@ const sp<IAudioFlinger>& AudioSystem::get_audio_flinger()
binder->linkToDeath(gAudioFlingerClient);
gAudioFlinger = interface_cast<IAudioFlinger>(binder);
gAudioFlinger->registerClient(gAudioFlingerClient);
- // Cache frequently accessed parameters
- for (int output = 0; output < NUM_AUDIO_OUTPUT_TYPES; output++) {
- gOutFrameCount[output] = (int)gAudioFlinger->frameCount(output);
- gOutSamplingRate[output] = (int)gAudioFlinger->sampleRate(output);
- gOutLatency[output] = gAudioFlinger->latency(output);
- }
- gA2dpEnabled = gAudioFlinger->isA2dpEnabled();
}
LOGE_IF(gAudioFlinger==0, "no AudioFlinger!?");
- return gAudioFlinger;
-}
-// routing helper functions
-status_t AudioSystem::speakerphone(bool state) {
- uint32_t routes = state ? ROUTE_SPEAKER : ROUTE_EARPIECE;
- return setRouting(MODE_IN_CALL, routes, ROUTE_ALL);
-}
-
-status_t AudioSystem::isSpeakerphoneOn(bool* state) {
- uint32_t routes = 0;
- status_t s = getRouting(MODE_IN_CALL, &routes);
- *state = !!(routes & ROUTE_SPEAKER);
- return s;
-}
-
-status_t AudioSystem::bluetoothSco(bool state) {
- uint32_t mask = ROUTE_BLUETOOTH_SCO;
- uint32_t routes = state ? mask : ROUTE_EARPIECE;
- return setRouting(MODE_IN_CALL, routes, ROUTE_ALL);
-}
-
-status_t AudioSystem::isBluetoothScoOn(bool* state) {
- uint32_t routes = 0;
- status_t s = getRouting(MODE_IN_CALL, &routes);
- *state = !!(routes & ROUTE_BLUETOOTH_SCO);
- return s;
+ return gAudioFlinger;
}
status_t AudioSystem::muteMicrophone(bool state) {
@@ -148,12 +125,12 @@ status_t AudioSystem::getMasterMute(bool* mute)
return NO_ERROR;
}
-status_t AudioSystem::setStreamVolume(int stream, float value)
+status_t AudioSystem::setStreamVolume(int stream, float value, void *output)
{
if (uint32_t(stream) >= NUM_STREAM_TYPES) return BAD_VALUE;
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
if (af == 0) return PERMISSION_DENIED;
- af->setStreamVolume(stream, value);
+ af->setStreamVolume(stream, value, output);
return NO_ERROR;
}
@@ -166,12 +143,12 @@ status_t AudioSystem::setStreamMute(int stream, bool mute)
return NO_ERROR;
}
-status_t AudioSystem::getStreamVolume(int stream, float* volume)
+status_t AudioSystem::getStreamVolume(int stream, float* volume, void *output)
{
if (uint32_t(stream) >= NUM_STREAM_TYPES) return BAD_VALUE;
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
if (af == 0) return PERMISSION_DENIED;
- *volume = af->streamVolume(stream);
+ *volume = af->streamVolume(stream, output);
return NO_ERROR;
}
@@ -192,43 +169,28 @@ status_t AudioSystem::setMode(int mode)
return af->setMode(mode);
}
-status_t AudioSystem::getMode(int* mode)
-{
+
+status_t AudioSystem::isMusicActive(bool* state) {
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
if (af == 0) return PERMISSION_DENIED;
- *mode = af->getMode();
+ *state = af->isMusicActive();
return NO_ERROR;
}
-status_t AudioSystem::setRouting(int mode, uint32_t routes, uint32_t mask)
-{
- const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
- if (af == 0) return PERMISSION_DENIED;
- return af->setRouting(mode, routes, mask);
-}
-status_t AudioSystem::getRouting(int mode, uint32_t* routes)
-{
+status_t AudioSystem::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs) {
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
if (af == 0) return PERMISSION_DENIED;
- uint32_t r = af->getRouting(mode);
- *routes = r;
- return NO_ERROR;
+ return af->setParameters(ioHandle, keyValuePairs);
}
-status_t AudioSystem::isMusicActive(bool* state) {
+String8 AudioSystem::getParameters(audio_io_handle_t ioHandle, const String8& keys) {
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
- if (af == 0) return PERMISSION_DENIED;
- *state = af->isMusicActive();
- return NO_ERROR;
-}
+ String8 result = String8("");
+ if (af == 0) return result;
-// Temporary interface, do not use
-// TODO: Replace with a more generic key:value get/set mechanism
-status_t AudioSystem::setParameter(const char* key, const char* value) {
- const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
- if (af == 0) return PERMISSION_DENIED;
- return af->setParameter(key, value);
+ result = af->getParameters(ioHandle, keys);
+ return result;
}
// convert volume steps to natural log scale
@@ -257,55 +219,108 @@ int AudioSystem::logToLinear(float volume)
status_t AudioSystem::getOutputSamplingRate(int* samplingRate, int streamType)
{
- int output = getOutput(streamType);
-
- if (output == NUM_AUDIO_OUTPUT_TYPES) return PERMISSION_DENIED;
+ OutputDescriptor *outputDesc;
+ audio_io_handle_t output;
+
+ if (streamType == DEFAULT) {
+ streamType = MUSIC;
+ }
+
+ output = getOutput((stream_type)streamType);
+ if (output == 0) {
+ return PERMISSION_DENIED;
+ }
+
+ gLock.lock();
+ outputDesc = AudioSystem::gOutputs.valueFor(output);
+ if (outputDesc == 0) {
+ LOGV("getOutputSamplingRate() no output descriptor for output %p in gOutputs", output);
+ gLock.unlock();
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return PERMISSION_DENIED;
+ *samplingRate = af->sampleRate(output);
+ } else {
+ LOGV("getOutputSamplingRate() reading from output desc");
+ *samplingRate = outputDesc->samplingRate;
+ gLock.unlock();
+ }
+
+ LOGV("getOutputSamplingRate() streamType %d, output %p, sampling rate %d", streamType, output, *samplingRate);
- // gOutSamplingRate[] is updated by getOutput() which calls get_audio_flinger()
- LOGV("getOutputSamplingRate() streamType %d, output %d, sampling rate %d", streamType, output, gOutSamplingRate[output]);
-
- *samplingRate = gOutSamplingRate[output];
-
return NO_ERROR;
}
status_t AudioSystem::getOutputFrameCount(int* frameCount, int streamType)
{
- int output = getOutput(streamType);
+ OutputDescriptor *outputDesc;
+ audio_io_handle_t output;
+
+ if (streamType == DEFAULT) {
+ streamType = MUSIC;
+ }
- if (output == NUM_AUDIO_OUTPUT_TYPES) return PERMISSION_DENIED;
+ output = getOutput((stream_type)streamType);
+ if (output == 0) {
+ return PERMISSION_DENIED;
+ }
+
+ gLock.lock();
+ outputDesc = AudioSystem::gOutputs.valueFor(output);
+ if (outputDesc == 0) {
+ gLock.unlock();
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return PERMISSION_DENIED;
+ *frameCount = af->frameCount(output);
+ } else {
+ *frameCount = outputDesc->frameCount;
+ gLock.unlock();
+ }
- // gOutFrameCount[] is updated by getOutput() which calls get_audio_flinger()
- LOGV("getOutputFrameCount() streamType %d, output %d, frame count %d", streamType, output, gOutFrameCount[output]);
+ LOGV("getOutputFrameCount() streamType %d, output %p, frameCount %d", streamType, output, *frameCount);
- *frameCount = gOutFrameCount[output];
-
return NO_ERROR;
}
status_t AudioSystem::getOutputLatency(uint32_t* latency, int streamType)
{
- int output = getOutput(streamType);
+ OutputDescriptor *outputDesc;
+ audio_io_handle_t output;
+
+ if (streamType == DEFAULT) {
+ streamType = MUSIC;
+ }
- if (output == NUM_AUDIO_OUTPUT_TYPES) return PERMISSION_DENIED;
+ output = getOutput((stream_type)streamType);
+ if (output == 0) {
+ return PERMISSION_DENIED;
+ }
+
+ gLock.lock();
+ outputDesc = AudioSystem::gOutputs.valueFor(output);
+ if (outputDesc == 0) {
+ gLock.unlock();
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return PERMISSION_DENIED;
+ *latency = af->latency(output);
+ } else {
+ *latency = outputDesc->latency;
+ gLock.unlock();
+ }
- // gOutLatency[] is updated by getOutput() which calls get_audio_flinger()
- LOGV("getOutputLatency() streamType %d, output %d, latency %d", streamType, output, gOutLatency[output]);
+ LOGV("getOutputLatency() streamType %d, output %p, latency %d", streamType, output, *latency);
- *latency = gOutLatency[output];
-
return NO_ERROR;
}
-status_t AudioSystem::getInputBufferSize(uint32_t sampleRate, int format, int channelCount,
+status_t AudioSystem::getInputBufferSize(uint32_t sampleRate, int format, int channelCount,
size_t* buffSize)
{
// Do we have a stale gInBufferSize or are we requesting the input buffer size for new values
- if ((gInBuffSize == 0) || (sampleRate != gPrevInSamplingRate) || (format != gPrevInFormat)
+ if ((gInBuffSize == 0) || (sampleRate != gPrevInSamplingRate) || (format != gPrevInFormat)
|| (channelCount != gPrevInChannelCount)) {
// save the request params
gPrevInSamplingRate = sampleRate;
- gPrevInFormat = format;
+ gPrevInFormat = format;
gPrevInChannelCount = channelCount;
gInBuffSize = 0;
@@ -314,24 +329,18 @@ status_t AudioSystem::getInputBufferSize(uint32_t sampleRate, int format, int ch
return PERMISSION_DENIED;
}
gInBuffSize = af->getInputBufferSize(sampleRate, format, channelCount);
- }
+ }
*buffSize = gInBuffSize;
-
+
return NO_ERROR;
}
// ---------------------------------------------------------------------------
-void AudioSystem::AudioFlingerClient::binderDied(const wp<IBinder>& who) {
+void AudioSystem::AudioFlingerClient::binderDied(const wp<IBinder>& who) {
Mutex::Autolock _l(AudioSystem::gLock);
- AudioSystem::gAudioFlinger.clear();
- for (int output = 0; output < NUM_AUDIO_OUTPUT_TYPES; output++) {
- gOutFrameCount[output] = 0;
- gOutSamplingRate[output] = 0;
- gOutLatency[output] = 0;
- }
- AudioSystem::gInBuffSize = 0;
+ AudioSystem::gAudioFlinger.clear();
if (gAudioErrorCallback) {
gAudioErrorCallback(DEAD_OBJECT);
@@ -339,33 +348,83 @@ void AudioSystem::AudioFlingerClient::binderDied(const wp<IBinder>& who) {
LOGW("AudioFlinger server died!");
}
-void AudioSystem::AudioFlingerClient::a2dpEnabledChanged(bool enabled) {
- gA2dpEnabled = enabled;
- LOGV("AudioFlinger A2DP enabled status changed! %d", enabled);
-}
+void AudioSystem::AudioFlingerClient::ioConfigChanged(int event, void *param1, void *param2) {
+ LOGV("ioConfigChanged() event %d", event);
+ audio_io_handle_t ioHandle = (audio_io_handle_t)param1;
+ OutputDescriptor *desc;
+ uint32_t stream;
+
+ if (param1 == 0) return;
-void AudioSystem::setErrorCallback(audio_error_callback cb) {
Mutex::Autolock _l(AudioSystem::gLock);
- gAudioErrorCallback = cb;
-}
-int AudioSystem::getOutput(int streamType)
-{
- // make sure that gA2dpEnabled is valid by calling get_audio_flinger() which in turn
- // will call gAudioFlinger->isA2dpEnabled()
- const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
- if (af == 0) return NUM_AUDIO_OUTPUT_TYPES;
+ switch (event) {
+ case STREAM_CONFIG_CHANGED:
+ if (param2 == 0) break;
+ stream = *(uint32_t *)param2;
+ LOGV("ioConfigChanged() STREAM_CONFIG_CHANGED stream %d, output %p", stream, ioHandle);
+ if (gStreamOutputMap.indexOfKey(stream) >= 0) {
+ gStreamOutputMap.replaceValueFor(stream, ioHandle);
+ }
+ break;
+ case OUTPUT_OPENED: {
+ if (gOutputs.indexOfKey(ioHandle) >= 0) {
+ LOGV("ioConfigChanged() opening already existing output! %p", ioHandle);
+ break;
+ }
+ if (param2 == 0) break;
+ desc = (OutputDescriptor *)param2;
+
+ OutputDescriptor *outputDesc = new OutputDescriptor(*desc);
+ gOutputs.add(ioHandle, outputDesc);
+ LOGV("ioConfigChanged() new output samplingRate %d, format %d channels %d frameCount %d latency %d",
+ outputDesc->samplingRate, outputDesc->format, outputDesc->channels, outputDesc->frameCount, outputDesc->latency);
+ } break;
+ case OUTPUT_CLOSED: {
+ if (gOutputs.indexOfKey(ioHandle) < 0) {
+ LOGW("ioConfigChanged() closing unknow output! %p", ioHandle);
+ break;
+ }
+ LOGV("ioConfigChanged() output %p closed", ioHandle);
+
+ gOutputs.removeItem(ioHandle);
+ for (int i = gStreamOutputMap.size() - 1; i >= 0 ; i--) {
+ if (gStreamOutputMap.valueAt(i) == ioHandle) {
+ gStreamOutputMap.removeItemsAt(i);
+ }
+ }
+ } break;
+
+ case OUTPUT_CONFIG_CHANGED: {
+ int index = gOutputs.indexOfKey(ioHandle);
+ if (index < 0) {
+ LOGW("ioConfigChanged() modifying unknow output! %p", ioHandle);
+ break;
+ }
+ if (param2 == 0) break;
+ desc = (OutputDescriptor *)param2;
+
+ LOGV("ioConfigChanged() new config for output %p samplingRate %d, format %d channels %d frameCount %d latency %d",
+ ioHandle, desc->samplingRate, desc->format,
+ desc->channels, desc->frameCount, desc->latency);
+ OutputDescriptor *outputDesc = gOutputs.valueAt(index);
+ delete outputDesc;
+ outputDesc = new OutputDescriptor(*desc);
+ gOutputs.replaceValueFor(ioHandle, outputDesc);
+ } break;
+ case INPUT_OPENED:
+ case INPUT_CLOSED:
+ case INPUT_CONFIG_CHANGED:
+ break;
- if (streamType == DEFAULT) {
- streamType = MUSIC;
- }
- if (gA2dpEnabled && routedToA2dpOutput(streamType)) {
- return AUDIO_OUTPUT_A2DP;
- } else {
- return AUDIO_OUTPUT_HARDWARE;
}
}
+void AudioSystem::setErrorCallback(audio_error_callback cb) {
+ Mutex::Autolock _l(gLock);
+ gAudioErrorCallback = cb;
+}
+
bool AudioSystem::routedToA2dpOutput(int streamType) {
switch(streamType) {
case MUSIC:
@@ -379,6 +438,451 @@ bool AudioSystem::routedToA2dpOutput(int streamType) {
}
+// client singleton for AudioPolicyService binder interface
+sp<IAudioPolicyService> AudioSystem::gAudioPolicyService;
+sp<AudioSystem::AudioPolicyServiceClient> AudioSystem::gAudioPolicyServiceClient;
+
+
+// establish binder interface to AudioFlinger service
+const sp<IAudioPolicyService>& AudioSystem::get_audio_policy_service()
+{
+ gLock.lock();
+ if (gAudioPolicyService.get() == 0) {
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> binder;
+ do {
+ binder = sm->getService(String16("media.audio_policy"));
+ if (binder != 0)
+ break;
+ LOGW("AudioPolicyService not published, waiting...");
+ usleep(500000); // 0.5 s
+ } while(true);
+ if (gAudioPolicyServiceClient == NULL) {
+ gAudioPolicyServiceClient = new AudioPolicyServiceClient();
+ }
+ binder->linkToDeath(gAudioPolicyServiceClient);
+ gAudioPolicyService = interface_cast<IAudioPolicyService>(binder);
+ gLock.unlock();
+ } else {
+ gLock.unlock();
+ }
+ return gAudioPolicyService;
+}
+
+status_t AudioSystem::setDeviceConnectionState(audio_devices device,
+ device_connection_state state,
+ const char *device_address)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+
+ return aps->setDeviceConnectionState(device, state, device_address);
+}
+
+AudioSystem::device_connection_state AudioSystem::getDeviceConnectionState(audio_devices device,
+ const char *device_address)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return DEVICE_STATE_UNAVAILABLE;
+
+ return aps->getDeviceConnectionState(device, device_address);
+}
+
+status_t AudioSystem::setPhoneState(int state)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+
+ return aps->setPhoneState(state);
+}
+
+status_t AudioSystem::setRingerMode(uint32_t mode, uint32_t mask)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->setRingerMode(mode, mask);
+}
+
+status_t AudioSystem::setForceUse(force_use usage, forced_config config)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->setForceUse(usage, config);
+}
+
+AudioSystem::forced_config AudioSystem::getForceUse(force_use usage)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return FORCE_NONE;
+ return aps->getForceUse(usage);
+}
+
+
+audio_io_handle_t AudioSystem::getOutput(stream_type stream,
+ uint32_t samplingRate,
+ uint32_t format,
+ uint32_t channels,
+ output_flags flags)
+{
+ audio_io_handle_t output = NULL;
+ if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) == 0) {
+ Mutex::Autolock _l(gLock);
+ output = AudioSystem::gStreamOutputMap.valueFor(stream);
+ LOGV_IF((output != NULL), "getOutput() read %p from cache for stream %d", output, stream);
+ }
+ if (output == NULL) {
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return NULL;
+ output = aps->getOutput(stream, samplingRate, format, channels, flags);
+ if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) == 0) {
+ Mutex::Autolock _l(gLock);
+ AudioSystem::gStreamOutputMap.add(stream, output);
+ }
+ }
+ return output;
+}
+
+status_t AudioSystem::startOutput(audio_io_handle_t output, AudioSystem::stream_type stream)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->startOutput(output, stream);
+}
+
+status_t AudioSystem::stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->stopOutput(output, stream);
+}
+
+void AudioSystem::releaseOutput(audio_io_handle_t output)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return;
+ aps->releaseOutput(output);
+}
+
+audio_io_handle_t AudioSystem::getInput(int inputSource,
+ uint32_t samplingRate,
+ uint32_t format,
+ uint32_t channels,
+ audio_in_acoustics acoustics)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return NULL;
+ return aps->getInput(inputSource, samplingRate, format, channels, acoustics);
+}
+
+status_t AudioSystem::startInput(audio_io_handle_t input)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->startInput(input);
+}
+
+status_t AudioSystem::stopInput(audio_io_handle_t input)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->stopInput(input);
+}
+
+void AudioSystem::releaseInput(audio_io_handle_t input)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return;
+ aps->releaseInput(input);
+}
+
+status_t AudioSystem::initStreamVolume(stream_type stream,
+ int indexMin,
+ int indexMax)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->initStreamVolume(stream, indexMin, indexMax);
+}
+
+status_t AudioSystem::setStreamVolumeIndex(stream_type stream, int index)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->setStreamVolumeIndex(stream, index);
+}
+
+status_t AudioSystem::getStreamVolumeIndex(stream_type stream, int *index)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->getStreamVolumeIndex(stream, index);
+}
+
+// ---------------------------------------------------------------------------
+
+void AudioSystem::AudioPolicyServiceClient::binderDied(const wp<IBinder>& who) {
+ Mutex::Autolock _l(AudioSystem::gLock);
+ AudioSystem::gAudioPolicyService.clear();
+
+ LOGW("AudioPolicyService server died!");
+}
+
+// ---------------------------------------------------------------------------
+
+
+// use emulated popcount optimization
+// http://www.df.lth.se/~john_e/gems/gem002d.html
+uint32_t AudioSystem::popCount(uint32_t u)
+{
+ u = ((u&0x55555555) + ((u>>1)&0x55555555));
+ u = ((u&0x33333333) + ((u>>2)&0x33333333));
+ u = ((u&0x0f0f0f0f) + ((u>>4)&0x0f0f0f0f));
+ u = ((u&0x00ff00ff) + ((u>>8)&0x00ff00ff));
+ u = ( u&0x0000ffff) + (u>>16);
+ return u;
+}
+
+bool AudioSystem::isOutputDevice(audio_devices device)
+{
+ if ((popCount(device) == 1 ) &&
+ ((device & ~AudioSystem::DEVICE_OUT_ALL) == 0)) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool AudioSystem::isInputDevice(audio_devices device)
+{
+ if ((popCount(device) == 1 ) &&
+ ((device & ~AudioSystem::DEVICE_IN_ALL) == 0)) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool AudioSystem::isA2dpDevice(audio_devices device)
+{
+ if ((popCount(device) == 1 ) &&
+ (device & (AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP |
+ AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
+ AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER))) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool AudioSystem::isBluetoothScoDevice(audio_devices device)
+{
+ if ((popCount(device) == 1 ) &&
+ (device & (AudioSystem::DEVICE_OUT_BLUETOOTH_SCO |
+ AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
+ AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT))) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool AudioSystem::isLowVisibility(stream_type stream)
+{
+ if (stream == AudioSystem::SYSTEM || stream == AudioSystem::NOTIFICATION) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool AudioSystem::isInputChannel(uint32_t channel)
+{
+ if ((channel & ~AudioSystem::CHANNEL_IN_ALL) == 0) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool AudioSystem::isOutputChannel(uint32_t channel)
+{
+ if ((channel & ~AudioSystem::CHANNEL_OUT_ALL) == 0) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool AudioSystem::isValidFormat(uint32_t format)
+{
+ switch (format & MAIN_FORMAT_MASK) {
+ case PCM:
+ case MP3:
+ case AMR_NB:
+ case AMR_WB:
+ case AAC:
+ case HE_AAC_V1:
+ case HE_AAC_V2:
+ case VORBIS:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool AudioSystem::isLinearPCM(uint32_t format)
+{
+ switch (format) {
+ case PCM_16_BIT:
+ case PCM_8_BIT:
+ return true;
+ default:
+ return false;
+ }
+}
+
+//------------------------- AudioParameter class implementation ---------------
+
+const char *AudioParameter::keyRouting = "routing";
+const char *AudioParameter::keySamplingRate = "sampling_rate";
+const char *AudioParameter::keyFormat = "format";
+const char *AudioParameter::keyChannels = "channels";
+const char *AudioParameter::keyFrameCount = "frame_count";
+
+AudioParameter::AudioParameter(const String8& keyValuePairs)
+{
+ char *str = new char[keyValuePairs.length()+1];
+ mKeyValuePairs = keyValuePairs;
+
+ strcpy(str, keyValuePairs.string());
+ char *pair = strtok(str, ";");
+ while (pair != NULL) {
+ if (strlen(pair) != 0) {
+ size_t eqIdx = strcspn(pair, "=");
+ String8 key = String8(pair, eqIdx);
+ String8 value;
+ if (eqIdx == strlen(pair)) {
+ value = String8("");
+ } else {
+ value = String8(pair + eqIdx + 1);
+ }
+ if (mParameters.indexOfKey(key) < 0) {
+ mParameters.add(key, value);
+ } else {
+ mParameters.replaceValueFor(key, value);
+ }
+ } else {
+ LOGV("AudioParameter() cstor empty key value pair");
+ }
+ pair = strtok(NULL, ";");
+ }
+
+ delete[] str;
+}
+
+AudioParameter::~AudioParameter()
+{
+ mParameters.clear();
+}
+
+String8 AudioParameter::toString()
+{
+ String8 str = String8("");
+
+ size_t size = mParameters.size();
+ for (size_t i = 0; i < size; i++) {
+ str += mParameters.keyAt(i);
+ str += "=";
+ str += mParameters.valueAt(i);
+ if (i < (size - 1)) str += ";";
+ }
+ return str;
+}
+
+status_t AudioParameter::add(const String8& key, const String8& value)
+{
+ if (mParameters.indexOfKey(key) < 0) {
+ mParameters.add(key, value);
+ return NO_ERROR;
+ } else {
+ mParameters.replaceValueFor(key, value);
+ return ALREADY_EXISTS;
+ }
+}
+
+status_t AudioParameter::addInt(const String8& key, const int value)
+{
+ char str[12];
+ if (snprintf(str, 12, "%d", value) > 0) {
+ String8 str8 = String8(str);
+ return add(key, str8);
+ } else {
+ return BAD_VALUE;
+ }
+}
+
+status_t AudioParameter::addFloat(const String8& key, const float value)
+{
+ char str[23];
+ if (snprintf(str, 23, "%.10f", value) > 0) {
+ String8 str8 = String8(str);
+ return add(key, str8);
+ } else {
+ return BAD_VALUE;
+ }
+}
+
+status_t AudioParameter::remove(const String8& key)
+{
+ if (mParameters.indexOfKey(key) >= 0) {
+ mParameters.removeItem(key);
+ return NO_ERROR;
+ } else {
+ return BAD_VALUE;
+ }
+}
+
+status_t AudioParameter::get(const String8& key, String8& value)
+{
+ if (mParameters.indexOfKey(key) >= 0) {
+ value = mParameters.valueFor(key);
+ return NO_ERROR;
+ } else {
+ return BAD_VALUE;
+ }
+}
+
+status_t AudioParameter::getInt(const String8& key, int& value)
+{
+ String8 str8;
+ status_t result = get(key, str8);
+ value = 0;
+ if (result == NO_ERROR) {
+ int val;
+ if (sscanf(str8.string(), "%d", &val) == 1) {
+ value = val;
+ } else {
+ result = INVALID_OPERATION;
+ }
+ }
+ return result;
+}
+
+status_t AudioParameter::getFloat(const String8& key, float& value)
+{
+ String8 str8;
+ status_t result = get(key, str8);
+ value = 0;
+ if (result == NO_ERROR) {
+ float val;
+ if (sscanf(str8.string(), "%f", &val) == 1) {
+ value = val;
+ } else {
+ result = INVALID_OPERATION;
+ }
+ }
+ return result;
+}
}; // namespace android
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 7b9eda7..b147d25 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -54,7 +54,7 @@ AudioTrack::AudioTrack(
int streamType,
uint32_t sampleRate,
int format,
- int channelCount,
+ int channels,
int frameCount,
uint32_t flags,
callback_t cbf,
@@ -62,7 +62,7 @@ AudioTrack::AudioTrack(
int notificationFrames)
: mStatus(NO_INIT)
{
- mStatus = set(streamType, sampleRate, format, channelCount,
+ mStatus = set(streamType, sampleRate, format, channels,
frameCount, flags, cbf, user, notificationFrames, 0);
}
@@ -70,7 +70,7 @@ AudioTrack::AudioTrack(
int streamType,
uint32_t sampleRate,
int format,
- int channelCount,
+ int channels,
const sp<IMemory>& sharedBuffer,
uint32_t flags,
callback_t cbf,
@@ -78,7 +78,7 @@ AudioTrack::AudioTrack(
int notificationFrames)
: mStatus(NO_INIT)
{
- mStatus = set(streamType, sampleRate, format, channelCount,
+ mStatus = set(streamType, sampleRate, format, channels,
0, flags, cbf, user, notificationFrames, sharedBuffer);
}
@@ -97,6 +97,7 @@ AudioTrack::~AudioTrack()
}
mAudioTrack.clear();
IPCThreadState::self()->flushCommands();
+ AudioSystem::releaseOutput(getOutput());
}
}
@@ -104,7 +105,7 @@ status_t AudioTrack::set(
int streamType,
uint32_t sampleRate,
int format,
- int channelCount,
+ int channels,
int frameCount,
uint32_t flags,
callback_t cbf,
@@ -150,63 +151,84 @@ status_t AudioTrack::set(
if (format == 0) {
format = AudioSystem::PCM_16_BIT;
}
- if (channelCount == 0) {
- channelCount = 2;
+ if (channels == 0) {
+ channels = AudioSystem::CHANNEL_OUT_STEREO;
}
// validate parameters
- if (((format != AudioSystem::PCM_8_BIT) || sharedBuffer != 0) &&
- (format != AudioSystem::PCM_16_BIT)) {
+ if (!AudioSystem::isValidFormat(format)) {
LOGE("Invalid format");
return BAD_VALUE;
}
- if (channelCount != 1 && channelCount != 2) {
- LOGE("Invalid channel number");
+
+ // force direct flag if format is not linear PCM
+ if (!AudioSystem::isLinearPCM(format)) {
+ flags |= AudioSystem::OUTPUT_FLAG_DIRECT;
+ }
+
+ if (!AudioSystem::isOutputChannel(channels)) {
+ LOGE("Invalid channel mask");
return BAD_VALUE;
}
+ uint32_t channelCount = AudioSystem::popCount(channels);
- // Ensure that buffer depth covers at least audio hardware latency
- uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSampleRate);
- if (minBufCount < 2) minBufCount = 2;
+ audio_io_handle_t output = AudioSystem::getOutput((AudioSystem::stream_type)streamType,
+ sampleRate, format, channels, (AudioSystem::output_flags)flags);
- // When playing from shared buffer, playback will start even if last audioflinger
- // block is partly filled.
- if (sharedBuffer != 0 && minBufCount > 1) {
- minBufCount--;
+ if (output == 0) {
+ LOGE("Could not get audio output for stream type %d", streamType);
+ return BAD_VALUE;
}
- int minFrameCount = (afFrameCount*sampleRate*minBufCount)/afSampleRate;
-
- if (sharedBuffer == 0) {
- if (frameCount == 0) {
- frameCount = minFrameCount;
- }
- if (notificationFrames == 0) {
- notificationFrames = frameCount/2;
- }
- // Make sure that application is notified with sufficient margin
- // before underrun
- if (notificationFrames > frameCount/2) {
- notificationFrames = frameCount/2;
+ if (!AudioSystem::isLinearPCM(format)) {
+ if (sharedBuffer != 0) {
+ frameCount = sharedBuffer->size();
}
} else {
- // Ensure that buffer alignment matches channelcount
- if (((uint32_t)sharedBuffer->pointer() & (channelCount | 1)) != 0) {
- LOGE("Invalid buffer alignement: address %p, channelCount %d", sharedBuffer->pointer(), channelCount);
- return BAD_VALUE;
- }
- frameCount = sharedBuffer->size()/channelCount/sizeof(int16_t);
- }
+ // Ensure that buffer depth covers at least audio hardware latency
+ uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSampleRate);
+ if (minBufCount < 2) minBufCount = 2;
- if (frameCount < minFrameCount) {
- LOGE("Invalid buffer size: minFrameCount %d, frameCount %d", minFrameCount, frameCount);
- return BAD_VALUE;
+ int minFrameCount = (afFrameCount*sampleRate*minBufCount)/afSampleRate;
+
+ if (sharedBuffer == 0) {
+ if (frameCount == 0) {
+ frameCount = minFrameCount;
+ }
+ if (notificationFrames == 0) {
+ notificationFrames = frameCount/2;
+ }
+ // Make sure that application is notified with sufficient margin
+ // before underrun
+ if (notificationFrames > frameCount/2) {
+ notificationFrames = frameCount/2;
+ }
+ if (frameCount < minFrameCount) {
+ LOGE("Invalid buffer size: minFrameCount %d, frameCount %d", minFrameCount, frameCount);
+ return BAD_VALUE;
+ }
+ } else {
+ // Ensure that buffer alignment matches channelcount
+ if (((uint32_t)sharedBuffer->pointer() & (channelCount | 1)) != 0) {
+ LOGE("Invalid buffer alignement: address %p, channelCount %d", sharedBuffer->pointer(), channelCount);
+ return BAD_VALUE;
+ }
+ frameCount = sharedBuffer->size()/channelCount/sizeof(int16_t);
+ }
}
// create the track
status_t status;
sp<IAudioTrack> track = audioFlinger->createTrack(getpid(),
- streamType, sampleRate, format, channelCount, frameCount, flags, sharedBuffer, &status);
+ streamType,
+ sampleRate,
+ format,
+ channelCount,
+ frameCount,
+ ((uint16_t)flags) << 16,
+ sharedBuffer,
+ output,
+ &status);
if (track == 0) {
LOGE("AudioFlinger could not create track, status: %d", status);
@@ -245,6 +267,7 @@ status_t AudioTrack::set(
mVolume[RIGHT] = 1.0f;
mStreamType = streamType;
mFormat = format;
+ mChannels = channels;
mChannelCount = channelCount;
mSharedBuffer = sharedBuffer;
mMuted = false;
@@ -259,6 +282,7 @@ status_t AudioTrack::set(
mMarkerReached = false;
mNewPosition = 0;
mUpdatePeriod = 0;
+ mFlags = flags;
return NO_ERROR;
}
@@ -297,7 +321,11 @@ uint32_t AudioTrack::frameCount() const
int AudioTrack::frameSize() const
{
- return channelCount()*((format() == AudioSystem::PCM_8_BIT) ? sizeof(uint8_t) : sizeof(int16_t));
+ if (AudioSystem::isLinearPCM(mFormat)) {
+ return channelCount()*((format() == AudioSystem::PCM_8_BIT) ? sizeof(uint8_t) : sizeof(int16_t));
+ } else {
+ return sizeof(uint8_t);
+ }
}
sp<IMemory>& AudioTrack::sharedBuffer()
@@ -323,6 +351,7 @@ void AudioTrack::start()
}
if (android_atomic_or(1, &mActive) == 0) {
+ AudioSystem::startOutput(getOutput(), (AudioSystem::stream_type)mStreamType);
mNewPosition = mCblk->server + mUpdatePeriod;
mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
mCblk->waitTimeMs = 0;
@@ -367,6 +396,7 @@ void AudioTrack::stop()
} else {
setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL);
}
+ AudioSystem::stopOutput(getOutput(), (AudioSystem::stream_type)mStreamType);
}
if (t != 0) {
@@ -382,12 +412,12 @@ bool AudioTrack::stopped() const
void AudioTrack::flush()
{
LOGV("flush");
-
+
// clear playback marker and periodic update counter
mMarkerPosition = 0;
mMarkerReached = false;
mUpdatePeriod = 0;
-
+
if (!mActive) {
mAudioTrack->flush();
@@ -403,6 +433,7 @@ void AudioTrack::pause()
if (android_atomic_and(~1, &mActive) == 1) {
mActive = 0;
mAudioTrack->pause();
+ AudioSystem::stopOutput(getOutput(), (AudioSystem::stream_type)mStreamType);
}
}
@@ -455,7 +486,6 @@ status_t AudioTrack::setLoop(uint32_t loopStart, uint32_t loopEnd, int loopCount
{
audio_track_cblk_t* cblk = mCblk;
-
Mutex::Autolock _l(cblk->lock);
if (loopCount == 0) {
@@ -476,7 +506,7 @@ status_t AudioTrack::setLoop(uint32_t loopStart, uint32_t loopEnd, int loopCount
LOGE("setLoop invalid value: loop markers beyond data: loopStart %d, loopEnd %d, framecount %d",
loopStart, loopEnd, mFrameCount);
return BAD_VALUE;
- }
+ }
cblk->loopStart = loopStart;
cblk->loopEnd = loopEnd;
@@ -555,7 +585,7 @@ status_t AudioTrack::setPosition(uint32_t position)
mCblk->server = position;
mCblk->forceReady = 1;
-
+
return NO_ERROR;
}
@@ -571,7 +601,7 @@ status_t AudioTrack::getPosition(uint32_t *position)
status_t AudioTrack::reload()
{
if (!stopped()) return INVALID_OPERATION;
-
+
flush();
mCblk->stepUser(mFrameCount);
@@ -579,6 +609,12 @@ status_t AudioTrack::reload()
return NO_ERROR;
}
+audio_io_handle_t AudioTrack::getOutput()
+{
+ return AudioSystem::getOutput((AudioSystem::stream_type)mStreamType,
+ mCblk->sampleRate, mFormat, mChannels, (AudioSystem::output_flags)mFlags);
+}
+
// -------------------------------------------------------------------------
status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
@@ -608,7 +644,7 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
return WOULD_BLOCK;
timeout = 0;
result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
- if (__builtin_expect(result!=NO_ERROR, false)) {
+ if (__builtin_expect(result!=NO_ERROR, false)) {
cblk->waitTimeMs += waitTimeMs;
if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) {
// timing out when a loop has been set and we have already written upto loop end
@@ -616,7 +652,7 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
if (cblk->user < cblk->loopEnd) {
LOGW( "obtainBuffer timed out (is the CPU pegged?) %p "
"user=%08x, server=%08x", this, cblk->user, cblk->server);
- //unlock cblk mutex before calling mAudioTrack->start() (see issue #1617140)
+ //unlock cblk mutex before calling mAudioTrack->start() (see issue #1617140)
cblk->lock.unlock();
mAudioTrack->start();
cblk->lock.lock();
@@ -624,7 +660,7 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
}
cblk->waitTimeMs = 0;
}
-
+
if (--waitCount == 0) {
return TIMED_OUT;
}
@@ -636,7 +672,7 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
}
cblk->waitTimeMs = 0;
-
+
if (framesReq > framesAvail) {
framesReq = framesAvail;
}
@@ -653,12 +689,16 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
"but didn't need to be locked. We recovered, but "
"this shouldn't happen (user=%08x, server=%08x)", cblk->user, cblk->server);
- audioBuffer->flags = mMuted ? Buffer::MUTE : 0;
- audioBuffer->channelCount= mChannelCount;
- audioBuffer->format = AudioSystem::PCM_16_BIT;
- audioBuffer->frameCount = framesReq;
- audioBuffer->size = framesReq*mChannelCount*sizeof(int16_t);
- audioBuffer->raw = (int8_t *)cblk->buffer(u);
+ audioBuffer->flags = mMuted ? Buffer::MUTE : 0;
+ audioBuffer->channelCount = mChannelCount;
+ audioBuffer->frameCount = framesReq;
+ audioBuffer->size = framesReq * cblk->frameSize;
+ if (AudioSystem::isLinearPCM(mFormat)) {
+ audioBuffer->format = AudioSystem::PCM_16_BIT;
+ } else {
+ audioBuffer->format = mFormat;
+ }
+ audioBuffer->raw = (int8_t *)cblk->buffer(u);
active = mActive;
return active ? status_t(NO_ERROR) : status_t(STOPPED);
}
@@ -690,10 +730,8 @@ ssize_t AudioTrack::write(const void* buffer, size_t userSize)
Buffer audioBuffer;
do {
- audioBuffer.frameCount = userSize/mChannelCount;
- if (mFormat == AudioSystem::PCM_16_BIT) {
- audioBuffer.frameCount >>= 1;
- }
+ audioBuffer.frameCount = userSize/frameSize();
+
// Calling obtainBuffer() with a negative wait count causes
// an (almost) infinite wait time.
status_t err = obtainBuffer(&audioBuffer, -1);
@@ -705,6 +743,7 @@ ssize_t AudioTrack::write(const void* buffer, size_t userSize)
}
size_t toWrite;
+
if (mFormat == AudioSystem::PCM_8_BIT) {
// Divide capacity by 2 to take expansion into account
toWrite = audioBuffer.size>>1;
@@ -742,13 +781,13 @@ bool AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread)
if (mCblk->flowControlFlag == 0) {
mCbf(EVENT_UNDERRUN, mUserData, 0);
if (mCblk->server == mCblk->frameCount) {
- mCbf(EVENT_BUFFER_END, mUserData, 0);
+ mCbf(EVENT_BUFFER_END, mUserData, 0);
}
mCblk->flowControlFlag = 1;
if (mSharedBuffer != 0) return false;
}
}
-
+
// Manage loop end callback
while (mLoopCount > mCblk->loopCount) {
int loopCount = -1;
@@ -767,7 +806,7 @@ bool AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread)
}
// Manage new position callback
- if(mUpdatePeriod > 0) {
+ if (mUpdatePeriod > 0) {
while (mCblk->server >= mNewPosition) {
mCbf(EVENT_NEW_POS, mUserData, (void *)&mNewPosition);
mNewPosition += mUpdatePeriod;
@@ -784,10 +823,10 @@ bool AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread)
do {
audioBuffer.frameCount = frames;
-
- // Calling obtainBuffer() with a wait count of 1
- // limits wait time to WAIT_PERIOD_MS. This prevents from being
- // stuck here not being able to handle timed events (position, markers, loops).
+
+ // Calling obtainBuffer() with a wait count of 1
+ // limits wait time to WAIT_PERIOD_MS. This prevents from being
+ // stuck here not being able to handle timed events (position, markers, loops).
status_t err = obtainBuffer(&audioBuffer, 1);
if (err < NO_ERROR) {
if (err != TIMED_OUT) {
@@ -832,7 +871,11 @@ bool AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread)
}
audioBuffer.size = writtenSize;
- audioBuffer.frameCount = writtenSize/mChannelCount/sizeof(int16_t);
+ // NOTE: mCblk->frameSize is not equal to AudioTrack::frameSize() for
+ // 8 bit PCM data: in this case, mCblk->frameSize is based on a sampel size of
+ // 16 bit.
+ audioBuffer.frameCount = writtenSize/mCblk->frameSize;
+
frames -= audioBuffer.frameCount;
releaseBuffer(&audioBuffer);
@@ -949,7 +992,7 @@ bool audio_track_cblk_t::stepServer(uint32_t frameCount)
// we switch to normal obtainBuffer() timeout period
if (bufferTimeoutMs == MAX_STARTUP_TIMEOUT_MS) {
bufferTimeoutMs = MAX_RUN_TIMEOUT_MS - 1;
- }
+ }
// It is possible that we receive a flush()
// while the mixer is processing a block: in this case,
// stepServer() is called After the flush() has reset u & s and
@@ -981,7 +1024,7 @@ bool audio_track_cblk_t::stepServer(uint32_t frameCount)
void* audio_track_cblk_t::buffer(uint32_t offset) const
{
- return (int16_t *)this->buffers + (offset-userBase)*this->channels;
+ return (int8_t *)this->buffers + (offset - userBase) * this->frameSize;
}
uint32_t audio_track_cblk_t::framesAvailable()
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
index 6fc0cb7..9385367 100644
--- a/media/libmedia/IAudioFlinger.cpp
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -16,6 +16,7 @@
*/
#define LOG_TAG "IAudioFlinger"
+//#define LOG_NDEBUG 0
#include <utils/Log.h>
#include <stdint.h>
@@ -44,17 +45,21 @@ enum {
STREAM_VOLUME,
STREAM_MUTE,
SET_MODE,
- GET_MODE,
- SET_ROUTING,
- GET_ROUTING,
SET_MIC_MUTE,
GET_MIC_MUTE,
IS_MUSIC_ACTIVE,
- SET_PARAMETER,
+ SET_PARAMETERS,
+ GET_PARAMETERS,
REGISTER_CLIENT,
GET_INPUTBUFFERSIZE,
- WAKE_UP,
- IS_A2DP_ENABLED
+ OPEN_OUTPUT,
+ OPEN_DUPLICATE_OUTPUT,
+ CLOSE_OUTPUT,
+ SUSPEND_OUTPUT,
+ RESTORE_OUTPUT,
+ OPEN_INPUT,
+ CLOSE_INPUT,
+ SET_STREAM_OUTPUT
};
class BpAudioFlinger : public BpInterface<IAudioFlinger>
@@ -74,6 +79,7 @@ public:
int frameCount,
uint32_t flags,
const sp<IMemory>& sharedBuffer,
+ void *output,
status_t *status)
{
Parcel data, reply;
@@ -86,6 +92,7 @@ public:
data.writeInt32(frameCount);
data.writeInt32(flags);
data.writeStrongBinder(sharedBuffer->asBinder());
+ data.write(&output, sizeof(void *));
status_t lStatus = remote()->transact(CREATE_TRACK, data, &reply);
if (lStatus != NO_ERROR) {
LOGE("createTrack error: %s", strerror(-lStatus));
@@ -99,7 +106,7 @@ public:
virtual sp<IAudioRecord> openRecord(
pid_t pid,
- int inputSource,
+ void *input,
uint32_t sampleRate,
int format,
int channelCount,
@@ -110,7 +117,7 @@ public:
Parcel data, reply;
data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
data.writeInt32(pid);
- data.writeInt32(inputSource);
+ data.write(&input, sizeof(void *));
data.writeInt32(sampleRate);
data.writeInt32(format);
data.writeInt32(channelCount);
@@ -124,47 +131,47 @@ public:
return interface_cast<IAudioRecord>(reply.readStrongBinder());
}
- virtual uint32_t sampleRate(int output) const
+ virtual uint32_t sampleRate(void *output) const
{
Parcel data, reply;
data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32(output);
+ data.write(&output, sizeof(void *));
remote()->transact(SAMPLE_RATE, data, &reply);
return reply.readInt32();
}
- virtual int channelCount(int output) const
+ virtual int channelCount(void *output) const
{
Parcel data, reply;
data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32(output);
+ data.write(&output, sizeof(void *));
remote()->transact(CHANNEL_COUNT, data, &reply);
return reply.readInt32();
}
- virtual int format(int output) const
+ virtual int format(void *output) const
{
Parcel data, reply;
data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32(output);
+ data.write(&output, sizeof(void *));
remote()->transact(FORMAT, data, &reply);
return reply.readInt32();
}
- virtual size_t frameCount(int output) const
+ virtual size_t frameCount(void *output) const
{
Parcel data, reply;
data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32(output);
+ data.write(&output, sizeof(void *));
remote()->transact(FRAME_COUNT, data, &reply);
return reply.readInt32();
}
- virtual uint32_t latency(int output) const
+ virtual uint32_t latency(void *output) const
{
Parcel data, reply;
data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32(output);
+ data.write(&output, sizeof(void *));
remote()->transact(LATENCY, data, &reply);
return reply.readInt32();
}
@@ -203,12 +210,13 @@ public:
return reply.readInt32();
}
- virtual status_t setStreamVolume(int stream, float value)
+ virtual status_t setStreamVolume(int stream, float value, void *output)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
data.writeInt32(stream);
data.writeFloat(value);
+ data.write(&output, sizeof(void *));
remote()->transact(SET_STREAM_VOLUME, data, &reply);
return reply.readInt32();
}
@@ -223,11 +231,12 @@ public:
return reply.readInt32();
}
- virtual float streamVolume(int stream) const
+ virtual float streamVolume(int stream, void *output) const
{
Parcel data, reply;
data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
data.writeInt32(stream);
+ data.write(&output, sizeof(void *));
remote()->transact(STREAM_VOLUME, data, &reply);
return reply.readFloat();
}
@@ -241,111 +250,205 @@ public:
return reply.readInt32();
}
- virtual status_t setRouting(int mode, uint32_t routes, uint32_t mask)
+ virtual status_t setMode(int mode)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
data.writeInt32(mode);
- data.writeInt32(routes);
- data.writeInt32(mask);
- remote()->transact(SET_ROUTING, data, &reply);
+ remote()->transact(SET_MODE, data, &reply);
return reply.readInt32();
}
- virtual uint32_t getRouting(int mode) const
+ virtual status_t setMicMute(bool state)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32(mode);
- remote()->transact(GET_ROUTING, data, &reply);
+ data.writeInt32(state);
+ remote()->transact(SET_MIC_MUTE, data, &reply);
return reply.readInt32();
}
- virtual status_t setMode(int mode)
+ virtual bool getMicMute() const
{
Parcel data, reply;
data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32(mode);
- remote()->transact(SET_MODE, data, &reply);
+ remote()->transact(GET_MIC_MUTE, data, &reply);
return reply.readInt32();
}
- virtual int getMode() const
+ virtual bool isMusicActive() const
{
Parcel data, reply;
data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- remote()->transact(GET_MODE, data, &reply);
+ remote()->transact(IS_MUSIC_ACTIVE, data, &reply);
return reply.readInt32();
}
- virtual status_t setMicMute(bool state)
+ virtual status_t setParameters(void *ioHandle, const String8& keyValuePairs)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32(state);
- remote()->transact(SET_MIC_MUTE, data, &reply);
+ data.write(&ioHandle, sizeof(void *));
+ data.writeString8(keyValuePairs);
+ remote()->transact(SET_PARAMETERS, data, &reply);
return reply.readInt32();
}
- virtual bool getMicMute() const
+ virtual String8 getParameters(void *ioHandle, const String8& keys)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- remote()->transact(GET_MIC_MUTE, data, &reply);
+ data.write(&ioHandle, sizeof(void *));
+ data.writeString8(keys);
+ remote()->transact(GET_PARAMETERS, data, &reply);
+ return reply.readString8();
+ }
+
+ virtual void registerClient(const sp<IAudioFlingerClient>& client)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeStrongBinder(client->asBinder());
+ remote()->transact(REGISTER_CLIENT, data, &reply);
+ }
+
+ virtual size_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32(sampleRate);
+ data.writeInt32(format);
+ data.writeInt32(channelCount);
+ remote()->transact(GET_INPUTBUFFERSIZE, data, &reply);
return reply.readInt32();
}
- virtual bool isMusicActive() const
+ virtual void *openOutput(uint32_t *pDevices,
+ uint32_t *pSamplingRate,
+ uint32_t *pFormat,
+ uint32_t *pChannels,
+ uint32_t *pLatencyMs,
+ uint32_t flags)
{
Parcel data, reply;
+ uint32_t devices = pDevices ? *pDevices : 0;
+ uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
+ uint32_t format = pFormat ? *pFormat : 0;
+ uint32_t channels = pChannels ? *pChannels : 0;
+ uint32_t latency = pLatencyMs ? *pLatencyMs : 0;
+
data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- remote()->transact(IS_MUSIC_ACTIVE, data, &reply);
+ data.writeInt32(devices);
+ data.writeInt32(samplingRate);
+ data.writeInt32(format);
+ data.writeInt32(channels);
+ data.writeInt32(latency);
+ data.writeInt32(flags);
+ remote()->transact(OPEN_OUTPUT, data, &reply);
+ void *output;
+ reply.read(&output, sizeof(void *));
+ LOGV("openOutput() returned output, %p", output);
+ devices = reply.readInt32();
+ if (pDevices) *pDevices = devices;
+ samplingRate = reply.readInt32();
+ if (pSamplingRate) *pSamplingRate = samplingRate;
+ format = reply.readInt32();
+ if (pFormat) *pFormat = format;
+ channels = reply.readInt32();
+ if (pChannels) *pChannels = channels;
+ latency = reply.readInt32();
+ if (pLatencyMs) *pLatencyMs = latency;
+ return output;
+ }
+
+ virtual void *openDuplicateOutput(void *output1, void *output2)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.write(&output1, sizeof(void *));
+ data.write(&output2, sizeof(void *));
+ remote()->transact(OPEN_DUPLICATE_OUTPUT, data, &reply);
+ void *output;
+ reply.read(&output, sizeof(void *));
+ return output;
+ }
+
+ virtual status_t closeOutput(void *output)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.write(&output, sizeof(void *));
+ remote()->transact(CLOSE_OUTPUT, data, &reply);
return reply.readInt32();
}
- virtual status_t setParameter(const char* key, const char* value)
+ virtual status_t suspendOutput(void *output)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeCString(key);
- data.writeCString(value);
- remote()->transact(SET_PARAMETER, data, &reply);
+ data.write(&output, sizeof(void *));
+ remote()->transact(SUSPEND_OUTPUT, data, &reply);
return reply.readInt32();
}
-
- virtual void registerClient(const sp<IAudioFlingerClient>& client)
+
+ virtual status_t restoreOutput(void *output)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeStrongBinder(client->asBinder());
- remote()->transact(REGISTER_CLIENT, data, &reply);
+ data.write(&output, sizeof(void *));
+ remote()->transact(RESTORE_OUTPUT, data, &reply);
+ return reply.readInt32();
}
-
- virtual size_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
+
+ virtual void *openInput(uint32_t *pDevices,
+ uint32_t *pSamplingRate,
+ uint32_t *pFormat,
+ uint32_t *pChannels,
+ uint32_t acoustics)
{
Parcel data, reply;
+ uint32_t devices = pDevices ? *pDevices : 0;
+ uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
+ uint32_t format = pFormat ? *pFormat : 0;
+ uint32_t channels = pChannels ? *pChannels : 0;
+
data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32(sampleRate);
+ data.writeInt32(devices);
+ data.writeInt32(samplingRate);
data.writeInt32(format);
- data.writeInt32(channelCount);
- remote()->transact(GET_INPUTBUFFERSIZE, data, &reply);
- return reply.readInt32();
+ data.writeInt32(channels);
+ data.writeInt32(acoustics);
+ remote()->transact(OPEN_INPUT, data, &reply);
+ void *input;
+ reply.read(&input, sizeof(void *));
+ devices = reply.readInt32();
+ if (pDevices) *pDevices = devices;
+ samplingRate = reply.readInt32();
+ if (pSamplingRate) *pSamplingRate = samplingRate;
+ format = reply.readInt32();
+ if (pFormat) *pFormat = format;
+ channels = reply.readInt32();
+ if (pChannels) *pChannels = channels;
+ return input;
}
-
- virtual void wakeUp()
+
+ virtual status_t closeInput(void *input)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- remote()->transact(WAKE_UP, data, &reply, IBinder::FLAG_ONEWAY);
- return;
+ data.write(&input, sizeof(void *));
+ remote()->transact(CLOSE_INPUT, data, &reply);
+ return reply.readInt32();
}
- virtual bool isA2dpEnabled() const
+ virtual status_t setStreamOutput(uint32_t stream, void *output)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- remote()->transact(IS_A2DP_ENABLED, data, &reply);
- return (bool)reply.readInt32();
+ data.writeInt32(stream);
+ data.write(&output, sizeof(void *));
+ remote()->transact(SET_STREAM_OUTPUT, data, &reply);
+ return reply.readInt32();
}
};
@@ -367,10 +470,12 @@ status_t BnAudioFlinger::onTransact(
size_t bufferCount = data.readInt32();
uint32_t flags = data.readInt32();
sp<IMemory> buffer = interface_cast<IMemory>(data.readStrongBinder());
+ void *output;
+ data.read(&output, sizeof(void *));
status_t status;
sp<IAudioTrack> track = createTrack(pid,
streamType, sampleRate, format,
- channelCount, bufferCount, flags, buffer, &status);
+ channelCount, bufferCount, flags, buffer, output, &status);
reply->writeInt32(status);
reply->writeStrongBinder(track->asBinder());
return NO_ERROR;
@@ -378,14 +483,15 @@ status_t BnAudioFlinger::onTransact(
case OPEN_RECORD: {
CHECK_INTERFACE(IAudioFlinger, data, reply);
pid_t pid = data.readInt32();
- int inputSource = data.readInt32();
+ void *input;
+ data.read(&input, sizeof(void *));
uint32_t sampleRate = data.readInt32();
int format = data.readInt32();
int channelCount = data.readInt32();
size_t bufferCount = data.readInt32();
uint32_t flags = data.readInt32();
status_t status;
- sp<IAudioRecord> record = openRecord(pid, inputSource,
+ sp<IAudioRecord> record = openRecord(pid, input,
sampleRate, format, channelCount, bufferCount, flags, &status);
reply->writeInt32(status);
reply->writeStrongBinder(record->asBinder());
@@ -393,31 +499,36 @@ status_t BnAudioFlinger::onTransact(
} break;
case SAMPLE_RATE: {
CHECK_INTERFACE(IAudioFlinger, data, reply);
- int output = data.readInt32();
+ void *output;
+ data.read(&output, sizeof(void *));
reply->writeInt32( sampleRate(output) );
return NO_ERROR;
} break;
case CHANNEL_COUNT: {
CHECK_INTERFACE(IAudioFlinger, data, reply);
- int output = data.readInt32();
+ void *output;
+ data.read(&output, sizeof(void *));
reply->writeInt32( channelCount(output) );
return NO_ERROR;
} break;
case FORMAT: {
CHECK_INTERFACE(IAudioFlinger, data, reply);
- int output = data.readInt32();
+ void *output;
+ data.read(&output, sizeof(void *));
reply->writeInt32( format(output) );
return NO_ERROR;
} break;
case FRAME_COUNT: {
CHECK_INTERFACE(IAudioFlinger, data, reply);
- int output = data.readInt32();
+ void *output;
+ data.read(&output, sizeof(void *));
reply->writeInt32( frameCount(output) );
return NO_ERROR;
} break;
case LATENCY: {
CHECK_INTERFACE(IAudioFlinger, data, reply);
- int output = data.readInt32();
+ void *output;
+ data.read(&output, sizeof(void *));
reply->writeInt32( latency(output) );
return NO_ERROR;
} break;
@@ -444,7 +555,10 @@ status_t BnAudioFlinger::onTransact(
case SET_STREAM_VOLUME: {
CHECK_INTERFACE(IAudioFlinger, data, reply);
int stream = data.readInt32();
- reply->writeInt32( setStreamVolume(stream, data.readFloat()) );
+ float volume = data.readFloat();
+ void *output;
+ data.read(&output, sizeof(void *));
+ reply->writeInt32( setStreamVolume(stream, volume, output) );
return NO_ERROR;
} break;
case SET_STREAM_MUTE: {
@@ -456,7 +570,9 @@ status_t BnAudioFlinger::onTransact(
case STREAM_VOLUME: {
CHECK_INTERFACE(IAudioFlinger, data, reply);
int stream = data.readInt32();
- reply->writeFloat( streamVolume(stream) );
+ void *output;
+ data.read(&output, sizeof(void *));
+ reply->writeFloat( streamVolume(stream, output) );
return NO_ERROR;
} break;
case STREAM_MUTE: {
@@ -465,31 +581,12 @@ status_t BnAudioFlinger::onTransact(
reply->writeInt32( streamMute(stream) );
return NO_ERROR;
} break;
- case SET_ROUTING: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- int mode = data.readInt32();
- uint32_t routes = data.readInt32();
- uint32_t mask = data.readInt32();
- reply->writeInt32( setRouting(mode, routes, mask) );
- return NO_ERROR;
- } break;
- case GET_ROUTING: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- int mode = data.readInt32();
- reply->writeInt32( getRouting(mode) );
- return NO_ERROR;
- } break;
case SET_MODE: {
CHECK_INTERFACE(IAudioFlinger, data, reply);
int mode = data.readInt32();
reply->writeInt32( setMode(mode) );
return NO_ERROR;
} break;
- case GET_MODE: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- reply->writeInt32( getMode() );
- return NO_ERROR;
- } break;
case SET_MIC_MUTE: {
CHECK_INTERFACE(IAudioFlinger, data, reply);
int state = data.readInt32();
@@ -506,13 +603,23 @@ status_t BnAudioFlinger::onTransact(
reply->writeInt32( isMusicActive() );
return NO_ERROR;
} break;
- case SET_PARAMETER: {
+ case SET_PARAMETERS: {
CHECK_INTERFACE(IAudioFlinger, data, reply);
- const char *key = data.readCString();
- const char *value = data.readCString();
- reply->writeInt32( setParameter(key, value) );
+ void *ioHandle;
+ data.read(&ioHandle, sizeof(void *));
+ String8 keyValuePairs(data.readString8());
+ reply->writeInt32(setParameters(ioHandle, keyValuePairs));
return NO_ERROR;
- } break;
+ } break;
+ case GET_PARAMETERS: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ void *ioHandle;
+ data.read(&ioHandle, sizeof(void *));
+ String8 keys(data.readString8());
+ reply->writeString8(getParameters(ioHandle, keys));
+ return NO_ERROR;
+ } break;
+
case REGISTER_CLIENT: {
CHECK_INTERFACE(IAudioFlinger, data, reply);
sp<IAudioFlingerClient> client = interface_cast<IAudioFlingerClient>(data.readStrongBinder());
@@ -527,14 +634,93 @@ status_t BnAudioFlinger::onTransact(
reply->writeInt32( getInputBufferSize(sampleRate, format, channelCount) );
return NO_ERROR;
} break;
- case WAKE_UP: {
+ case OPEN_OUTPUT: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ uint32_t devices = data.readInt32();
+ uint32_t samplingRate = data.readInt32();
+ uint32_t format = data.readInt32();
+ uint32_t channels = data.readInt32();
+ uint32_t latency = data.readInt32();
+ uint32_t flags = data.readInt32();
+ void *output = openOutput(&devices,
+ &samplingRate,
+ &format,
+ &channels,
+ &latency,
+ flags);
+ LOGV("OPEN_OUTPUT output, %p", output);
+ reply->write(&output, sizeof(void *));
+ reply->writeInt32(devices);
+ reply->writeInt32(samplingRate);
+ reply->writeInt32(format);
+ reply->writeInt32(channels);
+ reply->writeInt32(latency);
+ return NO_ERROR;
+ } break;
+ case OPEN_DUPLICATE_OUTPUT: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ void *output1;
+ void *output2;
+ data.read(&output1, sizeof(void *));
+ data.read(&output2, sizeof(void *));
+ void *output = openDuplicateOutput(output1, output2);
+ reply->write(&output, sizeof(void *));
+ return NO_ERROR;
+ } break;
+ case CLOSE_OUTPUT: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ void *output;
+ data.read(&output, sizeof(void *));
+ reply->writeInt32(closeOutput(output));
+ return NO_ERROR;
+ } break;
+ case SUSPEND_OUTPUT: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ void *output;
+ data.read(&output, sizeof(void *));
+ reply->writeInt32(suspendOutput(output));
+ return NO_ERROR;
+ } break;
+ case RESTORE_OUTPUT: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ void *output;
+ data.read(&output, sizeof(void *));
+ reply->writeInt32(restoreOutput(output));
+ return NO_ERROR;
+ } break;
+ case OPEN_INPUT: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ uint32_t devices = data.readInt32();
+ uint32_t samplingRate = data.readInt32();
+ uint32_t format = data.readInt32();
+ uint32_t channels = data.readInt32();
+ uint32_t acoutics = data.readInt32();
+
+ void *input = openInput(&devices,
+ &samplingRate,
+ &format,
+ &channels,
+ acoutics);
+ reply->write(&input, sizeof(void *));
+ reply->writeInt32(devices);
+ reply->writeInt32(samplingRate);
+ reply->writeInt32(format);
+ reply->writeInt32(channels);
+ return NO_ERROR;
+ } break;
+ case CLOSE_INPUT: {
CHECK_INTERFACE(IAudioFlinger, data, reply);
- wakeUp();
+ void *input;
+ data.read(&input, sizeof(void *));
+ reply->writeInt32(closeInput(input));
return NO_ERROR;
} break;
- case IS_A2DP_ENABLED: {
+ case SET_STREAM_OUTPUT: {
CHECK_INTERFACE(IAudioFlinger, data, reply);
- reply->writeInt32( (int)isA2dpEnabled() );
+ void *output;
+ uint32_t stream = data.readInt32();
+ data.read(&output, sizeof(void *));
+ reply->writeInt32(setStreamOutput(stream, output));
return NO_ERROR;
} break;
default:
diff --git a/media/libmedia/IAudioFlingerClient.cpp b/media/libmedia/IAudioFlingerClient.cpp
index 75699b4..eaae977 100644
--- a/media/libmedia/IAudioFlingerClient.cpp
+++ b/media/libmedia/IAudioFlingerClient.cpp
@@ -23,11 +23,12 @@
#include <binder/Parcel.h>
#include <media/IAudioFlingerClient.h>
+#include <media/AudioSystem.h>
namespace android {
enum {
- AUDIO_OUTPUT_CHANGED = IBinder::FIRST_CALL_TRANSACTION
+ IO_CONFIG_CHANGED = IBinder::FIRST_CALL_TRANSACTION
};
class BpAudioFlingerClient : public BpInterface<IAudioFlingerClient>
@@ -38,12 +39,25 @@ public:
{
}
- void a2dpEnabledChanged(bool enabled)
+ void ioConfigChanged(int event, void *param1, void *param2)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioFlingerClient::getInterfaceDescriptor());
- data.writeInt32((int)enabled);
- remote()->transact(AUDIO_OUTPUT_CHANGED, data, &reply, IBinder::FLAG_ONEWAY);
+ data.writeInt32(event);
+ data.write(&param1, sizeof(void *));
+ if (event == AudioSystem::STREAM_CONFIG_CHANGED) {
+ uint32_t stream = *(uint32_t *)param2;
+ LOGV("ioConfigChanged stream %d", stream);
+ data.writeInt32(stream);
+ } else if (event != AudioSystem::OUTPUT_CLOSED && event != AudioSystem::INPUT_CLOSED) {
+ AudioSystem::OutputDescriptor *desc = (AudioSystem::OutputDescriptor *)param2;
+ data.writeInt32(desc->samplingRate);
+ data.writeInt32(desc->format);
+ data.writeInt32(desc->channels);
+ data.writeInt32(desc->frameCount);
+ data.writeInt32(desc->latency);
+ }
+ remote()->transact(IO_CONFIG_CHANGED, data, &reply, IBinder::FLAG_ONEWAY);
}
};
@@ -55,10 +69,27 @@ status_t BnAudioFlingerClient::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code) {
- case AUDIO_OUTPUT_CHANGED: {
+ case IO_CONFIG_CHANGED: {
CHECK_INTERFACE(IAudioFlingerClient, data, reply);
- bool enabled = (bool)data.readInt32();
- a2dpEnabledChanged(enabled);
+ int event = data.readInt32();
+ void *param1;
+ void *param2 = 0;
+ AudioSystem::OutputDescriptor desc;
+ uint32_t stream;
+ data.read(&param1, sizeof(void *));
+ if (event == AudioSystem::STREAM_CONFIG_CHANGED) {
+ stream = data.readInt32();
+ param2 = &stream;
+ LOGV("STREAM_CONFIG_CHANGED stream %d", stream);
+ } else if (event != AudioSystem::OUTPUT_CLOSED && event != AudioSystem::INPUT_CLOSED) {
+ desc.samplingRate = data.readInt32();
+ desc.format = data.readInt32();
+ desc.channels = data.readInt32();
+ desc.frameCount = data.readInt32();
+ desc.latency = data.readInt32();
+ param2 = &desc;
+ }
+ ioConfigChanged(event, param1, param2);
return NO_ERROR;
} break;
default:
diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp
new file mode 100644
index 0000000..0d8a329
--- /dev/null
+++ b/media/libmedia/IAudioPolicyService.cpp
@@ -0,0 +1,423 @@
+/*
+**
+** Copyright 2009, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#define LOG_TAG "IAudioPolicyService"
+#include <utils/Log.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <binder/Parcel.h>
+
+#include <media/IAudioPolicyService.h>
+
+namespace android {
+
+enum {
+ SET_DEVICE_CONNECTION_STATE = IBinder::FIRST_CALL_TRANSACTION,
+ GET_DEVICE_CONNECTION_STATE,
+ SET_PHONE_STATE,
+ SET_RINGER_MODE,
+ SET_FORCE_USE,
+ GET_FORCE_USE,
+ GET_OUTPUT,
+ START_OUTPUT,
+ STOP_OUTPUT,
+ RELEASE_OUTPUT,
+ GET_INPUT,
+ START_INPUT,
+ STOP_INPUT,
+ RELEASE_INPUT,
+ INIT_STREAM_VOLUME,
+ SET_STREAM_VOLUME,
+ GET_STREAM_VOLUME
+};
+
+class BpAudioPolicyService : public BpInterface<IAudioPolicyService>
+{
+public:
+ BpAudioPolicyService(const sp<IBinder>& impl)
+ : BpInterface<IAudioPolicyService>(impl)
+ {
+ }
+
+ virtual status_t setDeviceConnectionState(
+ AudioSystem::audio_devices device,
+ AudioSystem::device_connection_state state,
+ const char *device_address)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(static_cast <uint32_t>(device));
+ data.writeInt32(static_cast <uint32_t>(state));
+ data.writeCString(device_address);
+ remote()->transact(SET_DEVICE_CONNECTION_STATE, data, &reply);
+ return static_cast <status_t> (reply.readInt32());
+ }
+
+ virtual AudioSystem::device_connection_state getDeviceConnectionState(
+ AudioSystem::audio_devices device,
+ const char *device_address)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(static_cast <uint32_t>(device));
+ data.writeCString(device_address);
+ remote()->transact(GET_DEVICE_CONNECTION_STATE, data, &reply);
+ return static_cast <AudioSystem::device_connection_state>(reply.readInt32());
+ }
+
+ virtual status_t setPhoneState(int state)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(state);
+ remote()->transact(SET_PHONE_STATE, data, &reply);
+ return static_cast <status_t> (reply.readInt32());
+ }
+
+ virtual status_t setRingerMode(uint32_t mode, uint32_t mask)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(mode);
+ data.writeInt32(mask);
+ remote()->transact(SET_RINGER_MODE, data, &reply);
+ return static_cast <status_t> (reply.readInt32());
+ }
+
+ virtual status_t setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(static_cast <uint32_t>(usage));
+ data.writeInt32(static_cast <uint32_t>(config));
+ remote()->transact(SET_FORCE_USE, data, &reply);
+ return static_cast <status_t> (reply.readInt32());
+ }
+
+ virtual AudioSystem::forced_config getForceUse(AudioSystem::force_use usage)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(static_cast <uint32_t>(usage));
+ remote()->transact(GET_FORCE_USE, data, &reply);
+ return static_cast <AudioSystem::forced_config> (reply.readInt32());
+ }
+
+ virtual audio_io_handle_t getOutput(
+ AudioSystem::stream_type stream,
+ uint32_t samplingRate,
+ uint32_t format,
+ uint32_t channels,
+ AudioSystem::output_flags flags)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(static_cast <uint32_t>(stream));
+ data.writeInt32(samplingRate);
+ data.writeInt32(static_cast <uint32_t>(format));
+ data.writeInt32(channels);
+ data.writeInt32(static_cast <uint32_t>(flags));
+ remote()->transact(GET_OUTPUT, data, &reply);
+ audio_io_handle_t output;
+ reply.read(&output, sizeof(audio_io_handle_t));
+ return output;
+ }
+
+ virtual status_t startOutput(audio_io_handle_t output, AudioSystem::stream_type stream)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.write(&output, sizeof(audio_io_handle_t));
+ data.writeInt32(stream);
+ remote()->transact(START_OUTPUT, data, &reply);
+ return static_cast <status_t> (reply.readInt32());
+ }
+
+ virtual status_t stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.write(&output, sizeof(audio_io_handle_t));
+ data.writeInt32(stream);
+ remote()->transact(STOP_OUTPUT, data, &reply);
+ return static_cast <status_t> (reply.readInt32());
+ }
+
+ virtual void releaseOutput(audio_io_handle_t output)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.write(&output, sizeof(audio_io_handle_t));
+ remote()->transact(RELEASE_OUTPUT, data, &reply);
+ }
+
+ virtual audio_io_handle_t getInput(
+ int inputSource,
+ uint32_t samplingRate,
+ uint32_t format,
+ uint32_t channels,
+ AudioSystem::audio_in_acoustics acoustics)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(inputSource);
+ data.writeInt32(samplingRate);
+ data.writeInt32(static_cast <uint32_t>(format));
+ data.writeInt32(channels);
+ data.writeInt32(static_cast <uint32_t>(acoustics));
+ remote()->transact(GET_INPUT, data, &reply);
+ audio_io_handle_t input;
+ reply.read(&input, sizeof(audio_io_handle_t));
+ return input;
+ }
+
+ virtual status_t startInput(audio_io_handle_t input)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.write(&input, sizeof(audio_io_handle_t));
+ remote()->transact(START_INPUT, data, &reply);
+ return static_cast <status_t> (reply.readInt32());
+ }
+
+ virtual status_t stopInput(audio_io_handle_t input)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.write(&input, sizeof(audio_io_handle_t));
+ remote()->transact(STOP_INPUT, data, &reply);
+ return static_cast <status_t> (reply.readInt32());
+ }
+
+ virtual void releaseInput(audio_io_handle_t input)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.write(&input, sizeof(audio_io_handle_t));
+ remote()->transact(RELEASE_INPUT, data, &reply);
+ }
+
+ virtual status_t initStreamVolume(AudioSystem::stream_type stream,
+ int indexMin,
+ int indexMax)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(static_cast <uint32_t>(stream));
+ data.writeInt32(indexMin);
+ data.writeInt32(indexMax);
+ remote()->transact(INIT_STREAM_VOLUME, data, &reply);
+ return static_cast <status_t> (reply.readInt32());
+ }
+
+ virtual status_t setStreamVolumeIndex(AudioSystem::stream_type stream, int index)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(static_cast <uint32_t>(stream));
+ data.writeInt32(index);
+ remote()->transact(SET_STREAM_VOLUME, data, &reply);
+ return static_cast <status_t> (reply.readInt32());
+ }
+
+ virtual status_t getStreamVolumeIndex(AudioSystem::stream_type stream, int *index)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(static_cast <uint32_t>(stream));
+ remote()->transact(GET_STREAM_VOLUME, data, &reply);
+ int lIndex = reply.readInt32();
+ if (index) *index = lIndex;
+ return static_cast <status_t> (reply.readInt32());
+ }
+};
+
+IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService");
+
+// ----------------------------------------------------------------------
+
+
+status_t BnAudioPolicyService::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ switch(code) {
+ case SET_DEVICE_CONNECTION_STATE: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ AudioSystem::audio_devices device = static_cast <AudioSystem::audio_devices>(data.readInt32());
+ AudioSystem::device_connection_state state = static_cast <AudioSystem::device_connection_state>(data.readInt32());
+ const char *device_address = data.readCString();
+ reply->writeInt32(static_cast <uint32_t>(setDeviceConnectionState(device, state, device_address)));
+ return NO_ERROR;
+ } break;
+
+ case GET_DEVICE_CONNECTION_STATE: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ AudioSystem::audio_devices device = static_cast <AudioSystem::audio_devices>(data.readInt32());
+ const char *device_address = data.readCString();
+ reply->writeInt32(static_cast <uint32_t>(getDeviceConnectionState(device, device_address)));
+ return NO_ERROR;
+ } break;
+
+ case SET_PHONE_STATE: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ reply->writeInt32(static_cast <uint32_t>(setPhoneState(data.readInt32())));
+ return NO_ERROR;
+ } break;
+
+ case SET_RINGER_MODE: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ uint32_t mode = data.readInt32();
+ uint32_t mask = data.readInt32();
+ reply->writeInt32(static_cast <uint32_t>(setRingerMode(mode, mask)));
+ return NO_ERROR;
+ } break;
+
+ case SET_FORCE_USE: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ AudioSystem::force_use usage = static_cast <AudioSystem::force_use>(data.readInt32());
+ AudioSystem::forced_config config = static_cast <AudioSystem::forced_config>(data.readInt32());
+ reply->writeInt32(static_cast <uint32_t>(setForceUse(usage, config)));
+ return NO_ERROR;
+ } break;
+
+ case GET_FORCE_USE: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ AudioSystem::force_use usage = static_cast <AudioSystem::force_use>(data.readInt32());
+ reply->writeInt32(static_cast <uint32_t>(getForceUse(usage)));
+ return NO_ERROR;
+ } break;
+
+ case GET_OUTPUT: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ AudioSystem::stream_type stream = static_cast <AudioSystem::stream_type>(data.readInt32());
+ uint32_t samplingRate = data.readInt32();
+ uint32_t format = data.readInt32();
+ uint32_t channels = data.readInt32();
+ AudioSystem::output_flags flags = static_cast <AudioSystem::output_flags>(data.readInt32());
+
+ audio_io_handle_t output = getOutput(stream,
+ samplingRate,
+ format,
+ channels,
+ flags);
+ reply->write(&output, sizeof(audio_io_handle_t));
+ return NO_ERROR;
+ } break;
+
+ case START_OUTPUT: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ audio_io_handle_t output;
+ data.read(&output, sizeof(audio_io_handle_t));
+ uint32_t stream = data.readInt32();
+ reply->writeInt32(static_cast <uint32_t>(startOutput(output, (AudioSystem::stream_type)stream)));
+ return NO_ERROR;
+ } break;
+
+ case STOP_OUTPUT: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ audio_io_handle_t output;
+ data.read(&output, sizeof(audio_io_handle_t));
+ uint32_t stream = data.readInt32();
+ reply->writeInt32(static_cast <uint32_t>(stopOutput(output, (AudioSystem::stream_type)stream)));
+ return NO_ERROR;
+ } break;
+
+ case RELEASE_OUTPUT: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ audio_io_handle_t output;
+ data.read(&output, sizeof(audio_io_handle_t));
+ releaseOutput(output);
+ return NO_ERROR;
+ } break;
+
+ case GET_INPUT: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ int inputSource = data.readInt32();
+ uint32_t samplingRate = data.readInt32();
+ uint32_t format = data.readInt32();
+ uint32_t channels = data.readInt32();
+ AudioSystem::audio_in_acoustics acoustics = static_cast <AudioSystem::audio_in_acoustics>(data.readInt32());
+ audio_io_handle_t input = getInput(inputSource,
+ samplingRate,
+ format,
+ channels,
+ acoustics);
+ reply->write(&input, sizeof(audio_io_handle_t));
+ return NO_ERROR;
+ } break;
+
+ case START_INPUT: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ audio_io_handle_t input;
+ data.read(&input, sizeof(audio_io_handle_t));
+ reply->writeInt32(static_cast <uint32_t>(startInput(input)));
+ return NO_ERROR;
+ } break;
+
+ case STOP_INPUT: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ audio_io_handle_t input;
+ data.read(&input, sizeof(audio_io_handle_t));
+ reply->writeInt32(static_cast <uint32_t>(stopInput(input)));
+ return NO_ERROR;
+ } break;
+
+ case RELEASE_INPUT: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ audio_io_handle_t input;
+ data.read(&input, sizeof(audio_io_handle_t));
+ releaseInput(input);
+ return NO_ERROR;
+ } break;
+
+ case INIT_STREAM_VOLUME: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ AudioSystem::stream_type stream = static_cast <AudioSystem::stream_type>(data.readInt32());
+ int indexMin = data.readInt32();
+ int indexMax = data.readInt32();
+ reply->writeInt32(static_cast <uint32_t>(initStreamVolume(stream, indexMin,indexMax)));
+ return NO_ERROR;
+ } break;
+
+ case SET_STREAM_VOLUME: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ AudioSystem::stream_type stream = static_cast <AudioSystem::stream_type>(data.readInt32());
+ int index = data.readInt32();
+ reply->writeInt32(static_cast <uint32_t>(setStreamVolumeIndex(stream, index)));
+ return NO_ERROR;
+ } break;
+
+ case GET_STREAM_VOLUME: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ AudioSystem::stream_type stream = static_cast <AudioSystem::stream_type>(data.readInt32());
+ int index;
+ status_t status = getStreamVolumeIndex(stream, &index);
+ reply->writeInt32(index);
+ reply->writeInt32(static_cast <uint32_t>(status));
+ return NO_ERROR;
+ } break;
+
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/media/libmedia/JetPlayer.cpp b/media/libmedia/JetPlayer.cpp
index 586aacb..ee9e1d8 100644
--- a/media/libmedia/JetPlayer.cpp
+++ b/media/libmedia/JetPlayer.cpp
@@ -99,7 +99,7 @@ int JetPlayer::init()
mAudioTrack->set(AudioSystem::MUSIC, //TODO parametrize this
pLibConfig->sampleRate,
1, // format = PCM 16bits per sample,
- pLibConfig->numChannels,
+ (pLibConfig->numChannels == 2) ? AudioSystem::CHANNEL_OUT_STEREO : AudioSystem::CHANNEL_OUT_MONO,
mTrackBufferSize,
0);
diff --git a/media/libmedia/ToneGenerator.cpp b/media/libmedia/ToneGenerator.cpp
index 5435da7..3ea64ae 100644
--- a/media/libmedia/ToneGenerator.cpp
+++ b/media/libmedia/ToneGenerator.cpp
@@ -1001,7 +1001,7 @@ bool ToneGenerator::initAudioTrack() {
// Open audio track in mono, PCM 16bit, default sampling rate, default buffer size
mpAudioTrack
- = new AudioTrack(mStreamType, 0, AudioSystem::PCM_16_BIT, 1, 0, 0, audioCallback, this, 0);
+ = new AudioTrack(mStreamType, 0, AudioSystem::PCM_16_BIT, AudioSystem::CHANNEL_OUT_MONO, 0, 0, audioCallback, this, 0);
if (mpAudioTrack == 0) {
LOGE("AudioTrack allocation failed");
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 77f7434..1d960c5 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -1310,11 +1310,21 @@ status_t MediaPlayerService::AudioOutput::open(
AudioTrack *t;
if (mCallback != NULL) {
t = new AudioTrack(
- mStreamType, sampleRate, format, channelCount, frameCount,
- 0 /* flags */, CallbackWrapper, this);
+ mStreamType,
+ sampleRate,
+ format,
+ (channelCount == 2) ? AudioSystem::CHANNEL_OUT_STEREO : AudioSystem::CHANNEL_OUT_MONO,
+ frameCount,
+ 0 /* flags */,
+ CallbackWrapper,
+ this);
} else {
t = new AudioTrack(
- mStreamType, sampleRate, format, channelCount, frameCount);
+ mStreamType,
+ sampleRate,
+ format,
+ (channelCount == 2) ? AudioSystem::CHANNEL_OUT_STEREO : AudioSystem::CHANNEL_OUT_MONO,
+ frameCount);
}
if ((t == 0) || (t->initCheck() != NO_ERROR)) {
diff --git a/media/mediaserver/main_mediaserver.cpp b/media/mediaserver/main_mediaserver.cpp
index fbea0d4..7094cfa 100644
--- a/media/mediaserver/main_mediaserver.cpp
+++ b/media/mediaserver/main_mediaserver.cpp
@@ -28,6 +28,7 @@
#include <AudioFlinger.h>
#include <CameraService.h>
#include <MediaPlayerService.h>
+#include <AudioPolicyService.h>
#include <private/android_filesystem_config.h>
using namespace android;
@@ -40,6 +41,7 @@ int main(int argc, char** argv)
AudioFlinger::instantiate();
MediaPlayerService::instantiate();
CameraService::instantiate();
+ AudioPolicyService::instantiate();
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}