Merge "EffectsFactory: fix subeffects loading"
diff --git a/drm/mediacas/plugins/clearkey/tests/Android.mk b/drm/mediacas/plugins/clearkey/tests/Android.mk
index 5418c1d..e1545af 100644
--- a/drm/mediacas/plugins/clearkey/tests/Android.mk
+++ b/drm/mediacas/plugins/clearkey/tests/Android.mk
@@ -21,6 +21,7 @@
ClearKeyFetcherTest.cpp
LOCAL_MODULE := ClearKeyFetcherTest
+LOCAL_VENDOR_MODULE := true
# LOCAL_LDFLAGS is needed here for the test to use the plugin, because
# the plugin is not in standard library search path. Without this .so
diff --git a/media/libaaudio/src/client/IsochronousClockModel.cpp b/media/libaaudio/src/client/IsochronousClockModel.cpp
index 73f4c1d..6ea1172 100644
--- a/media/libaaudio/src/client/IsochronousClockModel.cpp
+++ b/media/libaaudio/src/client/IsochronousClockModel.cpp
@@ -16,7 +16,7 @@
#define LOG_TAG "AAudio"
//#define LOG_NDEBUG 0
-#include <utils/Log.h>
+#include <log/log.h>
#include <stdint.h>
@@ -25,7 +25,6 @@
#define MIN_LATENESS_NANOS (10 * AAUDIO_NANOS_PER_MICROSECOND)
-using namespace android;
using namespace aaudio;
IsochronousClockModel::IsochronousClockModel()
diff --git a/media/libeffects/config/Android.bp b/media/libeffects/config/Android.bp
index 5666d14..4398a91 100644
--- a/media/libeffects/config/Android.bp
+++ b/media/libeffects/config/Android.bp
@@ -10,5 +10,8 @@
"libtinyxml2",
],
+ header_libs: ["libaudio_system_headers"],
+ export_header_lib_headers: ["libaudio_system_headers"],
+
export_include_dirs: ["include"],
}
diff --git a/media/libeffects/factory/Android.bp b/media/libeffects/factory/Android.bp
index 21be587..ddbfdd8 100644
--- a/media/libeffects/factory/Android.bp
+++ b/media/libeffects/factory/Android.bp
@@ -10,10 +10,11 @@
cc_library_shared {
name: "libeffects",
vendor: true,
- srcs: ["EffectsFactory.c",
- "EffectsConfigLoader.c",
- "EffectsFactoryState.c",
- "EffectsXmlConfigLoader.cpp",
+ srcs: [
+ "EffectsFactory.c",
+ "EffectsConfigLoader.c",
+ "EffectsFactoryState.c",
+ "EffectsXmlConfigLoader.cpp",
],
shared_libs: [
@@ -24,11 +25,12 @@
],
cflags: ["-fvisibility=hidden"],
- include_dirs: ["system/media/audio_effects/include"],
-
local_include_dirs:["include/media"],
- header_libs: ["libeffects_headers"],
+ header_libs: [
+ "libaudioeffects",
+ "libeffects_headers",
+ ],
export_header_lib_headers: ["libeffects_headers"],
}
diff --git a/media/libeffects/factory/EffectsConfigLoader.c b/media/libeffects/factory/EffectsConfigLoader.c
index 5c973b4..fcef36f 100644
--- a/media/libeffects/factory/EffectsConfigLoader.c
+++ b/media/libeffects/factory/EffectsConfigLoader.c
@@ -19,6 +19,7 @@
#include <dlfcn.h>
#include <stdlib.h>
+#include <unistd.h>
#include <cutils/config_utils.h>
#include <cutils/misc.h>
diff --git a/media/libeffects/factory/EffectsFactory.h b/media/libeffects/factory/EffectsFactory.h
index cdba362..29dbc9c 100644
--- a/media/libeffects/factory/EffectsFactory.h
+++ b/media/libeffects/factory/EffectsFactory.h
@@ -20,7 +20,6 @@
#include <dirent.h>
#include <pthread.h>
-#include <android/log.h>
#include <cutils/compiler.h>
#include <hardware/audio_effect.h>
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 758db1f..483a9ff 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -840,7 +840,7 @@
return;
}
- notifyEOS(true /* audio */, ERROR_END_OF_STREAM);
+ notifyEOS_l(true /* audio */, ERROR_END_OF_STREAM);
}
size_t NuPlayer::Renderer::fillAudioBuffer(void *buffer, size_t size) {
@@ -917,10 +917,10 @@
if (mAudioSink->needsTrailingPadding()) {
postEOSDelayUs = getPendingAudioPlayoutDurationUs(ALooper::GetNowUs());
}
- ALOGV("fillAudioBuffer: notifyEOS "
+ ALOGV("fillAudioBuffer: notifyEOS_l "
"mNumFramesWritten:%u finalResult:%d postEOSDelay:%lld",
mNumFramesWritten, entry->mFinalResult, (long long)postEOSDelayUs);
- notifyEOS(true /* audio */, entry->mFinalResult, postEOSDelayUs);
+ notifyEOS_l(true /* audio */, entry->mFinalResult, postEOSDelayUs);
}
}
return sizeCopied;
@@ -1408,6 +1408,11 @@
}
void NuPlayer::Renderer::notifyEOS(bool audio, status_t finalResult, int64_t delayUs) {
+ Mutex::Autolock autoLock(mLock);
+ notifyEOS_l(audio, finalResult, delayUs);
+}
+
+void NuPlayer::Renderer::notifyEOS_l(bool audio, status_t finalResult, int64_t delayUs) {
if (audio && delayUs > 0) {
sp<AMessage> msg = new AMessage(kWhatEOS, this);
msg->setInt32("audioEOSGeneration", mAudioEOSGeneration);
@@ -1420,6 +1425,11 @@
notify->setInt32("audio", static_cast<int32_t>(audio));
notify->setInt32("finalResult", finalResult);
notify->post(delayUs);
+
+ if (audio) {
+ // Video might outlive audio. Clear anchor to enable video only case.
+ mAnchorTimeMediaUs = -1;
+ }
}
void NuPlayer::Renderer::notifyAudioTearDown(AudioTearDownReason reason) {
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
index e6850b5..f58b79c 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
@@ -275,6 +275,7 @@
void onChangeAudioFormat(const sp<AMessage> &meta, const sp<AMessage> ¬ify);
void notifyEOS(bool audio, status_t finalResult, int64_t delayUs = 0);
+ void notifyEOS_l(bool audio, status_t finalResult, int64_t delayUs = 0);
void notifyFlushComplete(bool audio);
void notifyPosition();
void notifyVideoLateBy(int64_t lateByUs);
diff --git a/media/libnbaio/NBLog.cpp b/media/libnbaio/NBLog.cpp
index 2b5b4ff..f90d7fc 100644
--- a/media/libnbaio/NBLog.cpp
+++ b/media/libnbaio/NBLog.cpp
@@ -24,8 +24,8 @@
* Calls LOG_HIST_TS
* LOG_HIST_TS
* Hashes file name and line number, and writes single timestamp to buffer
-* calls NBLOG::Writer::logHistTS once
-* NBLOG::Writer::logHistTS
+* calls NBLOG::Writer::logEventHistTS once
+* NBLOG::Writer::logEventHistTS
* calls NBLOG::Writer::log on hash and current timestamp
* time is in CLOCK_MONOTONIC converted to ns
* NBLOG::Writer::log(Event, const void*, size_t)
@@ -44,6 +44,8 @@
* ssize_t audio_utils_fifo_reader::obtain
* Determines readable buffer section via pointer arithmetic on reader
* and writer pointers
+* Similarly, LOG_AUDIO_STATE() is called by onStateChange whenever audio is
+* turned on or off, and writes this notification to the FIFO.
*
* 2) reading the data from shared memory
* Thread::threadloop()
@@ -138,6 +140,7 @@
switch (type) {
case EVENT_START_FMT:
return std::make_unique<FormatEntry>(FormatEntry(ptr));
+ case EVENT_AUDIO_STATE:
case EVENT_HISTOGRAM_ENTRY_TS:
return std::make_unique<HistogramEntry>(HistogramEntry(ptr));
default:
@@ -516,7 +519,7 @@
log(EVENT_HASH, &hash, sizeof(hash));
}
-void NBLog::Writer::logHistTS(log_hash_t hash)
+void NBLog::Writer::logEventHistTs(Event event, log_hash_t hash)
{
if (!mEnabled) {
return;
@@ -525,7 +528,7 @@
data.hash = hash;
data.ts = get_monotonic_ns();
if (data.ts > 0) {
- log(EVENT_HISTOGRAM_ENTRY_TS, &data, sizeof(data));
+ log(event, &data, sizeof(data));
} else {
ALOGE("Failed to get timestamp");
}
@@ -758,7 +761,9 @@
const std::set<NBLog::Event> NBLog::Reader::startingTypes {NBLog::Event::EVENT_START_FMT,
NBLog::Event::EVENT_HISTOGRAM_ENTRY_TS};
const std::set<NBLog::Event> NBLog::Reader::endingTypes {NBLog::Event::EVENT_END_FMT,
- NBLog::Event::EVENT_HISTOGRAM_ENTRY_TS};
+ NBLog::Event::EVENT_HISTOGRAM_ENTRY_TS,
+ NBLog::Event::EVENT_AUDIO_STATE};
+
NBLog::Reader::Reader(const void *shared, size_t size)
: mShared((/*const*/ Shared *) shared), /*mIMemory*/
mFd(-1), mIndent(0),
@@ -925,6 +930,14 @@
++entry;
break;
}
+ case EVENT_AUDIO_STATE: {
+ StateTsEntryWithAuthor *data = (StateTsEntryWithAuthor *) (entry->data);
+ // TODO This memcpies are here to avoid unaligned memory access crash.
+ // There's probably a more efficient way to do it
+ performanceAnalysis.handleStateChange(data->author);
+ ++entry;
+ break;
+ }
case EVENT_END_FMT:
body.appendFormat("warning: got to end format event");
++entry;
diff --git a/media/libnbaio/PerformanceAnalysis.cpp b/media/libnbaio/PerformanceAnalysis.cpp
index fa8f47e..7cba4c6 100644
--- a/media/libnbaio/PerformanceAnalysis.cpp
+++ b/media/libnbaio/PerformanceAnalysis.cpp
@@ -71,6 +71,40 @@
return width;
}
+// Given a series of audio processing wakeup timestamps,
+// buckets the time intervals into a histogram, searches for
+// outliers, analyzes the outlier series for unexpectedly
+// small or large values and stores these as peaks, and flushes
+// the timestamp series from memory.
+void PerformanceAnalysis::processAndFlushTimeStampSeries(int author) {
+ // 1) analyze the series to store all outliers and their exact timestamps:
+ storeOutlierData(mTimeStampSeries[author]);
+
+ // 2) detect peaks in the outlier series
+ detectPeaks();
+
+ // 3) compute its histogram, append this to mRecentHists and erase the time series
+ // FIXME: need to store the timestamp of the beginning of each histogram
+ // FIXME: Restore LOG_HIST_FLUSH to separate histograms at every end-of-stream event
+ // A histogram should not span data between audio off/on timespans
+ mRecentHists.emplace_back(author, buildBuckets(mTimeStampSeries[author]));
+ // do not let mRecentHists exceed capacity
+ // ALOGD("mRecentHists size: %d", static_cast<int>(mRecentHists.size()));
+ if (mRecentHists.size() >= kRecentHistsCapacity) {
+ // ALOGD("popped back mRecentHists");
+ mRecentHists.pop_front();
+ }
+ mTimeStampSeries[author].clear();
+}
+
+// forces short-term histogram storage to avoid adding idle audio time interval
+// to buffer period data
+void PerformanceAnalysis::handleStateChange(int author) {
+ ALOGD("handleStateChange");
+ processAndFlushTimeStampSeries(author);
+ return;
+}
+
// Takes a single buffer period timestamp entry with author information and stores it
// in a temporary series of timestamps. Once the series is full, the data is analyzed,
// stored, and emptied.
@@ -82,25 +116,10 @@
// Store time series data for each reader in order to bucket it once there
// is enough data. Then, write to recentHists as a histogram.
mTimeStampSeries[author].push_back(ts);
- // if length of the time series has reached kShortHistSize samples, do 1) and 2):
+ // if length of the time series has reached kShortHistSize samples,
+ // analyze the data and flush the timestamp series from memory
if (mTimeStampSeries[author].size() >= kShortHistSize) {
- // 1) analyze the series to store all outliers and their exact timestamps:
- storeOutlierData(mTimeStampSeries[author]);
- // 2) detect peaks in the outlier series
- detectPeaks();
- // 3) compute its histogram, append this to mRecentHists and erase the time series
- // FIXME: need to store the timestamp of the beginning of each histogram
- // FIXME: Restore LOG_HIST_FLUSH to separate histograms at every end-of-stream event
- // A histogram should not span data between audio off/on timespans
- mRecentHists.emplace_back(author,
- buildBuckets(mTimeStampSeries[author]));
- // do not let mRecentHists exceed capacity
- // ALOGD("mRecentHists size: %d", static_cast<int>(mRecentHists.size()));
- if (mRecentHists.size() >= kRecentHistsCapacity) {
- // ALOGD("popped back mRecentHists");
- mRecentHists.pop_front();
- }
- mTimeStampSeries[author].clear();
+ processAndFlushTimeStampSeries(author);
}
}
diff --git a/media/libnbaio/include/media/nbaio/NBLog.h b/media/libnbaio/include/media/nbaio/NBLog.h
index 0b5e24d..3e48ee1 100644
--- a/media/libnbaio/include/media/nbaio/NBLog.h
+++ b/media/libnbaio/include/media/nbaio/NBLog.h
@@ -44,8 +44,6 @@
class Writer;
class Reader;
-private:
-
enum Event : uint8_t {
EVENT_RESERVED,
EVENT_STRING, // ASCII string, not NUL-terminated
@@ -60,11 +58,13 @@
EVENT_HASH, // unique HASH of log origin, originates from hash of file name
// and line number
EVENT_HISTOGRAM_ENTRY_TS, // single datum for timestamp histogram
+ EVENT_AUDIO_STATE, // audio on/off event: logged upon FastMixer::onStateChange() call
EVENT_END_FMT, // end of logFormat argument list
EVENT_UPPER_BOUND, // to check for invalid events
};
+private:
// ---------------------------------------------------------------------------
// API for handling format entry operations
@@ -248,6 +248,8 @@
int author;
}; //TODO __attribute__((packed));
+using StateTsEntryWithAuthor = HistTsEntryWithAuthor;
+
struct HistIntEntry {
log_hash_t hash;
int value;
@@ -341,7 +343,7 @@
virtual void logStart(const char *fmt);
virtual void logEnd();
virtual void logHash(log_hash_t hash);
- virtual void logHistTS(log_hash_t hash);
+ virtual void logEventHistTs(Event event, log_hash_t hash);
virtual bool isEnabled() const;
diff --git a/media/libnbaio/include/media/nbaio/PerformanceAnalysis.h b/media/libnbaio/include/media/nbaio/PerformanceAnalysis.h
index 89699bf..4be567f 100644
--- a/media/libnbaio/include/media/nbaio/PerformanceAnalysis.h
+++ b/media/libnbaio/include/media/nbaio/PerformanceAnalysis.h
@@ -52,6 +52,17 @@
using timestamp = uint64_t;
using timestamp_raw = int64_t;
+ // Given a series of audio processing wakeup timestamps,
+ // compresses and and analyzes the data, and flushes
+ // the timestamp series from memory.
+ void processAndFlushTimeStampSeries(int author);
+
+ // Called when an audio on/off event is read from the buffer
+ // calls flushTimeStampSeries on the data up to the event,
+ // effectively skipping over the idle audio time interval
+ // when writing buffer period data to memory.
+ void handleStateChange(int author);
+
// Writes wakeup timestamp entry to log and runs analysis
// author is the thread ID
// TODO: check. if the thread has multiple histograms, is author info correct
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 27c121f..92399f1 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -311,8 +311,14 @@
int64_t mMinCttsOffsetTicks;
int64_t mMaxCttsOffsetTicks;
- // Save the last 10 frames' timestamp for debug.
- std::list<std::pair<int64_t, int64_t>> mTimestampDebugHelper;
+ // Save the last 10 frames' timestamp and frame type for debug.
+ struct TimestampDebugHelperEntry {
+ int64_t pts;
+ int64_t dts;
+ std::string frameType;
+ };
+
+ std::list<TimestampDebugHelperEntry> mTimestampDebugHelper;
// Sequence parameter set or picture parameter set
struct AVCParamSet {
@@ -2543,12 +2549,12 @@
}
void MPEG4Writer::Track::dumpTimeStamps() {
- ALOGE("Dumping %s track's last 10 frames timestamp ", getTrackType());
+ ALOGE("Dumping %s track's last 10 frames timestamp and frame type ", getTrackType());
std::string timeStampString;
- for (std::list<std::pair<int64_t, int64_t>>::iterator num = mTimestampDebugHelper.begin();
- num != mTimestampDebugHelper.end(); ++num) {
- timeStampString += "(" + std::to_string(num->first)+
- "us, " + std::to_string(num->second) + "us) ";
+ for (std::list<TimestampDebugHelperEntry>::iterator entry = mTimestampDebugHelper.begin();
+ entry != mTimestampDebugHelper.end(); ++entry) {
+ timeStampString += "(" + std::to_string(entry->pts)+
+ "us, " + std::to_string(entry->dts) + "us " + entry->frameType + ") ";
}
ALOGE("%s", timeStampString.c_str());
}
@@ -2758,9 +2764,9 @@
previousPausedDurationUs += pausedDurationUs - lastDurationUs;
mResumed = false;
}
- std::pair<int64_t, int64_t> timestampPair;
+ TimestampDebugHelperEntry timestampDebugEntry;
timestampUs -= previousPausedDurationUs;
- timestampPair.first = timestampUs;
+ timestampDebugEntry.pts = timestampUs;
if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
copy->release();
mSource->stop();
@@ -2790,6 +2796,14 @@
}
mLastDecodingTimeUs = decodingTimeUs;
+ timestampDebugEntry.dts = decodingTimeUs;
+ timestampDebugEntry.frameType = isSync ? "Key frame" : "Non-Key frame";
+ // Insert the timestamp into the mTimestampDebugHelper
+ if (mTimestampDebugHelper.size() >= kTimestampDebugCount) {
+ mTimestampDebugHelper.pop_front();
+ }
+ mTimestampDebugHelper.push_back(timestampDebugEntry);
+
cttsOffsetTimeUs =
timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs;
if (WARN_UNLESS(cttsOffsetTimeUs >= 0ll, "for %s track", trackName)) {
@@ -2919,12 +2933,6 @@
lastDurationUs = timestampUs - lastTimestampUs;
lastDurationTicks = currDurationTicks;
lastTimestampUs = timestampUs;
- timestampPair.second = timestampUs;
- // Insert the timestamp into the mTimestampDebugHelper
- if (mTimestampDebugHelper.size() >= kTimestampDebugCount) {
- mTimestampDebugHelper.pop_front();
- }
- mTimestampDebugHelper.push_back(timestampPair);
if (isSync != 0) {
addOneStssTableEntry(mStszTableEntries->count());
diff --git a/media/libstagefright/omx/SoftOMXPlugin.cpp b/media/libstagefright/omx/SoftOMXPlugin.cpp
index fccb12b..0bc65e1 100644
--- a/media/libstagefright/omx/SoftOMXPlugin.cpp
+++ b/media/libstagefright/omx/SoftOMXPlugin.cpp
@@ -85,7 +85,21 @@
libName.append(kComponents[i].mLibNameSuffix);
libName.append(".so");
- void *libHandle = dlopen(libName.c_str(), RTLD_NOW);
+ // RTLD_NODELETE means we keep the shared library around forever.
+ // this eliminates thrashing during sequences like loading soundpools.
+ // It also leaves the rest of the logic around the dlopen()/dlclose()
+ // calls in this file unchanged.
+ //
+ // Implications of the change:
+ // -- the codec process (where this happens) will have a slightly larger
+ // long-term memory footprint as it accumulates the loaded shared libraries.
+ // This is expected to be a small amount of memory.
+ // -- plugin codecs can no longer (and never should have) depend on a
+ // free reset of any static data as the library would have crossed
+ // a dlclose/dlopen cycle.
+ //
+
+ void *libHandle = dlopen(libName.c_str(), RTLD_NOW|RTLD_NODELETE);
if (libHandle == NULL) {
ALOGE("unable to dlopen %s: %s", libName.c_str(), dlerror());
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index f1a55f1..f4428fe 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -1333,6 +1333,24 @@
ALOGVV("command(), cmdCode: %d, mHasControl: %d, mEffect: %p",
cmdCode, mHasControl, mEffect.unsafe_get());
+ // reject commands reserved for internal use by audio framework if coming from outside
+ // of audioserver
+ switch(cmdCode) {
+ case EFFECT_CMD_ENABLE:
+ case EFFECT_CMD_DISABLE:
+ case EFFECT_CMD_SET_PARAM:
+ case EFFECT_CMD_SET_PARAM_DEFERRED:
+ case EFFECT_CMD_SET_PARAM_COMMIT:
+ case EFFECT_CMD_GET_PARAM:
+ break;
+ default:
+ if (cmdCode >= EFFECT_CMD_FIRST_PROPRIETARY) {
+ break;
+ }
+ android_errorWriteLog(0x534e4554, "62019992");
+ return BAD_VALUE;
+ }
+
if (cmdCode == EFFECT_CMD_ENABLE) {
if (*replySize < sizeof(int)) {
android_errorWriteLog(0x534e4554, "32095713");
diff --git a/services/audioflinger/FastMixer.cpp b/services/audioflinger/FastMixer.cpp
index c4a0c0d..c10fa05 100644
--- a/services/audioflinger/FastMixer.cpp
+++ b/services/audioflinger/FastMixer.cpp
@@ -138,6 +138,8 @@
void FastMixer::onStateChange()
{
+ // log that audio was turned on/off
+ LOG_AUDIO_STATE();
const FastMixerState * const current = (const FastMixerState *) mCurrent;
const FastMixerState * const previous = (const FastMixerState *) mPrevious;
FastMixerDumpState * const dumpState = (FastMixerDumpState *) mDumpState;
diff --git a/services/audioflinger/TypedLogger.h b/services/audioflinger/TypedLogger.h
index 83aa6a1..909af09 100644
--- a/services/audioflinger/TypedLogger.h
+++ b/services/audioflinger/TypedLogger.h
@@ -88,7 +88,11 @@
// Write histogram timestamp entry
#define LOG_HIST_TS() do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
- x->logHistTS(hash(__FILE__, __LINE__)); } while(0)
+ x->logEventHistTs(NBLog::EVENT_HISTOGRAM_ENTRY_TS, hash(__FILE__, __LINE__)); } while(0)
+
+// Record that audio was turned on/off
+#define LOG_AUDIO_STATE() do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
+ x->logEventHistTs(NBLog::EVENT_AUDIO_STATE, hash(__FILE__, __LINE__)); } while(0)
namespace android {
extern "C" {
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index e022057..beec1f4 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -138,13 +138,15 @@
requestQueueRet.description().c_str());
return DEAD_OBJECT;
}
+
+ std::unique_ptr<ResultMetadataQueue>& resQueue = mResultMetadataQueue;
auto resultQueueRet = session->getCaptureResultMetadataQueue(
- [&queue = mResultMetadataQueue](const auto& descriptor) {
- queue = std::make_unique<ResultMetadataQueue>(descriptor);
- if (!queue->isValid() || queue->availableToWrite() <= 0) {
+ [&resQueue](const auto& descriptor) {
+ resQueue = std::make_unique<ResultMetadataQueue>(descriptor);
+ if (!resQueue->isValid() || resQueue->availableToWrite() <= 0) {
ALOGE("HAL returns empty result metadata fmq, not use it");
- queue = nullptr;
- // Don't use the queue onwards.
+ resQueue = nullptr;
+ // Don't use the resQueue onwards.
}
});
if (!resultQueueRet.isOk()) {
@@ -237,7 +239,7 @@
ALOGI("%s: E", __FUNCTION__);
status_t res = OK;
-
+ std::vector<wp<Camera3StreamInterface>> streams;
{
Mutex::Autolock l(mLock);
if (mStatus == STATUS_UNINITIALIZED) return res;
@@ -269,8 +271,13 @@
mRequestThread->requestExit();
}
- mOutputStreams.clear();
- mInputStream.clear();
+ streams.reserve(mOutputStreams.size() + (mInputStream != nullptr ? 1 : 0));
+ for (size_t i = 0; i < mOutputStreams.size(); i++) {
+ streams.push_back(mOutputStreams[i]);
+ }
+ if (mInputStream != nullptr) {
+ streams.push_back(mInputStream);
+ }
}
// Joining done without holding mLock, otherwise deadlocks may ensue
@@ -289,11 +296,8 @@
HalInterface* interface;
{
Mutex::Autolock l(mLock);
-
mRequestThread.clear();
mStatusTracker.clear();
- mBufferManager.clear();
-
interface = mInterface.get();
}
@@ -301,12 +305,25 @@
// wait on assorted callbacks,etc, to complete before it can return.
interface->close();
+ flushInflightRequests();
+
{
Mutex::Autolock l(mLock);
mInterface->clear();
+ mOutputStreams.clear();
+ mInputStream.clear();
+ mBufferManager.clear();
internalUpdateStatusLocked(STATUS_UNINITIALIZED);
}
+ for (auto& weakStream : streams) {
+ sp<Camera3StreamInterface> stream = weakStream.promote();
+ if (stream != nullptr) {
+ ALOGE("%s: Stream %d leaked! strong reference (%d)!",
+ __FUNCTION__, stream->getId(), stream->getStrongCount() - 1);
+ }
+ }
+
ALOGI("%s: X", __FUNCTION__);
return res;
}
@@ -834,6 +851,13 @@
hardware::Return<void> Camera3Device::processCaptureResult(
const hardware::hidl_vec<
hardware::camera::device::V3_2::CaptureResult>& results) {
+ {
+ Mutex::Autolock l(mLock);
+ if (mStatus == STATUS_ERROR) {
+ // Per API contract, HAL should act as closed after device error
+ ALOGW("%s: received capture result in error state!", __FUNCTION__);
+ }
+ }
if (mProcessCaptureResultLock.tryLock() != OK) {
// This should never happen; it indicates a wrong client implementation
@@ -965,6 +989,13 @@
hardware::Return<void> Camera3Device::notify(
const hardware::hidl_vec<hardware::camera::device::V3_2::NotifyMsg>& msgs) {
+ {
+ Mutex::Autolock l(mLock);
+ if (mStatus == STATUS_ERROR) {
+ // Per API contract, HAL should act as closed after device error
+ ALOGW("%s: received notify message in error state!", __FUNCTION__);
+ }
+ }
for (const auto& msg : msgs) {
notify(msg);
}
@@ -2434,6 +2465,53 @@
}
}
+void Camera3Device::flushInflightRequests() {
+ { // First return buffers cached in mInFlightMap
+ Mutex::Autolock l(mInFlightLock);
+ for (size_t idx = 0; idx < mInFlightMap.size(); idx++) {
+ const InFlightRequest &request = mInFlightMap.valueAt(idx);
+ returnOutputBuffers(request.pendingOutputBuffers.array(),
+ request.pendingOutputBuffers.size(), 0);
+ }
+ mInFlightMap.clear();
+ }
+
+ // Then return all inflight buffers not returned by HAL
+ std::vector<std::pair<int32_t, int32_t>> inflightKeys;
+ mInterface->getInflightBufferKeys(&inflightKeys);
+
+ int32_t inputStreamId = (mInputStream != nullptr) ? mInputStream->getId() : -1;
+ for (auto& pair : inflightKeys) {
+ int32_t frameNumber = pair.first;
+ int32_t streamId = pair.second;
+ buffer_handle_t* buffer;
+ status_t res = mInterface->popInflightBuffer(frameNumber, streamId, &buffer);
+ if (res != OK) {
+ ALOGE("%s: Frame %d: No in-flight buffer for stream %d",
+ __FUNCTION__, frameNumber, streamId);
+ continue;
+ }
+
+ camera3_stream_buffer_t streamBuffer;
+ streamBuffer.buffer = buffer;
+ streamBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
+ streamBuffer.acquire_fence = -1;
+ streamBuffer.release_fence = -1;
+ if (streamId == inputStreamId) {
+ streamBuffer.stream = mInputStream->asHalStream();
+ res = mInputStream->returnInputBuffer(streamBuffer);
+ if (res != OK) {
+ ALOGE("%s: Can't return input buffer for frame %d to"
+ " its stream:%s (%d)", __FUNCTION__,
+ frameNumber, strerror(-res), res);
+ }
+ } else {
+ streamBuffer.stream = mOutputStreams.valueFor(streamId)->asHalStream();
+ returnOutputBuffers(&streamBuffer, /*size*/1, /*timestamp*/ 0);
+ }
+ }
+}
+
void Camera3Device::insertResultLocked(CaptureResult *result,
uint32_t frameNumber) {
if (result == nullptr) return;
@@ -3349,6 +3427,20 @@
return res;
}
+void Camera3Device::HalInterface::getInflightBufferKeys(
+ std::vector<std::pair<int32_t, int32_t>>* out) {
+ std::lock_guard<std::mutex> lock(mInflightLock);
+ out->clear();
+ out->reserve(mInflightBufferMap.size());
+ for (auto& pair : mInflightBufferMap) {
+ uint64_t key = pair.first;
+ int32_t streamId = key & 0xFFFFFFFF;
+ int32_t frameNumber = (key >> 32) & 0xFFFFFFFF;
+ out->push_back(std::make_pair(frameNumber, streamId));
+ }
+ return;
+}
+
status_t Camera3Device::HalInterface::pushInflightBufferLocked(
int32_t frameNumber, int32_t streamId, buffer_handle_t *buffer, int acquireFence) {
uint64_t key = static_cast<uint64_t>(frameNumber) << 32 | static_cast<uint64_t>(streamId);
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 5549dd1..fb46d7e 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -265,6 +265,10 @@
status_t popInflightBuffer(int32_t frameNumber, int32_t streamId,
/*out*/ buffer_handle_t **buffer);
+ // Get a vector of (frameNumber, streamId) pair of currently inflight
+ // buffers
+ void getInflightBufferKeys(std::vector<std::pair<int32_t, int32_t>>* out);
+
private:
camera3_device_t *mHal3Device;
sp<hardware::camera::device::V3_2::ICameraDeviceSession> mHidlSession;
@@ -1023,6 +1027,10 @@
// Remove the in-flight request of the given index from mInFlightMap
// if it's no longer needed. It must only be called with mInFlightLock held.
void removeInFlightRequestIfReadyLocked(int idx);
+ // Remove all in-flight requests and return all buffers.
+ // This is used after HAL interface is closed to cleanup any request/buffers
+ // not returned by HAL.
+ void flushInflightRequests();
/**** End scope for mInFlightLock ****/
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.cpp b/services/camera/libcameraservice/device3/Camera3Stream.cpp
index 9297ac8..6789292 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Stream.cpp
@@ -523,6 +523,8 @@
return BAD_VALUE;
}
+ removeOutstandingBuffer(buffer);
+
/**
* TODO: Check that the state is valid first.
*
@@ -540,7 +542,6 @@
// buffer to be returned.
mOutputBufferReturnedSignal.signal();
- removeOutstandingBuffer(buffer);
return res;
}
@@ -591,13 +592,14 @@
return BAD_VALUE;
}
+ removeOutstandingBuffer(buffer);
+
status_t res = returnInputBufferLocked(buffer);
if (res == OK) {
fireBufferListenersLocked(buffer, /*acquired*/false, /*output*/false);
mInputBufferReturnedSignal.signal();
}
- removeOutstandingBuffer(buffer);
return res;
}
diff --git a/services/oboeservice/SharedMemoryProxy.cpp b/services/oboeservice/SharedMemoryProxy.cpp
index fc4532c..c31557e 100644
--- a/services/oboeservice/SharedMemoryProxy.cpp
+++ b/services/oboeservice/SharedMemoryProxy.cpp
@@ -16,12 +16,11 @@
#define LOG_TAG "AAudioService"
//#define LOG_NDEBUG 0
-#include <utils/Log.h>
+#include <log/log.h>
#include <aaudio/AAudio.h>
#include "SharedMemoryProxy.h"
-using namespace android;
using namespace aaudio;
SharedMemoryProxy::~SharedMemoryProxy()