Merge "Camera: Flush all state transitions before reconfigureCamera" into udc-qpr-dev
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index af00e55..4a589bc 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -584,6 +584,13 @@
* <p>Only constrains auto-exposure (AE) algorithm, not
* manual control of ACAMERA_SENSOR_EXPOSURE_TIME and
* ACAMERA_SENSOR_FRAME_DURATION.</p>
+ * <p>To start a CaptureSession with a target FPS range different from the
+ * capture request template's default value, the application
+ * is strongly recommended to call
+ * {@link ACameraDevice_createCaptureSessionWithSessionParameters }
+ * with the target fps range before creating the capture session. The aeTargetFpsRange is
+ * typically a session parameter. Specifying it at session creation time helps avoid
+ * session reconfiguration delays in cases like 60fps or high speed recording.</p>
*
* @see ACAMERA_SENSOR_EXPOSURE_TIME
* @see ACAMERA_SENSOR_FRAME_DURATION
@@ -1128,6 +1135,12 @@
* ACAMERA_CONTROL_VIDEO_STABILIZATION_MODE field will return
* OFF if the recording output is not stabilized, or if there are no output
* Surface types that can be stabilized.</p>
+ * <p>The application is strongly recommended to call
+ * {@link ACameraDevice_createCaptureSessionWithSessionParameters }
+ * with the desired video stabilization mode before creating the capture session.
+ * Video stabilization mode is a session parameter on many devices. Specifying
+ * it at session creation time helps avoid reconfiguration delay caused by difference
+ * between the default value and the first CaptureRequest.</p>
* <p>If a camera device supports both this mode and OIS
* (ACAMERA_LENS_OPTICAL_STABILIZATION_MODE), turning both modes on may
* produce undesirable interaction, so it is recommended not to enable
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp b/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
index d47ef67..8b0ea91 100644
--- a/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
+++ b/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
@@ -341,7 +341,7 @@
ASSERT_TRUE(false) << "Wait for generating C2Work exceeded timeout";
}
int64_t timestamp = (*Info)[frameID].timestamp;
- if ((*Info)[frameID].flags) flags = 1u << ((*Info)[frameID].flags - 1);
+ flags = ((*Info)[frameID].flags == FLAG_CONFIG_DATA) ? C2FrameData::FLAG_CODEC_CONFIG : 0;
if (signalEOS && ((frameID == (int)Info->size() - 1) || (frameID == (offset + range - 1))))
flags |= C2FrameData::FLAG_END_OF_STREAM;
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h b/media/codec2/hal/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h
index 2222aaf..ecab0cb 100644
--- a/media/codec2/hal/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h
+++ b/media/codec2/hal/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h
@@ -28,6 +28,8 @@
#include <fstream>
#define FLAG_NON_DISPLAY_FRAME (1 << 4)
+#define FLAG_CONFIG_DATA (1 << 5)
+
#define MAX_RETRY 20
#define TIME_OUT 400ms
#define MAX_INPUT_BUFFERS 8
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp b/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
index 117d9ca..386e81b 100644
--- a/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
+++ b/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
@@ -459,7 +459,8 @@
ASSERT_TRUE(false) << "Wait for generating C2Work exceeded timeout";
}
int64_t timestamp = (*Info)[frameID].timestamp;
- if ((*Info)[frameID].flags) flags = (1 << ((*Info)[frameID].flags - 1));
+
+ flags = ((*Info)[frameID].flags == FLAG_CONFIG_DATA) ? C2FrameData::FLAG_CODEC_CONFIG : 0;
if (signalEOS && ((frameID == (int)Info->size() - 1) || (frameID == (offset + range - 1))))
flags |= C2FrameData::FLAG_END_OF_STREAM;
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index a75ce70..1153fb6 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -2137,7 +2137,7 @@
}
std::map<size_t, sp<MediaCodecBuffer>> clientInputBuffers;
- status_t err = mChannel->prepareInitialInputBuffers(&clientInputBuffers);
+ status_t err = mChannel->prepareInitialInputBuffers(&clientInputBuffers, true);
if (err != OK) {
if (err == NO_MEMORY) {
// NO_MEMORY happens here when all the buffers are still
@@ -2160,7 +2160,6 @@
const std::unique_ptr<Config> &config = *configLocked;
return config->mBuffersBoundToCodec;
}());
-
{
Mutexed<State>::Locked state(mState);
if (state->get() != RESUMING) {
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index feca03d..fea9cb9 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -25,6 +25,8 @@
#include <atomic>
#include <list>
#include <numeric>
+#include <thread>
+#include <chrono>
#include <C2AllocatorGralloc.h>
#include <C2PlatformSupport.h>
@@ -1042,6 +1044,15 @@
if (desiredRenderTimeNs < nowNs) {
desiredRenderTimeNs = nowNs;
}
+
+ // If the render time is more than a second from now, then pretend the frame is supposed to be
+ // rendered immediately, because that's what SurfaceFlinger heuristics will do. This is a tight
+ // coupling, but is really the only way to optimize away unnecessary present fence checks in
+ // processRenderedFrames.
+ if (desiredRenderTimeNs > nowNs + 1*1000*1000*1000LL) {
+ desiredRenderTimeNs = nowNs;
+ }
+
// We've just queued a frame to the surface, so keep track of it and later check to see if it is
// actually rendered.
TrackedFrame frame;
@@ -1614,22 +1625,31 @@
}
status_t CCodecBufferChannel::prepareInitialInputBuffers(
- std::map<size_t, sp<MediaCodecBuffer>> *clientInputBuffers) {
+ std::map<size_t, sp<MediaCodecBuffer>> *clientInputBuffers, bool retry) {
if (mInputSurface) {
return OK;
}
size_t numInputSlots = mInput.lock()->numSlots;
-
- {
- Mutexed<Input>::Locked input(mInput);
- while (clientInputBuffers->size() < numInputSlots) {
- size_t index;
- sp<MediaCodecBuffer> buffer;
- if (!input->buffers->requestNewBuffer(&index, &buffer)) {
- break;
+ int retryCount = 1;
+ for (; clientInputBuffers->empty() && retryCount >= 0; retryCount--) {
+ {
+ Mutexed<Input>::Locked input(mInput);
+ while (clientInputBuffers->size() < numInputSlots) {
+ size_t index;
+ sp<MediaCodecBuffer> buffer;
+ if (!input->buffers->requestNewBuffer(&index, &buffer)) {
+ break;
+ }
+ clientInputBuffers->emplace(index, buffer);
}
- clientInputBuffers->emplace(index, buffer);
+ }
+ if (!retry || (retryCount <= 0)) {
+ break;
+ }
+ if (clientInputBuffers->empty()) {
+ // wait: buffer may be in transit from component.
+ std::this_thread::sleep_for(std::chrono::milliseconds(4));
}
}
if (clientInputBuffers->empty()) {
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.h b/media/codec2/sfplugin/CCodecBufferChannel.h
index 41f5ae2..f60b6fa 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.h
+++ b/media/codec2/sfplugin/CCodecBufferChannel.h
@@ -140,7 +140,8 @@
* initial input buffers.
*/
status_t prepareInitialInputBuffers(
- std::map<size_t, sp<MediaCodecBuffer>> *clientInputBuffers);
+ std::map<size_t, sp<MediaCodecBuffer>> *clientInputBuffers,
+ bool retry = false);
/**
* Request initial input buffers as prepared in clientInputBuffers.
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index d506ee5..189de9b 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -1592,6 +1592,15 @@
if (desiredRenderTimeNs < nowNs) {
desiredRenderTimeNs = nowNs;
}
+
+ // If the render time is more than a second from now, then pretend the frame is supposed to be
+ // rendered immediately, because that's what SurfaceFlinger heuristics will do. This is a tight
+ // coupling, but is really the only way to optimize away unnecessary present fence checks in
+ // processRenderedFrames.
+ if (desiredRenderTimeNs > nowNs + 1*1000*1000*1000LL) {
+ desiredRenderTimeNs = nowNs;
+ }
+
// We've just queued a frame to the surface, so keep track of it and later check to see if it is
// actually rendered.
TrackedFrame frame;
diff --git a/media/libstagefright/colorconversion/ColorConverter.cpp b/media/libstagefright/colorconversion/ColorConverter.cpp
index f91a8b2..6c26c28 100644
--- a/media/libstagefright/colorconversion/ColorConverter.cpp
+++ b/media/libstagefright/colorconversion/ColorConverter.cpp
@@ -363,6 +363,7 @@
int32_t _g_u;
int32_t _g_v;
int32_t _b_u;
+ int32_t _c16; // 16 for limited range matrix, 0 for full rance
};
/*
@@ -425,18 +426,18 @@
*
* clip range 8-bit: [-277, 535], 10-bit: [-1111, 2155]
*/
-const struct ColorConverter::Coeffs BT601_FULL = { 256, 359, 88, 183, 454 };
-const struct ColorConverter::Coeffs BT601_LIMITED = { 298, 409, 100, 208, 516 };
-const struct ColorConverter::Coeffs BT601_LTD_10BIT = { 299, 410, 101, 209, 518 };
+const struct ColorConverter::Coeffs BT601_FULL = { 256, 359, 88, 183, 454, 0 };
+const struct ColorConverter::Coeffs BT601_LIMITED = { 298, 409, 100, 208, 516, 16 };
+const struct ColorConverter::Coeffs BT601_LTD_10BIT = { 299, 410, 101, 209, 518, 16 };
/**
* BT.709: K_R = 0.2126; K_B = 0.0722
*
* clip range 8-bit: [-289, 547], 10-bit: [-1159, 2202]
*/
-const struct ColorConverter::Coeffs BT709_FULL = { 256, 403, 48, 120, 475 };
-const struct ColorConverter::Coeffs BT709_LIMITED = { 298, 459, 55, 136, 541 };
-const struct ColorConverter::Coeffs BT709_LTD_10BIT = { 290, 460, 55, 137, 542 };
+const struct ColorConverter::Coeffs BT709_FULL = { 256, 403, 48, 120, 475, 0 };
+const struct ColorConverter::Coeffs BT709_LIMITED = { 298, 459, 55, 136, 541, 16 };
+const struct ColorConverter::Coeffs BT709_LTD_10BIT = { 299, 460, 55, 137, 542, 16 };
/**
* BT.2020: K_R = 0.2627; K_B = 0.0593
@@ -445,9 +446,9 @@
*
* This is the largest clip range.
*/
-const struct ColorConverter::Coeffs BT2020_FULL = { 256, 377, 42, 146, 482 };
-const struct ColorConverter::Coeffs BT2020_LIMITED = { 298, 430, 48, 167, 548 };
-const struct ColorConverter::Coeffs BT2020_LTD_10BIT = { 299, 431, 48, 167, 550 };
+const struct ColorConverter::Coeffs BT2020_FULL = { 256, 377, 42, 146, 482, 0 };
+const struct ColorConverter::Coeffs BT2020_LIMITED = { 298, 430, 48, 167, 548, 16 };
+const struct ColorConverter::Coeffs BT2020_LTD_10BIT = { 299, 431, 48, 167, 550, 16 };
constexpr int CLIP_RANGE_MIN_8BIT = -294;
constexpr int CLIP_RANGE_MAX_8BIT = 552;
@@ -781,7 +782,7 @@
signed _neg_g_v = -matrix->_g_v;
signed _r_v = matrix->_r_v;
signed _y = matrix->_y;
- signed _c16 = mSrcColorSpace.mRange == ColorUtils::kColorRangeLimited ? 16 : 0;
+ signed _c16 = matrix->_c16;
uint8_t *kAdjustedClip = initClip();
@@ -1257,6 +1258,7 @@
signed _neg_g_v = -matrix->_g_v;
signed _r_v = matrix->_r_v;
signed _y = matrix->_y;
+ signed _c16 = matrix->_c16;
uint8_t *dst_ptr = (uint8_t *)dst.mBits
+ dst.mCropTop * dst.mStride + dst.mCropLeft * dst.mBpp;
@@ -1275,13 +1277,12 @@
//TODO: optimize for chroma sampling, reading and writing multiple pixels
// within the same loop
- signed _c16 = 0;
+
void *kAdjustedClip = nullptr;
if (mSrcImage->getBitDepth() != ImageBitDepth8) {
ALOGE("BitDepth != 8 for MediaImage2");
return ERROR_UNSUPPORTED;
}
- _c16 = mSrcColorSpace.mRange == ColorUtils::kColorRangeLimited ? 16 : 0;
kAdjustedClip = initClip();
auto writeToDst = getWriteToDst(mDstFormat, (void *)kAdjustedClip);
@@ -1388,7 +1389,7 @@
signed _neg_g_v = -matrix->_g_v;
signed _r_v = matrix->_r_v;
signed _y = matrix->_y;
- signed _c16 = mSrcColorSpace.mRange == ColorUtils::kColorRangeLimited ? 16 : 0;
+ signed _c16 = matrix->_c16;
uint8_t *kAdjustedClip = initClip();
@@ -1463,7 +1464,7 @@
signed _neg_g_v = -matrix->_g_v;
signed _r_v = matrix->_r_v;
signed _y = matrix->_y;
- signed _c16 = mSrcColorSpace.mRange == ColorUtils::kColorRangeLimited ? 64 : 0;
+ signed _c64 = matrix->_c16 * 4;
uint16_t *kAdjustedClip10bit = initClip10Bit();
@@ -1483,8 +1484,8 @@
for (size_t y = 0; y < src.cropHeight(); ++y) {
for (size_t x = 0; x < src.cropWidth(); x += 2) {
signed y1, y2, u, v;
- y1 = (src_y[x] >> 6) - _c16;
- y2 = (src_y[x + 1] >> 6) - _c16;
+ y1 = (src_y[x] >> 6) - _c64;
+ y2 = (src_y[x + 1] >> 6) - _c64;
u = int(src_uv[x] >> 6) - 512;
v = int(src_uv[x + 1] >> 6) - 512;
diff --git a/media/libstagefright/rtsp/ARTPWriter.cpp b/media/libstagefright/rtsp/ARTPWriter.cpp
index 41f2d67..bc83410 100644
--- a/media/libstagefright/rtsp/ARTPWriter.cpp
+++ b/media/libstagefright/rtsp/ARTPWriter.cpp
@@ -105,6 +105,7 @@
mRTCPAddr = mRTPAddr;
mRTCPAddr.sin_port = htons(ntohs(mRTPAddr.sin_port) | 1);
+ mVPSBuf = NULL;
mSPSBuf = NULL;
mPPSBuf = NULL;
diff --git a/services/audioflinger/MelReporter.cpp b/services/audioflinger/MelReporter.cpp
index 3af8828..23dfb7f 100644
--- a/services/audioflinger/MelReporter.cpp
+++ b/services/audioflinger/MelReporter.cpp
@@ -38,24 +38,21 @@
ndk::SpAIBinder soundDoseBinder;
if (device->getSoundDoseInterface(module, &soundDoseBinder) != OK) {
- ALOGW("%s: HAL cannot provide sound dose interface for module %s, use internal MEL",
+ ALOGW("%s: HAL cannot provide sound dose interface for module %s",
__func__, module.c_str());
- activateInternalSoundDoseComputation();
return false;
}
if (soundDoseBinder == nullptr) {
- ALOGW("%s: HAL doesn't implement a sound dose interface for module %s, use internal MEL",
+ ALOGW("%s: HAL doesn't implement a sound dose interface for module %s",
__func__, module.c_str());
- activateInternalSoundDoseComputation();
return false;
}
std::shared_ptr<ISoundDose> soundDoseInterface = ISoundDose::fromBinder(soundDoseBinder);
- if (!mSoundDoseManager->setHalSoundDoseInterface(soundDoseInterface)) {
+ if (!mSoundDoseManager->setHalSoundDoseInterface(module, soundDoseInterface)) {
ALOGW("%s: cannot activate HAL MEL reporting for module %s", __func__, module.c_str());
- activateInternalSoundDoseComputation();
return false;
}
@@ -73,7 +70,8 @@
mUseHalSoundDoseInterface = false;
}
- mSoundDoseManager->setHalSoundDoseInterface(nullptr);
+ // reset the HAL interfaces and use internal MELs
+ mSoundDoseManager->resetHalSoundDoseInterfaces();
}
void AudioFlinger::MelReporter::onFirstRef() {
@@ -251,6 +249,9 @@
void AudioFlinger::MelReporter::stopInternalMelComputation() {
ALOGV("%s", __func__);
std::lock_guard _l(mLock);
+ if (mUseHalSoundDoseInterface) {
+ return;
+ }
mActiveMelPatches.clear();
mUseHalSoundDoseInterface = true;
}
diff --git a/services/audioflinger/sounddose/SoundDoseManager.cpp b/services/audioflinger/sounddose/SoundDoseManager.cpp
index a551857..697d028 100644
--- a/services/audioflinger/sounddose/SoundDoseManager.cpp
+++ b/services/audioflinger/sounddose/SoundDoseManager.cpp
@@ -50,7 +50,7 @@
size_t channelCount, audio_format_t format) {
std::lock_guard _l(mLock);
- if (mHalSoundDose != nullptr && mEnabledCsd) {
+ if (mHalSoundDose.size() > 0 && mEnabledCsd) {
ALOGD("%s: using HAL MEL computation, no MelProcessor needed.", __func__);
return nullptr;
}
@@ -83,19 +83,27 @@
return melProcessor;
}
-bool SoundDoseManager::setHalSoundDoseInterface(const std::shared_ptr<ISoundDose>& halSoundDose) {
+bool SoundDoseManager::setHalSoundDoseInterface(const std::string &module,
+ const std::shared_ptr<ISoundDose> &halSoundDose) {
ALOGV("%s", __func__);
+ if (halSoundDose == nullptr) {
+ ALOGI("%s: passed ISoundDose object is null", __func__);
+ return false;
+ }
+
+ std::shared_ptr<HalSoundDoseCallback> halSoundDoseCallback;
{
std::lock_guard _l(mLock);
- mHalSoundDose = halSoundDose;
- if (halSoundDose == nullptr) {
- ALOGI("%s: passed ISoundDose object is null, switching to internal CSD", __func__);
+ if (mHalSoundDose.find(module) != mHalSoundDose.end()) {
+ ALOGW("%s: Module %s already has a sound dose HAL assigned, skipping", __func__,
+ module.c_str());
return false;
}
+ mHalSoundDose[module] = halSoundDose;
- if (!mHalSoundDose->setOutputRs2UpperBound(mRs2UpperBound).isOk()) {
+ if (!halSoundDose->setOutputRs2UpperBound(mRs2UpperBound).isOk()) {
ALOGW("%s: Cannot set RS2 value for momentary exposure %f",
__func__,
mRs2UpperBound);
@@ -119,16 +127,26 @@
return true;
}
+void SoundDoseManager::resetHalSoundDoseInterfaces() {
+ ALOGV("%s", __func__);
+
+ const std::lock_guard _l(mLock);
+ mHalSoundDose.clear();
+}
+
void SoundDoseManager::setOutputRs2UpperBound(float rs2Value) {
ALOGV("%s", __func__);
std::lock_guard _l(mLock);
- if (mHalSoundDose != nullptr) {
- // using the HAL sound dose interface
- if (!mHalSoundDose->setOutputRs2UpperBound(rs2Value).isOk()) {
- ALOGE("%s: Cannot set RS2 value for momentary exposure %f", __func__, rs2Value);
- return;
+ if (mHalSoundDose.size() > 0) {
+ for (auto& halSoundDose : mHalSoundDose) {
+ // using the HAL sound dose interface
+ if (!halSoundDose.second->setOutputRs2UpperBound(rs2Value).isOk()) {
+ ALOGE("%s: Cannot set RS2 value for momentary exposure %f", __func__, rs2Value);
+ continue;
+ }
}
+
mRs2UpperBound = rs2Value;
return;
}
@@ -200,14 +218,16 @@
ndk::ScopedAStatus SoundDoseManager::HalSoundDoseCallback::onMomentaryExposureWarning(
float in_currentDbA, const AudioDevice& in_audioDevice) {
- auto soundDoseManager = mSoundDoseManager.promote();
- if (soundDoseManager == nullptr) {
- return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ sp<SoundDoseManager> soundDoseManager;
+ {
+ const std::lock_guard _l(mCbLock);
+ soundDoseManager = mSoundDoseManager.promote();
+ if (soundDoseManager == nullptr) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
}
- std::shared_ptr<ISoundDose> halSoundDose;
- soundDoseManager->getHalSoundDose(&halSoundDose);
- if(halSoundDose == nullptr) {
+ if (!soundDoseManager->useHalSoundDose()) {
ALOGW("%s: HAL sound dose interface deactivated. Ignoring", __func__);
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
}
@@ -227,14 +247,16 @@
ndk::ScopedAStatus SoundDoseManager::HalSoundDoseCallback::onNewMelValues(
const ISoundDose::IHalSoundDoseCallback::MelRecord& in_melRecord,
const AudioDevice& in_audioDevice) {
- auto soundDoseManager = mSoundDoseManager.promote();
- if (soundDoseManager == nullptr) {
- return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ sp<SoundDoseManager> soundDoseManager;
+ {
+ const std::lock_guard _l(mCbLock);
+ soundDoseManager = mSoundDoseManager.promote();
+ if (soundDoseManager == nullptr) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
}
- std::shared_ptr<ISoundDose> halSoundDose;
- soundDoseManager->getHalSoundDose(&halSoundDose);
- if(halSoundDose == nullptr) {
+ if (!soundDoseManager->useHalSoundDose()) {
ALOGW("%s: HAL sound dose interface deactivated. Ignoring", __func__);
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
}
@@ -508,7 +530,7 @@
void SoundDoseManager::setUseFrameworkMel(bool useFrameworkMel) {
// invalidate any HAL sound dose interface used
- setHalSoundDoseInterface(nullptr);
+ resetHalSoundDoseInterfaces();
std::lock_guard _l(mLock);
mUseFrameworkMel = useFrameworkMel;
@@ -534,17 +556,12 @@
return false;
}
- std::shared_ptr<ISoundDose> halSoundDose;
- getHalSoundDose(&halSoundDose);
- if (mHalSoundDose == nullptr) {
- return false;
- }
- return true;
+ return useHalSoundDose();
}
-void SoundDoseManager::getHalSoundDose(std::shared_ptr<ISoundDose>* halSoundDose) const {
- std::lock_guard _l(mLock);
- *halSoundDose = mHalSoundDose;
+bool SoundDoseManager::useHalSoundDose() const {
+ const std::lock_guard _l(mLock);
+ return mHalSoundDose.size() > 0;
}
void SoundDoseManager::resetSoundDose() {
diff --git a/services/audioflinger/sounddose/SoundDoseManager.h b/services/audioflinger/sounddose/SoundDoseManager.h
index 42a793d..43175f1 100644
--- a/services/audioflinger/sounddose/SoundDoseManager.h
+++ b/services/audioflinger/sounddose/SoundDoseManager.h
@@ -94,12 +94,15 @@
sp<media::ISoundDose> getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback);
/**
- * Sets the HAL sound dose interface to use for the MEL computation. Use nullptr
- * for using the internal MEL computation.
+ * Sets the HAL sound dose interface for a specific module to use for the MEL computation.
*
* @return true if setting the HAL sound dose value was successful, false otherwise.
*/
- bool setHalSoundDoseInterface(const std::shared_ptr<ISoundDose>& halSoundDose);
+ bool setHalSoundDoseInterface(const std::string &module,
+ const std::shared_ptr<ISoundDose> &halSoundDose);
+
+ /** Reset all the stored HAL sound dose interface. */
+ void resetHalSoundDoseInterfaces();
/** Returns the cached audio port id from the active devices. */
audio_port_handle_t getIdForAudioDevice(
@@ -193,6 +196,7 @@
const aidl::android::media::audio::common::AudioDevice& in_audioDevice) override;
wp<SoundDoseManager> mSoundDoseManager;
+ std::mutex mCbLock;
};
void resetSoundDose();
@@ -206,8 +210,11 @@
void setUseFrameworkMel(bool useFrameworkMel);
void setComputeCsdOnAllDevices(bool computeCsdOnAllDevices);
bool isSoundDoseHalSupported() const;
- /** Returns the HAL sound dose interface or null if internal MEL computation is used. */
- void getHalSoundDose(std::shared_ptr<ISoundDose>* halSoundDose) const;
+ /**
+ * Returns true if there is one active HAL sound dose interface or null if internal MEL
+ * computation is used.
+ **/
+ bool useHalSoundDose() const;
mutable std::mutex mLock;
@@ -241,7 +248,7 @@
sp<SoundDose> mSoundDose GUARDED_BY(mLock);
- std::shared_ptr<ISoundDose> mHalSoundDose GUARDED_BY(mLock);
+ std::unordered_map<std::string, std::shared_ptr<ISoundDose>> mHalSoundDose GUARDED_BY(mLock);
std::shared_ptr<HalSoundDoseCallback> mHalSoundDoseCallback GUARDED_BY(mLock);
bool mUseFrameworkMel GUARDED_BY(mLock) = false;
diff --git a/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp b/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp
index 5860d96..5f6dcb9 100644
--- a/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp
+++ b/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp
@@ -45,6 +45,8 @@
MOCK_METHOD(void, stopMelComputationForDeviceId, (audio_port_handle_t), (override));
};
+constexpr char kPrimaryModule[] = "primary";
+constexpr char kSecondaryModule[] = "secondary";
class SoundDoseManagerTest : public ::testing::Test {
protected:
@@ -52,17 +54,24 @@
mMelReporterCallback = sp<MelReporterCallback>::make();
mSoundDoseManager = sp<SoundDoseManager>::make(mMelReporterCallback);
mHalSoundDose = ndk::SharedRefBase::make<HalSoundDoseMock>();
+ mSecondaryHalSoundDose = ndk::SharedRefBase::make<HalSoundDoseMock>();
ON_CALL(*mHalSoundDose.get(), setOutputRs2UpperBound)
.WillByDefault([] (float rs2) {
EXPECT_EQ(rs2, ISoundDose::DEFAULT_MAX_RS2);
return ndk::ScopedAStatus::ok();
});
+ ON_CALL(*mSecondaryHalSoundDose.get(), setOutputRs2UpperBound)
+ .WillByDefault([] (float rs2) {
+ EXPECT_EQ(rs2, ISoundDose::DEFAULT_MAX_RS2);
+ return ndk::ScopedAStatus::ok();
+ });
}
sp<MelReporterCallback> mMelReporterCallback;
sp<SoundDoseManager> mSoundDoseManager;
std::shared_ptr<HalSoundDoseMock> mHalSoundDose;
+ std::shared_ptr<HalSoundDoseMock> mSecondaryHalSoundDose;
};
TEST_F(SoundDoseManagerTest, GetProcessorForExistingStream) {
@@ -110,7 +119,7 @@
}
TEST_F(SoundDoseManagerTest, InvalidHalInterfaceIsNotSet) {
- EXPECT_FALSE(mSoundDoseManager->setHalSoundDoseInterface(nullptr));
+ EXPECT_FALSE(mSoundDoseManager->setHalSoundDoseInterface(kPrimaryModule, nullptr));
}
TEST_F(SoundDoseManagerTest, SetHalSoundDoseDisablesNewMelProcessorCallbacks) {
@@ -122,7 +131,7 @@
return ndk::ScopedAStatus::ok();
});
- EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose));
+ EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(kPrimaryModule, mHalSoundDose));
EXPECT_EQ(nullptr, mSoundDoseManager->getOrCreateProcessorForDevice(/*deviceId=*/2,
/*streamHandle=*/1,
@@ -139,8 +148,17 @@
EXPECT_NE(nullptr, callback);
return ndk::ScopedAStatus::ok();
});
+ EXPECT_CALL(*mSecondaryHalSoundDose.get(), setOutputRs2UpperBound).Times(1);
+ EXPECT_CALL(*mSecondaryHalSoundDose.get(), registerSoundDoseCallback)
+ .Times(1)
+ .WillOnce([&] (const std::shared_ptr<ISoundDose::IHalSoundDoseCallback>& callback) {
+ EXPECT_NE(nullptr, callback);
+ return ndk::ScopedAStatus::ok();
+ });
- EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose));
+ EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(kPrimaryModule, mHalSoundDose));
+ EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(kSecondaryModule,
+ mSecondaryHalSoundDose));
}
TEST_F(SoundDoseManagerTest, MomentaryExposureFromHalWithNoAddressIllegalArgument) {
@@ -154,7 +172,7 @@
return ndk::ScopedAStatus::ok();
});
- EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose));
+ EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(kPrimaryModule, mHalSoundDose));
EXPECT_NE(nullptr, halCallback);
AudioDevice audioDevice = {};
@@ -175,9 +193,9 @@
return ndk::ScopedAStatus::ok();
});
- EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose));
+ EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(kPrimaryModule, mHalSoundDose));
EXPECT_NE(nullptr, halCallback);
- EXPECT_FALSE(mSoundDoseManager->setHalSoundDoseInterface(nullptr));
+ mSoundDoseManager->resetHalSoundDoseInterfaces();
AudioDevice audioDevice = {};
audioDevice.address.set<AudioDeviceAddress::id>("test");
@@ -197,7 +215,7 @@
return ndk::ScopedAStatus::ok();
});
- EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose));
+ EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(kPrimaryModule, mHalSoundDose));
EXPECT_NE(nullptr, halCallback);
AudioDevice audioDevice = {};
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 8717083..b3c68b5 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -7656,8 +7656,10 @@
const auto musicVolumeSrc = toVolumeSource(AUDIO_STREAM_MUSIC, false);
const auto alarmVolumeSrc = toVolumeSource(AUDIO_STREAM_ALARM, false);
const auto a11yVolumeSrc = toVolumeSource(AUDIO_STREAM_ACCESSIBILITY, false);
-
- if (volumeSource == a11yVolumeSrc
+ // Verify that the current volume source is not the ringer volume to prevent recursively
+ // calling to compute volume. This could happen in cases where a11y and ringer sounds belong
+ // to the same volume group.
+ if (volumeSource != ringVolumeSrc && volumeSource == a11yVolumeSrc
&& (AUDIO_MODE_RINGTONE == mEngine->getPhoneState()) &&
mOutputs.isActive(ringVolumeSrc, 0)) {
auto &ringCurves = getVolumeCurves(AUDIO_STREAM_RING);
@@ -7720,8 +7722,12 @@
// when the phone is ringing we must consider that music could have been paused just before
// by the music application and behave as if music was active if the last music track was
// just stopped
- if (isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_HEADSET_MUSIC_DELAY) ||
- mLimitRingtoneVolume) {
+ // Verify that the current volume source is not the music volume to prevent recursively
+ // calling to compute volume. This could happen in cases where music and
+ // (alarm, ring, notification, system, etc.) sounds belong to the same volume group.
+ if (volumeSource != musicVolumeSrc &&
+ (isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_HEADSET_MUSIC_DELAY)
+ || mLimitRingtoneVolume)) {
volumeDb += SONIFICATION_HEADSET_VOLUME_FACTOR_DB;
DeviceTypeSet musicDevice =
mEngine->getOutputDevicesForAttributes(attributes_initializer(AUDIO_USAGE_MEDIA),
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 9f52ddf..0f7880a 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -817,10 +817,9 @@
std::unique_ptr<AutoConditionLock> serviceLockWrapper =
AutoConditionLock::waitAndAcquire(mServiceLockWrapper);
- Mutex::Autolock lock(mCameraIdRemappingLock);
- // This will disconnect all existing clients for camera Ids that are being
- // remapped in cameraIdRemapping, but only if they were being used by an
- // affected packageName.
+ // Collect all existing clients for camera Ids that are being
+ // remapped in the new cameraIdRemapping, but only if they were being used by a
+ // targeted packageName.
std::vector<sp<BasicClient>> clientsToDisconnect;
std::vector<String8> cameraIdsToUpdate;
for (const auto& [packageName, injectionMap] : cameraIdRemapping) {
@@ -831,7 +830,8 @@
if (clientDescriptor != nullptr) {
sp<BasicClient> clientSp = clientDescriptor->getValue();
if (clientSp->getPackageName() == packageName) {
- // This camera ID is being used by the affected packageName.
+ // This camera is being used by a targeted packageName and
+ // being remapped to a new camera Id. We should disconnect it.
clientsToDisconnect.push_back(clientSp);
cameraIdsToUpdate.push_back(id0);
}
@@ -839,25 +839,40 @@
}
}
- // Update mCameraIdRemapping.
- mCameraIdRemapping.clear();
- mCameraIdRemapping.insert(cameraIdRemapping.begin(), cameraIdRemapping.end());
+ for (auto& clientSp : clientsToDisconnect) {
+ // We send up ERROR_CAMERA_DEVICE so that the app attempts to reconnect
+ // automatically. Note that this itself can cause clientSp->disconnect() based on the
+ // app's response.
+ clientSp->notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE,
+ CaptureResultExtras{});
+ }
// Do not hold mServiceLock while disconnecting clients, but retain the condition
// blocking other clients from connecting in mServiceLockWrapper if held.
mServiceLock.unlock();
+ // Clear calling identity for disconnect() PID checks.
+ int64_t token = CameraThreadState::clearCallingIdentity();
+
// Disconnect clients.
for (auto& clientSp : clientsToDisconnect) {
- // We send up ERROR_CAMERA_DEVICE so that the app attempts to reconnect
- // automatically.
- clientSp->notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE,
- CaptureResultExtras{});
- // This also triggers the status updates
+ // This also triggers a call to updateStatus() which also reads mCameraIdRemapping
+ // and requires mCameraIdRemappingLock.
clientSp->disconnect();
}
+ // Invoke destructors (which call disconnect()) now while we don't hold the mServiceLock.
+ clientsToDisconnect.clear();
+
+ CameraThreadState::restoreCallingIdentity(token);
mServiceLock.lock();
+
+ {
+ Mutex::Autolock lock(mCameraIdRemappingLock);
+ // Update mCameraIdRemapping.
+ mCameraIdRemapping.clear();
+ mCameraIdRemapping.insert(cameraIdRemapping.begin(), cameraIdRemapping.end());
+ }
}
std::vector<String8> CameraService::findOriginalIdsForRemappedCameraId(
@@ -876,28 +891,27 @@
return cameraIds;
}
-String8 CameraService::resolveCameraId(const String8& inputCameraId) {
- return resolveCameraId(inputCameraId, String16(""));
-}
-
String8 CameraService::resolveCameraId(
const String8& inputCameraId,
+ int clientUid,
const String16& packageName) {
String16 packageNameVal = packageName;
if (packageName == String16("")) {
- int clientUid = CameraThreadState::getCallingUid();
packageNameVal = getPackageNameFromUid(clientUid);
}
+ if (clientUid < AID_APP_START || packageNameVal == String16("")) {
+ // We shouldn't remap cameras for processes with system/vendor UIDs.
+ return inputCameraId;
+ }
Mutex::Autolock lock(mCameraIdRemappingLock);
if (auto packageMapIter = mCameraIdRemapping.find(packageNameVal);
packageMapIter != mCameraIdRemapping.end()) {
- ALOGI("%s: resolveCameraId: packageName found %s",
- __FUNCTION__, String8(packageNameVal).c_str());
auto packageMap = packageMapIter->second;
if (auto replacementIdIter = packageMap.find(inputCameraId);
replacementIdIter != packageMap.end()) {
- ALOGI("%s: resolveCameraId: inputId found %s, replacing with %s",
+ ALOGI("%s: resolveCameraId: remapping cameraId %s for %s to %s",
__FUNCTION__, inputCameraId.c_str(),
+ String8(packageNameVal).c_str(),
replacementIdIter->second.c_str());
return replacementIdIter->second;
}
@@ -909,7 +923,12 @@
CameraInfo* cameraInfo) {
ATRACE_CALL();
Mutex::Autolock l(mServiceLock);
- std::string cameraIdStr = cameraIdIntToStrLocked(cameraId);
+
+ std::string unresolvedCameraId = cameraIdIntToStrLocked(cameraId);
+ std::string cameraIdStr = resolveCameraId(
+ String8(unresolvedCameraId.c_str()),
+ CameraThreadState::getCallingUid()).string();
+
if (shouldRejectSystemCameraConnection(String8(cameraIdStr.c_str()))) {
return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION, "Unable to retrieve camera"
"characteristics for system only device %s: ", cameraIdStr.c_str());
@@ -978,7 +997,8 @@
Status CameraService::getCameraCharacteristics(const String16& unresolvedCameraId,
int targetSdkVersion, bool overrideToPortrait, CameraMetadata* cameraInfo) {
ATRACE_CALL();
- String8 cameraId = resolveCameraId(String8(unresolvedCameraId));
+ String8 cameraId = resolveCameraId(String8(unresolvedCameraId),
+ CameraThreadState::getCallingUid());
if (!cameraInfo) {
ALOGE("%s: cameraInfo is NULL", __FUNCTION__);
return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, "cameraInfo is NULL");
@@ -1064,9 +1084,11 @@
return ret;
}
-Status CameraService::getTorchStrengthLevel(const String16& cameraId,
+Status CameraService::getTorchStrengthLevel(const String16& unresolvedCameraId,
int32_t* torchStrength) {
ATRACE_CALL();
+ String8 cameraId = resolveCameraId(String8(unresolvedCameraId),
+ CameraThreadState::getCallingUid());
Mutex::Autolock l(mServiceLock);
if (!mInitialized) {
ALOGE("%s: Camera HAL couldn't be initialized.", __FUNCTION__);
@@ -1343,7 +1365,9 @@
return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, "Parameters must not be null");
}
- String8 id = String8::format("%d", cameraId);
+ String8 unresolvedCameraId = String8::format("%d", cameraId);
+ String8 id = resolveCameraId(unresolvedCameraId,
+ CameraThreadState::getCallingUid());
// Check if we already have parameters
{
@@ -1855,7 +1879,9 @@
ATRACE_CALL();
Status ret = Status::ok();
- String8 id = cameraIdIntToStr(api1CameraId);
+ String8 unresolvedCameraId = cameraIdIntToStr(api1CameraId);
+ String8 id = resolveCameraId(unresolvedCameraId, CameraThreadState::getCallingUid());
+
sp<Client> client = nullptr;
ret = connectHelper<ICameraClient,Client>(cameraClient, id, api1CameraId,
clientPackageName,/*systemNativeClient*/ false, {}, clientUid, clientPid, API_1,
@@ -1950,7 +1976,6 @@
ATRACE_CALL();
Status ret = Status::ok();
- String8 id = resolveCameraId(String8(unresolvedCameraId), clientPackageName);
sp<CameraDeviceClient> client = nullptr;
String16 clientPackageNameAdj = clientPackageName;
int callingPid = CameraThreadState::getCallingPid();
@@ -1962,6 +1987,10 @@
systemNativeClient = true;
}
+ String8 id = resolveCameraId(String8(unresolvedCameraId),
+ CameraThreadState::getCallingUid(),
+ clientPackageNameAdj);
+
if (oomScoreOffset < 0) {
String8 msg =
String8::format("Cannot increase the priority of a client %s pid %d for "
@@ -2453,8 +2482,8 @@
"Torch client binder in null.");
}
- String8 id = resolveCameraId(String8(unresolvedCameraId));
int uid = CameraThreadState::getCallingUid();
+ String8 id = resolveCameraId(String8(unresolvedCameraId), uid);
if (shouldRejectSystemCameraConnection(id)) {
return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT, "Unable to change the strength level"
@@ -2584,8 +2613,8 @@
"Torch client Binder is null");
}
- String8 id = resolveCameraId(String8(unresolvedCameraId));
int uid = CameraThreadState::getCallingUid();
+ String8 id = resolveCameraId(String8(unresolvedCameraId), uid);
if (shouldRejectSystemCameraConnection(id)) {
return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT, "Unable to set torch mode"
@@ -3113,16 +3142,8 @@
/*out*/ bool *isSupported) {
ATRACE_CALL();
- String8 resolvedId;
- if (apiVersion == API_VERSION_2) {
- resolvedId = resolveCameraId(String8(unresolvedCameraId));
- } else { // if (apiVersion == API_VERSION_1)
- // We don't support remapping for API 1.
- // TODO(b/286287541): Also support remapping for API 1.
- resolvedId = String8(unresolvedCameraId);
- }
-
- const String8 id = resolvedId;
+ const String8 id = resolveCameraId(String8(unresolvedCameraId),
+ CameraThreadState::getCallingUid());
ALOGV("%s: for camera ID = %s", __FUNCTION__, id.string());
@@ -3186,7 +3207,8 @@
/*out*/ bool *isSupported) {
ATRACE_CALL();
- const String8 id = resolveCameraId(String8(unresolvedCameraId));
+ const String8 id = resolveCameraId(String8(unresolvedCameraId),
+ CameraThreadState::getCallingUid());
ALOGV("%s: for camera ID = %s", __FUNCTION__, id.string());
*isSupported = mCameraProviderManager->isHiddenPhysicalCamera(id.string());
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 65b11e7..0cbdd11 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -972,15 +972,13 @@
*
* This returns the Camera Id to use in case inputCameraId was remapped to a
* different Id for the given packageName. Otherwise, it returns the inputCameraId.
- */
- String8 resolveCameraId(const String8& inputCameraId, const String16& packageName);
- /**
- * Resolve the (potentially remapped) camera Id to use.
*
- * This returns the Camera Id to use in case inputCameraId was remapped to a
- * different Id for the packageName of the client. Otherwise, it returns the inputCameraId.
+ * If the packageName is not provided, it will be inferred from the clientUid.
*/
- String8 resolveCameraId(const String8& inputCameraId);
+ String8 resolveCameraId(
+ const String8& inputCameraId,
+ int clientUid,
+ const String16& packageName = String16(""));
/**
* Updates the state of mCameraIdRemapping, while disconnecting active clients as necessary.