Merge "Network traffic accounting for chromium stack support in mediaserver."
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index f20e234..eb22e32 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -108,6 +108,8 @@
static unsigned int getInputFramesLost(audio_io_handle_t ioHandle);
static int newAudioSessionId();
+ static void acquireAudioSessionId(int audioSession);
+ static void releaseAudioSessionId(int audioSession);
// types of io configuration change events received with ioConfigChanged()
enum io_config_event {
diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h
index 4037c46..9e3cb7f 100644
--- a/include/media/IAudioFlinger.h
+++ b/include/media/IAudioFlinger.h
@@ -139,6 +139,9 @@
virtual int newAudioSessionId() = 0;
+ virtual void acquireAudioSessionId(int audioSession) = 0;
+ virtual void releaseAudioSessionId(int audioSession) = 0;
+
virtual status_t queryNumberEffects(uint32_t *numEffects) = 0;
virtual status_t queryEffect(uint32_t index, effect_descriptor_t *pDescriptor) = 0;
diff --git a/include/media/stagefright/HardwareAPI.h b/include/media/stagefright/HardwareAPI.h
index 32eed3f..d785c48 100644
--- a/include/media/stagefright/HardwareAPI.h
+++ b/include/media/stagefright/HardwareAPI.h
@@ -73,6 +73,16 @@
OMX_BOOL bStoreMetaData;
};
+// A pointer to this struct is passed to OMX_SetParameter() when the extension
+// index "OMX.google.android.index.enableSecureMode"
+// is given.
+//
+struct EnableSecureModeParams {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_BOOL bEnableSecureMode;
+};
+
// A pointer to this struct is passed to OMX_SetParameter when the extension
// index for the 'OMX.google.android.index.useAndroidNativeBuffer' extension is
// given. This call will only be performed if a prior call was made with the
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index 2932744..2a1b3d8 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -319,6 +319,8 @@
void initOutputFormat(const sp<MetaData> &inputFormat);
status_t initNativeWindow();
+ status_t enableSecureMode();
+
void dumpPortStatus(OMX_U32 portIndex);
status_t configureCodec(const sp<MetaData> &meta);
diff --git a/include/media/stagefright/SurfaceMediaSource.h b/include/media/stagefright/SurfaceMediaSource.h
index fab258c..1affb8a 100644
--- a/include/media/stagefright/SurfaceMediaSource.h
+++ b/include/media/stagefright/SurfaceMediaSource.h
@@ -133,7 +133,8 @@
//
// This method will fail if the connect was previously called on the
// SurfaceMediaSource and no corresponding disconnect call was made.
- virtual status_t connect(int api);
+ virtual status_t connect(int api,
+ uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform);
// disconnect attempts to disconnect a client API from the SurfaceMediaSource.
// Calling this method will cause any subsequent calls to other
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index 16554c2..e5062ab 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -114,6 +114,7 @@
}
mAudioRecord.clear();
IPCThreadState::self()->flushCommands();
+ AudioSystem::releaseAudioSessionId(mSessionId);
}
}
@@ -233,6 +234,7 @@
mInputSource = (uint8_t)inputSource;
mFlags = flags;
mInput = input;
+ AudioSystem::acquireAudioSessionId(mSessionId);
return NO_ERROR;
}
@@ -465,6 +467,7 @@
((uint16_t)flags) << 16,
&mSessionId,
&status);
+
if (record == 0) {
LOGE("AudioFlinger could not create record track, status: %d", status);
return status;
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index 5009957..b26ed71 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -356,6 +356,20 @@
return af->newAudioSessionId();
}
+void AudioSystem::acquireAudioSessionId(int audioSession) {
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af != 0) {
+ af->acquireAudioSessionId(audioSession);
+ }
+}
+
+void AudioSystem::releaseAudioSessionId(int audioSession) {
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af != 0) {
+ af->releaseAudioSessionId(audioSession);
+ }
+}
+
// ---------------------------------------------------------------------------
void AudioSystem::AudioFlingerClient::binderDied(const wp<IBinder>& who) {
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 31eb97a..3949c39 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -134,6 +134,7 @@
}
mAudioTrack.clear();
IPCThreadState::self()->flushCommands();
+ AudioSystem::releaseAudioSessionId(mSessionId);
}
}
@@ -259,6 +260,7 @@
mNewPosition = 0;
mUpdatePeriod = 0;
mFlags = flags;
+ AudioSystem::acquireAudioSessionId(mSessionId);
return NO_ERROR;
}
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
index 4a12962..d58834b 100644
--- a/media/libmedia/IAudioFlinger.cpp
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -1,4 +1,4 @@
-/* //device/extlibs/pv/android/IAudioflinger.cpp
+/*
**
** Copyright 2007, The Android Open Source Project
**
@@ -63,6 +63,8 @@
GET_RENDER_POSITION,
GET_INPUT_FRAMES_LOST,
NEW_AUDIO_SESSION_ID,
+ ACQUIRE_AUDIO_SESSION_ID,
+ RELEASE_AUDIO_SESSION_ID,
QUERY_NUM_EFFECTS,
QUERY_EFFECT,
GET_EFFECT_DESCRIPTOR,
@@ -526,6 +528,22 @@
return id;
}
+ virtual void acquireAudioSessionId(int audioSession)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32(audioSession);
+ remote()->transact(ACQUIRE_AUDIO_SESSION_ID, data, &reply);
+ }
+
+ virtual void releaseAudioSessionId(int audioSession)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32(audioSession);
+ remote()->transact(RELEASE_AUDIO_SESSION_ID, data, &reply);
+ }
+
virtual status_t queryNumberEffects(uint32_t *numEffects)
{
Parcel data, reply;
@@ -919,6 +937,18 @@
reply->writeInt32(newAudioSessionId());
return NO_ERROR;
} break;
+ case ACQUIRE_AUDIO_SESSION_ID: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ int audioSession = data.readInt32();
+ acquireAudioSessionId(audioSession);
+ return NO_ERROR;
+ } break;
+ case RELEASE_AUDIO_SESSION_ID: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ int audioSession = data.readInt32();
+ releaseAudioSessionId(audioSession);
+ return NO_ERROR;
+ } break;
case QUERY_NUM_EFFECTS: {
CHECK_INTERFACE(IAudioFlinger, data, reply);
uint32_t numEffects;
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index 3dd9249..67a66a2 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -61,12 +61,14 @@
mVideoWidth = mVideoHeight = 0;
mLockThreadId = 0;
mAudioSessionId = AudioSystem::newAudioSessionId();
+ AudioSystem::acquireAudioSessionId(mAudioSessionId);
mSendLevel = 0;
}
MediaPlayer::~MediaPlayer()
{
LOGV("destructor");
+ AudioSystem::releaseAudioSessionId(mAudioSessionId);
disconnect();
IPCThreadState::self()->flushCommands();
}
@@ -618,7 +620,11 @@
if (sessionId < 0) {
return BAD_VALUE;
}
- mAudioSessionId = sessionId;
+ if (sessionId != mAudioSessionId) {
+ AudioSystem::releaseAudioSessionId(mAudioSessionId);
+ AudioSystem::acquireAudioSessionId(sessionId);
+ mAudioSessionId = sessionId;
+ }
return NO_ERROR;
}
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index ea8eaa4..ac3565f 100755
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -665,7 +665,7 @@
LOGV("releaseRecordingFrame");
if (mCameraRecordingProxy != NULL) {
mCameraRecordingProxy->releaseRecordingFrame(frame);
- } else {
+ } else if (mCamera != NULL) {
int64_t token = IPCThreadState::self()->clearCallingIdentity();
mCamera->releaseRecordingFrame(frame);
IPCThreadState::self()->restoreCallingIdentity(token);
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index a4f3922..5327f3b 100755
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -720,9 +720,32 @@
}
}
+ if (mFlags & kUseSecureInputBuffers) {
+ (void)enableSecureMode();
+ }
+
return OK;
}
+status_t OMXCodec::enableSecureMode() {
+ OMX_INDEXTYPE index;
+
+ status_t err =
+ mOMX->getExtensionIndex(
+ mNode, "OMX.google.android.index.enableSecureMode", &index);
+
+ if (err != OK) {
+ return err;
+ }
+
+ EnableSecureModeParams params;
+ InitOMXParams(¶ms);
+
+ params.bEnableSecureMode = OMX_TRUE;
+
+ return mOMX->setConfig(mNode, index, ¶ms, sizeof(params));
+}
+
void OMXCodec::setMinBufferSize(OMX_U32 portIndex, OMX_U32 size) {
OMX_PARAM_PORTDEFINITIONTYPE def;
InitOMXParams(&def);
diff --git a/media/libstagefright/SurfaceMediaSource.cpp b/media/libstagefright/SurfaceMediaSource.cpp
index 3d8c56a..ddfd9ff 100644
--- a/media/libstagefright/SurfaceMediaSource.cpp
+++ b/media/libstagefright/SurfaceMediaSource.cpp
@@ -371,7 +371,8 @@
return err;
}
-status_t SurfaceMediaSource::connect(int api) {
+status_t SurfaceMediaSource::connect(int api,
+ uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
LOGV("SurfaceMediaSource::connect");
Mutex::Autolock lock(mMutex);
status_t err = NO_ERROR;
@@ -384,6 +385,9 @@
err = -EINVAL;
} else {
mConnectedApi = api;
+ *outWidth = mDefaultWidth;
+ *outHeight = mDefaultHeight;
+ *outTransform = 0;
}
break;
default:
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 2355d5c..d6bfda6 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -264,6 +264,14 @@
}
}
}
+
+ result.append("Global session refs:\n");
+ result.append(" session pid cnt\n");
+ for (size_t i = 0; i < mAudioSessionRefs.size(); i++) {
+ AudioSessionRef *r = mAudioSessionRefs[i];
+ snprintf(buffer, SIZE, " %7d %3d %3d\n", r->sessionid, r->pid, r->cnt);
+ result.append(buffer);
+ }
write(fd, result.string(), result.size());
return NO_ERROR;
}
@@ -892,6 +900,25 @@
LOGV("removeNotificationClient() %p, pid %d", client.get(), pid);
mNotificationClients.removeItem(pid);
}
+
+ LOGV("%d died, releasing its sessions", pid);
+ int num = mAudioSessionRefs.size();
+ bool removed = false;
+ for (int i = 0; i< num; i++) {
+ AudioSessionRef *ref = mAudioSessionRefs.itemAt(i);
+ LOGV(" pid %d @ %d", ref->pid, i);
+ if (ref->pid == pid) {
+ LOGV(" removing entry for pid %d session %d", pid, ref->sessionid);
+ mAudioSessionRefs.removeAt(i);
+ delete ref;
+ removed = true;
+ i--;
+ num--;
+ }
+ }
+ if (removed) {
+ purgeStaleEffects_l();
+ }
}
// audioConfigChanged_l() must be called with AudioFlinger::mLock held
@@ -1392,12 +1419,13 @@
// Thread virtuals
status_t AudioFlinger::PlaybackThread::readyToRun()
{
- if (mSampleRate == 0) {
+ status_t status = initCheck();
+ if (status == NO_ERROR) {
+ LOGI("AudioFlinger's thread %p ready to run", this);
+ } else {
LOGE("No working audio driver found.");
- return NO_INIT;
}
- LOGI("AudioFlinger's thread %p ready to run", this);
- return NO_ERROR;
+ return status;
}
void AudioFlinger::PlaybackThread::onFirstRef()
@@ -1491,10 +1519,10 @@
uint32_t AudioFlinger::PlaybackThread::latency() const
{
- if (mOutput) {
+ Mutex::Autolock _l(mLock);
+ if (initCheck() == NO_ERROR) {
return mOutput->stream->get_latency(mOutput->stream);
- }
- else {
+ } else {
return 0;
}
}
@@ -1595,16 +1623,21 @@
String8 AudioFlinger::PlaybackThread::getParameters(const String8& keys)
{
- String8 out_s8;
+ String8 out_s8 = String8("");
char *s;
+ Mutex::Autolock _l(mLock);
+ if (initCheck() != NO_ERROR) {
+ return out_s8;
+ }
+
s = mOutput->stream->common.get_parameters(&mOutput->stream->common, keys.string());
out_s8 = String8(s);
free(s);
return out_s8;
}
-// destroyTrack_l() must be called with AudioFlinger::mLock held
+// audioConfigChanged_l() must be called with AudioFlinger::mLock held
void AudioFlinger::PlaybackThread::audioConfigChanged_l(int event, int param) {
AudioSystem::OutputDescriptor desc;
void *param2 = 0;
@@ -1663,6 +1696,7 @@
if (halFrames == 0 || dspFrames == 0) {
return BAD_VALUE;
}
+ Mutex::Autolock _l(mLock);
if (initCheck() != NO_ERROR) {
return INVALID_OPERATION;
}
@@ -1709,6 +1743,29 @@
}
+AudioFlinger::AudioStreamOut* AudioFlinger::PlaybackThread::getOutput()
+{
+ Mutex::Autolock _l(mLock);
+ return mOutput;
+}
+
+AudioFlinger::AudioStreamOut* AudioFlinger::PlaybackThread::clearOutput()
+{
+ Mutex::Autolock _l(mLock);
+ AudioStreamOut *output = mOutput;
+ mOutput = NULL;
+ return output;
+}
+
+// this method must always be called either with ThreadBase mLock held or inside the thread loop
+audio_stream_t* AudioFlinger::PlaybackThread::stream()
+{
+ if (mOutput == NULL) {
+ return NULL;
+ }
+ return &mOutput->stream->common;
+}
+
// ----------------------------------------------------------------------------
AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device)
@@ -4083,6 +4140,13 @@
run(mName, PRIORITY_URGENT_AUDIO);
}
+status_t AudioFlinger::RecordThread::readyToRun()
+{
+ status_t status = initCheck();
+ LOGW_IF(status != NO_ERROR,"RecordThread %p could not initialize", this);
+ return status;
+}
+
bool AudioFlinger::RecordThread::threadLoop()
{
AudioBufferProvider::Buffer buffer;
@@ -4573,7 +4637,12 @@
String8 AudioFlinger::RecordThread::getParameters(const String8& keys)
{
char *s;
- String8 out_s8;
+ String8 out_s8 = String8();
+
+ Mutex::Autolock _l(mLock);
+ if (initCheck() != NO_ERROR) {
+ return out_s8;
+ }
s = mInput->stream->common.get_parameters(&mInput->stream->common, keys.string());
out_s8 = String8(s);
@@ -4645,6 +4714,11 @@
unsigned int AudioFlinger::RecordThread::getInputFramesLost()
{
+ Mutex::Autolock _l(mLock);
+ if (initCheck() != NO_ERROR) {
+ return 0;
+ }
+
return mInput->stream->get_input_frames_lost(mInput->stream);
}
@@ -4669,6 +4743,30 @@
return mTrack;
}
+AudioFlinger::AudioStreamIn* AudioFlinger::RecordThread::getInput()
+{
+ Mutex::Autolock _l(mLock);
+ return mInput;
+}
+
+AudioFlinger::AudioStreamIn* AudioFlinger::RecordThread::clearInput()
+{
+ Mutex::Autolock _l(mLock);
+ AudioStreamIn *input = mInput;
+ mInput = NULL;
+ return input;
+}
+
+// this method must always be called either with ThreadBase mLock held or inside the thread loop
+audio_stream_t* AudioFlinger::RecordThread::stream()
+{
+ if (mInput == NULL) {
+ return NULL;
+ }
+ return &mInput->stream->common;
+}
+
+
// ----------------------------------------------------------------------------
int AudioFlinger::openOutput(uint32_t *pDevices,
@@ -4792,7 +4890,8 @@
thread->exit();
if (thread->type() != ThreadBase::DUPLICATING) {
- AudioStreamOut *out = thread->getOutput();
+ AudioStreamOut *out = thread->clearOutput();
+ // from now on thread->mOutput is NULL
out->hwDev->close_output_stream(out->hwDev, out->stream);
delete out;
}
@@ -4932,7 +5031,8 @@
}
thread->exit();
- AudioStreamIn *in = thread->getInput();
+ AudioStreamIn *in = thread->clearInput();
+ // from now on thread->mInput is NULL
in->hwDev->close_input_stream(in->hwDev, in->stream);
delete in;
@@ -4969,6 +5069,109 @@
return nextUniqueId();
}
+void AudioFlinger::acquireAudioSessionId(int audioSession)
+{
+ Mutex::Autolock _l(mLock);
+ int caller = IPCThreadState::self()->getCallingPid();
+ LOGV("acquiring %d from %d", audioSession, caller);
+ int num = mAudioSessionRefs.size();
+ for (int i = 0; i< num; i++) {
+ AudioSessionRef *ref = mAudioSessionRefs.editItemAt(i);
+ if (ref->sessionid == audioSession && ref->pid == caller) {
+ ref->cnt++;
+ LOGV(" incremented refcount to %d", ref->cnt);
+ return;
+ }
+ }
+ AudioSessionRef *ref = new AudioSessionRef();
+ ref->sessionid = audioSession;
+ ref->pid = caller;
+ ref->cnt = 1;
+ mAudioSessionRefs.push(ref);
+ LOGV(" added new entry for %d", ref->sessionid);
+}
+
+void AudioFlinger::releaseAudioSessionId(int audioSession)
+{
+ Mutex::Autolock _l(mLock);
+ int caller = IPCThreadState::self()->getCallingPid();
+ LOGV("releasing %d from %d", audioSession, caller);
+ int num = mAudioSessionRefs.size();
+ for (int i = 0; i< num; i++) {
+ AudioSessionRef *ref = mAudioSessionRefs.itemAt(i);
+ if (ref->sessionid == audioSession && ref->pid == caller) {
+ ref->cnt--;
+ LOGV(" decremented refcount to %d", ref->cnt);
+ if (ref->cnt == 0) {
+ mAudioSessionRefs.removeAt(i);
+ delete ref;
+ purgeStaleEffects_l();
+ }
+ return;
+ }
+ }
+ LOGW("session id %d not found for pid %d", audioSession, caller);
+}
+
+void AudioFlinger::purgeStaleEffects_l() {
+
+ LOGV("purging stale effects");
+
+ Vector< sp<EffectChain> > chains;
+
+ for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+ sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
+ for (size_t j = 0; j < t->mEffectChains.size(); j++) {
+ sp<EffectChain> ec = t->mEffectChains[j];
+ chains.push(ec);
+ }
+ }
+ for (size_t i = 0; i < mRecordThreads.size(); i++) {
+ sp<RecordThread> t = mRecordThreads.valueAt(i);
+ for (size_t j = 0; j < t->mEffectChains.size(); j++) {
+ sp<EffectChain> ec = t->mEffectChains[j];
+ chains.push(ec);
+ }
+ }
+
+ for (size_t i = 0; i < chains.size(); i++) {
+ sp<EffectChain> ec = chains[i];
+ int sessionid = ec->sessionId();
+ sp<ThreadBase> t = ec->mThread.promote();
+ if (t == 0) {
+ continue;
+ }
+ size_t numsessionrefs = mAudioSessionRefs.size();
+ bool found = false;
+ for (size_t k = 0; k < numsessionrefs; k++) {
+ AudioSessionRef *ref = mAudioSessionRefs.itemAt(k);
+ if (ref->sessionid == sessionid) {
+ LOGV(" session %d still exists for %d with %d refs",
+ sessionid, ref->pid, ref->cnt);
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ // remove all effects from the chain
+ while (ec->mEffects.size()) {
+ sp<EffectModule> effect = ec->mEffects[0];
+ effect->unPin();
+ Mutex::Autolock _l (t->mLock);
+ t->removeEffect_l(effect);
+ for (size_t j = 0; j < effect->mHandles.size(); j++) {
+ sp<EffectHandle> handle = effect->mHandles[j].promote();
+ if (handle != 0) {
+ handle->mEffect.clear();
+ }
+ }
+ AudioSystem::unregisterEffect(effect->id());
+ }
+ }
+ }
+ return;
+}
+
// checkPlaybackThread_l() must be called with AudioFlinger::mLock held
AudioFlinger::PlaybackThread *AudioFlinger::checkPlaybackThread_l(int output) const
{
@@ -5010,7 +5213,8 @@
{
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
- if (thread->getOutput()->hwDev == mPrimaryHardwareDev) {
+ AudioStreamOut *output = thread->getOutput();
+ if (output != NULL && output->hwDev == mPrimaryHardwareDev) {
return thread;
}
}
@@ -5125,6 +5329,7 @@
}
uint32_t numEffects = 0;
effect_descriptor_t d;
+ d.flags = 0; // prevent compiler warning
bool found = false;
lStatus = EffectQueryNumberEffects(&numEffects);
@@ -5228,7 +5433,7 @@
mClients.add(pid, client);
}
- // create effect on selected output trhead
+ // create effect on selected output thread
handle = thread->createEffect_l(client, effectClient, priority, sessionId,
&desc, enabled, &lStatus);
if (handle != 0 && id != NULL) {
@@ -5270,7 +5475,7 @@
return NO_ERROR;
}
-// moveEffectChain_l mustbe called with both srcThread and dstThread mLocks held
+// moveEffectChain_l must be called with both srcThread and dstThread mLocks held
status_t AudioFlinger::moveEffectChain_l(int sessionId,
AudioFlinger::PlaybackThread *srcThread,
AudioFlinger::PlaybackThread *dstThread,
@@ -5296,7 +5501,7 @@
// correct buffer sizes and audio parameters and effect engines reconfigured accordingly
int dstOutput = dstThread->id();
sp<EffectChain> dstChain;
- uint32_t strategy;
+ uint32_t strategy = 0; // prevent compiler warning
sp<EffectModule> effect = chain->getEffectFromId_l(0);
while (effect != 0) {
srcThread->removeEffect_l(effect);
@@ -5558,14 +5763,17 @@
}
void AudioFlinger::ThreadBase::disconnectEffect(const sp<EffectModule>& effect,
- const wp<EffectHandle>& handle) {
+ const wp<EffectHandle>& handle,
+ bool unpiniflast) {
Mutex::Autolock _l(mLock);
LOGV("disconnectEffect() %p effect %p", this, effect.get());
// delete the effect module if removing last handle on it
if (effect->removeHandle(handle) == 0) {
- removeEffect_l(effect);
- AudioSystem::unregisterEffect(effect->id());
+ if (!effect->isPinned() || unpiniflast) {
+ removeEffect_l(effect);
+ AudioSystem::unregisterEffect(effect->id());
+ }
}
}
@@ -5773,6 +5981,9 @@
goto Error;
}
+ if (mSessionId > AUDIO_SESSION_OUTPUT_MIX) {
+ mPinned = true;
+ }
LOGV("Constructor success name %s, Interface %p", mDescriptor.name, mEffectInterface);
return;
Error:
@@ -5789,7 +6000,10 @@
(mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) {
sp<ThreadBase> thread = mThread.promote();
if (thread != 0) {
- thread->stream()->remove_audio_effect(thread->stream(), mEffectInterface);
+ audio_stream_t *stream = thread->stream();
+ if (stream != NULL) {
+ stream->remove_audio_effect(stream, mEffectInterface);
+ }
}
}
// release effect engine
@@ -5861,7 +6075,7 @@
// Prevent calls to process() and other functions on effect interface from now on.
// The effect engine will be released by the destructor when the last strong reference on
// this object is released which can happen after next process is called.
- if (size == 0) {
+ if (size == 0 && !mPinned) {
mState = DESTROYED;
}
@@ -5878,9 +6092,7 @@
return handle;
}
-
-
-void AudioFlinger::EffectModule::disconnect(const wp<EffectHandle>& handle)
+void AudioFlinger::EffectModule::disconnect(const wp<EffectHandle>& handle, bool unpiniflast)
{
LOGV("disconnect() %p handle %p ", this, handle.unsafe_get());
// keep a strong reference on this EffectModule to avoid calling the
@@ -5889,7 +6101,7 @@
{
sp<ThreadBase> thread = mThread.promote();
if (thread != 0) {
- thread->disconnectEffect(keep, handle);
+ thread->disconnectEffect(keep, handle, unpiniflast);
}
}
}
@@ -6104,7 +6316,10 @@
(mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC)) {
sp<ThreadBase> thread = mThread.promote();
if (thread != 0) {
- thread->stream()->add_audio_effect(thread->stream(), mEffectInterface);
+ audio_stream_t *stream = thread->stream();
+ if (stream != NULL) {
+ stream->add_audio_effect(stream, mEffectInterface);
+ }
}
}
return status;
@@ -6137,7 +6352,10 @@
(mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC)) {
sp<ThreadBase> thread = mThread.promote();
if (thread != 0) {
- thread->stream()->remove_audio_effect(thread->stream(), mEffectInterface);
+ audio_stream_t *stream = thread->stream();
+ if (stream != NULL) {
+ stream->remove_audio_effect(stream, mEffectInterface);
+ }
}
}
return status;
@@ -6450,11 +6668,14 @@
const sp<IEffectClient>& effectClient,
int32_t priority)
: BnEffect(),
- mEffect(effect), mEffectClient(effectClient), mClient(client),
+ mEffect(effect), mEffectClient(effectClient), mClient(client), mCblk(NULL),
mPriority(priority), mHasControl(false), mEnabled(false)
{
LOGV("constructor %p", this);
+ if (client == 0) {
+ return;
+ }
int bufOffset = ((sizeof(effect_param_cblk_t) - 1) / sizeof(int) + 1) * sizeof(int);
mCblkMemory = client->heap()->allocate(EFFECT_PARAM_BUFFER_SIZE + bufOffset);
if (mCblkMemory != 0) {
@@ -6473,7 +6694,7 @@
AudioFlinger::EffectHandle::~EffectHandle()
{
LOGV("Destructor %p", this);
- disconnect();
+ disconnect(false);
LOGV("Destructor DONE %p", this);
}
@@ -6522,12 +6743,16 @@
void AudioFlinger::EffectHandle::disconnect()
{
- LOGV("disconnect %p", this);
+ disconnect(true);
+}
+
+void AudioFlinger::EffectHandle::disconnect(bool unpiniflast)
+{
+ LOGV("disconnect(%s)", unpiniflast ? "true" : "false");
if (mEffect == 0) {
return;
}
-
- mEffect->disconnect(this);
+ mEffect->disconnect(this, unpiniflast);
sp<ThreadBase> thread = mEffect->thread().promote();
if (thread != 0) {
@@ -6536,11 +6761,11 @@
// release sp on module => module destructor can be called now
mEffect.clear();
- if (mCblk) {
- mCblk->~effect_param_cblk_t(); // destroy our shared-structure.
- }
- mCblkMemory.clear(); // and free the shared memory
if (mClient != 0) {
+ if (mCblk) {
+ mCblk->~effect_param_cblk_t(); // destroy our shared-structure.
+ }
+ mCblkMemory.clear(); // and free the shared memory
Mutex::Autolock _l(mClient->audioFlinger()->mLock);
mClient.clear();
}
@@ -6560,6 +6785,7 @@
return INVALID_OPERATION;
}
if (mEffect == 0) return DEAD_OBJECT;
+ if (mClient == 0) return INVALID_OPERATION;
// handle commands that are not forwarded transparently to effect engine
if (cmdCode == EFFECT_CMD_SET_PARAM_COMMIT) {
@@ -6666,15 +6892,15 @@
void AudioFlinger::EffectHandle::dump(char* buffer, size_t size)
{
- bool locked = tryLock(mCblk->lock);
+ bool locked = mCblk ? tryLock(mCblk->lock) : false;
snprintf(buffer, size, "\t\t\t%05d %05d %01u %01u %05u %05u\n",
(mClient == NULL) ? getpid() : mClient->pid(),
mPriority,
mHasControl,
!locked,
- mCblk->clientIndex,
- mCblk->serverIndex
+ mCblk ? mCblk->clientIndex : 0,
+ mCblk ? mCblk->serverIndex : 0
);
if (locked) {
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 791341a..3a0aac9 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -149,6 +149,10 @@
virtual int newAudioSessionId();
+ virtual void acquireAudioSessionId(int audioSession);
+
+ virtual void releaseAudioSessionId(int audioSession);
+
virtual status_t queryNumberEffects(uint32_t *numEffects);
virtual status_t queryEffect(uint32_t index, effect_descriptor_t *descriptor);
@@ -215,6 +219,7 @@
status_t initCheck() const;
virtual void onFirstRef();
audio_hw_device_t* findSuitableHwDev_l(uint32_t devices);
+ void purgeStaleEffects_l();
// Internal dump utilites.
status_t dumpPermissionDenial(int fd, const Vector<String16>& args);
@@ -436,7 +441,8 @@
int *enabled,
status_t *status);
void disconnectEffect(const sp< EffectModule>& effect,
- const wp<EffectHandle>& handle);
+ const wp<EffectHandle>& handle,
+ bool unpiniflast);
// return values for hasAudioSession (bit field)
enum effect_state {
@@ -519,6 +525,7 @@
// updated mSuspendedSessions when an effect chain is removed
void updateSuspendedSessionsOnRemoveEffectChain_l(const sp<EffectChain>& chain);
+ friend class AudioFlinger;
friend class Track;
friend class TrackBase;
friend class PlaybackThread;
@@ -607,7 +614,6 @@
protected:
friend class ThreadBase;
- friend class AudioFlinger;
friend class TrackHandle;
friend class PlaybackThread;
friend class MixerThread;
@@ -724,8 +730,9 @@
int sessionId,
status_t *status);
- AudioStreamOut* getOutput() { return mOutput; }
- virtual audio_stream_t* stream() { return &mOutput->stream->common; }
+ AudioStreamOut* getOutput();
+ AudioStreamOut* clearOutput();
+ virtual audio_stream_t* stream();
void suspend() { mSuspended++; }
void restore() { if (mSuspended) mSuspended--; }
@@ -967,7 +974,7 @@
~RecordThread();
virtual bool threadLoop();
- virtual status_t readyToRun() { return NO_ERROR; }
+ virtual status_t readyToRun();
virtual void onFirstRef();
virtual status_t initCheck() const { return (mInput == 0) ? NO_INIT : NO_ERROR; }
@@ -984,8 +991,9 @@
status_t start(RecordTrack* recordTrack);
void stop(RecordTrack* recordTrack);
status_t dump(int fd, const Vector<String16>& args);
- AudioStreamIn* getInput() { return mInput; }
- virtual audio_stream_t* stream() { return &mInput->stream->common; }
+ AudioStreamIn* getInput();
+ AudioStreamIn* clearInput();
+ virtual audio_stream_t* stream();
virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer);
virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer);
@@ -1098,7 +1106,7 @@
wp<ThreadBase>& thread() { return mThread; }
status_t addHandle(sp<EffectHandle>& handle);
- void disconnect(const wp<EffectHandle>& handle);
+ void disconnect(const wp<EffectHandle>& handle, bool unpiniflast);
size_t removeHandle (const wp<EffectHandle>& handle);
effect_descriptor_t& desc() { return mDescriptor; }
@@ -1113,9 +1121,15 @@
sp<EffectHandle> controlHandle();
+ bool isPinned() { return mPinned; }
+ void unPin() { mPinned = false; }
+
status_t dump(int fd, const Vector<String16>& args);
protected:
+ friend class EffectHandle;
+ friend class AudioFlinger;
+ bool mPinned;
// Maximum time allocated to effect engines to complete the turn off sequence
static const uint32_t MAX_DISABLE_TIME_MS = 10000;
@@ -1167,6 +1181,7 @@
uint32_t *replySize,
void *pReplyData);
virtual void disconnect();
+ virtual void disconnect(bool unpiniflast);
virtual sp<IMemory> getCblk() const;
virtual status_t onTransact(uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags);
@@ -1194,7 +1209,8 @@
void dump(char* buffer, size_t size);
protected:
-
+ friend class AudioFlinger;
+ friend class EffectModule;
EffectHandle(const EffectHandle&);
EffectHandle& operator =(const EffectHandle&);
@@ -1286,7 +1302,7 @@
status_t dump(int fd, const Vector<String16>& args);
protected:
-
+ friend class AudioFlinger;
EffectChain(const EffectChain&);
EffectChain& operator =(const EffectChain&);
@@ -1342,6 +1358,12 @@
hwDev(dev), stream(in) {}
};
+ struct AudioSessionRef {
+ int sessionid;
+ pid_t pid;
+ int cnt;
+ };
+
friend class RecordThread;
friend class PlaybackThread;
@@ -1367,6 +1389,7 @@
uint32_t mMode;
bool mBtNrec;
+ Vector<AudioSessionRef*> mAudioSessionRefs;
};