Merge changes Ie06e73e5,I7ac6b5b0
* changes:
free all buffers when ANativeWindow::disconnect is called
return correct value from query after connecting a surface
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/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/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index e201b17..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
@@ -5042,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
{
@@ -5199,6 +5329,7 @@
}
uint32_t numEffects = 0;
effect_descriptor_t d;
+ d.flags = 0; // prevent compiler warning
bool found = false;
lStatus = EffectQueryNumberEffects(&numEffects);
@@ -5302,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) {
@@ -5344,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,
@@ -5370,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);
@@ -5632,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());
+ }
}
}
@@ -5847,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:
@@ -5938,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;
}
@@ -5955,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
@@ -5966,7 +6101,7 @@
{
sp<ThreadBase> thread = mThread.promote();
if (thread != 0) {
- thread->disconnectEffect(keep, handle);
+ thread->disconnectEffect(keep, handle, unpiniflast);
}
}
}
@@ -6533,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) {
@@ -6556,7 +6694,7 @@
AudioFlinger::EffectHandle::~EffectHandle()
{
LOGV("Destructor %p", this);
- disconnect();
+ disconnect(false);
LOGV("Destructor DONE %p", this);
}
@@ -6605,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) {
@@ -6619,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();
}
@@ -6643,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) {
@@ -6749,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 4fa70a2..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;
@@ -1100,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; }
@@ -1115,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;
@@ -1169,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);
@@ -1196,7 +1209,8 @@
void dump(char* buffer, size_t size);
protected:
-
+ friend class AudioFlinger;
+ friend class EffectModule;
EffectHandle(const EffectHandle&);
EffectHandle& operator =(const EffectHandle&);
@@ -1288,7 +1302,7 @@
status_t dump(int fd, const Vector<String16>& args);
protected:
-
+ friend class AudioFlinger;
EffectChain(const EffectChain&);
EffectChain& operator =(const EffectChain&);
@@ -1344,6 +1358,12 @@
hwDev(dev), stream(in) {}
};
+ struct AudioSessionRef {
+ int sessionid;
+ pid_t pid;
+ int cnt;
+ };
+
friend class RecordThread;
friend class PlaybackThread;
@@ -1369,6 +1389,7 @@
uint32_t mMode;
bool mBtNrec;
+ Vector<AudioSessionRef*> mAudioSessionRefs;
};