Merge "audio policy: fix delayed command insertion"
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index e5a60f5..74438ee 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -367,7 +367,6 @@
void AudioTrack::start()
{
sp<AudioTrackThread> t = mAudioTrackThread;
- status_t status = NO_ERROR;
ALOGV("start %p", this);
@@ -395,6 +394,7 @@
}
ALOGV("start %p before lock cblk %p", this, mCblk);
+ status_t status = NO_ERROR;
if (!(cblk->flags & CBLK_INVALID_MSK)) {
cblk->lock.unlock();
ALOGV("mAudioTrack->start()");
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
index 8473fab..c2d2790 100644
--- a/services/audioflinger/Android.mk
+++ b/services/audioflinger/Android.mk
@@ -89,7 +89,7 @@
LOCAL_CFLAGS += -DSTATE_QUEUE_INSTANTIATIONS='"StateQueueInstantiations.cpp"'
-LOCAL_CFLAGS += -DHAVE_REQUEST_PRIORITY -UFAST_TRACKS_AT_NON_NATIVE_SAMPLE_RATE -USOAKER
+LOCAL_CFLAGS += -UFAST_TRACKS_AT_NON_NATIVE_SAMPLE_RATE
# uncomment for systrace
# LOCAL_CFLAGS += -DATRACE_TAG=ATRACE_TAG_AUDIO
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 65255ba..ad0a533 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -83,13 +83,7 @@
#include "PipeReader.h"
#include "SourceAudioBufferProvider.h"
-#ifdef HAVE_REQUEST_PRIORITY
#include "SchedulingPolicyService.h"
-#endif
-
-#ifdef SOAKER
-#include "Soaker.h"
-#endif
// ----------------------------------------------------------------------------
@@ -216,8 +210,9 @@
AudioFlinger::AudioFlinger()
: BnAudioFlinger(),
mPrimaryHardwareDev(NULL),
- mHardwareStatus(AUDIO_HW_IDLE), // see also onFirstRef()
+ mHardwareStatus(AUDIO_HW_IDLE),
mMasterVolume(1.0f),
+ mMasterVolumeSW(1.0f),
mMasterVolumeSupportLvl(MVS_NONE),
mMasterMute(false),
mNextUniqueId(1),
@@ -247,9 +242,6 @@
}
mMode = AUDIO_MODE_NORMAL;
- mMasterVolumeSW = 1.0;
- mMasterVolume = 1.0;
- mHardwareStatus = AUDIO_HW_IDLE;
}
AudioFlinger::~AudioFlinger()
@@ -1133,8 +1125,7 @@
mChannelCount(0),
mFrameSize(1), mFormat(AUDIO_FORMAT_INVALID),
mParamStatus(NO_ERROR),
- mStandby(false), mId(id),
- mDevice(device),
+ mStandby(false), mDevice((audio_devices_t) device), mId(id),
mDeathRecipient(new PMDeathRecipient(this))
{
}
@@ -1805,7 +1796,6 @@
}
}
-#ifdef HAVE_REQUEST_PRIORITY
if ((flags & IAudioFlinger::TRACK_FAST) && (tid != -1)) {
pid_t callingPid = IPCThreadState::self()->getCallingPid();
// we don't have CAP_SYS_NICE, nor do we want to have it as it's too powerful,
@@ -1816,7 +1806,6 @@
1, callingPid, tid, err);
}
}
-#endif
lStatus = NO_ERROR;
@@ -2196,9 +2185,6 @@
audio_io_handle_t id, uint32_t device, type_t type)
: PlaybackThread(audioFlinger, output, id, device, type),
// mAudioMixer below
-#ifdef SOAKER
- mSoaker(NULL),
-#endif
// mFastMixer below
mFastMixerFutex(0)
// mOutputSink below
@@ -2268,13 +2254,6 @@
mTeeSource = teeSource;
#endif
-#ifdef SOAKER
- // create a soaker as workaround for governor issues
- mSoaker = new Soaker();
- // FIXME Soaker should only run when needed, i.e. when FastMixer is not in COLD_IDLE
- mSoaker->run("Soaker", PRIORITY_LOWEST);
-#endif
-
// create fast mixer and configure it initially with just one fast track for our submix
mFastMixer = new FastMixer();
FastMixerStateQueue *sq = mFastMixer->sq();
@@ -2306,14 +2285,12 @@
// start the fast mixer
mFastMixer->run("FastMixer", PRIORITY_URGENT_AUDIO);
-#ifdef HAVE_REQUEST_PRIORITY
pid_t tid = mFastMixer->getTid();
int err = requestPriority(getpid_cached, tid, 2);
if (err != 0) {
ALOGW("Policy SCHED_FIFO priority %d is unavailable for pid %d tid %d; error %d",
2, getpid_cached, tid, err);
}
-#endif
#ifdef AUDIO_WATCHDOG
// create and start the watchdog
@@ -2371,12 +2348,6 @@
delete fastTrack->mBufferProvider;
sq->end(false /*didModify*/);
delete mFastMixer;
-#ifdef SOAKER
- if (mSoaker != NULL) {
- mSoaker->requestExitAndWait();
- }
- delete mSoaker;
-#endif
if (mAudioWatchdog != 0) {
mAudioWatchdog->requestExit();
mAudioWatchdog->requestExitAndWait();
@@ -2517,9 +2488,9 @@
cacheParameters_l();
sleepTime = idleSleepTime;
-if (mType == MIXER) {
- sleepTimeShift = 0;
-}
+ if (mType == MIXER) {
+ sleepTimeShift = 0;
+ }
CpuStats cpuStats;
const String8 myName(String8::format("thread %p type %d TID %d", this, mType, gettid()));
@@ -2660,15 +2631,13 @@
// is now local to this block, but will keep it for now (at least until merge done).
}
-if (mType == MIXER || mType == DIRECT) {
- // put output stream into standby mode
- if (!mStandby) {
- mOutput->stream->common.standby(&mOutput->stream->common);
+ // for DuplicatingThread, standby mode is handled by the outputTracks, otherwise ...
+ if (mType == MIXER || mType == DIRECT) {
+ // put output stream into standby mode
+ if (!mStandby) {
+ mOutput->stream->common.standby(&mOutput->stream->common);
+ }
}
-}
-if (mType == DUPLICATING) {
- // for DuplicatingThread, standby mode is handled by the outputTracks
-}
releaseWakeLock();
@@ -3474,7 +3443,7 @@
// forward device change to effects that have requested to be
// aware of attached audio device.
- mDevice = (uint32_t)value;
+ mDevice = (audio_devices_t) value;
for (size_t i = 0; i < mEffectChains.size(); i++) {
mEffectChains[i]->setDevice_l(mDevice);
}
@@ -4062,6 +4031,7 @@
return false;
}
PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+ // see note at standby() declaration
if (playbackThread->standby() && !playbackThread->isSuspended()) {
ALOGV("DuplicatingThread output track %p on thread %p Not Ready", outputTracks[i].get(), thread.get());
return false;
@@ -4488,8 +4458,6 @@
}
buffer->raw = getBuffer(s, framesReq);
- if (buffer->raw == NULL) goto getNextBuffer_exit;
-
buffer->frameCount = framesReq;
return NO_ERROR;
}
@@ -5381,8 +5349,6 @@
}
buffer->raw = getBuffer(s, framesReq);
- if (buffer->raw == NULL) goto getNextBuffer_exit;
-
buffer->frameCount = framesReq;
return NO_ERROR;
}
@@ -6500,11 +6466,12 @@
// store input device and output device but do not forward output device to audio HAL.
// Note that status is ignored by the caller for output device
// (see AudioFlinger::setParameters()
+ uint32_t /*audio_devices_t*/ newDevice = mDevice;
if (value & AUDIO_DEVICE_OUT_ALL) {
- mDevice &= (uint32_t)~(value & AUDIO_DEVICE_OUT_ALL);
+ newDevice &= (uint32_t)~(value & AUDIO_DEVICE_OUT_ALL);
status = BAD_VALUE;
} else {
- mDevice &= (uint32_t)~(value & AUDIO_DEVICE_IN_ALL);
+ newDevice &= (uint32_t)~(value & AUDIO_DEVICE_IN_ALL);
// disable AEC and NS if the device is a BT SCO headset supporting those pre processings
if (mTrack != NULL) {
bool suspend = audio_is_bluetooth_sco_device(
@@ -6513,7 +6480,8 @@
setEffectSuspended_l(FX_IID_NS, suspend, mTrack->sessionId());
}
}
- mDevice |= (uint32_t)value;
+ newDevice |= value;
+ mDevice = (audio_devices_t) newDevice; // since mDevice is read by other threads, only write to it once
}
if (status == NO_ERROR) {
status = mInput->stream->common.set_parameters(&mInput->stream->common, keyValuePair.string());
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index cd157ec..08c727d 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -417,6 +417,13 @@
int sampleRate() const; // FIXME inline after cblk sr moved
+ // Return a pointer to the start of a contiguous slice of the track buffer.
+ // Parameter 'offset' is the requested start position, expressed in
+ // monotonically increasing frame units relative to the track epoch.
+ // Parameter 'frames' is the requested length, also in frame units.
+ // Always returns non-NULL. It is the caller's responsibility to
+ // verify that this will be successful; the result of calling this
+ // function with invalid 'offset' or 'frames' is undefined.
void* getBuffer(uint32_t offset, uint32_t frames) const;
bool isStopped() const {
@@ -484,13 +491,19 @@
};
virtual status_t initCheck() const = 0;
+
+ // static externally-visible
type_t type() const { return mType; }
+ audio_io_handle_t id() const { return mId;}
+
+ // dynamic externally-visible
uint32_t sampleRate() const { return mSampleRate; }
int channelCount() const { return mChannelCount; }
audio_format_t format() const { return mFormat; }
// Called by AudioFlinger::frameCount(audio_io_handle_t output) and effects,
// and returns the normal mix buffer's frame count. No API for HAL frame count.
size_t frameCount() const { return mNormalFrameCount; }
+
void wakeUp() { mWaitWorkCV.broadcast(); }
// Should be "virtual status_t requestExitAndWait()" and override same
// method in Thread, but Thread::requestExitAndWait() is not yet virtual.
@@ -502,9 +515,11 @@
void sendConfigEvent(int event, int param = 0);
void sendConfigEvent_l(int event, int param = 0);
void processConfigEvents();
- audio_io_handle_t id() const { return mId;}
+
+ // see note at declaration of mStandby and mDevice
bool standby() const { return mStandby; }
- uint32_t device() const { return mDevice; }
+ audio_devices_t device() const { return mDevice; }
+
virtual audio_stream_t* stream() const = 0;
sp<EffectHandle> createEffect_l(
@@ -647,11 +662,19 @@
status_t mParamStatus;
Vector<ConfigEvent> mConfigEvents;
- bool mStandby;
+
+ // These fields are written and read by thread itself without lock or barrier,
+ // and read by other threads without lock or barrier via standby() and device().
+ // Because of the absence of a lock or barrier, any other thread that reads
+ // these fields must use the information in isolation, or be prepared to deal
+ // with possibility that it might be inconsistent with other information.
+ bool mStandby; // Whether thread is currently in standby.
+ audio_devices_t mDevice; // output device for PlaybackThread
+ // input + output devices for RecordThread
+
const audio_io_handle_t mId;
Vector< sp<EffectChain> > mEffectChains;
- uint32_t mDevice; // output device for PlaybackThread
- // input + output devices for RecordThread
+
static const int kNameLength = 16; // prctl(PR_SET_NAME) limit
char mName[kNameLength];
sp<IPowerManager> mPowerManager;
@@ -709,9 +732,7 @@
void flush();
void destroy();
void mute(bool);
- int name() const {
- return mName;
- }
+ int name() const { return mName; }
audio_stream_type_t streamType() const {
return mStreamType;
@@ -768,10 +789,14 @@
void triggerEvents(AudioSystem::sync_event_t type);
virtual bool isTimedTrack() const { return false; }
bool isFastTrack() const { return (mFlags & IAudioFlinger::TRACK_FAST) != 0; }
+
protected:
- // we don't really need a lock for these
- volatile bool mMute;
+ // written by Track::mute() called by binder thread(s), without a mutex or barrier.
+ // read by Track::isMuted() called by playback thread, also without a mutex or barrier.
+ // The lack of mutex or barrier is safe because the mute status is only used by itself.
+ bool mMute;
+
// FILLED state is used for suppressing volume ramp at begin of playing
enum {FS_INVALID, FS_FILLING, FS_FILLED, FS_ACTIVE};
mutable uint8_t mFillingUpStatus;
@@ -1079,6 +1104,7 @@
// mStreamTypes[] uses 1 additional stream type internally for the OutputTrack used by DuplicatingThread
stream_type_t mStreamTypes[AUDIO_STREAM_CNT + 1];
AudioStreamOut *mOutput;
+
float mMasterVolume;
nsecs_t mLastWriteTime;
int mNumWrites;
@@ -1168,9 +1194,6 @@
AudioMixer* mAudioMixer; // normal mixer
private:
-#ifdef SOAKER
- Thread* mSoaker;
-#endif
// one-time initialization, no locks required
FastMixer* mFastMixer; // non-NULL if there is also a fast mixer
sp<AudioWatchdog> mAudioWatchdog; // non-0 if there is an audio watchdog thread
@@ -1712,12 +1735,12 @@
void incTrackCnt() { android_atomic_inc(&mTrackCnt); }
void decTrackCnt() { android_atomic_dec(&mTrackCnt); }
- int32_t trackCnt() const { return mTrackCnt;}
+ int32_t trackCnt() const { return android_atomic_acquire_load(&mTrackCnt); }
void incActiveTrackCnt() { android_atomic_inc(&mActiveTrackCnt);
mTailBufferCount = mMaxTailBuffers; }
void decActiveTrackCnt() { android_atomic_dec(&mActiveTrackCnt); }
- int32_t activeTrackCnt() const { return mActiveTrackCnt;}
+ int32_t activeTrackCnt() const { return android_atomic_acquire_load(&mActiveTrackCnt); }
uint32_t strategy() const { return mStrategy; }
void setStrategy(uint32_t strategy)
@@ -1769,8 +1792,11 @@
int mSessionId; // audio session ID
int16_t *mInBuffer; // chain input buffer
int16_t *mOutBuffer; // chain output buffer
- volatile int32_t mActiveTrackCnt; // number of active tracks connected
- volatile int32_t mTrackCnt; // number of tracks connected
+
+ // 'volatile' here means these are accessed with atomic operations instead of mutex
+ volatile int32_t mActiveTrackCnt; // number of active tracks connected
+ volatile int32_t mTrackCnt; // number of tracks connected
+
int32_t mTailBufferCount; // current effect tail buffer count
int32_t mMaxTailBuffers; // maximum effect tail buffers
bool mOwnInBuffer; // true if the chain owns its input buffer
diff --git a/services/audioflinger/Soaker.h b/services/audioflinger/Soaker.h
deleted file mode 100644
index 43d9d2f..0000000
--- a/services/audioflinger/Soaker.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _ANDROID_AUDIO_SOAKER_H
-#define _ANDROID_AUDIO_SOAKER_H
-
-#include <utils/Thread.h>
-
-namespace android {
-
-class Soaker : public Thread {
-public:
- Soaker() : Thread() { }
- virtual ~Soaker() { }
-protected:
- virtual bool threadLoop() {
- int j = 0;
- for (;;) {
- for (int i = 0; i < 10000; ++i) {
- j += i * i;
- }
- if (exitPending()) {
- return false;
- }
- }
- return j < 555555;
- }
-};
-
-} // namespace android
-
-#endif // _ANDROID_AUDIO_SOAKER_H