summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/media/AudioRecord.h17
-rw-r--r--include/media/AudioSystem.h2
-rw-r--r--include/media/AudioTrack.h45
-rw-r--r--include/media/EffectApi.h22
-rw-r--r--include/media/EffectFactoryApi.h12
-rw-r--r--include/media/IAudioFlinger.h27
-rw-r--r--include/media/IAudioTrack.h5
-rw-r--r--include/private/media/AudioEffectShared.h51
-rw-r--r--include/private/media/AudioTrackShared.h3
-rw-r--r--media/libeffects/EffectEqualizer.cpp2
-rw-r--r--media/libeffects/EffectReverb.c5
-rw-r--r--media/libeffects/EffectReverb.h2
-rw-r--r--media/libeffects/EffectsFactory.c12
-rw-r--r--media/libmedia/AudioRecord.cpp21
-rw-r--r--media/libmedia/AudioSystem.cpp6
-rw-r--r--media/libmedia/AudioTrack.cpp66
-rw-r--r--media/libmedia/IAudioFlinger.cpp260
-rw-r--r--media/libmedia/IAudioTrack.cpp24
18 files changed, 531 insertions, 51 deletions
diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h
index 92bc126..d956882 100644
--- a/include/media/AudioRecord.h
+++ b/include/media/AudioRecord.h
@@ -142,7 +142,8 @@ public:
uint32_t flags = 0,
callback_t cbf = 0,
void* user = 0,
- int notificationFrames = 0);
+ int notificationFrames = 0,
+ int sessionId = 0);
/* Terminates the AudioRecord and unregisters it from AudioFlinger.
@@ -168,7 +169,8 @@ public:
callback_t cbf = 0,
void* user = 0,
int notificationFrames = 0,
- bool threadCanCallJava = false);
+ bool threadCanCallJava = false,
+ int sessionId = 0);
/* Result of constructing the AudioRecord. This must be checked
@@ -270,6 +272,16 @@ public:
*/
audio_io_handle_t getInput();
+ /* returns the audio session ID associated to this AudioRecord.
+ *
+ * Parameters:
+ * none.
+ *
+ * Returned value:
+ * AudioRecord session ID.
+ */
+ int getSessionId();
+
/* 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,
@@ -356,6 +368,7 @@ private:
uint32_t mFlags;
uint32_t mChannels;
audio_io_handle_t mInput;
+ int mSessionId;
};
}; // namespace android
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index 9caef8f..f21e83d 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -230,6 +230,8 @@ public:
static status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, int stream = DEFAULT);
static unsigned int getInputFramesLost(audio_io_handle_t ioHandle);
+
+ static int newAudioSessionId();
//
// AudioPolicyService interface
//
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index cc4ab74..c46df1e 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -138,7 +138,8 @@ public:
uint32_t flags = 0,
callback_t cbf = 0,
void* user = 0,
- int notificationFrames = 0);
+ int notificationFrames = 0,
+ int sessionId = 0);
/* Creates an audio track and registers it with AudioFlinger. With this constructor,
* The PCM data to be rendered by AudioTrack is passed in a shared memory buffer
@@ -157,7 +158,8 @@ public:
uint32_t flags = 0,
callback_t cbf = 0,
void* user = 0,
- int notificationFrames = 0);
+ int notificationFrames = 0,
+ int sessionId = 0);
/* Terminates the AudioTrack and unregisters it from AudioFlinger.
* Also destroys all resources assotiated with the AudioTrack.
@@ -182,7 +184,8 @@ public:
void* user = 0,
int notificationFrames = 0,
const sp<IMemory>& sharedBuffer = 0,
- bool threadCanCallJava = false);
+ bool threadCanCallJava = false,
+ int sessionId = 0);
/* Result of constructing the AudioTrack. This must be checked
@@ -239,10 +242,17 @@ public:
/* set volume for this track, mostly used for games' sound effects
+ * left and right volumes. Levels must be <= 1.0.
*/
- void setVolume(float left, float right);
+ status_t setVolume(float left, float right);
void getVolume(float* left, float* right);
+ /* set the send level for this track. An auxiliary effect should be attached
+ * to the track with attachEffect(). Level must be <= 1.0.
+ */
+ status_t setSendLevel(float level);
+ void getSendLevel(float* level);
+
/* set sample rate for this track, mostly used for games' sound effects
*/
status_t setSampleRate(int sampleRate);
@@ -340,6 +350,31 @@ public:
*/
audio_io_handle_t getOutput();
+ /* returns the unique ID associated to this track.
+ *
+ * Parameters:
+ * none.
+ *
+ * Returned value:
+ * AudioTrack ID.
+ */
+ int getSessionId();
+
+
+ /* Attach track auxiliary output to specified effect. Used effectId = 0
+ * to detach track from effect.
+ *
+ * Parameters:
+ *
+ * effectId: effectId obtained from AudioEffect::id().
+ *
+ * Returned status (from utils/Errors.h) can be:
+ * - NO_ERROR: successful operation
+ * - INVALID_OPERATION: the effect is not an auxiliary effect.
+ * - BAD_VALUE: The specified effect ID is invalid
+ */
+ status_t attachAuxEffect(int effectId);
+
/* 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,
@@ -406,6 +441,7 @@ private:
sp<AudioTrackThread> mAudioTrackThread;
float mVolume[2];
+ float mSendLevel;
uint32_t mFrameCount;
audio_track_cblk_t* mCblk;
@@ -431,6 +467,7 @@ private:
uint32_t mNewPosition;
uint32_t mUpdatePeriod;
uint32_t mFlags;
+ int mSessionId;
};
diff --git a/include/media/EffectApi.h b/include/media/EffectApi.h
index a1bc3b8..97874f7 100644
--- a/include/media/EffectApi.h
+++ b/include/media/EffectApi.h
@@ -114,7 +114,8 @@ typedef struct effect_descriptor_s {
// +---------------------------+-----------+-----------------------------------
// | Volume management | 5..6 | 0 none
// | | | 1 implements volume control
-// | | | 2..3 reserved
+// | | | 2 requires volume indication
+// | | | 3 reserved
// +---------------------------+-----------+-----------------------------------
// | Device management | 7..8 | 0 none
// | | | 1 requires device updates
@@ -154,6 +155,7 @@ typedef struct effect_descriptor_s {
// volume control
#define EFFECT_FLAG_VOLUME_MASK 0x00000060
#define EFFECT_FLAG_VOLUME_CTRL 0x00000020
+#define EFFECT_FLAG_VOLUME_IND 0x00000040
#define EFFECT_FLAG_VOLUME_NONE 0x00000000
// device control
@@ -296,10 +298,12 @@ struct effect_interface_s {
// | Set and get volume. Used by | EFFECT_CMD_SET_VOLUME | size: n * sizeof(uint32_t) | size: n * sizeof(uint32_t)
// | audio framework to delegate | | data: volume for each channel | data: volume for each channel
// | volume control to effect engine| | defined in effect_config_t in | defined in effect_config_t in
-// | The engine must return the | | 8.24 fixed point format | 8.24 fixed point format
-// | volume that should be applied | | |
-// | before the effect is processed | | |
-// | The overall volume (the volume | | |
+// | If volume control flag is set | | 8.24 fixed point format | 8.24 fixed point format
+// | in the effect descriptor, the | | | It is legal to receive a null
+// | effect engine must return the | | | pointer as pReplyData in which
+// | volume that should be applied | | | case the effect framework has
+// | before the effect is processed | | | delegated volume control to
+// | The overall volume (the volume | | | another effect.
// | actually applied by the effect | | |
// | multiplied by the returned | | |
// | value) should match the | | |
@@ -370,7 +374,7 @@ typedef struct buffer_provider_s {
// structure that defines both input and output buffer configurations and is
// passed by the EFFECT_CMD_CONFIGURE command.
typedef struct buffer_config_s {
- audio_buffer_t buffer; // buffer for use by process() function is not passed explicitly
+ audio_buffer_t buffer; // buffer for use by process() function if not passed explicitly
uint32_t samplingRate; // sampling rate
uint32_t channels; // channel mask (see audio_channels_e in AudioCommon.h)
buffer_provider_t bufferProvider; // buffer provider
@@ -457,7 +461,7 @@ typedef struct effect_param_s {
//
// Function: EffectQueryNumberEffects
//
-// Description: Returns the number of different effect exposed by the
+// Description: Returns the number of different effects exposed by the
// library. Each effect must have a unique effect uuid (see
// effect_descriptor_t). This function together with EffectQueryNext()
// is used to enumerate all effects present in the library.
@@ -475,7 +479,7 @@ typedef struct effect_param_s {
// *pNumEffects: updated with number of effects in library
//
////////////////////////////////////////////////////////////////////////////////
-typedef int32_t (*effect_QueryNumberEffects_t)(int32_t *pNumEffects);
+typedef int32_t (*effect_QueryNumberEffects_t)(uint32_t *pNumEffects);
////////////////////////////////////////////////////////////////////////////////
//
@@ -521,7 +525,7 @@ typedef int32_t (*effect_QueryNextEffect_t)(effect_descriptor_t *pDescriptor);
// returned value: 0 successful operation.
// -ENODEV library failed to initialize
// -EINVAL invalid pEffectUuid or pInterface
-// -ENOENT No effect with this uuid found
+// -ENOENT no effect with this uuid found
// *pInterface: updated with the effect interface handle.
//
////////////////////////////////////////////////////////////////////////////////
diff --git a/include/media/EffectFactoryApi.h b/include/media/EffectFactoryApi.h
index 8179c23..6cc9932 100644
--- a/include/media/EffectFactoryApi.h
+++ b/include/media/EffectFactoryApi.h
@@ -34,7 +34,7 @@ extern "C" {
//
// Function: EffectQueryNumberEffects
//
-// Description: Returns the number of different effect in all loaded libraries.
+// Description: Returns the number of different effects in all loaded libraries.
// Each effect must have a different effect uuid (see
// effect_descriptor_t). This function together with EffectQueryNext()
// is used to enumerate all effects present in all loaded libraries.
@@ -52,7 +52,7 @@ extern "C" {
// *pNumEffects: updated with number of effects in factory
//
////////////////////////////////////////////////////////////////////////////////
-int EffectQueryNumberEffects(int *pNumEffects);
+int EffectQueryNumberEffects(uint32_t *pNumEffects);
////////////////////////////////////////////////////////////////////////////////
//
@@ -98,7 +98,7 @@ int EffectQueryNext(effect_descriptor_t *pDescriptor);
// returned value: 0 successful operation.
// -ENODEV factory failed to initialize
// -EINVAL invalid pEffectUuid or pInterface
-// -ENOENT No effect with this uuid found
+// -ENOENT no effect with this uuid found
// *pInterface: updated with the effect interface.
//
////////////////////////////////////////////////////////////////////////////////
@@ -140,7 +140,7 @@ int EffectRelease(effect_interface_t interface);
//
// Output:
// returned value: 0 successful operation.
-// -ENODEV Effect factory not initialized or
+// -ENODEV effect factory not initialized or
// library could not be loaded or
// library does not implement required functions
// -EINVAL invalid libPath string or handle
@@ -159,7 +159,7 @@ int EffectLoadLibrary(const char *libPath, int *handle);
//
// Output:
// returned value: 0 successful operation.
-// -ENODEV Effect factory not initialized
+// -ENODEV effect factory not initialized
// -ENOENT invalid handle
//
////////////////////////////////////////////////////////////////////////////////
@@ -184,7 +184,7 @@ int EffectUnloadLibrary(int handle);
// returned value: 0 successful operation.
// -ENODEV factory failed to initialize
// -EINVAL invalid pEffectUuid or pDescriptor
-// -ENOENT No effect with this uuid found
+// -ENOENT no effect with this uuid found
// *pDescriptor: updated with the effect descriptor.
//
////////////////////////////////////////////////////////////////////////////////
diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h
index c147632..ccfa530 100644
--- a/include/media/IAudioFlinger.h
+++ b/include/media/IAudioFlinger.h
@@ -27,6 +27,9 @@
#include <media/IAudioTrack.h>
#include <media/IAudioRecord.h>
#include <media/IAudioFlingerClient.h>
+#include <media/EffectApi.h>
+#include <media/IEffect.h>
+#include <media/IEffectClient.h>
#include <utils/String8.h>
namespace android {
@@ -51,6 +54,7 @@ public:
uint32_t flags,
const sp<IMemory>& sharedBuffer,
int output,
+ int *sessionId,
status_t *status) = 0;
virtual sp<IAudioRecord> openRecord(
@@ -61,6 +65,7 @@ public:
int channelCount,
int frameCount,
uint32_t flags,
+ int *sessionId,
status_t *status) = 0;
/* query the audio hardware state. This state never changes,
@@ -134,6 +139,28 @@ public:
virtual status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, int output) = 0;
virtual unsigned int getInputFramesLost(int ioHandle) = 0;
+
+ virtual int newAudioSessionId() = 0;
+
+ virtual status_t loadEffectLibrary(const char *libPath, int *handle) = 0;
+
+ virtual status_t unloadEffectLibrary(int handle) = 0;
+
+ virtual status_t queryNumberEffects(uint32_t *numEffects) = 0;
+
+ virtual status_t queryNextEffect(effect_descriptor_t *pDescriptor) = 0;
+
+ virtual status_t getEffectDescriptor(effect_uuid_t *pEffectUUID, effect_descriptor_t *pDescriptor) = 0;
+
+ virtual sp<IEffect> createEffect(pid_t pid,
+ effect_descriptor_t *pDesc,
+ const sp<IEffectClient>& client,
+ int32_t priority,
+ int output,
+ int sessionId,
+ status_t *status,
+ int *id,
+ int *enabled) = 0;
};
diff --git a/include/media/IAudioTrack.h b/include/media/IAudioTrack.h
index de6426a..47d530b 100644
--- a/include/media/IAudioTrack.h
+++ b/include/media/IAudioTrack.h
@@ -62,6 +62,11 @@ public:
*/
virtual void pause() = 0;
+ /* Attach track auxiliary output to specified effect. Use effectId = 0
+ * to detach track from effect.
+ */
+ virtual status_t attachAuxEffect(int effectId) = 0;
+
/* get this tracks control block */
virtual sp<IMemory> getCblk() const = 0;
};
diff --git a/include/private/media/AudioEffectShared.h b/include/private/media/AudioEffectShared.h
new file mode 100644
index 0000000..a3a99a4
--- /dev/null
+++ b/include/private/media/AudioEffectShared.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2010 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_EFFECTCBASESHARED_H
+#define ANDROID_EFFECTCBASESHARED_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/threads.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+// Size of buffer used to exchange parameters between application and mediaserver processes.
+#define EFFECT_PARAM_BUFFER_SIZE 1024
+
+
+// Shared memory area used to exchange parameters between application and mediaserver
+// process.
+struct effect_param_cblk_t
+{
+ Mutex lock;
+ volatile uint32_t clientIndex; // Current read/write index for application
+ volatile uint32_t serverIndex; // Current read/write index for mediaserver
+ uint8_t* buffer; // start of parameter buffer
+
+ effect_param_cblk_t()
+ : lock(Mutex::SHARED), clientIndex(0), serverIndex(0) {}
+};
+
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_EFFECTCBASESHARED_H
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index cd47fdf..1510f87 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -78,7 +78,8 @@ struct audio_track_cblk_t
uint16_t bufferTimeoutMs; // Maximum cumulated timeout before restarting audioflinger
uint16_t waitTimeMs; // Cumulated wait time
- uint32_t reserved;
+ uint16_t sendLevel;
+ uint16_t reserved;
// Cache line boundary (32 bytes)
audio_track_cblk_t();
uint32_t stepUser(uint32_t frameCount);
diff --git a/media/libeffects/EffectEqualizer.cpp b/media/libeffects/EffectEqualizer.cpp
index c08f4f5..e39e595 100644
--- a/media/libeffects/EffectEqualizer.cpp
+++ b/media/libeffects/EffectEqualizer.cpp
@@ -114,7 +114,7 @@ int Equalizer_setParameter(AudioEqualizer * pEqualizer, int32_t *pParam, void *p
//--- Effect Library Interface Implementation
//
-extern "C" int EffectQueryNumberEffects(int *pNumEffects) {
+extern "C" int EffectQueryNumberEffects(uint32_t *pNumEffects) {
*pNumEffects = 1;
gEffectIndex = 0;
return 0;
diff --git a/media/libeffects/EffectReverb.c b/media/libeffects/EffectReverb.c
index 3181504..202f50b 100644
--- a/media/libeffects/EffectReverb.c
+++ b/media/libeffects/EffectReverb.c
@@ -18,7 +18,8 @@
//
#define LOG_NDEBUG 0
#include <cutils/log.h>
-
+#include <stdlib.h>
+#include <string.h>
#include <stdbool.h>
#include "EffectReverb.h"
#include "EffectsMath.h"
@@ -86,7 +87,7 @@ static const effect_descriptor_t * const gDescriptors[] = {
/*--- Effect Library Interface Implementation ---*/
-int EffectQueryNumberEffects(int *pNumEffects) {
+int EffectQueryNumberEffects(uint32_t *pNumEffects) {
*pNumEffects = sizeof(gDescriptors) / sizeof(const effect_descriptor_t *)
- 1;
gEffectIndex = 0;
diff --git a/media/libeffects/EffectReverb.h b/media/libeffects/EffectReverb.h
index cd14891..578e09e 100644
--- a/media/libeffects/EffectReverb.h
+++ b/media/libeffects/EffectReverb.h
@@ -292,7 +292,7 @@ typedef struct reverb_module_s {
* Effect API
*------------------------------------
*/
-int EffectQueryNumberEffects(int *pNumEffects);
+int EffectQueryNumberEffects(uint32_t *pNumEffects);
int EffectQueryNext(effect_descriptor_t *pDescriptor);
int EffectCreate(effect_uuid_t *effectUID, effect_interface_t *pInterface);
int EffectRelease(effect_interface_t interface);
diff --git a/media/libeffects/EffectsFactory.c b/media/libeffects/EffectsFactory.c
index 35a1001..6800765 100644
--- a/media/libeffects/EffectsFactory.c
+++ b/media/libeffects/EffectsFactory.c
@@ -39,7 +39,7 @@ static int gInitDone; // true is global initialization has been preformed
static int init();
static int loadLibrary(const char *libPath, int *handle);
static int unloadLibrary(int handle);
-static int numEffectModules();
+static uint32_t numEffectModules();
static int findEffect(effect_uuid_t *uuid, lib_entry_t **lib, effect_descriptor_t **desc);
static void dumpEffectDescriptor(effect_descriptor_t *desc, char *str, size_t len);
@@ -96,7 +96,7 @@ const struct effect_interface_s gInterface = {
// Effect Factory Interface functions
/////////////////////////////////////////////////
-int EffectQueryNumberEffects(int *pNumEffects)
+int EffectQueryNumberEffects(uint32_t *pNumEffects)
{
int ret = init();
if (ret < 0) {
@@ -353,8 +353,8 @@ int loadLibrary(const char *libPath, int *handle)
effect_QueryNextEffect_t queryFx;
effect_CreateEffect_t createFx;
effect_ReleaseEffect_t releaseFx;
- int numFx;
- int fx;
+ uint32_t numFx;
+ uint32_t fx;
int ret;
list_elem_t *e, *descHead = NULL;
lib_entry_t *l;
@@ -525,9 +525,9 @@ int unloadLibrary(int handle)
-int numEffectModules() {
+uint32_t numEffectModules() {
list_elem_t *e = gLibraryList;
- int cnt = 0;
+ uint32_t cnt = 0;
// Reset pointers for EffectQueryNext()
gCurLib = e;
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index fd2b1ce..a2436ab 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -45,7 +45,7 @@ namespace android {
// ---------------------------------------------------------------------------
AudioRecord::AudioRecord()
- : mStatus(NO_INIT)
+ : mStatus(NO_INIT), mSessionId(0)
{
}
@@ -58,11 +58,12 @@ AudioRecord::AudioRecord(
uint32_t flags,
callback_t cbf,
void* user,
- int notificationFrames)
- : mStatus(NO_INIT)
+ int notificationFrames,
+ int sessionId)
+ : mStatus(NO_INIT), mSessionId(0)
{
mStatus = set(inputSource, sampleRate, format, channels,
- frameCount, flags, cbf, user, notificationFrames);
+ frameCount, flags, cbf, user, notificationFrames, sessionId);
}
AudioRecord::~AudioRecord()
@@ -91,7 +92,8 @@ status_t AudioRecord::set(
callback_t cbf,
void* user,
int notificationFrames,
- bool threadCanCallJava)
+ bool threadCanCallJava,
+ int sessionId)
{
LOGV("set(): sampleRate %d, channels %d, frameCount %d",sampleRate, channels, frameCount);
@@ -119,6 +121,7 @@ status_t AudioRecord::set(
if (!AudioSystem::isInputChannel(channels)) {
return BAD_VALUE;
}
+
int channelCount = AudioSystem::popCount(channels);
audio_io_handle_t input = AudioSystem::getInput(inputSource,
@@ -164,6 +167,8 @@ status_t AudioRecord::set(
notificationFrames = frameCount/2;
}
+ mSessionId = sessionId;
+
// create the IAudioRecord
status_t status = openRecord(sampleRate, format, channelCount,
frameCount, flags, input);
@@ -414,6 +419,7 @@ status_t AudioRecord::openRecord(
channelCount,
frameCount,
((uint16_t)flags) << 16,
+ &mSessionId,
&status);
if (record == 0) {
LOGE("AudioFlinger could not create record track, status: %d", status);
@@ -532,6 +538,11 @@ audio_io_handle_t AudioRecord::getInput()
return mInput;
}
+int AudioRecord::getSessionId()
+{
+ return mSessionId;
+}
+
// -------------------------------------------------------------------------
ssize_t AudioRecord::read(void* buffer, size_t userSize)
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index 5e6ce42..c77f551 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -364,6 +364,12 @@ unsigned int AudioSystem::getInputFramesLost(audio_io_handle_t ioHandle) {
return result;
}
+int AudioSystem::newAudioSessionId() {
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return 0;
+ return af->newAudioSessionId();
+}
+
// ---------------------------------------------------------------------------
void AudioSystem::AudioFlingerClient::binderDied(const wp<IBinder>& who) {
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index c350532..4b61131 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -58,7 +58,8 @@ AudioTrack::AudioTrack(
uint32_t flags,
callback_t cbf,
void* user,
- int notificationFrames)
+ int notificationFrames,
+ int sessionId)
: mStatus(NO_INIT)
{
mStatus = set(streamType, sampleRate, format, channels,
@@ -74,7 +75,8 @@ AudioTrack::AudioTrack(
uint32_t flags,
callback_t cbf,
void* user,
- int notificationFrames)
+ int notificationFrames,
+ int sessionId)
: mStatus(NO_INIT)
{
mStatus = set(streamType, sampleRate, format, channels,
@@ -110,7 +112,8 @@ status_t AudioTrack::set(
void* user,
int notificationFrames,
const sp<IMemory>& sharedBuffer,
- bool threadCanCallJava)
+ bool threadCanCallJava,
+ int sessionId)
{
LOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size());
@@ -171,8 +174,11 @@ status_t AudioTrack::set(
mVolume[LEFT] = 1.0f;
mVolume[RIGHT] = 1.0f;
+ mSendLevel = 0;
mFrameCount = frameCount;
mNotificationFramesReq = notificationFrames;
+ mSessionId = sessionId;
+
// create the IAudioTrack
status_t status = createTrack(streamType, sampleRate, format, channelCount,
frameCount, flags, sharedBuffer, output, true);
@@ -396,19 +402,49 @@ bool AudioTrack::muted() const
return mMuted;
}
-void AudioTrack::setVolume(float left, float right)
+status_t AudioTrack::setVolume(float left, float right)
{
+ if (left > 1.0f || right > 1.0f) {
+ return BAD_VALUE;
+ }
+
mVolume[LEFT] = left;
mVolume[RIGHT] = right;
// write must be atomic
- mCblk->volumeLR = (int32_t(int16_t(left * 0x1000)) << 16) | int16_t(right * 0x1000);
+ mCblk->volumeLR = (uint32_t(uint16_t(right * 0x1000)) << 16) | uint16_t(left * 0x1000);
+
+ return NO_ERROR;
}
void AudioTrack::getVolume(float* left, float* right)
{
- *left = mVolume[LEFT];
- *right = mVolume[RIGHT];
+ if (left != NULL) {
+ *left = mVolume[LEFT];
+ }
+ if (right != NULL) {
+ *right = mVolume[RIGHT];
+ }
+}
+
+status_t AudioTrack::setSendLevel(float level)
+{
+ if (level > 1.0f) {
+ return BAD_VALUE;
+ }
+
+ mSendLevel = level;
+
+ mCblk->sendLevel = uint16_t(level * 0x1000);
+
+ return NO_ERROR;
+}
+
+void AudioTrack::getSendLevel(float* level)
+{
+ if (level != NULL) {
+ *level = mSendLevel;
+ }
}
status_t AudioTrack::setSampleRate(int rate)
@@ -563,6 +599,16 @@ audio_io_handle_t AudioTrack::getOutput()
mCblk->sampleRate, mFormat, mChannels, (AudioSystem::output_flags)mFlags);
}
+int AudioTrack::getSessionId()
+{
+ return mSessionId;
+}
+
+status_t AudioTrack::attachAuxEffect(int effectId)
+{
+ return mAudioTrack->attachAuxEffect(effectId);
+}
+
// -------------------------------------------------------------------------
status_t AudioTrack::createTrack(
@@ -647,6 +693,7 @@ status_t AudioTrack::createTrack(
((uint16_t)flags) << 16,
sharedBuffer,
output,
+ &mSessionId,
&status);
if (track == 0) {
@@ -672,7 +719,8 @@ status_t AudioTrack::createTrack(
mCblk->stepUser(mCblk->frameCount);
}
- mCblk->volumeLR = (int32_t(int16_t(mVolume[LEFT] * 0x1000)) << 16) | int16_t(mVolume[RIGHT] * 0x1000);
+ mCblk->volumeLR = (uint32_t(uint16_t(mVolume[RIGHT] * 0x1000)) << 16) | uint16_t(mVolume[LEFT] * 0x1000);
+ mCblk->sendLevel = uint16_t(mSendLevel * 0x1000);
mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
mCblk->waitTimeMs = 0;
mRemainingFrames = mNotificationFramesAct;
@@ -1016,7 +1064,7 @@ audio_track_cblk_t::audio_track_cblk_t()
: lock(Mutex::SHARED), cv(Condition::SHARED), user(0), server(0),
userBase(0), serverBase(0), buffers(0), frameCount(0),
loopStart(UINT_MAX), loopEnd(UINT_MAX), loopCount(0), volumeLR(0),
- flags(0)
+ flags(0), sendLevel(0)
{
}
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
index 47bcc12..f2a8db3 100644
--- a/media/libmedia/IAudioFlinger.cpp
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -62,7 +62,14 @@ enum {
SET_STREAM_OUTPUT,
SET_VOICE_VOLUME,
GET_RENDER_POSITION,
- GET_INPUT_FRAMES_LOST
+ GET_INPUT_FRAMES_LOST,
+ NEW_AUDIO_SESSION_ID,
+ LOAD_EFFECT_LIBRARY,
+ UNLOAD_EFFECT_LIBRARY,
+ QUERY_NUM_EFFECTS,
+ QUERY_NEXT_EFFECT,
+ GET_EFFECT_DESCRIPTOR,
+ CREATE_EFFECT
};
class BpAudioFlinger : public BpInterface<IAudioFlinger>
@@ -83,6 +90,7 @@ public:
uint32_t flags,
const sp<IMemory>& sharedBuffer,
int output,
+ int *sessionId,
status_t *status)
{
Parcel data, reply;
@@ -97,10 +105,19 @@ public:
data.writeInt32(flags);
data.writeStrongBinder(sharedBuffer->asBinder());
data.writeInt32(output);
+ int lSessionId = 0;
+ if (sessionId != NULL) {
+ lSessionId = *sessionId;
+ }
+ data.writeInt32(lSessionId);
status_t lStatus = remote()->transact(CREATE_TRACK, data, &reply);
if (lStatus != NO_ERROR) {
LOGE("createTrack error: %s", strerror(-lStatus));
} else {
+ lSessionId = reply.readInt32();
+ if (sessionId != NULL) {
+ *sessionId = lSessionId;
+ }
lStatus = reply.readInt32();
track = interface_cast<IAudioTrack>(reply.readStrongBinder());
}
@@ -118,6 +135,7 @@ public:
int channelCount,
int frameCount,
uint32_t flags,
+ int *sessionId,
status_t *status)
{
Parcel data, reply;
@@ -130,10 +148,19 @@ public:
data.writeInt32(channelCount);
data.writeInt32(frameCount);
data.writeInt32(flags);
+ int lSessionId = 0;
+ if (sessionId != NULL) {
+ lSessionId = *sessionId;
+ }
+ data.writeInt32(lSessionId);
status_t lStatus = remote()->transact(OPEN_RECORD, data, &reply);
if (lStatus != NO_ERROR) {
LOGE("openRecord error: %s", strerror(-lStatus));
} else {
+ lSessionId = reply.readInt32();
+ if (sessionId != NULL) {
+ *sessionId = lSessionId;
+ }
lStatus = reply.readInt32();
record = interface_cast<IAudioRecord>(reply.readStrongBinder());
}
@@ -497,6 +524,157 @@ public:
remote()->transact(GET_INPUT_FRAMES_LOST, data, &reply);
return reply.readInt32();
}
+
+ virtual int newAudioSessionId()
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ status_t status = remote()->transact(NEW_AUDIO_SESSION_ID, data, &reply);
+ int id = 0;
+ if (status == NO_ERROR) {
+ id = reply.readInt32();
+ }
+ return id;
+ }
+
+ virtual status_t loadEffectLibrary(const char *libPath, int *handle)
+ {
+ if (libPath == NULL || handle == NULL) {
+ return BAD_VALUE;
+ }
+ *handle = 0;
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeCString(libPath);
+ status_t status = remote()->transact(LOAD_EFFECT_LIBRARY, data, &reply);
+ if (status == NO_ERROR) {
+ status = reply.readInt32();
+ if (status == NO_ERROR) {
+ *handle = reply.readInt32();
+ }
+ }
+ return status;
+ }
+
+ virtual status_t unloadEffectLibrary(int handle)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32(handle);
+ status_t status = remote()->transact(UNLOAD_EFFECT_LIBRARY, data, &reply);
+ if (status == NO_ERROR) {
+ status = reply.readInt32();
+ }
+ return status;
+ }
+
+ virtual status_t queryNumberEffects(uint32_t *numEffects)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ status_t status = remote()->transact(QUERY_NUM_EFFECTS, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = reply.readInt32();
+ if (status != NO_ERROR) {
+ return status;
+ }
+ if (numEffects) {
+ *numEffects = (uint32_t)reply.readInt32();
+ }
+ return NO_ERROR;
+ }
+
+ virtual status_t queryNextEffect(effect_descriptor_t *pDescriptor)
+ {
+ if (pDescriptor == NULL) {
+ return BAD_VALUE;
+ }
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ status_t status = remote()->transact(QUERY_NEXT_EFFECT, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = reply.readInt32();
+ if (status != NO_ERROR) {
+ return status;
+ }
+ reply.read(pDescriptor, sizeof(effect_descriptor_t));
+ return NO_ERROR;
+ }
+
+ virtual status_t getEffectDescriptor(effect_uuid_t *pUuid, effect_descriptor_t *pDescriptor)
+ {
+ if (pUuid == NULL || pDescriptor == NULL) {
+ return BAD_VALUE;
+ }
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.write(pUuid, sizeof(effect_uuid_t));
+ status_t status = remote()->transact(GET_EFFECT_DESCRIPTOR, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = reply.readInt32();
+ if (status != NO_ERROR) {
+ return status;
+ }
+ reply.read(pDescriptor, sizeof(effect_descriptor_t));
+ return NO_ERROR;
+ }
+
+ virtual sp<IEffect> createEffect(pid_t pid,
+ effect_descriptor_t *pDesc,
+ const sp<IEffectClient>& client,
+ int32_t priority,
+ int output,
+ int sessionId,
+ status_t *status,
+ int *id,
+ int *enabled)
+ {
+ Parcel data, reply;
+ sp<IEffect> effect;
+
+ if (pDesc == NULL) {
+ return effect;
+ if (status) {
+ *status = BAD_VALUE;
+ }
+ }
+
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32(pid);
+ data.write(pDesc, sizeof(effect_descriptor_t));
+ data.writeStrongBinder(client->asBinder());
+ data.writeInt32(priority);
+ data.writeInt32(output);
+ data.writeInt32(sessionId);
+
+ status_t lStatus = remote()->transact(CREATE_EFFECT, data, &reply);
+ if (lStatus != NO_ERROR) {
+ LOGE("createEffect error: %s", strerror(-lStatus));
+ } else {
+ lStatus = reply.readInt32();
+ int tmp = reply.readInt32();
+ if (id) {
+ *id = tmp;
+ }
+ tmp = reply.readInt32();
+ if (enabled) {
+ *enabled = tmp;
+ }
+ effect = interface_cast<IEffect>(reply.readStrongBinder());
+ reply.read(pDesc, sizeof(effect_descriptor_t));
+ }
+ if (status) {
+ *status = lStatus;
+ }
+
+ return effect;
+ }
};
IMPLEMENT_META_INTERFACE(AudioFlinger, "android.media.IAudioFlinger");
@@ -518,10 +696,12 @@ status_t BnAudioFlinger::onTransact(
uint32_t flags = data.readInt32();
sp<IMemory> buffer = interface_cast<IMemory>(data.readStrongBinder());
int output = data.readInt32();
+ int sessionId = data.readInt32();
status_t status;
sp<IAudioTrack> track = createTrack(pid,
streamType, sampleRate, format,
- channelCount, bufferCount, flags, buffer, output, &status);
+ channelCount, bufferCount, flags, buffer, output, &sessionId, &status);
+ reply->writeInt32(sessionId);
reply->writeInt32(status);
reply->writeStrongBinder(track->asBinder());
return NO_ERROR;
@@ -535,9 +715,11 @@ status_t BnAudioFlinger::onTransact(
int channelCount = data.readInt32();
size_t bufferCount = data.readInt32();
uint32_t flags = data.readInt32();
+ int sessionId = data.readInt32();
status_t status;
sp<IAudioRecord> record = openRecord(pid, input,
- sampleRate, format, channelCount, bufferCount, flags, &status);
+ sampleRate, format, channelCount, bufferCount, flags, &sessionId, &status);
+ reply->writeInt32(sessionId);
reply->writeInt32(status);
reply->writeStrongBinder(record->asBinder());
return NO_ERROR;
@@ -768,7 +950,79 @@ status_t BnAudioFlinger::onTransact(
reply->writeInt32(getInputFramesLost(ioHandle));
return NO_ERROR;
} break;
+ case NEW_AUDIO_SESSION_ID: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ reply->writeInt32(newAudioSessionId());
+ return NO_ERROR;
+ } break;
+ case LOAD_EFFECT_LIBRARY: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ int handle;
+ status_t status = loadEffectLibrary(data.readCString(), &handle);
+ reply->writeInt32(status);
+ if (status == NO_ERROR) {
+ reply->writeInt32(handle);
+ }
+ return NO_ERROR;
+ }
+ case UNLOAD_EFFECT_LIBRARY: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ reply->writeInt32(unloadEffectLibrary(data.readInt32()));
+ return NO_ERROR;
+ }
+ case QUERY_NUM_EFFECTS: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ uint32_t numEffects;
+ status_t status = queryNumberEffects(&numEffects);
+ reply->writeInt32(status);
+ if (status == NO_ERROR) {
+ reply->writeInt32((int32_t)numEffects);
+ }
+ return NO_ERROR;
+ }
+ case QUERY_NEXT_EFFECT: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ effect_descriptor_t desc;
+ status_t status = queryNextEffect(&desc);
+ reply->writeInt32(status);
+ if (status == NO_ERROR) {
+ reply->write(&desc, sizeof(effect_descriptor_t));
+ }
+ return NO_ERROR;
+ }
+ case GET_EFFECT_DESCRIPTOR: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ effect_uuid_t uuid;
+ data.read(&uuid, sizeof(effect_uuid_t));
+ effect_descriptor_t desc;
+ status_t status = getEffectDescriptor(&uuid, &desc);
+ reply->writeInt32(status);
+ if (status == NO_ERROR) {
+ reply->write(&desc, sizeof(effect_descriptor_t));
+ }
+ return NO_ERROR;
+ }
+ case CREATE_EFFECT: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ pid_t pid = data.readInt32();
+ effect_descriptor_t desc;
+ data.read(&desc, sizeof(effect_descriptor_t));
+ sp<IEffectClient> client = interface_cast<IEffectClient>(data.readStrongBinder());
+ int32_t priority = data.readInt32();
+ int output = data.readInt32();
+ int sessionId = data.readInt32();
+ status_t status;
+ int id;
+ int enabled;
+ sp<IEffect> effect = createEffect(pid, &desc, client, priority, output, sessionId, &status, &id, &enabled);
+ reply->writeInt32(status);
+ reply->writeInt32(id);
+ reply->writeInt32(enabled);
+ reply->writeStrongBinder(effect->asBinder());
+ reply->write(&desc, sizeof(effect_descriptor_t));
+ return NO_ERROR;
+ } break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/media/libmedia/IAudioTrack.cpp b/media/libmedia/IAudioTrack.cpp
index 01ffd75..bc8ff34 100644
--- a/media/libmedia/IAudioTrack.cpp
+++ b/media/libmedia/IAudioTrack.cpp
@@ -34,7 +34,8 @@ enum {
STOP,
FLUSH,
MUTE,
- PAUSE
+ PAUSE,
+ ATTACH_AUX_EFFECT
};
class BpAudioTrack : public BpInterface<IAudioTrack>
@@ -97,7 +98,21 @@ public:
cblk = interface_cast<IMemory>(reply.readStrongBinder());
}
return cblk;
- }
+ }
+
+ virtual status_t attachAuxEffect(int effectId)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
+ data.writeInt32(effectId);
+ status_t status = remote()->transact(ATTACH_AUX_EFFECT, data, &reply);
+ if (status == NO_ERROR) {
+ status = reply.readInt32();
+ } else {
+ LOGW("attachAuxEffect() error: %s", strerror(-status));
+ }
+ return status;
+ }
};
IMPLEMENT_META_INTERFACE(AudioTrack, "android.media.IAudioTrack");
@@ -138,6 +153,11 @@ status_t BnAudioTrack::onTransact(
pause();
return NO_ERROR;
}
+ case ATTACH_AUX_EFFECT: {
+ CHECK_INTERFACE(IAudioTrack, data, reply);
+ reply->writeInt32(attachAuxEffect(data.readInt32()));
+ return NO_ERROR;
+ } break;
default:
return BBinder::onTransact(code, data, reply, flags);
}