Merge "Camera: Fix "use after free" for mOutstandingBuffers" into oc-dr1-dev
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/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/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 ****/