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)",