Merge "AAudio: doc that 24BIT_PACKED is little-endian" into sc-dev
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 8fe48c2..716b550 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -1,6 +1,8 @@
[Hook Scripts]
mainline_hook = ${REPO_ROOT}/frameworks/av/tools/mainline_hook_partial.sh ${REPO_ROOT} ${PREUPLOAD_FILES}
+hidden_api_txt_checksorted_hook = ${REPO_ROOT}/tools/platform-compat/hiddenapi/checksorted_sha.sh ${PREUPLOAD_COMMIT} ${REPO_ROOT}
+
[Builtin Hooks]
clang_format = true
diff --git a/apex/Android.bp b/apex/Android.bp
index a86d2b9..b9abd12 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -98,6 +98,35 @@
name: "com.android.media-bootclasspath-fragment",
contents: ["updatable-media"],
apex_available: ["com.android.media"],
+
+ api: {
+ stub_libs: [
+ // Stubs for the APIs provided by updatable-media. This has to be
+ // specified explicitly because updatable-media is not a
+ // java_sdk_library.
+ "framework-media",
+ ],
+ },
+
+ // The bootclasspath_fragments that provide APIs on which this depends.
+ fragments: [
+ {
+ apex: "com.android.art",
+ module: "art-bootclasspath-fragment",
+ },
+ ],
+
+ // Additional stubs libraries that this fragment's contents use which are
+ // not provided by another bootclasspath_fragment.
+ additional_stubs: [
+ "android-non-updatable",
+ ],
+
+ // Additional hidden API flag files to override the defaults. This must only be
+ // modified by the Soong or platform compat team.
+ hidden_api: {
+ max_target_o_low_priority: ["hiddenapi/hiddenapi-max-target-o-low-priority.txt"],
+ },
}
// Encapsulate the contributions made by the com.android.media to the systemserverclasspath.
diff --git a/apex/hiddenapi/OWNERS b/apex/hiddenapi/OWNERS
new file mode 100644
index 0000000..ac8a2b6
--- /dev/null
+++ b/apex/hiddenapi/OWNERS
@@ -0,0 +1,5 @@
+# soong-team@ as the hiddenapi files are tightly coupled with Soong
+file:platform/build/soong:/OWNERS
+
+# compat-team@ for changes to hiddenapi files
+file:tools/platform-compat:/OWNERS
diff --git a/apex/hiddenapi/hiddenapi-max-target-o-low-priority.txt b/apex/hiddenapi/hiddenapi-max-target-o-low-priority.txt
new file mode 100644
index 0000000..32bbb10
--- /dev/null
+++ b/apex/hiddenapi/hiddenapi-max-target-o-low-priority.txt
@@ -0,0 +1,6 @@
+Landroid/media/MediaSession2$ControllerInfo;-><init>(Landroid/content/Context;IILjava/lang/String;Landroid/os/IInterface;)V
+Landroid/media/MediaSession2$ControllerInfo;->getPackageName()Ljava/lang/String;
+Landroid/media/MediaSession2$ControllerInfo;->getProvider()Landroid/media/update/MediaSession2Provider$ControllerInfoProvider;
+Landroid/media/MediaSession2$ControllerInfo;->getUid()I
+Landroid/media/MediaSession2$ControllerInfo;->isTrusted()Z
+Landroid/media/MediaSession2$ControllerInfo;->mProvider:Landroid/media/update/MediaSession2Provider$ControllerInfoProvider;
diff --git a/media/codec2/components/aac/C2SoftAacDec.cpp b/media/codec2/components/aac/C2SoftAacDec.cpp
index 332696d..f948dd4 100644
--- a/media/codec2/components/aac/C2SoftAacDec.cpp
+++ b/media/codec2/components/aac/C2SoftAacDec.cpp
@@ -514,8 +514,8 @@
// TODO: error handling, proper usage, etc.
C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
- c2_status_t err = pool->fetchLinearBlock(
- numSamples * sizeof(int16_t), usage, &block);
+ size_t bufferSize = numSamples * sizeof(int16_t);
+ c2_status_t err = pool->fetchLinearBlock(bufferSize, usage, &block);
if (err != C2_OK) {
ALOGD("failed to fetch a linear block (%d)", err);
return std::bind(fillEmptyWork, _1, C2_NO_MEMORY);
@@ -529,7 +529,7 @@
mSignalledError = true;
return std::bind(fillEmptyWork, _1, C2_CORRUPTED);
}
- return [buffer = createLinearBuffer(block)](
+ return [buffer = createLinearBuffer(block, 0, bufferSize)](
const std::unique_ptr<C2Work> &work) {
work->result = C2_OK;
C2FrameData &output = work->worklets.front()->output;
diff --git a/media/codec2/components/amr_nb_wb/C2SoftAmrDec.cpp b/media/codec2/components/amr_nb_wb/C2SoftAmrDec.cpp
index c08e02b..70a2da5 100644
--- a/media/codec2/components/amr_nb_wb/C2SoftAmrDec.cpp
+++ b/media/codec2/components/amr_nb_wb/C2SoftAmrDec.cpp
@@ -361,7 +361,13 @@
work->worklets.front()->output.flags = work->input.flags;
work->worklets.front()->output.buffers.clear();
- work->worklets.front()->output.buffers.push_back(createLinearBuffer(block));
+ // we filled the output buffer to (intptr_t)output - (intptr_t)wView.data()
+ // use calOutSize as that contains the expected number of samples
+ ALOGD_IF(calOutSize != ((intptr_t)output - (intptr_t)wView.data()),
+ "Expected %zu output bytes, but filled %lld",
+ calOutSize, (long long)((intptr_t)output - (intptr_t)wView.data()));
+ work->worklets.front()->output.buffers.push_back(
+ createLinearBuffer(block, 0, calOutSize));
work->worklets.front()->output.ordinal = work->input.ordinal;
if (eos) {
mSignalledOutputEos = true;
diff --git a/media/codec2/components/base/SimpleC2Component.cpp b/media/codec2/components/base/SimpleC2Component.cpp
index dfad226..6c4b7d9 100644
--- a/media/codec2/components/base/SimpleC2Component.cpp
+++ b/media/codec2/components/base/SimpleC2Component.cpp
@@ -592,21 +592,11 @@
}
std::shared_ptr<C2Buffer> SimpleC2Component::createLinearBuffer(
- const std::shared_ptr<C2LinearBlock> &block) {
- return createLinearBuffer(block, block->offset(), block->size());
-}
-
-std::shared_ptr<C2Buffer> SimpleC2Component::createLinearBuffer(
const std::shared_ptr<C2LinearBlock> &block, size_t offset, size_t size) {
return C2Buffer::CreateLinearBuffer(block->share(offset, size, ::C2Fence()));
}
std::shared_ptr<C2Buffer> SimpleC2Component::createGraphicBuffer(
- const std::shared_ptr<C2GraphicBlock> &block) {
- return createGraphicBuffer(block, C2Rect(block->width(), block->height()));
-}
-
-std::shared_ptr<C2Buffer> SimpleC2Component::createGraphicBuffer(
const std::shared_ptr<C2GraphicBlock> &block, const C2Rect &crop) {
return C2Buffer::CreateGraphicBuffer(block->share(crop, ::C2Fence()));
}
diff --git a/media/codec2/components/base/include/SimpleC2Component.h b/media/codec2/components/base/include/SimpleC2Component.h
index 22d5714..e5e16d8 100644
--- a/media/codec2/components/base/include/SimpleC2Component.h
+++ b/media/codec2/components/base/include/SimpleC2Component.h
@@ -140,15 +140,9 @@
std::shared_ptr<C2Buffer> createLinearBuffer(
- const std::shared_ptr<C2LinearBlock> &block);
-
- std::shared_ptr<C2Buffer> createLinearBuffer(
const std::shared_ptr<C2LinearBlock> &block, size_t offset, size_t size);
std::shared_ptr<C2Buffer> createGraphicBuffer(
- const std::shared_ptr<C2GraphicBlock> &block);
-
- std::shared_ptr<C2Buffer> createGraphicBuffer(
const std::shared_ptr<C2GraphicBlock> &block,
const C2Rect &crop);
diff --git a/media/codec2/components/g711/C2SoftG711Dec.cpp b/media/codec2/components/g711/C2SoftG711Dec.cpp
index f9299af..f952f22 100644
--- a/media/codec2/components/g711/C2SoftG711Dec.cpp
+++ b/media/codec2/components/g711/C2SoftG711Dec.cpp
@@ -199,7 +199,7 @@
work->worklets.front()->output.flags = work->input.flags;
work->worklets.front()->output.buffers.clear();
- work->worklets.front()->output.buffers.push_back(createLinearBuffer(block));
+ work->worklets.front()->output.buffers.push_back(createLinearBuffer(block, 0, outSize));
work->worklets.front()->output.ordinal = work->input.ordinal;
if (eos) {
diff --git a/media/codec2/components/vpx/C2SoftVpxEnc.cpp b/media/codec2/components/vpx/C2SoftVpxEnc.cpp
index 7e9090f..7486d27 100644
--- a/media/codec2/components/vpx/C2SoftVpxEnc.cpp
+++ b/media/codec2/components/vpx/C2SoftVpxEnc.cpp
@@ -635,7 +635,8 @@
}
work->worklets.front()->output.flags = (C2FrameData::flags_t)flags;
work->worklets.front()->output.buffers.clear();
- std::shared_ptr<C2Buffer> buffer = createLinearBuffer(block);
+ std::shared_ptr<C2Buffer> buffer =
+ createLinearBuffer(block, 0, encoded_packet->data.frame.sz);
if (encoded_packet->data.frame.flags & VPX_FRAME_IS_KEY) {
buffer->setInfo(std::make_shared<C2StreamPictureTypeMaskInfo::output>(
0u /* stream id */, C2Config::SYNC_FRAME));
diff --git a/media/codec2/components/xaac/C2SoftXaacDec.cpp b/media/codec2/components/xaac/C2SoftXaacDec.cpp
index 6deafda..8bf4b72 100644
--- a/media/codec2/components/xaac/C2SoftXaacDec.cpp
+++ b/media/codec2/components/xaac/C2SoftXaacDec.cpp
@@ -361,9 +361,8 @@
C2WriteView wView = block->map().get();
int16_t* outBuffer = reinterpret_cast<int16_t*>(wView.data());
memcpy(outBuffer, mOutputDrainBuffer, mOutputDrainBufferWritePos);
- mOutputDrainBufferWritePos = 0;
- auto fillWork = [buffer = createLinearBuffer(block)](
+ auto fillWork = [buffer = createLinearBuffer(block, 0, mOutputDrainBufferWritePos)](
const std::unique_ptr<C2Work>& work) {
uint32_t flags = 0;
if (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) {
@@ -376,6 +375,9 @@
work->worklets.front()->output.ordinal = work->input.ordinal;
work->workletsProcessed = 1u;
};
+
+ mOutputDrainBufferWritePos = 0;
+
if (work && work->input.ordinal.frameIndex == c2_cntr64_t(mCurFrameIndex)) {
fillWork(work);
} else {
diff --git a/media/codec2/core/include/C2Buffer.h b/media/codec2/core/include/C2Buffer.h
index a5d6fbf..abe343b 100644
--- a/media/codec2/core/include/C2Buffer.h
+++ b/media/codec2/core/include/C2Buffer.h
@@ -898,6 +898,12 @@
* Obtains a linear writeable block of given |capacity| and |usage|. If successful, the
* block is stored in |block|. Otherwise, |block| is set to 'nullptr'.
*
+ * \note The returned buffer may have a larger capacity than requested. In this case the
+ * larger (returned) capacity may be fully used.
+ *
+ * \note There is no guarantee on the alignedness of the returned block. The only guarantee is
+ * that its capacity is equal to or larger than the requested capacity.
+ *
* \param capacity the size of requested block.
* \param usage the memory usage info for the requested block. Returned blocks will be
* optimized for this usage, but may be used with any usage. One exception:
@@ -926,6 +932,12 @@
* Obtains a circular writeable block of given |capacity| and |usage|. If successful, the
* block is stored in |block|. Otherwise, |block| is set to 'nullptr'.
*
+ * \note The returned buffer may have a larger capacity than requested. In this case the
+ * larger (returned) capacity may be fully used.
+ *
+ * \note There is no guarantee on the alignedness of the returned block. The only guarantee is
+ * that its capacity is equal to or larger than the requested capacity.
+ *
* \param capacity the size of requested circular block. (note: the size of the obtained
* block could be slightly larger, e.g. to accommodate any system-required
* alignment)
@@ -956,6 +968,12 @@
* Obtains a 2D graphic block of given |width|, |height|, |format| and |usage|. If successful,
* the block is stored in |block|. Otherwise, |block| is set to 'nullptr'.
*
+ * \note The returned buffer may have a larger capacity (width and height) than requested. In
+ * this case the larger (returned) capacity may be fully used.
+ *
+ * \note There is no guarantee on the alignedness of the returned block. The only guarantee is
+ * that its capacity is equal to or larger than the requested capacity (width and height).
+ *
* \param width the width of requested block (the obtained block could be slightly larger, e.g.
* to accommodate any system-required alignment)
* \param height the height of requested block (the obtained block could be slightly larger,
@@ -1000,6 +1018,12 @@
* fence is signalled when the temporary restriction on fetch is lifted.
* e.g. more memory is available to fetch because some meomory or prior blocks were released.
*
+ * \note The returned buffer may have a larger capacity than requested. In this case the
+ * larger (returned) capacity may be fully used.
+ *
+ * \note There is no guarantee on the alignedness of the returned block. The only guarantee is
+ * that its capacity is equal to or larger than the requested capacity.
+ *
* \param capacity the size of requested block.
* \param usage the memory usage info for the requested block. Returned blocks will be
* optimized for this usage, but may be used with any usage. One exception:
@@ -1039,6 +1063,12 @@
* fence is signalled when the temporary restriction on fetch is lifted.
* e.g. more memory is available to fetch because some meomory or prior blocks were released.
*
+ * \note The returned buffer may have a larger capacity (width and height) than requested. In
+ * this case the larger (returned) capacity may be fully used.
+ *
+ * \note There is no guarantee on the alignedness of the returned block. The only guarantee is
+ * that its capacity is equal to or larger than the requested capacity (width and height).
+ *
* \param width the width of requested block (the obtained block could be slightly larger, e.g.
* to accommodate any system-required alignment)
* \param height the height of requested block (the obtained block could be slightly larger,
diff --git a/media/codec2/core/include/C2Config.h b/media/codec2/core/include/C2Config.h
index 7caa457..f5d6529 100644
--- a/media/codec2/core/include/C2Config.h
+++ b/media/codec2/core/include/C2Config.h
@@ -574,7 +574,6 @@
PROFILE_MPEGH_HIGH, ///< MPEG-H High
PROFILE_MPEGH_LC, ///< MPEG-H Low-complexity
PROFILE_MPEGH_BASELINE, ///< MPEG-H Baseline
-
};
enum C2Config::level_t : uint32_t {
diff --git a/media/codec2/hidl/plugin/samples/SampleFilterPlugin.cpp b/media/codec2/hidl/plugin/samples/SampleFilterPlugin.cpp
index 7de3503..b942be7 100644
--- a/media/codec2/hidl/plugin/samples/SampleFilterPlugin.cpp
+++ b/media/codec2/hidl/plugin/samples/SampleFilterPlugin.cpp
@@ -626,6 +626,14 @@
}
LOG(VERBOSE) << "work #" << workCount << ": flags=" << work->input.flags
<< " timestamp=" << work->input.ordinal.timestamp.peek();;
+
+ std::vector<C2Param *> configUpdate;
+ for (const std::unique_ptr<C2Param> ¶m : work->input.configUpdate) {
+ configUpdate.push_back(param.get());
+ }
+ std::vector<std::unique_ptr<C2SettingResult>> failures;
+ mIntf->config_vb(configUpdate, C2_MAY_BLOCK, &failures);
+
std::shared_ptr<C2StreamHdrStaticInfo::input> hdrStaticInfo =
mIntf->getHdrStaticMetadata();
uint32_t dataspace = mIntf->getDataSpace();
diff --git a/media/codec2/sfplugin/Codec2Buffer.cpp b/media/codec2/sfplugin/Codec2Buffer.cpp
index 34e6a88..691bab1 100644
--- a/media/codec2/sfplugin/Codec2Buffer.cpp
+++ b/media/codec2/sfplugin/Codec2Buffer.cpp
@@ -679,17 +679,20 @@
std::shared_ptr<C2Buffer> GraphicMetadataBuffer::asC2Buffer() {
#ifdef __LP64__
static std::once_flag s_checkOnce;
- static bool s_64bitonly {false};
+ static bool s_is64bitOk {true};
std::call_once(s_checkOnce, [&](){
const std::string abi32list =
::android::base::GetProperty("ro.product.cpu.abilist32", "");
- if (abi32list.empty()) {
- s_64bitonly = true;
+ if (!abi32list.empty()) {
+ int32_t inputSurfaceSetting =
+ ::android::base::GetIntProperty("debug.stagefright.c2inputsurface", int32_t(0));
+ s_is64bitOk = inputSurfaceSetting != 0;
}
});
- if (!s_64bitonly) {
- ALOGE("GraphicMetadataBuffer does not work in 32+64 system if compiled as 64-bit object");
+ if (!s_is64bitOk) {
+ ALOGE("GraphicMetadataBuffer does not work in 32+64 system if compiled as 64-bit object"\
+ "when debug.stagefright.c2inputsurface is set to 0");
return nullptr;
}
#endif
diff --git a/media/codec2/vndk/C2AllocatorBlob.cpp b/media/codec2/vndk/C2AllocatorBlob.cpp
index 6340cba..8cfa1d7 100644
--- a/media/codec2/vndk/C2AllocatorBlob.cpp
+++ b/media/codec2/vndk/C2AllocatorBlob.cpp
@@ -178,6 +178,8 @@
return C2_CORRUPTED;
}
+ // Note: the BLOB allocator does not support padding as this functionality is expected
+ // to be provided by the gralloc implementation.
std::shared_ptr<C2GraphicAllocation> graphicAllocation;
c2_status_t status = mC2AllocatorGralloc->newGraphicAllocation(
capacity, kLinearBufferHeight, kLinearBufferFormat, usage, &graphicAllocation);
diff --git a/media/codec2/vndk/C2AllocatorIon.cpp b/media/codec2/vndk/C2AllocatorIon.cpp
index a8528df..77b265a 100644
--- a/media/codec2/vndk/C2AllocatorIon.cpp
+++ b/media/codec2/vndk/C2AllocatorIon.cpp
@@ -417,15 +417,16 @@
buffer = -1;
}
}
- return new Impl(ionFd, allocSize, bufferFd, buffer, id, ret);
-
+ // the padding is not usable so deduct it from the advertised capacity
+ return new Impl(ionFd, allocSize - sPadding, bufferFd, buffer, id, ret);
} else {
ret = ion_alloc_fd(ionFd, allocSize, align, heapMask, flags, &bufferFd);
ALOGV("ion_alloc_fd(ionFd = %d, size = %zu, align = %zu, prot = %d, flags = %d) "
"returned (%d) ; bufferFd = %d",
ionFd, allocSize, align, heapMask, flags, ret, bufferFd);
- return new ImplV2(ionFd, allocSize, bufferFd, id, ret);
+ // the padding is not usable so deduct it from the advertised capacity
+ return new ImplV2(ionFd, allocSize - sPadding, bufferFd, id, ret);
}
}
diff --git a/media/codec2/vndk/C2DmaBufAllocator.cpp b/media/codec2/vndk/C2DmaBufAllocator.cpp
index 6d8552a..1aa3d69 100644
--- a/media/codec2/vndk/C2DmaBufAllocator.cpp
+++ b/media/codec2/vndk/C2DmaBufAllocator.cpp
@@ -111,8 +111,27 @@
virtual bool equals(const std::shared_ptr<C2LinearAllocation>& other) const override;
// internal methods
- C2DmaBufAllocation(BufferAllocator& alloc, size_t size, C2String heap_name, unsigned flags,
- C2Allocator::id_t id);
+
+ /**
+ * Constructs an allocation via a new allocation.
+ *
+ * @param alloc allocator
+ * @param allocSize size used for the allocator
+ * @param capacity capacity advertised to the client
+ * @param heap_name name of the dmabuf heap (device)
+ * @param flags flags
+ * @param id allocator id
+ */
+ C2DmaBufAllocation(BufferAllocator& alloc, size_t allocSize, size_t capacity,
+ C2String heap_name, unsigned flags, C2Allocator::id_t id);
+
+ /**
+ * Constructs an allocation by wrapping an existing allocation.
+ *
+ * @param size capacity advertised to the client
+ * @param shareFd dmabuf fd of the wrapped allocation
+ * @param id allocator id
+ */
C2DmaBufAllocation(size_t size, int shareFd, C2Allocator::id_t id);
c2_status_t status() const;
@@ -246,19 +265,19 @@
}
}
-C2DmaBufAllocation::C2DmaBufAllocation(BufferAllocator& alloc, size_t size, C2String heap_name,
- unsigned flags, C2Allocator::id_t id)
- : C2LinearAllocation(size), mHandle(-1, 0) {
+C2DmaBufAllocation::C2DmaBufAllocation(BufferAllocator& alloc, size_t allocSize, size_t capacity,
+ C2String heap_name, unsigned flags, C2Allocator::id_t id)
+ : C2LinearAllocation(capacity), mHandle(-1, 0) {
int bufferFd = -1;
int ret = 0;
- bufferFd = alloc.Alloc(heap_name, size, flags);
+ bufferFd = alloc.Alloc(heap_name, allocSize, flags);
if (bufferFd < 0) {
ret = bufferFd;
}
// this may be a non-working handle if bufferFd is negative
- mHandle = C2HandleBuf(bufferFd, size);
+ mHandle = C2HandleBuf(bufferFd, capacity);
mId = id;
mInit = c2_status_t(c2_map_errno<ENOMEM, EACCES, EINVAL>(ret));
}
@@ -381,7 +400,7 @@
size_t allocSize = (size_t)capacity + sPadding;
// TODO: should we align allocation size to mBlockSize to reflect the true allocation size?
std::shared_ptr<C2DmaBufAllocation> alloc = std::make_shared<C2DmaBufAllocation>(
- mBufferAllocator, allocSize, heap_name, flags, getId());
+ mBufferAllocator, allocSize, allocSize - sPadding, heap_name, flags, getId());
ret = alloc->status();
if (ret == C2_OK) {
*allocation = alloc;
diff --git a/media/libaaudio/src/legacy/AudioStreamLegacy.cpp b/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
index 60eb73a..e96e134 100644
--- a/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
@@ -94,10 +94,15 @@
AudioTrack::Buffer *audioBuffer = static_cast<AudioTrack::Buffer *>(info);
if (getState() == AAUDIO_STREAM_STATE_DISCONNECTED) {
ALOGW("processCallbackCommon() data, stream disconnected");
+ // This will kill the stream and prevent it from being restarted.
+ // That is OK because the stream is disconnected.
audioBuffer->size = SIZE_STOP_CALLBACKS;
} else if (!mCallbackEnabled.load()) {
- ALOGW("processCallbackCommon() no data because callback disabled");
- audioBuffer->size = SIZE_STOP_CALLBACKS;
+ ALOGW("processCallbackCommon() no data because callback disabled, set size=0");
+ // Do NOT use SIZE_STOP_CALLBACKS here because that will kill the stream and
+ // prevent it from being restarted. This can occur because of a race condition
+ // caused by Legacy callbacks running after the track is "stopped".
+ audioBuffer->size = 0;
} else {
if (audioBuffer->frameCount == 0) {
ALOGW("processCallbackCommon() data, frameCount is zero");
diff --git a/media/libstagefright/foundation/AMessage.cpp b/media/libstagefright/foundation/AMessage.cpp
index 6bb7b37..c2114b3 100644
--- a/media/libstagefright/foundation/AMessage.cpp
+++ b/media/libstagefright/foundation/AMessage.cpp
@@ -54,13 +54,11 @@
AMessage::AMessage(void)
: mWhat(0),
- mTarget(0),
- mNumItems(0) {
+ mTarget(0) {
}
AMessage::AMessage(uint32_t what, const sp<const AHandler> &handler)
- : mWhat(what),
- mNumItems(0) {
+ : mWhat(what) {
setTarget(handler);
}
@@ -89,13 +87,13 @@
}
void AMessage::clear() {
- for (size_t i = 0; i < mNumItems; ++i) {
- Item *item = &mItems[i];
- delete[] item->mName;
- item->mName = NULL;
- freeItemValue(item);
+ // Item needs to be handled delicately
+ for (Item &item : mItems) {
+ delete[] item.mName;
+ item.mName = NULL;
+ freeItemValue(&item);
}
- mNumItems = 0;
+ mItems.clear();
}
void AMessage::freeItemValue(Item *item) {
@@ -157,7 +155,7 @@
size_t memchecks = 0;
#endif
size_t i = 0;
- for (; i < mNumItems; i++) {
+ for (; i < mItems.size(); i++) {
if (len != mItems[i].mNameLength) {
continue;
}
@@ -172,7 +170,7 @@
{
Mutex::Autolock _l(gLock);
++gFindItemCalls;
- gAverageNumItems += mNumItems;
+ gAverageNumItems += mItems.size();
gAverageNumMemChecks += memchecks;
gAverageNumChecks += i;
reportStats();
@@ -188,20 +186,26 @@
memcpy((void*)mName, name, len + 1);
}
+AMessage::Item::Item(const char *name, size_t len)
+ : mType(kTypeInt32) {
+ // mName and mNameLength are initialized by setName
+ setName(name, len);
+}
+
AMessage::Item *AMessage::allocateItem(const char *name) {
size_t len = strlen(name);
size_t i = findItemIndex(name, len);
Item *item;
- if (i < mNumItems) {
+ if (i < mItems.size()) {
item = &mItems[i];
freeItemValue(item);
} else {
- CHECK(mNumItems < kMaxNumItems);
- i = mNumItems++;
+ CHECK(mItems.size() < kMaxNumItems);
+ i = mItems.size();
+ // place a 'blank' item at the end - this is of type kTypeInt32
+ mItems.emplace_back(name, len);
item = &mItems[i];
- item->mType = kTypeInt32;
- item->setName(name, len);
}
return item;
@@ -210,7 +214,7 @@
const AMessage::Item *AMessage::findItem(
const char *name, Type type) const {
size_t i = findItemIndex(name, strlen(name));
- if (i < mNumItems) {
+ if (i < mItems.size()) {
const Item *item = &mItems[i];
return item->mType == type ? item : NULL;
@@ -220,7 +224,7 @@
bool AMessage::findAsFloat(const char *name, float *value) const {
size_t i = findItemIndex(name, strlen(name));
- if (i < mNumItems) {
+ if (i < mItems.size()) {
const Item *item = &mItems[i];
switch (item->mType) {
case kTypeFloat:
@@ -247,7 +251,7 @@
bool AMessage::findAsInt64(const char *name, int64_t *value) const {
size_t i = findItemIndex(name, strlen(name));
- if (i < mNumItems) {
+ if (i < mItems.size()) {
const Item *item = &mItems[i];
switch (item->mType) {
case kTypeInt64:
@@ -265,15 +269,16 @@
bool AMessage::contains(const char *name) const {
size_t i = findItemIndex(name, strlen(name));
- return i < mNumItems;
+ return i < mItems.size();
}
#define BASIC_TYPE(NAME,FIELDNAME,TYPENAME) \
void AMessage::set##NAME(const char *name, TYPENAME value) { \
Item *item = allocateItem(name); \
- \
- item->mType = kType##NAME; \
- item->u.FIELDNAME = value; \
+ if (item) { \
+ item->mType = kType##NAME; \
+ item->u.FIELDNAME = value; \
+ } \
} \
\
/* NOLINT added to avoid incorrect warning/fix from clang.tidy */ \
@@ -298,8 +303,10 @@
void AMessage::setString(
const char *name, const char *s, ssize_t len) {
Item *item = allocateItem(name);
- item->mType = kTypeString;
- item->u.stringValue = new AString(s, len < 0 ? strlen(s) : len);
+ if (item) {
+ item->mType = kTypeString;
+ item->u.stringValue = new AString(s, len < 0 ? strlen(s) : len);
+ }
}
void AMessage::setString(
@@ -310,10 +317,12 @@
void AMessage::setObjectInternal(
const char *name, const sp<RefBase> &obj, Type type) {
Item *item = allocateItem(name);
- item->mType = type;
+ if (item) {
+ item->mType = type;
- if (obj != NULL) { obj->incStrong(this); }
- item->u.refValue = obj.get();
+ if (obj != NULL) { obj->incStrong(this); }
+ item->u.refValue = obj.get();
+ }
}
void AMessage::setObject(const char *name, const sp<RefBase> &obj) {
@@ -326,22 +335,26 @@
void AMessage::setMessage(const char *name, const sp<AMessage> &obj) {
Item *item = allocateItem(name);
- item->mType = kTypeMessage;
+ if (item) {
+ item->mType = kTypeMessage;
- if (obj != NULL) { obj->incStrong(this); }
- item->u.refValue = obj.get();
+ if (obj != NULL) { obj->incStrong(this); }
+ item->u.refValue = obj.get();
+ }
}
void AMessage::setRect(
const char *name,
int32_t left, int32_t top, int32_t right, int32_t bottom) {
Item *item = allocateItem(name);
- item->mType = kTypeRect;
+ if (item) {
+ item->mType = kTypeRect;
- item->u.rectValue.mLeft = left;
- item->u.rectValue.mTop = top;
- item->u.rectValue.mRight = right;
- item->u.rectValue.mBottom = bottom;
+ item->u.rectValue.mLeft = left;
+ item->u.rectValue.mTop = top;
+ item->u.rectValue.mRight = right;
+ item->u.rectValue.mBottom = bottom;
+ }
}
bool AMessage::findString(const char *name, AString *value) const {
@@ -466,18 +479,18 @@
sp<AMessage> AMessage::dup() const {
sp<AMessage> msg = new AMessage(mWhat, mHandler.promote());
- msg->mNumItems = mNumItems;
+ msg->mItems = mItems;
#ifdef DUMP_STATS
{
Mutex::Autolock _l(gLock);
++gDupCalls;
- gAverageDupItems += mNumItems;
+ gAverageDupItems += mItems.size();
reportStats();
}
#endif
- for (size_t i = 0; i < mNumItems; ++i) {
+ for (size_t i = 0; i < mItems.size(); ++i) {
const Item *from = &mItems[i];
Item *to = &msg->mItems[i];
@@ -560,7 +573,7 @@
}
s.append(") = {\n");
- for (size_t i = 0; i < mNumItems; ++i) {
+ for (size_t i = 0; i < mItems.size(); ++i) {
const Item &item = mItems[i];
switch (item.mType) {
@@ -653,19 +666,20 @@
sp<AMessage> msg = new AMessage();
msg->setWhat(what);
- msg->mNumItems = static_cast<size_t>(parcel.readInt32());
- if (msg->mNumItems > kMaxNumItems) {
+ size_t numItems = static_cast<size_t>(parcel.readInt32());
+ if (numItems > kMaxNumItems) {
ALOGE("Too large number of items clipped.");
- msg->mNumItems = kMaxNumItems;
+ numItems = kMaxNumItems;
}
+ msg->mItems.resize(numItems);
- for (size_t i = 0; i < msg->mNumItems; ++i) {
+ for (size_t i = 0; i < msg->mItems.size(); ++i) {
Item *item = &msg->mItems[i];
const char *name = parcel.readCString();
if (name == NULL) {
ALOGE("Failed reading name for an item. Parsing aborted.");
- msg->mNumItems = i;
+ msg->mItems.resize(i);
break;
}
@@ -709,7 +723,7 @@
if (stringValue == NULL) {
ALOGE("Failed reading string value from a parcel. "
"Parsing aborted.");
- msg->mNumItems = i;
+ msg->mItems.resize(i);
continue;
// The loop will terminate subsequently.
} else {
@@ -754,11 +768,9 @@
void AMessage::writeToParcel(Parcel *parcel) const {
parcel->writeInt32(static_cast<int32_t>(mWhat));
- parcel->writeInt32(static_cast<int32_t>(mNumItems));
+ parcel->writeInt32(static_cast<int32_t>(mItems.size()));
- for (size_t i = 0; i < mNumItems; ++i) {
- const Item &item = mItems[i];
-
+ for (const Item &item : mItems) {
parcel->writeCString(item.mName);
parcel->writeInt32(static_cast<int32_t>(item.mType));
@@ -828,8 +840,7 @@
diff->setTarget(mHandler.promote());
}
- for (size_t i = 0; i < mNumItems; ++i) {
- const Item &item = mItems[i];
+ for (const Item &item : mItems) {
const Item *oitem = other->findItem(item.mName, item.mType);
switch (item.mType) {
case kTypeInt32:
@@ -936,11 +947,11 @@
}
size_t AMessage::countEntries() const {
- return mNumItems;
+ return mItems.size();
}
const char *AMessage::getEntryNameAt(size_t index, Type *type) const {
- if (index >= mNumItems) {
+ if (index >= mItems.size()) {
*type = kTypeInt32;
return NULL;
@@ -953,7 +964,7 @@
AMessage::ItemData AMessage::getEntryAt(size_t index) const {
ItemData it;
- if (index < mNumItems) {
+ if (index < mItems.size()) {
switch (mItems[index].mType) {
case kTypeInt32: it.set(mItems[index].u.int32Value); break;
case kTypeInt64: it.set(mItems[index].u.int64Value); break;
@@ -986,7 +997,7 @@
}
status_t AMessage::setEntryNameAt(size_t index, const char *name) {
- if (index >= mNumItems) {
+ if (index >= mItems.size()) {
return BAD_INDEX;
}
if (name == nullptr) {
@@ -996,7 +1007,7 @@
return OK; // name has not changed
}
size_t len = strlen(name);
- if (findItemIndex(name, len) < mNumItems) {
+ if (findItemIndex(name, len) < mItems.size()) {
return ALREADY_EXISTS;
}
delete[] mItems[index].mName;
@@ -1011,7 +1022,7 @@
sp<AMessage> msgValue;
sp<ABuffer> bufValue;
- if (index >= mNumItems) {
+ if (index >= mItems.size()) {
return BAD_INDEX;
}
if (!item.used()) {
@@ -1060,21 +1071,22 @@
}
status_t AMessage::removeEntryAt(size_t index) {
- if (index >= mNumItems) {
+ if (index >= mItems.size()) {
return BAD_INDEX;
}
// delete entry data and objects
- --mNumItems;
delete[] mItems[index].mName;
mItems[index].mName = nullptr;
freeItemValue(&mItems[index]);
// swap entry with last entry and clear last entry's data
- if (index < mNumItems) {
- mItems[index] = mItems[mNumItems];
- mItems[mNumItems].mName = nullptr;
- mItems[mNumItems].mType = kTypeInt32;
+ size_t lastIndex = mItems.size() - 1;
+ if (index < lastIndex) {
+ mItems[index] = mItems[lastIndex];
+ mItems[lastIndex].mName = nullptr;
+ mItems[lastIndex].mType = kTypeInt32;
}
+ mItems.pop_back();
return OK;
}
@@ -1083,7 +1095,7 @@
return BAD_VALUE;
}
size_t index = findEntryByName(name);
- if (index >= mNumItems) {
+ if (index >= mItems.size()) {
return BAD_INDEX;
}
return removeEntryAt(index);
@@ -1093,7 +1105,7 @@
if (item.used()) {
Item *it = allocateItem(name);
if (it != nullptr) {
- setEntryAt(it - mItems, item);
+ setEntryAt(it - &mItems[0], item);
}
}
}
@@ -1108,11 +1120,11 @@
return;
}
- for (size_t ix = 0; ix < other->mNumItems; ++ix) {
+ for (size_t ix = 0; ix < other->mItems.size(); ++ix) {
Item *it = allocateItem(other->mItems[ix].mName);
if (it != nullptr) {
ItemData data = other->getEntryAt(ix);
- setEntryAt(it - mItems, data);
+ setEntryAt(it - &mItems[0], data);
}
}
}
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/AMessage.h b/media/libstagefright/foundation/include/media/stagefright/foundation/AMessage.h
index 98d6147..960212a 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/AMessage.h
+++ b/media/libstagefright/foundation/include/media/stagefright/foundation/AMessage.h
@@ -24,6 +24,8 @@
#include <utils/KeyedVector.h>
#include <utils/RefBase.h>
+#include <vector>
+
namespace android {
struct ABuffer;
@@ -95,6 +97,7 @@
void setTarget(const sp<const AHandler> &handler);
+ // removes all items
void clear();
void setInt32(const char *name, int32_t value);
@@ -302,16 +305,39 @@
size_t mNameLength;
Type mType;
void setName(const char *name, size_t len);
+ Item() : mName(nullptr), mNameLength(0), mType(kTypeInt32) { }
+ Item(const char *name, size_t length);
};
enum {
- kMaxNumItems = 64
+ kMaxNumItems = 256
};
- Item mItems[kMaxNumItems];
- size_t mNumItems;
+ std::vector<Item> mItems;
+ /**
+ * Allocates an item with the given key |name|. If the key already exists, the corresponding
+ * item value is freed. Otherwise a new item is added.
+ *
+ * This method currently asserts if the number of elements would exceed the max number of
+ * elements allowed (kMaxNumItems). This is a security precaution to avoid arbitrarily large
+ * AMessage structures.
+ *
+ * @todo(b/192153245) Either revisit this security precaution, or change the behavior to
+ * silently ignore keys added after the max number of elements are reached.
+ *
+ * @note All previously returned Item* pointers are deemed invalid after this call. (E.g. from
+ * allocateItem or findItem)
+ *
+ * @param name the key for the requested item.
+ *
+ * @return Item* a pointer to the item.
+ */
Item *allocateItem(const char *name);
+
+ /** Frees the value for the item. */
void freeItemValue(Item *item);
+
+ /** Finds an item with given key |name| and |type|. Returns nullptr if item is not found. */
const Item *findItem(const char *name, Type type) const;
void setObjectInternal(
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 578a32f..aefc75e 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -779,16 +779,21 @@
}
lines = String8(" In-flight requests:\n");
- if (mInFlightMap.size() == 0) {
- lines.append(" None\n");
- } else {
- for (size_t i = 0; i < mInFlightMap.size(); i++) {
- InFlightRequest r = mInFlightMap.valueAt(i);
- lines.appendFormat(" Frame %d | Timestamp: %" PRId64 ", metadata"
- " arrived: %s, buffers left: %d\n", mInFlightMap.keyAt(i),
- r.shutterTimestamp, r.haveResultMetadata ? "true" : "false",
- r.numBuffersLeft);
+ if (mInFlightLock.try_lock()) {
+ if (mInFlightMap.size() == 0) {
+ lines.append(" None\n");
+ } else {
+ for (size_t i = 0; i < mInFlightMap.size(); i++) {
+ InFlightRequest r = mInFlightMap.valueAt(i);
+ lines.appendFormat(" Frame %d | Timestamp: %" PRId64 ", metadata"
+ " arrived: %s, buffers left: %d\n", mInFlightMap.keyAt(i),
+ r.shutterTimestamp, r.haveResultMetadata ? "true" : "false",
+ r.numBuffersLeft);
+ }
}
+ mInFlightLock.unlock();
+ } else {
+ lines.append(" Failed to acquire In-flight lock!\n");
}
write(fd, lines.string(), lines.size());