From c03ecbc8925452ded7b740630b8a8ed6eeec7c64 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Thu, 10 Jan 2013 12:31:01 -0800 Subject: Update tee sink Implement rotation to reduce long-term storage use. Implement optional per-track tee. Dynamically enable at runtime based on property, instead of at compile-time. Dynamic frame count not yet implemented. Bug: 8223560 Change-Id: I3706443c6ec0cb0c6656dc288715a02ad5fea63a --- services/audioflinger/Android.mk | 8 --- services/audioflinger/AudioFlinger.cpp | 111 ++++++++++++++++++++++++++++++--- services/audioflinger/AudioFlinger.h | 17 +++++ services/audioflinger/Threads.cpp | 26 ++++---- services/audioflinger/TrackBase.h | 3 + services/audioflinger/Tracks.cpp | 31 ++++++++- 6 files changed, 164 insertions(+), 32 deletions(-) diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk index 6d42143..0855db6 100644 --- a/services/audioflinger/Android.mk +++ b/services/audioflinger/Android.mk @@ -66,14 +66,6 @@ LOCAL_CFLAGS += -DSTATE_QUEUE_INSTANTIATIONS='"StateQueueInstantiations.cpp"' LOCAL_CFLAGS += -UFAST_TRACKS_AT_NON_NATIVE_SAMPLE_RATE -# uncomment for dumpsys to write most recent audio output to .wav file -# 47.5 seconds at 44.1 kHz, 8 megabytes -# LOCAL_CFLAGS += -DTEE_SINK_FRAMES=0x200000 - -# uncomment for dumpsys to write most recent audio input to .wav file -# 47.5 seconds at 44.1 kHz, 8 megabytes -# LOCAL_CFLAGS += -DTEE_SINK_INPUT_FRAMES=0x200000 - # uncomment to enable the audio watchdog # LOCAL_SRC_FILES += AudioWatchdog.cpp # LOCAL_CFLAGS += -DAUDIO_WATCHDOG diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index 47c2772..e0ab8cd 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -19,6 +19,7 @@ #define LOG_TAG "AudioFlinger" //#define LOG_NDEBUG 0 +#include #include #include #include @@ -61,6 +62,9 @@ #include +#include +#include + // ---------------------------------------------------------------------------- // Note: the following macro is used for extremely verbose logging message. In @@ -86,6 +90,14 @@ nsecs_t AudioFlinger::mStandbyTimeInNsecs = kDefaultStandbyTimeInNsecs; uint32_t AudioFlinger::mScreenState; +bool AudioFlinger::mTeeSinkInputEnabled = false; +bool AudioFlinger::mTeeSinkOutputEnabled = false; +bool AudioFlinger::mTeeSinkTrackEnabled = false; + +size_t AudioFlinger::mTeeSinkInputFrames = kTeeSinkInputFramesDefault; +size_t AudioFlinger::mTeeSinkOutputFrames = kTeeSinkOutputFramesDefault; +size_t AudioFlinger::mTeeSinkTrackFrames = kTeeSinkTrackFramesDefault; + // ---------------------------------------------------------------------------- static int load_audio_interface(const char *if_name, audio_hw_device_t **dev) @@ -134,6 +146,19 @@ AudioFlinger::AudioFlinger() if (doLog) { mLogMemoryDealer = new MemoryDealer(kLogMemorySize, "LogWriters"); } + (void) property_get("ro.debuggable", value, "0"); + int debuggable = atoi(value); + int teeEnabled = 0; + if (debuggable) { + (void) property_get("af.tee", value, "0"); + teeEnabled = atoi(value); + } + if (teeEnabled & 1) + mTeeSinkInputEnabled = true; + if (teeEnabled & 2) + mTeeSinkOutputEnabled = true; + if (teeEnabled & 4) + mTeeSinkTrackEnabled = true; } void AudioFlinger::onFirstRef() @@ -1602,7 +1627,6 @@ audio_io_handle_t AudioFlinger::openInput(audio_module_handle_t module, // Try to re-use most recently used Pipe to archive a copy of input for dumpsys, // or (re-)create if current Pipe is idle and does not match the new format sp teeSink; -#ifdef TEE_SINK_INPUT_FRAMES enum { TEE_SINK_NO, // don't copy input TEE_SINK_NEW, // copy input using a new pipe @@ -1610,7 +1634,9 @@ audio_io_handle_t AudioFlinger::openInput(audio_module_handle_t module, } kind; NBAIO_Format format = Format_from_SR_C(inStream->common.get_sample_rate(&inStream->common), popcount(inStream->common.get_channels(&inStream->common))); - if (format == Format_Invalid) { + if (!mTeeSinkInputEnabled) { + kind = TEE_SINK_NO; + } else if (format == Format_Invalid) { kind = TEE_SINK_NO; } else if (mRecordTeeSink == 0) { kind = TEE_SINK_NEW; @@ -1623,7 +1649,7 @@ audio_io_handle_t AudioFlinger::openInput(audio_module_handle_t module, } switch (kind) { case TEE_SINK_NEW: { - Pipe *pipe = new Pipe(TEE_SINK_INPUT_FRAMES, format); + Pipe *pipe = new Pipe(mTeeSinkInputFrames, format); size_t numCounterOffers = 0; const NBAIO_Format offers[1] = {format}; ssize_t index = pipe->negotiate(offers, 1, NULL, numCounterOffers); @@ -1644,7 +1670,7 @@ audio_io_handle_t AudioFlinger::openInput(audio_module_handle_t module, default: break; } -#endif + AudioStreamIn *input = new AudioStreamIn(inHwDev, inStream); // Start record thread @@ -2199,19 +2225,80 @@ status_t AudioFlinger::moveEffectChain_l(int sessionId, return NO_ERROR; } +struct Entry { +#define MAX_NAME 32 // %Y%m%d%H%M%S_%d.wav + char mName[MAX_NAME]; +}; + +int comparEntry(const void *p1, const void *p2) +{ + return strcmp(((const Entry *) p1)->mName, ((const Entry *) p2)->mName); +} + void AudioFlinger::dumpTee(int fd, const sp& source, audio_io_handle_t id) { NBAIO_Source *teeSource = source.get(); if (teeSource != NULL) { + // .wav rotation + // There is a benign race condition if 2 threads call this simultaneously. + // They would both traverse the directory, but the result would simply be + // failures at unlink() which are ignored. It's also unlikely since + // normally dumpsys is only done by bugreport or from the command line. + char teePath[32+256]; + strcpy(teePath, "/data/misc/media"); + size_t teePathLen = strlen(teePath); + DIR *dir = opendir(teePath); + teePath[teePathLen++] = '/'; + if (dir != NULL) { +#define MAX_SORT 20 // number of entries to sort +#define MAX_KEEP 10 // number of entries to keep + struct Entry entries[MAX_SORT]; + size_t entryCount = 0; + while (entryCount < MAX_SORT) { + struct dirent de; + struct dirent *result = NULL; + int rc = readdir_r(dir, &de, &result); + if (rc != 0) { + ALOGW("readdir_r failed %d", rc); + break; + } + if (result == NULL) { + break; + } + if (result != &de) { + ALOGW("readdir_r returned unexpected result %p != %p", result, &de); + break; + } + // ignore non .wav file entries + size_t nameLen = strlen(de.d_name); + if (nameLen <= 4 || nameLen >= MAX_NAME || + strcmp(&de.d_name[nameLen - 4], ".wav")) { + continue; + } + strcpy(entries[entryCount++].mName, de.d_name); + } + (void) closedir(dir); + if (entryCount > MAX_KEEP) { + qsort(entries, entryCount, sizeof(Entry), comparEntry); + for (size_t i = 0; i < entryCount - MAX_KEEP; ++i) { + strcpy(&teePath[teePathLen], entries[i].mName); + (void) unlink(teePath); + } + } + } else { + if (fd >= 0) { + fdprintf(fd, "unable to rotate tees in %s: %s\n", teePath, strerror(errno)); + } + } char teeTime[16]; struct timeval tv; gettimeofday(&tv, NULL); struct tm tm; localtime_r(&tv.tv_sec, &tm); - strftime(teeTime, sizeof(teeTime), "%T", &tm); - char teePath[64]; - sprintf(teePath, "/data/misc/media/%s_%d.wav", teeTime, id); - int teeFd = open(teePath, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); + strftime(teeTime, sizeof(teeTime), "%Y%m%d%H%M%S", &tm); + snprintf(&teePath[teePathLen], sizeof(teePath) - teePathLen, "%s_%d.wav", teeTime, id); + // if 2 dumpsys are done within 1 second, and rotation didn't work, then discard 2nd + int teeFd = open(teePath, O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW, S_IRUSR | S_IWUSR); if (teeFd >= 0) { char wavHeader[44]; memcpy(wavHeader, @@ -2253,9 +2340,13 @@ void AudioFlinger::dumpTee(int fd, const sp& source, audio_io_hand temp = total * channelCount * sizeof(short); write(teeFd, &temp, sizeof(temp)); close(teeFd); - fdprintf(fd, "FastMixer tee copied to %s\n", teePath); + if (fd >= 0) { + fdprintf(fd, "tee copied to %s\n", teePath); + } } else { - fdprintf(fd, "FastMixer unable to create tee %s: \n", strerror(errno)); + if (fd >= 0) { + fdprintf(fd, "unable to create tee %s: %s\n", teePath, strerror(errno)); + } } } } diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h index c3f08f6..44bd260 100644 --- a/services/audioflinger/AudioFlinger.h +++ b/services/audioflinger/AudioFlinger.h @@ -593,7 +593,24 @@ private: sp mRecordTeeSource; public: + // tee sink, if enabled by property, allows dumpsys to write most recent audio to .wav file static void dumpTee(int fd, const sp& source, audio_io_handle_t id = 0); + + // whether tee sink is enabled by property + static bool mTeeSinkInputEnabled; + static bool mTeeSinkOutputEnabled; + static bool mTeeSinkTrackEnabled; + + // runtime configured size of each tee sink pipe, in frames + static size_t mTeeSinkInputFrames; + static size_t mTeeSinkOutputFrames; + static size_t mTeeSinkTrackFrames; + + // compile-time default size of tee sink pipes, in frames + // 0x200000 stereo 16-bit PCM frames = 47.5 seconds at 44.1 kHz, 8 megabytes + static const size_t kTeeSinkInputFramesDefault = 0x200000; + static const size_t kTeeSinkOutputFramesDefault = 0x200000; + static const size_t kTeeSinkTrackFramesDefault = 0x1000; }; #undef INCLUDING_FROM_AUDIOFLINGER_H diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index ba848d7..1209ea6 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -2124,19 +2124,19 @@ AudioFlinger::MixerThread::MixerThread(const sp& audioFlinger, Aud (monoPipe->maxFrames() * 7) / 8 : mNormalFrameCount * 2); mPipeSink = monoPipe; -#ifdef TEE_SINK_FRAMES - // create a Pipe to archive a copy of FastMixer's output for dumpsys - Pipe *teeSink = new Pipe(TEE_SINK_FRAMES, format); - numCounterOffers = 0; - index = teeSink->negotiate(offers, 1, NULL, numCounterOffers); - ALOG_ASSERT(index == 0); - mTeeSink = teeSink; - PipeReader *teeSource = new PipeReader(*teeSink); - numCounterOffers = 0; - index = teeSource->negotiate(offers, 1, NULL, numCounterOffers); - ALOG_ASSERT(index == 0); - mTeeSource = teeSource; -#endif + if (mTeeSinkOutputEnabled) { + // create a Pipe to archive a copy of FastMixer's output for dumpsys + Pipe *teeSink = new Pipe(mTeeSinkOutputFrames, format); + numCounterOffers = 0; + index = teeSink->negotiate(offers, 1, NULL, numCounterOffers); + ALOG_ASSERT(index == 0); + mTeeSink = teeSink; + PipeReader *teeSource = new PipeReader(*teeSink); + numCounterOffers = 0; + index = teeSource->negotiate(offers, 1, NULL, numCounterOffers); + ALOG_ASSERT(index == 0); + mTeeSource = teeSource; + } // create fast mixer and configure it initially with just one fast track for our submix mFastMixer = new FastMixer(); diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h index e0bd97a..fecbfda 100644 --- a/services/audioflinger/TrackBase.h +++ b/services/audioflinger/TrackBase.h @@ -141,4 +141,7 @@ protected: Vector < sp >mSyncEvents; const bool mIsOut; ServerProxy* mServerProxy; + const int mId; + sp mTeeSink; + sp mTeeSource; }; diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp index 315cbbc..724ce38 100644 --- a/services/audioflinger/Tracks.cpp +++ b/services/audioflinger/Tracks.cpp @@ -32,6 +32,9 @@ #include "AudioFlinger.h" #include "ServiceUtilities.h" +#include +#include + // ---------------------------------------------------------------------------- // Note: the following macro is used for extremely verbose logging message. In @@ -53,6 +56,8 @@ namespace android { // TrackBase // ---------------------------------------------------------------------------- +static volatile int32_t nextTrackId = 55; + // TrackBase constructor must be called with AudioFlinger::mLock held AudioFlinger::ThreadBase::TrackBase::TrackBase( ThreadBase *thread, @@ -82,7 +87,8 @@ AudioFlinger::ThreadBase::TrackBase::TrackBase( mStepServerFailed(false), mSessionId(sessionId), mIsOut(isOut), - mServerProxy(NULL) + mServerProxy(NULL), + mId(android_atomic_inc(&nextTrackId)) { // client == 0 implies sharedBuffer == 0 ALOG_ASSERT(!(client == 0 && sharedBuffer != 0)); @@ -134,11 +140,30 @@ AudioFlinger::ThreadBase::TrackBase::TrackBase( } mBufferEnd = (uint8_t *)mBuffer + bufferSize; mServerProxy = new ServerProxy(mCblk, mBuffer, frameCount, mFrameSize, isOut); + + if (mTeeSinkTrackEnabled) { + NBAIO_Format pipeFormat = Format_from_SR_C(mSampleRate, mChannelCount); + if (pipeFormat != Format_Invalid) { + Pipe *pipe = new Pipe(mTeeSinkTrackFrames, pipeFormat); + size_t numCounterOffers = 0; + const NBAIO_Format offers[1] = {pipeFormat}; + ssize_t index = pipe->negotiate(offers, 1, NULL, numCounterOffers); + ALOG_ASSERT(index == 0); + PipeReader *pipeReader = new PipeReader(*pipe); + numCounterOffers = 0; + index = pipeReader->negotiate(offers, 1, NULL, numCounterOffers); + ALOG_ASSERT(index == 0); + mTeeSink = pipe; + mTeeSource = pipeReader; + } + } + } } AudioFlinger::ThreadBase::TrackBase::~TrackBase() { + dumpTee(-1, mTeeSource, mId); // delete the proxy before deleting the shared memory it refers to, to avoid dangling reference delete mServerProxy; if (mCblk != NULL) { @@ -164,6 +189,10 @@ AudioFlinger::ThreadBase::TrackBase::~TrackBase() // This implementation of releaseBuffer() is used by Track and RecordTrack, but not TimedTrack void AudioFlinger::ThreadBase::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer) { + if (mTeeSink != 0) { + (void) mTeeSink->write(buffer->raw, buffer->frameCount); + } + buffer->raw = NULL; mStepCount = buffer->frameCount; // FIXME See note at getNextBuffer() -- cgit v1.1 From 6f5c40a5c69498b437983e00650d3a453134eb1a Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Thu, 18 Apr 2013 15:26:47 -0700 Subject: Fix error message to match CTS Bug: 8657725 Change-Id: Ib608eb55f14d557d667f93e4f646c03d5ea470c1 --- services/medialog/MediaLogService.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/services/medialog/MediaLogService.cpp b/services/medialog/MediaLogService.cpp index f60749d..683fdf3 100644 --- a/services/medialog/MediaLogService.cpp +++ b/services/medialog/MediaLogService.cpp @@ -60,7 +60,9 @@ status_t MediaLogService::dump(int fd, const Vector& args) static const String16 sDump("android.permission.DUMP"); if (!(IPCThreadState::self()->getCallingUid() == AID_MEDIA || PermissionCache::checkCallingPermission(sDump))) { - fdprintf(fd, "Permission denied.\n"); + fdprintf(fd, "Permission Denial: can't dump media.log from pid=%d, uid=%d\n", + IPCThreadState::self()->getCallingPid(), + IPCThreadState::self()->getCallingUid()); return NO_ERROR; } -- cgit v1.1 From d57be914c50aadcc1fa0663234e934e42755de8d Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Wed, 1 May 2013 16:15:49 -0700 Subject: Fix reverb at 48kHz The LVM reverb wrapper had a test to only accept input sampling rate of 44.1 kHz. As the LVM reberb engine supports multiple sampling rate we can remove this test. The fix for issue 8512027 (commit 2a9c5cd4) caused a regression because the framework now checks the return code of the effect configure command and ignores subsequent commands in case of error. Bug: 8630044 Change-Id: I3146871f1ad8f7945a2e63ea763dd7b87368337d --- media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp index 87e2c85..8a96212 100644 --- a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp +++ b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp @@ -616,10 +616,6 @@ int Reverb_setConfig(ReverbContext *pContext, effect_config_t *pConfig){ || pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE); CHECK_ARG(pConfig->inputCfg.format == AUDIO_FORMAT_PCM_16_BIT); - if(pConfig->inputCfg.samplingRate != 44100){ - return -EINVAL; - } - //ALOGV("\tReverb_setConfig calling memcpy"); pContext->config = *pConfig; @@ -648,7 +644,7 @@ int Reverb_setConfig(ReverbContext *pContext, effect_config_t *pConfig){ return -EINVAL; } - if(pContext->SampleRate != SampleRate){ + if (pContext->SampleRate != SampleRate) { LVREV_ControlParams_st ActiveParams; LVREV_ReturnStatus_en LvmStatus = LVREV_SUCCESS; @@ -662,11 +658,14 @@ int Reverb_setConfig(ReverbContext *pContext, effect_config_t *pConfig){ LVM_ERROR_CHECK(LvmStatus, "LVREV_GetControlParameters", "Reverb_setConfig") if(LvmStatus != LVREV_SUCCESS) return -EINVAL; + ActiveParams.SampleRate = SampleRate; + LvmStatus = LVREV_SetControlParameters(pContext->hInstance, &ActiveParams); LVM_ERROR_CHECK(LvmStatus, "LVREV_SetControlParameters", "Reverb_setConfig") + if(LvmStatus != LVREV_SUCCESS) return -EINVAL; //ALOGV("\tReverb_setConfig Succesfully called LVREV_SetControlParameters\n"); - + pContext->SampleRate = SampleRate; }else{ //ALOGV("\tReverb_setConfig keep sampling rate at %d", SampleRate); } @@ -818,6 +817,7 @@ int Reverb_init(ReverbContext *pContext){ /* General parameters */ params.OperatingMode = LVM_MODE_ON; params.SampleRate = LVM_FS_44100; + pContext->SampleRate = LVM_FS_44100; if(pContext->config.inputCfg.channels == AUDIO_CHANNEL_OUT_MONO){ params.SourceFormat = LVM_MONO; -- cgit v1.1 From 1a90a780fb33cfc44fdc404a982b210d6fb81bcb Mon Sep 17 00:00:00 2001 From: Eino-Ville Talvala Date: Thu, 9 May 2013 17:03:54 -0700 Subject: Camera3: Fix initial orientation configuration. One call to set orientation too many. Bug: 8683719 Change-Id: I4b776fc8665eed940a1f18a6f617be4f1406e41a --- services/camera/libcameraservice/camera3/Camera3OutputStream.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/services/camera/libcameraservice/camera3/Camera3OutputStream.cpp b/services/camera/libcameraservice/camera3/Camera3OutputStream.cpp index ec8cf0d..ddb1d6d 100644 --- a/services/camera/libcameraservice/camera3/Camera3OutputStream.cpp +++ b/services/camera/libcameraservice/camera3/Camera3OutputStream.cpp @@ -335,11 +335,6 @@ status_t Camera3OutputStream::configureQueueLocked() { return res; } - res = setTransformLocked(0); - if (res != OK) { - return res; - } - if (mMaxSize == 0) { // For buffers of known size res = native_window_set_buffers_geometry(mConsumer.get(), -- cgit v1.1 From 5bbca4625679e312ff540d9807ea1d1b2149c13a Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Mon, 20 May 2013 09:13:23 -0700 Subject: Avoid a deadlock during EmptyBufferDone The deadlock happens withen in the case where we use an OMX encoder with a GraphicBufferSource. Bug: 8329090 Change-Id: Icec58bb85ff3839ad1a2e3eca02fa9d6d133ca45 --- media/libstagefright/omx/OMXNodeInstance.cpp | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp index e7d5e74..a9eb94f 100644 --- a/media/libstagefright/omx/OMXNodeInstance.cpp +++ b/media/libstagefright/omx/OMXNodeInstance.cpp @@ -779,6 +779,23 @@ void OMXNodeInstance::onMessage(const omx_message &msg) { static_cast(buffer->pAppPrivate); buffer_meta->CopyFromOMX(buffer); + } else if (msg.type == omx_message::EMPTY_BUFFER_DONE) { + const sp& bufferSource(getGraphicBufferSource()); + + if (bufferSource != NULL) { + // This is one of the buffers used exclusively by + // GraphicBufferSource. + // Don't dispatch a message back to ACodec, since it doesn't + // know that anyone asked to have the buffer emptied and will + // be very confused. + + OMX_BUFFERHEADERTYPE *buffer = + static_cast( + msg.u.buffer_data.buffer); + + bufferSource->codecBufferEmptied(buffer); + return; + } } mObserver->onMessage(msg); @@ -839,17 +856,6 @@ OMX_ERRORTYPE OMXNodeInstance::OnEmptyBufferDone( if (instance->mDying) { return OMX_ErrorNone; } - const sp& bufferSource( - instance->getGraphicBufferSource()); - if (bufferSource != NULL) { - bufferSource->codecBufferEmptied(pBuffer); - - // This is one of the buffers used exclusively by GraphicBufferSource. - // Don't dispatch a message back to ACodec, since it doesn't - // know that anyone asked to have the buffer emptied and will - // be very confused. - return OMX_ErrorNone; - } return instance->owner()->OnEmptyBufferDone(instance->nodeID(), pBuffer); } -- cgit v1.1 From b662e330c84fbd49ab41d31bbf857a6dd97723ee Mon Sep 17 00:00:00 2001 From: Igor Murashkin Date: Wed, 22 May 2013 15:54:57 -0700 Subject: camera3: Fix zsl buffers released-while-in-use race condition Bug: 9007356 Change-Id: I0ced31020410978c549d408b2815f925e9c9ffcf --- .../libcameraservice/camera2/ZslProcessor3.cpp | 2 ++ .../libcameraservice/gui/RingBufferConsumer.cpp | 30 +++++++++++++--------- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/services/camera/libcameraservice/camera2/ZslProcessor3.cpp b/services/camera/libcameraservice/camera2/ZslProcessor3.cpp index e2c120c..56525a3 100644 --- a/services/camera/libcameraservice/camera2/ZslProcessor3.cpp +++ b/services/camera/libcameraservice/camera2/ZslProcessor3.cpp @@ -402,6 +402,8 @@ nsecs_t ZslProcessor3::getCandidateTimestampLocked(size_t* metadataIdx) const { minTimestamp = frameTimestamp; idx = j; } + + ALOGVV("%s: Saw timestamp %lld", __FUNCTION__, frameTimestamp); } } diff --git a/services/camera/libcameraservice/gui/RingBufferConsumer.cpp b/services/camera/libcameraservice/gui/RingBufferConsumer.cpp index 2fa78a4..cd39bad 100644 --- a/services/camera/libcameraservice/gui/RingBufferConsumer.cpp +++ b/services/camera/libcameraservice/gui/RingBufferConsumer.cpp @@ -101,12 +101,6 @@ sp RingBufferConsumer::pinSelectedBuffer( } // end scope of mMutex autolock - if (pinnedBuffer != 0) { - BI_LOGV("Pinned buffer frame %lld, timestamp %lld", - pinnedBuffer->getBufferItem().mFrameNumber, - pinnedBuffer->getBufferItem().mTimestamp); - } - if (waitForFence) { status_t err = pinnedBuffer->getBufferItem().mFence->waitForever( "RingBufferConsumer::pinSelectedBuffer"); @@ -172,6 +166,9 @@ void RingBufferConsumer::pinBufferLocked(const BufferItem& item) { if (it == end) { BI_LOGE("Failed to pin buffer (timestamp %lld, framenumber %lld)", item.mTimestamp, item.mFrameNumber); + } else { + BI_LOGV("Pinned buffer (frame %lld, timestamp %lld)", + item.mFrameNumber, item.mTimestamp); } } @@ -182,7 +179,7 @@ status_t RingBufferConsumer::releaseOldestBufferLocked(size_t* pinnedFrames) { it = mBufferItemList.begin(); end = mBufferItemList.end(); - accIt = it; + accIt = end; if (it == end) { /** @@ -197,12 +194,17 @@ status_t RingBufferConsumer::releaseOldestBufferLocked(size_t* pinnedFrames) { for (; it != end; ++it) { RingBufferItem& find = *it; - if (find.mTimestamp < accIt->mTimestamp && find.mPinCount <= 0) { - accIt = it; + + if (find.mPinCount > 0) { + if (pinnedFrames != NULL) { + ++(*pinnedFrames); + } + // Filter out pinned frame when searching for buffer to release + continue; } - if (find.mPinCount > 0 && pinnedFrames != NULL) { - ++(*pinnedFrames); + if (find.mTimestamp < accIt->mTimestamp || accIt == end) { + accIt = it; } } @@ -323,7 +325,11 @@ void RingBufferConsumer::unpinBuffer(const BufferItem& item) { } if (it == end) { - BI_LOGE("Failed to unpin buffer (timestamp %lld, framenumber %lld", + // This should never happen. If it happens, we have a bug. + BI_LOGE("Failed to unpin buffer (timestamp %lld, framenumber %lld)", + item.mTimestamp, item.mFrameNumber); + } else { + BI_LOGV("Unpinned buffer (timestamp %lld, framenumber %lld)", item.mTimestamp, item.mFrameNumber); } } -- cgit v1.1 From f8f370b6ecb0227aa6f2b1c41d045eeaf613f726 Mon Sep 17 00:00:00 2001 From: Igor Murashkin Date: Thu, 23 May 2013 16:51:44 -0700 Subject: camera3: Disable ZSL for limited mode camera HALs Bug: 9111852 Change-Id: Idad7e0d2f912341bd643d0ad1a0861fb2043aa90 --- .../camera/libcameraservice/camera2/Parameters.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/services/camera/libcameraservice/camera2/Parameters.cpp b/services/camera/libcameraservice/camera2/Parameters.cpp index 49fc3d8..a248b76 100644 --- a/services/camera/libcameraservice/camera2/Parameters.cpp +++ b/services/camera/libcameraservice/camera2/Parameters.cpp @@ -795,13 +795,21 @@ status_t Parameters::initialize(const CameraMetadata *info) { previewCallbackFlags = 0; previewCallbackOneShot = false; - char value[PROPERTY_VALUE_MAX]; - property_get("camera.disable_zsl_mode", value, "0"); - if (!strcmp(value,"1")) { - ALOGI("Camera %d: Disabling ZSL mode", cameraId); + camera_metadata_ro_entry_t supportedHardwareLevel = + staticInfo(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL); + if (!supportedHardwareLevel.count || (supportedHardwareLevel.data.u8[0] == + ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED)) { + ALOGI("Camera %d: ZSL mode disabled for limited mode HALs", cameraId); zslMode = false; } else { - zslMode = true; + char value[PROPERTY_VALUE_MAX]; + property_get("camera.disable_zsl_mode", value, "0"); + if (!strcmp(value,"1")) { + ALOGI("Camera %d: Disabling ZSL mode", cameraId); + zslMode = false; + } else { + zslMode = true; + } } lightFx = LIGHTFX_NONE; -- cgit v1.1 From b4a0680452c4049b6342ebbee5f33db232f9370a Mon Sep 17 00:00:00 2001 From: Zhijun He Date: Wed, 22 May 2013 14:01:30 -0700 Subject: Camera3: Fix the deadlock during recording pinch zooming When zooming during recording, hal callback thread and request update thread run into deadlock due to lock circular dependency. This change release lock during queuebuffer in callback thread to break the dependency. Bug: 9091576 Change-Id: Ia7b3f0ec17573cb32a5696dcde419ca28f42cfb8 --- .../libcameraservice/camera3/Camera3OutputStream.cpp | 15 ++++++++++++--- .../camera/libcameraservice/camera3/Camera3OutputStream.h | 3 +++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/services/camera/libcameraservice/camera3/Camera3OutputStream.cpp b/services/camera/libcameraservice/camera3/Camera3OutputStream.cpp index a2c97d4..2efeede 100644 --- a/services/camera/libcameraservice/camera3/Camera3OutputStream.cpp +++ b/services/camera/libcameraservice/camera3/Camera3OutputStream.cpp @@ -166,11 +166,20 @@ status_t Camera3OutputStream::returnBufferCheckedLocked( int anwReleaseFence = releaseFence->dup(); /** + * Release the lock briefly to avoid deadlock with + * StreamingProcessor::startStream -> Camera3Stream::isConfiguring (this + * thread will go into StreamingProcessor::onFrameAvailable) during + * queueBuffer + */ + sp currentConsumer = mConsumer; + mLock.unlock(); + + /** * Return buffer back to ANativeWindow */ if (buffer.status == CAMERA3_BUFFER_STATUS_ERROR) { // Cancel buffer - res = mConsumer->cancelBuffer(mConsumer.get(), + res = currentConsumer->cancelBuffer(currentConsumer.get(), container_of(buffer.buffer, ANativeWindowBuffer, handle), anwReleaseFence); if (res != OK) { @@ -178,7 +187,7 @@ status_t Camera3OutputStream::returnBufferCheckedLocked( " %s (%d)", __FUNCTION__, mId, strerror(-res), res); } } else { - res = mConsumer->queueBuffer(mConsumer.get(), + res = currentConsumer->queueBuffer(currentConsumer.get(), container_of(buffer.buffer, ANativeWindowBuffer, handle), anwReleaseFence); if (res != OK) { @@ -186,7 +195,7 @@ status_t Camera3OutputStream::returnBufferCheckedLocked( "%s (%d)", __FUNCTION__, mId, strerror(-res), res); } } - + mLock.lock(); if (res != OK) { close(anwReleaseFence); return res; diff --git a/services/camera/libcameraservice/camera3/Camera3OutputStream.h b/services/camera/libcameraservice/camera3/Camera3OutputStream.h index ce317f9..774fbdd 100644 --- a/services/camera/libcameraservice/camera3/Camera3OutputStream.h +++ b/services/camera/libcameraservice/camera3/Camera3OutputStream.h @@ -66,6 +66,9 @@ class Camera3OutputStream : Camera3OutputStream(int id, camera3_stream_type_t type, uint32_t width, uint32_t height, int format); + /** + * Note that we release the lock briefly in this function + */ virtual status_t returnBufferCheckedLocked( const camera3_stream_buffer &buffer, nsecs_t timestamp, -- cgit v1.1