summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
Diffstat (limited to 'services')
-rw-r--r--services/audioflinger/Android.mk4
-rw-r--r--services/audioflinger/AudioFlinger.cpp935
-rw-r--r--services/audioflinger/AudioFlinger.h215
-rw-r--r--services/audioflinger/AudioMixer.cpp4
-rw-r--r--services/audioflinger/AudioPolicyService.cpp11
-rw-r--r--services/camera/libcameraservice/Camera2Client.cpp2
-rw-r--r--services/camera/libcameraservice/CameraClient.cpp75
-rw-r--r--services/camera/libcameraservice/CameraClient.h3
-rw-r--r--services/camera/libcameraservice/CameraHardwareInterface.h16
-rw-r--r--services/camera/libcameraservice/CameraService.cpp15
-rw-r--r--services/camera/libcameraservice/CameraService.h4
11 files changed, 1236 insertions, 48 deletions
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
index 2899953..a14c205 100644
--- a/services/audioflinger/Android.mk
+++ b/services/audioflinger/Android.mk
@@ -13,6 +13,10 @@ include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
+ifeq ($(TARGET_QCOM_AUDIO_VARIANT),caf)
+LOCAL_CFLAGS += -DQCOM_ENHANCED_AUDIO
+endif
+
LOCAL_SRC_FILES:= \
AudioFlinger.cpp \
AudioMixer.cpp.arm \
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 1913b6f..bcb9756 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1,6 +1,11 @@
/*
**
** Copyright 2007, The Android Open Source Project
+** Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+**
+** Copyright (c) 2012, The Linux Foundation. All rights reserved.
+** Not a Contribution, Apache license notifications and license are retained
+** for attribution purposes only.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
@@ -100,6 +105,11 @@
#define ALOGVV(a...) do { } while(0)
#endif
+#ifdef QCOM_HARDWARE
+#define DIRECT_TRACK_EOS 1
+static const char lockName[] = "DirectTrack";
+#endif
+
namespace android {
static const char kDeadlockedString[] = "AudioFlinger may be deadlocked\n";
@@ -206,11 +216,13 @@ static int load_audio_interface(const char *if_name, audio_hw_device_t **dev)
if (rc) {
goto out;
}
+#if !defined(ICS_AUDIO_BLOB) && !defined(MR0_AUDIO_BLOB)
if ((*dev)->common.version != AUDIO_DEVICE_API_VERSION_CURRENT) {
ALOGE("%s wrong audio hw device version %04x", __func__, (*dev)->common.version);
rc = BAD_VALUE;
goto out;
}
+#endif
return 0;
out:
@@ -218,6 +230,14 @@ out:
return rc;
}
+static uint32_t getInputChannelCount(uint32_t channels) {
+#ifdef QCOM_HARDWARE
+ // only mono or stereo and 5.1 are supported for input sources
+ return popcount((channels) & (AUDIO_CHANNEL_IN_STEREO | AUDIO_CHANNEL_IN_MONO | AUDIO_CHANNEL_IN_5POINT1));
+#else
+ return popcount(channels);
+#endif
+}
// ----------------------------------------------------------------------------
AudioFlinger::AudioFlinger()
@@ -235,10 +255,18 @@ AudioFlinger::AudioFlinger()
void AudioFlinger::onFirstRef()
{
int rc = 0;
+#ifdef QCOM_HARDWARE
+ mA2DPHandle = -1;
+#endif
Mutex::Autolock _l(mLock);
/* TODO: move all this work into an Init() function */
+#ifdef QCOM_HARDWARE
+ mLPASessionId = -2; // -2 is invalid session ID
+ mIsEffectConfigChanged = false;
+ mLPAEffectChain = NULL;
+#endif
char val_str[PROPERTY_VALUE_MAX] = { 0 };
if (property_get("ro.audio.flinger_standbytime_ms", val_str, NULL) >= 0) {
uint32_t int_val;
@@ -298,6 +326,13 @@ AudioFlinger::AudioHwDevice* AudioFlinger::findSuitableHwDev_l(
if ((dev->get_supported_devices != NULL) &&
(dev->get_supported_devices(dev) & devices) == devices)
return audioHwDevice;
+#ifdef ICS_AUDIO_BLOB
+ else if (dev->get_supported_devices == NULL && i != 0 &&
+ devices == 0x80)
+ // Reasonably safe assumption: A non-primary HAL without
+ // get_supported_devices is a locally-built A2DP binary
+ return audioHwDevice;
+#endif
}
} else {
// check a match for the requested module handle
@@ -544,9 +579,218 @@ Exit:
return trackHandle;
}
+#ifdef QCOM_HARDWARE
+sp<IDirectTrack> AudioFlinger::createDirectTrack(
+ pid_t pid,
+ uint32_t sampleRate,
+ audio_channel_mask_t channelMask,
+ audio_io_handle_t output,
+ int *sessionId,
+ IDirectTrackClient *client,
+ audio_stream_type_t streamType,
+ status_t *status)
+{
+ *status = NO_ERROR;
+ status_t lStatus = NO_ERROR;
+ sp<IDirectTrack> track = NULL;
+ DirectAudioTrack* directTrack = NULL;
+ Mutex::Autolock _l(mLock);
+
+ ALOGV("createDirectTrack() sessionId: %d sampleRate %d channelMask %d",
+ *sessionId, sampleRate, channelMask);
+ AudioSessionDescriptor *desc = mDirectAudioTracks.valueFor(output);
+ if(desc == NULL) {
+ ALOGE("Error: Invalid output (%d) to create direct audio track", output);
+ lStatus = BAD_VALUE;
+ goto Exit;
+ }
+ desc->mStreamType = streamType;
+ if (desc->flag & AUDIO_OUTPUT_FLAG_LPA) {
+ if (sessionId != NULL && *sessionId != AUDIO_SESSION_OUTPUT_MIX) {
+ for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+ sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
+ // Check if the session ID is already associated with a track
+ uint32_t sessions = t->hasAudioSession(*sessionId);
+
+ // check if an effect with same session ID is waiting for a ssession to be created
+ ALOGV("check if an effect with same session ID is waiting for a ssession to be created");
+ if ((mLPAEffectChain == NULL) && (sessions & PlaybackThread::EFFECT_SESSION)) {
+ // Clear reference to previous effect chain if any
+ t->mLock.lock();
+ ALOGV("getting the LPA effect chain and setting LPA flag to true.");
+ mLPAEffectChain = t->getEffectChain_l(*sessionId);
+ t->mLock.unlock();
+ }
+ }
+ mLPASessionId = *sessionId;
+ if (mLPAEffectChain != NULL) {
+ mLPAEffectChain->setLPAFlag(true);
+ // For LPA, the volume will be applied in DSP. No need for volume
+ // control in the Effect chain, so setting it to unity.
+ uint32_t volume = 0x1000000; // Equals to 1.0 in 8.24 format
+ mLPAEffectChain->setVolume_l(&volume,&volume);
+ } else {
+ ALOGW("There was no effectChain created for the sessionId(%d)", mLPASessionId);
+ }
+ mLPASampleRate = sampleRate;
+ mLPANumChannels = popcount(channelMask);
+ } else {
+ if(sessionId != NULL) {
+ ALOGE("Error: Invalid sessionID (%d) for direct audio track", *sessionId);
+ }
+ }
+ }
+ mLock.unlock();
+ directTrack = new DirectAudioTrack(this, output, desc, client, desc->flag);
+ desc->trackRefPtr = dynamic_cast<void *>(directTrack);
+ mLock.lock();
+ if (directTrack != 0) {
+ track = dynamic_cast<IDirectTrack *>(directTrack);
+ AudioEventObserver* obv = dynamic_cast<AudioEventObserver *>(directTrack);
+ ALOGE("setting observer mOutputDesc track %p, obv %p", track.get(), obv);
+ desc->stream->set_observer(desc->stream, reinterpret_cast<void *>(obv));
+ } else {
+ lStatus = BAD_VALUE;
+ }
+Exit:
+ if(lStatus) {
+ if (track != NULL) {
+ track.clear();
+ }
+ *status = lStatus;
+ }
+ return track;
+}
+
+void AudioFlinger::deleteEffectSession()
+{
+ Mutex::Autolock _l(mLock);
+ ALOGV("deleteSession");
+ // -2 is invalid session ID
+ mLPASessionId = -2;
+ if (mLPAEffectChain != NULL) {
+ mLPAEffectChain->setLPAFlag(false);
+ size_t i, numEffects = mLPAEffectChain->getNumEffects();
+ for(i = 0; i < numEffects; i++) {
+ sp<EffectModule> effect = mLPAEffectChain->getEffectFromIndex_l(i);
+ effect->setInBuffer(mLPAEffectChain->inBuffer());
+ if (i == numEffects-1) {
+ effect->setOutBuffer(mLPAEffectChain->outBuffer());
+ } else {
+ effect->setOutBuffer(mLPAEffectChain->inBuffer());
+ }
+ effect->configure();
+ }
+ mLPAEffectChain.clear();
+ mLPAEffectChain = NULL;
+ }
+}
+
+// ToDo: Should we go ahead with this frameCount?
+#define DEAFULT_FRAME_COUNT 1200
+void AudioFlinger::applyEffectsOn(void *token, int16_t *inBuffer, int16_t *outBuffer, int size)
+{
+ ALOGV("applyEffectsOn: inBuf %p outBuf %p size %d token %p", inBuffer, outBuffer, size, token);
+ // This might be the first buffer to apply effects after effect config change
+ // should not skip effects processing
+ mIsEffectConfigChanged = false;
+
+ volatile size_t numEffects = 0;
+ if(mLPAEffectChain != NULL) {
+ numEffects = mLPAEffectChain->getNumEffects();
+ }
+
+ if( numEffects > 0) {
+ size_t i = 0;
+ int16_t *pIn = inBuffer;
+ int16_t *pOut = outBuffer;
+
+ int frameCount = size / (sizeof(int16_t) * mLPANumChannels);
+
+ while(frameCount > 0) {
+ if(mLPAEffectChain == NULL) {
+ ALOGV("LPA Effect Chain is removed - No effects processing !!");
+ numEffects = 0;
+ break;
+ }
+ mLPAEffectChain->lock();
+
+ numEffects = mLPAEffectChain->getNumEffects();
+ if(!numEffects) {
+ ALOGV("applyEffectsOn: All the effects are removed - nothing to process");
+ mLPAEffectChain->unlock();
+ break;
+ }
+
+ int outFrameCount = (frameCount > DEAFULT_FRAME_COUNT ? DEAFULT_FRAME_COUNT: frameCount);
+ bool isEffectEnabled = false;
+ for(i = 0; i < numEffects; i++) {
+ // If effect configuration is changed while applying effects do not process further
+ if(mIsEffectConfigChanged) {
+ mLPAEffectChain->unlock();
+ ALOGV("applyEffectsOn: mIsEffectConfigChanged is set - no further processing");
+ return;
+ }
+ sp<EffectModule> effect = mLPAEffectChain->getEffectFromIndex_l(i);
+ if(effect == NULL) {
+ ALOGE("getEffectFromIndex_l(%d) returned NULL ptr", i);
+ mLPAEffectChain->unlock();
+ return;
+ }
+ if(i == 0) {
+ // For the first set input and output buffers different
+ isEffectEnabled = effect->isProcessEnabled();
+ effect->setInBuffer(pIn);
+ effect->setOutBuffer(pOut);
+ } else {
+ // For the remaining use previous effect's output buffer as input buffer
+ effect->setInBuffer(pOut);
+ effect->setOutBuffer(pOut);
+ }
+ // true indicates that it is being applied on LPA output
+ effect->configure(true, mLPASampleRate, mLPANumChannels, outFrameCount);
+ }
+
+ if(isEffectEnabled) {
+ // Clear the output buffer
+ memset(pOut, 0, (outFrameCount * mLPANumChannels * sizeof(int16_t)));
+ } else {
+ // Copy input buffer content to the output buffer
+ memcpy(pOut, pIn, (outFrameCount * mLPANumChannels * sizeof(int16_t)));
+ }
+
+ mLPAEffectChain->process_l();
+
+ mLPAEffectChain->unlock();
+
+ // Update input and output buffer pointers
+ pIn += (outFrameCount * mLPANumChannels);
+ pOut += (outFrameCount * mLPANumChannels);
+ frameCount -= outFrameCount;
+ }
+ }
+
+ if (!numEffects) {
+ ALOGV("applyEffectsOn: There are no effects to be applied");
+ if(inBuffer != outBuffer) {
+ // No effect applied so just copy input buffer to output buffer
+ memcpy(outBuffer, inBuffer, size);
+ }
+ }
+}
+#endif
+
uint32_t AudioFlinger::sampleRate(audio_io_handle_t output) const
{
Mutex::Autolock _l(mLock);
+#ifdef QCOM_HARDWARE
+ if (!mDirectAudioTracks.isEmpty()) {
+ AudioSessionDescriptor *desc = mDirectAudioTracks.valueFor(output);
+ if(desc != NULL) {
+ return desc->stream->common.get_sample_rate(&desc->stream->common);
+ }
+ }
+#endif
PlaybackThread *thread = checkPlaybackThread_l(output);
if (thread == NULL) {
ALOGW("sampleRate() unknown thread %d", output);
@@ -558,6 +802,12 @@ uint32_t AudioFlinger::sampleRate(audio_io_handle_t output) const
int AudioFlinger::channelCount(audio_io_handle_t output) const
{
Mutex::Autolock _l(mLock);
+#ifdef QCOM_HARDWARE
+ AudioSessionDescriptor *desc = mDirectAudioTracks.valueFor(output);
+ if(desc != NULL) {
+ return desc->stream->common.get_channels(&desc->stream->common);
+ }
+#endif
PlaybackThread *thread = checkPlaybackThread_l(output);
if (thread == NULL) {
ALOGW("channelCount() unknown thread %d", output);
@@ -580,6 +830,12 @@ audio_format_t AudioFlinger::format(audio_io_handle_t output) const
size_t AudioFlinger::frameCount(audio_io_handle_t output) const
{
Mutex::Autolock _l(mLock);
+#ifdef QCOM_HARDWARE
+ AudioSessionDescriptor *desc = mDirectAudioTracks.valueFor(output);
+ if(desc != NULL) {
+ return desc->stream->common.get_buffer_size(&desc->stream->common);
+ }
+#endif
PlaybackThread *thread = checkPlaybackThread_l(output);
if (thread == NULL) {
ALOGW("frameCount() unknown thread %d", output);
@@ -613,6 +869,9 @@ status_t AudioFlinger::setMasterVolume(float value)
return PERMISSION_DENIED;
}
+#ifdef QCOM_HARDWARE
+ mA2DPHandle = -1;
+#endif
Mutex::Autolock _l(mLock);
mMasterVolume = value;
@@ -724,6 +983,7 @@ status_t AudioFlinger::setMasterMute(bool muted)
mMasterMute = muted;
// Set master mute in the HALs which support it.
+#ifndef ICS_AUDIO_BLOB
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
AutoMutex lock(mHardwareLock);
AudioHwDevice *dev = mAudioHwDevs.valueAt(i);
@@ -734,6 +994,7 @@ status_t AudioFlinger::setMasterMute(bool muted)
}
mHardwareStatus = AUDIO_HW_IDLE;
}
+#endif
// Now set the master mute in each playback thread. Playback threads
// assigned to HALs which do not have master mute support will apply master
@@ -781,12 +1042,35 @@ status_t AudioFlinger::setStreamVolume(audio_stream_type_t stream, float value,
}
AutoMutex lock(mLock);
+#ifdef QCOM_HARDWARE
+ ALOGV("setStreamVolume stream %d, output %d, value %f",stream, output, value);
+ AudioSessionDescriptor *desc = NULL;
+ if (!mDirectAudioTracks.isEmpty()) {
+ desc = mDirectAudioTracks.valueFor(output);
+ if (desc != NULL) {
+ ALOGV("setStreamVolume for mAudioTracks size %d desc %p",mDirectAudioTracks.size(),desc);
+ if (desc->mStreamType == stream) {
+ mStreamTypes[stream].volume = value;
+ desc->stream->set_volume(desc->stream,
+ desc->mVolumeLeft * mStreamTypes[stream].volume,
+ desc->mVolumeRight* mStreamTypes[stream].volume);
+ return NO_ERROR;
+ }
+ }
+ }
+#endif
PlaybackThread *thread = NULL;
if (output) {
thread = checkPlaybackThread_l(output);
if (thread == NULL) {
+#ifdef QCOM_HARDWARE
+ if (desc != NULL) {
+ return NO_ERROR;
+ }
+#endif
return BAD_VALUE;
}
+
}
mStreamTypes[stream].volume = value;
@@ -913,6 +1197,26 @@ status_t AudioFlinger::setParameters(audio_io_handle_t ioHandle, const String8&
return final_result;
}
+#ifdef QCOM_HARDWARE
+ AudioSessionDescriptor *desc = NULL;
+ if (!mDirectAudioTracks.isEmpty()) {
+ desc = mDirectAudioTracks.valueFor(ioHandle);
+ if (desc != NULL) {
+ ALOGV("setParameters for mAudioTracks size %d desc %p",mDirectAudioTracks.size(),desc);
+ desc->stream->common.set_parameters(&desc->stream->common, keyValuePairs.string());
+ AudioParameter param = AudioParameter(keyValuePairs);
+ String8 key = String8(AudioParameter::keyRouting);
+ int device;
+ if (param.getInt(key, device) == NO_ERROR) {
+ if(mLPAEffectChain != NULL){
+ mLPAEffectChain->setDevice_l(device);
+ audioConfigChanged_l(AudioSystem::EFFECT_CONFIG_CHANGED, 0, NULL);
+ }
+ }
+ }
+ }
+#endif
+
// hold a strong ref on thread in case closeOutput() or closeInput() is called
// and the thread is exited once the lock is released
sp<ThreadBase> thread;
@@ -925,13 +1229,17 @@ status_t AudioFlinger::setParameters(audio_io_handle_t ioHandle, const String8&
// indicate output device change to all input threads for pre processing
AudioParameter param = AudioParameter(keyValuePairs);
int value;
+ DefaultKeyedVector< int, sp<RecordThread> > recordThreads = mRecordThreads;
+ mLock.unlock();
if ((param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) &&
(value != 0)) {
- for (size_t i = 0; i < mRecordThreads.size(); i++) {
- mRecordThreads.valueAt(i)->setParameters(keyValuePairs);
+ for (size_t i = 0; i < recordThreads.size(); i++) {
+ recordThreads.valueAt(i)->setParameters(keyValuePairs);
}
}
+ mLock.lock();
}
+ mLock.unlock();
}
if (thread != 0) {
return thread->setParameters(keyValuePairs);
@@ -991,7 +1299,11 @@ size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, audio_format_t form
format: format,
};
audio_hw_device_t *dev = mPrimaryHardwareDev->hwDevice();
+#ifndef ICS_AUDIO_BLOB
size_t size = dev->get_input_buffer_size(dev, &config);
+#else
+ size_t size = dev->get_input_buffer_size(dev, sampleRate, format, popcount(channelMask));
+#endif
mHardwareStatus = AUDIO_HW_IDLE;
return size;
}
@@ -1048,14 +1360,14 @@ void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)
Mutex::Autolock _l(mLock);
- pid_t pid = IPCThreadState::self()->getCallingPid();
- if (mNotificationClients.indexOfKey(pid) < 0) {
+ sp<IBinder> binder = client->asBinder();
+ if (mNotificationClients.indexOfKey(binder) < 0) {
sp<NotificationClient> notificationClient = new NotificationClient(this,
client,
- pid);
- ALOGV("registerClient() client %p, pid %d", notificationClient.get(), pid);
+ binder);
+ ALOGV("registerClient() client %p, binder %d", notificationClient.get(), binder.get());
- mNotificationClients.add(pid, notificationClient);
+ mNotificationClients.add(binder, notificationClient);
sp<IBinder> binder = client->asBinder();
binder->linkToDeath(notificationClient);
@@ -1070,14 +1382,39 @@ void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)
mRecordThreads.valueAt(i)->sendIoConfigEvent(AudioSystem::INPUT_OPENED);
}
}
+#ifdef QCOM_HARDWARE
+ // Send the notification to the client only once.
+ if (mA2DPHandle != -1) {
+ ALOGV("A2DP active. Notifying the registered client");
+ client->ioConfigChanged(AudioSystem::A2DP_OUTPUT_STATE, mA2DPHandle, &mA2DPHandle);
+ }
+#endif
}
-void AudioFlinger::removeNotificationClient(pid_t pid)
+#ifdef QCOM_HARDWARE
+status_t AudioFlinger::deregisterClient(const sp<IAudioFlingerClient>& client)
{
+ ALOGV("deregisterClient() %p, tid %d, calling tid %d", client.get(), gettid(), IPCThreadState::self()->getCallingPid());
Mutex::Autolock _l(mLock);
- mNotificationClients.removeItem(pid);
+ sp<IBinder> binder = client->asBinder();
+ int index = mNotificationClients.indexOfKey(binder);
+ if (index >= 0) {
+ mNotificationClients.removeItemsAt(index);
+ return true;
+ }
+ return false;
+}
+#endif
+
+void AudioFlinger::removeNotificationClient(sp<IBinder> binder)
+{
+ Mutex::Autolock _l(mLock);
+
+ mNotificationClients.removeItem(binder);
+
+ int pid = IPCThreadState::self()->getCallingPid();
ALOGV("%d died, releasing its sessions", pid);
size_t num = mAudioSessionRefs.size();
bool removed = false;
@@ -1102,6 +1439,12 @@ void AudioFlinger::removeNotificationClient(pid_t pid)
// audioConfigChanged_l() must be called with AudioFlinger::mLock held
void AudioFlinger::audioConfigChanged_l(int event, audio_io_handle_t ioHandle, const void *param2)
{
+#ifdef QCOM_HARDWARE
+ ALOGV("AudioFlinger::audioConfigChanged_l: event %d", event);
+ if (event == AudioSystem::EFFECT_CONFIG_CHANGED) {
+ mIsEffectConfigChanged = true;
+ }
+#endif
size_t size = mNotificationClients.size();
for (size_t i = 0; i < size; i++) {
mNotificationClients.valueAt(i)->audioFlingerClient()->ioConfigChanged(event, ioHandle,
@@ -1204,6 +1547,15 @@ status_t AudioFlinger::ThreadBase::setParameters(const String8& keyValuePairs)
return status;
}
+#ifdef QCOM_HARDWARE
+void AudioFlinger::ThreadBase::effectConfigChanged() {
+ mAudioFlinger->mLock.lock();
+ ALOGV("New effect is being added to LPA chain, Notifying LPA Direct Track");
+ mAudioFlinger->audioConfigChanged_l(AudioSystem::EFFECT_CONFIG_CHANGED, 0, NULL);
+ mAudioFlinger->mLock.unlock();
+}
+#endif
+
void AudioFlinger::ThreadBase::sendIoConfigEvent(int event, int param)
{
Mutex::Autolock _l(mLock);
@@ -2652,7 +3004,10 @@ bool AudioFlinger::PlaybackThread::threadLoop()
// only process effects if we're going to write
if (sleepTime == 0) {
for (size_t i = 0; i < effectChains.size(); i ++) {
- effectChains[i]->process_l();
+#ifdef QCOM_HARDWARE
+ if (effectChains[i] != mAudioFlinger->mLPAEffectChain)
+#endif
+ effectChains[i]->process_l();
}
}
@@ -2844,11 +3199,13 @@ void AudioFlinger::MixerThread::threadLoop_mix()
int64_t pts;
status_t status = INVALID_OPERATION;
+#ifndef ICS_AUDIO_BLOB
if (mNormalSink != 0) {
status = mNormalSink->getNextWriteTimestamp(&pts);
} else {
status = mOutputSink->getNextWriteTimestamp(&pts);
}
+#endif
if (status != NO_ERROR) {
pts = AudioBufferProvider::kInvalidPTS;
@@ -5775,8 +6132,8 @@ void AudioFlinger::Client::releaseTimedTrack()
AudioFlinger::NotificationClient::NotificationClient(const sp<AudioFlinger>& audioFlinger,
const sp<IAudioFlingerClient>& client,
- pid_t pid)
- : mAudioFlinger(audioFlinger), mPid(pid), mAudioFlingerClient(client)
+ sp<IBinder> binder)
+ : mAudioFlinger(audioFlinger), mBinder(binder), mAudioFlingerClient(client)
{
}
@@ -5787,9 +6144,313 @@ AudioFlinger::NotificationClient::~NotificationClient()
void AudioFlinger::NotificationClient::binderDied(const wp<IBinder>& who)
{
sp<NotificationClient> keep(this);
- mAudioFlinger->removeNotificationClient(mPid);
+ mAudioFlinger->removeNotificationClient(mBinder);
+}
+
+// ----------------------------------------------------------------------------
+#ifdef QCOM_HARDWARE
+AudioFlinger::DirectAudioTrack::DirectAudioTrack(const sp<AudioFlinger>& audioFlinger,
+ int output, AudioSessionDescriptor *outputDesc,
+ IDirectTrackClient* client, audio_output_flags_t outflag)
+ : BnDirectTrack(), mIsPaused(false), mAudioFlinger(audioFlinger), mOutput(output), mOutputDesc(outputDesc),
+ mClient(client), mEffectConfigChanged(false), mKillEffectsThread(false), mFlag(outflag)
+{
+ if (mFlag & AUDIO_OUTPUT_FLAG_LPA) {
+ createEffectThread();
+
+ mAudioFlingerClient = new AudioFlingerDirectTrackClient(this);
+ mAudioFlinger->registerClient(mAudioFlingerClient);
+
+ allocateBufPool();
+ }
+ mDeathRecipient = new PMDeathRecipient(this);
+ acquireWakeLock();
+}
+
+AudioFlinger::DirectAudioTrack::~DirectAudioTrack() {
+ if (mFlag & AUDIO_OUTPUT_FLAG_LPA) {
+ requestAndWaitForEffectsThreadExit();
+ mAudioFlinger->deregisterClient(mAudioFlingerClient);
+ mAudioFlinger->deleteEffectSession();
+ deallocateBufPool();
+ }
+ AudioSystem::releaseOutput(mOutput);
+ releaseWakeLock();
+
+ {
+ Mutex::Autolock _l(pmLock);
+ if (mPowerManager != 0) {
+ sp<IBinder> binder = mPowerManager->asBinder();
+ binder->unlinkToDeath(mDeathRecipient);
+ }
+ }
+}
+
+status_t AudioFlinger::DirectAudioTrack::start() {
+ if(mIsPaused) {
+ mIsPaused = false;
+ mOutputDesc->stream->start(mOutputDesc->stream);
+ }
+ mOutputDesc->mActive = true;
+ AudioSystem::startOutput(mOutput, (audio_stream_type_t)mOutputDesc->mStreamType);
+ return NO_ERROR;
+}
+
+void AudioFlinger::DirectAudioTrack::stop() {
+ mOutputDesc->mActive = false;
+ mOutputDesc->stream->stop(mOutputDesc->stream);
+ AudioSystem::stopOutput(mOutput, (audio_stream_type_t)mOutputDesc->mStreamType);
+}
+
+void AudioFlinger::DirectAudioTrack::pause() {
+ if(!mIsPaused) {
+ mIsPaused = true;
+ mOutputDesc->stream->pause(mOutputDesc->stream);
+ mOutputDesc->mActive = false;
+ AudioSystem::stopOutput(mOutput, (audio_stream_type_t)mOutputDesc->mStreamType);
+ }
+}
+
+ssize_t AudioFlinger::DirectAudioTrack::write(const void *buffer, size_t size) {
+ ALOGV("Writing to AudioSessionOut");
+ int isAvail = 0;
+ mOutputDesc->stream->is_buffer_available(mOutputDesc->stream, &isAvail);
+ if (!isAvail) {
+ return 0;
+ }
+
+ if (mFlag & AUDIO_OUTPUT_FLAG_LPA) {
+ mEffectLock.lock();
+ List<BufferInfo>::iterator it = mEffectsPool.begin();
+ BufferInfo buf = *it;
+ mEffectsPool.erase(it);
+ memcpy((char *) buf.localBuf, (char *)buffer, size);
+ buf.bytesToWrite = size;
+ mEffectsPool.push_back(buf);
+ mAudioFlinger->applyEffectsOn(static_cast<void *>(this), (int16_t*)buf.localBuf,(int16_t*)buffer,(int)size);
+ mEffectLock.unlock();
+ }
+ return mOutputDesc->stream->write(mOutputDesc->stream, buffer, size);
+}
+
+void AudioFlinger::DirectAudioTrack::flush() {
+ if (mFlag & AUDIO_OUTPUT_FLAG_LPA) {
+ mEffectsPool.clear();
+ mEffectsPool = mBufPool;
+ }
+ mOutputDesc->stream->flush(mOutputDesc->stream);
+}
+
+void AudioFlinger::DirectAudioTrack::mute(bool muted) {
}
+void AudioFlinger::DirectAudioTrack::setVolume(float left, float right) {
+ mOutputDesc->mVolumeLeft = left;
+ mOutputDesc->mVolumeRight = right;
+}
+
+int64_t AudioFlinger::DirectAudioTrack::getTimeStamp() {
+ int64_t time;
+ mOutputDesc->stream->get_next_write_timestamp(mOutputDesc->stream, &time);
+ ALOGV("Timestamp %lld",time);
+ return time;
+}
+
+void AudioFlinger::DirectAudioTrack::postEOS(int64_t delayUs) {
+ ALOGV("Notify Audio Track of EOS event");
+ mClient->notify(DIRECT_TRACK_EOS);
+}
+
+void AudioFlinger::DirectAudioTrack::allocateBufPool() {
+ void *dsp_buf = NULL;
+ void *local_buf = NULL;
+
+ //1. get the ion buffer information
+ struct buf_info* buf = NULL;
+ mOutputDesc->stream->get_buffer_info(mOutputDesc->stream, &buf);
+ ALOGV("get buffer info %p",buf);
+ if (!buf) {
+ ALOGV("buffer is NULL");
+ return;
+ }
+ int nSize = buf->bufsize;
+ int bufferCount = buf->nBufs;
+
+ //2. allocate the buffer pool, allocate local buffers
+ for (int i = 0; i < bufferCount; i++) {
+ dsp_buf = (void *)buf->buffers[i];
+ local_buf = malloc(nSize);
+ memset(local_buf, 0, nSize);
+ // Store this information for internal mapping / maintanence
+ BufferInfo buf(local_buf, dsp_buf, nSize);
+ buf.bytesToWrite = 0;
+ mBufPool.push_back(buf);
+ mEffectsPool.push_back(buf);
+
+ ALOGV("The MEM that is allocated buffer is %x, size %d",(unsigned int)dsp_buf,nSize);
+ }
+ free(buf);
+}
+
+void AudioFlinger::DirectAudioTrack::deallocateBufPool() {
+
+ //1. Deallocate the local memory
+ //2. Remove all the buffers from bufpool
+ while (!mBufPool.empty()) {
+ List<BufferInfo>::iterator it = mBufPool.begin();
+ BufferInfo &memBuffer = *it;
+ // free the local buffer corresponding to mem buffer
+ if (memBuffer.localBuf) {
+ free(memBuffer.localBuf);
+ memBuffer.localBuf = NULL;
+ }
+ ALOGV("Removing from bufpool");
+ mBufPool.erase(it);
+ }
+}
+
+status_t AudioFlinger::DirectAudioTrack::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ return BnDirectTrack::onTransact(code, data, reply, flags);
+}
+
+void *AudioFlinger::DirectAudioTrack::EffectsThreadWrapper(void *me) {
+ static_cast<DirectAudioTrack *>(me)->EffectsThreadEntry();
+ return NULL;
+}
+
+void AudioFlinger::DirectAudioTrack::EffectsThreadEntry() {
+ while(1) {
+ mEffectLock.lock();
+ if (!mEffectConfigChanged && !mKillEffectsThread) {
+ mEffectCv.wait(mEffectLock);
+ }
+
+ if(mKillEffectsThread) {
+ mEffectLock.unlock();
+ break;
+ }
+
+ if (mEffectConfigChanged) {
+ mEffectConfigChanged = false;
+ for ( List<BufferInfo>::iterator it = mEffectsPool.begin();
+ it != mEffectsPool.end(); it++) {
+ ALOGV("Apply effects on the buffer dspbuf %p, mEffectsPool.size() %d",it->dspBuf,mEffectsPool.size());
+ mAudioFlinger->applyEffectsOn(static_cast<void *>(this),
+ (int16_t *)it->localBuf,
+ (int16_t *)it->dspBuf,
+ it->bytesToWrite);
+ if (mEffectConfigChanged) {
+ break;
+ }
+ }
+
+ }
+ mEffectLock.unlock();
+ }
+ ALOGV("Effects thread is dead");
+ mEffectsThreadAlive = false;
+}
+
+void AudioFlinger::DirectAudioTrack::requestAndWaitForEffectsThreadExit() {
+ if (!mEffectsThreadAlive)
+ return;
+ mKillEffectsThread = true;
+ mEffectCv.signal();
+ pthread_join(mEffectsThread,NULL);
+ ALOGV("effects thread killed");
+}
+
+void AudioFlinger::DirectAudioTrack::createEffectThread() {
+ //Create the effects thread
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+ mEffectsThreadAlive = true;
+ ALOGV("Creating Effects Thread");
+ pthread_create(&mEffectsThread, &attr, EffectsThreadWrapper, this);
+}
+AudioFlinger::DirectAudioTrack::AudioFlingerDirectTrackClient::AudioFlingerDirectTrackClient(void *obj)
+{
+ ALOGV("AudioFlinger::DirectAudioTrack::AudioFlingerDirectTrackClient");
+ pBaseClass = (DirectAudioTrack*)obj;
+}
+
+void AudioFlinger::DirectAudioTrack::AudioFlingerDirectTrackClient::binderDied(const wp<IBinder>& who) {
+ pBaseClass->mAudioFlinger.clear();
+ ALOGW("AudioFlinger server died!");
+}
+
+void AudioFlinger::DirectAudioTrack::AudioFlingerDirectTrackClient
+ ::ioConfigChanged(int event, audio_io_handle_t ioHandle, const void *param2) {
+ ALOGV("ioConfigChanged() event %d", event);
+ if (event == AudioSystem::EFFECT_CONFIG_CHANGED) {
+ ALOGV("Received notification for change in effect module");
+ // Seek to current media time - flush the decoded buffers with the driver
+ pBaseClass->mEffectConfigChanged = true;
+ // Signal effects thread to re-apply effects
+ ALOGV("Signalling Effects Thread");
+ pBaseClass->mEffectCv.signal();
+
+ }
+ ALOGV("ioConfigChanged Out");
+}
+
+void AudioFlinger::DirectAudioTrack::acquireWakeLock()
+{
+ Mutex::Autolock _l(pmLock);
+
+ if (mPowerManager == 0) {
+ // use checkService() to avoid blocking if power service is not up yet
+ sp<IBinder> binder =
+ defaultServiceManager()->checkService(String16("power"));
+ if (binder == 0) {
+ ALOGW("Thread %s cannot connect to the power manager service", lockName);
+ } else {
+ mPowerManager = interface_cast<IPowerManager>(binder);
+ binder->linkToDeath(mDeathRecipient);
+ }
+ }
+ if (mPowerManager != 0 && mWakeLockToken == 0) {
+ sp<IBinder> binder = new BBinder();
+ status_t status = mPowerManager->acquireWakeLock(POWERMANAGER_PARTIAL_WAKE_LOCK,
+ binder,
+ String16(lockName));
+ if (status == NO_ERROR) {
+ mWakeLockToken = binder;
+ }
+ ALOGV("acquireWakeLock() status %d", status);
+ }
+}
+
+void AudioFlinger::DirectAudioTrack::releaseWakeLock()
+{
+ Mutex::Autolock _l(pmLock);
+
+ if (mWakeLockToken != 0) {
+ ALOGV("releaseWakeLock()");
+ if (mPowerManager != 0) {
+ mPowerManager->releaseWakeLock(mWakeLockToken, 0);
+ }
+ mWakeLockToken.clear();
+ }
+}
+
+void AudioFlinger::DirectAudioTrack::clearPowerManager()
+{
+ releaseWakeLock();
+ Mutex::Autolock _l(pmLock);
+ mPowerManager.clear();
+}
+
+void AudioFlinger::DirectAudioTrack::PMDeathRecipient::binderDied(const wp<IBinder>& who)
+{
+ parentClass->clearPowerManager();
+ ALOGW("power manager service died !!!");
+}
+#endif
+
// ----------------------------------------------------------------------------
AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::PlaybackThread::Track>& track)
@@ -5992,7 +6653,7 @@ AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger,
ThreadBase(audioFlinger, id, AUDIO_DEVICE_NONE, device, RECORD),
mInput(input), mResampler(NULL), mRsmpOutBuffer(NULL), mRsmpInBuffer(NULL),
// mRsmpInIndex and mInputBytes set by readInputParameters()
- mReqChannelCount(popcount(channelMask)),
+ mReqChannelCount(getInputChannelCount(channelMask)),
mReqSampleRate(sampleRate)
// mBytesRead is only meaningful while active, and so is cleared in start()
// (but might be better to also clear here for dump?)
@@ -6607,7 +7268,7 @@ bool AudioFlinger::RecordThread::checkForNewParameters_l()
reconfig = true;
}
if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
- reqChannelCount = popcount(value);
+ reqChannelCount = getInputChannelCount(value);
reconfig = true;
}
if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
@@ -6668,7 +7329,7 @@ bool AudioFlinger::RecordThread::checkForNewParameters_l()
reqFormat == mInput->stream->common.get_format(&mInput->stream->common) &&
reqFormat == AUDIO_FORMAT_PCM_16_BIT &&
((int)mInput->stream->common.get_sample_rate(&mInput->stream->common) <= (2 * reqSamplingRate)) &&
- popcount(mInput->stream->common.get_channels(&mInput->stream->common)) <= FCC_2 &&
+ getInputChannelCount(mInput->stream->common.get_channels(&mInput->stream->common)) <= FCC_2 &&
(reqChannelCount <= FCC_2)) {
status = NO_ERROR;
}
@@ -6739,7 +7400,7 @@ void AudioFlinger::RecordThread::readInputParameters()
mSampleRate = mInput->stream->common.get_sample_rate(&mInput->stream->common);
mChannelMask = mInput->stream->common.get_channels(&mInput->stream->common);
- mChannelCount = (uint16_t)popcount(mChannelMask);
+ mChannelCount = (uint16_t)getInputChannelCount(mChannelMask);
mFormat = mInput->stream->common.get_format(&mInput->stream->common);
mFrameSize = audio_stream_frame_size(&mInput->stream->common);
mInputBytes = mInput->stream->common.get_buffer_size(&mInput->stream->common);
@@ -6877,6 +7538,7 @@ audio_module_handle_t AudioFlinger::loadHwModule_l(const char *name)
{ // scope for auto-lock pattern
AutoMutex lock(mHardwareLock);
+#if !defined(ICS_AUDIO_BLOB) && !defined(MR0_AUDIO_BLOB)
if (0 == mAudioHwDevs.size()) {
mHardwareStatus = AUDIO_HW_GET_MASTER_VOLUME;
if (NULL != dev->get_master_volume) {
@@ -6894,6 +7556,7 @@ audio_module_handle_t AudioFlinger::loadHwModule_l(const char *name)
}
}
}
+#endif
mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
if ((NULL != dev->set_master_volume) &&
@@ -6902,12 +7565,14 @@ audio_module_handle_t AudioFlinger::loadHwModule_l(const char *name)
AudioHwDevice::AHWD_CAN_SET_MASTER_VOLUME);
}
+#if !defined(ICS_AUDIO_BLOB) && !defined(MR0_AUDIO_BLOB)
mHardwareStatus = AUDIO_HW_SET_MASTER_MUTE;
if ((NULL != dev->set_master_mute) &&
(OK == dev->set_master_mute(dev, mMasterMute))) {
flags = static_cast<AudioHwDevice::Flags>(flags |
AudioHwDevice::AHWD_CAN_SET_MASTER_MUTE);
}
+#endif
mHardwareStatus = AUDIO_HW_IDLE;
}
@@ -6981,12 +7646,23 @@ audio_io_handle_t AudioFlinger::openOutput(audio_module_handle_t module,
mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
+#ifndef ICS_AUDIO_BLOB
status = hwDevHal->open_output_stream(hwDevHal,
id,
*pDevices,
(audio_output_flags_t)flags,
&config,
&outStream);
+#else
+ status = hwDevHal->open_output_stream(hwDevHal,
+ *pDevices,
+ (int *)&config.format,
+ &config.channel_mask,
+ &config.sample_rate,
+ &outStream);
+ uint32_t newflags = flags | AUDIO_OUTPUT_FLAG_PRIMARY;
+ flags = (audio_output_flags_t)newflags;
+#endif
mHardwareStatus = AUDIO_HW_IDLE;
ALOGV("openOutput() openOutputStream returned output %p, SamplingRate %d, Format %d, Channels %x, status %d",
@@ -6998,7 +7674,18 @@ audio_io_handle_t AudioFlinger::openOutput(audio_module_handle_t module,
if (status == NO_ERROR && outStream != NULL) {
AudioStreamOut *output = new AudioStreamOut(outHwDev, outStream);
-
+#ifdef QCOM_HARDWARE
+ if (flags & AUDIO_OUTPUT_FLAG_LPA || flags & AUDIO_OUTPUT_FLAG_TUNNEL ) {
+ AudioSessionDescriptor *desc = new AudioSessionDescriptor(hwDevHal, outStream, flags);
+ desc->mActive = true;
+ //TODO: no stream type
+ //desc->mStreamType = streamType;
+ desc->mVolumeLeft = 1.0;
+ desc->mVolumeRight = 1.0;
+ desc->device = *pDevices;
+ mDirectAudioTracks.add(id, desc);
+ } else
+#endif
if ((flags & AUDIO_OUTPUT_FLAG_DIRECT) ||
(config.format != AUDIO_FORMAT_PCM_16_BIT) ||
(config.channel_mask != AUDIO_CHANNEL_OUT_STEREO)) {
@@ -7008,16 +7695,39 @@ audio_io_handle_t AudioFlinger::openOutput(audio_module_handle_t module,
thread = new MixerThread(this, output, id, *pDevices);
ALOGV("openOutput() created mixer output: ID %d thread %p", id, thread);
}
- mPlaybackThreads.add(id, thread);
+#ifdef QCOM_HARDWARE
+ if (thread != NULL)
+#endif
+ mPlaybackThreads.add(id, thread);
+
+#ifdef QCOM_HARDWARE
+ // if the device is a A2DP, then this is an A2DP Output
+ if ( true == audio_is_a2dp_device((audio_devices_t) *pDevices) )
+ {
+ mA2DPHandle = id;
+ ALOGV("A2DP device activated. The handle is set to %d", mA2DPHandle);
+ }
+#endif
if (pSamplingRate != NULL) *pSamplingRate = config.sample_rate;
if (pFormat != NULL) *pFormat = config.format;
if (pChannelMask != NULL) *pChannelMask = config.channel_mask;
- if (pLatencyMs != NULL) *pLatencyMs = thread->latency();
-
- // notify client processes of the new output creation
- thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED);
-
+#ifdef QCOM_HARDWARE
+ if (thread != NULL) {
+#endif
+ if (pLatencyMs != NULL) *pLatencyMs = thread->latency();
+ // notify client processes of the new output creation
+ thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED);
+#ifdef QCOM_HARDWARE
+ }
+ else {
+ *pLatencyMs = 0;
+ if ((flags & AUDIO_OUTPUT_FLAG_LPA) || (flags & AUDIO_OUTPUT_FLAG_TUNNEL)) {
+ AudioSessionDescriptor *desc = mDirectAudioTracks.valueFor(id);
+ *pLatencyMs = desc->stream->get_latency(desc->stream);
+ }
+ }
+#endif
// the first primary output opened designates the primary hw device
if ((mPrimaryHardwareDev == NULL) && (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
ALOGI("Using module %d has the primary audio interface", module);
@@ -7064,6 +7774,21 @@ status_t AudioFlinger::closeOutput_nonvirtual(audio_io_handle_t output)
{
// keep strong reference on the playback thread so that
// it is not destroyed while exit() is executed
+#ifdef QCOM_HARDWARE
+ AudioSessionDescriptor *desc = mDirectAudioTracks.valueFor(output);
+ if (desc) {
+ ALOGV("Closing DirectTrack output %d", output);
+ desc->mActive = false;
+ desc->stream->common.standby(&desc->stream->common);
+ desc->hwDev->close_output_stream(desc->hwDev, desc->stream);
+ desc->trackRefPtr = NULL;
+ mDirectAudioTracks.removeItem(output);
+ audioConfigChanged_l(AudioSystem::OUTPUT_CLOSED, output, NULL);
+ delete desc;
+ return NO_ERROR;
+ }
+#endif
+
sp<PlaybackThread> thread;
{
Mutex::Autolock _l(mLock);
@@ -7084,6 +7809,14 @@ status_t AudioFlinger::closeOutput_nonvirtual(audio_io_handle_t output)
}
audioConfigChanged_l(AudioSystem::OUTPUT_CLOSED, output, NULL);
mPlaybackThreads.removeItem(output);
+#ifdef QCOM_HARDWARE
+ if (mA2DPHandle == output)
+ {
+ mA2DPHandle = -1;
+ ALOGV("A2DP OutputClosed Notifying Client");
+ audioConfigChanged_l(AudioSystem::A2DP_OUTPUT_STATE, mA2DPHandle, &mA2DPHandle);
+ }
+#endif
}
thread->exit();
// The thread entity (active unit of execution) is no longer running here,
@@ -7162,8 +7895,16 @@ audio_io_handle_t AudioFlinger::openInput(audio_module_handle_t module,
audio_hw_device_t *inHwHal = inHwDev->hwDevice();
audio_io_handle_t id = nextUniqueId();
+#ifndef ICS_AUDIO_BLOB
status = inHwHal->open_input_stream(inHwHal, id, *pDevices, &config,
&inStream);
+#else
+ status = inHwHal->open_input_stream(inHwHal, *pDevices,
+ (int *)&config.format,
+ &config.channel_mask,
+ &config.sample_rate, (audio_in_acoustics_t)0,
+ &inStream);
+#endif
ALOGV("openInput() openInputStream returned input %p, SamplingRate %d, Format %d, Channels %x, status %d",
inStream,
config.sample_rate,
@@ -7177,10 +7918,18 @@ audio_io_handle_t AudioFlinger::openInput(audio_module_handle_t module,
if (status == BAD_VALUE &&
reqFormat == config.format && config.format == AUDIO_FORMAT_PCM_16_BIT &&
(config.sample_rate <= 2 * reqSamplingRate) &&
- (popcount(config.channel_mask) <= FCC_2) && (popcount(reqChannels) <= FCC_2)) {
+ (getInputChannelCount(config.channel_mask) <= FCC_2) && (getInputChannelCount(reqChannels) <= FCC_2)) {
ALOGV("openInput() reopening with proposed sampling rate and channel mask");
inStream = NULL;
+#ifndef ICS_AUDIO_BLOB
status = inHwHal->open_input_stream(inHwHal, id, *pDevices, &config, &inStream);
+#else
+ status = inHwHal->open_input_stream(inHwHal, *pDevices,
+ (int *)&config.format,
+ &config.channel_mask,
+ &config.sample_rate, (audio_in_acoustics_t)0,
+ &inStream);
+#endif
}
if (status == NO_ERROR && inStream != NULL) {
@@ -7253,6 +8002,12 @@ status_t AudioFlinger::setStreamOutput(audio_stream_type_t stream, audio_io_hand
PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
thread->invalidateTracks(stream);
}
+#ifdef QCOM_HARDWARE
+ if ( mA2DPHandle == output ) {
+ ALOGV("A2DP Activated and hence notifying the client");
+ audioConfigChanged_l(AudioSystem::A2DP_OUTPUT_STATE, mA2DPHandle, &output);
+ }
+#endif
return NO_ERROR;
}
@@ -7792,6 +8547,21 @@ sp<AudioFlinger::EffectHandle> AudioFlinger::ThreadBase::createEffect_l(
addEffectChain_l(chain);
chain->setStrategy(getStrategyForSession_l(sessionId));
chainCreated = true;
+#ifdef QCOM_HARDWARE
+ if(sessionId == mAudioFlinger->mLPASessionId) {
+ // Clear reference to previous effect chain if any
+ if(mAudioFlinger->mLPAEffectChain.get()) {
+ mAudioFlinger->mLPAEffectChain.clear();
+ }
+ ALOGV("New EffectChain is created for LPA session ID %d", sessionId);
+ mAudioFlinger->mLPAEffectChain = chain;
+ chain->setLPAFlag(true);
+ // For LPA, the volume will be applied in DSP. No need for volume
+ // control in the Effect chain, so setting it to unity.
+ uint32_t volume = 0x1000000; // Equals to 1.0 in 8.24 format
+ chain->setVolume_l(&volume,&volume);
+ }
+#endif
} else {
effect = chain->getEffectFromDesc_l(desc);
}
@@ -7822,6 +8592,11 @@ sp<AudioFlinger::EffectHandle> AudioFlinger::ThreadBase::createEffect_l(
effect->setDevice(mInDevice);
effect->setMode(mAudioFlinger->getMode());
effect->setAudioSource(mAudioSource);
+#ifdef QCOM_HARDWARE
+ if(chain == mAudioFlinger->mLPAEffectChain) {
+ effect->setLPAFlag(true);
+ }
+#endif
}
// create effect handle and connect it to effect module
handle = new EffectHandle(effect, client, effectClient, priority);
@@ -7928,7 +8703,10 @@ void AudioFlinger::ThreadBase::lockEffectChains_l(
{
effectChains = mEffectChains;
for (size_t i = 0; i < mEffectChains.size(); i++) {
- mEffectChains[i]->lock();
+#ifdef QCOM_HARDWARE
+ if (mEffectChains[i] != mAudioFlinger->mLPAEffectChain)
+#endif
+ mEffectChains[i]->lock();
}
}
@@ -7936,7 +8714,10 @@ void AudioFlinger::ThreadBase::unlockEffectChains(
const Vector< sp<AudioFlinger::EffectChain> >& effectChains)
{
for (size_t i = 0; i < effectChains.size(); i++) {
- effectChains[i]->unlock();
+#ifdef QCOM_HARDWARE
+ if (mEffectChains[i] != mAudioFlinger->mLPAEffectChain)
+#endif
+ effectChains[i]->unlock();
}
}
@@ -8168,6 +8949,9 @@ AudioFlinger::EffectModule::EffectModule(ThreadBase *thread,
// mMaxDisableWaitCnt is set by configure() and not used before then
// mDisableWaitCnt is set by process() and updateState() and not used before then
mSuspended(false)
+#ifdef QCOM_HARDWARE
+ ,mIsForLPA(false)
+#endif
{
ALOGV("Constructor %p", this);
int lStatus;
@@ -8293,6 +9077,9 @@ AudioFlinger::EffectHandle *AudioFlinger::EffectModule::controlHandle_l()
size_t AudioFlinger::EffectModule::disconnect(EffectHandle *handle, bool unpinIfLast)
{
+#ifdef QCOM_HARDWARE
+ setEnabled(false);
+#endif
ALOGV("disconnect() %p handle %p", this, handle);
// keep a strong reference on this EffectModule to avoid calling the
// destructor before we exit
@@ -8399,8 +9186,19 @@ void AudioFlinger::EffectModule::reset_l()
(*mEffectInterface)->command(mEffectInterface, EFFECT_CMD_RESET, 0, NULL, 0, NULL);
}
+#ifndef QCOM_HARDWARE
status_t AudioFlinger::EffectModule::configure()
{
+#else
+status_t AudioFlinger::EffectModule::configure(bool isForLPA, int sampleRate, int channelCount, int frameCount)
+{
+ uint32_t channels;
+
+ // Acquire lock here to make sure that any other thread does not delete
+ // the effect handle and release the effect module.
+ Mutex::Autolock _l(mLock);
+#endif
+
if (mEffectInterface == NULL) {
return NO_INIT;
}
@@ -8412,6 +9210,23 @@ status_t AudioFlinger::EffectModule::configure()
// TODO: handle configuration of effects replacing track process
audio_channel_mask_t channelMask = thread->channelMask();
+#ifdef QCOM_HARDWARE
+ mIsForLPA = isForLPA;
+ if(isForLPA) {
+ if (channelCount == 1) {
+ channels = AUDIO_CHANNEL_OUT_MONO;
+ } else {
+ channels = AUDIO_CHANNEL_OUT_STEREO;
+ }
+ ALOGV("%s: LPA ON - channels %d", __func__, channels);
+ } else {
+ if (thread->channelCount() == 1) {
+ channels = AUDIO_CHANNEL_OUT_MONO;
+ } else {
+ channels = AUDIO_CHANNEL_OUT_STEREO;
+ }
+ }
+#endif
if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
mConfig.inputCfg.channels = AUDIO_CHANNEL_OUT_MONO;
@@ -8421,7 +9236,13 @@ status_t AudioFlinger::EffectModule::configure()
mConfig.outputCfg.channels = channelMask;
mConfig.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
mConfig.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
- mConfig.inputCfg.samplingRate = thread->sampleRate();
+#ifdef QCOM_HARDWARE
+ if(isForLPA){
+ mConfig.inputCfg.samplingRate = sampleRate;
+ ALOGV("%s: LPA ON - sampleRate %d", __func__, sampleRate);
+ } else
+#endif
+ mConfig.inputCfg.samplingRate = thread->sampleRate();
mConfig.outputCfg.samplingRate = mConfig.inputCfg.samplingRate;
mConfig.inputCfg.bufferProvider.cookie = NULL;
mConfig.inputCfg.bufferProvider.getBuffer = NULL;
@@ -8446,7 +9267,13 @@ status_t AudioFlinger::EffectModule::configure()
}
mConfig.inputCfg.mask = EFFECT_CONFIG_ALL;
mConfig.outputCfg.mask = EFFECT_CONFIG_ALL;
- mConfig.inputCfg.buffer.frameCount = thread->frameCount();
+#ifdef QCOM_HARDWARE
+ if(isForLPA) {
+ mConfig.inputCfg.buffer.frameCount = frameCount;
+ ALOGV("%s: LPA ON - frameCount %d", __func__, frameCount);
+ } else
+#endif
+ mConfig.inputCfg.buffer.frameCount = thread->frameCount();
mConfig.outputCfg.buffer.frameCount = mConfig.inputCfg.buffer.frameCount;
ALOGV("configure() %p thread %p buffer %p framecount %d",
@@ -8626,10 +9453,15 @@ status_t AudioFlinger::EffectModule::setEnabled(bool enabled)
// must be called with EffectModule::mLock held
status_t AudioFlinger::EffectModule::setEnabled_l(bool enabled)
{
-
+#ifdef QCOM_HARDWARE
+ bool effectStateChanged = false;
+#endif
ALOGV("setEnabled %p enabled %d", this, enabled);
if (enabled != isEnabled()) {
+#ifdef QCOM_HARDWARE
+ effectStateChanged = true;
+#endif
status_t status = AudioSystem::setEffectEnabled(mId, enabled);
if (enabled && status != NO_ERROR) {
return status;
@@ -8667,6 +9499,16 @@ status_t AudioFlinger::EffectModule::setEnabled_l(bool enabled)
}
}
}
+#ifdef QCOM_HARDWARE
+ /*
+ Send notification event to LPA Player when an effect for
+ LPA output is enabled or disabled.
+ */
+ if (effectStateChanged && mIsForLPA) {
+ sp<ThreadBase> thread = mThread.promote();
+ thread->effectConfigChanged();
+ }
+#endif
return NO_ERROR;
}
@@ -9116,6 +9958,18 @@ status_t AudioFlinger::EffectHandle::command(uint32_t cmdCode,
return disable();
}
+#ifdef QCOM_HARDWARE
+ ALOGV("EffectHandle::command: isOnLPA %d", mEffect->isOnLPA());
+ if(mEffect->isOnLPA() &&
+ ((cmdCode == EFFECT_CMD_SET_PARAM) || (cmdCode == EFFECT_CMD_SET_PARAM_DEFERRED) ||
+ (cmdCode == EFFECT_CMD_SET_PARAM_COMMIT) || (cmdCode == EFFECT_CMD_SET_DEVICE) ||
+ (cmdCode == EFFECT_CMD_SET_VOLUME) || (cmdCode == EFFECT_CMD_SET_AUDIO_MODE)) ) {
+ // Notify Direct track for the change in Effect module
+ // TODO: check if it is required to send mLPAHandle
+ ALOGV("Notifying Direct Track for the change in effect config");
+ mClient->audioFlinger()->audioConfigChanged_l(AudioSystem::EFFECT_CONFIG_CHANGED, 0, NULL);
+ }
+#endif
return mEffect->command(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
}
@@ -9184,6 +10038,9 @@ AudioFlinger::EffectChain::EffectChain(ThreadBase *thread,
: mThread(thread), mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0), mTailBufferCount(0),
mOwnInBuffer(false), mVolumeCtrlIdx(-1), mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX),
mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX)
+#ifdef QCOM_HARDWARE
+ ,mIsForLPATrack(false)
+#endif
{
mStrategy = AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
if (thread == NULL) {
@@ -9228,6 +10085,20 @@ sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromId_l(int
return 0;
}
+#ifdef QCOM_HARDWARE
+sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromIndex_l(int idx)
+{
+ sp<EffectModule> effect = NULL;
+ if(idx < 0 || idx >= mEffects.size()) {
+ ALOGE("EffectChain::getEffectFromIndex_l: invalid index %d", idx);
+ }
+ if(mEffects.size() > 0){
+ effect = mEffects[idx];
+ }
+ return effect;
+}
+#endif
+
// getEffectFromType_l() must be called with ThreadBase::mLock held
sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromType_l(
const effect_uuid_t *type)
@@ -9294,7 +10165,11 @@ void AudioFlinger::EffectChain::process_l()
}
size_t size = mEffects.size();
+#ifdef QCOM_HARDWARE
+ if (doProcess || isForLPATrack()) {
+#else
if (doProcess) {
+#endif
for (size_t i = 0; i < size; i++) {
mEffects[i]->process();
}
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 49e2b2c..dcdc55c 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -1,6 +1,9 @@
/*
**
** Copyright 2007, The Android Open Source Project
+** Copyright (c) 2012, The Linux Foundation. All rights reserved.
+** Not a Contribution, Apache license notifications and license are retained
+** for attribution purposes only.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
@@ -26,6 +29,10 @@
#include <media/IAudioFlinger.h>
#include <media/IAudioFlingerClient.h>
+#ifdef QCOM_HARDWARE
+#include <media/IDirectTrack.h>
+#include <media/IDirectTrackClient.h>
+#endif
#include <media/IAudioTrack.h>
#include <media/IAudioRecord.h>
#include <media/AudioSystem.h>
@@ -52,6 +59,7 @@
#include "AudioWatchdog.h"
#include <powermanager/IPowerManager.h>
+#include <utils/List.h>
namespace android {
@@ -99,6 +107,19 @@ public:
pid_t tid,
int *sessionId,
status_t *status);
+#ifdef QCOM_HARDWARE
+ virtual sp<IDirectTrack> createDirectTrack(
+ pid_t pid,
+ uint32_t sampleRate,
+ audio_channel_mask_t channelMask,
+ audio_io_handle_t output,
+ int *sessionId,
+ IDirectTrackClient* client,
+ audio_stream_type_t streamType,
+ status_t *status);
+
+ virtual void deleteEffectSession();
+#endif
virtual sp<IAudioRecord> openRecord(
pid_t pid,
@@ -141,7 +162,9 @@ public:
virtual String8 getParameters(audio_io_handle_t ioHandle, const String8& keys) const;
virtual void registerClient(const sp<IAudioFlingerClient>& client);
-
+#ifdef QCOM_HARDWARE
+ virtual status_t deregisterClient(const sp<IAudioFlingerClient>& client);
+#endif
virtual size_t getInputBufferSize(uint32_t sampleRate, audio_format_t format,
audio_channel_mask_t channelMask) const;
@@ -216,6 +239,13 @@ public:
Parcel* reply,
uint32_t flags);
+#ifdef QCOM_HARDWARE
+ void applyEffectsOn(void *token,
+ int16_t *buffer1,
+ int16_t *buffer2,
+ int size);
+#endif
+
// end of IAudioFlinger interface
class SyncEvent;
@@ -314,7 +344,7 @@ private:
public:
NotificationClient(const sp<AudioFlinger>& audioFlinger,
const sp<IAudioFlingerClient>& client,
- pid_t pid);
+ sp<IBinder> binder);
virtual ~NotificationClient();
sp<IAudioFlingerClient> audioFlingerClient() const { return mAudioFlingerClient; }
@@ -327,7 +357,7 @@ private:
NotificationClient& operator = (const NotificationClient&);
const sp<AudioFlinger> mAudioFlinger;
- const pid_t mPid;
+ sp<IBinder> mBinder;
const sp<IAudioFlingerClient> mAudioFlingerClient;
};
@@ -343,6 +373,9 @@ private:
class EffectModule;
class EffectHandle;
class EffectChain;
+#ifdef QCOM_HARDWARE
+ struct AudioSessionDescriptor;
+#endif
struct AudioStreamOut;
struct AudioStreamIn;
@@ -570,6 +603,9 @@ private:
virtual status_t setParameters(const String8& keyValuePairs);
virtual String8 getParameters(const String8& keys) = 0;
virtual void audioConfigChanged_l(int event, int param = 0) = 0;
+#ifdef QCOM_HARDWARE
+ void effectConfigChanged();
+#endif
void sendIoConfigEvent(int event, int param = 0);
void sendIoConfigEvent_l(int event, int param = 0);
void sendPrioConfigEvent_l(pid_t pid, pid_t tid, int32_t prio);
@@ -1400,6 +1436,115 @@ private:
sp<PlaybackThread> getEffectThread_l(int sessionId, int EffectId);
// server side of the client's IAudioTrack
+#ifdef QCOM_HARDWARE
+ class DirectAudioTrack : public android::BnDirectTrack,
+ public AudioEventObserver
+ {
+ public:
+ DirectAudioTrack(const sp<AudioFlinger>& audioFlinger,
+ int output, AudioSessionDescriptor *outputDesc,
+ IDirectTrackClient* client, audio_output_flags_t outflag);
+ virtual ~DirectAudioTrack();
+ virtual status_t start();
+ virtual void stop();
+ virtual void flush();
+ virtual void mute(bool);
+ virtual void pause();
+ virtual ssize_t write(const void *buffer, size_t bytes);
+ virtual void setVolume(float left, float right);
+ virtual int64_t getTimeStamp();
+ virtual void postEOS(int64_t delayUs);
+
+ virtual status_t onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
+ private:
+
+ IDirectTrackClient* mClient;
+ AudioSessionDescriptor *mOutputDesc;
+ int mOutput;
+ bool mIsPaused;
+ audio_output_flags_t mFlag;
+
+ class BufferInfo {
+ public:
+ BufferInfo(void *buf1, void *buf2, int32_t nSize) :
+ localBuf(buf1), dspBuf(buf2), memBufsize(nSize)
+ {}
+
+ void *localBuf;
+ void *dspBuf;
+ uint32_t memBufsize;
+ uint32_t bytesToWrite;
+ };
+ List<BufferInfo> mBufPool;
+ List<BufferInfo> mEffectsPool;
+
+ void allocateBufPool();
+ void deallocateBufPool();
+
+ //******Effects*************
+ static void *EffectsThreadWrapper(void *me);
+ void EffectsThreadEntry();
+ // make sure the Effects thread also exited
+ void requestAndWaitForEffectsThreadExit();
+ void createEffectThread();
+ Condition mEffectCv;
+ Mutex mEffectLock;
+ pthread_t mEffectsThread;
+ bool mKillEffectsThread;
+ bool mEffectsThreadAlive;
+ bool mEffectConfigChanged;
+
+ //Structure to recieve the Effect notification from the flinger.
+ class AudioFlingerDirectTrackClient: public IBinder::DeathRecipient, public BnAudioFlingerClient {
+ public:
+ AudioFlingerDirectTrackClient(void *obj);
+
+ DirectAudioTrack *pBaseClass;
+ // DeathRecipient
+ virtual void binderDied(const wp<IBinder>& who);
+
+ // IAudioFlingerClient
+
+ // 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, audio_io_handle_t ioHandle, const void *param2);
+
+ friend class DirectAudioTrack;
+ };
+ // helper function to obtain AudioFlinger service handle
+ sp<AudioFlinger> mAudioFlinger;
+ sp<AudioFlingerDirectTrackClient> mAudioFlingerClient;
+
+ void clearPowerManager();
+ class PMDeathRecipient : public IBinder::DeathRecipient {
+ public:
+ PMDeathRecipient(void *obj){parentClass = (DirectAudioTrack *)obj;}
+ virtual ~PMDeathRecipient() {}
+
+ // IBinder::DeathRecipient
+ virtual void binderDied(const wp<IBinder>& who);
+
+ private:
+ DirectAudioTrack *parentClass;
+ PMDeathRecipient(const PMDeathRecipient&);
+ PMDeathRecipient& operator = (const PMDeathRecipient&);
+
+ friend class DirectAudioTrack;
+ };
+
+ friend class PMDeathRecipient;
+
+ Mutex pmLock;
+ void acquireWakeLock();
+ void releaseWakeLock();
+
+ sp<IPowerManager> mPowerManager;
+ sp<IBinder> mWakeLockToken;
+ sp<PMDeathRecipient> mDeathRecipient;
+ };
+#endif
+
class TrackHandle : public android::BnAudioTrack {
public:
TrackHandle(const sp<PlaybackThread::Track>& track);
@@ -1424,7 +1569,7 @@ private:
};
void removeClient_l(pid_t pid);
- void removeNotificationClient(pid_t pid);
+ void removeNotificationClient(sp<IBinder> binder);
// record thread
@@ -1636,7 +1781,14 @@ private:
void *pReplyData);
void reset_l();
+#ifdef QCOM_HARDWARE
+ status_t configure(bool isForLPA = false,
+ int sampleRate = 0,
+ int channelCount = 0,
+ int frameCount = 0);
+#else
status_t configure();
+#endif
status_t init();
effect_state state() const {
return mState;
@@ -1683,7 +1835,10 @@ private:
bool purgeHandles();
void lock() { mLock.lock(); }
void unlock() { mLock.unlock(); }
-
+#ifdef QCOM_HARDWARE
+ bool isOnLPA() { return mIsForLPA;}
+ void setLPAFlag(bool isForLPA) {mIsForLPA = isForLPA; }
+#endif
void dump(int fd, const Vector<String16>& args);
protected:
@@ -1715,6 +1870,9 @@ mutable Mutex mLock; // mutex for process, commands and handl
// sending disable command.
uint32_t mDisableWaitCnt; // current process() calls count during disable period.
bool mSuspended; // effect is suspended: temporarily disabled by framework
+#ifdef QCOM_HARDWARE
+ bool mIsForLPA;
+#endif
};
// The EffectHandle class implements the IEffect interface. It provides resources
@@ -1823,12 +1981,18 @@ mutable Mutex mLock; // mutex for process, commands and handl
status_t addEffect_l(const sp<EffectModule>& handle);
size_t removeEffect_l(const sp<EffectModule>& handle);
+#ifdef QCOM_HARDWARE
+ size_t getNumEffects() { return mEffects.size(); }
+#endif
int sessionId() const { return mSessionId; }
void setSessionId(int sessionId) { mSessionId = sessionId; }
sp<EffectModule> getEffectFromDesc_l(effect_descriptor_t *descriptor);
sp<EffectModule> getEffectFromId_l(int id);
+#ifdef QCOM_HARDWARE
+ sp<EffectModule> getEffectFromIndex_l(int idx);
+#endif
sp<EffectModule> getEffectFromType_l(const effect_uuid_t *type);
bool setVolume_l(uint32_t *left, uint32_t *right);
void setDevice_l(audio_devices_t device);
@@ -1874,6 +2038,10 @@ mutable Mutex mLock; // mutex for process, commands and handl
void clearInputBuffer();
void dump(int fd, const Vector<String16>& args);
+#ifdef QCOM_HARDWARE
+ bool isForLPATrack() {return mIsForLPATrack; }
+ void setLPAFlag(bool flag) {mIsForLPATrack = flag;}
+#endif
protected:
friend class AudioFlinger; // for mThread, mEffects
@@ -1922,6 +2090,9 @@ mutable Mutex mLock; // mutex for process, commands and handl
uint32_t mNewLeftVolume; // new volume on left channel
uint32_t mNewRightVolume; // new volume on right channel
uint32_t mStrategy; // strategy for this effect chain
+#ifdef QCOM_HARDWARE
+ bool mIsForLPATrack;
+#endif
// mSuspendedEffects lists all effects currently suspended in the chain.
// Use effect type UUID timelow field as key. There is no real risk of identical
// timeLow fields among effect type UUIDs.
@@ -1983,7 +2154,21 @@ mutable Mutex mLock; // mutex for process, commands and handl
AudioStreamIn(AudioHwDevice *dev, audio_stream_in_t *in) :
audioHwDev(dev), stream(in) {}
};
-
+#ifdef QCOM_HARDWARE
+ struct AudioSessionDescriptor {
+ bool mActive;
+ int mStreamType;
+ float mVolumeLeft;
+ float mVolumeRight;
+ audio_hw_device_t *hwDev;
+ audio_stream_out_t *stream;
+ audio_output_flags_t flag;
+ void *trackRefPtr;
+ audio_devices_t device;
+ AudioSessionDescriptor(audio_hw_device_t *dev, audio_stream_out_t *out, audio_output_flags_t outflag) :
+ hwDev(dev), stream(out), flag(outflag) {}
+ };
+#endif
// for mAudioSessionRefs only
struct AudioSessionRef {
AudioSessionRef(int sessionid, pid_t pid) :
@@ -2043,14 +2228,26 @@ mutable Mutex mLock; // mutex for process, commands and handl
DefaultKeyedVector< audio_io_handle_t, sp<RecordThread> > mRecordThreads;
- DefaultKeyedVector< pid_t, sp<NotificationClient> > mNotificationClients;
+ DefaultKeyedVector< sp<IBinder>, sp<NotificationClient> > mNotificationClients;
volatile int32_t mNextUniqueId; // updated by android_atomic_inc
audio_mode_t mMode;
bool mBtNrecIsOff;
-
+#ifdef QCOM_HARDWARE
+ DefaultKeyedVector<audio_io_handle_t, AudioSessionDescriptor *> mDirectAudioTracks;
+ int mA2DPHandle; // Handle to notify A2DP connection status
+#endif
// protected by mLock
+#ifdef QCOM_HARDWARE
+ volatile bool mIsEffectConfigChanged;
+#endif
Vector<AudioSessionRef*> mAudioSessionRefs;
-
+#ifdef QCOM_HARDWARE
+ sp<EffectChain> mLPAEffectChain;
+ int mLPASessionId;
+ int mLPASampleRate;
+ int mLPANumChannels;
+ volatile bool mAllChainsLocked;
+#endif
float masterVolume_l() const;
bool masterMute_l() const;
audio_module_handle_t loadHwModule_l(const char *name);
diff --git a/services/audioflinger/AudioMixer.cpp b/services/audioflinger/AudioMixer.cpp
index 1e4049a..ab6f38f 100644
--- a/services/audioflinger/AudioMixer.cpp
+++ b/services/audioflinger/AudioMixer.cpp
@@ -549,7 +549,11 @@ bool AudioMixer::track_t::setResampler(uint32_t value, uint32_t devSampleRate)
(value == 48000 && devSampleRate == 44100))) {
quality = AudioResampler::LOW_QUALITY;
} else {
+#ifdef QCOM_ENHANCED_AUDIO
+ quality = AudioResampler::VERY_HIGH_QUALITY;
+#else
quality = AudioResampler::DEFAULT_QUALITY;
+#endif
}
resampler = AudioResampler::create(
format,
diff --git a/services/audioflinger/AudioPolicyService.cpp b/services/audioflinger/AudioPolicyService.cpp
index 8b99bd2..7dd46f2 100644
--- a/services/audioflinger/AudioPolicyService.cpp
+++ b/services/audioflinger/AudioPolicyService.cpp
@@ -388,12 +388,16 @@ status_t AudioPolicyService::setStreamVolumeIndex(audio_stream_type_t stream,
return BAD_VALUE;
}
Mutex::Autolock _l(mLock);
+
+#ifndef ICS_AUDIO_BLOB
if (mpAudioPolicy->set_stream_volume_index_for_device) {
return mpAudioPolicy->set_stream_volume_index_for_device(mpAudioPolicy,
stream,
index,
device);
- } else {
+ } else
+#endif
+ {
return mpAudioPolicy->set_stream_volume_index(mpAudioPolicy, stream, index);
}
}
@@ -409,12 +413,15 @@ status_t AudioPolicyService::getStreamVolumeIndex(audio_stream_type_t stream,
return BAD_VALUE;
}
Mutex::Autolock _l(mLock);
+#ifndef ICS_AUDIO_BLOB
if (mpAudioPolicy->get_stream_volume_index_for_device) {
return mpAudioPolicy->get_stream_volume_index_for_device(mpAudioPolicy,
stream,
index,
device);
- } else {
+ } else
+#endif
+ {
return mpAudioPolicy->get_stream_volume_index(mpAudioPolicy, stream, index);
}
}
diff --git a/services/camera/libcameraservice/Camera2Client.cpp b/services/camera/libcameraservice/Camera2Client.cpp
index 0f1e650..bddcb8c 100644
--- a/services/camera/libcameraservice/Camera2Client.cpp
+++ b/services/camera/libcameraservice/Camera2Client.cpp
@@ -1430,11 +1430,13 @@ void Camera2Client::notifyAutoFocus(uint8_t newState, int triggerId) {
}
}
if (sendMovingMessage) {
+#ifndef OMAP_ICS_CAMERA
SharedCameraClient::Lock l(mSharedCameraClient);
if (l.mCameraClient != 0) {
l.mCameraClient->notifyCallback(CAMERA_MSG_FOCUS_MOVE,
afInMotion ? 1 : 0, 0);
}
+#endif
}
if (sendCompletedMessage) {
SharedCameraClient::Lock l(mSharedCameraClient);
diff --git a/services/camera/libcameraservice/CameraClient.cpp b/services/camera/libcameraservice/CameraClient.cpp
index b930c02..1cdb938 100644
--- a/services/camera/libcameraservice/CameraClient.cpp
+++ b/services/camera/libcameraservice/CameraClient.cpp
@@ -83,8 +83,14 @@ status_t CameraClient::initialize(camera_module_t *module) {
(void *)mCameraId);
// Enable zoom, error, focus, and metadata messages by default
- enableMsgType(CAMERA_MSG_ERROR | CAMERA_MSG_ZOOM | CAMERA_MSG_FOCUS |
- CAMERA_MSG_PREVIEW_METADATA | CAMERA_MSG_FOCUS_MOVE);
+ enableMsgType(CAMERA_MSG_ERROR | CAMERA_MSG_ZOOM | CAMERA_MSG_FOCUS
+#ifndef QCOM_HARDWARE
+ | CAMERA_MSG_PREVIEW_METADATA
+#endif
+#ifndef OMAP_ICS_CAMERA
+ | CAMERA_MSG_FOCUS_MOVE
+#endif
+ );
LOG1("CameraClient::initialize X (pid %d, id %d)", callingPid, mCameraId);
return OK;
@@ -244,9 +250,14 @@ void CameraClient::disconnect() {
// Release the held ANativeWindow resources.
if (mPreviewWindow != 0) {
+#ifdef QCOM_HARDWARE
+ mHardware->setPreviewWindow(0);
+#endif
disconnectWindow(mPreviewWindow);
mPreviewWindow = 0;
+#ifndef QCOM_HARDWARE
mHardware->setPreviewWindow(mPreviewWindow);
+#endif
}
mHardware.clear();
@@ -285,6 +296,10 @@ status_t CameraClient::setPreviewWindow(const sp<IBinder>& binder,
native_window_set_buffers_transform(window.get(), mOrientation);
result = mHardware->setPreviewWindow(window);
}
+#ifdef QCOM_HARDWARE
+ } else {
+ result = mHardware->setPreviewWindow(window);
+#endif
}
if (result == NO_ERROR) {
@@ -344,6 +359,9 @@ void CameraClient::setPreviewCallbackFlag(int callback_flag) {
// start preview mode
status_t CameraClient::startPreview() {
LOG1("startPreview (pid %d)", getCallingPid());
+#ifdef QCOM_HARDWARE
+ enableMsgType(CAMERA_MSG_PREVIEW_METADATA);
+#endif
return startCameraMode(CAMERA_PREVIEW_MODE);
}
@@ -393,6 +411,11 @@ status_t CameraClient::startPreviewMode() {
native_window_set_buffers_transform(mPreviewWindow.get(),
mOrientation);
}
+
+#if defined(OMAP_ICS_CAMERA) || defined(OMAP_ENHANCEMENT_BURST_CAPTURE)
+ disableMsgType(CAMERA_MSG_COMPRESSED_BURST_IMAGE);
+#endif
+
mHardware->setPreviewWindow(mPreviewWindow);
result = mHardware->startPreview();
@@ -429,9 +452,22 @@ status_t CameraClient::startRecordingMode() {
// stop preview mode
void CameraClient::stopPreview() {
LOG1("stopPreview (pid %d)", getCallingPid());
+#ifdef QCOM_HARDWARE
+ disableMsgType(CAMERA_MSG_PREVIEW_METADATA);
+#endif
Mutex::Autolock lock(mLock);
if (checkPidAndHardware() != NO_ERROR) return;
+#ifdef OMAP_ENHANCEMENT
+ // According to framework documentation, preview needs
+ // to be started for image capture. This will make sure
+ // that image capture related messages get disabled if
+ // not done already in their respective handlers.
+ // If these messages come when in the midddle of
+ // stopping preview we will deadlock the system in
+ // lockIfMessageWanted().
+ disableMsgType(CAMERA_MSG_POSTVIEW_FRAME);
+#endif
disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
mHardware->stopPreview();
@@ -527,8 +563,18 @@ status_t CameraClient::takePicture(int msgType) {
CAMERA_MSG_POSTVIEW_FRAME |
CAMERA_MSG_RAW_IMAGE |
CAMERA_MSG_RAW_IMAGE_NOTIFY |
+#if defined(OMAP_ICS_CAMERA) || defined(OMAP_ENHANCEMENT_BURST_CAPTURE)
+ CAMERA_MSG_RAW_BURST |
+#endif
CAMERA_MSG_COMPRESSED_IMAGE);
+#if defined(OMAP_ICS_CAMERA) || defined(OMAP_ENHANCEMENT_BURST_CAPTURE)
+ picMsgType |= CAMERA_MSG_COMPRESSED_BURST_IMAGE;
+#endif
+
+#ifdef QCOM_HARDWARE
+ disableMsgType(CAMERA_MSG_PREVIEW_METADATA);
+#endif
enableMsgType(picMsgType);
return mHardware->takePicture();
@@ -687,6 +733,12 @@ void CameraClient::notifyCallback(int32_t msgType, int32_t ext1,
int32_t ext2, void* user) {
LOG2("notifyCallback(%d)", msgType);
+ // Ignore CAF_RESTART callbacks from Samsung's camera driver
+ if (msgType == CAMERA_MSG_FOCUS && ext1 == 4) {
+ LOG2("Ignore CAF_RESTART callback");
+ return;
+ }
+
Mutex* lock = getClientLockFromCookie(user);
if (lock == NULL) return;
Mutex::Autolock alock(*lock);
@@ -740,6 +792,11 @@ void CameraClient::dataCallback(int32_t msgType,
case CAMERA_MSG_COMPRESSED_IMAGE:
client->handleCompressedPicture(dataPtr);
break;
+#if defined(OMAP_ICS_CAMERA) || defined(OMAP_ENHANCEMENT_BURST_CAPTURE)
+ case CAMERA_MSG_COMPRESSED_BURST_IMAGE:
+ client->handleCompressedBurstPicture(dataPtr);
+ break;
+#endif
default:
client->handleGenericData(msgType, dataPtr, metadata);
break;
@@ -869,6 +926,20 @@ void CameraClient::handleCompressedPicture(const sp<IMemory>& mem) {
}
}
+#if defined(OMAP_ICS_CAMERA) || defined(OMAP_ENHANCEMENT_BURST_CAPTURE)
+// burst picture callback - compressed picture ready
+void CameraClient::handleCompressedBurstPicture(const sp<IMemory>& mem) {
+ // Don't disable this message type yet. In this mode takePicture() will
+ // get called only once. When burst finishes this message will get automatically
+ // disabled in the respective call for restarting the preview.
+
+ sp<ICameraClient> c = mCameraClient;
+ mLock.unlock();
+ if (c != 0) {
+ c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem, NULL);
+ }
+}
+#endif
void CameraClient::handleGenericNotify(int32_t msgType,
int32_t ext1, int32_t ext2) {
diff --git a/services/camera/libcameraservice/CameraClient.h b/services/camera/libcameraservice/CameraClient.h
index 2f31c4e..9b10706 100644
--- a/services/camera/libcameraservice/CameraClient.h
+++ b/services/camera/libcameraservice/CameraClient.h
@@ -97,6 +97,9 @@ private:
void handlePostview(const sp<IMemory>& mem);
void handleRawPicture(const sp<IMemory>& mem);
void handleCompressedPicture(const sp<IMemory>& mem);
+#if defined(OMAP_ICS_CAMERA) || defined(OMAP_ENHANCEMENT_BURST_CAPTURE)
+ void handleCompressedBurstPicture(const sp<IMemory>& mem);
+#endif
void handleGenericNotify(int32_t msgType, int32_t ext1, int32_t ext2);
void handleGenericData(int32_t msgType, const sp<IMemory>& dataPtr,
camera_frame_metadata_t *metadata);
diff --git a/services/camera/libcameraservice/CameraHardwareInterface.h b/services/camera/libcameraservice/CameraHardwareInterface.h
index 05ac9fa..d67996e 100644
--- a/services/camera/libcameraservice/CameraHardwareInterface.h
+++ b/services/camera/libcameraservice/CameraHardwareInterface.h
@@ -113,6 +113,12 @@ public:
ALOGV("%s(%s) buf %p", __FUNCTION__, mName.string(), buf.get());
if (mDevice->ops->set_preview_window) {
+#ifdef QCOM_HARDWARE
+ ALOGV("%s buf %p mPreviewWindow %p", __FUNCTION__, buf.get(), mPreviewWindow.get());
+ if (mPreviewWindow.get() && (buf.get() != mPreviewWindow.get())) {
+ mDevice->ops->set_preview_window(mDevice, 0);
+ }
+#endif
mPreviewWindow = buf;
mHalPreviewWindow.user = this;
ALOGV("%s &mHalPreviewWindow %p mHalPreviewWindow.user %p", __FUNCTION__,
@@ -456,13 +462,17 @@ private:
ALOGV("%s", __FUNCTION__);
CameraHardwareInterface *__this =
static_cast<CameraHardwareInterface *>(user);
- sp<CameraHeapMemory> mem(static_cast<CameraHeapMemory *>(data->handle));
- if (index >= mem->mNumBufs) {
+ if (data != NULL) {
+ sp<CameraHeapMemory> mem(static_cast<CameraHeapMemory *>(data->handle));
+ if (index >= mem->mNumBufs) {
ALOGE("%s: invalid buffer index %d, max allowed is %d", __FUNCTION__,
index, mem->mNumBufs);
return;
+ }
+ __this->mDataCb(msg_type, mem->mBuffers[index], metadata, __this->mCbUser);
+ } else {
+ __this->mDataCb(msg_type, NULL, metadata, __this->mCbUser);
}
- __this->mDataCb(msg_type, mem->mBuffers[index], metadata, __this->mCbUser);
}
static void __data_cb_timestamp(nsecs_t timestamp, int32_t msg_type,
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 124d24d..d8365eb 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -37,6 +37,7 @@
#include <utils/Log.h>
#include <utils/String16.h>
+#include <system/camera.h>
#include "CameraService.h"
#include "CameraClient.h"
#include "Camera2Client.h"
@@ -358,8 +359,18 @@ void CameraService::loadSound() {
LOG1("CameraService::loadSound ref=%d", mSoundRef);
if (mSoundRef++) return;
- mSoundPlayer[SOUND_SHUTTER] = newMediaPlayer("/system/media/audio/ui/camera_click.ogg");
- mSoundPlayer[SOUND_RECORDING] = newMediaPlayer("/system/media/audio/ui/VideoRecord.ogg");
+ char value[PROPERTY_VALUE_MAX];
+ property_get("persist.camera.shutter.disable", value, "0");
+ int disableSound = atoi(value);
+
+ if(!disableSound) {
+ mSoundPlayer[SOUND_SHUTTER] = newMediaPlayer("/system/media/audio/ui/camera_click.ogg");
+ mSoundPlayer[SOUND_RECORDING] = newMediaPlayer("/system/media/audio/ui/VideoRecord.ogg");
+ }
+ else {
+ mSoundPlayer[SOUND_SHUTTER] = NULL;
+ mSoundPlayer[SOUND_RECORDING] = NULL;
+ }
}
void CameraService::releaseSound() {
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 4dab340..7844047 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -23,7 +23,11 @@
#include <hardware/camera.h>
/* This needs to be increased if we can have more cameras */
+#ifdef OMAP_ENHANCEMENT
+#define MAX_CAMERAS 3
+#else
#define MAX_CAMERAS 2
+#endif
namespace android {