Merge changes from topic "foldable_orientation" into sc-v2-dev
* changes:
Camera: Only override rotate&crop for Camera2 clients
Camera: Allow dynamic sensor orientation updates
diff --git a/media/codec2/components/mp3/C2SoftMp3Dec.cpp b/media/codec2/components/mp3/C2SoftMp3Dec.cpp
index 30d7394..e394670 100644
--- a/media/codec2/components/mp3/C2SoftMp3Dec.cpp
+++ b/media/codec2/components/mp3/C2SoftMp3Dec.cpp
@@ -406,7 +406,7 @@
mConfig->inputBufferCurrentLength = (inSize - inPos);
mConfig->inputBufferMaxLength = 0;
mConfig->inputBufferUsedLength = 0;
- mConfig->outputFrameSize = (calOutSize - outSize);
+ mConfig->outputFrameSize = (calOutSize - outSize) / sizeof(int16_t);
mConfig->pOutputBuffer = reinterpret_cast<int16_t *> (wView.data() + outSize);
ERROR_CODE decoderErr;
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index e9adfc9..307396b 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -19,6 +19,7 @@
#include <utils/Log.h>
#include <algorithm>
+#include <atomic>
#include <list>
#include <numeric>
@@ -155,6 +156,7 @@
input->pipelineDelay = 0u;
input->numSlots = kSmoothnessFactor;
input->numExtraSlots = 0u;
+ input->lastFlushIndex = 0u;
}
{
Mutexed<Output>::Locked output(mOutput);
@@ -1116,6 +1118,7 @@
input->numSlots = numInputSlots;
input->extraBuffers.flush();
input->numExtraSlots = 0u;
+ input->lastFlushIndex = mFrameIndex.load(std::memory_order_relaxed);
if (audioEncoder && encoderFrameSize && sampleRate && channelCount) {
input->frameReassembler.init(
pool,
@@ -1523,6 +1526,7 @@
ALOGV("[%s] flush", mName);
std::vector<uint64_t> indices;
std::list<std::unique_ptr<C2Work>> configs;
+ mInput.lock()->lastFlushIndex = mFrameIndex.load(std::memory_order_relaxed);
for (const std::unique_ptr<C2Work> &work : flushedWork) {
indices.push_back(work->input.ordinal.frameIndex.peeku());
if (!(work->input.flags & C2FrameData::FLAG_CODEC_CONFIG)) {
@@ -1589,12 +1593,18 @@
}
std::shared_ptr<C2Buffer> buffer =
mPipelineWatcher.lock()->onInputBufferReleased(frameIndex, arrayIndex);
- bool newInputSlotAvailable;
+ bool newInputSlotAvailable = false;
{
Mutexed<Input>::Locked input(mInput);
- newInputSlotAvailable = input->buffers->expireComponentBuffer(buffer);
- if (!newInputSlotAvailable) {
- (void)input->extraBuffers.expireComponentBuffer(buffer);
+ if (input->lastFlushIndex >= frameIndex) {
+ ALOGD("[%s] Ignoring stale input buffer done callback: "
+ "last flush index = %lld, frameIndex = %lld",
+ mName, input->lastFlushIndex.peekll(), (long long)frameIndex);
+ } else {
+ newInputSlotAvailable = input->buffers->expireComponentBuffer(buffer);
+ if (!newInputSlotAvailable) {
+ (void)input->extraBuffers.expireComponentBuffer(buffer);
+ }
}
}
if (newInputSlotAvailable) {
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.h b/media/codec2/sfplugin/CCodecBufferChannel.h
index 5a2aca2..4db69cb 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.h
+++ b/media/codec2/sfplugin/CCodecBufferChannel.h
@@ -273,6 +273,7 @@
size_t numExtraSlots;
uint32_t inputDelay;
uint32_t pipelineDelay;
+ c2_cntr64_t lastFlushIndex;
FrameReassembler frameReassembler;
};
diff --git a/media/codecs/m4v_h263/enc/src/mp4enc_api.cpp b/media/codecs/m4v_h263/enc/src/mp4enc_api.cpp
index 234faef..00b2ab6 100644
--- a/media/codecs/m4v_h263/enc/src/mp4enc_api.cpp
+++ b/media/codecs/m4v_h263/enc/src/mp4enc_api.cpp
@@ -610,18 +610,19 @@
/* Find the maximum width*height for memory allocation of the VOPs */
for (idx = 0; idx < nLayers; idx++)
{
- temp_w = video->encParams->LayerWidth[idx];
- temp_h = video->encParams->LayerHeight[idx];
+ temp_w = ((video->encParams->LayerWidth[idx] + 15) >> 4) << 4;
+ temp_h = ((video->encParams->LayerHeight[idx] + 15) >> 4) << 4;
+
+ if (temp_w > 2048 || temp_h > 2048) {
+ goto CLEAN_UP;
+ }
if ((temp_w*temp_h) > max)
{
max = temp_w * temp_h;
- max_width = ((temp_w + 15) >> 4) << 4;
- max_height = ((temp_h + 15) >> 4) << 4;
- if (((uint64_t)max_width * max_height) > (uint64_t)INT32_MAX
- || temp_w > INT32_MAX - 15 || temp_h > INT32_MAX - 15) {
- goto CLEAN_UP;
- }
+ max_width = temp_w;
+ max_height = temp_h;
+
nTotalMB = ((max_width * max_height) >> 8);
}
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index fbcd554..8836c47 100644
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -157,6 +157,7 @@
MediaBufferHelper *mBuffer;
+ size_t mSrcBufferSize;
uint8_t *mSrcBuffer;
bool mIsHeif;
@@ -5083,6 +5084,7 @@
mNALLengthSize(0),
mStarted(false),
mBuffer(NULL),
+ mSrcBufferSize(0),
mSrcBuffer(NULL),
mItemTable(itemTable),
mElstShiftStartTicks(elstShiftStartTicks),
@@ -5264,6 +5266,7 @@
// file probably specified a bad max size
return AMEDIA_ERROR_MALFORMED;
}
+ mSrcBufferSize = max_size;
mStarted = true;
@@ -5280,6 +5283,7 @@
mBuffer = NULL;
}
+ mSrcBufferSize = 0;
delete[] mSrcBuffer;
mSrcBuffer = NULL;
@@ -6467,13 +6471,19 @@
// Whole NAL units are returned but each fragment is prefixed by
// the start code (0x00 00 00 01).
ssize_t num_bytes_read = 0;
- num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size);
+ bool mSrcBufferFitsDataToRead = size <= mSrcBufferSize;
+ if (mSrcBufferFitsDataToRead) {
+ num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size);
+ } else {
+ // We are trying to read a sample larger than the expected max sample size.
+ // Fall through and let the failure be handled by the following if.
+ android_errorWriteLog(0x534e4554, "188893559");
+ }
if (num_bytes_read < (ssize_t)size) {
mBuffer->release();
mBuffer = NULL;
-
- return AMEDIA_ERROR_IO;
+ return mSrcBufferFitsDataToRead ? AMEDIA_ERROR_IO : AMEDIA_ERROR_MALFORMED;
}
uint8_t *dstData = (uint8_t *)mBuffer->data();
diff --git a/media/libeffects/downmix/EffectDownmix.cpp b/media/libeffects/downmix/EffectDownmix.cpp
index 90bb410..d8f5787 100644
--- a/media/libeffects/downmix/EffectDownmix.cpp
+++ b/media/libeffects/downmix/EffectDownmix.cpp
@@ -188,9 +188,11 @@
if (!mask) {
return false;
}
- // check against unsupported channels
- if (mask & ~AUDIO_CHANNEL_OUT_22POINT2) {
- ALOGE("Unsupported channels in %u", mask & ~AUDIO_CHANNEL_OUT_22POINT2);
+ // check against unsupported channels (up to FCC_26)
+ constexpr uint32_t MAXIMUM_CHANNEL_MASK = AUDIO_CHANNEL_OUT_22POINT2
+ | AUDIO_CHANNEL_OUT_FRONT_WIDE_LEFT | AUDIO_CHANNEL_OUT_FRONT_WIDE_RIGHT;
+ if (mask & ~MAXIMUM_CHANNEL_MASK) {
+ ALOGE("Unsupported channels in %#x", mask & ~MAXIMUM_CHANNEL_MASK);
return false;
}
return true;
@@ -647,6 +649,12 @@
ALOGE("Downmix_Configure error: invalid config");
return -EINVAL;
}
+ // when configuring the effect, do not allow a blank or unsupported channel mask
+ if (!Downmix_validChannelMask(pConfig->inputCfg.channels)) {
+ ALOGE("Downmix_Configure error: input channel mask(0x%x) not supported",
+ pConfig->inputCfg.channels);
+ return -EINVAL;
+ }
if (&pDwmModule->config != pConfig) {
memcpy(&pDwmModule->config, pConfig, sizeof(effect_config_t));
@@ -657,12 +665,6 @@
pDownmixer->apply_volume_correction = false;
pDownmixer->input_channel_count = 8; // matches default input of AUDIO_CHANNEL_OUT_7POINT1
} else {
- // when configuring the effect, do not allow a blank or unsupported channel mask
- if (!Downmix_validChannelMask(pConfig->inputCfg.channels)) {
- ALOGE("Downmix_Configure error: input channel mask(0x%x) not supported",
- pConfig->inputCfg.channels);
- return -EINVAL;
- }
pDownmixer->input_channel_count =
audio_channel_count_from_out_mask(pConfig->inputCfg.channels);
}
diff --git a/media/libeffects/downmix/tests/downmix_tests.cpp b/media/libeffects/downmix/tests/downmix_tests.cpp
index 26c7c31..20e19a3 100644
--- a/media/libeffects/downmix/tests/downmix_tests.cpp
+++ b/media/libeffects/downmix/tests/downmix_tests.cpp
@@ -50,6 +50,8 @@
AUDIO_CHANNEL_OUT_7POINT1POINT4,
AUDIO_CHANNEL_OUT_13POINT_360RA,
AUDIO_CHANNEL_OUT_22POINT2,
+ audio_channel_mask_t(AUDIO_CHANNEL_OUT_22POINT2
+ | AUDIO_CHANNEL_OUT_FRONT_WIDE_LEFT | AUDIO_CHANNEL_OUT_FRONT_WIDE_RIGHT),
};
constexpr float COEF_25 = 0.2508909536f;
@@ -82,6 +84,8 @@
M_SQRT1_2, // AUDIO_CHANNEL_OUT_BOTTOM_FRONT_CENTER = 0x200000u,
0.f, // AUDIO_CHANNEL_OUT_BOTTOM_FRONT_RIGHT = 0x400000u,
0.f, // AUDIO_CHANNEL_OUT_LOW_FREQUENCY_2 = 0x800000u,
+ M_SQRT1_2, // AUDIO_CHANNEL_OUT_FRONT_WIDE_LEFT = 0x1000000u,
+ 0.f, // AUDIO_CHANNEL_OUT_FRONT_WIDE_RIGHT = 0x2000000u,
};
constexpr inline float kScaleFromChannelIdxRight[] = {
@@ -109,6 +113,8 @@
M_SQRT1_2, // AUDIO_CHANNEL_OUT_BOTTOM_FRONT_CENTER = 0x200000u,
1.f, // AUDIO_CHANNEL_OUT_BOTTOM_FRONT_RIGHT = 0x400000u,
M_SQRT1_2, // AUDIO_CHANNEL_OUT_LOW_FREQUENCY_2 = 0x800000u,
+ 0.f, // AUDIO_CHANNEL_OUT_FRONT_WIDE_LEFT = 0x1000000u,
+ M_SQRT1_2, // AUDIO_CHANNEL_OUT_FRONT_WIDE_RIGHT = 0x2000000u,
};
// Downmix doesn't change with sample rate
@@ -156,7 +162,7 @@
double savedPower[32][2]{};
for (unsigned i = 0, channel = channelMask; channel != 0; ++i) {
const int index = __builtin_ctz(channel);
- ASSERT_LT(index, FCC_24);
+ ASSERT_LT(index, FCC_26);
const int pairIndex = pairIdxFromChannelIdx(index);
const AUDIO_GEOMETRY_SIDE side = sideFromChannelIdx(index);
const int channelBit = 1 << index;
@@ -243,6 +249,7 @@
handle_, EFFECT_CMD_SET_CONFIG,
sizeof(effect_config_t), &config_, &replySize, &reply);
ASSERT_EQ(0, err);
+ ASSERT_EQ(0, reply);
err = (downmixApi->command)(
handle_, EFFECT_CMD_ENABLE,
0, nullptr, &replySize, &reply);
@@ -253,6 +260,27 @@
ASSERT_EQ(0, err);
}
+ // This test assumes the channel mask is invalid.
+ void testInvalidChannelMask(audio_channel_mask_t invalidChannelMask) {
+ reconfig(48000 /* sampleRate */, invalidChannelMask);
+ const int32_t sessionId = 0;
+ const int32_t ioId = 0;
+ int32_t err = AUDIO_EFFECT_LIBRARY_INFO_SYM.create_effect(
+ &downmix_uuid_, sessionId, ioId, &handle_);
+ ASSERT_EQ(0, err);
+
+ const struct effect_interface_s * const downmixApi = *handle_;
+ int32_t reply = 0;
+ uint32_t replySize = (uint32_t)sizeof(reply);
+ err = (downmixApi->command)(
+ handle_, EFFECT_CMD_SET_CONFIG,
+ sizeof(effect_config_t), &config_, &replySize, &reply);
+ ASSERT_EQ(0, err);
+ ASSERT_NE(0, reply); // error has occurred.
+ err = AUDIO_EFFECT_LIBRARY_INFO_SYM.release_effect(handle_);
+ ASSERT_EQ(0, err);
+ }
+
private:
void reconfig(int sampleRate, audio_channel_mask_t channelMask) {
config_.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
@@ -299,6 +327,16 @@
int inputChannelCount_{};
};
+TEST(DownmixTestSimple, invalidChannelMask) {
+ // Fill in a dummy test method to use DownmixTest outside of a parameterized test.
+ class DownmixTestComplete : public DownmixTest {
+ void TestBody() override {}
+ } downmixtest;
+
+ constexpr auto INVALID_CHANNEL_MASK = audio_channel_mask_t(1 << 31);
+ downmixtest.testInvalidChannelMask(INVALID_CHANNEL_MASK);
+}
+
TEST_P(DownmixTest, basic) {
testBalance(kSampleRates[std::get<0>(GetParam())],
kChannelPositionMasks[std::get<1>(GetParam())]);
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 5795dcf..f51ebce 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -2055,6 +2055,11 @@
id.string());
errorCode = ERROR_ILLEGAL_ARGUMENT;
break;
+ case -EBUSY:
+ msg = String8::format("Camera \"%s\" is in use",
+ id.string());
+ errorCode = ERROR_CAMERA_IN_USE;
+ break;
default:
msg = String8::format(
"Setting torch mode of camera \"%s\" to %d failed: %s (%d)",