summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
Diffstat (limited to 'services')
-rw-r--r--services/audioflinger/AudioFlinger.cpp102
-rw-r--r--services/audioflinger/AudioFlinger.h17
-rw-r--r--services/audioflinger/Effects.cpp4
-rw-r--r--services/audioflinger/Threads.cpp33
-rw-r--r--services/audioflinger/Threads.h19
-rw-r--r--services/audioflinger/Tracks.cpp4
-rw-r--r--services/audiopolicy/AudioPolicyService.cpp184
-rw-r--r--services/audiopolicy/AudioPolicyService.h17
-rw-r--r--services/camera/libcameraservice/api1/client2/Parameters.cpp3
9 files changed, 173 insertions, 210 deletions
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index e256f32..11170c2 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -82,6 +82,7 @@ namespace android {
static const char kDeadlockedString[] = "AudioFlinger may be deadlocked\n";
static const char kHardwareLockedString[] = "Hardware lock is taken\n";
+static const char kClientLockedString[] = "Client lock is taken\n";
nsecs_t AudioFlinger::mStandbyTimeInNsecs = kDefaultStandbyTimeInNsecs;
@@ -382,7 +383,16 @@ status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
write(fd, result.string(), result.size());
}
+ bool clientLocked = dumpTryLock(mClientLock);
+ if (!clientLocked) {
+ String8 result(kClientLockedString);
+ write(fd, result.string(), result.size());
+ }
dumpClients(fd, args);
+ if (clientLocked) {
+ mClientLock.unlock();
+ }
+
dumpInternals(fd, args);
// dump playback threads
@@ -426,8 +436,9 @@ status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
return NO_ERROR;
}
-sp<AudioFlinger::Client> AudioFlinger::registerPid_l(pid_t pid)
+sp<AudioFlinger::Client> AudioFlinger::registerPid(pid_t pid)
{
+ Mutex::Autolock _cl(mClientLock);
// If pid is already in the mClients wp<> map, then use that entry
// (for which promote() is always != 0), otherwise create a new entry and Client.
sp<Client> client = mClients.valueFor(pid).promote();
@@ -564,7 +575,7 @@ sp<IAudioTrack> AudioFlinger::createTrack(
}
pid_t pid = IPCThreadState::self()->getCallingPid();
- client = registerPid_l(pid);
+ client = registerPid(pid);
PlaybackThread *effectThread = NULL;
if (sessionId != NULL && *sessionId != AUDIO_SESSION_ALLOCATE) {
@@ -623,7 +634,8 @@ sp<IAudioTrack> AudioFlinger::createTrack(
if (lStatus != NO_ERROR) {
// remove local strong reference to Client before deleting the Track so that the
- // Client destructor is called by the TrackBase destructor with mLock held
+ // Client destructor is called by the TrackBase destructor with mClientLock held
+ Mutex::Autolock _cl(mClientLock);
client.clear();
track.clear();
goto Exit;
@@ -1140,21 +1152,29 @@ status_t AudioFlinger::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrame
void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)
{
-
Mutex::Autolock _l(mLock);
+ bool clientAdded = false;
+ {
+ Mutex::Autolock _cl(mClientLock);
- pid_t pid = IPCThreadState::self()->getCallingPid();
- if (mNotificationClients.indexOfKey(pid) < 0) {
- sp<NotificationClient> notificationClient = new NotificationClient(this,
- client,
- pid);
- ALOGV("registerClient() client %p, pid %d", notificationClient.get(), pid);
+ pid_t pid = IPCThreadState::self()->getCallingPid();
+ if (mNotificationClients.indexOfKey(pid) < 0) {
+ sp<NotificationClient> notificationClient = new NotificationClient(this,
+ client,
+ pid);
+ ALOGV("registerClient() client %p, pid %d", notificationClient.get(), pid);
- mNotificationClients.add(pid, notificationClient);
+ mNotificationClients.add(pid, notificationClient);
- sp<IBinder> binder = client->asBinder();
- binder->linkToDeath(notificationClient);
+ sp<IBinder> binder = client->asBinder();
+ binder->linkToDeath(notificationClient);
+ clientAdded = true;
+ }
+ }
+ // mClientLock should not be held here because ThreadBase::sendIoConfigEvent() will lock the
+ // ThreadBase mutex and teh locknig order is ThreadBase::mLock then AudioFlinger::mClientLock.
+ if (clientAdded) {
// the config change is always sent from playback or record threads to avoid deadlock
// with AudioSystem::gLock
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
@@ -1170,8 +1190,10 @@ void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)
void AudioFlinger::removeNotificationClient(pid_t pid)
{
Mutex::Autolock _l(mLock);
-
- mNotificationClients.removeItem(pid);
+ {
+ Mutex::Autolock _cl(mClientLock);
+ mNotificationClients.removeItem(pid);
+ }
ALOGV("%d died, releasing its sessions", pid);
size_t num = mAudioSessionRefs.size();
@@ -1194,22 +1216,18 @@ void AudioFlinger::removeNotificationClient(pid_t pid)
}
}
-// audioConfigChanged_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::audioConfigChanged_l(
- const DefaultKeyedVector< pid_t,sp<NotificationClient> >& notificationClients,
- int event,
- audio_io_handle_t ioHandle,
- const void *param2)
+void AudioFlinger::audioConfigChanged(int event, audio_io_handle_t ioHandle, const void *param2)
{
- size_t size = notificationClients.size();
+ Mutex::Autolock _l(mClientLock);
+ size_t size = mNotificationClients.size();
for (size_t i = 0; i < size; i++) {
- notificationClients.valueAt(i)->audioFlingerClient()->ioConfigChanged(event,
+ mNotificationClients.valueAt(i)->audioFlingerClient()->ioConfigChanged(event,
ioHandle,
param2);
}
}
-// removeClient_l() must be called with AudioFlinger::mLock held
+// removeClient_l() must be called with AudioFlinger::mClientLock held
void AudioFlinger::removeClient_l(pid_t pid)
{
ALOGV("removeClient_l() pid %d, calling pid %d", pid,
@@ -1247,7 +1265,7 @@ AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
// 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer
}
-// Client destructor must be called with AudioFlinger::mLock held
+// Client destructor must be called with AudioFlinger::mClientLock held
AudioFlinger::Client::~Client()
{
mAudioFlinger->removeClient_l(mPid);
@@ -1377,7 +1395,7 @@ sp<IAudioRecord> AudioFlinger::openRecord(
}
pid_t pid = IPCThreadState::self()->getCallingPid();
- client = registerPid_l(pid);
+ client = registerPid(pid);
if (sessionId != NULL && *sessionId != AUDIO_SESSION_ALLOCATE) {
lSessionId = *sessionId;
@@ -1400,7 +1418,8 @@ sp<IAudioRecord> AudioFlinger::openRecord(
if (lStatus != NO_ERROR) {
// remove local strong reference to Client before deleting the RecordTrack so that the
- // Client destructor is called by the TrackBase destructor with mLock held
+ // Client destructor is called by the TrackBase destructor with mClientLock held
+ Mutex::Autolock _cl(mClientLock);
client.clear();
recordTrack.clear();
goto Exit;
@@ -1638,7 +1657,7 @@ audio_io_handle_t AudioFlinger::openOutput(audio_module_handle_t module,
}
// notify client processes of the new output creation
- thread->audioConfigChanged_l(mNotificationClients, AudioSystem::OUTPUT_OPENED);
+ thread->audioConfigChanged(AudioSystem::OUTPUT_OPENED);
// the first primary output opened designates the primary hw device
if ((mPrimaryHardwareDev == NULL) && (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
@@ -1674,7 +1693,7 @@ audio_io_handle_t AudioFlinger::openDuplicateOutput(audio_io_handle_t output1,
thread->addOutputTrack(thread2);
mPlaybackThreads.add(id, thread);
// notify client processes of the new output creation
- thread->audioConfigChanged_l(mNotificationClients, AudioSystem::OUTPUT_OPENED);
+ thread->audioConfigChanged(AudioSystem::OUTPUT_OPENED);
return id;
}
@@ -1724,7 +1743,7 @@ status_t AudioFlinger::closeOutput_nonvirtual(audio_io_handle_t output)
}
}
}
- audioConfigChanged_l(mNotificationClients, AudioSystem::OUTPUT_CLOSED, output, NULL);
+ audioConfigChanged(AudioSystem::OUTPUT_CLOSED, output, NULL);
}
thread->exit();
// The thread entity (active unit of execution) is no longer running here,
@@ -1904,7 +1923,7 @@ audio_io_handle_t AudioFlinger::openInput(audio_module_handle_t module,
}
// notify client processes of the new input creation
- thread->audioConfigChanged_l(mNotificationClients, AudioSystem::INPUT_OPENED);
+ thread->audioConfigChanged(AudioSystem::INPUT_OPENED);
return id;
}
@@ -1929,7 +1948,7 @@ status_t AudioFlinger::closeInput_nonvirtual(audio_io_handle_t input)
}
ALOGV("closeInput() %d", input);
- audioConfigChanged_l(mNotificationClients, AudioSystem::INPUT_CLOSED, input, NULL);
+ audioConfigChanged(AudioSystem::INPUT_CLOSED, input, NULL);
mRecordThreads.removeItem(input);
}
thread->exit();
@@ -1973,13 +1992,16 @@ void AudioFlinger::acquireAudioSessionId(int audioSession, pid_t pid)
caller = pid;
}
- // Ignore requests received from processes not known as notification client. The request
- // is likely proxied by mediaserver (e.g CameraService) and releaseAudioSessionId() can be
- // called from a different pid leaving a stale session reference. Also we don't know how
- // to clear this reference if the client process dies.
- if (mNotificationClients.indexOfKey(caller) < 0) {
- ALOGW("acquireAudioSessionId() unknown client %d for session %d", caller, audioSession);
- return;
+ {
+ Mutex::Autolock _cl(mClientLock);
+ // Ignore requests received from processes not known as notification client. The request
+ // is likely proxied by mediaserver (e.g CameraService) and releaseAudioSessionId() can be
+ // called from a different pid leaving a stale session reference. Also we don't know how
+ // to clear this reference if the client process dies.
+ if (mNotificationClients.indexOfKey(caller) < 0) {
+ ALOGW("acquireAudioSessionId() unknown client %d for session %d", caller, audioSession);
+ return;
+ }
}
size_t num = mAudioSessionRefs.size();
@@ -2348,7 +2370,7 @@ sp<IEffect> AudioFlinger::createEffect(
}
}
- sp<Client> client = registerPid_l(pid);
+ sp<Client> client = registerPid(pid);
// create effect on selected output thread
handle = thread->createEffect_l(client, effectClient, priority, sessionId,
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 894bd35..c1d4c08 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -453,11 +453,7 @@ private:
// no range check, doesn't check per-thread stream volume, AudioFlinger::mLock held
float streamVolume_l(audio_stream_type_t stream) const
{ return mStreamTypes[stream].volume; }
- void audioConfigChanged_l(const DefaultKeyedVector< pid_t,sp<NotificationClient> >&
- notificationClients,
- int event,
- audio_io_handle_t ioHandle,
- const void *param2);
+ void audioConfigChanged(int event, audio_io_handle_t ioHandle, const void *param2);
// Allocate an audio_io_handle_t, session ID, effect ID, or audio_module_handle_t.
// They all share the same ID space, but the namespaces are actually independent
@@ -482,8 +478,6 @@ private:
void removeClient_l(pid_t pid);
void removeNotificationClient(pid_t pid);
- DefaultKeyedVector< pid_t,sp<NotificationClient> > notificationClients() {
- Mutex::Autolock _l(mLock); return mNotificationClients; }
bool isNonOffloadableGlobalEffectEnabled_l();
void onNonOffloadableGlobalEffectEnable();
@@ -553,7 +547,11 @@ private:
};
mutable Mutex mLock;
-
+ // protects mClients and mNotificationClients.
+ // must be locked after mLock and ThreadBase::mLock if both must be locked
+ // avoids acquiring AudioFlinger::mLock from inside thread loop.
+ mutable Mutex mClientLock;
+ // protected by mClientLock
DefaultKeyedVector< pid_t, wp<Client> > mClients; // see ~Client()
mutable Mutex mHardwareLock;
@@ -602,6 +600,7 @@ private:
DefaultKeyedVector< audio_io_handle_t, sp<RecordThread> > mRecordThreads;
+ // protected by mClientLock
DefaultKeyedVector< pid_t, sp<NotificationClient> > mNotificationClients;
volatile int32_t mNextUniqueId; // updated by android_atomic_inc
@@ -622,7 +621,7 @@ private:
// to be created
private:
- sp<Client> registerPid_l(pid_t pid); // always returns non-0
+ sp<Client> registerPid(pid_t pid); // always returns non-0
// for use from destructor
status_t closeOutput_nonvirtual(audio_io_handle_t output);
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 29b56db..77aca00 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -1162,8 +1162,8 @@ void AudioFlinger::EffectHandle::disconnect(bool unpinIfLast)
mCblk->~effect_param_cblk_t(); // destroy our shared-structure.
}
mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to
- // Client destructor must run with AudioFlinger mutex locked
- Mutex::Autolock _l(mClient->audioFlinger()->mLock);
+ // Client destructor must run with AudioFlinger client mutex locked
+ Mutex::Autolock _l(mClient->audioFlinger()->mClientLock);
mClient.clear();
}
}
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 470b018..8243a8b 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -401,8 +401,7 @@ status_t AudioFlinger::ThreadBase::sendSetParameterConfigEvent_l(const String8&
}
// post condition: mConfigEvents.isEmpty()
-void AudioFlinger::ThreadBase::processConfigEvents_l(
- const DefaultKeyedVector< pid_t,sp<NotificationClient> >& notificationClients)
+void AudioFlinger::ThreadBase::processConfigEvents_l()
{
bool configChanged = false;
@@ -423,7 +422,7 @@ void AudioFlinger::ThreadBase::processConfigEvents_l(
} break;
case CFG_EVENT_IO: {
IoConfigEventData *data = (IoConfigEventData *)event->mData.get();
- audioConfigChanged_l(notificationClients, data->mEvent, data->mParam);
+ audioConfigChanged(data->mEvent, data->mParam);
} break;
case CFG_EVENT_SET_PARAMETER: {
SetParameterConfigEventData *data = (SetParameterConfigEventData *)event->mData.get();
@@ -1638,15 +1637,11 @@ String8 AudioFlinger::PlaybackThread::getParameters(const String8& keys)
return out_s8;
}
-// audioConfigChanged_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::PlaybackThread::audioConfigChanged_l(
- const DefaultKeyedVector< pid_t,sp<NotificationClient> >& notificationClients,
- int event,
- int param) {
+void AudioFlinger::PlaybackThread::audioConfigChanged(int event, int param) {
AudioSystem::OutputDescriptor desc;
void *param2 = NULL;
- ALOGV("PlaybackThread::audioConfigChanged_l, thread %p, event %d, param %d", this, event,
+ ALOGV("PlaybackThread::audioConfigChanged, thread %p, event %d, param %d", this, event,
param);
switch (event) {
@@ -1667,7 +1662,7 @@ void AudioFlinger::PlaybackThread::audioConfigChanged_l(
default:
break;
}
- mAudioFlinger->audioConfigChanged_l(notificationClients, event, mId, param2);
+ mAudioFlinger->audioConfigChanged(event, mId, param2);
}
void AudioFlinger::PlaybackThread::writeCallback()
@@ -2317,15 +2312,11 @@ bool AudioFlinger::PlaybackThread::threadLoop()
Vector< sp<EffectChain> > effectChains;
- DefaultKeyedVector< pid_t,sp<NotificationClient> > notificationClients =
- mAudioFlinger->notificationClients();
-
{ // scope for mLock
Mutex::Autolock _l(mLock);
- processConfigEvents_l(notificationClients);
- notificationClients.clear();
+ processConfigEvents_l();
if (logString != NULL) {
mNBLogWriter->logTimestamp();
@@ -4695,14 +4686,11 @@ reacquire_wakelock:
// activeTracks accumulates a copy of a subset of mActiveTracks
Vector< sp<RecordTrack> > activeTracks;
- DefaultKeyedVector< pid_t,sp<NotificationClient> > notificationClients =
- mAudioFlinger->notificationClients();
{ // scope for mLock
Mutex::Autolock _l(mLock);
- processConfigEvents_l(notificationClients);
- notificationClients.clear();
+ processConfigEvents_l();
// check exitPending here because checkForNewParameters_l() and
// checkForNewParameters_l() can temporarily release mLock
@@ -5605,10 +5593,7 @@ String8 AudioFlinger::RecordThread::getParameters(const String8& keys)
return out_s8;
}
-void AudioFlinger::RecordThread::audioConfigChanged_l(
- const DefaultKeyedVector< pid_t,sp<NotificationClient> >& notificationClients,
- int event,
- int param __unused) {
+void AudioFlinger::RecordThread::audioConfigChanged(int event, int param __unused) {
AudioSystem::OutputDescriptor desc;
const void *param2 = NULL;
@@ -5627,7 +5612,7 @@ void AudioFlinger::RecordThread::audioConfigChanged_l(
default:
break;
}
- mAudioFlinger->audioConfigChanged_l(notificationClients, event, mId, param2);
+ mAudioFlinger->audioConfigChanged(event, mId, param2);
}
void AudioFlinger::RecordThread::readInputParameters_l()
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 9578993..cc2b246 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -200,10 +200,7 @@ public:
status_t& status) = 0;
virtual status_t setParameters(const String8& keyValuePairs);
virtual String8 getParameters(const String8& keys) = 0;
- virtual void audioConfigChanged_l(
- const DefaultKeyedVector< pid_t,sp<NotificationClient> >& notificationClients,
- int event,
- int param = 0) = 0;
+ virtual void audioConfigChanged(int event, int param = 0) = 0;
// sendConfigEvent_l() must be called with ThreadBase::mLock held
// Can temporarily release the lock if waiting for a reply from
// processConfigEvents_l().
@@ -212,8 +209,7 @@ public:
void sendIoConfigEvent_l(int event, int param = 0);
void sendPrioConfigEvent_l(pid_t pid, pid_t tid, int32_t prio);
status_t sendSetParameterConfigEvent_l(const String8& keyValuePair);
- void processConfigEvents_l(
- const DefaultKeyedVector< pid_t,sp<NotificationClient> >& notificationClients);
+ void processConfigEvents_l();
virtual void cacheParameters_l() = 0;
// see note at declaration of mStandby, mOutDevice and mInDevice
@@ -502,10 +498,7 @@ public:
{ return android_atomic_acquire_load(&mSuspended) > 0; }
virtual String8 getParameters(const String8& keys);
- virtual void audioConfigChanged_l(
- const DefaultKeyedVector< pid_t,sp<NotificationClient> >& notificationClients,
- int event,
- int param = 0);
+ virtual void audioConfigChanged(int event, int param = 0);
status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames);
// FIXME rename mixBuffer() to sinkBuffer() and remove int16_t* dependency.
// Consider also removing and passing an explicit mMainBuffer initialization
@@ -652,7 +645,6 @@ private:
friend class AudioFlinger; // for numerous
- PlaybackThread(const Client&);
PlaybackThread& operator = (const PlaybackThread&);
status_t addTrack_l(const sp<Track>& track);
@@ -1037,10 +1029,7 @@ public:
status_t& status);
virtual void cacheParameters_l() {}
virtual String8 getParameters(const String8& keys);
- virtual void audioConfigChanged_l(
- const DefaultKeyedVector< pid_t,sp<NotificationClient> >& notificationClients,
- int event,
- int param = 0);
+ virtual void audioConfigChanged(int event, int param = 0);
void readInputParameters_l();
virtual uint32_t getInputFramesLost();
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index d8f3423..88ead74 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -198,8 +198,8 @@ AudioFlinger::ThreadBase::TrackBase::~TrackBase()
}
mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to
if (mClient != 0) {
- // Client destructor must run with AudioFlinger mutex locked
- Mutex::Autolock _l(mClient->audioFlinger()->mLock);
+ // Client destructor must run with AudioFlinger client mutex locked
+ Mutex::Autolock _l(mClient->audioFlinger()->mClientLock);
// If the client's reference count drops to zero, the associated destructor
// must run with AudioFlinger lock held. Thus the explicit clear() rather than
// relying on the automatic clear() at end of scope.
diff --git a/services/audiopolicy/AudioPolicyService.cpp b/services/audiopolicy/AudioPolicyService.cpp
index 2811475..4e9a2f0 100644
--- a/services/audiopolicy/AudioPolicyService.cpp
+++ b/services/audiopolicy/AudioPolicyService.cpp
@@ -51,7 +51,7 @@ static const char kCmdDeadlockedString[] = "AudioPolicyService command thread ma
static const int kDumpLockRetries = 50;
static const int kDumpLockSleepUs = 20000;
-static const nsecs_t kAudioCommandTimeout = 3000000000LL; // 3 seconds
+static const nsecs_t kAudioCommandTimeoutNs = seconds(3); // 3 seconds
namespace {
extern struct audio_policy_service_ops aps_ops;
@@ -268,10 +268,6 @@ AudioPolicyService::AudioCommandThread::~AudioCommandThread()
if (!mAudioCommands.isEmpty()) {
release_wake_lock(mName.string());
}
- for (size_t k=0; k < mAudioCommands.size(); k++) {
- delete mAudioCommands[k]->mParam;
- delete mAudioCommands[k];
- }
mAudioCommands.clear();
delete mpToneGenerator;
}
@@ -292,20 +288,19 @@ bool AudioPolicyService::AudioCommandThread::threadLoop()
nsecs_t curTime = systemTime();
// commands are sorted by increasing time stamp: execute them from index 0 and up
if (mAudioCommands[0]->mTime <= curTime) {
- AudioCommand *command = mAudioCommands[0];
+ sp<AudioCommand> command = mAudioCommands[0];
mAudioCommands.removeAt(0);
- mLastCommand = *command;
+ mLastCommand = command;
switch (command->mCommand) {
case START_TONE: {
mLock.unlock();
- ToneData *data = (ToneData *)command->mParam;
+ ToneData *data = (ToneData *)command->mParam.get();
ALOGV("AudioCommandThread() processing start tone %d on stream %d",
data->mType, data->mStream);
delete mpToneGenerator;
mpToneGenerator = new ToneGenerator(data->mStream, 1.0);
mpToneGenerator->startTone(data->mType);
- delete data;
mLock.lock();
}break;
case STOP_TONE: {
@@ -319,42 +314,27 @@ bool AudioPolicyService::AudioCommandThread::threadLoop()
mLock.lock();
}break;
case SET_VOLUME: {
- VolumeData *data = (VolumeData *)command->mParam;
+ VolumeData *data = (VolumeData *)command->mParam.get();
ALOGV("AudioCommandThread() processing set volume stream %d, \
volume %f, output %d", data->mStream, data->mVolume, data->mIO);
command->mStatus = AudioSystem::setStreamVolume(data->mStream,
data->mVolume,
data->mIO);
- if (command->mWaitStatus) {
- command->mCond.signal();
- command->mCond.waitRelative(mLock, kAudioCommandTimeout);
- }
- delete data;
}break;
case SET_PARAMETERS: {
- ParametersData *data = (ParametersData *)command->mParam;
+ ParametersData *data = (ParametersData *)command->mParam.get();
ALOGV("AudioCommandThread() processing set parameters string %s, io %d",
data->mKeyValuePairs.string(), data->mIO);
command->mStatus = AudioSystem::setParameters(data->mIO, data->mKeyValuePairs);
- if (command->mWaitStatus) {
- command->mCond.signal();
- command->mCond.waitRelative(mLock, kAudioCommandTimeout);
- }
- delete data;
}break;
case SET_VOICE_VOLUME: {
- VoiceVolumeData *data = (VoiceVolumeData *)command->mParam;
+ VoiceVolumeData *data = (VoiceVolumeData *)command->mParam.get();
ALOGV("AudioCommandThread() processing set voice volume volume %f",
data->mVolume);
command->mStatus = AudioSystem::setVoiceVolume(data->mVolume);
- if (command->mWaitStatus) {
- command->mCond.signal();
- command->mCond.waitRelative(mLock, kAudioCommandTimeout);
- }
- delete data;
}break;
case STOP_OUTPUT: {
- StopOutputData *data = (StopOutputData *)command->mParam;
+ StopOutputData *data = (StopOutputData *)command->mParam.get();
ALOGV("AudioCommandThread() processing stop output %d",
data->mIO);
sp<AudioPolicyService> svc = mService.promote();
@@ -364,10 +344,9 @@ bool AudioPolicyService::AudioCommandThread::threadLoop()
mLock.unlock();
svc->doStopOutput(data->mIO, data->mStream, data->mSession);
mLock.lock();
- delete data;
}break;
case RELEASE_OUTPUT: {
- ReleaseOutputData *data = (ReleaseOutputData *)command->mParam;
+ ReleaseOutputData *data = (ReleaseOutputData *)command->mParam.get();
ALOGV("AudioCommandThread() processing release output %d",
data->mIO);
sp<AudioPolicyService> svc = mService.promote();
@@ -377,12 +356,17 @@ bool AudioPolicyService::AudioCommandThread::threadLoop()
mLock.unlock();
svc->doReleaseOutput(data->mIO);
mLock.lock();
- delete data;
}break;
default:
ALOGW("AudioCommandThread() unknown command %d", command->mCommand);
}
- delete command;
+ {
+ Mutex::Autolock _l(command->mLock);
+ if (command->mWaitStatus) {
+ command->mWaitStatus = false;
+ command->mCond.signal();
+ }
+ }
waitTime = INT64_MAX;
} else {
waitTime = mAudioCommands[0]->mTime - curTime;
@@ -425,8 +409,12 @@ status_t AudioPolicyService::AudioCommandThread::dump(int fd)
result.append(buffer);
}
result.append(" Last Command\n");
- mLastCommand.dump(buffer, SIZE);
- result.append(buffer);
+ if (mLastCommand != 0) {
+ mLastCommand->dump(buffer, SIZE);
+ result.append(buffer);
+ } else {
+ result.append(" none\n");
+ }
write(fd, result.string(), result.size());
@@ -438,27 +426,22 @@ status_t AudioPolicyService::AudioCommandThread::dump(int fd)
void AudioPolicyService::AudioCommandThread::startToneCommand(ToneGenerator::tone_type type,
audio_stream_type_t stream)
{
- AudioCommand *command = new AudioCommand();
+ sp<AudioCommand> command = new AudioCommand();
command->mCommand = START_TONE;
- ToneData *data = new ToneData();
+ sp<ToneData> data = new ToneData();
data->mType = type;
data->mStream = stream;
command->mParam = data;
- Mutex::Autolock _l(mLock);
- insertCommand_l(command);
ALOGV("AudioCommandThread() adding tone start type %d, stream %d", type, stream);
- mWaitWorkCV.signal();
+ sendCommand(command);
}
void AudioPolicyService::AudioCommandThread::stopToneCommand()
{
- AudioCommand *command = new AudioCommand();
+ sp<AudioCommand> command = new AudioCommand();
command->mCommand = STOP_TONE;
- command->mParam = NULL;
- Mutex::Autolock _l(mLock);
- insertCommand_l(command);
ALOGV("AudioCommandThread() adding tone stop");
- mWaitWorkCV.signal();
+ sendCommand(command);
}
status_t AudioPolicyService::AudioCommandThread::volumeCommand(audio_stream_type_t stream,
@@ -466,109 +449,96 @@ status_t AudioPolicyService::AudioCommandThread::volumeCommand(audio_stream_type
audio_io_handle_t output,
int delayMs)
{
- status_t status = NO_ERROR;
-
- AudioCommand *command = new AudioCommand();
+ sp<AudioCommand> command = new AudioCommand();
command->mCommand = SET_VOLUME;
- VolumeData *data = new VolumeData();
+ sp<VolumeData> data = new VolumeData();
data->mStream = stream;
data->mVolume = volume;
data->mIO = output;
command->mParam = data;
- Mutex::Autolock _l(mLock);
- insertCommand_l(command, delayMs);
+ command->mWaitStatus = true;
ALOGV("AudioCommandThread() adding set volume stream %d, volume %f, output %d",
stream, volume, output);
- mWaitWorkCV.signal();
- if (command->mWaitStatus) {
- command->mCond.wait(mLock);
- status = command->mStatus;
- command->mCond.signal();
- }
- return status;
+ return sendCommand(command, delayMs);
}
status_t AudioPolicyService::AudioCommandThread::parametersCommand(audio_io_handle_t ioHandle,
const char *keyValuePairs,
int delayMs)
{
- status_t status = NO_ERROR;
-
- AudioCommand *command = new AudioCommand();
+ sp<AudioCommand> command = new AudioCommand();
command->mCommand = SET_PARAMETERS;
- ParametersData *data = new ParametersData();
+ sp<ParametersData> data = new ParametersData();
data->mIO = ioHandle;
data->mKeyValuePairs = String8(keyValuePairs);
command->mParam = data;
- Mutex::Autolock _l(mLock);
- insertCommand_l(command, delayMs);
+ command->mWaitStatus = true;
ALOGV("AudioCommandThread() adding set parameter string %s, io %d ,delay %d",
keyValuePairs, ioHandle, delayMs);
- mWaitWorkCV.signal();
- if (command->mWaitStatus) {
- command->mCond.wait(mLock);
- status = command->mStatus;
- command->mCond.signal();
- }
- return status;
+ return sendCommand(command, delayMs);
}
status_t AudioPolicyService::AudioCommandThread::voiceVolumeCommand(float volume, int delayMs)
{
- status_t status = NO_ERROR;
-
- AudioCommand *command = new AudioCommand();
+ sp<AudioCommand> command = new AudioCommand();
command->mCommand = SET_VOICE_VOLUME;
- VoiceVolumeData *data = new VoiceVolumeData();
+ sp<VoiceVolumeData> data = new VoiceVolumeData();
data->mVolume = volume;
command->mParam = data;
- Mutex::Autolock _l(mLock);
- insertCommand_l(command, delayMs);
+ command->mWaitStatus = true;
ALOGV("AudioCommandThread() adding set voice volume volume %f", volume);
- mWaitWorkCV.signal();
- if (command->mWaitStatus) {
- command->mCond.wait(mLock);
- status = command->mStatus;
- command->mCond.signal();
- }
- return status;
+ return sendCommand(command, delayMs);
}
void AudioPolicyService::AudioCommandThread::stopOutputCommand(audio_io_handle_t output,
audio_stream_type_t stream,
int session)
{
- AudioCommand *command = new AudioCommand();
+ sp<AudioCommand> command = new AudioCommand();
command->mCommand = STOP_OUTPUT;
- StopOutputData *data = new StopOutputData();
+ sp<StopOutputData> data = new StopOutputData();
data->mIO = output;
data->mStream = stream;
data->mSession = session;
command->mParam = data;
- Mutex::Autolock _l(mLock);
- insertCommand_l(command);
ALOGV("AudioCommandThread() adding stop output %d", output);
- mWaitWorkCV.signal();
+ sendCommand(command);
}
void AudioPolicyService::AudioCommandThread::releaseOutputCommand(audio_io_handle_t output)
{
- AudioCommand *command = new AudioCommand();
+ sp<AudioCommand> command = new AudioCommand();
command->mCommand = RELEASE_OUTPUT;
- ReleaseOutputData *data = new ReleaseOutputData();
+ sp<ReleaseOutputData> data = new ReleaseOutputData();
data->mIO = output;
command->mParam = data;
- Mutex::Autolock _l(mLock);
- insertCommand_l(command);
ALOGV("AudioCommandThread() adding release output %d", output);
- mWaitWorkCV.signal();
+ sendCommand(command);
+}
+
+status_t AudioPolicyService::AudioCommandThread::sendCommand(sp<AudioCommand>& command, int delayMs)
+{
+ {
+ Mutex::Autolock _l(mLock);
+ insertCommand_l(command, delayMs);
+ mWaitWorkCV.signal();
+ }
+ Mutex::Autolock _l(command->mLock);
+ while (command->mWaitStatus) {
+ nsecs_t timeOutNs = kAudioCommandTimeoutNs + milliseconds(delayMs);
+ if (command->mCond.waitRelative(command->mLock, timeOutNs) != NO_ERROR) {
+ command->mStatus = TIMED_OUT;
+ command->mWaitStatus = false;
+ }
+ }
+ return command->mStatus;
}
// insertCommand_l() must be called with mLock held
-void AudioPolicyService::AudioCommandThread::insertCommand_l(AudioCommand *command, int delayMs)
+void AudioPolicyService::AudioCommandThread::insertCommand_l(sp<AudioCommand>& command, int delayMs)
{
ssize_t i; // not size_t because i will count down to -1
- Vector <AudioCommand *> removedCommands;
+ Vector < sp<AudioCommand> > removedCommands;
command->mTime = systemTime() + milliseconds(delayMs);
// acquire wake lock to make sure delayed commands are processed
@@ -578,15 +548,15 @@ void AudioPolicyService::AudioCommandThread::insertCommand_l(AudioCommand *comma
// check same pending commands with later time stamps and eliminate them
for (i = mAudioCommands.size()-1; i >= 0; i--) {
- AudioCommand *command2 = mAudioCommands[i];
+ sp<AudioCommand> command2 = mAudioCommands[i];
// commands are sorted by increasing time stamp: no need to scan the rest of mAudioCommands
if (command2->mTime <= command->mTime) break;
if (command2->mCommand != command->mCommand) continue;
switch (command->mCommand) {
case SET_PARAMETERS: {
- ParametersData *data = (ParametersData *)command->mParam;
- ParametersData *data2 = (ParametersData *)command2->mParam;
+ ParametersData *data = (ParametersData *)command->mParam.get();
+ ParametersData *data2 = (ParametersData *)command2->mParam.get();
if (data->mIO != data2->mIO) break;
ALOGV("Comparing parameter command %s to new command %s",
data2->mKeyValuePairs.string(), data->mKeyValuePairs.string());
@@ -621,8 +591,8 @@ void AudioPolicyService::AudioCommandThread::insertCommand_l(AudioCommand *comma
} break;
case SET_VOLUME: {
- VolumeData *data = (VolumeData *)command->mParam;
- VolumeData *data2 = (VolumeData *)command2->mParam;
+ VolumeData *data = (VolumeData *)command->mParam.get();
+ VolumeData *data2 = (VolumeData *)command2->mParam.get();
if (data->mIO != data2->mIO) break;
if (data->mStream != data2->mStream) break;
ALOGV("Filtering out volume command on output %d for stream %d",
@@ -644,12 +614,8 @@ void AudioPolicyService::AudioCommandThread::insertCommand_l(AudioCommand *comma
for (size_t j = 0; j < removedCommands.size(); j++) {
// removed commands always have time stamps greater than current command
for (size_t k = i + 1; k < mAudioCommands.size(); k++) {
- if (mAudioCommands[k] == removedCommands[j]) {
+ if (mAudioCommands[k].get() == removedCommands[j].get()) {
ALOGV("suppressing command: %d", mAudioCommands[k]->mCommand);
- // for commands that are not filtered,
- // command->mParam is deleted in threadLoop
- delete mAudioCommands[k]->mParam;
- delete mAudioCommands[k];
mAudioCommands.removeAt(k);
break;
}
@@ -657,10 +623,8 @@ void AudioPolicyService::AudioCommandThread::insertCommand_l(AudioCommand *comma
}
removedCommands.clear();
- // wait for status only if delay is 0
- if (delayMs == 0) {
- command->mWaitStatus = true;
- } else {
+ // Disable wait for status if delay is not 0
+ if (delayMs != 0) {
command->mWaitStatus = false;
}
@@ -688,7 +652,7 @@ void AudioPolicyService::AudioCommandThread::AudioCommand::dump(char* buffer, si
(int)ns2s(mTime),
(int)ns2ms(mTime)%1000,
mWaitStatus,
- mParam);
+ mParam.get());
}
/******* helpers for the service_ops callbacks defined below *********/
diff --git a/services/audiopolicy/AudioPolicyService.h b/services/audiopolicy/AudioPolicyService.h
index 28e3a4b..26037e4 100644
--- a/services/audiopolicy/AudioPolicyService.h
+++ b/services/audiopolicy/AudioPolicyService.h
@@ -194,30 +194,31 @@ private:
audio_stream_type_t stream,
int session);
void releaseOutputCommand(audio_io_handle_t output);
-
- void insertCommand_l(AudioCommand *command, int delayMs = 0);
+ status_t sendCommand(sp<AudioCommand>& command, int delayMs = 0);
+ void insertCommand_l(sp<AudioCommand>& command, int delayMs = 0);
private:
class AudioCommandData;
// descriptor for requested tone playback event
- class AudioCommand {
+ class AudioCommand: public RefBase {
public:
AudioCommand()
- : mCommand(-1) {}
+ : mCommand(-1), mStatus(NO_ERROR), mWaitStatus(false) {}
void dump(char* buffer, size_t size);
int mCommand; // START_TONE, STOP_TONE ...
nsecs_t mTime; // time stamp
+ Mutex mLock; // mutex associated to mCond
Condition mCond; // condition for status return
status_t mStatus; // command status
bool mWaitStatus; // true if caller is waiting for status
- AudioCommandData *mParam; // command specific parameter data
+ sp<AudioCommandData> mParam; // command specific parameter data
};
- class AudioCommandData {
+ class AudioCommandData: public RefBase {
public:
virtual ~AudioCommandData() {}
protected:
@@ -262,9 +263,9 @@ private:
Mutex mLock;
Condition mWaitWorkCV;
- Vector <AudioCommand *> mAudioCommands; // list of pending commands
+ Vector < sp<AudioCommand> > mAudioCommands; // list of pending commands
ToneGenerator *mpToneGenerator; // the tone generator
- AudioCommand mLastCommand; // last processed command (used by dump)
+ sp<AudioCommand> mLastCommand; // last processed command (used by dump)
String8 mName; // string used by wake lock fo delayed commands
wp<AudioPolicyService> mService;
};
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp
index 5bfb969..65592d3 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.cpp
+++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp
@@ -1754,6 +1754,9 @@ status_t Parameters::updateRequest(CameraMetadata *request) const {
camera_metadata_entry_t intent =
request->find(ANDROID_CONTROL_CAPTURE_INTENT);
+
+ if (intent.count == 0) return BAD_VALUE;
+
if (intent.data.u8[0] == ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE) {
res = request->update(ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
fastInfo.bestStillCaptureFpsRange, 2);