Merge "stagefright: reuse buffers instead of cloning"
diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h
index 63076e9..f7eb397 100644
--- a/include/media/AudioRecord.h
+++ b/include/media/AudioRecord.h
@@ -180,7 +180,7 @@
audio_session_t sessionId = AUDIO_SESSION_ALLOCATE,
transfer_type transferType = TRANSFER_DEFAULT,
audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE,
- int uid = -1,
+ uid_t uid = AUDIO_UID_INVALID,
pid_t pid = -1,
const audio_attributes_t* pAttributes = NULL);
@@ -218,7 +218,7 @@
audio_session_t sessionId = AUDIO_SESSION_ALLOCATE,
transfer_type transferType = TRANSFER_DEFAULT,
audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE,
- int uid = -1,
+ uid_t uid = AUDIO_UID_INVALID,
pid_t pid = -1,
const audio_attributes_t* pAttributes = NULL);
@@ -642,7 +642,7 @@
sp<DeathNotifier> mDeathNotifier;
uint32_t mSequence; // incremented for each new IAudioRecord attempt
- int mClientUid;
+ uid_t mClientUid;
pid_t mClientPid;
audio_attributes_t mAttributes;
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index 399154c..7c5686a 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -233,7 +233,7 @@
audio_session_t sessionId = AUDIO_SESSION_ALLOCATE,
transfer_type transferType = TRANSFER_DEFAULT,
const audio_offload_info_t *offloadInfo = NULL,
- int uid = -1,
+ uid_t uid = AUDIO_UID_INVALID,
pid_t pid = -1,
const audio_attributes_t* pAttributes = NULL,
bool doNotReconnect = false,
@@ -263,7 +263,7 @@
audio_session_t sessionId = AUDIO_SESSION_ALLOCATE,
transfer_type transferType = TRANSFER_DEFAULT,
const audio_offload_info_t *offloadInfo = NULL,
- int uid = -1,
+ uid_t uid = AUDIO_UID_INVALID,
pid_t pid = -1,
const audio_attributes_t* pAttributes = NULL,
bool doNotReconnect = false,
@@ -309,7 +309,7 @@
audio_session_t sessionId = AUDIO_SESSION_ALLOCATE,
transfer_type transferType = TRANSFER_DEFAULT,
const audio_offload_info_t *offloadInfo = NULL,
- int uid = -1,
+ uid_t uid = AUDIO_UID_INVALID,
pid_t pid = -1,
const audio_attributes_t* pAttributes = NULL,
bool doNotReconnect = false,
@@ -1130,7 +1130,7 @@
sp<DeathNotifier> mDeathNotifier;
uint32_t mSequence; // incremented for each new IAudioTrack attempt
- int mClientUid;
+ uid_t mClientUid;
pid_t mClientPid;
sp<AudioSystem::AudioDeviceCallback> mDeviceCallback;
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index ff5903d..7476519 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -85,7 +85,7 @@
audio_session_t sessionId,
transfer_type transferType,
audio_input_flags_t flags,
- int uid,
+ uid_t uid,
pid_t pid,
const audio_attributes_t* pAttributes)
: mActive(false),
@@ -143,7 +143,7 @@
audio_session_t sessionId,
transfer_type transferType,
audio_input_flags_t flags,
- int uid,
+ uid_t uid,
pid_t pid,
const audio_attributes_t* pAttributes)
{
@@ -236,7 +236,7 @@
int callingpid = IPCThreadState::self()->getCallingPid();
int mypid = getpid();
- if (uid == -1 || (callingpid != mypid)) {
+ if (uid == AUDIO_UID_INVALID || (callingpid != mypid)) {
mClientUid = IPCThreadState::self()->getCallingUid();
} else {
mClientUid = uid;
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index 6a1e31e..3c7e8b7 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -204,7 +204,7 @@
audio_session_t sessionId,
transfer_type transferType,
const audio_offload_info_t *offloadInfo,
- int uid,
+ uid_t uid,
pid_t pid,
const audio_attributes_t* pAttributes,
bool doNotReconnect,
@@ -235,7 +235,7 @@
audio_session_t sessionId,
transfer_type transferType,
const audio_offload_info_t *offloadInfo,
- int uid,
+ uid_t uid,
pid_t pid,
const audio_attributes_t* pAttributes,
bool doNotReconnect,
@@ -296,7 +296,7 @@
audio_session_t sessionId,
transfer_type transferType,
const audio_offload_info_t *offloadInfo,
- int uid,
+ uid_t uid,
pid_t pid,
const audio_attributes_t* pAttributes,
bool doNotReconnect,
@@ -490,7 +490,7 @@
}
int callingpid = IPCThreadState::self()->getCallingPid();
int mypid = getpid();
- if (uid == -1 || (callingpid != mypid)) {
+ if (uid == AUDIO_UID_INVALID || (callingpid != mypid)) {
mClientUid = IPCThreadState::self()->getCallingUid();
} else {
mClientUid = uid;
diff --git a/media/libeffects/visualizer/EffectVisualizer.cpp b/media/libeffects/visualizer/EffectVisualizer.cpp
index 4c71907..1d9801f 100644
--- a/media/libeffects/visualizer/EffectVisualizer.cpp
+++ b/media/libeffects/visualizer/EffectVisualizer.cpp
@@ -59,6 +59,8 @@
#define DISCARD_MEASUREMENTS_TIME_MS 2000 // discard measurements older than this number of ms
+#define MAX_LATENCY_MS 3000 // 3 seconds of latency for audio pipeline
+
// maximum number of buffers for which we keep track of the measurements
#define MEASUREMENT_WINDOW_MAX_SIZE_IN_BUFFERS 25 // note: buffer index is stored in uint8_t
@@ -519,18 +521,29 @@
break;
}
switch (*(uint32_t *)p->data) {
- case VISUALIZER_PARAM_CAPTURE_SIZE:
- pContext->mCaptureSize = *((uint32_t *)p->data + 1);
- ALOGV("set mCaptureSize = %" PRIu32, pContext->mCaptureSize);
- break;
+ case VISUALIZER_PARAM_CAPTURE_SIZE: {
+ const uint32_t captureSize = *((uint32_t *)p->data + 1);
+ if (captureSize > VISUALIZER_CAPTURE_SIZE_MAX) {
+ android_errorWriteLog(0x534e4554, "31781965");
+ *(int32_t *)pReplyData = -EINVAL;
+ ALOGW("set mCaptureSize = %u > %u", captureSize, VISUALIZER_CAPTURE_SIZE_MAX);
+ } else {
+ pContext->mCaptureSize = captureSize;
+ ALOGV("set mCaptureSize = %u", captureSize);
+ }
+ } break;
case VISUALIZER_PARAM_SCALING_MODE:
pContext->mScalingMode = *((uint32_t *)p->data + 1);
ALOGV("set mScalingMode = %" PRIu32, pContext->mScalingMode);
break;
- case VISUALIZER_PARAM_LATENCY:
- pContext->mLatency = *((uint32_t *)p->data + 1);
- ALOGV("set mLatency = %" PRIu32, pContext->mLatency);
- break;
+ case VISUALIZER_PARAM_LATENCY: {
+ uint32_t latency = *((uint32_t *)p->data + 1);
+ if (latency > MAX_LATENCY_MS) {
+ latency = MAX_LATENCY_MS; // clamp latency b/31781965
+ }
+ pContext->mLatency = latency;
+ ALOGV("set mLatency = %u", latency);
+ } break;
case VISUALIZER_PARAM_MEASUREMENT_MODE:
pContext->mMeasurementMode = *((uint32_t *)p->data + 1);
ALOGV("set mMeasurementMode = %" PRIu32, pContext->mMeasurementMode);
@@ -569,10 +582,18 @@
if (latencyMs < 0) {
latencyMs = 0;
}
- const uint32_t deltaSmpl =
- pContext->mConfig.inputCfg.samplingRate * latencyMs / 1000;
- int32_t capturePoint = pContext->mCaptureIdx - captureSize - deltaSmpl;
+ uint32_t deltaSmpl = captureSize
+ + pContext->mConfig.inputCfg.samplingRate * latencyMs / 1000;
+ // large sample rate, latency, or capture size, could cause overflow.
+ // do not offset more than the size of buffer.
+ if (deltaSmpl > CAPTURE_BUF_SIZE) {
+ android_errorWriteLog(0x534e4554, "31781965");
+ deltaSmpl = CAPTURE_BUF_SIZE;
+ }
+
+ int32_t capturePoint = pContext->mCaptureIdx - deltaSmpl;
+ // a negative capturePoint means we wrap the buffer.
if (capturePoint < 0) {
uint32_t size = -capturePoint;
if (size > captureSize) {
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index baf7f31..3a04651 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -365,6 +365,8 @@
if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
mConfig.inputCfg.channels = AUDIO_CHANNEL_OUT_MONO;
+ mConfig.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
+ ALOGV("Overriding auxiliary effect input as MONO and output as STEREO");
} else {
mConfig.inputCfg.channels = channelMask;
// TODO: Update this logic when multichannel effects are implemented.
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index cfa3e1a..0bcb9a0 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -32,7 +32,7 @@
void *buffer,
const sp<IMemory>& sharedBuffer,
audio_session_t sessionId,
- int uid,
+ uid_t uid,
audio_output_flags_t flags,
track_type type);
virtual ~Track();
@@ -188,7 +188,7 @@
audio_format_t format,
audio_channel_mask_t channelMask,
size_t frameCount,
- int uid);
+ uid_t uid);
virtual ~OutputTrack();
virtual status_t start(AudioSystem::sync_event_t event =
diff --git a/services/audioflinger/RecordTracks.h b/services/audioflinger/RecordTracks.h
index 123e033..883ff6b 100644
--- a/services/audioflinger/RecordTracks.h
+++ b/services/audioflinger/RecordTracks.h
@@ -30,7 +30,7 @@
size_t frameCount,
void *buffer,
audio_session_t sessionId,
- int uid,
+ uid_t uid,
audio_input_flags_t flags,
track_type type);
virtual ~RecordTrack();
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 8818d8b..1d7b946 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -508,7 +508,8 @@
mAudioSource(AUDIO_SOURCE_DEFAULT), mId(id),
// mName will be set by concrete (non-virtual) subclass
mDeathRecipient(new PMDeathRecipient(this)),
- mSystemReady(systemReady)
+ mSystemReady(systemReady),
+ mNotifiedBatteryStart(false)
{
memset(&mPatch, 0, sizeof(struct audio_patch));
}
@@ -849,10 +850,10 @@
}
}
-void AudioFlinger::ThreadBase::acquireWakeLock()
+void AudioFlinger::ThreadBase::acquireWakeLock(int uid)
{
Mutex::Autolock _l(mLock);
- acquireWakeLock_l();
+ acquireWakeLock_l(uid);
}
String16 AudioFlinger::ThreadBase::getWakeLockTag()
@@ -874,23 +875,37 @@
}
}
-void AudioFlinger::ThreadBase::acquireWakeLock_l()
+void AudioFlinger::ThreadBase::acquireWakeLock_l(int uid)
{
getPowerManager_l();
if (mPowerManager != 0) {
sp<IBinder> binder = new BBinder();
- // Uses AID_AUDIOSERVER for wakelock. updateWakeLockUids_l() updates with client uids.
- status_t status = mPowerManager->acquireWakeLock(POWERMANAGER_PARTIAL_WAKE_LOCK,
+ status_t status;
+ if (uid >= 0) {
+ status = mPowerManager->acquireWakeLockWithUid(POWERMANAGER_PARTIAL_WAKE_LOCK,
+ binder,
+ getWakeLockTag(),
+ String16("audioserver"),
+ uid,
+ true /* FIXME force oneway contrary to .aidl */);
+ } else {
+ status = mPowerManager->acquireWakeLock(POWERMANAGER_PARTIAL_WAKE_LOCK,
binder,
getWakeLockTag(),
String16("audioserver"),
true /* FIXME force oneway contrary to .aidl */);
+ }
if (status == NO_ERROR) {
mWakeLockToken = binder;
}
ALOGV("acquireWakeLock_l() %s status %d", mThreadName, status);
}
+ if (!mNotifiedBatteryStart) {
+ // TODO: call this function for each track when it becomes active.
+ BatteryNotifier::getInstance().noteStartAudio(AID_AUDIOSERVER);
+ mNotifiedBatteryStart = true;
+ }
gBoottime.acquire(mWakeLockToken);
mTimestamp.mTimebaseOffset[ExtendedTimestamp::TIMEBASE_BOOTTIME] =
gBoottime.getBoottimeOffset();
@@ -913,6 +928,12 @@
}
mWakeLockToken.clear();
}
+
+ if (mNotifiedBatteryStart) {
+ // TODO: call this function for each track when it becomes inactive.
+ BatteryNotifier::getInstance().noteStopAudio(AID_AUDIOSERVER);
+ mNotifiedBatteryStart = false;
+ }
}
void AudioFlinger::ThreadBase::getPowerManager_l() {
@@ -931,15 +952,6 @@
void AudioFlinger::ThreadBase::updateWakeLockUids_l(const SortedVector<int> &uids) {
getPowerManager_l();
-
-#if !LOG_NDEBUG
- std::stringstream s;
- for (int uid : uids) {
- s << uid << " ";
- }
- ALOGD("updateWakeLockUids_l %s uids:%s", mThreadName, s.str().c_str());
-#endif
-
if (mWakeLockToken == NULL) { // token may be NULL if AudioFlinger::systemReady() not called.
if (mSystemReady) {
ALOGE("no wake lock to update, but system ready!");
@@ -949,10 +961,10 @@
return;
}
if (mPowerManager != 0) {
- sp<IBinder> binder = new BBinder();
- status_t status;
- status = mPowerManager->updateWakeLockUids(mWakeLockToken, uids.size(), uids.array(),
- true /* FIXME force oneway contrary to .aidl */);
+ std::vector<int> uidsAsInt(uids.begin(), uids.end()); // powermanager expects uids as ints
+ status_t status = mPowerManager->updateWakeLockUids(
+ mWakeLockToken, uidsAsInt.size(), uidsAsInt.data(),
+ true /* FIXME force oneway contrary to .aidl */);
ALOGV("updateWakeLockUids_l() %s status %d", mThreadName, status);
}
}
@@ -1501,41 +1513,6 @@
mPendingConfigEvents.clear();
}
-template <typename T>
-ssize_t AudioFlinger::ThreadBase::ActiveTracks<T>::add(const sp<T> &track) {
- ssize_t index = mActiveTracks.indexOf(track);
- if (index >= 0) {
- ALOGW("ActiveTracks<T>::add track %p already there", track.get());
- return index;
- }
- mActiveTracksGeneration++;
- mLatestActiveTrack = track;
- BatteryNotifier::getInstance().noteStartAudio(track->uid());
- return mActiveTracks.add(track);
-}
-
-template <typename T>
-ssize_t AudioFlinger::ThreadBase::ActiveTracks<T>::remove(const sp<T> &track) {
- ssize_t index = mActiveTracks.remove(track);
- if (index < 0) {
- ALOGW("ActiveTracks<T>::remove nonexistent track %p", track.get());
- return index;
- }
- mActiveTracksGeneration++;
- BatteryNotifier::getInstance().noteStopAudio(track->uid());
- // mLatestActiveTrack is not cleared even if is the same as track.
- return index;
-}
-
-template <typename T>
-void AudioFlinger::ThreadBase::ActiveTracks<T>::clear() {
- for (const sp<T> &track : mActiveTracks) {
- BatteryNotifier::getInstance().noteStopAudio(track->uid());
- }
- mLastActiveTracksGeneration = mActiveTracksGeneration;
- mActiveTracks.clear();
- mLatestActiveTrack.clear();
-}
// ----------------------------------------------------------------------------
// Playback
@@ -1562,6 +1539,7 @@
mSuspended(0), mBytesWritten(0),
mFramesWritten(0),
mSuspendedFrames(0),
+ mActiveTracksGeneration(0),
// mStreamTypes[] initialized in constructor body
mOutput(output),
mLastWriteTime(-1), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false),
@@ -1680,8 +1658,8 @@
result.append(buffer);
Track::appendDumpHeader(result);
for (size_t i = 0; i < numactive; ++i) {
- sp<Track> track = mActiveTracks[i];
- if (mTracks.indexOf(track) < 0) {
+ sp<Track> track = mActiveTracks[i].promote();
+ if (track != 0 && mTracks.indexOf(track) < 0) {
track->dump(buffer, SIZE, true);
result.append(buffer);
}
@@ -1753,7 +1731,7 @@
audio_session_t sessionId,
audio_output_flags_t *flags,
pid_t tid,
- int uid,
+ uid_t uid,
status_t *status)
{
size_t frameCount = *pFrameCount;
@@ -2084,6 +2062,9 @@
track->mResetDone = false;
track->mPresentationCompleteFrames = 0;
mActiveTracks.add(track);
+ mWakeLockUids.add(track->uid());
+ mActiveTracksGeneration++;
+ mLatestActiveTrack = track;
sp<EffectChain> chain = getEffectChain_l(track->sessionId());
if (chain != 0) {
ALOGV("addTrack_l() starting track on chain %p for session %d", chain.get(),
@@ -2718,7 +2699,11 @@
}
// indicate all active tracks in the chain
- for (const sp<Track> &track : mActiveTracks) {
+ for (size_t i = 0 ; i < mActiveTracks.size() ; ++i) {
+ sp<Track> track = mActiveTracks[i].promote();
+ if (track == 0) {
+ continue;
+ }
if (session == track->sessionId()) {
ALOGV("addEffectChain_l() activating track %p on session %d", track.get(), session);
chain->incActiveTrackCnt();
@@ -2765,7 +2750,11 @@
if (chain == mEffectChains[i]) {
mEffectChains.removeAt(i);
// detach all active tracks from the chain
- for (const sp<Track> &track : mActiveTracks) {
+ for (size_t i = 0 ; i < mActiveTracks.size() ; ++i) {
+ sp<Track> track = mActiveTracks[i].promote();
+ if (track == 0) {
+ continue;
+ }
if (session == track->sessionId()) {
ALOGV("removeEffectChain_l(): stopping track on chain %p for session Id: %d",
chain.get(), session);
@@ -2842,6 +2831,8 @@
// FIXME could this be made local to while loop?
writeFrames = 0;
+ int lastGeneration = 0;
+
cacheParameters_l();
mSleepTimeUs = mIdleSleepTimeUs;
@@ -2939,9 +2930,10 @@
mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_SERVER] = mLastWriteTime == -1
? systemTime() : mLastWriteTime;
}
-
- for (const sp<Track> &t : mActiveTracks) {
- if (!t->isFastTrack()) {
+ const size_t size = mActiveTracks.size();
+ for (size_t i = 0; i < size; ++i) {
+ sp<Track> t = mActiveTracks[i].promote();
+ if (t != 0 && !t->isFastTrack()) {
t->updateTrackFrameInfo(
t->mAudioTrackServerProxy->framesReleased(),
mFramesWritten,
@@ -2962,6 +2954,8 @@
if (!keepWakeLock()) {
releaseWakeLock_l();
released = true;
+ mWakeLockUids.clear();
+ mActiveTracksGeneration++;
}
ALOGV("wait async completion");
mWaitWorkCV.wait(mLock);
@@ -2995,6 +2989,8 @@
}
releaseWakeLock_l();
+ mWakeLockUids.clear();
+ mActiveTracksGeneration++;
// wait until we have something to do...
ALOGV("%s going to sleep", myName.string());
mWaitWorkCV.wait(mLock);
@@ -3019,7 +3015,12 @@
// mMixerStatusIgnoringFastTracks is also updated internally
mMixerStatus = prepareTracks_l(&tracksToRemove);
- mActiveTracks.updateWakeLockUids(this);
+ // compare with previously applied list
+ if (lastGeneration != mActiveTracksGeneration) {
+ // update wakelock
+ updateWakeLockUids_l(mWakeLockUids);
+ lastGeneration = mActiveTracksGeneration;
+ }
// prevent any changes in effect chain list and in each effect chain
// during mixing and effect process as the audio buffers could be deleted
@@ -3237,6 +3238,8 @@
}
releaseWakeLock();
+ mWakeLockUids.clear();
+ mActiveTracksGeneration++;
ALOGV("Thread %p type %d exiting", this, mType);
return false;
@@ -3250,6 +3253,8 @@
for (size_t i=0 ; i<count ; i++) {
const sp<Track>& track = tracksToRemove.itemAt(i);
mActiveTracks.remove(track);
+ mWakeLockUids.remove(track->uid());
+ mActiveTracksGeneration++;
ALOGV("removeTracks_l removing track on session %d", track->sessionId());
sp<EffectChain> chain = getEffectChain_l(track->sessionId());
if (chain != 0) {
@@ -3868,7 +3873,10 @@
mEffectBufferValid = false; // mEffectBuffer has no valid data until tracks found.
for (size_t i=0 ; i<count ; i++) {
- const sp<Track> t = mActiveTracks[i];
+ const sp<Track> t = mActiveTracks[i].promote();
+ if (t == 0) {
+ continue;
+ }
// this const just means the local variable doesn't change
Track* const track = t.get();
@@ -4364,7 +4372,11 @@
size_t i = __builtin_ctz(resetMask);
ALOG_ASSERT(i < count);
resetMask &= ~(1 << i);
- sp<Track> track = mActiveTracks[i];
+ sp<Track> t = mActiveTracks[i].promote();
+ if (t == 0) {
+ continue;
+ }
+ Track* track = t.get();
ALOG_ASSERT(track->isFastTrack() && track->isStopped());
track->reset();
}
@@ -4416,7 +4428,7 @@
{
uint32_t trackCount = 0;
for (size_t i = 0; i < mTracks.size() ; i++) {
- if (mTracks[i]->uid() == (int)uid) {
+ if (mTracks[i]->uid() == uid) {
trackCount++;
}
}
@@ -4625,7 +4637,7 @@
{
}
-void AudioFlinger::DirectOutputThread::processVolume_l(sp<Track> track, bool lastTrack)
+void AudioFlinger::DirectOutputThread::processVolume_l(Track *track, bool lastTrack)
{
float left, right;
@@ -4674,7 +4686,7 @@
void AudioFlinger::DirectOutputThread::onAddNewTrack_l()
{
sp<Track> previousTrack = mPreviousTrack.promote();
- sp<Track> latestTrack = mActiveTracks.getLatest();
+ sp<Track> latestTrack = mLatestActiveTrack.promote();
if (previousTrack != 0 && latestTrack != 0) {
if (mType == DIRECT) {
@@ -4700,13 +4712,20 @@
bool doHwResume = false;
// find out which tracks need to be processed
- for (const sp<Track> &track : mActiveTracks) {
- if (track->isInvalid()) {
- ALOGW("An invalidated track shouldn't be in active list");
- tracksToRemove->add(track);
+ for (size_t i = 0; i < count; i++) {
+ sp<Track> t = mActiveTracks[i].promote();
+ // The track died recently
+ if (t == 0) {
continue;
}
+ if (t->isInvalid()) {
+ ALOGW("An invalidated track shouldn't be in active list");
+ tracksToRemove->add(t);
+ continue;
+ }
+
+ Track* const track = t.get();
#ifdef VERY_VERY_VERBOSE_LOGGING
audio_track_cblk_t* cblk = track->cblk();
#endif
@@ -4714,7 +4733,8 @@
// In theory an older track could underrun and restart after the new one starts
// but as we only care about the transition phase between two tracks on a
// direct output, it is not a problem to ignore the underrun case.
- bool last = mActiveTracks.getLatest() == track;
+ sp<Track> l = mLatestActiveTrack.promote();
+ bool last = l.get() == track;
if (track->isPausing()) {
track->setPaused();
@@ -4786,7 +4806,7 @@
// reset retry count
track->mRetryCount = kMaxTrackRetriesDirect;
- mActiveTrack = track; // save track as mActiveTracks may change without lock.
+ mActiveTrack = t;
mixerStatus = MIXER_TRACKS_READY;
if (mHwPaused) {
doHwResume = true;
@@ -5247,7 +5267,13 @@
ALOGV("OffloadThread::prepareTracks_l active tracks %zu", count);
// find out which tracks need to be processed
- for (const sp<Track> &track : mActiveTracks) {
+ for (size_t i = 0; i < count; i++) {
+ sp<Track> t = mActiveTracks[i].promote();
+ // The track died recently
+ if (t == 0) {
+ continue;
+ }
+ Track* const track = t.get();
#ifdef VERY_VERY_VERBOSE_LOGGING
audio_track_cblk_t* cblk = track->cblk();
#endif
@@ -5255,7 +5281,8 @@
// In theory an older track could underrun and restart after the new one starts
// but as we only care about the transition phase between two tracks on a
// direct output, it is not a problem to ignore the underrun case.
- bool last = mActiveTracks.getLatest() == track;
+ sp<Track> l = mLatestActiveTrack.promote();
+ bool last = l.get() == track;
if (track->isInvalid()) {
ALOGW("An invalidated track shouldn't be in active list");
@@ -5361,7 +5388,7 @@
} else {
track->mRetryCount = kMaxTrackRetriesOffload;
}
- mActiveTrack = track; // save track as mActiveTracks may change without lock.
+ mActiveTrack = t;
mixerStatus = MIXER_TRACKS_READY;
}
} else {
@@ -5713,7 +5740,7 @@
#endif
) :
ThreadBase(audioFlinger, id, outDevice, inDevice, RECORD, systemReady),
- mInput(input), mRsmpInBuffer(NULL),
+ mInput(input), mActiveTracksGen(0), mRsmpInBuffer(NULL),
// mRsmpInFrames, mRsmpInFramesP2, and mRsmpInFramesOA are set by readInputParameters_l()
mRsmpInRear(0)
#ifdef TEE_SINK
@@ -5871,9 +5898,25 @@
reacquire_wakelock:
sp<RecordTrack> activeTrack;
+ int activeTracksGen;
{
Mutex::Autolock _l(mLock);
- acquireWakeLock_l();
+ size_t size = mActiveTracks.size();
+ activeTracksGen = mActiveTracksGen;
+ if (size > 0) {
+ // FIXME an arbitrary choice
+ activeTrack = mActiveTracks[0];
+ acquireWakeLock_l(activeTrack->uid());
+ if (size > 1) {
+ SortedVector<int> tmp;
+ for (size_t i = 0; i < size; i++) {
+ tmp.add(mActiveTracks[i]->uid());
+ }
+ updateWakeLockUids_l(tmp);
+ }
+ } else {
+ acquireWakeLock_l(-1);
+ }
}
// used to request a deferred sleep, to be executed later while mutex is unlocked
@@ -5925,6 +5968,15 @@
goto reacquire_wakelock;
}
+ if (mActiveTracksGen != activeTracksGen) {
+ activeTracksGen = mActiveTracksGen;
+ SortedVector<int> tmp;
+ for (size_t i = 0; i < size; i++) {
+ tmp.add(mActiveTracks[i]->uid());
+ }
+ updateWakeLockUids_l(tmp);
+ }
+
bool doBroadcast = false;
bool allStopped = true;
for (size_t i = 0; i < size; ) {
@@ -5937,6 +5989,7 @@
}
removeTrack_l(activeTrack);
mActiveTracks.remove(activeTrack);
+ mActiveTracksGen++;
size--;
continue;
}
@@ -5946,6 +5999,7 @@
case TrackBase::PAUSING:
mActiveTracks.remove(activeTrack);
+ mActiveTracksGen++;
doBroadcast = true;
size--;
continue;
@@ -5985,8 +6039,6 @@
}
}
- mActiveTracks.updateWakeLockUids(this);
-
if (allStopped) {
standbyIfNotAlreadyInStandby();
}
@@ -6285,6 +6337,7 @@
track->invalidate();
}
mActiveTracks.clear();
+ mActiveTracksGen++;
mStartStopCond.broadcast();
}
@@ -6351,7 +6404,7 @@
size_t *pFrameCount,
audio_session_t sessionId,
size_t *notificationFrames,
- int uid,
+ uid_t uid,
audio_input_flags_t *flags,
pid_t tid,
status_t *status)
@@ -6538,6 +6591,7 @@
// or using a separate command thread
recordTrack->mState = TrackBase::STARTING_1;
mActiveTracks.add(recordTrack);
+ mActiveTracksGen++;
status_t status = NO_ERROR;
if (recordTrack->isExternalTrack()) {
mLock.unlock();
@@ -6546,6 +6600,7 @@
// FIXME should verify that recordTrack is still in mActiveTracks
if (status != NO_ERROR) {
mActiveTracks.remove(recordTrack);
+ mActiveTracksGen++;
recordTrack->clearSyncStartEvent();
ALOGV("RecordThread::start error %d", status);
return status;
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 862dc51..5235cde 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -400,8 +400,8 @@
effect_uuid_t mType; // effect type UUID
};
- void acquireWakeLock();
- virtual void acquireWakeLock_l();
+ void acquireWakeLock(int uid = -1);
+ virtual void acquireWakeLock_l(int uid = -1);
void releaseWakeLock();
void releaseWakeLock_l();
void updateWakeLockUids_l(const SortedVector<int> &uids);
@@ -478,88 +478,8 @@
static const size_t kLogSize = 4 * 1024;
sp<NBLog::Writer> mNBLogWriter;
bool mSystemReady;
+ bool mNotifiedBatteryStart;
ExtendedTimestamp mTimestamp;
-
- // ActiveTracks is a sorted vector of track type T representing the
- // active tracks of threadLoop() to be considered by the locked prepare portion.
- // ActiveTracks should be accessed with the ThreadBase lock held.
- //
- // During processing and I/O, the threadLoop does not hold the lock;
- // hence it does not directly use ActiveTracks. Care should be taken
- // to hold local strong references or defer removal of tracks
- // if the threadLoop may still be accessing those tracks due to mix, etc.
- //
- // This class updates power information appropriately.
- //
-
- template <typename T>
- class ActiveTracks {
- public:
- ActiveTracks()
- : mActiveTracksGeneration(0)
- , mLastActiveTracksGeneration(0)
- { }
-
- ~ActiveTracks() {
- clear();
- }
- // returns the last track added (even though it may have been
- // subsequently removed from ActiveTracks).
- //
- // Used for DirectOutputThread to ensure a flush is called when transitioning
- // to a new track (even though it may be on the same session).
- // Used for OffloadThread to ensure that volume and mixer state is
- // taken from the latest track added.
- //
- // The latest track is saved with a weak pointer to prevent keeping an
- // otherwise useless track alive. Thus the function will return nullptr
- // if the latest track has subsequently been removed and destroyed.
- sp<T> getLatest() {
- return mLatestActiveTrack.promote();
- }
-
- // Updates ActiveTracks client uids to the thread wakelock.
- void updateWakeLockUids(sp<ThreadBase> thread, bool force = false) {
- if (mActiveTracksGeneration != mLastActiveTracksGeneration || force) {
- thread->updateWakeLockUids_l(getWakeLockUids());
- mLastActiveTracksGeneration = mActiveTracksGeneration;
- }
- }
-
- // SortedVector methods
- ssize_t add(const sp<T> &track);
- ssize_t remove(const sp<T> &track);
- size_t size() const {
- return mActiveTracks.size();
- }
- ssize_t indexOf(const sp<T>& item) {
- return mActiveTracks.indexOf(item);
- }
- sp<T> operator[](size_t index) const {
- return mActiveTracks[index];
- }
- typename SortedVector<sp<T>>::iterator begin() {
- return mActiveTracks.begin();
- }
- typename SortedVector<sp<T>>::iterator end() {
- return mActiveTracks.end();
- }
- void clear();
-
- private:
- SortedVector<int> getWakeLockUids() {
- SortedVector<int> wakeLockUids;
- for (const sp<T> &track : mActiveTracks) {
- wakeLockUids.add(track->uid());
- }
- return wakeLockUids; // moved by underlying SharedBuffer
- }
-
- SortedVector<sp<T>> mActiveTracks;
- int mActiveTracksGeneration;
- int mLastActiveTracksGeneration;
- wp<T> mLatestActiveTrack; // latest track added to ActiveTracks
- };
};
// --- PlaybackThread ---
@@ -638,10 +558,6 @@
virtual void preExit();
virtual bool keepWakeLock() const { return true; }
- virtual void acquireWakeLock_l() {
- ThreadBase::acquireWakeLock_l();
- mActiveTracks.updateWakeLockUids(this, true /* force */);
- }
public:
@@ -671,7 +587,7 @@
audio_session_t sessionId,
audio_output_flags_t *flags,
pid_t tid,
- int uid,
+ uid_t uid,
status_t *status /*non-NULL*/);
AudioStreamOut* getOutput() const;
@@ -814,7 +730,10 @@
bool mMasterMute;
void setMasterMute_l(bool muted) { mMasterMute = muted; }
protected:
- ActiveTracks<Track> mActiveTracks;
+ SortedVector< wp<Track> > mActiveTracks; // FIXME check if this could be sp<>
+ SortedVector<int> mWakeLockUids;
+ int mActiveTracksGeneration;
+ wp<Track> mLatestActiveTrack; // latest track added to mActiveTracks
// Allocate a track name for a given channel mask.
// Returns name >= 0 if successful, -1 on failure.
@@ -980,8 +899,8 @@
virtual uint32_t suspendSleepTimeUs() const;
virtual void cacheParameters_l();
- virtual void acquireWakeLock_l() {
- PlaybackThread::acquireWakeLock_l();
+ virtual void acquireWakeLock_l(int uid = -1) {
+ PlaybackThread::acquireWakeLock_l(uid);
if (hasFastMixer()) {
mFastMixer->setBoottimeOffset(
mTimestamp.mTimebaseOffset[ExtendedTimestamp::TIMEBASE_BOOTTIME]);
@@ -1077,7 +996,7 @@
DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
audio_io_handle_t id, uint32_t device, ThreadBase::type_t type,
bool systemReady);
- void processVolume_l(sp<Track> track, bool lastTrack);
+ void processVolume_l(Track *track, bool lastTrack);
// prepareTracks_l() tells threadLoop_mix() the name of the single active track
sp<Track> mActiveTrack;
@@ -1366,7 +1285,7 @@
size_t *pFrameCount,
audio_session_t sessionId,
size_t *notificationFrames,
- int uid,
+ uid_t uid,
audio_input_flags_t *flags,
pid_t tid,
status_t *status /*non-NULL*/);
@@ -1420,11 +1339,6 @@
virtual status_t checkEffectCompatibility_l(const effect_descriptor_t *desc,
audio_session_t sessionId);
- virtual void acquireWakeLock_l() {
- ThreadBase::acquireWakeLock_l();
- mActiveTracks.updateWakeLockUids(this, true /* force */);
- }
-
private:
// Enter standby if not already in standby, and set mStandby flag
void standbyIfNotAlreadyInStandby();
@@ -1436,8 +1350,9 @@
SortedVector < sp<RecordTrack> > mTracks;
// mActiveTracks has dual roles: it indicates the current active track(s), and
// is used together with mStartStopCond to indicate start()/stop() progress
- ActiveTracks<RecordTrack> mActiveTracks;
-
+ SortedVector< sp<RecordTrack> > mActiveTracks;
+ // generation counter for mActiveTracks
+ int mActiveTracksGen;
Condition mStartStopCond;
// resampler converts input at HAL Hz to output at AudioRecord client Hz
diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h
index 7c48375..4fcb596 100644
--- a/services/audioflinger/TrackBase.h
+++ b/services/audioflinger/TrackBase.h
@@ -62,7 +62,7 @@
size_t frameCount,
void *buffer,
audio_session_t sessionId,
- int uid,
+ uid_t uid,
bool isOut,
alloc_type alloc = ALLOC_CBLK,
track_type type = TYPE_DEFAULT);
@@ -75,7 +75,7 @@
sp<IMemory> getCblk() const { return mCblkMemory; }
audio_track_cblk_t* cblk() const { return mCblk; }
audio_session_t sessionId() const { return mSessionId; }
- int uid() const { return mUid; }
+ uid_t uid() const { return mUid; }
virtual status_t setSyncEvent(const sp<SyncEvent>& event);
sp<IMemory> getBuffers() const { return mBufferMemory; }
@@ -153,7 +153,7 @@
// openRecord(), and then adjusted as needed
const audio_session_t mSessionId;
- int mUid;
+ uid_t mUid;
Vector < sp<SyncEvent> >mSyncEvents;
const bool mIsOut;
sp<ServerProxy> mServerProxy;
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index e1fe7e2..8f134c1 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -72,7 +72,7 @@
size_t frameCount,
void *buffer,
audio_session_t sessionId,
- int clientUid,
+ uid_t clientUid,
bool isOut,
alloc_type alloc,
track_type type)
@@ -99,10 +99,10 @@
mThreadIoHandle(thread->id())
{
const uid_t callingUid = IPCThreadState::self()->getCallingUid();
- if (!isTrustedCallingUid(callingUid) || clientUid == -1) {
- ALOGW_IF(clientUid != -1 && clientUid != (int)callingUid,
+ if (!isTrustedCallingUid(callingUid) || clientUid == AUDIO_UID_INVALID) {
+ ALOGW_IF(clientUid != AUDIO_UID_INVALID && clientUid != callingUid,
"%s uid %d tried to pass itself off as %d", __FUNCTION__, callingUid, clientUid);
- clientUid = (int)callingUid;
+ clientUid = callingUid;
}
// clientUid contains the uid of the app that is responsible for this track, so we can blame
// battery usage on it.
@@ -341,7 +341,7 @@
void *buffer,
const sp<IMemory>& sharedBuffer,
audio_session_t sessionId,
- int uid,
+ uid_t uid,
audio_output_flags_t flags,
track_type type)
: TrackBase(thread, client, sampleRate, format, channelMask, frameCount,
@@ -1138,7 +1138,7 @@
audio_format_t format,
audio_channel_mask_t channelMask,
size_t frameCount,
- int uid)
+ uid_t uid)
: Track(playbackThread, NULL, AUDIO_STREAM_PATCH,
sampleRate, format, channelMask, frameCount,
NULL, 0, AUDIO_SESSION_NONE, uid, AUDIO_OUTPUT_FLAG_NONE,
@@ -1474,7 +1474,7 @@
size_t frameCount,
void *buffer,
audio_session_t sessionId,
- int uid,
+ uid_t uid,
audio_input_flags_t flags,
track_type type)
: TrackBase(thread, client, sampleRate, format,