Merge "stagefright: Enhance MPEG4 writer/extractor to store/retrieve layer info" into nyc-mr1-dev
diff --git a/camera/cameraserver/cameraserver.rc b/camera/cameraserver/cameraserver.rc
index c11a02a..8f6737f 100644
--- a/camera/cameraserver/cameraserver.rc
+++ b/camera/cameraserver/cameraserver.rc
@@ -4,3 +4,4 @@
group audio camera input drmrpc inet media mediadrm net_bt net_bt_admin net_bw_acct
ioprio rt 4
writepid /dev/cpuset/camera-daemon/tasks
+ writepid /dev/stune/top-app/tasks
diff --git a/include/media/stagefright/ColorConverter.h b/include/media/stagefright/ColorConverter.h
index 85ba920..270c809 100644
--- a/include/media/stagefright/ColorConverter.h
+++ b/include/media/stagefright/ColorConverter.h
@@ -70,6 +70,9 @@
status_t convertYUV420Planar(
const BitmapParams &src, const BitmapParams &dst);
+ status_t convertYUV420PlanarUseLibYUV(
+ const BitmapParams &src, const BitmapParams &dst);
+
status_t convertQCOMYUV420SemiPlanar(
const BitmapParams &src, const BitmapParams &dst);
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index acba6d7..32f86df 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -237,7 +237,8 @@
// copying array size -1, array for tags was calloc'd, no need to NULL-terminate it
size_t tagSize = realTagSize > AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1 ?
AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1 : realTagSize;
- utf16_to_utf8(tags.string(), tagSize, attributes->tags);
+ utf16_to_utf8(tags.string(), tagSize, attributes->tags,
+ sizeof(attributes->tags) / sizeof(attributes->tags[0]));
}
} else {
ALOGE("unmarshallAudioAttributes() received unflattened tags, ignoring tag values");
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 2445842..3848502 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -104,6 +104,7 @@
LOCAL_STATIC_LIBRARIES := \
libstagefright_color_conversion \
+ libyuv_static \
libstagefright_aacenc \
libstagefright_matroska \
libstagefright_mediafilter \
diff --git a/media/libstagefright/SampleTable.cpp b/media/libstagefright/SampleTable.cpp
index 542a06d..c9c49f5 100644
--- a/media/libstagefright/SampleTable.cpp
+++ b/media/libstagefright/SampleTable.cpp
@@ -123,7 +123,7 @@
mNumSampleSizes(0),
mHasTimeToSample(false),
mTimeToSampleCount(0),
- mTimeToSample(),
+ mTimeToSample(NULL),
mSampleTimeEntries(NULL),
mCompositionTimeDeltaEntries(NULL),
mNumCompositionTimeDeltaEntries(0),
@@ -132,7 +132,8 @@
mNumSyncSamples(0),
mSyncSamples(NULL),
mLastSyncSampleIndex(0),
- mSampleToChunkEntries(NULL) {
+ mSampleToChunkEntries(NULL),
+ mTotalSize(0) {
mSampleIterator = new SampleIterator(this);
}
@@ -143,6 +144,9 @@
delete[] mSyncSamples;
mSyncSamples = NULL;
+ delete[] mTimeToSample;
+ mTimeToSample = NULL;
+
delete mCompositionDeltaLookup;
mCompositionDeltaLookup = NULL;
@@ -233,13 +237,43 @@
return ERROR_MALFORMED;
}
- if (SIZE_MAX / sizeof(SampleToChunkEntry) <= (size_t)mNumSampleToChunkOffsets)
+ if ((uint64_t)SIZE_MAX / sizeof(SampleToChunkEntry) <=
+ (uint64_t)mNumSampleToChunkOffsets) {
+ ALOGE("Sample-to-chunk table size too large.");
return ERROR_OUT_OF_RANGE;
+ }
+
+ mTotalSize += (uint64_t)mNumSampleToChunkOffsets *
+ sizeof(SampleToChunkEntry);
+ if (mTotalSize > kMaxTotalSize) {
+ ALOGE("Sample-to-chunk table size would make sample table too large.\n"
+ " Requested sample-to-chunk table size = %llu\n"
+ " Eventual sample table size >= %llu\n"
+ " Allowed sample table size = %llu\n",
+ (unsigned long long)mNumSampleToChunkOffsets *
+ sizeof(SampleToChunkEntry),
+ (unsigned long long)mTotalSize,
+ (unsigned long long)kMaxTotalSize);
+ return ERROR_OUT_OF_RANGE;
+ }
mSampleToChunkEntries =
new (std::nothrow) SampleToChunkEntry[mNumSampleToChunkOffsets];
- if (!mSampleToChunkEntries)
+ if (!mSampleToChunkEntries) {
+ ALOGE("Cannot allocate sample-to-chunk table with %llu entries.",
+ (unsigned long long)mNumSampleToChunkOffsets);
return ERROR_OUT_OF_RANGE;
+ }
+
+ if (mNumSampleToChunkOffsets == 0) {
+ return OK;
+ }
+
+ if ((off64_t)(SIZE_MAX - 8 -
+ ((mNumSampleToChunkOffsets - 1) * sizeof(SampleToChunkEntry)))
+ < mSampleToChunkOffset) {
+ return ERROR_MALFORMED;
+ }
for (uint32_t i = 0; i < mNumSampleToChunkOffsets; ++i) {
uint8_t buffer[12];
@@ -358,20 +392,41 @@
// 2) mTimeToSampleCount is the number of entries of the time-to-sample
// table.
// 3) We hope that the table size does not exceed UINT32_MAX.
- ALOGE(" Error: Time-to-sample table size too large.");
+ ALOGE("Time-to-sample table size too large.");
return ERROR_OUT_OF_RANGE;
}
// Note: At this point, we know that mTimeToSampleCount * 2 will not
// overflow because of the above condition.
- if (!mDataSource->getVector(data_offset + 8, &mTimeToSample,
- mTimeToSampleCount * 2)) {
- ALOGE(" Error: Incomplete data read for time-to-sample table.");
+
+ uint64_t allocSize = (uint64_t)mTimeToSampleCount * 2 * sizeof(uint32_t);
+ mTotalSize += allocSize;
+ if (mTotalSize > kMaxTotalSize) {
+ ALOGE("Time-to-sample table size would make sample table too large.\n"
+ " Requested time-to-sample table size = %llu\n"
+ " Eventual sample table size >= %llu\n"
+ " Allowed sample table size = %llu\n",
+ (unsigned long long)allocSize,
+ (unsigned long long)mTotalSize,
+ (unsigned long long)kMaxTotalSize);
+ return ERROR_OUT_OF_RANGE;
+ }
+
+ mTimeToSample = new (std::nothrow) uint32_t[mTimeToSampleCount * 2];
+ if (!mTimeToSample) {
+ ALOGE("Cannot allocate time-to-sample table with %llu entries.",
+ (unsigned long long)mTimeToSampleCount);
+ return ERROR_OUT_OF_RANGE;
+ }
+
+ if (mDataSource->readAt(data_offset + 8, mTimeToSample,
+ (size_t)allocSize) < (ssize_t)allocSize) {
+ ALOGE("Incomplete data read for time-to-sample table.");
return ERROR_IO;
}
- for (size_t i = 0; i < mTimeToSample.size(); ++i) {
- mTimeToSample.editItemAt(i) = ntohl(mTimeToSample[i]);
+ for (size_t i = 0; i < mTimeToSampleCount * 2; ++i) {
+ mTimeToSample[i] = ntohl(mTimeToSample[i]);
}
mHasTimeToSample = true;
@@ -413,18 +468,33 @@
}
mNumCompositionTimeDeltaEntries = numEntries;
- uint64_t allocSize = (uint64_t)numEntries * 2 * sizeof(uint32_t);
- if (allocSize > UINT32_MAX) {
+ uint64_t allocSize = (uint64_t)numEntries * 2 * sizeof(int32_t);
+ if (allocSize > SIZE_MAX) {
+ ALOGE("Composition-time-to-sample table size too large.");
+ return ERROR_OUT_OF_RANGE;
+ }
+
+ mTotalSize += allocSize;
+ if (mTotalSize > kMaxTotalSize) {
+ ALOGE("Composition-time-to-sample table would make sample table too large.\n"
+ " Requested composition-time-to-sample table size = %llu\n"
+ " Eventual sample table size >= %llu\n"
+ " Allowed sample table size = %llu\n",
+ (unsigned long long)allocSize,
+ (unsigned long long)mTotalSize,
+ (unsigned long long)kMaxTotalSize);
return ERROR_OUT_OF_RANGE;
}
mCompositionTimeDeltaEntries = new (std::nothrow) int32_t[2 * numEntries];
- if (!mCompositionTimeDeltaEntries)
+ if (!mCompositionTimeDeltaEntries) {
+ ALOGE("Cannot allocate composition-time-to-sample table with %llu "
+ "entries.", (unsigned long long)numEntries);
return ERROR_OUT_OF_RANGE;
+ }
- if (mDataSource->readAt(
- data_offset + 8, mCompositionTimeDeltaEntries, numEntries * 8)
- < (ssize_t)numEntries * 8) {
+ if (mDataSource->readAt(data_offset + 8, mCompositionTimeDeltaEntries,
+ (size_t)allocSize) < (ssize_t)allocSize) {
delete[] mCompositionTimeDeltaEntries;
mCompositionTimeDeltaEntries = NULL;
@@ -465,18 +535,33 @@
ALOGV("Table of sync samples is empty or has only a single entry!");
}
- uint64_t allocSize = mNumSyncSamples * (uint64_t)sizeof(uint32_t);
+ uint64_t allocSize = (uint64_t)mNumSyncSamples * sizeof(uint32_t);
if (allocSize > SIZE_MAX) {
+ ALOGE("Sync sample table size too large.");
+ return ERROR_OUT_OF_RANGE;
+ }
+
+ mTotalSize += allocSize;
+ if (mTotalSize > kMaxTotalSize) {
+ ALOGE("Sync sample table size would make sample table too large.\n"
+ " Requested sync sample table size = %llu\n"
+ " Eventual sample table size >= %llu\n"
+ " Allowed sample table size = %llu\n",
+ (unsigned long long)allocSize,
+ (unsigned long long)mTotalSize,
+ (unsigned long long)kMaxTotalSize);
return ERROR_OUT_OF_RANGE;
}
mSyncSamples = new (std::nothrow) uint32_t[mNumSyncSamples];
- if (!mSyncSamples)
+ if (!mSyncSamples) {
+ ALOGE("Cannot allocate sync sample table with %llu entries.",
+ (unsigned long long)mNumSyncSamples);
return ERROR_OUT_OF_RANGE;
+ }
- size_t size = mNumSyncSamples * sizeof(uint32_t);
- if (mDataSource->readAt(mSyncSampleOffset + 8, mSyncSamples, size)
- != (ssize_t)size) {
+ if (mDataSource->readAt(mSyncSampleOffset + 8, mSyncSamples,
+ (size_t)allocSize) != (ssize_t)allocSize) {
return ERROR_IO;
}
@@ -544,9 +629,24 @@
return;
}
- mSampleTimeEntries = new (std::nothrow) SampleTimeEntry[mNumSampleSizes];
- if (!mSampleTimeEntries)
+ mTotalSize += (uint64_t)mNumSampleSizes * sizeof(SampleTimeEntry);
+ if (mTotalSize > kMaxTotalSize) {
+ ALOGE("Sample entry table size would make sample table too large.\n"
+ " Requested sample entry table size = %llu\n"
+ " Eventual sample table size >= %llu\n"
+ " Allowed sample table size = %llu\n",
+ (unsigned long long)mNumSampleSizes * sizeof(SampleTimeEntry),
+ (unsigned long long)mTotalSize,
+ (unsigned long long)kMaxTotalSize);
return;
+ }
+
+ mSampleTimeEntries = new (std::nothrow) SampleTimeEntry[mNumSampleSizes];
+ if (!mSampleTimeEntries) {
+ ALOGE("Cannot allocate sample entry table with %llu entries.",
+ (unsigned long long)mNumSampleSizes);
+ return;
+ }
uint32_t sampleIndex = 0;
uint32_t sampleTime = 0;
diff --git a/media/libstagefright/colorconversion/Android.mk b/media/libstagefright/colorconversion/Android.mk
index 32e2dfd..0bf9701 100644
--- a/media/libstagefright/colorconversion/Android.mk
+++ b/media/libstagefright/colorconversion/Android.mk
@@ -7,7 +7,11 @@
LOCAL_C_INCLUDES := \
$(TOP)/frameworks/native/include/media/openmax \
- $(TOP)/hardware/msm7k
+ $(TOP)/hardware/msm7k \
+ $(TOP)/external/libyuv/files/include
+
+LOCAL_STATIC_LIBRARIES := \
+ libyuv_static \
LOCAL_CFLAGS += -Werror
LOCAL_CLANG := true
diff --git a/media/libstagefright/colorconversion/ColorConverter.cpp b/media/libstagefright/colorconversion/ColorConverter.cpp
index 597167f..3ca7cc0 100644
--- a/media/libstagefright/colorconversion/ColorConverter.cpp
+++ b/media/libstagefright/colorconversion/ColorConverter.cpp
@@ -22,6 +22,10 @@
#include <media/stagefright/ColorConverter.h>
#include <media/stagefright/MediaErrors.h>
+#include "libyuv/convert_from.h"
+
+#define USE_LIBYUV
+
namespace android {
ColorConverter::ColorConverter(
@@ -103,7 +107,11 @@
switch (mSrcFormat) {
case OMX_COLOR_FormatYUV420Planar:
+#ifdef USE_LIBYUV
+ err = convertYUV420PlanarUseLibYUV(src, dst);
+#else
err = convertYUV420Planar(src, dst);
+#endif
break;
case OMX_COLOR_FormatCbYCrY:
@@ -196,6 +204,34 @@
return OK;
}
+status_t ColorConverter::convertYUV420PlanarUseLibYUV(
+ const BitmapParams &src, const BitmapParams &dst) {
+ if (!((src.mCropLeft & 1) == 0
+ && src.cropWidth() == dst.cropWidth()
+ && src.cropHeight() == dst.cropHeight())) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ uint16_t *dst_ptr = (uint16_t *)dst.mBits
+ + dst.mCropTop * dst.mWidth + dst.mCropLeft;
+
+ const uint8_t *src_y =
+ (const uint8_t *)src.mBits + src.mCropTop * src.mWidth + src.mCropLeft;
+
+ const uint8_t *src_u =
+ (const uint8_t *)src_y + src.mWidth * src.mHeight
+ + src.mCropTop * (src.mWidth / 2) + src.mCropLeft / 2;
+
+ const uint8_t *src_v =
+ src_u + (src.mWidth / 2) * (src.mHeight / 2);
+
+
+ libyuv::I420ToRGB565(src_y, src.mWidth, src_u, src.mWidth / 2, src_v, src.mWidth / 2,
+ (uint8 *)dst_ptr, dst.mWidth * 2, dst.mWidth, dst.mHeight);
+
+ return OK;
+}
+
status_t ColorConverter::convertYUV420Planar(
const BitmapParams &src, const BitmapParams &dst) {
if (!((src.mCropLeft & 1) == 0
diff --git a/media/libstagefright/include/SampleTable.h b/media/libstagefright/include/SampleTable.h
index 54da497..2100ca6 100644
--- a/media/libstagefright/include/SampleTable.h
+++ b/media/libstagefright/include/SampleTable.h
@@ -24,7 +24,6 @@
#include <media/stagefright/MediaErrors.h>
#include <utils/RefBase.h>
#include <utils/threads.h>
-#include <utils/Vector.h>
namespace android {
@@ -96,6 +95,9 @@
static const uint32_t kSampleSizeType32;
static const uint32_t kSampleSizeTypeCompact;
+ // Limit the total size of all internal tables to 200MiB.
+ static const size_t kMaxTotalSize = 200 * (1 << 20);
+
sp<DataSource> mDataSource;
Mutex mLock;
@@ -113,7 +115,7 @@
bool mHasTimeToSample;
uint32_t mTimeToSampleCount;
- Vector<uint32_t> mTimeToSample;
+ uint32_t* mTimeToSample;
struct SampleTimeEntry {
uint32_t mSampleIndex;
@@ -139,6 +141,9 @@
};
SampleToChunkEntry *mSampleToChunkEntries;
+ // Approximate size of all tables combined.
+ uint64_t mTotalSize;
+
friend struct SampleIterator;
// normally we don't round
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index f9a9ab9..abe2582 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -1042,49 +1042,13 @@
return;
}
- sp<ABuffer> accessUnit;
- CHECK(msg->findBuffer("access-unit", &accessUnit));
-
- uint32_t seqNum = (uint32_t)accessUnit->int32Data();
-
if (mSeekPending) {
ALOGV("we're seeking, dropping stale packet.");
break;
}
- if (track->mNewSegment) {
- // The sequence number from RTP packet has only 16 bits and is extended
- // by ARTPSource. Only the low 16 bits of seq in RTP-Info of reply of
- // RTSP "PLAY" command should be used to detect the first RTP packet
- // after seeking.
- if (track->mAllowedStaleAccessUnits > 0) {
- if ((((seqNum ^ track->mFirstSeqNumInSegment) & 0xffff) != 0)) {
- // Not the first rtp packet of the stream after seeking, discarding.
- track->mAllowedStaleAccessUnits--;
- ALOGV("discarding stale access unit (0x%x : 0x%x)",
- seqNum, track->mFirstSeqNumInSegment);
- break;
- }
- } else { // track->mAllowedStaleAccessUnits <= 0
- mNumAccessUnitsReceived = 0;
- ALOGW_IF(track->mAllowedStaleAccessUnits == 0,
- "Still no first rtp packet after %d stale ones",
- kMaxAllowedStaleAccessUnits);
- track->mAllowedStaleAccessUnits = -1;
- break;
- }
-
- // Now found the first rtp packet of the stream after seeking.
- track->mFirstSeqNumInSegment = seqNum;
- track->mNewSegment = false;
- }
-
- if (seqNum < track->mFirstSeqNumInSegment) {
- ALOGV("dropping stale access-unit (%d < %d)",
- seqNum, track->mFirstSeqNumInSegment);
- break;
- }
-
+ sp<ABuffer> accessUnit;
+ CHECK(msg->findBuffer("access-unit", &accessUnit));
onAccessUnitComplete(trackIndex, accessUnit);
break;
}
@@ -1852,17 +1816,16 @@
int32_t trackIndex, const sp<ABuffer> &accessUnit) {
ALOGV("onAccessUnitComplete track %d", trackIndex);
+ TrackInfo *track = &mTracks.editItemAt(trackIndex);
if(!mPlayResponseParsed){
- ALOGI("play response is not parsed, storing accessunit");
- TrackInfo *track = &mTracks.editItemAt(trackIndex);
+ uint32_t seqNum = (uint32_t)accessUnit->int32Data();
+ ALOGI("play response is not parsed, storing accessunit %u", seqNum);
track->mPackets.push_back(accessUnit);
return;
}
handleFirstAccessUnit();
- TrackInfo *track = &mTracks.editItemAt(trackIndex);
-
if (!mAllTracksHaveTime) {
ALOGV("storing accessUnit, no time established yet");
track->mPackets.push_back(accessUnit);
@@ -1873,6 +1836,41 @@
sp<ABuffer> accessUnit = *track->mPackets.begin();
track->mPackets.erase(track->mPackets.begin());
+ uint32_t seqNum = (uint32_t)accessUnit->int32Data();
+ if (track->mNewSegment) {
+ // The sequence number from RTP packet has only 16 bits and is extended
+ // by ARTPSource. Only the low 16 bits of seq in RTP-Info of reply of
+ // RTSP "PLAY" command should be used to detect the first RTP packet
+ // after seeking.
+ if (track->mAllowedStaleAccessUnits > 0) {
+ if ((((seqNum ^ track->mFirstSeqNumInSegment) & 0xffff) != 0)) {
+ // Not the first rtp packet of the stream after seeking, discarding.
+ track->mAllowedStaleAccessUnits--;
+ ALOGV("discarding stale access unit (0x%x : 0x%x)",
+ seqNum, track->mFirstSeqNumInSegment);
+ continue;
+ }
+ } else { // track->mAllowedStaleAccessUnits <= 0
+ mNumAccessUnitsReceived = 0;
+ ALOGW_IF(track->mAllowedStaleAccessUnits == 0,
+ "Still no first rtp packet after %d stale ones",
+ kMaxAllowedStaleAccessUnits);
+ track->mAllowedStaleAccessUnits = -1;
+ return;
+ }
+
+ // Now found the first rtp packet of the stream after seeking.
+ track->mFirstSeqNumInSegment = seqNum;
+ track->mNewSegment = false;
+ }
+
+ if (seqNum < track->mFirstSeqNumInSegment) {
+ ALOGV("dropping stale access-unit (%d < %d)",
+ seqNum, track->mFirstSeqNumInSegment);
+ continue;
+ }
+
+
if (addMediaTimestamp(trackIndex, track, accessUnit)) {
postQueueAccessUnit(trackIndex, accessUnit);
}
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 83e8222..149b492 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -132,6 +132,9 @@
case AUDIO_FORMAT_AC3: return "ac-3";
case AUDIO_FORMAT_E_AC3: return "e-ac-3";
case AUDIO_FORMAT_IEC61937: return "iec61937";
+ case AUDIO_FORMAT_DTS: return "dts";
+ case AUDIO_FORMAT_DTS_HD: return "dts-hd";
+ case AUDIO_FORMAT_DOLBY_TRUEHD: return "dolby-truehd";
default:
break;
}
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 6f827d9..72be301 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1341,12 +1341,10 @@
}
} break;
case OFFLOAD:
- // only offloadable effects on offload thread
- if ((desc->flags & EFFECT_FLAG_OFFLOAD_MASK) != EFFECT_FLAG_OFFLOAD_SUPPORTED) {
- ALOGW("checkEffectCompatibility_l(): non offloadable effect %s created on"
- " OFFLOAD thread %s", desc->name, mThreadName);
- return BAD_VALUE;
- }
+ // nothing actionable on offload threads, if the effect:
+ // - is offloadable: the effect can be created
+ // - is NOT offloadable: the effect should still be created, but EffectHandle::enable()
+ // will take care of invalidating the tracks of the thread
break;
case DIRECT:
// Reject any effect on Direct output threads for now, since the format of
diff --git a/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp b/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp
index f639551..48bfd79 100644
--- a/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp
@@ -142,6 +142,7 @@
MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_DTS),
MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_DTS_HD),
MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_IEC61937),
+ MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
};
template<>
const size_t FormatConverter::mSize = sizeof(FormatConverter::mTable) /
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 3b075fa..0e64716 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -4375,7 +4375,7 @@
}
routing_strategy curStrategy = getStrategy((audio_stream_type_t)curStream);
audio_devices_t curDevices =
- getDeviceForStrategy((routing_strategy)curStrategy, true /*fromCache*/);
+ getDeviceForStrategy((routing_strategy)curStrategy, false /*fromCache*/);
SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(curDevices, mOutputs);
for (size_t i = 0; i < outputs.size(); i++) {
sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(outputs[i]);
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index ff73c28..4510d36 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -911,8 +911,9 @@
// Can camera service trust the caller based on the calling UID?
static bool isTrustedCallingUid(uid_t uid) {
switch (uid) {
- case AID_MEDIA: // mediaserver
+ case AID_MEDIA: // mediaserver
case AID_CAMERASERVER: // cameraserver
+ case AID_RADIO: // telephony
return true;
default:
return false;
diff --git a/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp b/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
index ffe96fc..d6d8dde 100644
--- a/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
@@ -67,10 +67,15 @@
}
void JpegProcessor::onBufferReleased(const BufferInfo& bufferInfo) {
- Mutex::Autolock l(mInputMutex);
ALOGV("%s", __FUNCTION__);
-
if (bufferInfo.mError) {
+ // Only lock in case of error, since we get one of these for each
+ // onFrameAvailable as well, and scheduling may delay this call late
+ // enough to run into later preview restart operations, for non-error
+ // cases.
+ // b/29524651
+ ALOGV("%s: JPEG buffer lost", __FUNCTION__);
+ Mutex::Autolock l(mInputMutex);
mCaptureDone = true;
mCaptureSuccess = false;
mCaptureDoneSignal.signal();