Merge changes from topic "reverted-mistakenly-tv" into udc-dev
* changes:
GraphicBufferSource: Use 64bit consumer usage
C2BqPool: Expire waiters on Surface switching
diff --git a/cmds/screenrecord/screenrecord.cpp b/cmds/screenrecord/screenrecord.cpp
index cd4932d..f53fc0a 100644
--- a/cmds/screenrecord/screenrecord.cpp
+++ b/cmds/screenrecord/screenrecord.cpp
@@ -122,7 +122,7 @@
static uint32_t gBitRate = 20000000; // 20Mbps
static uint32_t gTimeLimitSec = kMaxTimeLimitSec;
static uint32_t gBframes = 0;
-static PhysicalDisplayId gPhysicalDisplayId;
+static std::optional<PhysicalDisplayId> gPhysicalDisplayId;
// Set by signal handler to stop recording.
static volatile bool gStopRequested = false;
@@ -336,6 +336,24 @@
}
/*
+ * Gets the physical id of the display to record. If the user specified a physical
+ * display id, then that id will be set. Otherwise, the default display will be set.
+ */
+static status_t getPhysicalDisplayId(PhysicalDisplayId& outDisplayId) {
+ if (gPhysicalDisplayId) {
+ outDisplayId = *gPhysicalDisplayId;
+ return NO_ERROR;
+ }
+
+ const std::vector<PhysicalDisplayId> ids = SurfaceComposerClient::getPhysicalDisplayIds();
+ if (ids.empty()) {
+ return INVALID_OPERATION;
+ }
+ outDisplayId = ids.front();
+ return NO_ERROR;
+}
+
+/*
* Configures the virtual display. When this completes, virtual display
* frames will start arriving from the buffer producer.
*/
@@ -350,7 +368,12 @@
setDisplayProjection(t, dpy, displayState);
ui::LayerStack layerStack = ui::LayerStack::fromValue(std::rand());
t.setDisplayLayerStack(dpy, layerStack);
- *mirrorRoot = SurfaceComposerClient::getDefault()->mirrorDisplay(gPhysicalDisplayId);
+ PhysicalDisplayId displayId;
+ status_t err = getPhysicalDisplayId(displayId);
+ if (err != NO_ERROR) {
+ return err;
+ }
+ *mirrorRoot = SurfaceComposerClient::getDefault()->mirrorDisplay(displayId);
if (*mirrorRoot == nullptr) {
ALOGE("Failed to create a mirror for screenrecord");
return UNKNOWN_ERROR;
@@ -486,6 +509,43 @@
}
/*
+ * Update the display projection if size or orientation have changed.
+ */
+void updateDisplayProjection(const sp<IBinder>& virtualDpy, ui::DisplayState& displayState) {
+ ATRACE_NAME("updateDisplayProjection");
+
+ PhysicalDisplayId displayId;
+ if (getPhysicalDisplayId(displayId) != NO_ERROR) {
+ fprintf(stderr, "ERROR: Failed to get display id\n");
+ return;
+ }
+
+ sp<IBinder> displayToken = SurfaceComposerClient::getPhysicalDisplayToken(displayId);
+ if (!displayToken) {
+ fprintf(stderr, "ERROR: failed to get display token\n");
+ return;
+ }
+
+ ui::DisplayState currentDisplayState;
+ if (SurfaceComposerClient::getDisplayState(displayToken, ¤tDisplayState) != NO_ERROR) {
+ ALOGW("ERROR: failed to get display state\n");
+ return;
+ }
+
+ if (currentDisplayState.orientation != displayState.orientation ||
+ currentDisplayState.layerStackSpaceRect != displayState.layerStackSpaceRect) {
+ displayState = currentDisplayState;
+ ALOGD("display state changed, now has orientation %s, size (%d, %d)",
+ toCString(displayState.orientation), displayState.layerStackSpaceRect.getWidth(),
+ displayState.layerStackSpaceRect.getHeight());
+
+ SurfaceComposerClient::Transaction t;
+ setDisplayProjection(t, virtualDpy, currentDisplayState);
+ t.apply();
+ }
+}
+
+/*
* Runs the MediaCodec encoder, sending the output to the MediaMuxer. The
* input frames are coming from the virtual display as fast as SurfaceFlinger
* wants to send them.
@@ -494,9 +554,8 @@
*
* The muxer must *not* have been started before calling.
*/
-static status_t runEncoder(const sp<MediaCodec>& encoder,
- AMediaMuxer *muxer, FILE* rawFp, const sp<IBinder>& display,
- const sp<IBinder>& virtualDpy, ui::Rotation orientation) {
+static status_t runEncoder(const sp<MediaCodec>& encoder, AMediaMuxer* muxer, FILE* rawFp,
+ const sp<IBinder>& virtualDpy, ui::DisplayState displayState) {
static int kTimeout = 250000; // be responsive on signal
status_t err;
ssize_t trackIdx = -1;
@@ -555,24 +614,7 @@
ALOGV("Got data in buffer %zu, size=%zu, pts=%" PRId64,
bufIndex, size, ptsUsec);
- { // scope
- ATRACE_NAME("orientation");
- // Check orientation, update if it has changed.
- //
- // Polling for changes is inefficient and wrong, but the
- // useful stuff is hard to get at without a Dalvik VM.
- ui::DisplayState displayState;
- err = SurfaceComposerClient::getDisplayState(display, &displayState);
- if (err != NO_ERROR) {
- ALOGW("getDisplayState() failed: %d", err);
- } else if (orientation != displayState.orientation) {
- ALOGD("orientation changed, now %s", toCString(displayState.orientation));
- SurfaceComposerClient::Transaction t;
- setDisplayProjection(t, virtualDpy, displayState);
- t.apply();
- orientation = displayState.orientation;
- }
- }
+ updateDisplayProjection(virtualDpy, displayState);
// If the virtual display isn't providing us with timestamps,
// use the current time. This isn't great -- we could get
@@ -764,6 +806,38 @@
};
/*
+ * Computes the maximum width and height across all physical displays.
+ */
+static ui::Size getMaxDisplaySize() {
+ const std::vector<PhysicalDisplayId> physicalDisplayIds =
+ SurfaceComposerClient::getPhysicalDisplayIds();
+ if (physicalDisplayIds.empty()) {
+ fprintf(stderr, "ERROR: Failed to get physical display ids\n");
+ return {};
+ }
+
+ ui::Size result;
+ for (auto& displayId : physicalDisplayIds) {
+ sp<IBinder> displayToken = SurfaceComposerClient::getPhysicalDisplayToken(displayId);
+ if (!displayToken) {
+ fprintf(stderr, "ERROR: failed to get display token\n");
+ continue;
+ }
+
+ ui::DisplayState displayState;
+ status_t err = SurfaceComposerClient::getDisplayState(displayToken, &displayState);
+ if (err != NO_ERROR) {
+ fprintf(stderr, "ERROR: failed to get display state\n");
+ continue;
+ }
+
+ result.height = std::max(result.height, displayState.layerStackSpaceRect.getHeight());
+ result.width = std::max(result.width, displayState.layerStackSpaceRect.getWidth());
+ }
+ return result;
+}
+
+/*
* Main "do work" start point.
*
* Configures codec, muxer, and virtual display, then starts moving bits
@@ -781,9 +855,15 @@
sp<ProcessState> self = ProcessState::self();
self->startThreadPool();
+ PhysicalDisplayId displayId;
+ err = getPhysicalDisplayId(displayId);
+ if (err != NO_ERROR) {
+ fprintf(stderr, "ERROR: Failed to get display id\n");
+ return err;
+ }
+
// Get main display parameters.
- sp<IBinder> display = SurfaceComposerClient::getPhysicalDisplayToken(
- gPhysicalDisplayId);
+ sp<IBinder> display = SurfaceComposerClient::getPhysicalDisplayToken(displayId);
if (display == nullptr) {
fprintf(stderr, "ERROR: no display\n");
return NAME_NOT_FOUND;
@@ -808,7 +888,8 @@
return INVALID_OPERATION;
}
- const ui::Size& layerStackSpaceRect = displayState.layerStackSpaceRect;
+ const ui::Size layerStackSpaceRect =
+ gPhysicalDisplayId ? displayState.layerStackSpaceRect : getMaxDisplaySize();
if (gVerbose) {
printf("Display is %dx%d @%.2ffps (orientation=%s), layerStack=%u\n",
layerStackSpaceRect.getWidth(), layerStackSpaceRect.getHeight(),
@@ -973,8 +1054,7 @@
}
} else {
// Main encoder loop.
- err = runEncoder(recordingData.encoder, muxer, rawFp, display, recordingData.dpy,
- displayState.orientation);
+ err = runEncoder(recordingData.encoder, muxer, rawFp, recordingData.dpy, displayState);
if (err != NO_ERROR) {
fprintf(stderr, "Encoder failed (err=%d)\n", err);
// fall through to cleanup
@@ -1175,14 +1255,6 @@
{ NULL, 0, NULL, 0 }
};
- const std::vector<PhysicalDisplayId> ids = SurfaceComposerClient::getPhysicalDisplayIds();
- if (ids.empty()) {
- fprintf(stderr, "Failed to get ID for any displays\n");
- return 1;
- }
-
- gPhysicalDisplayId = ids.front();
-
while (true) {
int optionIndex = 0;
int ic = getopt_long(argc, argv, "", longOptions, &optionIndex);
diff --git a/media/audioaidlconversion/AidlConversionNdkCpp.cpp b/media/audioaidlconversion/AidlConversionNdkCpp.cpp
index 36f6128..c64a074 100644
--- a/media/audioaidlconversion/AidlConversionNdkCpp.cpp
+++ b/media/audioaidlconversion/AidlConversionNdkCpp.cpp
@@ -123,6 +123,7 @@
GENERATE_CONVERTERS(android::media::audio::common, AudioHalEngineConfig);
GENERATE_CONVERTERS(android::media::audio::common, AudioMMapPolicyInfo);
GENERATE_ENUM_CONVERTERS(android::media::audio::common, AudioMMapPolicyType);
+GENERATE_ENUM_CONVERTERS(android::media::audio::common, AudioMode);
GENERATE_CONVERTERS(android::media::audio::common, AudioPort);
} // namespace android
diff --git a/media/audioaidlconversion/include/media/AidlConversionNdkCpp.h b/media/audioaidlconversion/include/media/AidlConversionNdkCpp.h
index 09f1c22..f4822aa 100644
--- a/media/audioaidlconversion/include/media/AidlConversionNdkCpp.h
+++ b/media/audioaidlconversion/include/media/AidlConversionNdkCpp.h
@@ -23,11 +23,13 @@
#include <aidl/android/media/audio/common/AudioHalEngineConfig.h>
#include <aidl/android/media/audio/common/AudioMMapPolicyInfo.h>
#include <aidl/android/media/audio/common/AudioMMapPolicyType.h>
+#include <aidl/android/media/audio/common/AudioMode.h>
#include <aidl/android/media/audio/common/AudioPort.h>
#include <android/media/audio/common/AudioFormatDescription.h>
#include <android/media/audio/common/AudioHalEngineConfig.h>
#include <android/media/audio/common/AudioMMapPolicyInfo.h>
#include <android/media/audio/common/AudioMMapPolicyType.h>
+#include <android/media/audio/common/AudioMode.h>
#include <android/media/audio/common/AudioPort.h>
#include <media/AidlConversionUtil.h>
@@ -43,6 +45,7 @@
DECLARE_CONVERTERS(android::media::audio::common, AudioHalEngineConfig);
DECLARE_CONVERTERS(android::media::audio::common, AudioMMapPolicyInfo);
DECLARE_CONVERTERS(android::media::audio::common, AudioMMapPolicyType);
+DECLARE_CONVERTERS(android::media::audio::common, AudioMode);
DECLARE_CONVERTERS(android::media::audio::common, AudioPort);
#undef DECLARE_CONVERTERS
diff --git a/media/codec2/components/aom/C2SoftAomEnc.cpp b/media/codec2/components/aom/C2SoftAomEnc.cpp
index 59cad9d..e8b0506 100644
--- a/media/codec2/components/aom/C2SoftAomEnc.cpp
+++ b/media/codec2/components/aom/C2SoftAomEnc.cpp
@@ -542,15 +542,15 @@
mCodecConfiguration->kf_max_dist = 3000;
// Encoder determines optimal key frame placement automatically.
mCodecConfiguration->kf_mode = AOM_KF_AUTO;
- // Initial value of the buffer level in ms.
- mCodecConfiguration->rc_buf_initial_sz = 500;
- // Amount of data that the encoder should try to maintain in ms.
- mCodecConfiguration->rc_buf_optimal_sz = 600;
// The amount of data that may be buffered by the decoding
// application in ms.
mCodecConfiguration->rc_buf_sz = 1000;
if (mBitrateControlMode == AOM_CBR) {
+ // Initial value of the buffer level in ms.
+ mCodecConfiguration->rc_buf_initial_sz = 500;
+ // Amount of data that the encoder should try to maintain in ms.
+ mCodecConfiguration->rc_buf_optimal_sz = 600;
// Maximum amount of bits that can be subtracted from the target
// bitrate - expressed as percentage of the target bitrate.
mCodecConfiguration->rc_undershoot_pct = 100;
@@ -563,7 +563,7 @@
mCodecConfiguration->rc_undershoot_pct = 100;
// Maximum amount of bits that can be added to the target
// bitrate - expressed as percentage of the target bitrate.
- mCodecConfiguration->rc_overshoot_pct = 25;
+ mCodecConfiguration->rc_overshoot_pct = 100;
}
if (mIntf->getSyncFramePeriod() >= 0) {
@@ -576,6 +576,12 @@
}
if (mMaxQuantizer > 0) {
mCodecConfiguration->rc_max_quantizer = mMaxQuantizer;
+ } else {
+ if (mBitrateControlMode == AOM_VBR) {
+ // For VBR we are limiting MaxQP to 52 (down 11 steps) to maintain quality
+ // 52 comes from experiments done on libaom standalone app
+ mCodecConfiguration->rc_max_quantizer = 52;
+ }
}
mCodecContext = new aom_codec_ctx_t;
diff --git a/media/codec2/components/gav1/C2SoftGav1Dec.cpp b/media/codec2/components/gav1/C2SoftGav1Dec.cpp
index 8aed623..77296a4 100644
--- a/media/codec2/components/gav1/C2SoftGav1Dec.cpp
+++ b/media/codec2/components/gav1/C2SoftGav1Dec.cpp
@@ -726,24 +726,6 @@
}
}
-void C2SoftGav1Dec::setError(const std::unique_ptr<C2Work> &work, c2_status_t error) {
- mSignalledError = true;
- work->result = error;
- work->workletsProcessed = 1u;
-}
-
-bool C2SoftGav1Dec::allocTmpFrameBuffer(size_t size) {
- if (size > mTmpFrameBufferSize) {
- mTmpFrameBuffer = std::make_unique<uint16_t[]>(size);
- if (mTmpFrameBuffer == nullptr) {
- mTmpFrameBufferSize = 0;
- return false;
- }
- mTmpFrameBufferSize = size;
- }
- return true;
-}
-
bool C2SoftGav1Dec::outputBuffer(const std::shared_ptr<C2BlockPool> &pool,
const std::unique_ptr<C2Work> &work) {
if (!(work && pool)) return false;
@@ -790,6 +772,16 @@
getHDRStaticParams(buffer, work);
getHDR10PlusInfoData(buffer, work);
+ if (buffer->bitdepth == 10 &&
+ !(buffer->image_format == libgav1::kImageFormatYuv420 ||
+ buffer->image_format == libgav1::kImageFormatMonochrome400)) {
+ ALOGE("image_format %d not supported for 10bit", buffer->image_format);
+ mSignalledError = true;
+ work->workletsProcessed = 1u;
+ work->result = C2_CORRUPTED;
+ return false;
+ }
+
const bool isMonochrome =
buffer->image_format == libgav1::kImageFormatMonochrome400;
@@ -862,6 +854,9 @@
uint8_t *dstY = const_cast<uint8_t *>(wView.data()[C2PlanarLayout::PLANE_Y]);
uint8_t *dstU = const_cast<uint8_t *>(wView.data()[C2PlanarLayout::PLANE_U]);
uint8_t *dstV = const_cast<uint8_t *>(wView.data()[C2PlanarLayout::PLANE_V]);
+ size_t srcYStride = buffer->stride[0];
+ size_t srcUStride = buffer->stride[1];
+ size_t srcVStride = buffer->stride[2];
C2PlanarLayout layout = wView.layout();
size_t dstYStride = layout.planes[C2PlanarLayout::PLANE_Y].rowInc;
@@ -872,88 +867,26 @@
const uint16_t *srcY = (const uint16_t *)buffer->plane[0];
const uint16_t *srcU = (const uint16_t *)buffer->plane[1];
const uint16_t *srcV = (const uint16_t *)buffer->plane[2];
- size_t srcYStride = buffer->stride[0] / 2;
- size_t srcUStride = buffer->stride[1] / 2;
- size_t srcVStride = buffer->stride[2] / 2;
if (format == HAL_PIXEL_FORMAT_RGBA_1010102) {
convertYUV420Planar16ToY410OrRGBA1010102(
- (uint32_t *)dstY, srcY, srcU, srcV, srcYStride,
- srcUStride, srcVStride,
+ (uint32_t *)dstY, srcY, srcU, srcV, srcYStride / 2,
+ srcUStride / 2, srcVStride / 2,
dstYStride / sizeof(uint32_t), mWidth, mHeight,
std::static_pointer_cast<const C2ColorAspectsStruct>(codedColorAspects));
} else if (format == HAL_PIXEL_FORMAT_YCBCR_P010) {
- dstYStride /= 2;
- dstUStride /= 2;
- dstVStride /= 2;
- if (buffer->image_format == libgav1::kImageFormatYuv444 ||
- buffer->image_format == libgav1::kImageFormatYuv422) {
- // TODO(https://crbug.com/libyuv/952): replace this block with libyuv::I410ToP010 and
- // libyuv::I210ToP010 when they are available.
- // Note it may be safe to alias dstY in I010ToP010, but the libyuv API doesn't make any
- // guarantees.
- const size_t tmpSize = dstYStride * mHeight + dstUStride * align(mHeight, 2);
- if (!allocTmpFrameBuffer(tmpSize)) {
- ALOGE("Error allocating temp conversion buffer (%zu bytes)", tmpSize);
- setError(work, C2_NO_MEMORY);
- return false;
- }
- uint16_t *const tmpY = mTmpFrameBuffer.get();
- uint16_t *const tmpU = tmpY + dstYStride * mHeight;
- uint16_t *const tmpV = tmpU + dstUStride * align(mHeight, 2) / 2;
- if (buffer->image_format == libgav1::kImageFormatYuv444) {
- libyuv::I410ToI010(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride,
- tmpY, dstYStride, tmpU, dstUStride, tmpV, dstUStride,
- mWidth, mHeight);
- } else {
- libyuv::I210ToI010(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride,
- tmpY, dstYStride, tmpU, dstUStride, tmpV, dstUStride,
- mWidth, mHeight);
- }
- libyuv::I010ToP010(tmpY, dstYStride, tmpU, dstUStride, tmpV, dstVStride,
- (uint16_t*)dstY, dstYStride, (uint16_t*)dstU, dstUStride,
- mWidth, mHeight);
- } else {
- convertYUV420Planar16ToP010((uint16_t *)dstY, (uint16_t *)dstU, srcY, srcU, srcV,
- srcYStride, srcUStride, srcVStride, dstYStride,
- dstUStride, mWidth, mHeight, isMonochrome);
- }
+ convertYUV420Planar16ToP010((uint16_t *)dstY, (uint16_t *)dstU, srcY, srcU, srcV,
+ srcYStride / 2, srcUStride / 2, srcVStride / 2, dstYStride / 2,
+ dstUStride / 2, mWidth, mHeight, isMonochrome);
} else {
- if (buffer->image_format == libgav1::kImageFormatYuv444) {
- // TODO(https://crbug.com/libyuv/950): replace this block with libyuv::I410ToI420 when
- // it's available.
- const size_t tmpSize = dstYStride * mHeight + dstUStride * align(mHeight, 2);
- if (!allocTmpFrameBuffer(tmpSize)) {
- ALOGE("Error allocating temp conversion buffer (%zu bytes)", tmpSize);
- setError(work, C2_NO_MEMORY);
- return false;
- }
- uint16_t *const tmpY = mTmpFrameBuffer.get();
- uint16_t *const tmpU = tmpY + dstYStride * mHeight;
- uint16_t *const tmpV = tmpU + dstUStride * align(mHeight, 2) / 2;
- libyuv::I410ToI010(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride,
- tmpY, dstYStride, tmpU, dstUStride, tmpV, dstVStride,
- mWidth, mHeight);
- libyuv::I010ToI420(tmpY, dstYStride, tmpU, dstUStride, tmpV, dstUStride,
- dstY, dstYStride, dstU, dstUStride, dstV, dstVStride,
- mWidth, mHeight);
- } else if (buffer->image_format == libgav1::kImageFormatYuv422) {
- libyuv::I210ToI420(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride,
- dstY, dstYStride, dstU, dstUStride, dstV, dstVStride,
- mWidth, mHeight);
- } else {
- convertYUV420Planar16ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride / 2,
- srcUStride / 2, srcVStride / 2, dstYStride, dstUStride,
- mWidth, mHeight, isMonochrome);
- }
+ convertYUV420Planar16ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride / 2,
+ srcUStride / 2, srcVStride / 2, dstYStride, dstUStride, mWidth,
+ mHeight, isMonochrome);
}
} else {
const uint8_t *srcY = (const uint8_t *)buffer->plane[0];
const uint8_t *srcU = (const uint8_t *)buffer->plane[1];
const uint8_t *srcV = (const uint8_t *)buffer->plane[2];
- size_t srcYStride = buffer->stride[0];
- size_t srcUStride = buffer->stride[1];
- size_t srcVStride = buffer->stride[2];
if (buffer->image_format == libgav1::kImageFormatYuv444) {
libyuv::I444ToI420(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride,
diff --git a/media/codec2/components/gav1/C2SoftGav1Dec.h b/media/codec2/components/gav1/C2SoftGav1Dec.h
index c3b27ea..f0e14d7 100644
--- a/media/codec2/components/gav1/C2SoftGav1Dec.h
+++ b/media/codec2/components/gav1/C2SoftGav1Dec.h
@@ -19,8 +19,6 @@
#include <inttypes.h>
-#include <memory>
-
#include <media/stagefright/foundation/ColorUtils.h>
#include <SimpleC2Component.h>
@@ -62,9 +60,6 @@
uint32_t mHeight;
bool mSignalledOutputEos;
bool mSignalledError;
- // Used during 10-bit I444/I422 to 10-bit P010 & 8-bit I420 conversions.
- std::unique_ptr<uint16_t[]> mTmpFrameBuffer;
- size_t mTmpFrameBufferSize = 0;
C2StreamHdrStaticMetadataInfo::output mHdrStaticMetadataInfo;
std::unique_ptr<C2StreamHdr10PlusInfo::output> mHdr10PlusInfo = nullptr;
@@ -102,9 +97,6 @@
void destroyDecoder();
void finishWork(uint64_t index, const std::unique_ptr<C2Work>& work,
const std::shared_ptr<C2GraphicBlock>& block);
- // Sets |work->result| and mSignalledError. Returns false.
- void setError(const std::unique_ptr<C2Work> &work, c2_status_t error);
- bool allocTmpFrameBuffer(size_t size);
bool outputBuffer(const std::shared_ptr<C2BlockPool>& pool,
const std::unique_ptr<C2Work>& work);
c2_status_t drainInternal(uint32_t drainMode,
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index eb1b4b5..2db6f2f 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -1828,6 +1828,7 @@
mCallback->onError(err2, ACTION_CODE_FATAL);
return;
}
+
err2 = mChannel->start(inputFormat, outputFormat, buffersBoundToCodec);
if (err2 != OK) {
mCallback->onError(err2, ACTION_CODE_FATAL);
@@ -2131,6 +2132,25 @@
RevertOutputFormatIfNeeded(outputFormat, config->mOutputFormat);
}
+ std::map<size_t, sp<MediaCodecBuffer>> clientInputBuffers;
+ status_t err = mChannel->prepareInitialInputBuffers(&clientInputBuffers);
+ if (err != OK) {
+ if (err == NO_MEMORY) {
+ // NO_MEMORY happens here when all the buffers are still
+ // with the codec. That is not an error as it is momentarily
+ // and the buffers are send to the client as soon as the codec
+ // releases them
+ ALOGI("Resuming with all input buffers still with codec");
+ } else {
+ ALOGE("Resume request for Input Buffers failed");
+ mCallback->onError(err, ACTION_CODE_FATAL);
+ return;
+ }
+ }
+
+ // channel start should be called after prepareInitialBuffers
+ // Calling before can cause a failure during prepare when
+ // buffers are sent to the client before preparation from onWorkDone
(void)mChannel->start(nullptr, nullptr, [&]{
Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
const std::unique_ptr<Config> &config = *configLocked;
@@ -2148,14 +2168,6 @@
state->set(RUNNING);
}
- std::map<size_t, sp<MediaCodecBuffer>> clientInputBuffers;
- status_t err = mChannel->prepareInitialInputBuffers(&clientInputBuffers);
- // FIXME(b/237656746)
- if (err != OK && err != NO_MEMORY) {
- ALOGE("Resume request for Input Buffers failed");
- mCallback->onError(err, ACTION_CODE_FATAL);
- return;
- }
mChannel->requestInitialInputBuffers(std::move(clientInputBuffers));
}
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index d5bbb52..7122af1 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -287,9 +287,11 @@
"aidl/android/media/AudioFlag.aidl",
"aidl/android/media/AudioGainSys.aidl",
"aidl/android/media/AudioHalVersion.aidl",
+ "aidl/android/media/AudioHwModule.aidl",
"aidl/android/media/AudioIoConfigEvent.aidl",
"aidl/android/media/AudioIoDescriptor.aidl",
"aidl/android/media/AudioPatchFw.aidl",
+ "aidl/android/media/AudioPolicyConfig.aidl",
"aidl/android/media/AudioPortFw.aidl",
"aidl/android/media/AudioPortSys.aidl",
"aidl/android/media/AudioPortConfigFw.aidl",
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index b731702..4527e0f 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -2529,6 +2529,14 @@
return af->supportsBluetoothVariableLatency(support);
}
+status_t AudioSystem::getAudioPolicyConfig(media::AudioPolicyConfig *config) {
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == nullptr) {
+ return PERMISSION_DENIED;
+ }
+ return af->getAudioPolicyConfig(config);
+}
+
class CaptureStateListenerImpl : public media::BnCaptureStateListener,
public IBinder::DeathRecipient {
public:
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index 4384f97..7b33a00 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -887,6 +887,16 @@
return statusTFromBinderStatus(mDelegate->invalidateTracks(portIdsAidl));
}
+status_t AudioFlingerClientAdapter::getAudioPolicyConfig(media::AudioPolicyConfig *config) {
+ if (config == nullptr) {
+ return BAD_VALUE;
+ }
+
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mDelegate->getAudioPolicyConfig(config)));
+
+ return NO_ERROR;
+}
+
////////////////////////////////////////////////////////////////////////////////////////////////////
// AudioFlingerServerAdapter
AudioFlingerServerAdapter::AudioFlingerServerAdapter(
@@ -1429,4 +1439,8 @@
return Status::ok();
}
+Status AudioFlingerServerAdapter::getAudioPolicyConfig(media::AudioPolicyConfig* _aidl_return) {
+ return Status::fromStatusT(mDelegate->getAudioPolicyConfig(_aidl_return));
+}
+
} // namespace android
diff --git a/media/libaudioclient/aidl/android/media/AudioHwModule.aidl b/media/libaudioclient/aidl/android/media/AudioHwModule.aidl
new file mode 100644
index 0000000..9251400
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/AudioHwModule.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.media.audio.common.AudioPort;
+import android.media.AudioRoute;
+
+/*
+ * A representation of a HAL module configuration.
+ * {@hide}
+ */
+parcelable AudioHwModule {
+ int /* audio_module_handle_t */ handle;
+ @utf8InCpp String name;
+ AudioPort[] ports;
+ AudioRoute[] routes;
+}
diff --git a/media/libaudioclient/aidl/android/media/AudioPolicyConfig.aidl b/media/libaudioclient/aidl/android/media/AudioPolicyConfig.aidl
new file mode 100644
index 0000000..87767c2
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/AudioPolicyConfig.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.media.AudioHwModule;
+import android.media.SurroundSoundConfig;
+import android.media.audio.common.AudioHalEngineConfig;
+import android.media.audio.common.AudioMode;
+
+/*
+ * Audio policy configuration. Functionally replaces the APM XML file.
+ * {@hide}
+ */
+parcelable AudioPolicyConfig {
+ AudioHwModule[] modules;
+ AudioMode[] supportedModes;
+ SurroundSoundConfig surroundSoundConfig;
+ AudioHalEngineConfig engineConfig;
+}
diff --git a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
index 884cd30..6412810 100644
--- a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
@@ -17,6 +17,7 @@
package android.media;
import android.media.AudioPatchFw;
+import android.media.AudioPolicyConfig;
import android.media.AudioPortFw;
import android.media.AudioPortConfigFw;
import android.media.AudioUniqueIdUse;
@@ -281,6 +282,12 @@
*/
void invalidateTracks(in int[] /* audio_port_handle_t[] */ portIds);
+ /**
+ * Only implemented for AIDL. Provides the APM configuration which
+ * used to be in the XML file.
+ */
+ AudioPolicyConfig getAudioPolicyConfig();
+
// When adding a new method, please review and update
// IAudioFlinger.h AudioFlingerServerAdapter::Delegate::TransactionCode
// AudioFlinger.cpp AudioFlinger::onTransactWrapper()
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 1bfe34d..8f8c9dd 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -23,6 +23,7 @@
#include <vector>
#include <android/content/AttributionSourceState.h>
+#include <android/media/AudioPolicyConfig.h>
#include <android/media/AudioPortFw.h>
#include <android/media/AudioVibratorInfo.h>
#include <android/media/BnAudioFlingerClient.h>
@@ -663,6 +664,8 @@
audio_port_handle_t portId,
uid_t uid);
+ static status_t getAudioPolicyConfig(media::AudioPolicyConfig *config);
+
// A listener for capture state changes.
class CaptureStateListener : public virtual RefBase {
public:
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index 6e28d51..2e2ef65 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -382,6 +382,8 @@
virtual status_t isBluetoothVariableLatencyEnabled(bool* enabled) = 0;
virtual status_t supportsBluetoothVariableLatency(bool* support) = 0;
+
+ virtual status_t getAudioPolicyConfig(media::AudioPolicyConfig* output) = 0;
};
/**
@@ -495,6 +497,7 @@
status_t getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback,
sp<media::ISoundDose>* soundDose) override;
status_t invalidateTracks(const std::vector<audio_port_handle_t>& portIds) override;
+ status_t getAudioPolicyConfig(media::AudioPolicyConfig* output) override;
private:
const sp<media::IAudioFlingerService> mDelegate;
@@ -594,6 +597,8 @@
media::BnAudioFlingerService::TRANSACTION_supportsBluetoothVariableLatency,
GET_SOUND_DOSE_INTERFACE = media::BnAudioFlingerService::TRANSACTION_getSoundDoseInterface,
INVALIDATE_TRACKS = media::BnAudioFlingerService::TRANSACTION_invalidateTracks,
+ GET_AUDIO_POLICY_CONFIG =
+ media::BnAudioFlingerService::TRANSACTION_getAudioPolicyConfig,
};
protected:
@@ -726,6 +731,7 @@
Status getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback,
sp<media::ISoundDose>* _aidl_return) override;
Status invalidateTracks(const std::vector<int32_t>& portIds) override;
+ Status getAudioPolicyConfig(media::AudioPolicyConfig* _aidl_return) override;
private:
const sp<AudioFlingerServerAdapter::Delegate> mDelegate;
};
diff --git a/media/libaudiohal/impl/DeviceHalAidl.cpp b/media/libaudiohal/impl/DeviceHalAidl.cpp
index f993907..865d1d6 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalAidl.cpp
@@ -107,8 +107,26 @@
return cpp;
}
+template<typename T>
+std::shared_ptr<T> retrieveSubInterface(const std::shared_ptr<IModule>& module,
+ ::ndk::ScopedAStatus (IModule::*getT)(std::shared_ptr<T>*)) {
+ if (module != nullptr) {
+ std::shared_ptr<T> instance;
+ if (auto status = (module.get()->*getT)(&instance); status.isOk()) {
+ return instance;
+ }
+ }
+ return nullptr;
+}
+
} // namespace
+DeviceHalAidl::DeviceHalAidl(const std::string& instance, const std::shared_ptr<IModule>& module)
+ : ConversionHelperAidl("DeviceHalAidl"),
+ mInstance(instance), mModule(module),
+ mTelephony(retrieveSubInterface<ITelephony>(module, &IModule::getTelephony)) {
+}
+
status_t DeviceHalAidl::getAudioPorts(std::vector<media::audio::common::AudioPort> *ports) {
auto convertAudioPortFromMap = [](const Ports::value_type& pair) {
return ndk2cpp_AudioPort(pair.second);
@@ -124,6 +142,22 @@
return OK;
}
+status_t DeviceHalAidl::getSupportedModes(std::vector<media::audio::common::AudioMode> *modes) {
+ TIME_CHECK();
+ if (modes == nullptr) {
+ return BAD_VALUE;
+ }
+ if (mModule == nullptr) return NO_INIT;
+ if (mTelephony == nullptr) return INVALID_OPERATION;
+ std::vector<AudioMode> aidlModes;
+ RETURN_STATUS_IF_ERROR(
+ statusTFromBinderStatus(mTelephony->getSupportedAudioModes(&aidlModes)));
+ *modes = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::convertContainer<std::vector<media::audio::common::AudioMode>>(
+ aidlModes, ndk2cpp_AudioMode));
+ return OK;
+}
+
status_t DeviceHalAidl::getSupportedDevices(uint32_t*) {
// Obsolete.
return INVALID_OPERATION;
@@ -175,17 +209,14 @@
status_t DeviceHalAidl::setVoiceVolume(float volume) {
TIME_CHECK();
if (!mModule) return NO_INIT;
- std::shared_ptr<ITelephony> telephony;
- if (ndk::ScopedAStatus status = mModule->getTelephony(&telephony);
- status.isOk() && telephony != nullptr) {
- ITelephony::TelecomConfig inConfig{ .voiceVolume = Float{volume} }, outConfig;
- RETURN_STATUS_IF_ERROR(
- statusTFromBinderStatus(telephony->setTelecomConfig(inConfig, &outConfig)));
- ALOGW_IF(outConfig.voiceVolume.has_value() && volume != outConfig.voiceVolume.value().value,
- "%s: the resulting voice volume %f is not the same as requested %f",
- __func__, outConfig.voiceVolume.value().value, volume);
- }
- return INVALID_OPERATION;
+ if (mTelephony == nullptr) return INVALID_OPERATION;
+ ITelephony::TelecomConfig inConfig{ .voiceVolume = Float{volume} }, outConfig;
+ RETURN_STATUS_IF_ERROR(
+ statusTFromBinderStatus(mTelephony->setTelecomConfig(inConfig, &outConfig)));
+ ALOGW_IF(outConfig.voiceVolume.has_value() && volume != outConfig.voiceVolume.value().value,
+ "%s: the resulting voice volume %f is not the same as requested %f",
+ __func__, outConfig.voiceVolume.value().value, volume);
+ return OK;
}
status_t DeviceHalAidl::setMasterVolume(float volume) {
@@ -204,10 +235,8 @@
TIME_CHECK();
if (!mModule) return NO_INIT;
AudioMode audioMode = VALUE_OR_FATAL(::aidl::android::legacy2aidl_audio_mode_t_AudioMode(mode));
- std::shared_ptr<ITelephony> telephony;
- if (ndk::ScopedAStatus status = mModule->getTelephony(&telephony);
- status.isOk() && telephony != nullptr) {
- RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(telephony->switchAudioMode(audioMode)));
+ if (mTelephony != nullptr) {
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mTelephony->switchAudioMode(audioMode)));
}
return statusTFromBinderStatus(mModule->updateAudioMode(audioMode));
}
diff --git a/media/libaudiohal/impl/DeviceHalAidl.h b/media/libaudiohal/impl/DeviceHalAidl.h
index f2c64de..5c9950b 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.h
+++ b/media/libaudiohal/impl/DeviceHalAidl.h
@@ -73,6 +73,8 @@
status_t getAudioRoutes(std::vector<media::AudioRoute> *routes) override;
+ status_t getSupportedModes(std::vector<media::audio::common::AudioMode> *modes) override;
+
// Sets the value of 'devices' to a bitmask of 1 or more values of audio_devices_t.
status_t getSupportedDevices(uint32_t *devices) override;
@@ -201,8 +203,7 @@
// Must not be constructed directly by clients.
DeviceHalAidl(
const std::string& instance,
- const std::shared_ptr<::aidl::android::hardware::audio::core::IModule>& module)
- : ConversionHelperAidl("DeviceHalAidl"), mInstance(instance), mModule(module) {}
+ const std::shared_ptr<::aidl::android::hardware::audio::core::IModule>& module);
~DeviceHalAidl() override = default;
@@ -286,6 +287,7 @@
const std::string mInstance;
const std::shared_ptr<::aidl::android::hardware::audio::core::IModule> mModule;
+ const std::shared_ptr<::aidl::android::hardware::audio::core::ITelephony> mTelephony;
std::shared_ptr<::aidl::android::hardware::audio::core::sounddose::ISoundDose>
mSoundDose = nullptr;
Ports mPorts;
diff --git a/media/libaudiohal/impl/DeviceHalHidl.cpp b/media/libaudiohal/impl/DeviceHalHidl.cpp
index d67cbdc..826461f 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalHidl.cpp
@@ -113,6 +113,11 @@
return INVALID_OPERATION;
}
+status_t DeviceHalHidl::getSupportedModes(
+ std::vector<media::audio::common::AudioMode> *modes __unused) {
+ return INVALID_OPERATION;
+}
+
status_t DeviceHalHidl::getSupportedDevices(uint32_t*) {
// Obsolete.
return INVALID_OPERATION;
diff --git a/media/libaudiohal/impl/DeviceHalHidl.h b/media/libaudiohal/impl/DeviceHalHidl.h
index 7222f03..c5addde 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.h
+++ b/media/libaudiohal/impl/DeviceHalHidl.h
@@ -33,6 +33,8 @@
status_t getAudioRoutes(std::vector<media::AudioRoute> *routes) override;
+ status_t getSupportedModes(std::vector<media::audio::common::AudioMode> *modes) override;
+
// Sets the value of 'devices' to a bitmask of 1 or more values of audio_devices_t.
status_t getSupportedDevices(uint32_t *devices) override;
diff --git a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
index 45f2922..71e5e7a 100644
--- a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
@@ -19,6 +19,7 @@
#include <android/media/audio/common/AudioMMapPolicyInfo.h>
#include <android/media/audio/common/AudioMMapPolicyType.h>
+#include <android/media/audio/common/AudioMode.h>
#include <android/media/audio/common/AudioPort.h>
#include <android/media/AudioRoute.h>
#include <error/Result.h>
@@ -44,6 +45,8 @@
virtual status_t getAudioRoutes(std::vector<media::AudioRoute> *routes) = 0;
+ virtual status_t getSupportedModes(std::vector<media::audio::common::AudioMode> *modes) = 0;
+
// Sets the value of 'devices' to a bitmask of 1 or more values of audio_devices_t.
virtual status_t getSupportedDevices(uint32_t *devices) = 0;
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index f69307b..ab197f8 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -111,6 +111,7 @@
using media::IEffectClient;
using media::audio::common::AudioMMapPolicyInfo;
using media::audio::common::AudioMMapPolicyType;
+using media::audio::common::AudioMode;
using android::content::AttributionSourceState;
using android::detail::AudioHalVersionInfo;
@@ -236,6 +237,7 @@
BINDER_METHOD_ENTRY(isBluetoothVariableLatencyEnabled) \
BINDER_METHOD_ENTRY(supportsBluetoothVariableLatency) \
BINDER_METHOD_ENTRY(getSoundDoseInterface) \
+BINDER_METHOD_ENTRY(getAudioPolicyConfig) \
// singleton for Binder Method Statistics for IAudioFlinger
static auto& getIAudioFlingerStatistics() {
@@ -2573,6 +2575,47 @@
// ----------------------------------------------------------------------------
+status_t AudioFlinger::getAudioPolicyConfig(media::AudioPolicyConfig *config)
+{
+ if (config == nullptr) {
+ return BAD_VALUE;
+ }
+ Mutex::Autolock _l(mLock);
+ AutoMutex lock(mHardwareLock);
+ RETURN_STATUS_IF_ERROR(
+ mDevicesFactoryHal->getSurroundSoundConfig(&config->surroundSoundConfig));
+ RETURN_STATUS_IF_ERROR(mDevicesFactoryHal->getEngineConfig(&config->engineConfig));
+ std::vector<std::string> hwModuleNames;
+ RETURN_STATUS_IF_ERROR(mDevicesFactoryHal->getDeviceNames(&hwModuleNames));
+ std::set<AudioMode> allSupportedModes;
+ for (const auto& name : hwModuleNames) {
+ AudioHwDevice* module = loadHwModule_l(name.c_str());
+ if (module == nullptr) continue;
+ media::AudioHwModule aidlModule;
+ if (module->hwDevice()->getAudioPorts(&aidlModule.ports) == OK &&
+ module->hwDevice()->getAudioRoutes(&aidlModule.routes) == OK) {
+ aidlModule.handle = module->handle();
+ aidlModule.name = module->moduleName();
+ config->modules.push_back(std::move(aidlModule));
+ }
+ std::vector<AudioMode> supportedModes;
+ if (module->hwDevice()->getSupportedModes(&supportedModes) == OK) {
+ allSupportedModes.insert(supportedModes.begin(), supportedModes.end());
+ }
+ }
+ if (!allSupportedModes.empty()) {
+ config->supportedModes.insert(config->supportedModes.end(),
+ allSupportedModes.begin(), allSupportedModes.end());
+ } else {
+ ALOGW("%s: The HAL does not provide telephony functionality", __func__);
+ config->supportedModes = { media::audio::common::AudioMode::NORMAL,
+ media::audio::common::AudioMode::RINGTONE,
+ media::audio::common::AudioMode::IN_CALL,
+ media::audio::common::AudioMode::IN_COMMUNICATION };
+ }
+ return OK;
+}
+
audio_module_handle_t AudioFlinger::loadHwModule(const char *name)
{
if (name == NULL) {
@@ -2583,16 +2626,17 @@
}
Mutex::Autolock _l(mLock);
AutoMutex lock(mHardwareLock);
- return loadHwModule_l(name);
+ AudioHwDevice* module = loadHwModule_l(name);
+ return module != nullptr ? module->handle() : AUDIO_MODULE_HANDLE_NONE;
}
// loadHwModule_l() must be called with AudioFlinger::mLock and AudioFlinger::mHardwareLock held
-audio_module_handle_t AudioFlinger::loadHwModule_l(const char *name)
+AudioHwDevice* AudioFlinger::loadHwModule_l(const char *name)
{
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
if (strncmp(mAudioHwDevs.valueAt(i)->moduleName(), name, strlen(name)) == 0) {
ALOGW("loadHwModule() module %s already loaded", name);
- return mAudioHwDevs.keyAt(i);
+ return mAudioHwDevs.valueAt(i);
}
}
@@ -2601,7 +2645,7 @@
int rc = mDevicesFactoryHal->openDevice(name, &dev);
if (rc) {
ALOGE("loadHwModule() error %d loading module %s", rc, name);
- return AUDIO_MODULE_HANDLE_NONE;
+ return nullptr;
}
if (!mMelReporter->activateHalSoundDoseComputation(name, dev)) {
ALOGW("loadHwModule() sound dose reporting is not available");
@@ -2612,7 +2656,7 @@
mHardwareStatus = AUDIO_HW_IDLE;
if (rc) {
ALOGE("loadHwModule() init check error %d for module %s", rc, name);
- return AUDIO_MODULE_HANDLE_NONE;
+ return nullptr;
}
// Check and cache this HAL's level of support for master mute and master
@@ -2686,8 +2730,7 @@
ALOGI("loadHwModule() Loaded %s audio interface, handle %d", name, handle);
- return handle;
-
+ return audioDevice;
}
// ----------------------------------------------------------------------------
@@ -4729,6 +4772,7 @@
case TransactionCode::SET_REQUESTED_LATENCY_MODE:
case TransactionCode::GET_SUPPORTED_LATENCY_MODES:
case TransactionCode::INVALIDATE_TRACKS:
+ case TransactionCode::GET_AUDIO_POLICY_CONFIG:
ALOGW("%s: transaction %d received from PID %d",
__func__, code, IPCThreadState::self()->getCallingPid());
// return status only for non void methods
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 47fa74f..10bfdb9 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -319,6 +319,8 @@
status_t invalidateTracks(const std::vector<audio_port_handle_t>& portIds) override;
+ virtual status_t getAudioPolicyConfig(media::AudioPolicyConfig* config);
+
status_t onTransactWrapper(TransactionCode code, const Parcel& data, uint32_t flags,
const std::function<status_t()>& delegate) override;
@@ -990,7 +992,7 @@
float masterVolume_l() const;
float getMasterBalance_l() const;
bool masterMute_l() const;
- audio_module_handle_t loadHwModule_l(const char *name);
+ AudioHwDevice* loadHwModule_l(const char *name);
Vector < sp<SyncEvent> > mPendingSyncEvents; // sync events awaiting for a session
// to be created
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 19e4151..f324408 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -3407,12 +3407,20 @@
} else if (patch.isSoftware() || patch.thread().promote() != nullptr) {
sp <ThreadBase> thread;
if (audio_port_config_has_input_direction(port)) {
+ if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) {
+ ALOGI("%s don't create postprocessing effect on record thread", __func__);
+ return NAME_NOT_FOUND;
+ }
if (patch.isSoftware()) {
thread = patch.mRecord.thread();
} else {
thread = patch.thread().promote();
}
} else {
+ if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC) {
+ ALOGI("%s don't create preprocessing effect on playback thread", __func__);
+ return NAME_NOT_FOUND;
+ }
if (patch.isSoftware()) {
thread = patch.mPlayback.thread();
} else {
diff --git a/services/audioflinger/MelReporter.cpp b/services/audioflinger/MelReporter.cpp
index e024319..39f772b 100644
--- a/services/audioflinger/MelReporter.cpp
+++ b/services/audioflinger/MelReporter.cpp
@@ -95,7 +95,6 @@
// TODO(b/278265907): enable A2DP when we can distinguish A2DP headsets
// case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP:
case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
- case AUDIO_DEVICE_OUT_HEARING_AID:
case AUDIO_DEVICE_OUT_USB_HEADSET:
case AUDIO_DEVICE_OUT_BLE_HEADSET:
case AUDIO_DEVICE_OUT_BLE_BROADCAST:
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 134d068..da0df5f 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -438,6 +438,8 @@
public:
virtual ~AudioPolicyClientInterface() {}
+ virtual status_t getAudioPolicyConfig(media::AudioPolicyConfig *config) = 0;
+
//
// Audio HW module functions
//
diff --git a/services/audiopolicy/common/managerdefinitions/Android.bp b/services/audiopolicy/common/managerdefinitions/Android.bp
index 92a5628..1d570b7 100644
--- a/services/audiopolicy/common/managerdefinitions/Android.bp
+++ b/services/audiopolicy/common/managerdefinitions/Android.bp
@@ -15,6 +15,7 @@
"src/AudioInputDescriptor.cpp",
"src/AudioOutputDescriptor.cpp",
"src/AudioPatch.cpp",
+ "src/AudioPolicyConfig.cpp",
"src/AudioPolicyMix.cpp",
"src/AudioProfileVectorHelper.cpp",
"src/AudioRoute.cpp",
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
index a62d3f0..32c78a1 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
@@ -16,62 +16,58 @@
#pragma once
+#include <string>
#include <unordered_map>
#include <unordered_set>
+#include <vector>
-#include <AudioPatch.h>
#include <DeviceDescriptor.h>
-#include <IOProfile.h>
#include <HwModule.h>
-#include <PolicyAudioPort.h>
-#include <AudioInputDescriptor.h>
-#include <AudioOutputDescriptor.h>
-#include <AudioPolicyMix.h>
-#include <EffectDescriptor.h>
-#include <SoundTriggerSession.h>
-#include <media/AudioProfile.h>
+#include <error/Result.h>
+#include <utils/StrongPointer.h>
+#include <utils/RefBase.h>
namespace android {
-// This class gathers together various bits of AudioPolicyManager
-// configuration, which are usually filled out as a result of parsing
-// the audio_policy_configuration.xml file.
+// This class gathers together various bits of AudioPolicyManager configuration. It can be filled
+// out either as a result of parsing the audio_policy_configuration.xml file, from the HAL data, or
+// to default fallback data.
//
-// Note that AudioPolicyConfig doesn't own some of the data,
-// it simply proxies access to the fields of AudioPolicyManager
-// class. Be careful about the fields that are references,
-// e.g. 'mOutputDevices'. This also means that it's impossible
-// to implement "deep copying" of this class without re-designing it.
-class AudioPolicyConfig
+// The data in this class is immutable once loaded, this is why a pointer to a const is returned
+// from the factory methods. However, this does not prevent modifications of data bits that
+// are held inside collections, for example, individual modules, devices, etc.
+class AudioPolicyConfig : public RefBase
{
public:
- AudioPolicyConfig(HwModuleCollection &hwModules,
- DeviceVector &outputDevices,
- DeviceVector &inputDevices,
- sp<DeviceDescriptor> &defaultOutputDevice)
- : mHwModules(hwModules),
- mOutputDevices(outputDevices),
- mInputDevices(inputDevices),
- mDefaultOutputDevice(defaultOutputDevice) {
- clear();
- }
+ // Surround formats, with an optional list of subformats that are equivalent from users' POV.
+ using SurroundFormats = std::unordered_map<audio_format_t, std::unordered_set<audio_format_t>>;
- void clear() {
- mSource = {};
- mEngineLibraryNameSuffix = kDefaultEngineLibraryNameSuffix;
- mHwModules.clear();
- mOutputDevices.clear();
- mInputDevices.clear();
- mDefaultOutputDevice.clear();
- mIsSpeakerDrcEnabled = false;
- mIsCallScreenModeSupported = false;
- mSurroundFormats.clear();
- }
+ // The source used to indicate the default fallback configuration.
+ static const constexpr char* const kDefaultConfigSource = "AudioPolicyConfig::setDefault";
+ // The suffix of the "engine default" implementation shared library name.
+ static const constexpr char* const kDefaultEngineLibraryNameSuffix = "default";
+
+ // Creates the default (fallback) configuration.
+ static sp<const AudioPolicyConfig> createDefault();
+ // Attempts to load the configuration from the XML file, falls back to default on failure.
+ // If the XML file path is not provided, uses `audio_get_audio_policy_config_file` function.
+ static sp<const AudioPolicyConfig> loadFromApmXmlConfigWithFallback(
+ const std::string& xmlFilePath = "");
+ // The factory method to use in APM tests which craft the configuration manually.
+ static sp<AudioPolicyConfig> createWritableForTests();
+ // The factory method to use in APM tests which use a custom XML file.
+ static error::Result<sp<AudioPolicyConfig>> loadFromCustomXmlConfigForTests(
+ const std::string& xmlFilePath);
+ // The factory method to use in VTS tests. If the 'configPath' is empty,
+ // it is determined automatically from the list of known config paths.
+ static error::Result<sp<AudioPolicyConfig>> loadFromCustomXmlConfigForVtsTests(
+ const std::string& configPath, const std::string& xmlFileName);
+
+ ~AudioPolicyConfig() = default;
const std::string& getSource() const {
return mSource;
}
-
void setSource(const std::string& file) {
mSource = file;
}
@@ -79,16 +75,24 @@
const std::string& getEngineLibraryNameSuffix() const {
return mEngineLibraryNameSuffix;
}
-
void setEngineLibraryNameSuffix(const std::string& suffix) {
mEngineLibraryNameSuffix = suffix;
}
+ const HwModuleCollection& getHwModules() const { return mHwModules; }
void setHwModules(const HwModuleCollection &hwModules)
{
mHwModules = hwModules;
}
+ const DeviceVector& getInputDevices() const
+ {
+ return mInputDevices;
+ }
+ const DeviceVector& getOutputDevices() const
+ {
+ return mOutputDevices;
+ }
void addDevice(const sp<DeviceDescriptor> &device)
{
if (audio_is_output_device(device->type())) {
@@ -97,128 +101,54 @@
mInputDevices.add(device);
}
}
-
void addInputDevices(const DeviceVector &inputDevices)
{
mInputDevices.add(inputDevices);
}
-
void addOutputDevices(const DeviceVector &outputDevices)
{
mOutputDevices.add(outputDevices);
}
- bool isSpeakerDrcEnabled() const { return mIsSpeakerDrcEnabled; }
-
- void setSpeakerDrcEnabled(bool isSpeakerDrcEnabled)
- {
- mIsSpeakerDrcEnabled = isSpeakerDrcEnabled;
- }
-
- bool isCallScreenModeSupported() const { return mIsCallScreenModeSupported; }
-
- void setCallScreenModeSupported(bool isCallScreenModeSupported)
- {
- mIsCallScreenModeSupported = isCallScreenModeSupported;
- }
-
-
- const HwModuleCollection getHwModules() const { return mHwModules; }
-
- const DeviceVector &getInputDevices() const
- {
- return mInputDevices;
- }
-
- const DeviceVector &getOutputDevices() const
- {
- return mOutputDevices;
- }
-
+ const sp<DeviceDescriptor>& getDefaultOutputDevice() const { return mDefaultOutputDevice; }
void setDefaultOutputDevice(const sp<DeviceDescriptor> &defaultDevice)
{
mDefaultOutputDevice = defaultDevice;
}
- const sp<DeviceDescriptor> &getDefaultOutputDevice() const { return mDefaultOutputDevice; }
-
- void setDefault(void)
+ bool isCallScreenModeSupported() const { return mIsCallScreenModeSupported; }
+ void setCallScreenModeSupported(bool isCallScreenModeSupported)
{
- mSource = "AudioPolicyConfig::setDefault";
- mEngineLibraryNameSuffix = kDefaultEngineLibraryNameSuffix;
- mDefaultOutputDevice = new DeviceDescriptor(AUDIO_DEVICE_OUT_SPEAKER);
- mDefaultOutputDevice->addAudioProfile(AudioProfile::createFullDynamic(gDynamicFormat));
- sp<DeviceDescriptor> defaultInputDevice = new DeviceDescriptor(AUDIO_DEVICE_IN_BUILTIN_MIC);
- defaultInputDevice->addAudioProfile(AudioProfile::createFullDynamic(gDynamicFormat));
- sp<AudioProfile> micProfile = new AudioProfile(
- AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_MONO, 8000);
- defaultInputDevice->addAudioProfile(micProfile);
- mOutputDevices.add(mDefaultOutputDevice);
- mInputDevices.add(defaultInputDevice);
-
- sp<HwModule> module = new HwModule(AUDIO_HARDWARE_MODULE_ID_PRIMARY, 2 /*halVersionMajor*/);
- mHwModules.add(module);
-
- sp<OutputProfile> outProfile = new OutputProfile("primary");
- outProfile->addAudioProfile(
- new AudioProfile(AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 44100));
- outProfile->addSupportedDevice(mDefaultOutputDevice);
- outProfile->setFlags(AUDIO_OUTPUT_FLAG_PRIMARY);
- module->addOutputProfile(outProfile);
-
- sp<InputProfile> inProfile = new InputProfile("primary");
- inProfile->addAudioProfile(micProfile);
- inProfile->addSupportedDevice(defaultInputDevice);
- module->addInputProfile(inProfile);
-
- setDefaultSurroundFormats();
+ mIsCallScreenModeSupported = isCallScreenModeSupported;
}
- // Surround formats, with an optional list of subformats that are equivalent from users' POV.
- using SurroundFormats = std::unordered_map<audio_format_t, std::unordered_set<audio_format_t>>;
-
const SurroundFormats &getSurroundFormats() const
{
return mSurroundFormats;
}
-
+ void setDefaultSurroundFormats();
void setSurroundFormats(const SurroundFormats &surroundFormats)
{
mSurroundFormats = surroundFormats;
}
- void setDefaultSurroundFormats()
- {
- mSurroundFormats = {
- {AUDIO_FORMAT_AC3, {}},
- {AUDIO_FORMAT_E_AC3, {}},
- {AUDIO_FORMAT_DTS, {}},
- {AUDIO_FORMAT_DTS_HD, {}},
- {AUDIO_FORMAT_DTS_HD_MA, {}},
- {AUDIO_FORMAT_DTS_UHD, {}},
- {AUDIO_FORMAT_DTS_UHD_P2, {}},
- {AUDIO_FORMAT_AAC_LC, {
- AUDIO_FORMAT_AAC_HE_V1, AUDIO_FORMAT_AAC_HE_V2, AUDIO_FORMAT_AAC_ELD,
- AUDIO_FORMAT_AAC_XHE}},
- {AUDIO_FORMAT_DOLBY_TRUEHD, {}},
- {AUDIO_FORMAT_E_AC3_JOC, {}},
- {AUDIO_FORMAT_AC4, {}}};
- }
+ void setDefault();
private:
- static const constexpr char* const kDefaultEngineLibraryNameSuffix = "default";
+ friend class sp<AudioPolicyConfig>;
- std::string mSource;
- std::string mEngineLibraryNameSuffix;
- HwModuleCollection &mHwModules; /**< Collection of Module, with Profiles, i.e. Mix Ports. */
- DeviceVector &mOutputDevices;
- DeviceVector &mInputDevices;
- sp<DeviceDescriptor> &mDefaultOutputDevice;
- // TODO: remove when legacy conf file is removed. true on devices that use DRC on the
- // DEVICE_CATEGORY_SPEAKER path to boost soft sounds, used to adjust volume curves accordingly.
- // Note: remove also speaker_drc_enabled from global configuration of XML config file.
- bool mIsSpeakerDrcEnabled;
- bool mIsCallScreenModeSupported;
+ AudioPolicyConfig() = default;
+
+ void augmentData();
+ status_t loadFromXml(const std::string& xmlFilePath, bool forVts);
+
+ std::string mSource; // Not kDefaultConfigSource. Empty source means an empty config.
+ std::string mEngineLibraryNameSuffix = kDefaultEngineLibraryNameSuffix;
+ HwModuleCollection mHwModules; /**< Collection of Module, with Profiles, i.e. Mix Ports. */
+ DeviceVector mOutputDevices; // Attached output devices.
+ DeviceVector mInputDevices; // Attached input devices.
+ sp<DeviceDescriptor> mDefaultOutputDevice;
+ bool mIsCallScreenModeSupported = false;
SurroundFormats mSurroundFormats;
};
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp
new file mode 100644
index 0000000..42c76e2
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "APM_Config"
+
+#include <AudioPolicyConfig.h>
+#include <IOProfile.h>
+#include <Serializer.h>
+#include <media/AudioProfile.h>
+#include <system/audio.h>
+#include <system/audio_config.h>
+#include <utils/Log.h>
+
+namespace android {
+
+// static
+sp<const AudioPolicyConfig> AudioPolicyConfig::createDefault() {
+ auto config = sp<AudioPolicyConfig>::make();
+ config->setDefault();
+ return config;
+}
+
+// static
+sp<const AudioPolicyConfig> AudioPolicyConfig::loadFromApmXmlConfigWithFallback(
+ const std::string& xmlFilePath) {
+ const std::string filePath =
+ xmlFilePath.empty() ? audio_get_audio_policy_config_file() : xmlFilePath;
+ auto config = sp<AudioPolicyConfig>::make();
+ if (status_t status = config->loadFromXml(filePath, false /*forVts*/); status == NO_ERROR) {
+ return config;
+ }
+ return createDefault();
+}
+
+// static
+sp<AudioPolicyConfig> AudioPolicyConfig::createWritableForTests() {
+ return sp<AudioPolicyConfig>::make();
+}
+
+// static
+error::Result<sp<AudioPolicyConfig>> AudioPolicyConfig::loadFromCustomXmlConfigForTests(
+ const std::string& xmlFilePath) {
+ auto config = sp<AudioPolicyConfig>::make();
+ if (status_t status = config->loadFromXml(xmlFilePath, false /*forVts*/); status == NO_ERROR) {
+ return config;
+ } else {
+ return base::unexpected(status);
+ }
+}
+
+// static
+error::Result<sp<AudioPolicyConfig>> AudioPolicyConfig::loadFromCustomXmlConfigForVtsTests(
+ const std::string& configPath, const std::string& xmlFileName) {
+ auto filePath = configPath;
+ if (filePath.empty()) {
+ for (const auto& location : audio_get_configuration_paths()) {
+ std::string path = location + '/' + xmlFileName;
+ if (access(path.c_str(), F_OK) == 0) {
+ filePath = location;
+ break;
+ }
+ }
+ }
+ if (filePath.empty()) {
+ ALOGE("Did not find a config file \"%s\" among known config paths", xmlFileName.c_str());
+ return base::unexpected(BAD_VALUE);
+ }
+ auto config = sp<AudioPolicyConfig>::make();
+ if (status_t status = config->loadFromXml(filePath + "/" + xmlFileName, true /*forVts*/);
+ status == NO_ERROR) {
+ return config;
+ } else {
+ return base::unexpected(status);
+ }
+}
+
+void AudioPolicyConfig::augmentData() {
+ // If microphones address is empty, set it according to device type
+ for (size_t i = 0; i < mInputDevices.size(); i++) {
+ if (mInputDevices[i]->address().empty()) {
+ if (mInputDevices[i]->type() == AUDIO_DEVICE_IN_BUILTIN_MIC) {
+ mInputDevices[i]->setAddress(AUDIO_BOTTOM_MICROPHONE_ADDRESS);
+ } else if (mInputDevices[i]->type() == AUDIO_DEVICE_IN_BACK_MIC) {
+ mInputDevices[i]->setAddress(AUDIO_BACK_MICROPHONE_ADDRESS);
+ }
+ }
+ }
+}
+
+status_t AudioPolicyConfig::loadFromXml(const std::string& xmlFilePath, bool forVts) {
+ if (xmlFilePath.empty()) {
+ ALOGE("Audio policy configuration file name is empty");
+ return BAD_VALUE;
+ }
+ status_t status = forVts ? deserializeAudioPolicyFileForVts(xmlFilePath.c_str(), this)
+ : deserializeAudioPolicyFile(xmlFilePath.c_str(), this);
+ if (status == NO_ERROR) {
+ mSource = xmlFilePath;
+ augmentData();
+ } else {
+ ALOGE("Could not load audio policy from the configuration file \"%s\": %d",
+ xmlFilePath.c_str(), status);
+ }
+ return status;
+}
+
+void AudioPolicyConfig::setDefault() {
+ mSource = kDefaultConfigSource;
+ mEngineLibraryNameSuffix = kDefaultEngineLibraryNameSuffix;
+
+ mDefaultOutputDevice = new DeviceDescriptor(AUDIO_DEVICE_OUT_SPEAKER);
+ mDefaultOutputDevice->addAudioProfile(AudioProfile::createFullDynamic(gDynamicFormat));
+ sp<DeviceDescriptor> defaultInputDevice = new DeviceDescriptor(AUDIO_DEVICE_IN_BUILTIN_MIC);
+ defaultInputDevice->addAudioProfile(AudioProfile::createFullDynamic(gDynamicFormat));
+ sp<AudioProfile> micProfile = new AudioProfile(
+ AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_MONO, 8000);
+ defaultInputDevice->addAudioProfile(micProfile);
+ mOutputDevices.add(mDefaultOutputDevice);
+ mInputDevices.add(defaultInputDevice);
+
+ sp<HwModule> module = new HwModule(AUDIO_HARDWARE_MODULE_ID_PRIMARY, 2 /*halVersionMajor*/);
+ mHwModules.add(module);
+
+ sp<OutputProfile> outProfile = new OutputProfile("primary");
+ outProfile->addAudioProfile(
+ new AudioProfile(AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 44100));
+ outProfile->addSupportedDevice(mDefaultOutputDevice);
+ outProfile->setFlags(AUDIO_OUTPUT_FLAG_PRIMARY);
+ module->addOutputProfile(outProfile);
+
+ sp<InputProfile> inProfile = new InputProfile("primary");
+ inProfile->addAudioProfile(micProfile);
+ inProfile->addSupportedDevice(defaultInputDevice);
+ module->addInputProfile(inProfile);
+
+ setDefaultSurroundFormats();
+ augmentData();
+}
+
+void AudioPolicyConfig::setDefaultSurroundFormats() {
+ mSurroundFormats = {
+ {AUDIO_FORMAT_AC3, {}},
+ {AUDIO_FORMAT_E_AC3, {}},
+ {AUDIO_FORMAT_DTS, {}},
+ {AUDIO_FORMAT_DTS_HD, {}},
+ {AUDIO_FORMAT_DTS_HD_MA, {}},
+ {AUDIO_FORMAT_DTS_UHD, {}},
+ {AUDIO_FORMAT_DTS_UHD_P2, {}},
+ {AUDIO_FORMAT_AAC_LC, {
+ AUDIO_FORMAT_AAC_HE_V1, AUDIO_FORMAT_AAC_HE_V2, AUDIO_FORMAT_AAC_ELD,
+ AUDIO_FORMAT_AAC_XHE}},
+ {AUDIO_FORMAT_DOLBY_TRUEHD, {}},
+ {AUDIO_FORMAT_E_AC3_JOC, {}},
+ {AUDIO_FORMAT_AC4, {}}};
+}
+
+} // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
index d446e96..3d5c1d2 100644
--- a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
@@ -29,6 +29,7 @@
#include <utils/StrongPointer.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
+#include "IOProfile.h"
#include "Serializer.h"
#include "TypeConverter.h"
@@ -196,7 +197,6 @@
struct Attributes
{
- static constexpr const char *speakerDrcEnabled = "speaker_drc_enabled";
static constexpr const char *callScreenModeSupported= "call_screen_mode_supported";
static constexpr const char *engineLibrarySuffix = "engine_library";
};
@@ -769,12 +769,7 @@
for (const xmlNode *cur = root->xmlChildrenNode; cur != NULL; cur = cur->next) {
if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(GlobalConfigTraits::tag))) {
bool value;
- std::string attr = getXmlAttribute(cur, Attributes::speakerDrcEnabled);
- if (!attr.empty() &&
- convertTo<std::string, bool>(attr, value)) {
- config->setSpeakerDrcEnabled(value);
- }
- attr = getXmlAttribute(cur, Attributes::callScreenModeSupported);
+ std::string attr = getXmlAttribute(cur, Attributes::callScreenModeSupported);
if (!attr.empty() &&
convertTo<std::string, bool>(attr, value)) {
config->setCallScreenModeSupported(value);
@@ -907,7 +902,6 @@
{
PolicySerializer serializer;
status_t status = serializer.deserialize(fileName, config);
- if (status != OK) config->clear();
return status;
}
@@ -915,7 +909,6 @@
{
PolicySerializer serializer;
status_t status = serializer.deserialize(fileName, config, true /*ignoreVendorExtensions*/);
- if (status != OK) config->clear();
return status;
}
diff --git a/services/audiopolicy/engine/common/include/EngineBase.h b/services/audiopolicy/engine/common/include/EngineBase.h
index 7ff0301..bac51f5 100644
--- a/services/audiopolicy/engine/common/include/EngineBase.h
+++ b/services/audiopolicy/engine/common/include/EngineBase.h
@@ -113,7 +113,7 @@
status_t getDevicesForRoleAndStrategy(product_strategy_t strategy, device_role_t role,
AudioDeviceTypeAddrVector &devices) const override;
- engineConfig::ParsingResult loadAudioPolicyEngineConfig();
+ engineConfig::ParsingResult loadAudioPolicyEngineConfig(const std::string& xmlFilePath = "");
const ProductStrategyMap &getProductStrategies() const { return mProductStrategies; }
diff --git a/services/audiopolicy/engine/common/src/EngineBase.cpp b/services/audiopolicy/engine/common/src/EngineBase.cpp
index 5769a97..7d6a308 100644
--- a/services/audiopolicy/engine/common/src/EngineBase.cpp
+++ b/services/audiopolicy/engine/common/src/EngineBase.cpp
@@ -115,7 +115,7 @@
return PRODUCT_STRATEGY_NONE;
}
-engineConfig::ParsingResult EngineBase::loadAudioPolicyEngineConfig()
+engineConfig::ParsingResult EngineBase::loadAudioPolicyEngineConfig(const std::string& xmlFilePath)
{
auto loadVolumeConfig = [](auto &volumeGroups, auto &volumeConfig) {
// Ensure name unicity to prevent duplicate
@@ -163,8 +163,9 @@
return stat(path, &fileStat) == 0 && S_ISREG(fileStat.st_mode);
};
- auto result = fileExists(engineConfig::DEFAULT_PATH) ?
- engineConfig::parse(engineConfig::DEFAULT_PATH) : engineConfig::ParsingResult{};
+ const std::string filePath = xmlFilePath.empty() ? engineConfig::DEFAULT_PATH : xmlFilePath;
+ auto result = fileExists(filePath.c_str()) ?
+ engineConfig::parse(filePath.c_str()) : engineConfig::ParsingResult{};
if (result.parsedConfig == nullptr) {
ALOGD("%s: No configuration found, using default matching phone experience.", __FUNCTION__);
engineConfig::Config config = gDefaultEngineConfig;
diff --git a/services/audiopolicy/engine/interface/EngineInterface.h b/services/audiopolicy/engine/interface/EngineInterface.h
index ea8fc41..dd7ac1a 100644
--- a/services/audiopolicy/engine/interface/EngineInterface.h
+++ b/services/audiopolicy/engine/interface/EngineInterface.h
@@ -16,6 +16,7 @@
#pragma once
+#include <string>
#include <utility>
#include <AudioPolicyManagerObserver.h>
@@ -46,6 +47,13 @@
{
public:
/**
+ * Loads the engine configuration from the specified or the default config file.
+ * If loading failed, tries to fall back to some default configuration. If fallback
+ * is impossible, returns an error.
+ */
+ virtual status_t loadFromXmlConfigWithFallback(const std::string& xmlFilePath = "") = 0;
+
+ /**
* Checks if the engine was correctly initialized.
*
* @return NO_ERROR if initialization has been done correctly, error code otherwise..
diff --git a/services/audiopolicy/engineconfigurable/src/Collection.h b/services/audiopolicy/engineconfigurable/src/Collection.h
index 02b41cb..4640515 100644
--- a/services/audiopolicy/engineconfigurable/src/Collection.h
+++ b/services/audiopolicy/engineconfigurable/src/Collection.h
@@ -53,6 +53,10 @@
{
collectionSupported();
}
+ ~Collection()
+ {
+ clear();
+ }
/**
* Add a policy element to the collection. Policy elements are streams, strategies, input
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.cpp b/services/audiopolicy/engineconfigurable/src/Engine.cpp
index a7f92cd..2eb0177 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Engine.cpp
@@ -68,16 +68,15 @@
Engine::Engine() : mPolicyParameterMgr(new ParameterManagerWrapper())
{
- status_t loadResult = loadAudioPolicyEngineConfig();
+}
+
+status_t Engine::loadFromXmlConfigWithFallback(const std::string& xmlFilePath)
+{
+ status_t loadResult = loadAudioPolicyEngineConfig(xmlFilePath);
if (loadResult < 0) {
ALOGE("Policy Engine configuration is invalid.");
}
-}
-
-Engine::~Engine()
-{
- mStreamCollection.clear();
- mInputSourceCollection.clear();
+ return loadResult;
}
status_t Engine::initCheck()
@@ -93,7 +92,7 @@
template <typename Key>
Element<Key> *Engine::getFromCollection(const Key &key) const
{
- const Collection<Key> collection = getCollection<Key>();
+ const Collection<Key> &collection = getCollection<Key>();
return collection.get(key);
}
@@ -194,9 +193,9 @@
return EngineBase::setDeviceConnectionState(device, state);
}
-status_t Engine::loadAudioPolicyEngineConfig()
+status_t Engine::loadAudioPolicyEngineConfig(const std::string& xmlFilePath)
{
- auto result = EngineBase::loadAudioPolicyEngineConfig();
+ auto result = EngineBase::loadAudioPolicyEngineConfig(xmlFilePath);
// Custom XML Parsing
auto loadCriteria= [this](const auto& configCriteria, const auto& configCriterionTypes) {
@@ -531,5 +530,3 @@
} // namespace audio_policy
} // namespace android
-
-
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.h b/services/audiopolicy/engineconfigurable/src/Engine.h
index 8ea8052..b964cd6 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.h
+++ b/services/audiopolicy/engineconfigurable/src/Engine.h
@@ -33,12 +33,17 @@
{
public:
Engine();
- virtual ~Engine();
+ virtual ~Engine() = default;
template <class RequestedInterface>
RequestedInterface *queryInterface();
///
+ /// from EngineInterface
+ ///
+ android::status_t loadFromXmlConfigWithFallback(const std::string& xmlFilePath = "") override;
+
+ ///
/// from EngineBase
///
android::status_t initCheck() override;
@@ -132,7 +137,7 @@
template <typename Property, typename Key>
bool setPropertyForKey(const Property &property, const Key &key);
- status_t loadAudioPolicyEngineConfig();
+ status_t loadAudioPolicyEngineConfig(const std::string& xmlFilePath);
DeviceVector getCachedDevices(product_strategy_t ps) const;
@@ -150,4 +155,3 @@
} // namespace audio_policy
} // namespace android
-
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index 84e7cb8..88cbb7d 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -59,9 +59,8 @@
return legacyStrategy;
}
-Engine::Engine()
-{
- auto result = EngineBase::loadAudioPolicyEngineConfig();
+status_t Engine::loadFromXmlConfigWithFallback(const std::string& xmlFilePath) {
+ auto result = EngineBase::loadAudioPolicyEngineConfig(xmlFilePath);
ALOGE_IF(result.nbSkippedElement != 0,
"Policy Engine configuration is partially invalid, skipped %zu elements",
result.nbSkippedElement);
@@ -70,6 +69,8 @@
for (const auto &strategy : legacyStrategy) {
mLegacyStrategyMap[getProductStrategyByName(strategy.name)] = strategy.id;
}
+
+ return OK;
}
status_t Engine::setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config)
@@ -845,5 +846,3 @@
} // namespace audio_policy
} // namespace android
-
-
diff --git a/services/audiopolicy/enginedefault/src/Engine.h b/services/audiopolicy/enginedefault/src/Engine.h
index 2e4decf..8410560 100644
--- a/services/audiopolicy/enginedefault/src/Engine.h
+++ b/services/audiopolicy/enginedefault/src/Engine.h
@@ -45,9 +45,14 @@
class Engine : public EngineBase
{
public:
- Engine();
+ Engine() = default;
virtual ~Engine() = default;
+ ///
+ /// from EngineInterface
+ ///
+ status_t loadFromXmlConfigWithFallback(const std::string& xmlFilePath = "") override;
+
private:
///
/// from EngineBase, so from EngineInterface
@@ -105,4 +110,3 @@
};
} // namespace audio_policy
} // namespace android
-
diff --git a/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp b/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp
index 14f565b..8793085 100644
--- a/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp
+++ b/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp
@@ -216,8 +216,9 @@
virtual void process();
protected:
+ sp<AudioPolicyConfig> mConfig{AudioPolicyConfig::createWritableForTests()};
std::unique_ptr<AudioPolicyManagerTestClient> mClient{new AudioPolicyManagerTestClient};
- std::unique_ptr<AudioPolicyTestManager> mManager{new AudioPolicyTestManager(mClient.get())};
+ std::unique_ptr<AudioPolicyTestManager> mManager;
FuzzedDataProvider *mFdp;
};
@@ -230,7 +231,10 @@
}
// init code
SetUpManagerConfig();
-
+ if (mConfig == nullptr) {
+ return false;
+ }
+ mManager.reset(new AudioPolicyTestManager(mConfig, mClient.get()));
if (mManager->initialize() != NO_ERROR) {
return false;
}
@@ -240,7 +244,7 @@
return true;
}
-void AudioPolicyManagerFuzzer::SetUpManagerConfig() { mManager->getConfig().setDefault(); }
+void AudioPolicyManagerFuzzer::SetUpManagerConfig() { mConfig->setDefault(); }
bool AudioPolicyManagerFuzzer::getOutputForAttr(
audio_port_handle_t *selectedDeviceId, audio_format_t format, audio_channel_mask_t channelMask,
@@ -408,7 +412,11 @@
}
void AudioPolicyManagerFuzzerWithConfigurationFile::SetUpManagerConfig() {
- deserializeAudioPolicyFile(getConfigFile().c_str(), &mManager->getConfig());
+ const std::string configFilePath = getConfigFile();
+ auto result = AudioPolicyConfig::loadFromCustomXmlConfigForTests(configFilePath);
+ mConfig = result.ok() ? mConfig = result.value() : nullptr;
+ ALOGE_IF(!result.ok(), "%s: Failed to deserialize \"%s\": %d",
+ __func__, configFilePath.c_str(), result.error());
}
void AudioPolicyManagerFuzzerWithConfigurationFile::traverseAndFuzzXML(xmlDocPtr pDoc,
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index b678662..ab1a050 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1330,7 +1330,7 @@
*selectedDeviceId = getFirstDeviceId(outputDevices);
for (auto &outputDevice : outputDevices) {
- if (outputDevice->getId() == getConfig().getDefaultOutputDevice()->getId()) {
+ if (outputDevice->getId() == mConfig->getDefaultOutputDevice()->getId()) {
*selectedDeviceId = outputDevice->getId();
break;
}
@@ -1915,7 +1915,8 @@
}
bool AudioPolicyManager::msdHasPatchesToAllDevices(const AudioDeviceTypeAddrVector& devices) {
- DeviceVector devicesToCheck = mOutputDevicesAll.getDevicesFromDeviceTypeAddrVec(devices);
+ DeviceVector devicesToCheck =
+ mConfig->getOutputDevices().getDevicesFromDeviceTypeAddrVec(devices);
AudioPatchCollection msdPatches = getMsdOutputPatches();
for (size_t i = 0; i < msdPatches.size(); i++) {
const auto& patch = msdPatches[i];
@@ -4106,13 +4107,13 @@
dst->appendFormat(" TTS output %savailable\n", mTtsOutputAvailable ? "" : "not ");
dst->appendFormat(" Master mono: %s\n", mMasterMono ? "on" : "off");
dst->appendFormat(" Communication Strategy id: %d\n", mCommunnicationStrategy);
- dst->appendFormat(" Config source: %s\n", mConfig.getSource().c_str()); // getConfig not const
+ dst->appendFormat(" Config source: %s\n", mConfig->getSource().c_str());
dst->append("\n");
mAvailableOutputDevices.dump(dst, String8("Available output"), 1);
dst->append("\n");
mAvailableInputDevices.dump(dst, String8("Available input"), 1);
- mHwModulesAll.dump(dst);
+ mHwModules.dump(dst);
mOutputs.dump(dst);
mInputs.dump(dst);
mEffects.dump(dst, 1);
@@ -4619,7 +4620,7 @@
return OK;
};
- for (const auto& module : mHwModulesAll) {
+ for (const auto& module : mHwModules) {
for (const auto& dev : module->getDeclaredDevices()) {
if (role == media::AudioPortRole::NONE ||
((role == media::AudioPortRole::SOURCE)
@@ -5526,10 +5527,10 @@
size_t formatsWritten = 0;
size_t formatsMax = *numSurroundFormats;
- *numSurroundFormats = mConfig.getSurroundFormats().size();
+ *numSurroundFormats = mConfig->getSurroundFormats().size();
audio_policy_forced_cfg_t forceUse = mEngine->getForceUse(
AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND);
- for (const auto& format: mConfig.getSurroundFormats()) {
+ for (const auto& format: mConfig->getSurroundFormats()) {
if (formatsWritten < formatsMax) {
surroundFormats[formatsWritten] = format.first;
bool formatEnabled = true;
@@ -5582,10 +5583,10 @@
formatset.insert(encodedFormats.begin(), encodedFormats.end());
// Filter the formats which are supported by the vendor hardware.
for (auto it = formatset.begin(); it != formatset.end(); ++it) {
- if (mConfig.getSurroundFormats().count(*it) != 0) {
+ if (mConfig->getSurroundFormats().count(*it) != 0) {
formats.insert(*it);
} else {
- for (const auto& pair : mConfig.getSurroundFormats()) {
+ for (const auto& pair : mConfig->getSurroundFormats()) {
if (pair.second.count(*it) != 0) {
formats.insert(pair.first);
break;
@@ -5606,8 +5607,8 @@
status_t AudioPolicyManager::setSurroundFormatEnabled(audio_format_t audioFormat, bool enabled)
{
ALOGV("%s() format 0x%X enabled %d", __func__, audioFormat, enabled);
- const auto& formatIter = mConfig.getSurroundFormats().find(audioFormat);
- if (formatIter == mConfig.getSurroundFormats().end()) {
+ const auto& formatIter = mConfig->getSurroundFormats().find(audioFormat);
+ if (formatIter == mConfig->getSurroundFormats().end()) {
ALOGW("%s() format 0x%X is not a known surround format", __func__, audioFormat);
return BAD_VALUE;
}
@@ -5762,7 +5763,7 @@
bool AudioPolicyManager::isCallScreenModeSupported()
{
- return getConfig().isCallScreenModeSupported();
+ return mConfig->isCallScreenModeSupported();
}
@@ -5995,26 +5996,16 @@
return mAudioPortGeneration++;
}
-static status_t deserializeAudioPolicyXmlConfig(AudioPolicyConfig &config) {
- if (std::string audioPolicyXmlConfigFile = audio_get_audio_policy_config_file();
- !audioPolicyXmlConfigFile.empty()) {
- status_t ret = deserializeAudioPolicyFile(audioPolicyXmlConfigFile.c_str(), &config);
- if (ret == NO_ERROR) {
- config.setSource(audioPolicyXmlConfigFile);
- }
- return ret;
- }
- return BAD_VALUE;
-}
-
-AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface,
- bool /*forTesting*/)
+AudioPolicyManager::AudioPolicyManager(const sp<const AudioPolicyConfig>& config,
+ EngineInstance&& engine,
+ AudioPolicyClientInterface *clientInterface)
:
mUidCached(AID_AUDIOSERVER), // no need to call getuid(), there's only one of us running.
+ mConfig(config),
+ mEngine(std::move(engine)),
mpClientInterface(clientInterface),
mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f),
mA2dpSuspended(false),
- mConfig(mHwModulesAll, mOutputDevicesAll, mInputDevicesAll, mDefaultOutputDevice),
mAudioPortGeneration(1),
mBeaconMuteRefCount(0),
mBeaconPlayingRefCount(0),
@@ -6025,32 +6016,9 @@
{
}
-AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface)
- : AudioPolicyManager(clientInterface, false /*forTesting*/)
-{
- loadConfig();
-}
-
-void AudioPolicyManager::loadConfig() {
- if (deserializeAudioPolicyXmlConfig(getConfig()) != NO_ERROR) {
- ALOGE("could not load audio policy configuration file, setting defaults");
- getConfig().setDefault();
- }
-}
-
status_t AudioPolicyManager::initialize() {
- {
- auto engLib = EngineLibrary::load(
- "libaudiopolicyengine" + getConfig().getEngineLibraryNameSuffix() + ".so");
- if (!engLib) {
- ALOGE("%s: Failed to load the engine library", __FUNCTION__);
- return NO_INIT;
- }
- mEngine = engLib->createEngine();
- if (mEngine == nullptr) {
- ALOGE("%s: Failed to instantiate the APM engine", __FUNCTION__);
- return NO_INIT;
- }
+ if (mEngine == nullptr) {
+ return NO_INIT;
}
mEngine->setObserver(this);
status_t status = mEngine->initCheck();
@@ -6059,31 +6027,22 @@
return status;
}
- // If microphones address is empty, set it according to device type
- for (size_t i = 0; i < mInputDevicesAll.size(); i++) {
- if (mInputDevicesAll[i]->address().empty()) {
- if (mInputDevicesAll[i]->type() == AUDIO_DEVICE_IN_BUILTIN_MIC) {
- mInputDevicesAll[i]->setAddress(AUDIO_BOTTOM_MICROPHONE_ADDRESS);
- } else if (mInputDevicesAll[i]->type() == AUDIO_DEVICE_IN_BACK_MIC) {
- mInputDevicesAll[i]->setAddress(AUDIO_BACK_MICROPHONE_ADDRESS);
- }
- }
- }
-
// The actual device selection cache will be updated when calling `updateDevicesAndOutputs`
// at the end of this function.
mEngine->initializeDeviceSelectionCache();
mCommunnicationStrategy = mEngine->getProductStrategyForAttributes(
mEngine->getAttributesForStreamType(AUDIO_STREAM_VOICE_CALL));
- // after parsing the config, mOutputDevicesAll and mInputDevicesAll contain all known devices;
+ // after parsing the config, mConfig contain all known devices;
// open all output streams needed to access attached devices
onNewAudioModulesAvailableInt(nullptr /*newDevices*/);
// make sure default device is reachable
- if (mDefaultOutputDevice == 0 || !mAvailableOutputDevices.contains(mDefaultOutputDevice)) {
- ALOGE_IF(mDefaultOutputDevice != 0, "Default device %s is unreachable",
- mDefaultOutputDevice->toString().c_str());
+ if (const auto defaultOutputDevice = mConfig->getDefaultOutputDevice();
+ defaultOutputDevice == nullptr ||
+ !mAvailableOutputDevices.contains(defaultOutputDevice)) {
+ ALOGE_IF(defaultOutputDevice != nullptr, "Default device %s is unreachable",
+ defaultOutputDevice->toString().c_str());
status = NO_INIT;
}
ALOGW_IF(mPrimaryOutput == nullptr, "The policy configuration does not declare a primary output");
@@ -6108,8 +6067,8 @@
mOutputs.clear();
mInputs.clear();
mHwModules.clear();
- mHwModulesAll.clear();
mManualSurroundFormats.clear();
+ mConfig.clear();
}
status_t AudioPolicyManager::initCheck()
@@ -6131,14 +6090,18 @@
void AudioPolicyManager::onNewAudioModulesAvailableInt(DeviceVector *newDevices)
{
- for (const auto& hwModule : mHwModulesAll) {
+ for (const auto& hwModule : mConfig->getHwModules()) {
if (std::find(mHwModules.begin(), mHwModules.end(), hwModule) != mHwModules.end()) {
continue;
}
- hwModule->setHandle(mpClientInterface->loadHwModule(hwModule->getName()));
if (hwModule->getHandle() == AUDIO_MODULE_HANDLE_NONE) {
- ALOGW("could not open HW module %s", hwModule->getName());
- continue;
+ if (audio_module_handle_t handle = mpClientInterface->loadHwModule(hwModule->getName());
+ handle != AUDIO_MODULE_HANDLE_NONE) {
+ hwModule->setHandle(handle);
+ } else {
+ ALOGW("could not load HW module %s", hwModule->getName());
+ continue;
+ }
}
mHwModules.push_back(hwModule);
// open all output streams needed to access attached devices.
@@ -6160,10 +6123,10 @@
}
const DeviceVector &supportedDevices = outProfile->getSupportedDevices();
- DeviceVector availProfileDevices = supportedDevices.filter(mOutputDevicesAll);
+ DeviceVector availProfileDevices = supportedDevices.filter(mConfig->getOutputDevices());
sp<DeviceDescriptor> supportedDevice = 0;
- if (supportedDevices.contains(mDefaultOutputDevice)) {
- supportedDevice = mDefaultOutputDevice;
+ if (supportedDevices.contains(mConfig->getDefaultOutputDevice())) {
+ supportedDevice = mConfig->getDefaultOutputDevice();
} else {
// choose first device present in profile's SupportedDevices also part of
// mAvailableOutputDevices.
@@ -6172,7 +6135,7 @@
}
supportedDevice = availProfileDevices.itemAt(0);
}
- if (!mOutputDevicesAll.contains(supportedDevice)) {
+ if (!mConfig->getOutputDevices().contains(supportedDevice)) {
continue;
}
sp<SwAudioOutputDescriptor> outputDesc = new SwAudioOutputDescriptor(outProfile,
@@ -6227,7 +6190,7 @@
// chose first device present in profile's SupportedDevices also part of
// available input devices
const DeviceVector &supportedDevices = inProfile->getSupportedDevices();
- DeviceVector availProfileDevices = supportedDevices.filter(mInputDevicesAll);
+ DeviceVector availProfileDevices = supportedDevices.filter(mConfig->getInputDevices());
if (availProfileDevices.isEmpty()) {
ALOGV("%s: Input device list is empty! for profile %s",
__func__, inProfile->getTagName().c_str());
@@ -7987,7 +7950,7 @@
std::unordered_set<audio_format_t> enforcedSurround(
devDesc->encodedFormats().begin(), devDesc->encodedFormats().end());
std::unordered_set<audio_format_t> allSurround; // A flat set of all known surround formats
- for (const auto& pair : mConfig.getSurroundFormats()) {
+ for (const auto& pair : mConfig->getSurroundFormats()) {
allSurround.insert(pair.first);
for (const auto& subformat : pair.second) allSurround.insert(subformat);
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index dc82d54..88bafef 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -94,7 +94,9 @@
{
public:
- explicit AudioPolicyManager(AudioPolicyClientInterface *clientInterface);
+ AudioPolicyManager(const sp<const AudioPolicyConfig>& config,
+ EngineInstance&& engine,
+ AudioPolicyClientInterface *clientInterface);
virtual ~AudioPolicyManager();
// AudioPolicyInterface
@@ -427,19 +429,7 @@
status_t initialize();
protected:
- // A constructor that allows more fine-grained control over initialization process,
- // used in automatic tests.
- AudioPolicyManager(AudioPolicyClientInterface *clientInterface, bool forTesting);
-
- // These methods should be used when finer control over APM initialization
- // is needed, e.g. in tests. Must be used in conjunction with the constructor
- // that only performs fields initialization. The public constructor comprises
- // these steps in the following sequence:
- // - field initializing constructor;
- // - loadConfig;
- // - initialize.
- AudioPolicyConfig& getConfig() { return mConfig; }
- void loadConfig();
+ const AudioPolicyConfig& getConfig() const { return *(mConfig.get()); }
// From AudioPolicyManagerObserver
virtual const AudioPatchCollection &getAudioPatches() const
@@ -473,7 +463,7 @@
}
virtual const sp<DeviceDescriptor> &getDefaultOutputDevice() const
{
- return mDefaultOutputDevice;
+ return mConfig->getDefaultOutputDevice();
}
std::vector<volume_group_t> getVolumeGroups() const
@@ -932,6 +922,8 @@
sp<SwAudioOutputDescriptor> ignoredOutput, uint32_t delayMs);
const uid_t mUidCached; // AID_AUDIOSERVER
+ sp<const AudioPolicyConfig> mConfig;
+ EngineInstance mEngine; // Audio Policy Engine instance
AudioPolicyClientInterface *mpClientInterface; // audio policy client interface
sp<SwAudioOutputDescriptor> mPrimaryOutput; // primary output descriptor
// list of descriptors for outputs currently opened
@@ -944,8 +936,6 @@
SwAudioOutputCollection mPreviousOutputs;
AudioInputCollection mInputs; // list of input descriptors
- DeviceVector mOutputDevicesAll; // all output devices from the config
- DeviceVector mInputDevicesAll; // all input devices from the config
DeviceVector mAvailableOutputDevices; // all available output devices
DeviceVector mAvailableInputDevices; // all available input devices
@@ -955,11 +945,7 @@
bool mA2dpSuspended; // true if A2DP output is suspended
EffectDescriptorCollection mEffects; // list of registered audio effects
- sp<DeviceDescriptor> mDefaultOutputDevice; // output device selected by default at boot time
HwModuleCollection mHwModules; // contains modules that have been loaded successfully
- HwModuleCollection mHwModulesAll; // contains all modules declared in the config
-
- AudioPolicyConfig mConfig;
std::atomic<uint32_t> mAudioPortGeneration;
@@ -990,9 +976,6 @@
uint32_t nextAudioPortGeneration();
- // Audio Policy Engine Interface.
- EngineInstance mEngine;
-
// Surround formats that are enabled manually. Taken into account when
// "encoded surround" is forced into "manual" mode.
std::unordered_set<audio_format_t> mManualSurroundFormats;
diff --git a/services/audiopolicy/managerdefault/EngineLibrary.cpp b/services/audiopolicy/managerdefault/EngineLibrary.cpp
index ef699aa..939fbc5 100644
--- a/services/audiopolicy/managerdefault/EngineLibrary.cpp
+++ b/services/audiopolicy/managerdefault/EngineLibrary.cpp
@@ -23,9 +23,27 @@
namespace android {
-// static
-std::shared_ptr<EngineLibrary> EngineLibrary::load(std::string libraryPath)
+EngineInstance loadApmEngineLibraryAndCreateEngine(const std::string& librarySuffix,
+ const std::string& configXmlFilePath)
{
+ auto engLib = EngineLibrary::load(librarySuffix);
+ if (!engLib) {
+ ALOGE("%s: Failed to load the engine library, suffix \"%s\"",
+ __func__, librarySuffix.c_str());
+ return nullptr;
+ }
+ auto engine = engLib->createEngineUsingXmlConfig(configXmlFilePath);
+ if (engine == nullptr) {
+ ALOGE("%s: Failed to instantiate the APM engine", __func__);
+ return nullptr;
+ }
+ return engine;
+}
+
+// static
+std::shared_ptr<EngineLibrary> EngineLibrary::load(const std::string& librarySuffix)
+{
+ std::string libraryPath = "libaudiopolicyengine" + librarySuffix + ".so";
std::shared_ptr<EngineLibrary> engLib(new EngineLibrary());
return engLib->init(std::move(libraryPath)) ? engLib : nullptr;
}
@@ -35,6 +53,20 @@
close();
}
+EngineInstance EngineLibrary::createEngineUsingXmlConfig(const std::string& xmlFilePath) {
+ auto instance = createEngine();
+ if (instance != nullptr) {
+ if (status_t status = instance->loadFromXmlConfigWithFallback(xmlFilePath);
+ status == OK) {
+ return instance;
+ } else {
+ ALOGE("%s: loading of the engine config with XML configuration file \"%s\" failed: %d",
+ __func__, xmlFilePath.empty() ? "default" : xmlFilePath.c_str(), status);
+ }
+ }
+ return nullptr;
+}
+
bool EngineLibrary::init(std::string libraryPath)
{
mLibraryHandle = dlopen(libraryPath.c_str(), 0);
diff --git a/services/audiopolicy/managerdefault/EngineLibrary.h b/services/audiopolicy/managerdefault/EngineLibrary.h
index f143916..dc138a1 100644
--- a/services/audiopolicy/managerdefault/EngineLibrary.h
+++ b/services/audiopolicy/managerdefault/EngineLibrary.h
@@ -26,9 +26,12 @@
using EngineInstance = std::unique_ptr<EngineInterface, std::function<void (EngineInterface*)>>;
+EngineInstance loadApmEngineLibraryAndCreateEngine(const std::string& librarySuffix,
+ const std::string& configXmlFilePath = "");
+
class EngineLibrary : public std::enable_shared_from_this<EngineLibrary> {
public:
- static std::shared_ptr<EngineLibrary> load(std::string libraryPath);
+ static std::shared_ptr<EngineLibrary> load(const std::string& librarySuffix);
~EngineLibrary();
EngineLibrary(const EngineLibrary&) = delete;
@@ -36,11 +39,12 @@
EngineLibrary& operator=(const EngineLibrary&) = delete;
EngineLibrary& operator=(EngineLibrary&&) = delete;
- EngineInstance createEngine();
+ EngineInstance createEngineUsingXmlConfig(const std::string& xmlFilePath);
private:
EngineLibrary() = default;
bool init(std::string libraryPath);
+ EngineInstance createEngine();
void close();
void *mLibraryHandle = nullptr;
diff --git a/services/audiopolicy/service/Android.bp b/services/audiopolicy/service/Android.bp
index 10403fa..2f677da 100644
--- a/services/audiopolicy/service/Android.bp
+++ b/services/audiopolicy/service/Android.bp
@@ -52,8 +52,9 @@
"libsensor",
"libsensorprivacy",
"libshmemcompat",
- "libutils",
"libstagefright_foundation",
+ "libutils",
+ "libxml2",
"audioclient-types-aidl-cpp",
"audioflinger-aidl-cpp",
"audiopolicy-aidl-cpp",
diff --git a/services/audiopolicy/service/AudioPolicyClientImpl.cpp b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
index 887f210..13e682b 100644
--- a/services/audiopolicy/service/AudioPolicyClientImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
@@ -27,6 +27,18 @@
/* implementation of the client interface from the policy manager */
+status_t AudioPolicyService::AudioPolicyClient::getAudioPolicyConfig(
+ media::AudioPolicyConfig *config)
+{
+ sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+ if (af == 0) {
+ ALOGW("%s: could not get AudioFlinger", __func__);
+ return AUDIO_MODULE_HANDLE_NONE;
+ }
+
+ return af->getAudioPolicyConfig(config);
+}
+
audio_module_handle_t AudioPolicyService::AudioPolicyClient::loadHwModule(const char *name)
{
sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index e5b1c91..bc3c199 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -46,6 +46,7 @@
#include <system/audio.h>
#include <system/audio_policy.h>
+#include <AudioPolicyConfig.h>
#include <AudioPolicyManager.h>
namespace android {
@@ -185,7 +186,10 @@
static AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface)
{
- AudioPolicyManager *apm = new AudioPolicyManager(clientInterface);
+ auto config = AudioPolicyConfig::loadFromApmXmlConfigWithFallback(); // This can't fail.
+ AudioPolicyManager *apm = new AudioPolicyManager(
+ config, loadApmEngineLibraryAndCreateEngine(config->getEngineLibraryNameSuffix()),
+ clientInterface);
status_t status = apm->initialize();
if (status != NO_ERROR) {
delete apm;
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 981951a..4710a8a 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -735,6 +735,8 @@
explicit AudioPolicyClient(AudioPolicyService *service) : mAudioPolicyService(service) {}
virtual ~AudioPolicyClient() {}
+ virtual status_t getAudioPolicyConfig(media::AudioPolicyConfig *config);
+
//
// Audio HW module functions
//
diff --git a/services/audiopolicy/tests/Android.bp b/services/audiopolicy/tests/Android.bp
index bf82680..285b354 100644
--- a/services/audiopolicy/tests/Android.bp
+++ b/services/audiopolicy/tests/Android.bp
@@ -19,19 +19,20 @@
],
shared_libs: [
+ "framework-permission-aidl-cpp",
"libaudioclient",
"libaudiofoundation",
"libaudiopolicy",
"libaudiopolicymanagerdefault",
"libbase",
+ "libbinder",
+ "libcutils",
"libhidlbase",
"liblog",
"libmedia_helper",
"libutils",
"libcutils",
"libxml2",
- "framework-permission-aidl-cpp",
- "libbinder",
],
static_libs: [
@@ -73,17 +74,19 @@
require_root: true,
shared_libs: [
- "libaudiofoundation",
+ "audioclient-types-aidl-cpp",
"libaudioclient",
+ "libaudioclient_aidl_conversion",
+ "libaudiofoundation",
"libaudiopolicymanagerdefault",
+ "libcutils",
"liblog",
"libmedia_helper",
- "libutils",
- "libaudioclient_aidl_conversion",
- "libstagefright_foundation",
"libshmemcompat",
"libshmemutil",
- "audioclient-types-aidl-cpp",
+ "libstagefright_foundation",
+ "libutils",
+ "libxml2",
],
static_libs: ["libaudiopolicycomponents"],
diff --git a/services/audiopolicy/tests/AudioPolicyTestClient.h b/services/audiopolicy/tests/AudioPolicyTestClient.h
index 71e34e3..2ae0e97 100644
--- a/services/audiopolicy/tests/AudioPolicyTestClient.h
+++ b/services/audiopolicy/tests/AudioPolicyTestClient.h
@@ -25,6 +25,9 @@
virtual ~AudioPolicyTestClient() = default;
// AudioPolicyClientInterface Implementation
+ status_t getAudioPolicyConfig(media::AudioPolicyConfig* /*config*/) override {
+ return INVALID_OPERATION;
+ }
audio_module_handle_t loadHwModule(const char* /*name*/) override {
return AUDIO_MODULE_HANDLE_NONE;
}
diff --git a/services/audiopolicy/tests/AudioPolicyTestManager.h b/services/audiopolicy/tests/AudioPolicyTestManager.h
index 2a7a060..31ee252 100644
--- a/services/audiopolicy/tests/AudioPolicyTestManager.h
+++ b/services/audiopolicy/tests/AudioPolicyTestManager.h
@@ -22,9 +22,13 @@
class AudioPolicyTestManager : public AudioPolicyManager {
public:
explicit AudioPolicyTestManager(AudioPolicyClientInterface *clientInterface)
- : AudioPolicyManager(clientInterface, true /*forTesting*/) { }
+ : AudioPolicyTestManager(AudioPolicyConfig::createDefault(), clientInterface) {}
+ AudioPolicyTestManager(const sp<const AudioPolicyConfig>& config,
+ AudioPolicyClientInterface *clientInterface)
+ : AudioPolicyManager(config,
+ loadApmEngineLibraryAndCreateEngine(config->getEngineLibraryNameSuffix()),
+ clientInterface) {}
using AudioPolicyManager::getConfig;
- using AudioPolicyManager::loadConfig;
using AudioPolicyManager::initialize;
using AudioPolicyManager::getOutputs;
using AudioPolicyManager::getAvailableOutputDevices;
diff --git a/services/audiopolicy/tests/audio_health_tests.cpp b/services/audiopolicy/tests/audio_health_tests.cpp
index 798332c..70a3022 100644
--- a/services/audiopolicy/tests/audio_health_tests.cpp
+++ b/services/audiopolicy/tests/audio_health_tests.cpp
@@ -21,6 +21,7 @@
#include <gtest/gtest.h>
+#include <AudioPolicyConfig.h>
#include <media/AudioSystem.h>
#include <media/TypeConverter.h>
#include <system/audio.h>
@@ -65,19 +66,17 @@
}
free(audioPorts);
- AudioPolicyManagerTestClient client;
- AudioPolicyTestManager manager(&client);
- manager.loadConfig();
- ASSERT_NE("AudioPolicyConfig::setDefault", manager.getConfig().getSource());
+ auto config = AudioPolicyConfig::loadFromApmXmlConfigWithFallback();
+ ASSERT_NE(AudioPolicyConfig::kDefaultConfigSource, config->getSource());
- for (auto desc : manager.getConfig().getInputDevices()) {
+ for (const auto& desc : config->getInputDevices()) {
if (attachedDevices.find(desc->type()) == attachedDevices.end()) {
std::string deviceType;
(void)DeviceConverter::toString(desc->type(), deviceType);
ADD_FAILURE() << "Input device \"" << deviceType << "\" not found";
}
}
- for (auto desc : manager.getConfig().getOutputDevices()) {
+ for (const auto& desc : config->getOutputDevices()) {
if (attachedDevices.find(desc->type()) == attachedDevices.end()) {
std::string deviceType;
(void)DeviceConverter::toString(desc->type(), deviceType);
@@ -87,13 +86,13 @@
}
TEST(AudioHealthTest, ConnectSupportedDevice) {
+ auto config = AudioPolicyConfig::loadFromApmXmlConfigWithFallback();
+ ASSERT_NE(AudioPolicyConfig::kDefaultConfigSource, config->getSource());
AudioPolicyManagerTestClient client;
- AudioPolicyTestManager manager(&client);
- manager.loadConfig();
- ASSERT_NE("AudioPolicyConfig::setDefault", manager.getConfig().getSource());
+ AudioPolicyTestManager manager(config, &client);
DeviceVector devices;
- for (const auto& hwModule : manager.getConfig().getHwModules()) {
+ for (const auto& hwModule : config->getHwModules()) {
for (const auto& profile : hwModule->getOutputProfiles()) {
devices.merge(profile->getSupportedDevices());
}
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index 412ab19..97a1e0d 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -92,11 +92,44 @@
} // namespace
+TEST(AudioPolicyConfigTest, DefaultConfigForTestsIsEmpty) {
+ auto config = AudioPolicyConfig::createWritableForTests();
+ EXPECT_TRUE(config->getSource().empty());
+ EXPECT_TRUE(config->getHwModules().isEmpty());
+ EXPECT_TRUE(config->getInputDevices().isEmpty());
+ EXPECT_TRUE(config->getOutputDevices().isEmpty());
+}
+
+TEST(AudioPolicyConfigTest, FallbackToDefault) {
+ auto config = AudioPolicyConfig::loadFromApmXmlConfigWithFallback(
+ base::GetExecutableDirectory() + "/test_invalid_audio_policy_configuration.xml");
+ EXPECT_EQ(AudioPolicyConfig::kDefaultConfigSource, config->getSource());
+}
+
+TEST(AudioPolicyConfigTest, LoadForTests) {
+ {
+ auto result = AudioPolicyConfig::loadFromCustomXmlConfigForTests(
+ base::GetExecutableDirectory() + "/test_invalid_audio_policy_configuration.xml");
+ EXPECT_FALSE(result.ok());
+ }
+ {
+ const std::string source =
+ base::GetExecutableDirectory() + "/test_audio_policy_configuration.xml";
+ auto result = AudioPolicyConfig::loadFromCustomXmlConfigForTests(source);
+ ASSERT_TRUE(result.ok());
+ EXPECT_EQ(source, result.value()->getSource());
+ EXPECT_FALSE(result.value()->getHwModules().isEmpty());
+ EXPECT_FALSE(result.value()->getInputDevices().isEmpty());
+ EXPECT_FALSE(result.value()->getOutputDevices().isEmpty());
+ }
+}
+
TEST(AudioPolicyManagerTestInit, EngineFailure) {
AudioPolicyTestClient client;
- AudioPolicyTestManager manager(&client);
- manager.getConfig().setDefault();
- manager.getConfig().setEngineLibraryNameSuffix("non-existent");
+ auto config = AudioPolicyConfig::createWritableForTests();
+ config->setDefault();
+ config->setEngineLibraryNameSuffix("non-existent");
+ AudioPolicyTestManager manager(config, &client);
ASSERT_EQ(NO_INIT, manager.initialize());
ASSERT_EQ(NO_INIT, manager.initCheck());
}
@@ -104,41 +137,12 @@
TEST(AudioPolicyManagerTestInit, ClientFailure) {
AudioPolicyTestClient client;
AudioPolicyTestManager manager(&client);
- manager.getConfig().setDefault();
// Since the default client fails to open anything,
// APM should indicate that the initialization didn't succeed.
ASSERT_EQ(NO_INIT, manager.initialize());
ASSERT_EQ(NO_INIT, manager.initCheck());
}
-// Verifies that a failure while loading a config doesn't leave
-// APM config in a "dirty" state. Since AudioPolicyConfig object
-// is a proxy for the data hosted by APM, it isn't possible
-// to "deep copy" it, and thus we have to test its elements
-// individually.
-TEST(AudioPolicyManagerTestInit, ConfigLoadingIsTransactional) {
- AudioPolicyTestClient client;
- AudioPolicyTestManager manager(&client);
- ASSERT_TRUE(manager.getConfig().getHwModules().isEmpty());
- ASSERT_TRUE(manager.getConfig().getInputDevices().isEmpty());
- ASSERT_TRUE(manager.getConfig().getOutputDevices().isEmpty());
- status_t status = deserializeAudioPolicyFile(
- (base::GetExecutableDirectory() +
- "/test_invalid_audio_policy_configuration.xml").c_str(),
- &manager.getConfig());
- ASSERT_NE(NO_ERROR, status);
- EXPECT_TRUE(manager.getConfig().getHwModules().isEmpty());
- EXPECT_TRUE(manager.getConfig().getInputDevices().isEmpty());
- EXPECT_TRUE(manager.getConfig().getOutputDevices().isEmpty());
- status = deserializeAudioPolicyFile(
- (base::GetExecutableDirectory() + "/test_audio_policy_configuration.xml").c_str(),
- &manager.getConfig());
- ASSERT_EQ(NO_ERROR, status);
- EXPECT_FALSE(manager.getConfig().getHwModules().isEmpty());
- EXPECT_FALSE(manager.getConfig().getInputDevices().isEmpty());
- EXPECT_FALSE(manager.getConfig().getOutputDevices().isEmpty());
-}
-
class PatchCountCheck {
public:
@@ -200,6 +204,7 @@
static audio_port_handle_t getDeviceIdFromPatch(const struct audio_patch* patch);
virtual AudioPolicyManagerTestClient* getClient() { return new AudioPolicyManagerTestClient; }
+ sp<AudioPolicyConfig> mConfig;
std::unique_ptr<AudioPolicyManagerTestClient> mClient;
std::unique_ptr<AudioPolicyTestManager> mManager;
@@ -208,8 +213,8 @@
void AudioPolicyManagerTest::SetUp() {
mClient.reset(getClient());
- mManager.reset(new AudioPolicyTestManager(mClient.get()));
ASSERT_NO_FATAL_FAILURE(SetUpManagerConfig()); // Subclasses may want to customize the config.
+ mManager.reset(new AudioPolicyTestManager(mConfig, mClient.get()));
ASSERT_EQ(NO_ERROR, mManager->initialize());
ASSERT_EQ(NO_ERROR, mManager->initCheck());
}
@@ -220,7 +225,8 @@
}
void AudioPolicyManagerTest::SetUpManagerConfig() {
- mManager->getConfig().setDefault();
+ mConfig = AudioPolicyConfig::createWritableForTests();
+ mConfig->setDefault();
}
void AudioPolicyManagerTest::dumpToLog() {
@@ -467,7 +473,6 @@
void AudioPolicyManagerTestMsd::SetUpManagerConfig() {
// TODO: Consider using Serializer to load part of the config from a string.
ASSERT_NO_FATAL_FAILURE(AudioPolicyManagerTest::SetUpManagerConfig());
- AudioPolicyConfig& config = mManager->getConfig();
mMsdOutputDevice = new DeviceDescriptor(AUDIO_DEVICE_OUT_BUS);
sp<AudioProfile> pcmOutputProfile = new AudioProfile(
AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, k48000SamplingRate);
@@ -483,26 +488,26 @@
sp<AudioProfile> pcmInputProfile = new AudioProfile(
AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO, 44100);
mMsdInputDevice->addAudioProfile(pcmInputProfile);
- config.addDevice(mMsdOutputDevice);
- config.addDevice(mMsdInputDevice);
+ mConfig->addDevice(mMsdOutputDevice);
+ mConfig->addDevice(mMsdInputDevice);
if (mExpectedAudioPatchCount == 2) {
// Add SPDIF device with PCM output profile as a second device for dual MSD audio patching.
mSpdifDevice = new DeviceDescriptor(AUDIO_DEVICE_OUT_SPDIF);
mSpdifDevice->addAudioProfile(pcmOutputProfile);
- config.addDevice(mSpdifDevice);
+ mConfig->addDevice(mSpdifDevice);
sp<OutputProfile> spdifOutputProfile = new OutputProfile("spdif output");
spdifOutputProfile->addAudioProfile(pcmOutputProfile);
spdifOutputProfile->addSupportedDevice(mSpdifDevice);
- config.getHwModules().getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY)->
+ mConfig->getHwModules().getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY)->
addOutputProfile(spdifOutputProfile);
}
sp<HwModule> msdModule = new HwModule(AUDIO_HARDWARE_MODULE_ID_MSD, 2 /*halVersionMajor*/);
- HwModuleCollection modules = config.getHwModules();
+ HwModuleCollection modules = mConfig->getHwModules();
modules.add(msdModule);
- config.setHwModules(modules);
+ mConfig->setHwModules(modules);
sp<OutputProfile> msdOutputProfile = new OutputProfile("msd input");
msdOutputProfile->addAudioProfile(pcmOutputProfile);
@@ -530,15 +535,15 @@
// of streams that are not supported by MSD.
sp<AudioProfile> dtsOutputProfile = new AudioProfile(
AUDIO_FORMAT_DTS, AUDIO_CHANNEL_OUT_5POINT1, k48000SamplingRate);
- config.getDefaultOutputDevice()->addAudioProfile(dtsOutputProfile);
+ mConfig->getDefaultOutputDevice()->addAudioProfile(dtsOutputProfile);
sp<OutputProfile> primaryEncodedOutputProfile = new OutputProfile("encoded");
primaryEncodedOutputProfile->addAudioProfile(dtsOutputProfile);
primaryEncodedOutputProfile->setFlags(AUDIO_OUTPUT_FLAG_DIRECT);
- primaryEncodedOutputProfile->addSupportedDevice(config.getDefaultOutputDevice());
- config.getHwModules().getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY)->
+ primaryEncodedOutputProfile->addSupportedDevice(mConfig->getDefaultOutputDevice());
+ mConfig->getHwModules().getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY)->
addOutputProfile(primaryEncodedOutputProfile);
- mDefaultOutputDevice = config.getDefaultOutputDevice();
+ mDefaultOutputDevice = mConfig->getDefaultOutputDevice();
if (mExpectedAudioPatchCount == 2) {
mSpdifDevice->addAudioProfile(dtsOutputProfile);
primaryEncodedOutputProfile->addSupportedDevice(mSpdifDevice);
@@ -549,12 +554,12 @@
sp<AudioProfile> iec958InputProfile = new AudioProfile(
AUDIO_FORMAT_IEC60958, AUDIO_CHANNEL_INDEX_MASK_24, k48000SamplingRate);
mHdmiInputDevice->addAudioProfile(iec958InputProfile);
- config.addDevice(mHdmiInputDevice);
+ mConfig->addDevice(mHdmiInputDevice);
sp<InputProfile> hdmiInputProfile = new InputProfile("hdmi input");
hdmiInputProfile->addAudioProfile(iec958InputProfile);
hdmiInputProfile->setFlags(AUDIO_INPUT_FLAG_DIRECT);
hdmiInputProfile->addSupportedDevice(mHdmiInputDevice);
- config.getHwModules().getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY)->
+ mConfig->getHwModules().getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY)->
addInputProfile(hdmiInputProfile);
}
@@ -721,7 +726,7 @@
int countDirectProfilesPrimary = 0;
const auto& primary = mManager->getConfig().getHwModules()
.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY);
- for (const auto outputProfile : primary->getOutputProfiles()) {
+ for (const auto& outputProfile : primary->getOutputProfiles()) {
if (outputProfile->asAudioPort()->isDirectOutput()) {
countDirectProfilesPrimary += outputProfile->asAudioPort()->getAudioProfiles().size();
}
@@ -731,7 +736,7 @@
int countDirectProfilesMsd = 0;
const auto& msd = mManager->getConfig().getHwModules()
.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_MSD);
- for (const auto outputProfile : msd->getOutputProfiles()) {
+ for (const auto& outputProfile : msd->getOutputProfiles()) {
if (outputProfile->asAudioPort()->isDirectOutput()) {
countDirectProfilesMsd += outputProfile->asAudioPort()->getAudioProfiles().size();
}
@@ -922,9 +927,9 @@
sExecutableDir + "test_audio_policy_configuration.xml";
void AudioPolicyManagerTestWithConfigurationFile::SetUpManagerConfig() {
- status_t status = deserializeAudioPolicyFile(getConfigFile().c_str(), &mManager->getConfig());
- ASSERT_EQ(NO_ERROR, status);
- mManager->getConfig().setSource(getConfigFile());
+ auto result = AudioPolicyConfig::loadFromCustomXmlConfigForTests(getConfigFile());
+ ASSERT_TRUE(result.ok());
+ mConfig = result.value();
}
TEST_F(AudioPolicyManagerTestWithConfigurationFile, InitSuccess) {
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index cecced4..eb824de 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -3910,18 +3910,21 @@
void CameraService::UidPolicy::registerWithActivityManager() {
Mutex::Autolock _l(mUidLock);
+ int32_t emptyUidArray[] = { };
if (mRegistered) return;
status_t res = mAm.linkToDeath(this);
- mAm.registerUidObserver(this, ActivityManager::UID_OBSERVER_GONE
+ mAm.registerUidObserverForUids(this, ActivityManager::UID_OBSERVER_GONE
| ActivityManager::UID_OBSERVER_IDLE
| ActivityManager::UID_OBSERVER_ACTIVE | ActivityManager::UID_OBSERVER_PROCSTATE
| ActivityManager::UID_OBSERVER_PROC_OOM_ADJ,
ActivityManager::PROCESS_STATE_UNKNOWN,
- String16("cameraserver"));
+ String16("cameraserver"), emptyUidArray, 0, mObserverToken);
if (res == OK) {
mRegistered = true;
ALOGV("UidPolicy: Registered with ActivityManager");
+ } else {
+ ALOGE("UidPolicy: Failed to register with ActivityManager: 0x%08x", res);
}
}
@@ -4019,13 +4022,16 @@
if (it->second.hasCamera) {
for (auto &monitoredUid : mMonitoredUids) {
if (monitoredUid.first != uid && adj > monitoredUid.second.procAdj) {
+ ALOGV("%s: notify uid %d", __FUNCTION__, monitoredUid.first);
notifyUidSet.emplace(monitoredUid.first);
}
}
+ ALOGV("%s: notify uid %d", __FUNCTION__, uid);
notifyUidSet.emplace(uid);
} else {
for (auto &monitoredUid : mMonitoredUids) {
if (monitoredUid.second.hasCamera && adj < monitoredUid.second.procAdj) {
+ ALOGV("%s: notify uid %d", __FUNCTION__, uid);
notifyUidSet.emplace(uid);
}
}
@@ -4056,6 +4062,10 @@
monitoredUid.procAdj = resource_policy::UNKNOWN_ADJ;
monitoredUid.refCount = 1;
it = mMonitoredUids.emplace(std::pair<uid_t, MonitoredUid>(uid, monitoredUid)).first;
+ status_t res = mAm.addUidToObserver(mObserverToken, String16("cameraserver"), uid);
+ if (res != OK) {
+ ALOGE("UidPolicy: Failed to add uid to observer: 0x%08x", res);
+ }
}
if (openCamera) {
@@ -4073,6 +4083,10 @@
it->second.refCount--;
if (it->second.refCount == 0) {
mMonitoredUids.erase(it);
+ status_t res = mAm.removeUidFromObserver(mObserverToken, String16("cameraserver"), uid);
+ if (res != OK) {
+ ALOGE("UidPolicy: Failed to remove uid from observer: 0x%08x", res);
+ }
} else if (closeCamera) {
it->second.hasCamera = false;
}
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 8c57d26..d84cb00 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -798,6 +798,7 @@
// Monitored uid map
std::unordered_map<uid_t, MonitoredUid> mMonitoredUids;
std::unordered_map<uid_t, bool> mOverrideUids;
+ sp<IBinder> mObserverToken;
}; // class UidPolicy
// If sensor privacy is enabled then all apps, including those that are active, should be
diff --git a/services/camera/libcameraservice/CameraServiceWatchdog.cpp b/services/camera/libcameraservice/CameraServiceWatchdog.cpp
index e80064a..1c1bd24 100644
--- a/services/camera/libcameraservice/CameraServiceWatchdog.cpp
+++ b/services/camera/libcameraservice/CameraServiceWatchdog.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "CameraServiceWatchdog"
#include "CameraServiceWatchdog.h"
+#include "android/set_abort_message.h"
#include "utils/CameraServiceProxyWrapper.h"
namespace android {
@@ -36,12 +37,14 @@
{
AutoMutex _l(mWatchdogLock);
- for (auto it = tidToCycleCounterMap.begin(); it != tidToCycleCounterMap.end(); it++) {
+ for (auto it = mTidMap.begin(); it != mTidMap.end(); it++) {
uint32_t currentThreadId = it->first;
- tidToCycleCounterMap[currentThreadId]++;
+ mTidMap[currentThreadId].cycles++;
- if (tidToCycleCounterMap[currentThreadId] >= mMaxCycles) {
+ if (mTidMap[currentThreadId].cycles >= mMaxCycles) {
+ std::string abortMessage = getAbortMessage(mTidMap[currentThreadId].functionName);
+ android_set_abort_message(abortMessage.c_str());
ALOGW("CameraServiceWatchdog triggering abort for pid: %d tid: %d", getpid(),
currentThreadId);
mCameraServiceProxyWrapper->logClose(mCameraId, 0 /*latencyMs*/,
@@ -56,13 +59,19 @@
return true;
}
+std::string CameraServiceWatchdog::getAbortMessage(const std::string& functionName) {
+ std::string res = "CameraServiceWatchdog triggering abort during "
+ + functionName;
+ return res;
+}
+
void CameraServiceWatchdog::requestExit()
{
Thread::requestExit();
AutoMutex _l(mWatchdogLock);
- tidToCycleCounterMap.clear();
+ mTidMap.clear();
if (mPause) {
mPause = false;
@@ -85,18 +94,21 @@
{
AutoMutex _l(mWatchdogLock);
- tidToCycleCounterMap.erase(tid);
+ mTidMap.erase(tid);
- if (tidToCycleCounterMap.empty()) {
+ if (mTidMap.empty()) {
mPause = true;
}
}
-void CameraServiceWatchdog::start(uint32_t tid)
+void CameraServiceWatchdog::start(uint32_t tid, const char* functionName)
{
AutoMutex _l(mWatchdogLock);
- tidToCycleCounterMap[tid] = 0;
+ MonitoredFunction monitoredFunction = {};
+ monitoredFunction.cycles = 0;
+ monitoredFunction.functionName = functionName;
+ mTidMap[tid] = monitoredFunction;
if (mPause) {
mPause = false;
diff --git a/services/camera/libcameraservice/CameraServiceWatchdog.h b/services/camera/libcameraservice/CameraServiceWatchdog.h
index 6617873..de6ac9e 100644
--- a/services/camera/libcameraservice/CameraServiceWatchdog.h
+++ b/services/camera/libcameraservice/CameraServiceWatchdog.h
@@ -40,9 +40,9 @@
#include "utils/CameraServiceProxyWrapper.h"
// Used to wrap the call of interest in start and stop calls
-#define WATCH(toMonitor) watchThread([&]() { return toMonitor;}, gettid())
+#define WATCH(toMonitor) watchThread([&]() { return toMonitor;}, gettid(), __FUNCTION__)
#define WATCH_CUSTOM_TIMER(toMonitor, cycles, cycleLength) \
- watchThread([&]() { return toMonitor;}, gettid(), cycles, cycleLength);
+ watchThread([&]() { return toMonitor;}, gettid(), __FUNCTION__, cycles, cycleLength);
// Default cycles and cycle length values used to calculate permitted elapsed time
const static size_t kMaxCycles = 100;
@@ -52,6 +52,11 @@
class CameraServiceWatchdog : public Thread {
+struct MonitoredFunction {
+ uint32_t cycles;
+ std::string functionName;
+};
+
public:
explicit CameraServiceWatchdog(const String8 &cameraId,
std::shared_ptr<CameraServiceProxyWrapper> cameraServiceProxyWrapper) :
@@ -75,7 +80,8 @@
/** Used to wrap monitored calls in start and stop functions using custom timer values */
template<typename T>
- auto watchThread(T func, uint32_t tid, uint32_t cycles, uint32_t cycleLength) {
+ auto watchThread(T func, uint32_t tid, const char* functionName, uint32_t cycles,
+ uint32_t cycleLength) {
decltype(func()) res;
if (cycles != mMaxCycles || cycleLength != mCycleLengthMs) {
@@ -91,17 +97,17 @@
status_t status = tempWatchdog->run("CameraServiceWatchdog");
if (status != OK) {
ALOGE("Unable to watch thread: %s (%d)", strerror(-status), status);
- res = watchThread(func, tid);
+ res = watchThread(func, tid, functionName);
return res;
}
- res = tempWatchdog->watchThread(func, tid);
+ res = tempWatchdog->watchThread(func, tid, functionName);
tempWatchdog->requestExit();
tempWatchdog.clear();
} else {
// If custom timer values are equivalent to set class timer values, use
// current thread
- res = watchThread(func, tid);
+ res = watchThread(func, tid, functionName);
}
return res;
@@ -109,12 +115,12 @@
/** Used to wrap monitored calls in start and stop functions using class timer values */
template<typename T>
- auto watchThread(T func, uint32_t tid) {
+ auto watchThread(T func, uint32_t tid, const char* functionName) {
decltype(func()) res;
AutoMutex _l(mEnabledLock);
if (mEnabled) {
- start(tid);
+ start(tid, functionName);
res = func();
stop(tid);
} else {
@@ -130,7 +136,7 @@
* Start adds a cycle counter for the calling thread. When threadloop is blocked/paused,
* start() unblocks and starts the watchdog
*/
- void start(uint32_t tid);
+ void start(uint32_t tid, const char* functionName);
/**
* If there are no calls left to be monitored, stop blocks/pauses threadloop
@@ -138,6 +144,8 @@
*/
void stop(uint32_t tid);
+ std::string getAbortMessage(const std::string& functionName);
+
virtual bool threadLoop();
Mutex mWatchdogLock; // Lock for condition variable
@@ -151,7 +159,9 @@
std::shared_ptr<CameraServiceProxyWrapper> mCameraServiceProxyWrapper;
- std::unordered_map<uint32_t, uint32_t> tidToCycleCounterMap; // Thread Id to cycle counter map
+ std::unordered_map<uint32_t, MonitoredFunction> mTidMap; // Thread Id to MonitoredFunction type
+ // which retrieves the num of cycles
+ // and name of the function
};
} // namespace android
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index fda6af3..38c615d 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -957,7 +957,7 @@
bool isHeicCompositeStream = camera3::HeicCompositeStream::isHeicCompositeStream(surfaces[0]);
bool isJpegRCompositeStream =
camera3::JpegRCompositeStream::isJpegRCompositeStream(surfaces[0]) &&
- !mDevice->supportNativeJpegR();
+ !mDevice->isCompositeJpegRDisabled();
if (isDepthCompositeStream || isHeicCompositeStream || isJpegRCompositeStream) {
sp<CompositeStream> compositeStream;
if (isDepthCompositeStream) {
@@ -1851,7 +1851,7 @@
isCompositeStream = camera3::DepthCompositeStream::isDepthCompositeStream(s) ||
camera3::HeicCompositeStream::isHeicCompositeStream(s) ||
(camera3::JpegRCompositeStream::isJpegRCompositeStream(s) &&
- !mDevice->supportNativeJpegR());
+ !mDevice->isCompositeJpegRDisabled());
if (isCompositeStream) {
auto compositeIdx = mCompositeStreamMap.indexOfKey(IInterface::asBinder(gbp));
if (compositeIdx == NAME_NOT_FOUND) {
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index 530b03e..919108d 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -113,7 +113,7 @@
*/
virtual const CameraMetadata& infoPhysical(const String8& physicalId) const = 0;
- virtual bool supportNativeJpegR() const { return false; };
+ virtual bool isCompositeJpegRDisabled() const { return false; };
struct PhysicalCameraSettings {
std::string cameraId;
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index 77abeeb..6f4c04a 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -316,16 +316,16 @@
return deviceInfo->supportNativeZoomRatio();
}
-bool CameraProviderManager::supportNativeJpegR(const std::string &id) const {
+bool CameraProviderManager::isCompositeJpegRDisabled(const std::string &id) const {
std::lock_guard<std::mutex> lock(mInterfaceMutex);
- return supportNativeJpegRLocked(id);
+ return isCompositeJpegRDisabledLocked(id);
}
-bool CameraProviderManager::supportNativeJpegRLocked(const std::string &id) const {
+bool CameraProviderManager::isCompositeJpegRDisabledLocked(const std::string &id) const {
auto deviceInfo = findDeviceInfoLocked(id);
if (deviceInfo == nullptr) return false;
- return deviceInfo->supportNativeJpegR();
+ return deviceInfo->isCompositeJpegRDisabled();
}
status_t CameraProviderManager::getResourceCost(const std::string &id,
@@ -1120,7 +1120,7 @@
}
status_t CameraProviderManager::ProviderInfo::DeviceInfo3::deriveJpegRTags(bool maxResolution) {
- if (kFrameworkJpegRDisabled || mSupportsNativeJpegR) {
+ if (kFrameworkJpegRDisabled || mCompositeJpegRDisabled) {
return OK;
}
@@ -1166,6 +1166,18 @@
return OK;
}
+ if (!isConcurrentDynamicRangeCaptureSupported(c,
+ ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HLG10,
+ ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD) &&
+ !property_get_bool("ro.camera.enableCompositeAPI0JpegR", false)) {
+ // API0, P010 only Jpeg/R support is meant to be used only as a reference due to possible
+ // impact on quality and performance.
+ // This data path will be turned off by default and individual device builds must enable
+ // 'ro.camera.enableCompositeAPI0JpegR' in order to experiment using it.
+ mCompositeJpegRDisabled = true;
+ return OK;
+ }
+
getSupportedSizes(c, scalerSizesTag,
static_cast<android_pixel_format_t>(HAL_PIXEL_FORMAT_BLOB), &supportedBlobSizes);
getSupportedSizes(c, scalerSizesTag,
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index ce4129c..e6e4619 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -248,9 +248,9 @@
bool supportNativeZoomRatio(const std::string &id) const;
/**
- * Return true if the camera device has native Jpeg/R support.
+ * Return true if the camera device has no composite Jpeg/R support.
*/
- bool supportNativeJpegR(const std::string &id) const;
+ bool isCompositeJpegRDisabled(const std::string &id) const;
/**
* Return the resource cost of this camera device
@@ -573,7 +573,7 @@
bool hasFlashUnit() const { return mHasFlashUnit; }
bool supportNativeZoomRatio() const { return mSupportNativeZoomRatio; }
- bool supportNativeJpegR() const { return mSupportsNativeJpegR; }
+ bool isCompositeJpegRDisabled() const { return mCompositeJpegRDisabled; }
virtual status_t setTorchMode(bool enabled) = 0;
virtual status_t turnOnTorchWithStrengthLevel(int32_t torchStrength) = 0;
virtual status_t getTorchStrengthLevel(int32_t *torchStrength) = 0;
@@ -615,14 +615,14 @@
mParentProvider(parentProvider), mTorchStrengthLevel(0),
mTorchMaximumStrengthLevel(0), mTorchDefaultStrengthLevel(0),
mHasFlashUnit(false), mSupportNativeZoomRatio(false),
- mPublicCameraIds(publicCameraIds), mSupportsNativeJpegR(false) {}
+ mPublicCameraIds(publicCameraIds), mCompositeJpegRDisabled(false) {}
virtual ~DeviceInfo() {}
protected:
bool mHasFlashUnit; // const after constructor
bool mSupportNativeZoomRatio; // const after constructor
const std::vector<std::string>& mPublicCameraIds;
- bool mSupportsNativeJpegR;
+ bool mCompositeJpegRDisabled;
};
std::vector<std::unique_ptr<DeviceInfo>> mDevices;
std::unordered_set<std::string> mUniqueCameraIds;
@@ -811,7 +811,7 @@
// No guarantees on the order of traversal
ProviderInfo::DeviceInfo* findDeviceInfoLocked(const std::string& id) const;
- bool supportNativeJpegRLocked(const std::string &id) const;
+ bool isCompositeJpegRDisabledLocked(const std::string &id) const;
// Map external providers to USB devices in order to handle USB hotplug
// events for lazy HALs
diff --git a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
index 64098ea..b18cbd4 100644
--- a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
+++ b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
@@ -483,7 +483,7 @@
}
}
- mSupportsNativeJpegR = mCameraCharacteristics.exists(
+ mCompositeJpegRDisabled = mCameraCharacteristics.exists(
ANDROID_JPEGR_AVAILABLE_JPEG_R_STREAM_CONFIGURATIONS);
mSystemCameraKind = getSystemCameraKind();
@@ -735,7 +735,7 @@
camera::device::StreamConfiguration streamConfiguration;
bool earlyExit = false;
auto bRes = SessionConfigurationUtils::convertToHALStreamCombination(configuration,
- String8(mId.c_str()), mCameraCharacteristics, mSupportsNativeJpegR, getMetadata,
+ String8(mId.c_str()), mCameraCharacteristics, mCompositeJpegRDisabled, getMetadata,
mPhysicalIds, streamConfiguration, overrideForPerfClass, &earlyExit);
if (!bRes.isOk()) {
@@ -802,7 +802,7 @@
SessionConfigurationUtils::convertToHALStreamCombination(
cameraIdAndSessionConfig.mSessionConfiguration,
String8(cameraId.c_str()), deviceInfo,
- mManager->supportNativeJpegRLocked(cameraId), getMetadata,
+ mManager->isCompositeJpegRDisabledLocked(cameraId), getMetadata,
physicalCameraIds, streamConfiguration,
overrideForPerfClass, &shouldExit);
if (!bStatus.isOk()) {
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index dcafd74..f5f50a5 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -81,7 +81,7 @@
mLegacyClient(legacyClient),
mOperatingMode(NO_MODE),
mIsConstrainedHighSpeedConfiguration(false),
- mSupportNativeJpegR(false),
+ mIsCompositeJpegRDisabled(false),
mStatus(STATUS_UNINITIALIZED),
mStatusWaiters(0),
mUsePartialResult(false),
@@ -265,113 +265,110 @@
status_t Camera3Device::disconnectImpl() {
ATRACE_CALL();
+ Mutex::Autolock il(mInterfaceLock);
+
ALOGI("%s: E", __FUNCTION__);
status_t res = OK;
std::vector<wp<Camera3StreamInterface>> streams;
+ nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
{
- Mutex::Autolock il(mInterfaceLock);
- nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
- {
- Mutex::Autolock l(mLock);
- if (mStatus == STATUS_UNINITIALIZED) return res;
+ Mutex::Autolock l(mLock);
+ if (mStatus == STATUS_UNINITIALIZED) return res;
- if (mRequestThread != NULL) {
- if (mStatus == STATUS_ACTIVE || mStatus == STATUS_ERROR) {
- res = mRequestThread->clear();
+ if (mRequestThread != NULL) {
+ if (mStatus == STATUS_ACTIVE || mStatus == STATUS_ERROR) {
+ res = mRequestThread->clear();
+ if (res != OK) {
+ SET_ERR_L("Can't stop streaming");
+ // Continue to close device even in case of error
+ } else {
+ res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration,
+ /*requestThreadInvocation*/ false);
if (res != OK) {
- SET_ERR_L("Can't stop streaming");
+ SET_ERR_L("Timeout waiting for HAL to drain (% " PRIi64 " ns)",
+ maxExpectedDuration);
// Continue to close device even in case of error
- } else {
- res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration);
- if (res != OK) {
- SET_ERR_L("Timeout waiting for HAL to drain (% " PRIi64 " ns)",
- maxExpectedDuration);
- // Continue to close device even in case of error
- }
}
}
- // Signal to request thread that we're not expecting any
- // more requests. This will be true since once we're in
- // disconnect and we've cleared off the request queue, the
- // request thread can't receive any new requests through
- // binder calls - since disconnect holds
- // mBinderSerialization lock.
- mRequestThread->setRequestClearing();
}
+ // Signal to request thread that we're not expecting any
+ // more requests. This will be true since once we're in
+ // disconnect and we've cleared off the request queue, the
+ // request thread can't receive any new requests through
+ // binder calls - since disconnect holds
+ // mBinderSerialization lock.
+ mRequestThread->setRequestClearing();
+ }
- if (mStatus == STATUS_ERROR) {
- CLOGE("Shutting down in an error state");
- }
+ if (mStatus == STATUS_ERROR) {
+ CLOGE("Shutting down in an error state");
+ }
- if (mStatusTracker != NULL) {
- mStatusTracker->requestExit();
- }
+ if (mStatusTracker != NULL) {
+ mStatusTracker->requestExit();
+ }
- if (mRequestThread != NULL) {
- mRequestThread->requestExit();
- }
+ if (mRequestThread != NULL) {
+ mRequestThread->requestExit();
+ }
- streams.reserve(mOutputStreams.size() + (mInputStream != nullptr ? 1 : 0));
- for (size_t i = 0; i < mOutputStreams.size(); i++) {
- streams.push_back(mOutputStreams[i]);
- }
- if (mInputStream != nullptr) {
- streams.push_back(mInputStream);
- }
+ streams.reserve(mOutputStreams.size() + (mInputStream != nullptr ? 1 : 0));
+ for (size_t i = 0; i < mOutputStreams.size(); i++) {
+ streams.push_back(mOutputStreams[i]);
+ }
+ if (mInputStream != nullptr) {
+ streams.push_back(mInputStream);
}
}
- // Joining done without holding mLock and mInterfaceLock, otherwise deadlocks may ensue
- // as the threads try to access parent state (b/143513518)
+
+ // Joining done without holding mLock, otherwise deadlocks may ensue
+ // as the threads try to access parent state
if (mRequestThread != NULL && mStatus != STATUS_ERROR) {
// HAL may be in a bad state, so waiting for request thread
// (which may be stuck in the HAL processCaptureRequest call)
// could be dangerous.
- // give up mInterfaceLock here and then lock it again. Could this lead
- // to other deadlocks
mRequestThread->join();
}
+
+ if (mStatusTracker != NULL) {
+ mStatusTracker->join();
+ }
+
+ if (mInjectionMethods->isInjecting()) {
+ mInjectionMethods->stopInjection();
+ }
+
+ HalInterface* interface;
{
- Mutex::Autolock il(mInterfaceLock);
- if (mStatusTracker != NULL) {
- mStatusTracker->join();
- }
+ Mutex::Autolock l(mLock);
+ mRequestThread.clear();
+ Mutex::Autolock stLock(mTrackerLock);
+ mStatusTracker.clear();
+ interface = mInterface.get();
+ }
- if (mInjectionMethods->isInjecting()) {
- mInjectionMethods->stopInjection();
- }
+ // Call close without internal mutex held, as the HAL close may need to
+ // wait on assorted callbacks,etc, to complete before it can return.
+ mCameraServiceWatchdog->WATCH(interface->close());
- HalInterface* interface;
- {
- Mutex::Autolock l(mLock);
- mRequestThread.clear();
- Mutex::Autolock stLock(mTrackerLock);
- mStatusTracker.clear();
- interface = mInterface.get();
- }
+ flushInflightRequests();
- // Call close without internal mutex held, as the HAL close may need to
- // wait on assorted callbacks,etc, to complete before it can return.
- mCameraServiceWatchdog->WATCH(interface->close());
+ {
+ Mutex::Autolock l(mLock);
+ mInterface->clear();
+ mOutputStreams.clear();
+ mInputStream.clear();
+ mDeletedStreams.clear();
+ mBufferManager.clear();
+ internalUpdateStatusLocked(STATUS_UNINITIALIZED);
+ }
- flushInflightRequests();
-
- {
- Mutex::Autolock l(mLock);
- mInterface->clear();
- mOutputStreams.clear();
- mInputStream.clear();
- mDeletedStreams.clear();
- mBufferManager.clear();
- internalUpdateStatusLocked(STATUS_UNINITIALIZED);
- }
-
- for (auto& weakStream : streams) {
- sp<Camera3StreamInterface> stream = weakStream.promote();
- if (stream != nullptr) {
- ALOGE("%s: Stream %d leaked! strong reference (%d)!",
- __FUNCTION__, stream->getId(), stream->getStrongCount() - 1);
- }
+ for (auto& weakStream : streams) {
+ sp<Camera3StreamInterface> stream = weakStream.promote();
+ if (stream != nullptr) {
+ ALOGE("%s: Stream %d leaked! strong reference (%d)!",
+ __FUNCTION__, stream->getId(), stream->getStrongCount() - 1);
}
}
ALOGI("%s: X", __FUNCTION__);
@@ -843,7 +840,7 @@
}
if (res == OK) {
- waitUntilStateThenRelock(/*active*/true, kActiveTimeout);
+ waitUntilStateThenRelock(/*active*/true, kActiveTimeout, /*requestThreadInvocation*/false);
if (res != OK) {
SET_ERR_L("Can't transition to active in %f seconds!",
kActiveTimeout/1e9);
@@ -968,7 +965,8 @@
break;
case STATUS_ACTIVE:
ALOGV("%s: Stopping activity to reconfigure streams", __FUNCTION__);
- res = internalPauseAndWaitLocked(maxExpectedDuration);
+ res = internalPauseAndWaitLocked(maxExpectedDuration,
+ /*requestThreadInvocation*/ false);
if (res != OK) {
SET_ERR_L("Can't pause captures to reconfigure streams!");
return res;
@@ -1085,7 +1083,8 @@
break;
case STATUS_ACTIVE:
ALOGV("%s: Stopping activity to reconfigure streams", __FUNCTION__);
- res = internalPauseAndWaitLocked(maxExpectedDuration);
+ res = internalPauseAndWaitLocked(maxExpectedDuration,
+ /*requestThreadInvocation*/ false);
if (res != OK) {
SET_ERR_L("Can't pause captures to reconfigure streams!");
return res;
@@ -1558,7 +1557,8 @@
}
ALOGV("%s: Camera %s: Waiting until idle (%" PRIi64 "ns)", __FUNCTION__, mId.string(),
maxExpectedDuration);
- status_t res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration);
+ status_t res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration,
+ /*requestThreadInvocation*/ false);
if (res != OK) {
mStatusTracker->dumpActiveComponents();
SET_ERR_L("Error waiting for HAL to drain: %s (%d)", strerror(-res),
@@ -1569,12 +1569,14 @@
void Camera3Device::internalUpdateStatusLocked(Status status) {
mStatus = status;
- mRecentStatusUpdates.add(mStatus);
+ mStatusIsInternal = mPauseStateNotify ? true : false;
+ mRecentStatusUpdates.add({mStatus, mStatusIsInternal});
mStatusChanged.broadcast();
}
// Pause to reconfigure
-status_t Camera3Device::internalPauseAndWaitLocked(nsecs_t maxExpectedDuration) {
+status_t Camera3Device::internalPauseAndWaitLocked(nsecs_t maxExpectedDuration,
+ bool requestThreadInvocation) {
if (mRequestThread.get() != nullptr) {
mRequestThread->setPaused(true);
} else {
@@ -1583,7 +1585,8 @@
ALOGV("%s: Camera %s: Internal wait until idle (% " PRIi64 " ns)", __FUNCTION__, mId.string(),
maxExpectedDuration);
- status_t res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration);
+ status_t res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration,
+ requestThreadInvocation);
if (res != OK) {
mStatusTracker->dumpActiveComponents();
SET_ERR_L("Can't idle device in %f seconds!",
@@ -1601,7 +1604,9 @@
ALOGV("%s: Camera %s: Internal wait until active (% " PRIi64 " ns)", __FUNCTION__, mId.string(),
kActiveTimeout);
- res = waitUntilStateThenRelock(/*active*/ true, kActiveTimeout);
+ // internalResumeLocked is always called from a binder thread.
+ res = waitUntilStateThenRelock(/*active*/ true, kActiveTimeout,
+ /*requestThreadInvocation*/ false);
if (res != OK) {
SET_ERR_L("Can't transition to active in %f seconds!",
kActiveTimeout/1e9);
@@ -1610,7 +1615,8 @@
return OK;
}
-status_t Camera3Device::waitUntilStateThenRelock(bool active, nsecs_t timeout) {
+status_t Camera3Device::waitUntilStateThenRelock(bool active, nsecs_t timeout,
+ bool requestThreadInvocation) {
status_t res = OK;
size_t startIndex = 0;
@@ -1639,7 +1645,8 @@
bool stateSeen = false;
nsecs_t startTime = systemTime();
do {
- if (active == (mStatus == STATUS_ACTIVE)) {
+ if (active == (mStatus == STATUS_ACTIVE) &&
+ (requestThreadInvocation || !mStatusIsInternal)) {
// Desired state is current
break;
}
@@ -1661,9 +1668,14 @@
"%s: Skipping status updates in Camera3Device, may result in deadlock.",
__FUNCTION__);
- // Encountered desired state since we began waiting
+ // Encountered desired state since we began waiting. Internal invocations coming from
+ // request threads (such as reconfigureCamera) should be woken up immediately, whereas
+ // invocations from binder threads (such as createInputStream) should only be woken up if
+ // they are not paused. This avoids intermediate pause signals from reconfigureCamera as it
+ // changes the status to active right after.
for (size_t i = startIndex; i < mRecentStatusUpdates.size(); i++) {
- if (active == (mRecentStatusUpdates[i] == STATUS_ACTIVE) ) {
+ if (active == (mRecentStatusUpdates[i].status == STATUS_ACTIVE) &&
+ (requestThreadInvocation || !mRecentStatusUpdates[i].isInternal)) {
stateSeen = true;
break;
}
@@ -2310,7 +2322,9 @@
nsecs_t startTime = systemTime();
- Mutex::Autolock il(mInterfaceLock);
+ // We must not hold mInterfaceLock here since this function is called from
+ // RequestThread::threadLoop and holding mInterfaceLock could lead to
+ // deadlocks (http://b/143513518)
nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
Mutex::Autolock l(mLock);
@@ -2325,8 +2339,18 @@
if (mStatus == STATUS_ACTIVE) {
markClientActive = true;
mPauseStateNotify = true;
+ mStatusTracker->markComponentIdle(clientStatusId, Fence::NO_FENCE);
- rc = internalPauseAndWaitLocked(maxExpectedDuration);
+ // This is essentially the same as calling rc = internalPauseAndWaitLocked(..), except that
+ // we don't want to call setPaused(true) to avoid it interfering with setPaused() called
+ // from createInputStream/createStream.
+ rc = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration,
+ /*requestThreadInvocation*/ true);
+ if (rc != OK) {
+ mStatusTracker->dumpActiveComponents();
+ SET_ERR_L("Can't idle device in %f seconds!",
+ maxExpectedDuration/1e9);
+ }
}
if (rc == NO_ERROR) {
@@ -3567,13 +3591,8 @@
if (res == OK) {
sp<Camera3Device> parent = mParent.promote();
if (parent != nullptr) {
- sp<StatusTracker> statusTracker = mStatusTracker.promote();
- if (statusTracker != nullptr) {
- statusTracker->markComponentIdle(mStatusId, Fence::NO_FENCE);
- }
mReconfigured |= parent->reconfigureCamera(mLatestSessionParams, mStatusId);
}
- setPaused(false);
if (mNextRequests[0].captureRequest->mInputStream != nullptr) {
mNextRequests[0].captureRequest->mInputStream->restoreConfiguredState();
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index abfd9aa..b1dd135 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -119,7 +119,7 @@
status_t dumpWatchedEventsToVector(std::vector<std::string> &out) override;
const CameraMetadata& info() const override;
const CameraMetadata& infoPhysical(const String8& physicalId) const override;
- bool supportNativeJpegR() const override { return mSupportNativeJpegR; };
+ bool isCompositeJpegRDisabled() const override { return mIsCompositeJpegRDisabled; };
// Capture and setStreamingRequest will configure streams if currently in
// idle state
@@ -366,6 +366,7 @@
// A lock to enforce serialization on the input/configure side
// of the public interface.
+ // Only locked by public methods inherited from CameraDeviceBase.
// Not locked by methods guarded by mOutputLock, since they may act
// concurrently to the input/configure side of the interface.
// Must be locked before mLock if both will be locked by a method
@@ -552,7 +553,7 @@
CameraMetadata mDeviceInfo;
bool mSupportNativeZoomRatio;
- bool mSupportNativeJpegR;
+ bool mIsCompositeJpegRDisabled;
std::unordered_map<std::string, CameraMetadata> mPhysicalDeviceInfoMap;
CameraMetadata mRequestTemplateCache[CAMERA_TEMPLATE_COUNT];
@@ -571,8 +572,15 @@
STATUS_ACTIVE
} mStatus;
+ struct StatusInfo {
+ Status status;
+ bool isInternal; // status triggered by internal reconfigureCamera.
+ };
+
+ bool mStatusIsInternal;
+
// Only clear mRecentStatusUpdates, mStatusWaiters from waitUntilStateThenRelock
- Vector<Status> mRecentStatusUpdates;
+ Vector<StatusInfo> mRecentStatusUpdates;
int mStatusWaiters;
Condition mStatusChanged;
@@ -717,7 +725,8 @@
* CameraDeviceBase interface we shouldn't need to.
* Must be called with mLock and mInterfaceLock both held.
*/
- status_t internalPauseAndWaitLocked(nsecs_t maxExpectedDuration);
+ status_t internalPauseAndWaitLocked(nsecs_t maxExpectedDuration,
+ bool requestThreadInvocation);
/**
* Resume work after internalPauseAndWaitLocked()
@@ -736,7 +745,8 @@
* During the wait mLock is released.
*
*/
- status_t waitUntilStateThenRelock(bool active, nsecs_t timeout);
+ status_t waitUntilStateThenRelock(bool active, nsecs_t timeout,
+ bool requestThreadInvocation);
/**
* Implementation of waitUntilDrained. On success, will transition to IDLE state.
diff --git a/services/camera/libcameraservice/device3/Camera3DeviceInjectionMethods.cpp b/services/camera/libcameraservice/device3/Camera3DeviceInjectionMethods.cpp
index 031c255..ab772d4 100644
--- a/services/camera/libcameraservice/device3/Camera3DeviceInjectionMethods.cpp
+++ b/services/camera/libcameraservice/device3/Camera3DeviceInjectionMethods.cpp
@@ -58,7 +58,8 @@
if (parent->mStatus == STATUS_ACTIVE) {
ALOGV("%s: Let the device be IDLE and the request thread is paused",
__FUNCTION__);
- res = parent->internalPauseAndWaitLocked(maxExpectedDuration);
+ res = parent->internalPauseAndWaitLocked(maxExpectedDuration,
+ /*requestThreadInvocation*/false);
if (res != OK) {
ALOGE("%s: Can't pause captures to inject camera!", __FUNCTION__);
return res;
@@ -117,7 +118,8 @@
if (parent->mStatus == STATUS_ACTIVE) {
ALOGV("%s: Let the device be IDLE and the request thread is paused",
__FUNCTION__);
- res = parent->internalPauseAndWaitLocked(maxExpectedDuration);
+ res = parent->internalPauseAndWaitLocked(maxExpectedDuration,
+ /*requestThreadInvocation*/false);
if (res != OK) {
ALOGE("%s: Can't pause captures to stop injection!", __FUNCTION__);
return res;
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index beef0da..f2a62fa 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -1444,7 +1444,7 @@
//
nsecs_t captureInterval = t - mLastCaptureTime;
if (captureInterval > kSpacingResetIntervalNs) {
- for (size_t i = 0; i < VsyncEventData::kFrameTimelinesLength; i++) {
+ for (size_t i = 0; i < vsyncEventData.frameTimelinesLength; i++) {
const auto& timeline = vsyncEventData.frameTimelines[i];
if (timeline.deadlineTimestamp >= currentTime &&
timeline.expectedPresentationTime > minPresentT) {
@@ -1513,7 +1513,7 @@
// - For variable FPS, or if the capture interval deviates from refresh
// interval for more than 5%, find a presentation time closest to the
// (lastPresentationTime + captureToPresentOffset) instead.
- int maxTimelines = std::min(kMaxTimelines, (int)VsyncEventData::kFrameTimelinesLength);
+ int maxTimelines = std::min(kMaxTimelines, (int)vsyncEventData.frameTimelinesLength);
float biasForShortDelay = 1.0f;
for (int i = 0; i < maxTimelines; i ++) {
const auto& vsyncTime = vsyncEventData.frameTimelines[i];
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp
index e186f13..aa941b0 100644
--- a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp
@@ -205,7 +205,7 @@
return res;
}
mSupportNativeZoomRatio = manager->supportNativeZoomRatio(mId.string());
- mSupportNativeJpegR = manager->supportNativeJpegR(mId.string());
+ mIsCompositeJpegRDisabled = manager->isCompositeJpegRDisabled(mId.string());
std::vector<std::string> physicalCameraIds;
bool isLogical = manager->isLogicalCamera(mId.string(), &physicalCameraIds);
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
index e25f972..ffd9f01 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
@@ -677,7 +677,8 @@
binder::Status
convertToHALStreamCombination(
const SessionConfiguration& sessionConfiguration,
- const String8 &logicalCameraId, const CameraMetadata &deviceInfo, bool supportNativeJpegR,
+ const String8 &logicalCameraId, const CameraMetadata &deviceInfo,
+ bool isCompositeJpegRDisabled,
metadataGetter getMetadata, const std::vector<std::string> &physicalCameraIds,
aidl::android::hardware::camera::device::StreamConfiguration &streamConfiguration,
bool overrideForPerfClass, bool *earlyExit) {
@@ -822,7 +823,7 @@
camera3::HeicCompositeStream::isHeicCompositeStream(surface);
bool isJpegRCompositeStream =
camera3::JpegRCompositeStream::isJpegRCompositeStream(surface) &&
- !supportNativeJpegR;
+ !isCompositeJpegRDisabled;
if (isDepthCompositeStream || isHeicCompositeStream || isJpegRCompositeStream) {
// We need to take in to account that composite streams can have
// additional internal camera streams.
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.h b/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
index d27144e..dc143da 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
@@ -138,7 +138,7 @@
binder::Status
convertToHALStreamCombination(
const SessionConfiguration& sessionConfiguration,
- const String8 &logicalCameraId, const CameraMetadata &deviceInfo, bool supportNativeJpegR,
+ const String8 &logicalCameraId, const CameraMetadata &deviceInfo, bool isCompositeJpegRDisabled,
metadataGetter getMetadata, const std::vector<std::string> &physicalCameraIds,
aidl::android::hardware::camera::device::StreamConfiguration &streamConfiguration,
bool overrideForPerfClass, bool *earlyExit);
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtilsHidl.cpp b/services/camera/libcameraservice/utils/SessionConfigurationUtilsHidl.cpp
index d960024..111c1bf 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtilsHidl.cpp
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtilsHidl.cpp
@@ -111,8 +111,8 @@
bool overrideForPerfClass, bool *earlyExit) {
aidl::android::hardware::camera::device::StreamConfiguration aidlStreamConfiguration;
auto ret = convertToHALStreamCombination(sessionConfiguration, logicalCameraId, deviceInfo,
- false /*supportNativeJpegR*/, getMetadata, physicalCameraIds, aidlStreamConfiguration,
- overrideForPerfClass, earlyExit);
+ false /*isCompositeJpegRDisabled*/, getMetadata, physicalCameraIds,
+ aidlStreamConfiguration, overrideForPerfClass, earlyExit);
if (!ret.isOk()) {
return ret;
}