Merge "cameraserver: fix deadlock scenario in torchModeStatusChanged callback."
diff --git a/camera/OWNERS b/camera/OWNERS
index a4ab616..385c163 100644
--- a/camera/OWNERS
+++ b/camera/OWNERS
@@ -1,8 +1,7 @@
-
# Bug component: 41727
+etalvala@google.com
arakesh@google.com
epeev@google.com
-etalvala@google.com
jchowdhary@google.com
shuzhenwang@google.com
ruchamk@google.com
diff --git a/camera/aidl/android/hardware/ICameraServiceProxy.aidl b/camera/aidl/android/hardware/ICameraServiceProxy.aidl
index bbb0289..3d78aef 100644
--- a/camera/aidl/android/hardware/ICameraServiceProxy.aidl
+++ b/camera/aidl/android/hardware/ICameraServiceProxy.aidl
@@ -37,8 +37,11 @@
oneway void notifyCameraState(in CameraSessionStats cameraSessionStats);
/**
- * Reports whether the top activity needs a rotate and crop override.
+ * Returns the necessary rotate and crop override for the top activity which
+ * will be one of ({@link android.hardware.camera2.CameraMetadata#SCALER_ROTATE_AND_CROP_NONE},
+ * {@link android.hardware.camera2.CameraMetadata#SCALER_ROTATE_AND_CROP_90},
+ * {@link android.hardware.camera2.CameraMetadata#SCALER_ROTATE_AND_CROP_180},
+ * {@link android.hardware.camera2.CameraMetadata#SCALER_ROTATE_AND_CROP_270}).
*/
- boolean isRotateAndCropOverrideNeeded(String packageName, int sensorOrientation,
- int lensFacing);
+ int getRotateAndCropOverride(String packageName, int lensFacing);
}
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index c353b2d..abc63ac 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -2144,6 +2144,50 @@
*/
ACAMERA_FLASH_INFO_AVAILABLE = // byte (acamera_metadata_enum_android_flash_info_available_t)
ACAMERA_FLASH_INFO_START,
+ /**
+ * <p>Maximum flashlight brightness level.</p>
+ *
+ * <p>Type: int32</p>
+ *
+ * <p>This tag may appear in:
+ * <ul>
+ * <li>ACameraMetadata from ACameraManager_getCameraCharacteristics</li>
+ * </ul></p>
+ *
+ * <p>If this value is greater than 1, then the device supports controlling the
+ * flashlight brightness level via
+ * {android.hardware.camera2.CameraManager#setTorchStrengthLevel}.
+ * If this value is equal to 1, flashlight brightness control is not supported.
+ * This value will be -1 if the flash unit is not available.</p>
+ */
+ ACAMERA_FLASH_INFO_STRENGTH_MAXIMUM_LEVEL = // int32
+ ACAMERA_FLASH_INFO_START + 2,
+ /**
+ * <p>Default flashlight brightness level to be set via
+ * {android.hardware.camera2.CameraManager#setTorchStrengthLevel}.</p>
+ *
+ * <p>Type: int32</p>
+ *
+ * <p>This tag may appear in:
+ * <ul>
+ * <li>ACameraMetadata from ACameraManager_getCameraCharacteristics</li>
+ * </ul></p>
+ *
+ * <p>If flash unit is available this will be greater than or equal to 1 and less
+ * or equal to <code>ACAMERA_FLASH_INFO_STRENGTH_MAXIMUM_LEVEL</code>.
+ * If flash unit is not available this will be set to -1.</p>
+ * <p>Setting flashlight brightness above the default level
+ * (i.e.<code>ACAMERA_FLASH_INFO_STRENGTH_DEFAULT_LEVEL</code>) may make the device more
+ * likely to reach thermal throttling conditions and slow down, or drain the
+ * battery quicker than normal. To minimize such issues, it is recommended to
+ * start the flashlight at this default brightness until a user explicitly requests
+ * a brighter level.</p>
+ *
+ * @see ACAMERA_FLASH_INFO_STRENGTH_DEFAULT_LEVEL
+ * @see ACAMERA_FLASH_INFO_STRENGTH_MAXIMUM_LEVEL
+ */
+ ACAMERA_FLASH_INFO_STRENGTH_DEFAULT_LEVEL = // int32
+ ACAMERA_FLASH_INFO_START + 3,
ACAMERA_FLASH_INFO_END,
/**
@@ -4585,7 +4629,7 @@
* Clients are advised to not cache or store the orientation value of such logical sensors.
* In case repeated queries to CameraCharacteristics are not preferred, then clients can
* also access the entire mapping from device state to sensor orientation in
- * <a href="https://developer.android.com/reference/android/hardware/camera2/params/DeviceStateOrientationMap.html">DeviceStateOrientationMap</a>.
+ * <a href="https://developer.android.com/reference/android/hardware/camera2/params/DeviceStateSensorOrientationMap.html">DeviceStateSensorOrientationMap</a>.
* Do note that a dynamically changing sensor orientation value in camera characteristics
* will not be the best way to establish the orientation per frame. Clients that want to
* know the sensor orientation of a particular captured frame should query the
diff --git a/cmds/screenrecord/Android.bp b/cmds/screenrecord/Android.bp
index 359a835..d0b3ce0 100644
--- a/cmds/screenrecord/Android.bp
+++ b/cmds/screenrecord/Android.bp
@@ -55,12 +55,6 @@
"libGLESv2",
],
- include_dirs: [
- "frameworks/av/media/libstagefright",
- "frameworks/av/media/libstagefright/include",
- "frameworks/native/include/media/openmax",
- ],
-
cflags: [
"-Werror",
"-Wall",
diff --git a/media/audioserver/Android.bp b/media/audioserver/Android.bp
index e4fc4de..0b44700 100644
--- a/media/audioserver/Android.bp
+++ b/media/audioserver/Android.bp
@@ -25,6 +25,7 @@
],
shared_libs: [
+ "packagemanager_aidl-cpp",
"libaaudioservice",
"libaudioclient",
"libaudioflinger",
diff --git a/media/codec2/components/avc/C2SoftAvcDec.cpp b/media/codec2/components/avc/C2SoftAvcDec.cpp
index e8287f9..cc4517d 100644
--- a/media/codec2/components/avc/C2SoftAvcDec.cpp
+++ b/media/codec2/components/avc/C2SoftAvcDec.cpp
@@ -511,7 +511,7 @@
status_t C2SoftAvcDec::initDecoder() {
if (OK != createDecoder()) return UNKNOWN_ERROR;
mNumCores = MIN(getCpuCoreCount(), MAX_NUM_CORES);
- mStride = ALIGN32(mWidth);
+ mStride = ALIGN128(mWidth);
mSignalledError = false;
resetPlugin();
(void) setNumCores();
@@ -777,20 +777,20 @@
return C2_CORRUPTED;
}
if (mOutBlock &&
- (mOutBlock->width() != ALIGN32(mWidth) || mOutBlock->height() != mHeight)) {
+ (mOutBlock->width() != ALIGN128(mWidth) || mOutBlock->height() != mHeight)) {
mOutBlock.reset();
}
if (!mOutBlock) {
uint32_t format = HAL_PIXEL_FORMAT_YV12;
C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
c2_status_t err =
- pool->fetchGraphicBlock(ALIGN32(mWidth), mHeight, format, usage, &mOutBlock);
+ pool->fetchGraphicBlock(ALIGN128(mWidth), mHeight, format, usage, &mOutBlock);
if (err != C2_OK) {
ALOGE("fetchGraphicBlock for Output failed with status %d", err);
return err;
}
ALOGV("provided (%dx%d) required (%dx%d)",
- mOutBlock->width(), mOutBlock->height(), ALIGN32(mWidth), mHeight);
+ mOutBlock->width(), mOutBlock->height(), ALIGN128(mWidth), mHeight);
}
return C2_OK;
@@ -928,7 +928,7 @@
if (0 < ps_decode_op->u4_pic_wd && 0 < ps_decode_op->u4_pic_ht) {
if (mHeaderDecoded == false) {
mHeaderDecoded = true;
- mStride = ALIGN32(ps_decode_op->u4_pic_wd);
+ mStride = ALIGN128(ps_decode_op->u4_pic_wd);
setParams(mStride, IVD_DECODE_FRAME);
}
if (ps_decode_op->u4_pic_wd != mWidth || ps_decode_op->u4_pic_ht != mHeight) {
diff --git a/media/codec2/components/avc/C2SoftAvcDec.h b/media/codec2/components/avc/C2SoftAvcDec.h
index 5c07d29..59d5184 100644
--- a/media/codec2/components/avc/C2SoftAvcDec.h
+++ b/media/codec2/components/avc/C2SoftAvcDec.h
@@ -38,7 +38,7 @@
#define ivdext_ctl_set_num_cores_op_t ih264d_ctl_set_num_cores_op_t
#define ivdext_ctl_get_vui_params_ip_t ih264d_ctl_get_vui_params_ip_t
#define ivdext_ctl_get_vui_params_op_t ih264d_ctl_get_vui_params_op_t
-#define ALIGN32(x) ((((x) + 31) >> 5) << 5)
+#define ALIGN128(x) ((((x) + 127) >> 7) << 7)
#define MAX_NUM_CORES 4
#define IVDEXT_CMD_CTL_SET_NUM_CORES \
(IVD_CONTROL_API_COMMAND_TYPE_T)IH264D_CMD_CTL_SET_NUM_CORES
diff --git a/media/codec2/components/gav1/C2SoftGav1Dec.cpp b/media/codec2/components/gav1/C2SoftGav1Dec.cpp
index f857e87..7bd3358 100644
--- a/media/codec2/components/gav1/C2SoftGav1Dec.cpp
+++ b/media/codec2/components/gav1/C2SoftGav1Dec.cpp
@@ -20,6 +20,7 @@
#include <C2Debug.h>
#include <C2PlatformSupport.h>
+#include <Codec2Mapper.h>
#include <SimpleC2Interface.h>
#include <log/log.h>
#include <media/stagefright/foundation/AUtils.h>
@@ -156,6 +157,42 @@
.withSetter(DefaultColorAspectsSetter)
.build());
+ addParameter(
+ DefineParam(mCodedColorAspects, C2_PARAMKEY_VUI_COLOR_ASPECTS)
+ .withDefault(new C2StreamColorAspectsInfo::input(
+ 0u, C2Color::RANGE_LIMITED, C2Color::PRIMARIES_UNSPECIFIED,
+ C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
+ .withFields({
+ C2F(mCodedColorAspects, range).inRange(
+ C2Color::RANGE_UNSPECIFIED, C2Color::RANGE_OTHER),
+ C2F(mCodedColorAspects, primaries).inRange(
+ C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER),
+ C2F(mCodedColorAspects, transfer).inRange(
+ C2Color::TRANSFER_UNSPECIFIED, C2Color::TRANSFER_OTHER),
+ C2F(mCodedColorAspects, matrix).inRange(
+ C2Color::MATRIX_UNSPECIFIED, C2Color::MATRIX_OTHER)
+ })
+ .withSetter(CodedColorAspectsSetter)
+ .build());
+
+ addParameter(
+ DefineParam(mColorAspects, C2_PARAMKEY_COLOR_ASPECTS)
+ .withDefault(new C2StreamColorAspectsInfo::output(
+ 0u, C2Color::RANGE_UNSPECIFIED, C2Color::PRIMARIES_UNSPECIFIED,
+ C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
+ .withFields({
+ C2F(mColorAspects, range).inRange(
+ C2Color::RANGE_UNSPECIFIED, C2Color::RANGE_OTHER),
+ C2F(mColorAspects, primaries).inRange(
+ C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER),
+ C2F(mColorAspects, transfer).inRange(
+ C2Color::TRANSFER_UNSPECIFIED, C2Color::TRANSFER_OTHER),
+ C2F(mColorAspects, matrix).inRange(
+ C2Color::MATRIX_UNSPECIFIED, C2Color::MATRIX_OTHER)
+ })
+ .withSetter(ColorAspectsSetter, mDefaultColorAspects, mCodedColorAspects)
+ .build());
+
// TODO: support more formats?
addParameter(DefineParam(mPixelFormat, C2_PARAMKEY_PIXEL_FORMAT)
.withConstValue(new C2StreamPixelFormatInfo::output(
@@ -218,6 +255,37 @@
return C2R::Ok();
}
+ static C2R CodedColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsInfo::input> &me) {
+ (void)mayBlock;
+ if (me.v.range > C2Color::RANGE_OTHER) {
+ me.set().range = C2Color::RANGE_OTHER;
+ }
+ if (me.v.primaries > C2Color::PRIMARIES_OTHER) {
+ me.set().primaries = C2Color::PRIMARIES_OTHER;
+ }
+ if (me.v.transfer > C2Color::TRANSFER_OTHER) {
+ me.set().transfer = C2Color::TRANSFER_OTHER;
+ }
+ if (me.v.matrix > C2Color::MATRIX_OTHER) {
+ me.set().matrix = C2Color::MATRIX_OTHER;
+ }
+ return C2R::Ok();
+ }
+
+ static C2R ColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsInfo::output> &me,
+ const C2P<C2StreamColorAspectsTuning::output> &def,
+ const C2P<C2StreamColorAspectsInfo::input> &coded) {
+ (void)mayBlock;
+ // take default values for all unspecified fields, and coded values for specified ones
+ me.set().range = coded.v.range == RANGE_UNSPECIFIED ? def.v.range : coded.v.range;
+ me.set().primaries = coded.v.primaries == PRIMARIES_UNSPECIFIED
+ ? def.v.primaries : coded.v.primaries;
+ me.set().transfer = coded.v.transfer == TRANSFER_UNSPECIFIED
+ ? def.v.transfer : coded.v.transfer;
+ me.set().matrix = coded.v.matrix == MATRIX_UNSPECIFIED ? def.v.matrix : coded.v.matrix;
+ return C2R::Ok();
+ }
+
static C2R ProfileLevelSetter(
bool mayBlock, C2P<C2StreamProfileLevelInfo::input> &me,
const C2P<C2StreamPictureSizeInfo::output> &size) {
@@ -232,6 +300,10 @@
return mDefaultColorAspects;
}
+ std::shared_ptr<C2StreamColorAspectsInfo::output> getColorAspects_l() {
+ return mColorAspects;
+ }
+
static C2R Hdr10PlusInfoInputSetter(bool mayBlock,
C2P<C2StreamHdr10PlusInfo::input> &me) {
(void)mayBlock;
@@ -254,6 +326,8 @@
std::shared_ptr<C2StreamColorInfo::output> mColorInfo;
std::shared_ptr<C2StreamPixelFormatInfo::output> mPixelFormat;
std::shared_ptr<C2StreamColorAspectsTuning::output> mDefaultColorAspects;
+ std::shared_ptr<C2StreamColorAspectsInfo::input> mCodedColorAspects;
+ std::shared_ptr<C2StreamColorAspectsInfo::output> mColorAspects;
std::shared_ptr<C2StreamHdr10PlusInfo::input> mHdr10PlusInfoInput;
std::shared_ptr<C2StreamHdr10PlusInfo::output> mHdr10PlusInfoOutput;
};
@@ -371,6 +445,10 @@
const std::shared_ptr<C2GraphicBlock> &block) {
std::shared_ptr<C2Buffer> buffer =
createGraphicBuffer(block, C2Rect(mWidth, mHeight));
+ {
+ IntfImpl::Lock lock = mIntf->lock();
+ buffer->setInfo(mIntf->getColorAspects_l());
+ }
auto fillWork = [buffer, index](const std::unique_ptr<C2Work> &work) {
uint32_t flags = 0;
if ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) &&
@@ -609,6 +687,38 @@
}
}
+void C2SoftGav1Dec::getVuiParams(const libgav1::DecoderBuffer *buffer) {
+ VuiColorAspects vuiColorAspects;
+ vuiColorAspects.primaries = buffer->color_primary;
+ vuiColorAspects.transfer = buffer->transfer_characteristics;
+ vuiColorAspects.coeffs = buffer->matrix_coefficients;
+ vuiColorAspects.fullRange = buffer->color_range;
+
+ // convert vui aspects to C2 values if changed
+ if (!(vuiColorAspects == mBitstreamColorAspects)) {
+ mBitstreamColorAspects = vuiColorAspects;
+ ColorAspects sfAspects;
+ C2StreamColorAspectsInfo::input codedAspects = { 0u };
+ ColorUtils::convertIsoColorAspectsToCodecAspects(
+ vuiColorAspects.primaries, vuiColorAspects.transfer, vuiColorAspects.coeffs,
+ vuiColorAspects.fullRange, sfAspects);
+ if (!C2Mapper::map(sfAspects.mPrimaries, &codedAspects.primaries)) {
+ codedAspects.primaries = C2Color::PRIMARIES_UNSPECIFIED;
+ }
+ if (!C2Mapper::map(sfAspects.mRange, &codedAspects.range)) {
+ codedAspects.range = C2Color::RANGE_UNSPECIFIED;
+ }
+ if (!C2Mapper::map(sfAspects.mMatrixCoeffs, &codedAspects.matrix)) {
+ codedAspects.matrix = C2Color::MATRIX_UNSPECIFIED;
+ }
+ if (!C2Mapper::map(sfAspects.mTransfer, &codedAspects.transfer)) {
+ codedAspects.transfer = C2Color::TRANSFER_UNSPECIFIED;
+ }
+ std::vector<std::unique_ptr<C2SettingResult>> failures;
+ mIntf->config({&codedAspects}, C2_MAY_BLOCK, &failures);
+ }
+}
+
bool C2SoftGav1Dec::outputBuffer(const std::shared_ptr<C2BlockPool> &pool,
const std::unique_ptr<C2Work> &work) {
if (!(work && pool)) return false;
@@ -651,6 +761,7 @@
}
}
+ getVuiParams(buffer);
if (!(buffer->image_format == libgav1::kImageFormatYuv420 ||
buffer->image_format == libgav1::kImageFormatMonochrome400)) {
ALOGE("image_format %d not supported", buffer->image_format);
@@ -666,12 +777,12 @@
uint32_t format = HAL_PIXEL_FORMAT_YV12;
if (buffer->bitdepth == 10) {
IntfImpl::Lock lock = mIntf->lock();
- std::shared_ptr<C2StreamColorAspectsTuning::output> defaultColorAspects =
- mIntf->getDefaultColorAspects_l();
+ std::shared_ptr<C2StreamColorAspectsInfo::output> codedColorAspects =
+ mIntf->getColorAspects_l();
- if (defaultColorAspects->primaries == C2Color::PRIMARIES_BT2020 &&
- defaultColorAspects->matrix == C2Color::MATRIX_BT2020 &&
- defaultColorAspects->transfer == C2Color::TRANSFER_ST2084) {
+ if (codedColorAspects->primaries == C2Color::PRIMARIES_BT2020 &&
+ codedColorAspects->matrix == C2Color::MATRIX_BT2020 &&
+ codedColorAspects->transfer == C2Color::TRANSFER_ST2084) {
if (buffer->image_format != libgav1::kImageFormatYuv420) {
ALOGE("Only YUV420 output is supported when targeting RGBA_1010102");
mSignalledError = true;
diff --git a/media/codec2/components/gav1/C2SoftGav1Dec.h b/media/codec2/components/gav1/C2SoftGav1Dec.h
index 555adc9..134fa0d 100644
--- a/media/codec2/components/gav1/C2SoftGav1Dec.h
+++ b/media/codec2/components/gav1/C2SoftGav1Dec.h
@@ -17,7 +17,10 @@
#ifndef ANDROID_C2_SOFT_GAV1_DEC_H_
#define ANDROID_C2_SOFT_GAV1_DEC_H_
+#include <media/stagefright/foundation/ColorUtils.h>
+
#include <SimpleC2Component.h>
+#include <C2Config.h>
#include "libgav1/src/gav1/decoder.h"
#include "libgav1/src/gav1/decoder_settings.h"
@@ -56,10 +59,32 @@
bool mSignalledOutputEos;
bool mSignalledError;
+ // Color aspects. These are ISO values and are meant to detect changes in aspects to avoid
+ // converting them to C2 values for each frame
+ struct VuiColorAspects {
+ uint8_t primaries;
+ uint8_t transfer;
+ uint8_t coeffs;
+ uint8_t fullRange;
+
+ // default color aspects
+ VuiColorAspects()
+ : primaries(C2Color::PRIMARIES_UNSPECIFIED),
+ transfer(C2Color::TRANSFER_UNSPECIFIED),
+ coeffs(C2Color::MATRIX_UNSPECIFIED),
+ fullRange(C2Color::RANGE_UNSPECIFIED) { }
+
+ bool operator==(const VuiColorAspects &o) {
+ return primaries == o.primaries && transfer == o.transfer && coeffs == o.coeffs
+ && fullRange == o.fullRange;
+ }
+ } mBitstreamColorAspects;
+
struct timeval mTimeStart; // Time at the start of decode()
struct timeval mTimeEnd; // Time at the end of decode()
bool initDecoder();
+ void getVuiParams(const libgav1::DecoderBuffer *buffer);
void destroyDecoder();
void finishWork(uint64_t index, const std::unique_ptr<C2Work>& work,
const std::shared_ptr<C2GraphicBlock>& block);
diff --git a/media/codec2/components/hevc/C2SoftHevcDec.cpp b/media/codec2/components/hevc/C2SoftHevcDec.cpp
index 6bcf3a2..5f5b2ef 100644
--- a/media/codec2/components/hevc/C2SoftHevcDec.cpp
+++ b/media/codec2/components/hevc/C2SoftHevcDec.cpp
@@ -502,7 +502,7 @@
status_t C2SoftHevcDec::initDecoder() {
if (OK != createDecoder()) return UNKNOWN_ERROR;
mNumCores = MIN(getCpuCoreCount(), MAX_NUM_CORES);
- mStride = ALIGN32(mWidth);
+ mStride = ALIGN128(mWidth);
mSignalledError = false;
resetPlugin();
(void) setNumCores();
@@ -768,20 +768,20 @@
return C2_CORRUPTED;
}
if (mOutBlock &&
- (mOutBlock->width() != ALIGN32(mWidth) || mOutBlock->height() != mHeight)) {
+ (mOutBlock->width() != ALIGN128(mWidth) || mOutBlock->height() != mHeight)) {
mOutBlock.reset();
}
if (!mOutBlock) {
uint32_t format = HAL_PIXEL_FORMAT_YV12;
C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
c2_status_t err =
- pool->fetchGraphicBlock(ALIGN32(mWidth), mHeight, format, usage, &mOutBlock);
+ pool->fetchGraphicBlock(ALIGN128(mWidth), mHeight, format, usage, &mOutBlock);
if (err != C2_OK) {
ALOGE("fetchGraphicBlock for Output failed with status %d", err);
return err;
}
ALOGV("provided (%dx%d) required (%dx%d)",
- mOutBlock->width(), mOutBlock->height(), ALIGN32(mWidth), mHeight);
+ mOutBlock->width(), mOutBlock->height(), ALIGN128(mWidth), mHeight);
}
return C2_OK;
@@ -917,7 +917,7 @@
if (0 < ps_decode_op->u4_pic_wd && 0 < ps_decode_op->u4_pic_ht) {
if (mHeaderDecoded == false) {
mHeaderDecoded = true;
- setParams(ALIGN32(ps_decode_op->u4_pic_wd), IVD_DECODE_FRAME);
+ setParams(ALIGN128(ps_decode_op->u4_pic_wd), IVD_DECODE_FRAME);
}
if (ps_decode_op->u4_pic_wd != mWidth || ps_decode_op->u4_pic_ht != mHeight) {
mWidth = ps_decode_op->u4_pic_wd;
diff --git a/media/codec2/components/hevc/C2SoftHevcDec.h b/media/codec2/components/hevc/C2SoftHevcDec.h
index b9b0a48..b9296e9 100644
--- a/media/codec2/components/hevc/C2SoftHevcDec.h
+++ b/media/codec2/components/hevc/C2SoftHevcDec.h
@@ -36,7 +36,7 @@
#define ivdext_ctl_set_num_cores_op_t ihevcd_cxa_ctl_set_num_cores_op_t
#define ivdext_ctl_get_vui_params_ip_t ihevcd_cxa_ctl_get_vui_params_ip_t
#define ivdext_ctl_get_vui_params_op_t ihevcd_cxa_ctl_get_vui_params_op_t
-#define ALIGN32(x) ((((x) + 31) >> 5) << 5)
+#define ALIGN128(x) ((((x) + 127) >> 7) << 7)
#define MAX_NUM_CORES 4
#define IVDEXT_CMD_CTL_SET_NUM_CORES \
(IVD_CONTROL_API_COMMAND_TYPE_T)IHEVCD_CXA_CMD_CTL_SET_NUM_CORES
diff --git a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp
index b1cf388..5f9b30b 100644
--- a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp
+++ b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp
@@ -572,7 +572,7 @@
if (OK != createDecoder()) return UNKNOWN_ERROR;
mNumCores = MIN(getCpuCoreCount(), MAX_NUM_CORES);
- mStride = ALIGN32(mWidth);
+ mStride = ALIGN128(mWidth);
mSignalledError = false;
resetPlugin();
(void) setNumCores();
@@ -845,20 +845,20 @@
return C2_CORRUPTED;
}
if (mOutBlock &&
- (mOutBlock->width() != ALIGN32(mWidth) || mOutBlock->height() != mHeight)) {
+ (mOutBlock->width() != ALIGN128(mWidth) || mOutBlock->height() != mHeight)) {
mOutBlock.reset();
}
if (!mOutBlock) {
uint32_t format = HAL_PIXEL_FORMAT_YV12;
C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
c2_status_t err =
- pool->fetchGraphicBlock(ALIGN32(mWidth), mHeight, format, usage, &mOutBlock);
+ pool->fetchGraphicBlock(ALIGN128(mWidth), mHeight, format, usage, &mOutBlock);
if (err != C2_OK) {
ALOGE("fetchGraphicBlock for Output failed with status %d", err);
return err;
}
ALOGV("provided (%dx%d) required (%dx%d)",
- mOutBlock->width(), mOutBlock->height(), ALIGN32(mWidth), mHeight);
+ mOutBlock->width(), mOutBlock->height(), ALIGN128(mWidth), mHeight);
}
return C2_OK;
diff --git a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.h b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.h
index fd66304a..8a29c14 100644
--- a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.h
+++ b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.h
@@ -37,7 +37,7 @@
#define ivdext_ctl_set_num_cores_op_t impeg2d_ctl_set_num_cores_op_t
#define ivdext_ctl_get_seq_info_ip_t impeg2d_ctl_get_seq_info_ip_t
#define ivdext_ctl_get_seq_info_op_t impeg2d_ctl_get_seq_info_op_t
-#define ALIGN32(x) ((((x) + 31) >> 5) << 5)
+#define ALIGN128(x) ((((x) + 127) >> 7) << 7)
#define MAX_NUM_CORES 4
#define IVDEXT_CMD_CTL_SET_NUM_CORES \
(IVD_CONTROL_API_COMMAND_TYPE_T)IMPEG2D_CMD_CTL_SET_NUM_CORES
diff --git a/media/codec2/vndk/platform/C2BqBuffer.cpp b/media/codec2/vndk/platform/C2BqBuffer.cpp
index 169de0c..01995fd 100644
--- a/media/codec2/vndk/platform/C2BqBuffer.cpp
+++ b/media/codec2/vndk/platform/C2BqBuffer.cpp
@@ -16,6 +16,7 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "C2BqBuffer"
+#include <android/hardware_buffer.h>
#include <utils/Log.h>
#include <ui/BufferQueueDefs.h>
@@ -171,6 +172,91 @@
return stamp;
}
+// Do not rely on AHardwareBuffer module for GraphicBuffer handling since AHardwareBuffer
+// module is linked to framework which could have a different implementation of GraphicBuffer
+// than mainline/vndk implementation.(See b/203347494.)
+//
+// b2h/h2b between HardwareBuffer and GraphicBuffer cannot be used. (b2h/h2b depend on
+// AHardwareBuffer module for the conversion between HardwareBuffer and GraphicBuffer.)
+// hgbp_ prefixed methods are added to be used instead of b2h/h2b.
+//
+// TODO: Remove dependency with existing AHwB module. Also clean up conversions.(conversions here
+// and h2b/b2h coversions)
+const GraphicBuffer* hgbp_AHBuffer_to_GraphicBuffer(const AHardwareBuffer* buffer) {
+ return GraphicBuffer::fromAHardwareBuffer(buffer);
+}
+
+int hgbp_createFromHandle(const AHardwareBuffer_Desc* desc,
+ const native_handle_t* handle,
+ sp<GraphicBuffer> *outBuffer) {
+
+ if (!desc || !handle || !outBuffer) return ::android::BAD_VALUE;
+ if (desc->rfu0 != 0 || desc->rfu1 != 0) return ::android::BAD_VALUE;
+ if (desc->format == AHARDWAREBUFFER_FORMAT_BLOB && desc->height != 1)
+ return ::android::BAD_VALUE;
+
+ const int format = uint32_t(desc->format);
+ const uint64_t usage = uint64_t(desc->usage);
+ sp<GraphicBuffer> gbuffer(new GraphicBuffer(handle,
+ GraphicBuffer::HandleWrapMethod::CLONE_HANDLE,
+ desc->width, desc->height,
+ format, desc->layers, usage, desc->stride));
+ status_t err = gbuffer->initCheck();
+ if (err != 0 || gbuffer->handle == 0) return err;
+
+ *outBuffer = gbuffer;
+
+ return ::android::NO_ERROR;
+}
+
+void hgbp_describe(const AHardwareBuffer* buffer,
+ AHardwareBuffer_Desc* outDesc) {
+ if (!buffer || !outDesc) return;
+
+ const GraphicBuffer* gbuffer = hgbp_AHBuffer_to_GraphicBuffer(buffer);
+
+ outDesc->width = gbuffer->getWidth();
+ outDesc->height = gbuffer->getHeight();
+ outDesc->layers = gbuffer->getLayerCount();
+ outDesc->format = uint32_t(gbuffer->getPixelFormat());
+ outDesc->usage = uint64_t(gbuffer->getUsage());
+ outDesc->stride = gbuffer->getStride();
+ outDesc->rfu0 = 0;
+ outDesc->rfu1 = 0;
+}
+
+
+bool hgbp_h2b(HBuffer const& from, sp<GraphicBuffer>* to) {
+ AHardwareBuffer_Desc const* desc =
+ reinterpret_cast<AHardwareBuffer_Desc const*>(
+ from.description.data());
+ native_handle_t const* handle = from.nativeHandle;
+ if (hgbp_createFromHandle(desc, handle, to) != ::android::OK) {
+ return false;
+ }
+ return true;
+}
+
+bool hgbp_b2h(sp<GraphicBuffer> const& from, HBuffer* to,
+ uint32_t* toGenerationNumber) {
+ if (!from) {
+ return false;
+ }
+ AHardwareBuffer* hwBuffer = from->toAHardwareBuffer();
+ to->nativeHandle.setTo(
+ const_cast<native_handle_t*>(from->handle),
+ false);
+ hgbp_describe(
+ hwBuffer,
+ reinterpret_cast<AHardwareBuffer_Desc*>(to->description.data()));
+ if (toGenerationNumber) {
+ *toGenerationNumber = from->getGenerationNumber();
+ }
+ return true;
+}
+
+// End of hgbp methods for GraphicBuffer creation.
+
bool getGenerationNumberAndUsage(const sp<HGraphicBufferProducer> &producer,
uint32_t *generation, uint64_t *usage) {
status_t status{};
@@ -211,7 +297,7 @@
HBuffer const& hBuffer,
uint32_t generationNumber){
if (h2b(hStatus, &status) &&
- h2b(hBuffer, &slotBuffer) &&
+ hgbp_h2b(hBuffer, &slotBuffer) &&
slotBuffer) {
*generation = generationNumber;
*usage = slotBuffer->getUsage();
@@ -402,7 +488,7 @@
HBuffer const& hBuffer,
uint32_t generationNumber){
if (h2b(hStatus, &status) &&
- h2b(hBuffer, &slotBuffer) &&
+ hgbp_h2b(hBuffer, &slotBuffer) &&
slotBuffer) {
slotBuffer->setGenerationNumber(generationNumber);
outGeneration = generationNumber;
@@ -804,7 +890,7 @@
HBuffer hBuffer{};
uint32_t hGenerationNumber{};
- if (!b2h(graphicBuffer, &hBuffer, &hGenerationNumber)) {
+ if (!hgbp_b2h(graphicBuffer, &hBuffer, &hGenerationNumber)) {
ALOGD("I to O conversion failed");
return -1;
}
diff --git a/media/libaaudio/fuzzer/Android.bp b/media/libaaudio/fuzzer/Android.bp
new file mode 100644
index 0000000..b19376d
--- /dev/null
+++ b/media/libaaudio/fuzzer/Android.bp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+cc_fuzz {
+ name: "libaaudio_fuzzer",
+ srcs: [
+ "libaaudio_fuzzer.cpp",
+ ],
+ header_libs: [
+ "libaaudio_headers",
+ ],
+ shared_libs: [
+ "libbinder",
+ "libaudiomanager",
+ "libaudiopolicy",
+ "libaudioclient_aidl_conversion",
+ ],
+ static_libs: [
+ "android.media.audio.common.types-V1-cpp",
+ "liblog",
+ "libutils",
+ "libcutils",
+ "libaaudio",
+ "libjsoncpp",
+ "libbase_ndk",
+ "libcgrouprc",
+ "libaudioutils",
+ "libaudioclient",
+ "aaudio-aidl-cpp",
+ "libmedia_helper",
+ "libmediametrics",
+ "libprocessgroup",
+ "av-types-aidl-cpp",
+ "libaaudio_internal",
+ "libcgrouprc_format",
+ "audiopolicy-aidl-cpp",
+ "audioflinger-aidl-cpp",
+ "audiopolicy-types-aidl-cpp",
+ "audioclient-types-aidl-cpp",
+ "shared-file-region-aidl-cpp",
+ "framework-permission-aidl-cpp",
+ "mediametricsservice-aidl-cpp",
+ ],
+ fuzz_config: {
+ cc: [
+ "android-media-fuzzing-reports@google.com",
+ ],
+ componentid: 155276,
+ },
+}
diff --git a/media/libaaudio/fuzzer/README.md b/media/libaaudio/fuzzer/README.md
new file mode 100644
index 0000000..4ba15c5
--- /dev/null
+++ b/media/libaaudio/fuzzer/README.md
@@ -0,0 +1,77 @@
+# Fuzzer for libaaudio
+
+## Plugin Design Considerations
+The fuzzer plugin for `libaaudio` are designed based on the understanding of the
+source code and tries to achieve the following:
+
+##### Maximize code coverage
+The configuration parameters are not hardcoded, but instead selected based on
+incoming data. This ensures more code paths are reached by the fuzzer.
+
+Fuzzers assigns values to the following parameters to pass on to libaaudio:
+1. Device Id (parameter name: `deviceId`)
+2. Sampling Rate (parameter name: `sampleRate`)
+3. Number of channels (parameter name: `channelCount`)
+4. Audio Travel Direction (parameter name: `direction`)
+5. Audio Format (parameter name: `format`)
+6. Audio Sharing Mode (parameter name: `sharingMode`)
+7. Audio Usage (parameter name: `usage`)
+8. Audio Content type (parameter name: `contentType`)
+9. Audio Input Preset (parameter name: `inputPreset`)
+10. Audio Privacy Sensitivity (parameter name: `privacySensitive`)
+11. Buffer Capacity In Frames (parameter name: `frames`)
+12. Performance Mode (parameter name: `mode`)
+13. Allowed Capture Policy (parameter name: `allowedCapturePolicy`)
+14. Session Id (parameter name: `sessionId`)
+15. Frames per Data Callback (parameter name: `framesPerDataCallback`)
+16. MMap Policy (parameter name: `policy`)
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+| `deviceId` | Any value of type `int32_t` | Value obtained from FuzzedDataProvider |
+| `sampleRate` | Any value of type `int32_t` | Value obtained from FuzzedDataProvider |
+| `channelCount` | Any value of type `int32_t` | Value obtained from FuzzedDataProvider |
+| `direction` | 0. `AAUDIO_DIRECTION_OUTPUT` 1. `AAUDIO_DIRECTION_INPUT` | Value obtained from FuzzedDataProvider |
+| `format` | 0. `AAUDIO_FORMAT_INVALID` 1. `AAUDIO_FORMAT_UNSPECIFIED` 2. `AAUDIO_FORMAT_PCM_I16` 3. `AAUDIO_FORMAT_PCM_FLOAT` | Value obtained from FuzzedDataProvider |
+| `sharingMode` | 0. `AAUDIO_SHARING_MODE_EXCLUSIVE` 1. `AAUDIO_SHARING_MODE_SHARED` | Value obtained from FuzzedDataProvider |
+| `usage` | 0. `AAUDIO_USAGE_MEDIA` 1. `AAUDIO_USAGE_VOICE_COMMUNICATION` 2. `AAUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING` 3. `AAUDIO_USAGE_ALARM` 4. `AAUDIO_USAGE_NOTIFICATION` 5. `AAUDIO_USAGE_NOTIFICATION_RINGTONE` 6. `AAUDIO_USAGE_NOTIFICATION_EVENT` 7. `AAUDIO_USAGE_ASSISTANCE_ACCESSIBILITY` 8. `AAUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE` 9. `AAUDIO_USAGE_ASSISTANCE_SONIFICATION` 10. `AAUDIO_USAGE_GAME` 11. `AAUDIO_USAGE_ASSISTANT` 12. `AAUDIO_SYSTEM_USAGE_EMERGENCY` 13. `AAUDIO_SYSTEM_USAGE_SAFETY` 14. `AAUDIO_SYSTEM_USAGE_VEHICLE_STATUS` 15. `AAUDIO_SYSTEM_USAGE_ANNOUNCEMENT` | Value obtained from FuzzedDataProvider |
+| `contentType` | 0. `AAUDIO_CONTENT_TYPE_SPEECH` 1. `AAUDIO_CONTENT_TYPE_MUSIC` 2. `AAUDIO_CONTENT_TYPE_MOVIE` 3. `AAUDIO_CONTENT_TYPE_SONIFICATION` | Value obtained from FuzzedDataProvider |
+| `inputPreset` | 0. `AAUDIO_INPUT_PRESET_GENERIC` 1. `AAUDIO_INPUT_PRESET_CAMCORDER` 2. `AAUDIO_INPUT_PRESET_VOICE_RECOGNITION` 3. `AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION` 4. `AAUDIO_INPUT_PRESET_UNPROCESSED` 5. `AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE` | Value obtained from FuzzedDataProvider |
+| `privacySensitive` | 0. `true` 1. `false` | Value obtained from FuzzedDataProvider |
+| `frames` | Any value of type `int32_t` | Value obtained from FuzzedDataProvider |
+| `mode` | 0. `AAUDIO_PERFORMANCE_MODE_NONE` 1. `AAUDIO_PERFORMANCE_MODE_POWER_SAVING` 2. `AAUDIO_PERFORMANCE_MODE_LOW_LATENCY` | Value obtained from FuzzedDataProvider |
+| `allowedCapturePolicy` | 0. `AAUDIO_ALLOW_CAPTURE_BY_ALL` 1. `AAUDIO_ALLOW_CAPTURE_BY_SYSTEM` 2. `AAUDIO_ALLOW_CAPTURE_BY_NONE` | Value obtained from FuzzedDataProvider |
+| `sessionId` | 0. `AAUDIO_SESSION_ID_NONE` 1. `AAUDIO_SESSION_ID_ALLOCATE` | Value obtained from FuzzedDataProvider |
+| `framesPerDataCallback` | Any value of type `int32_t` | Value obtained from FuzzedDataProvider |
+| `policy` | 0. `AAUDIO_POLICY_NEVER` 1. `AAUDIO_POLICY_AUTO` 2. `AAUDIO_POLICY_ALWAYS` | Value obtained from FuzzedDataProvider |
+
+This also ensures that the plugin is always deterministic for any given input.
+
+##### Maximize utilization of input data
+The plugin feed the entire input data to the module.
+This ensures that the plugins tolerates any kind of input (empty, huge,
+malformed, etc) and doesn't `exit()` on any input and thereby increasing the
+chance of identifying vulnerabilities.
+
+## Build
+
+This describes steps to build libaaudio_fuzzer binary.
+
+### Android
+
+#### Steps to build
+Build the fuzzer
+```
+ $ mm -j$(nproc) libaaudio_fuzzer
+```
+### Steps to run
+
+To run on device
+```
+ $ adb sync data
+ $ adb shell /data/fuzz/arm64/libaaudio_fuzzer/libaaudio_fuzzer
+```
+
+## References:
+ * http://llvm.org/docs/LibFuzzer.html
+ * https://github.com/google/oss-fuzz
diff --git a/media/libaaudio/fuzzer/libaaudio_fuzzer.cpp b/media/libaaudio/fuzzer/libaaudio_fuzzer.cpp
new file mode 100644
index 0000000..1167bb0
--- /dev/null
+++ b/media/libaaudio/fuzzer/libaaudio_fuzzer.cpp
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2021 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.
+ *
+ */
+
+#include "aaudio/AAudio.h"
+#include "aaudio/AAudioTesting.h"
+#include <fuzzer/FuzzedDataProvider.h>
+
+constexpr int32_t kRandomStringLength = 256;
+
+constexpr int64_t kNanosPerMillisecond = 1000 * 1000;
+
+constexpr aaudio_direction_t kDirections[] = {
+ AAUDIO_DIRECTION_OUTPUT, AAUDIO_DIRECTION_INPUT, AAUDIO_UNSPECIFIED};
+
+constexpr aaudio_performance_mode_t kPerformanceModes[] = {
+ AAUDIO_PERFORMANCE_MODE_NONE, AAUDIO_PERFORMANCE_MODE_POWER_SAVING,
+ AAUDIO_PERFORMANCE_MODE_LOW_LATENCY, AAUDIO_UNSPECIFIED};
+
+constexpr aaudio_format_t kFormats[] = {
+ AAUDIO_FORMAT_INVALID, AAUDIO_FORMAT_UNSPECIFIED,
+ AAUDIO_FORMAT_PCM_I16, AAUDIO_FORMAT_PCM_FLOAT,
+ AAUDIO_FORMAT_PCM_I24_PACKED, AAUDIO_FORMAT_PCM_I32};
+
+constexpr aaudio_sharing_mode_t kSharingModes[] = {
+ AAUDIO_SHARING_MODE_EXCLUSIVE, AAUDIO_SHARING_MODE_SHARED};
+
+constexpr int32_t kSampleRates[] = {AAUDIO_UNSPECIFIED,
+ 8000,
+ 11025,
+ 16000,
+ 22050,
+ 32000,
+ 44100,
+ 48000,
+ 88200,
+ 96000};
+
+constexpr aaudio_usage_t kUsages[] = {
+ AAUDIO_USAGE_MEDIA,
+ AAUDIO_USAGE_VOICE_COMMUNICATION,
+ AAUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING,
+ AAUDIO_USAGE_ALARM,
+ AAUDIO_USAGE_NOTIFICATION,
+ AAUDIO_USAGE_NOTIFICATION_RINGTONE,
+ AAUDIO_USAGE_NOTIFICATION_EVENT,
+ AAUDIO_USAGE_ASSISTANCE_ACCESSIBILITY,
+ AAUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
+ AAUDIO_USAGE_ASSISTANCE_SONIFICATION,
+ AAUDIO_USAGE_GAME,
+ AAUDIO_USAGE_ASSISTANT,
+ AAUDIO_SYSTEM_USAGE_EMERGENCY,
+ AAUDIO_SYSTEM_USAGE_SAFETY,
+ AAUDIO_SYSTEM_USAGE_VEHICLE_STATUS,
+ AAUDIO_SYSTEM_USAGE_ANNOUNCEMENT,
+ AAUDIO_UNSPECIFIED};
+
+constexpr aaudio_content_type_t kContentTypes[] = {
+ AAUDIO_CONTENT_TYPE_SPEECH, AAUDIO_CONTENT_TYPE_MUSIC,
+ AAUDIO_CONTENT_TYPE_MOVIE, AAUDIO_CONTENT_TYPE_SONIFICATION,
+ AAUDIO_UNSPECIFIED};
+
+constexpr aaudio_input_preset_t kInputPresets[] = {
+ AAUDIO_INPUT_PRESET_GENERIC,
+ AAUDIO_INPUT_PRESET_CAMCORDER,
+ AAUDIO_INPUT_PRESET_VOICE_RECOGNITION,
+ AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION,
+ AAUDIO_INPUT_PRESET_UNPROCESSED,
+ AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE,
+ AAUDIO_UNSPECIFIED};
+
+constexpr aaudio_allowed_capture_policy_t kAllowedCapturePolicies[] = {
+ AAUDIO_ALLOW_CAPTURE_BY_ALL, AAUDIO_ALLOW_CAPTURE_BY_SYSTEM,
+ AAUDIO_ALLOW_CAPTURE_BY_NONE, AAUDIO_UNSPECIFIED};
+
+constexpr aaudio_session_id_t kSessionIds[] = {
+ AAUDIO_SESSION_ID_NONE, AAUDIO_SESSION_ID_ALLOCATE, AAUDIO_UNSPECIFIED};
+
+constexpr aaudio_policy_t kPolicies[] = {
+ AAUDIO_POLICY_NEVER, AAUDIO_POLICY_AUTO, AAUDIO_POLICY_ALWAYS,
+ AAUDIO_UNSPECIFIED};
+
+class LibAaudioFuzzer {
+public:
+ ~LibAaudioFuzzer() { deInit(); }
+ bool init();
+ void process(const uint8_t *data, size_t size);
+ void deInit();
+
+private:
+ AAudioStreamBuilder *mAaudioBuilder = nullptr;
+ AAudioStream *mAaudioStream = nullptr;
+};
+
+bool LibAaudioFuzzer::init() {
+ aaudio_result_t result = AAudio_createStreamBuilder(&mAaudioBuilder);
+ if ((result != AAUDIO_OK) || (!mAaudioBuilder)) {
+ return false;
+ }
+ return true;
+}
+
+void LibAaudioFuzzer::process(const uint8_t *data, size_t size) {
+ FuzzedDataProvider fdp(data, size);
+ aaudio_performance_mode_t mode =
+ fdp.PickValueInArray({fdp.PickValueInArray(kPerformanceModes),
+ fdp.ConsumeIntegral<int32_t>()});
+ AAudioStreamBuilder_setPerformanceMode(mAaudioBuilder, mode);
+
+ int32_t deviceId = fdp.PickValueInArray(
+ {AAUDIO_UNSPECIFIED, fdp.ConsumeIntegral<int32_t>()});
+ AAudioStreamBuilder_setDeviceId(mAaudioBuilder, deviceId);
+
+ std::string packageName = fdp.PickValueInArray<std::string>(
+ {"android.nativemedia.aaudio", "android.app.appops.cts",
+ fdp.ConsumeRandomLengthString(kRandomStringLength)});
+ AAudioStreamBuilder_setPackageName(mAaudioBuilder, packageName.c_str());
+
+ std::string attributionTag =
+ fdp.ConsumeRandomLengthString(kRandomStringLength);
+ AAudioStreamBuilder_setAttributionTag(mAaudioBuilder, attributionTag.c_str());
+
+ int32_t sampleRate = fdp.PickValueInArray(kSampleRates);
+ AAudioStreamBuilder_setSampleRate(mAaudioBuilder, sampleRate);
+
+ int32_t channelCount = fdp.PickValueInArray(
+ {AAUDIO_UNSPECIFIED, fdp.ConsumeIntegral<int32_t>()});
+ AAudioStreamBuilder_setChannelCount(mAaudioBuilder, channelCount);
+
+ aaudio_direction_t direction = fdp.PickValueInArray(
+ {fdp.PickValueInArray(kDirections), fdp.ConsumeIntegral<int32_t>()});
+ AAudioStreamBuilder_setDirection(mAaudioBuilder, direction);
+
+ aaudio_format_t format = fdp.PickValueInArray(
+ {fdp.PickValueInArray(kFormats), fdp.ConsumeIntegral<int32_t>()});
+ AAudioStreamBuilder_setFormat(mAaudioBuilder, format);
+
+ aaudio_sharing_mode_t sharingMode = fdp.PickValueInArray(
+ {fdp.PickValueInArray(kSharingModes), fdp.ConsumeIntegral<int32_t>()});
+ AAudioStreamBuilder_setSharingMode(mAaudioBuilder, sharingMode);
+
+ aaudio_usage_t usage = fdp.PickValueInArray(
+ {fdp.PickValueInArray(kUsages), fdp.ConsumeIntegral<int32_t>()});
+ AAudioStreamBuilder_setUsage(mAaudioBuilder, usage);
+
+ aaudio_content_type_t contentType = fdp.PickValueInArray(
+ {fdp.PickValueInArray(kContentTypes), fdp.ConsumeIntegral<int32_t>()});
+ AAudioStreamBuilder_setContentType(mAaudioBuilder, contentType);
+
+ aaudio_input_preset_t inputPreset = fdp.PickValueInArray(
+ {fdp.PickValueInArray(kInputPresets), fdp.ConsumeIntegral<int32_t>()});
+ AAudioStreamBuilder_setInputPreset(mAaudioBuilder, inputPreset);
+
+ bool privacySensitive = fdp.ConsumeBool();
+ AAudioStreamBuilder_setPrivacySensitive(mAaudioBuilder, privacySensitive);
+
+ int32_t frames = fdp.PickValueInArray(
+ {AAUDIO_UNSPECIFIED, fdp.ConsumeIntegral<int32_t>()});
+ AAudioStreamBuilder_setBufferCapacityInFrames(mAaudioBuilder, frames);
+
+ aaudio_allowed_capture_policy_t allowedCapturePolicy =
+ fdp.PickValueInArray({fdp.PickValueInArray(kAllowedCapturePolicies),
+ fdp.ConsumeIntegral<int32_t>()});
+ AAudioStreamBuilder_setAllowedCapturePolicy(mAaudioBuilder,
+ allowedCapturePolicy);
+
+ aaudio_session_id_t sessionId = fdp.PickValueInArray(
+ {fdp.PickValueInArray(kSessionIds), fdp.ConsumeIntegral<int32_t>()});
+ AAudioStreamBuilder_setSessionId(mAaudioBuilder, sessionId);
+
+ AAudioStreamBuilder_setDataCallback(mAaudioBuilder, nullptr, nullptr);
+ AAudioStreamBuilder_setErrorCallback(mAaudioBuilder, nullptr, nullptr);
+
+ int32_t framesPerDataCallback = fdp.PickValueInArray(
+ {AAUDIO_UNSPECIFIED, fdp.ConsumeIntegral<int32_t>()});
+ AAudioStreamBuilder_setFramesPerDataCallback(mAaudioBuilder,
+ framesPerDataCallback);
+
+ aaudio_policy_t policy = fdp.PickValueInArray(
+ {fdp.PickValueInArray(kPolicies), fdp.ConsumeIntegral<int32_t>()});
+ AAudio_setMMapPolicy(policy);
+ (void)AAudio_getMMapPolicy();
+
+ aaudio_result_t result =
+ AAudioStreamBuilder_openStream(mAaudioBuilder, &mAaudioStream);
+ if ((result != AAUDIO_OK) || (!mAaudioStream)) {
+ return;
+ }
+
+ int32_t framesPerBurst = AAudioStream_getFramesPerBurst(mAaudioStream);
+ uint8_t numberOfBursts = fdp.ConsumeIntegral<uint8_t>();
+ int32_t maxInputFrames = numberOfBursts * framesPerBurst;
+ int32_t requestedBufferSize =
+ fdp.ConsumeIntegral<uint16_t>() * framesPerBurst;
+ AAudioStream_setBufferSizeInFrames(mAaudioStream, requestedBufferSize);
+
+ int64_t position = 0, nanoseconds = 0;
+ AAudioStream_getTimestamp(mAaudioStream, CLOCK_MONOTONIC, &position,
+ &nanoseconds);
+
+ AAudioStream_requestStart(mAaudioStream);
+
+ aaudio_format_t actualFormat = AAudioStream_getFormat(mAaudioStream);
+ int32_t actualChannelCount = AAudioStream_getChannelCount(mAaudioStream);
+
+ int32_t count = fdp.ConsumeIntegral<int32_t>();
+ direction = AAudioStream_getDirection(mAaudioStream);
+ framesPerDataCallback = AAudioStream_getFramesPerDataCallback(mAaudioStream);
+
+ if (actualFormat == AAUDIO_FORMAT_PCM_I16) {
+ std::vector<int16_t> inputShortData(maxInputFrames * actualChannelCount,
+ 0x0);
+ if (direction == AAUDIO_DIRECTION_INPUT) {
+ AAudioStream_read(mAaudioStream, inputShortData.data(),
+ framesPerDataCallback, count * kNanosPerMillisecond);
+ } else if (direction == AAUDIO_DIRECTION_OUTPUT) {
+ AAudioStream_write(mAaudioStream, inputShortData.data(),
+ framesPerDataCallback, count * kNanosPerMillisecond);
+ }
+ } else if (actualFormat == AAUDIO_FORMAT_PCM_FLOAT) {
+ std::vector<float> inputFloatData(maxInputFrames * actualChannelCount, 0x0);
+ if (direction == AAUDIO_DIRECTION_INPUT) {
+ AAudioStream_read(mAaudioStream, inputFloatData.data(),
+ framesPerDataCallback, count * kNanosPerMillisecond);
+ } else if (direction == AAUDIO_DIRECTION_OUTPUT) {
+ AAudioStream_write(mAaudioStream, inputFloatData.data(),
+ framesPerDataCallback, count * kNanosPerMillisecond);
+ }
+ }
+
+ aaudio_stream_state_t state = AAUDIO_STREAM_STATE_UNKNOWN;
+ AAudioStream_waitForStateChange(mAaudioStream, AAUDIO_STREAM_STATE_UNKNOWN,
+ &state, count * kNanosPerMillisecond);
+ (void)AAudio_convertStreamStateToText(state);
+
+ (void)AAudioStream_getUsage(mAaudioStream);
+ (void)AAudioStream_getSampleRate(mAaudioStream);
+ (void)AAudioStream_getState(mAaudioStream);
+ (void)AAudioStream_getSamplesPerFrame(mAaudioStream);
+ (void)AAudioStream_getContentType(mAaudioStream);
+ (void)AAudioStream_getInputPreset(mAaudioStream);
+ (void)AAudioStream_isPrivacySensitive(mAaudioStream);
+ (void)AAudioStream_getAllowedCapturePolicy(mAaudioStream);
+ (void)AAudioStream_getPerformanceMode(mAaudioStream);
+ (void)AAudioStream_getDeviceId(mAaudioStream);
+ (void)AAudioStream_getSharingMode(mAaudioStream);
+ (void)AAudioStream_getSessionId(mAaudioStream);
+ (void)AAudioStream_getFramesRead(mAaudioStream);
+ (void)AAudioStream_getFramesWritten(mAaudioStream);
+ (void)AAudioStream_getXRunCount(mAaudioStream);
+ (void)AAudioStream_getBufferCapacityInFrames(mAaudioStream);
+ (void)AAudioStream_getBufferSizeInFrames(mAaudioStream);
+ (void)AAudioStream_isMMapUsed(mAaudioStream);
+
+ AAudioStream_requestPause(mAaudioStream);
+ AAudioStream_requestFlush(mAaudioStream);
+ AAudioStream_release(mAaudioStream);
+ AAudioStream_requestStop(mAaudioStream);
+}
+
+void LibAaudioFuzzer::deInit() {
+ if (mAaudioBuilder) {
+ AAudioStreamBuilder_delete(mAaudioBuilder);
+ }
+ if (mAaudioStream) {
+ AAudioStream_close(mAaudioStream);
+ }
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ LibAaudioFuzzer libAaudioFuzzer;
+ if (libAaudioFuzzer.init()) {
+ libAaudioFuzzer.process(data, size);
+ }
+ return 0;
+}
diff --git a/media/libaaudio/include/aaudio/AAudio.h b/media/libaaudio/include/aaudio/AAudio.h
index b710e29..efa9941 100644
--- a/media/libaaudio/include/aaudio/AAudio.h
+++ b/media/libaaudio/include/aaudio/AAudio.h
@@ -20,7 +20,7 @@
*/
/**
- * @file AAudio.h
+ * @file aaudio/AAudio.h
*/
/**
diff --git a/media/libaudioclient/AidlConversion.cpp b/media/libaudioclient/AidlConversion.cpp
index 5f63a69..fad861a 100644
--- a/media/libaudioclient/AidlConversion.cpp
+++ b/media/libaudioclient/AidlConversion.cpp
@@ -50,8 +50,12 @@
using media::audio::common::AudioGain;
using media::audio::common::AudioGainConfig;
using media::audio::common::AudioGainMode;
+using media::audio::common::AudioInputFlags;
+using media::audio::common::AudioIoFlags;
using media::audio::common::AudioMode;
using media::audio::common::AudioOffloadInfo;
+using media::audio::common::AudioOutputFlags;
+using media::audio::common::AudioPortDeviceExt;
using media::audio::common::AudioPortExt;
using media::audio::common::AudioPortMixExt;
using media::audio::common::AudioPortMixExtUseCase;
@@ -1281,129 +1285,129 @@
}
ConversionResult<audio_input_flags_t> aidl2legacy_AudioInputFlags_audio_input_flags_t(
- media::AudioInputFlags aidl) {
+ AudioInputFlags aidl) {
switch (aidl) {
- case media::AudioInputFlags::FAST:
+ case AudioInputFlags::FAST:
return AUDIO_INPUT_FLAG_FAST;
- case media::AudioInputFlags::HW_HOTWORD:
+ case AudioInputFlags::HW_HOTWORD:
return AUDIO_INPUT_FLAG_HW_HOTWORD;
- case media::AudioInputFlags::RAW:
+ case AudioInputFlags::RAW:
return AUDIO_INPUT_FLAG_RAW;
- case media::AudioInputFlags::SYNC:
+ case AudioInputFlags::SYNC:
return AUDIO_INPUT_FLAG_SYNC;
- case media::AudioInputFlags::MMAP_NOIRQ:
+ case AudioInputFlags::MMAP_NOIRQ:
return AUDIO_INPUT_FLAG_MMAP_NOIRQ;
- case media::AudioInputFlags::VOIP_TX:
+ case AudioInputFlags::VOIP_TX:
return AUDIO_INPUT_FLAG_VOIP_TX;
- case media::AudioInputFlags::HW_AV_SYNC:
+ case AudioInputFlags::HW_AV_SYNC:
return AUDIO_INPUT_FLAG_HW_AV_SYNC;
- case media::AudioInputFlags::DIRECT:
+ case AudioInputFlags::DIRECT:
return AUDIO_INPUT_FLAG_DIRECT;
}
return unexpected(BAD_VALUE);
}
-ConversionResult<media::AudioInputFlags> legacy2aidl_audio_input_flags_t_AudioInputFlags(
+ConversionResult<AudioInputFlags> legacy2aidl_audio_input_flags_t_AudioInputFlags(
audio_input_flags_t legacy) {
switch (legacy) {
case AUDIO_INPUT_FLAG_NONE:
break; // shouldn't get here. must be listed -Werror,-Wswitch
case AUDIO_INPUT_FLAG_FAST:
- return media::AudioInputFlags::FAST;
+ return AudioInputFlags::FAST;
case AUDIO_INPUT_FLAG_HW_HOTWORD:
- return media::AudioInputFlags::HW_HOTWORD;
+ return AudioInputFlags::HW_HOTWORD;
case AUDIO_INPUT_FLAG_RAW:
- return media::AudioInputFlags::RAW;
+ return AudioInputFlags::RAW;
case AUDIO_INPUT_FLAG_SYNC:
- return media::AudioInputFlags::SYNC;
+ return AudioInputFlags::SYNC;
case AUDIO_INPUT_FLAG_MMAP_NOIRQ:
- return media::AudioInputFlags::MMAP_NOIRQ;
+ return AudioInputFlags::MMAP_NOIRQ;
case AUDIO_INPUT_FLAG_VOIP_TX:
- return media::AudioInputFlags::VOIP_TX;
+ return AudioInputFlags::VOIP_TX;
case AUDIO_INPUT_FLAG_HW_AV_SYNC:
- return media::AudioInputFlags::HW_AV_SYNC;
+ return AudioInputFlags::HW_AV_SYNC;
case AUDIO_INPUT_FLAG_DIRECT:
- return media::AudioInputFlags::DIRECT;
+ return AudioInputFlags::DIRECT;
}
return unexpected(BAD_VALUE);
}
ConversionResult<audio_output_flags_t> aidl2legacy_AudioOutputFlags_audio_output_flags_t(
- media::AudioOutputFlags aidl) {
+ AudioOutputFlags aidl) {
switch (aidl) {
- case media::AudioOutputFlags::DIRECT:
+ case AudioOutputFlags::DIRECT:
return AUDIO_OUTPUT_FLAG_DIRECT;
- case media::AudioOutputFlags::PRIMARY:
+ case AudioOutputFlags::PRIMARY:
return AUDIO_OUTPUT_FLAG_PRIMARY;
- case media::AudioOutputFlags::FAST:
+ case AudioOutputFlags::FAST:
return AUDIO_OUTPUT_FLAG_FAST;
- case media::AudioOutputFlags::DEEP_BUFFER:
+ case AudioOutputFlags::DEEP_BUFFER:
return AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
- case media::AudioOutputFlags::COMPRESS_OFFLOAD:
+ case AudioOutputFlags::COMPRESS_OFFLOAD:
return AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
- case media::AudioOutputFlags::NON_BLOCKING:
+ case AudioOutputFlags::NON_BLOCKING:
return AUDIO_OUTPUT_FLAG_NON_BLOCKING;
- case media::AudioOutputFlags::HW_AV_SYNC:
+ case AudioOutputFlags::HW_AV_SYNC:
return AUDIO_OUTPUT_FLAG_HW_AV_SYNC;
- case media::AudioOutputFlags::TTS:
+ case AudioOutputFlags::TTS:
return AUDIO_OUTPUT_FLAG_TTS;
- case media::AudioOutputFlags::RAW:
+ case AudioOutputFlags::RAW:
return AUDIO_OUTPUT_FLAG_RAW;
- case media::AudioOutputFlags::SYNC:
+ case AudioOutputFlags::SYNC:
return AUDIO_OUTPUT_FLAG_SYNC;
- case media::AudioOutputFlags::IEC958_NONAUDIO:
+ case AudioOutputFlags::IEC958_NONAUDIO:
return AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO;
- case media::AudioOutputFlags::DIRECT_PCM:
+ case AudioOutputFlags::DIRECT_PCM:
return AUDIO_OUTPUT_FLAG_DIRECT_PCM;
- case media::AudioOutputFlags::MMAP_NOIRQ:
+ case AudioOutputFlags::MMAP_NOIRQ:
return AUDIO_OUTPUT_FLAG_MMAP_NOIRQ;
- case media::AudioOutputFlags::VOIP_RX:
+ case AudioOutputFlags::VOIP_RX:
return AUDIO_OUTPUT_FLAG_VOIP_RX;
- case media::AudioOutputFlags::INCALL_MUSIC:
+ case AudioOutputFlags::INCALL_MUSIC:
return AUDIO_OUTPUT_FLAG_INCALL_MUSIC;
- case media::AudioOutputFlags::GAPLESS_OFFLOAD:
+ case AudioOutputFlags::GAPLESS_OFFLOAD:
return AUDIO_OUTPUT_FLAG_GAPLESS_OFFLOAD;
}
return unexpected(BAD_VALUE);
}
-ConversionResult<media::AudioOutputFlags> legacy2aidl_audio_output_flags_t_AudioOutputFlags(
+ConversionResult<AudioOutputFlags> legacy2aidl_audio_output_flags_t_AudioOutputFlags(
audio_output_flags_t legacy) {
switch (legacy) {
case AUDIO_OUTPUT_FLAG_NONE:
break; // shouldn't get here. must be listed -Werror,-Wswitch
case AUDIO_OUTPUT_FLAG_DIRECT:
- return media::AudioOutputFlags::DIRECT;
+ return AudioOutputFlags::DIRECT;
case AUDIO_OUTPUT_FLAG_PRIMARY:
- return media::AudioOutputFlags::PRIMARY;
+ return AudioOutputFlags::PRIMARY;
case AUDIO_OUTPUT_FLAG_FAST:
- return media::AudioOutputFlags::FAST;
+ return AudioOutputFlags::FAST;
case AUDIO_OUTPUT_FLAG_DEEP_BUFFER:
- return media::AudioOutputFlags::DEEP_BUFFER;
+ return AudioOutputFlags::DEEP_BUFFER;
case AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD:
- return media::AudioOutputFlags::COMPRESS_OFFLOAD;
+ return AudioOutputFlags::COMPRESS_OFFLOAD;
case AUDIO_OUTPUT_FLAG_NON_BLOCKING:
- return media::AudioOutputFlags::NON_BLOCKING;
+ return AudioOutputFlags::NON_BLOCKING;
case AUDIO_OUTPUT_FLAG_HW_AV_SYNC:
- return media::AudioOutputFlags::HW_AV_SYNC;
+ return AudioOutputFlags::HW_AV_SYNC;
case AUDIO_OUTPUT_FLAG_TTS:
- return media::AudioOutputFlags::TTS;
+ return AudioOutputFlags::TTS;
case AUDIO_OUTPUT_FLAG_RAW:
- return media::AudioOutputFlags::RAW;
+ return AudioOutputFlags::RAW;
case AUDIO_OUTPUT_FLAG_SYNC:
- return media::AudioOutputFlags::SYNC;
+ return AudioOutputFlags::SYNC;
case AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO:
- return media::AudioOutputFlags::IEC958_NONAUDIO;
+ return AudioOutputFlags::IEC958_NONAUDIO;
case AUDIO_OUTPUT_FLAG_DIRECT_PCM:
- return media::AudioOutputFlags::DIRECT_PCM;
+ return AudioOutputFlags::DIRECT_PCM;
case AUDIO_OUTPUT_FLAG_MMAP_NOIRQ:
- return media::AudioOutputFlags::MMAP_NOIRQ;
+ return AudioOutputFlags::MMAP_NOIRQ;
case AUDIO_OUTPUT_FLAG_VOIP_RX:
- return media::AudioOutputFlags::VOIP_RX;
+ return AudioOutputFlags::VOIP_RX;
case AUDIO_OUTPUT_FLAG_INCALL_MUSIC:
- return media::AudioOutputFlags::INCALL_MUSIC;
+ return AudioOutputFlags::INCALL_MUSIC;
case AUDIO_OUTPUT_FLAG_GAPLESS_OFFLOAD:
- return media::AudioOutputFlags::GAPLESS_OFFLOAD;
+ return AudioOutputFlags::GAPLESS_OFFLOAD;
}
return unexpected(BAD_VALUE);
}
@@ -1413,9 +1417,9 @@
using LegacyMask = std::underlying_type_t<audio_input_flags_t>;
LegacyMask converted = VALUE_OR_RETURN(
- (convertBitmask<LegacyMask, int32_t, audio_input_flags_t, media::AudioInputFlags>(
+ (convertBitmask<LegacyMask, int32_t, audio_input_flags_t, AudioInputFlags>(
aidl, aidl2legacy_AudioInputFlags_audio_input_flags_t,
- indexToEnum_index<media::AudioInputFlags>,
+ indexToEnum_index<AudioInputFlags>,
enumToMask_bitmask<LegacyMask, audio_input_flags_t>)));
return static_cast<audio_input_flags_t>(converted);
}
@@ -1425,10 +1429,10 @@
using LegacyMask = std::underlying_type_t<audio_input_flags_t>;
LegacyMask legacyMask = static_cast<LegacyMask>(legacy);
- return convertBitmask<int32_t, LegacyMask, media::AudioInputFlags, audio_input_flags_t>(
+ return convertBitmask<int32_t, LegacyMask, AudioInputFlags, audio_input_flags_t>(
legacyMask, legacy2aidl_audio_input_flags_t_AudioInputFlags,
indexToEnum_bitmask<audio_input_flags_t>,
- enumToMask_index<int32_t, media::AudioInputFlags>);
+ enumToMask_index<int32_t, AudioInputFlags>);
}
ConversionResult<audio_output_flags_t> aidl2legacy_int32_t_audio_output_flags_t_mask(
@@ -1436,9 +1440,9 @@
return convertBitmask<audio_output_flags_t,
int32_t,
audio_output_flags_t,
- media::AudioOutputFlags>(
+ AudioOutputFlags>(
aidl, aidl2legacy_AudioOutputFlags_audio_output_flags_t,
- indexToEnum_index<media::AudioOutputFlags>,
+ indexToEnum_index<AudioOutputFlags>,
enumToMask_bitmask<audio_output_flags_t, audio_output_flags_t>);
}
@@ -1447,14 +1451,14 @@
using LegacyMask = std::underlying_type_t<audio_output_flags_t>;
LegacyMask legacyMask = static_cast<LegacyMask>(legacy);
- return convertBitmask<int32_t, LegacyMask, media::AudioOutputFlags, audio_output_flags_t>(
+ return convertBitmask<int32_t, LegacyMask, AudioOutputFlags, audio_output_flags_t>(
legacyMask, legacy2aidl_audio_output_flags_t_AudioOutputFlags,
indexToEnum_bitmask<audio_output_flags_t>,
- enumToMask_index<int32_t, media::AudioOutputFlags>);
+ enumToMask_index<int32_t, AudioOutputFlags>);
}
ConversionResult<audio_io_flags> aidl2legacy_AudioIoFlags_audio_io_flags(
- const media::AudioIoFlags& aidl, media::AudioPortRole role, media::AudioPortType type) {
+ const AudioIoFlags& aidl, media::AudioPortRole role, media::AudioPortType type) {
audio_io_flags legacy;
Direction dir = VALUE_OR_RETURN(direction(role, type));
switch (dir) {
@@ -1476,9 +1480,9 @@
return legacy;
}
-ConversionResult<media::AudioIoFlags> legacy2aidl_audio_io_flags_AudioIoFlags(
+ConversionResult<AudioIoFlags> legacy2aidl_audio_io_flags_AudioIoFlags(
const audio_io_flags& legacy, audio_port_role_t role, audio_port_type_t type) {
- media::AudioIoFlags aidl;
+ AudioIoFlags aidl;
Direction dir = VALUE_OR_RETURN(direction(role, type));
switch (dir) {
@@ -1497,21 +1501,22 @@
}
ConversionResult<audio_port_config_device_ext>
-aidl2legacy_AudioDevice_audio_port_config_device_ext(
- const AudioDevice& aidl, const media::AudioPortDeviceExtSys& aidlDeviceExt) {
+aidl2legacy_AudioPortDeviceExt_audio_port_config_device_ext(
+ const AudioPortDeviceExt& aidl, const media::AudioPortDeviceExtSys& aidlDeviceExt) {
audio_port_config_device_ext legacy;
legacy.hw_module = VALUE_OR_RETURN(
aidl2legacy_int32_t_audio_module_handle_t(aidlDeviceExt.hwModule));
- RETURN_IF_ERROR(aidl2legacy_AudioDevice_audio_device(aidl, &legacy.type, legacy.address));
+ RETURN_IF_ERROR(aidl2legacy_AudioDevice_audio_device(
+ aidl.device, &legacy.type, legacy.address));
return legacy;
}
-status_t legacy2aidl_audio_port_config_device_ext_AudioDevice(
+status_t legacy2aidl_audio_port_config_device_ext_AudioPortDeviceExt(
const audio_port_config_device_ext& legacy,
- AudioDevice* aidl, media::AudioPortDeviceExtSys* aidlDeviceExt) {
+ AudioPortDeviceExt* aidl, media::AudioPortDeviceExtSys* aidlDeviceExt) {
aidlDeviceExt->hwModule = VALUE_OR_RETURN_STATUS(
legacy2aidl_audio_module_handle_t_int32_t(legacy.hw_module));
- *aidl = VALUE_OR_RETURN_STATUS(
+ aidl->device = VALUE_OR_RETURN_STATUS(
legacy2aidl_audio_device_AudioDevice(legacy.type, legacy.address));
return OK;
}
@@ -1777,7 +1782,7 @@
return legacy;
case media::AudioPortType::DEVICE:
legacy.device = VALUE_OR_RETURN(
- aidl2legacy_AudioDevice_audio_port_config_device_ext(
+ aidl2legacy_AudioPortDeviceExt_audio_port_config_device_ext(
VALUE_OR_RETURN(UNION_GET(aidl, device)),
VALUE_OR_RETURN(UNION_GET(aidlSys, device))));
return legacy;
@@ -1806,10 +1811,10 @@
UNION_SET(*aidlSys, unspecified, false);
return OK;
case AUDIO_PORT_TYPE_DEVICE: {
- AudioDevice device;
+ AudioPortDeviceExt device;
media::AudioPortDeviceExtSys deviceSys;
RETURN_STATUS_IF_ERROR(
- legacy2aidl_audio_port_config_device_ext_AudioDevice(
+ legacy2aidl_audio_port_config_device_ext_AudioPortDeviceExt(
legacy.device, &device, &deviceSys));
UNION_SET(*aidl, device, device);
UNION_SET(*aidlSys, device, deviceSys);
@@ -1862,10 +1867,10 @@
aidl.hal.gain.value(), isInput));
legacy.config_mask |= AUDIO_PORT_CONFIG_GAIN;
}
- if (aidl.sys.flags.has_value()) {
+ if (aidl.hal.flags.has_value()) {
legacy.flags = VALUE_OR_RETURN(
aidl2legacy_AudioIoFlags_audio_io_flags(
- aidl.sys.flags.value(), aidl.sys.role, aidl.sys.type));
+ aidl.hal.flags.value(), aidl.sys.role, aidl.sys.type));
legacy.config_mask |= AUDIO_PORT_CONFIG_FLAGS;
}
legacy.ext = VALUE_OR_RETURN(
@@ -1900,7 +1905,7 @@
legacy2aidl_audio_gain_config_AudioGainConfig(legacy.gain, isInput));
}
if (legacy.config_mask & AUDIO_PORT_CONFIG_FLAGS) {
- aidl.sys.flags = VALUE_OR_RETURN(
+ aidl.hal.flags = VALUE_OR_RETURN(
legacy2aidl_audio_io_flags_AudioIoFlags(legacy.flags, legacy.role, legacy.type));
}
RETURN_IF_ERROR(legacy2aidl_AudioPortExt(legacy.ext, legacy.type, legacy.role,
@@ -2581,12 +2586,13 @@
}
ConversionResult<audio_port_device_ext>
-aidl2legacy_AudioDevice_audio_port_device_ext(
- const AudioDevice& aidl, const media::AudioPortDeviceExtSys& aidlSys) {
+aidl2legacy_AudioPortDeviceExt_audio_port_device_ext(
+ const AudioPortDeviceExt& aidl, const media::AudioPortDeviceExtSys& aidlSys) {
audio_port_device_ext legacy;
legacy.hw_module = VALUE_OR_RETURN(
aidl2legacy_int32_t_audio_module_handle_t(aidlSys.hwModule));
- RETURN_IF_ERROR(aidl2legacy_AudioDevice_audio_device(aidl, &legacy.type, legacy.address));
+ RETURN_IF_ERROR(aidl2legacy_AudioDevice_audio_device(
+ aidl.device, &legacy.type, legacy.address));
legacy.encapsulation_modes = VALUE_OR_RETURN(
aidl2legacy_AudioEncapsulationMode_mask(aidlSys.encapsulationModes));
legacy.encapsulation_metadata_types = VALUE_OR_RETURN(
@@ -2595,12 +2601,12 @@
return legacy;
}
-status_t legacy2aidl_audio_port_device_ext_AudioDevice(
+status_t legacy2aidl_audio_port_device_ext_AudioPortDeviceExt(
const audio_port_device_ext& legacy,
- AudioDevice* aidl, media::AudioPortDeviceExtSys* aidlDeviceExt) {
+ AudioPortDeviceExt* aidl, media::AudioPortDeviceExtSys* aidlDeviceExt) {
aidlDeviceExt->hwModule = VALUE_OR_RETURN_STATUS(
legacy2aidl_audio_module_handle_t_int32_t(legacy.hw_module));
- *aidl = VALUE_OR_RETURN_STATUS(
+ aidl->device = VALUE_OR_RETURN_STATUS(
legacy2aidl_audio_device_AudioDevice(legacy.type, legacy.address));
aidlDeviceExt->encapsulationModes = VALUE_OR_RETURN_STATUS(
legacy2aidl_AudioEncapsulationMode_mask(legacy.encapsulation_modes));
@@ -2653,7 +2659,7 @@
return legacy;
case media::AudioPortType::DEVICE:
legacy.device = VALUE_OR_RETURN(
- aidl2legacy_AudioDevice_audio_port_device_ext(
+ aidl2legacy_AudioPortDeviceExt_audio_port_device_ext(
VALUE_OR_RETURN(UNION_GET(aidl, device)),
VALUE_OR_RETURN(UNION_GET(aidlSys, device))));
return legacy;
@@ -2682,10 +2688,10 @@
UNION_SET(*aidlSys, unspecified, false);
return OK;
case AUDIO_PORT_TYPE_DEVICE: {
- AudioDevice device;
+ AudioPortDeviceExt device;
media::AudioPortDeviceExtSys deviceSys;
RETURN_STATUS_IF_ERROR(
- legacy2aidl_audio_port_device_ext_AudioDevice(
+ legacy2aidl_audio_port_device_ext_AudioPortDeviceExt(
legacy.device, &device, &deviceSys));
UNION_SET(*aidl, device, device);
UNION_SET(*aidlSys, device, deviceSys);
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index f6446bb..d63a002 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -138,6 +138,7 @@
"libshmemcompat",
"libutils",
"framework-permission-aidl-cpp",
+ "packagemanager_aidl-cpp",
],
export_shared_lib_headers: [
"audioflinger-aidl-cpp",
@@ -315,11 +316,8 @@
"aidl/android/media/AudioDualMonoMode.aidl",
"aidl/android/media/AudioFlag.aidl",
"aidl/android/media/AudioGainSys.aidl",
- "aidl/android/media/AudioInputFlags.aidl",
"aidl/android/media/AudioIoConfigEvent.aidl",
"aidl/android/media/AudioIoDescriptor.aidl",
- "aidl/android/media/AudioIoFlags.aidl",
- "aidl/android/media/AudioOutputFlags.aidl",
"aidl/android/media/AudioPatch.aidl",
"aidl/android/media/AudioPlaybackRate.aidl",
"aidl/android/media/AudioPort.aidl",
diff --git a/media/libaudioclient/aidl/android/media/AudioGainSys.aidl b/media/libaudioclient/aidl/android/media/AudioGainSys.aidl
index 9ec8390..426f4ed 100644
--- a/media/libaudioclient/aidl/android/media/AudioGainSys.aidl
+++ b/media/libaudioclient/aidl/android/media/AudioGainSys.aidl
@@ -24,5 +24,4 @@
parcelable AudioGainSys {
int index;
boolean isInput;
- boolean useForVolume;
}
diff --git a/media/libaudioclient/aidl/android/media/AudioInputFlags.aidl b/media/libaudioclient/aidl/android/media/AudioInputFlags.aidl
deleted file mode 100644
index bfc0eb0..0000000
--- a/media/libaudioclient/aidl/android/media/AudioInputFlags.aidl
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2020 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;
-
-/**
- * {@hide}
- */
-@Backing(type="int")
-enum AudioInputFlags {
- FAST = 0,
- HW_HOTWORD = 1,
- RAW = 2,
- SYNC = 3,
- MMAP_NOIRQ = 4,
- VOIP_TX = 5,
- HW_AV_SYNC = 6,
- DIRECT = 7,
-}
diff --git a/media/libaudioclient/aidl/android/media/AudioIoFlags.aidl b/media/libaudioclient/aidl/android/media/AudioIoFlags.aidl
deleted file mode 100644
index f9b25bf..0000000
--- a/media/libaudioclient/aidl/android/media/AudioIoFlags.aidl
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2020 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;
-
-/**
- * {@hide}
- */
-union AudioIoFlags {
- /** Bitmask indexed by AudioInputFlags. */
- int input;
- /** Bitmask indexed by AudioOutputFlags. */
- int output;
-}
diff --git a/media/libaudioclient/aidl/android/media/AudioOutputFlags.aidl b/media/libaudioclient/aidl/android/media/AudioOutputFlags.aidl
deleted file mode 100644
index cebd8f0..0000000
--- a/media/libaudioclient/aidl/android/media/AudioOutputFlags.aidl
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2020 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;
-
-/**
- * {@hide}
- */
-@Backing(type="int")
-enum AudioOutputFlags {
- DIRECT = 0,
- PRIMARY = 1,
- FAST = 2,
- DEEP_BUFFER = 3,
- COMPRESS_OFFLOAD = 4,
- NON_BLOCKING = 5,
- HW_AV_SYNC = 6,
- TTS = 7,
- RAW = 8,
- SYNC = 9,
- IEC958_NONAUDIO = 10,
- DIRECT_PCM = 11,
- MMAP_NOIRQ = 12,
- VOIP_RX = 13,
- INCALL_MUSIC = 14,
- GAPLESS_OFFLOAD = 15,
-}
diff --git a/media/libaudioclient/aidl/android/media/AudioPortConfigSys.aidl b/media/libaudioclient/aidl/android/media/AudioPortConfigSys.aidl
index 6a615cd..8692848 100644
--- a/media/libaudioclient/aidl/android/media/AudioPortConfigSys.aidl
+++ b/media/libaudioclient/aidl/android/media/AudioPortConfigSys.aidl
@@ -16,7 +16,6 @@
package android.media;
-import android.media.AudioIoFlags;
import android.media.AudioPortExtSys;
import android.media.AudioPortRole;
import android.media.AudioPortType;
@@ -29,7 +28,5 @@
AudioPortRole role;
/** Device, mix ... */
AudioPortType type;
- /** Flags: HW_AV_SYNC, DIRECT, ... Can be left unspecified. */
- @nullable AudioIoFlags flags;
AudioPortExtSys ext;
}
diff --git a/media/libaudioclient/aidl/android/media/INativeSpatializerCallback.aidl b/media/libaudioclient/aidl/android/media/INativeSpatializerCallback.aidl
index 0e9634c..88b8108 100644
--- a/media/libaudioclient/aidl/android/media/INativeSpatializerCallback.aidl
+++ b/media/libaudioclient/aidl/android/media/INativeSpatializerCallback.aidl
@@ -31,4 +31,9 @@
* (e.g. when the spatializer is enabled or disabled)
*/
void onLevelChanged(SpatializationLevel level);
+
+ /** Called when the output stream the Spatializer is attached to changes.
+ * Indicates the IO Handle of the new output.
+ */
+ void onOutputChanged(int output);
}
diff --git a/media/libaudioclient/include/media/AidlConversion.h b/media/libaudioclient/include/media/AidlConversion.h
index 52ea91b..fda9efb 100644
--- a/media/libaudioclient/include/media/AidlConversion.h
+++ b/media/libaudioclient/include/media/AidlConversion.h
@@ -25,10 +25,8 @@
#include <android/media/AudioClient.h>
#include <android/media/AudioDualMonoMode.h>
#include <android/media/AudioFlag.h>
-#include <android/media/AudioInputFlags.h>
#include <android/media/AudioIoConfigEvent.h>
#include <android/media/AudioIoDescriptor.h>
-#include <android/media/AudioOutputFlags.h>
#include <android/media/AudioPlaybackRate.h>
#include <android/media/AudioPort.h>
#include <android/media/AudioPortConfig.h>
@@ -49,8 +47,10 @@
#include <android/media/audio/common/AudioGain.h>
#include <android/media/audio/common/AudioGainConfig.h>
#include <android/media/audio/common/AudioGainMode.h>
+#include <android/media/audio/common/AudioInputFlags.h>
#include <android/media/audio/common/AudioMode.h>
#include <android/media/audio/common/AudioOffloadInfo.h>
+#include <android/media/audio/common/AudioOutputFlags.h>
#include <android/media/audio/common/AudioPortExt.h>
#include <android/media/audio/common/AudioPortMixExt.h>
#include <android/media/audio/common/AudioProfile.h>
@@ -173,15 +173,15 @@
ConversionResult<media::audio::common::AudioGainConfig>
legacy2aidl_audio_gain_config_AudioGainConfig(const audio_gain_config& legacy, bool isInput);
-ConversionResult<audio_input_flags_t> aidl2legacy_AudioInputFlags_audio_input_flags_t(
- media::AudioInputFlags aidl);
-ConversionResult<media::AudioInputFlags> legacy2aidl_audio_input_flags_t_AudioInputFlags(
- audio_input_flags_t legacy);
+ConversionResult<audio_input_flags_t>
+aidl2legacy_AudioInputFlags_audio_input_flags_t(media::audio::common::AudioInputFlags aidl);
+ConversionResult<media::audio::common::AudioInputFlags>
+legacy2aidl_audio_input_flags_t_AudioInputFlags(audio_input_flags_t legacy);
-ConversionResult<audio_output_flags_t> aidl2legacy_AudioOutputFlags_audio_output_flags_t(
- media::AudioOutputFlags aidl);
-ConversionResult<media::AudioOutputFlags> legacy2aidl_audio_output_flags_t_AudioOutputFlags(
- audio_output_flags_t legacy);
+ConversionResult<audio_output_flags_t>
+aidl2legacy_AudioOutputFlags_audio_output_flags_t(media::audio::common::AudioOutputFlags aidl);
+ConversionResult<media::audio::common::AudioOutputFlags>
+legacy2aidl_audio_output_flags_t_AudioOutputFlags(audio_output_flags_t legacy);
ConversionResult<audio_input_flags_t> aidl2legacy_int32_t_audio_input_flags_t_mask(
int32_t aidl);
@@ -194,17 +194,19 @@
audio_output_flags_t legacy);
ConversionResult<audio_io_flags> aidl2legacy_AudioIoFlags_audio_io_flags(
- const media::AudioIoFlags& aidl, media::AudioPortRole role, media::AudioPortType type);
-ConversionResult<media::AudioIoFlags> legacy2aidl_audio_io_flags_AudioIoFlags(
+ const media::audio::common::AudioIoFlags& aidl,
+ media::AudioPortRole role, media::AudioPortType type);
+ConversionResult<media::audio::common::AudioIoFlags> legacy2aidl_audio_io_flags_AudioIoFlags(
const audio_io_flags& legacy, audio_port_role_t role, audio_port_type_t type);
ConversionResult<audio_port_config_device_ext>
-aidl2legacy_AudioDevice_audio_port_config_device_ext(
- const media::audio::common::AudioDevice& aidl,
+aidl2legacy_AudioPortDeviceExt_audio_port_config_device_ext(
+ const media::audio::common::AudioPortDeviceExt& aidl,
const media::AudioPortDeviceExtSys& aidlDeviceExt);
-status_t legacy2aidl_audio_port_config_device_ext_AudioDevice(
+status_t legacy2aidl_audio_port_config_device_ext_AudioPortDeviceExt(
const audio_port_config_device_ext& legacy,
- media::audio::common::AudioDevice* aidl, media::AudioPortDeviceExtSys* aidlDeviceExt);
+ media::audio::common::AudioPortDeviceExt* aidl,
+ media::AudioPortDeviceExtSys* aidlDeviceExt);
ConversionResult<audio_stream_type_t> aidl2legacy_AudioStreamType_audio_stream_type_t(
media::audio::common::AudioStreamType aidl);
@@ -344,12 +346,12 @@
legacy2aidl_AudioEncapsulationMetadataType_mask(uint32_t legacy);
ConversionResult<audio_port_device_ext>
-aidl2legacy_AudioDevice_audio_port_device_ext(
- const media::audio::common::AudioDevice& aidl,
+aidl2legacy_AudioPortDeviceExt_audio_port_device_ext(
+ const media::audio::common::AudioPortDeviceExt& aidl,
const media::AudioPortDeviceExtSys& aidlDeviceExt);
-status_t legacy2aidl_audio_port_device_ext_AudioDevice(
+status_t legacy2aidl_audio_port_device_ext_AudioPortDeviceExt(
const audio_port_device_ext& legacy,
- media::audio::common::AudioDevice* aidl,
+ media::audio::common::AudioPortDeviceExt* aidl,
media::AudioPortDeviceExtSys* aidlDeviceExt);
ConversionResult<audio_port_mix_ext>
diff --git a/media/libaudiofoundation/AudioGain.cpp b/media/libaudiofoundation/AudioGain.cpp
index 1a8fbf0..47e0edb 100644
--- a/media/libaudiofoundation/AudioGain.cpp
+++ b/media/libaudiofoundation/AudioGain.cpp
@@ -122,20 +122,20 @@
ConversionResult<AudioGain::Aidl> AudioGain::toParcelable() const {
media::audio::common::AudioGain aidl = VALUE_OR_RETURN(
legacy2aidl_audio_gain_AudioGain(mGain, mIsInput));
+ aidl.useForVolume = mUseForVolume;
media::AudioGainSys aidlSys;
aidlSys.index = VALUE_OR_RETURN(convertIntegral<int32_t>(mIndex));
aidlSys.isInput = mIsInput;
- aidlSys.useForVolume = mUseForVolume;
return std::make_pair(aidl, aidlSys);
}
ConversionResult<sp<AudioGain>> AudioGain::fromParcelable(const AudioGain::Aidl& aidl) {
+ const media::audio::common::AudioGain& hal = aidl.first;
const media::AudioGainSys& sys = aidl.second;
auto index = VALUE_OR_RETURN(convertIntegral<int>(sys.index));
sp<AudioGain> legacy = sp<AudioGain>::make(index, sys.isInput);
- legacy->mGain = VALUE_OR_RETURN(
- aidl2legacy_AudioGain_audio_gain(aidl.first, sys.isInput));
- legacy->mUseForVolume = sys.useForVolume;
+ legacy->mGain = VALUE_OR_RETURN(aidl2legacy_AudioGain_audio_gain(hal, sys.isInput));
+ legacy->mUseForVolume = hal.useForVolume;
return legacy;
}
diff --git a/media/libaudiofoundation/AudioPort.cpp b/media/libaudiofoundation/AudioPort.cpp
index 099aff4..a00e00d 100644
--- a/media/libaudiofoundation/AudioPort.cpp
+++ b/media/libaudiofoundation/AudioPort.cpp
@@ -219,6 +219,14 @@
auto aidlGains = VALUE_OR_RETURN_STATUS(legacy2aidl_AudioGains(mGains));
parcelable->hal.gains = aidlGains.first;
parcelable->sys.gains = aidlGains.second;
+ if (mType == AUDIO_PORT_TYPE_MIX) {
+ media::audio::common::AudioPortMixExt mixExt{};
+ mixExt.maxOpenStreamCount = maxOpenCount;
+ mixExt.maxActiveStreamCount = maxActiveCount;
+ mixExt.recommendedMuteDurationMs = recommendedMuteDurationMs;
+ parcelable->hal.ext = media::audio::common::AudioPortExt::make<
+ media::audio::common::AudioPortExt::mix>(mixExt);
+ }
return OK;
}
@@ -241,6 +249,13 @@
mExtraAudioDescriptors = parcelable.hal.extraAudioDescriptors;
mGains = VALUE_OR_RETURN_STATUS(
aidl2legacy_AudioGains(std::make_pair(parcelable.hal.gains, parcelable.sys.gains)));
+ if (mType == AUDIO_PORT_TYPE_MIX) {
+ const media::audio::common::AudioPortMixExt& mixExt =
+ parcelable.hal.ext.get<media::audio::common::AudioPortExt::mix>();
+ maxOpenCount = mixExt.maxOpenStreamCount;
+ maxActiveCount = mixExt.maxActiveStreamCount;
+ recommendedMuteDurationMs = mixExt.recommendedMuteDurationMs;
+ }
return OK;
}
diff --git a/media/libaudiofoundation/DeviceDescriptorBase.cpp b/media/libaudiofoundation/DeviceDescriptorBase.cpp
index cf829b5..b383db4 100644
--- a/media/libaudiofoundation/DeviceDescriptorBase.cpp
+++ b/media/libaudiofoundation/DeviceDescriptorBase.cpp
@@ -30,16 +30,20 @@
{
}
-DeviceDescriptorBase::DeviceDescriptorBase(audio_devices_t type, const std::string& address) :
- DeviceDescriptorBase(AudioDeviceTypeAddr(type, address))
+DeviceDescriptorBase::DeviceDescriptorBase(
+ audio_devices_t type, const std::string& address,
+ const FormatVector &encodedFormats) :
+ DeviceDescriptorBase(AudioDeviceTypeAddr(type, address), encodedFormats)
{
}
-DeviceDescriptorBase::DeviceDescriptorBase(const AudioDeviceTypeAddr &deviceTypeAddr) :
+DeviceDescriptorBase::DeviceDescriptorBase(
+ const AudioDeviceTypeAddr &deviceTypeAddr, const FormatVector &encodedFormats) :
AudioPort("", AUDIO_PORT_TYPE_DEVICE,
audio_is_output_device(deviceTypeAddr.mType) ? AUDIO_PORT_ROLE_SINK :
AUDIO_PORT_ROLE_SOURCE),
- mDeviceTypeAddr(deviceTypeAddr)
+ mDeviceTypeAddr(deviceTypeAddr),
+ mEncodedFormats(encodedFormats)
{
if (mDeviceTypeAddr.address().empty() && audio_is_remote_submix_device(mDeviceTypeAddr.mType)) {
mDeviceTypeAddr.setAddress("0");
@@ -148,12 +152,35 @@
AudioPort::log(" ");
}
+template<typename T>
+bool checkEqual(const T& f1, const T& f2)
+{
+ std::set<typename T::value_type> s1(f1.begin(), f1.end());
+ std::set<typename T::value_type> s2(f2.begin(), f2.end());
+ return s1 == s2;
+}
+
bool DeviceDescriptorBase::equals(const sp<DeviceDescriptorBase> &other) const
{
return other != nullptr &&
static_cast<const AudioPort*>(this)->equals(other) &&
static_cast<const AudioPortConfig*>(this)->equals(other) &&
- mDeviceTypeAddr.equals(other->mDeviceTypeAddr);
+ mDeviceTypeAddr.equals(other->mDeviceTypeAddr) &&
+ checkEqual(mEncodedFormats, other->mEncodedFormats);
+}
+
+bool DeviceDescriptorBase::supportsFormat(audio_format_t format)
+{
+ if (mEncodedFormats.empty()) {
+ return true;
+ }
+
+ for (const auto& devFormat : mEncodedFormats) {
+ if (devFormat == format) {
+ return true;
+ }
+ }
+ return false;
}
@@ -169,9 +196,13 @@
AudioPortConfig::writeToParcelable(&parcelable->hal.activeConfig, useInputChannelMask());
parcelable->hal.id = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_port_handle_t_int32_t(mId));
- media::audio::common::AudioDevice device = VALUE_OR_RETURN_STATUS(
+ media::audio::common::AudioPortDeviceExt deviceExt;
+ deviceExt.device = VALUE_OR_RETURN_STATUS(
legacy2aidl_AudioDeviceTypeAddress(mDeviceTypeAddr));
- UNION_SET(parcelable->hal.ext, device, device);
+ deviceExt.encodedFormats = VALUE_OR_RETURN_STATUS(
+ convertContainer<std::vector<media::audio::common::AudioFormatDescription>>(
+ mEncodedFormats, legacy2aidl_audio_format_t_AudioFormatDescription));
+ UNION_SET(parcelable->hal.ext, device, deviceExt);
media::AudioPortDeviceExtSys deviceSys;
deviceSys.encapsulationModes = VALUE_OR_RETURN_STATUS(
legacy2aidl_AudioEncapsulationMode_mask(mEncapsulationModes));
@@ -198,10 +229,13 @@
return status;
}
- media::audio::common::AudioDevice device = VALUE_OR_RETURN_STATUS(
+ media::audio::common::AudioPortDeviceExt deviceExt = VALUE_OR_RETURN_STATUS(
UNION_GET(parcelable.hal.ext, device));
mDeviceTypeAddr = VALUE_OR_RETURN_STATUS(
- aidl2legacy_AudioDeviceTypeAddress(device));
+ aidl2legacy_AudioDeviceTypeAddress(deviceExt.device));
+ mEncodedFormats = VALUE_OR_RETURN_STATUS(
+ convertContainer<FormatVector>(deviceExt.encodedFormats,
+ aidl2legacy_AudioFormatDescription_audio_format_t));
media::AudioPortDeviceExtSys deviceSys = VALUE_OR_RETURN_STATUS(
UNION_GET(parcelable.sys.ext, device));
mEncapsulationModes = VALUE_OR_RETURN_STATUS(
diff --git a/media/libaudiofoundation/include/media/AudioPort.h b/media/libaudiofoundation/include/media/AudioPort.h
index aa9b5f6..b5a17c9 100644
--- a/media/libaudiofoundation/include/media/AudioPort.h
+++ b/media/libaudiofoundation/include/media/AudioPort.h
@@ -106,6 +106,21 @@
status_t readFromParcelable(const media::AudioPort& parcelable);
AudioGains mGains; // gain controllers
+ // Maximum number of input or output streams that can be simultaneously
+ // opened for this profile. By convention 0 means no limit. To respect
+ // legacy behavior, initialized to 1 for output profiles and 0 for input
+ // profiles
+ // FIXME: IOProfile code used the same value for both cases.
+ uint32_t maxOpenCount = 1;
+ // Maximum number of input or output streams that can be simultaneously
+ // active for this profile. By convention 0 means no limit. To respect
+ // legacy behavior, initialized to 0 for output profiles and 1 for input
+ // profiles
+ // FIXME: IOProfile code used the same value for both cases.
+ uint32_t maxActiveCount = 1;
+ // Mute duration while changing device on this output profile.
+ uint32_t recommendedMuteDurationMs = 0;
+
protected:
std::string mName;
audio_port_type_t mType;
diff --git a/media/libaudiofoundation/include/media/DeviceDescriptorBase.h b/media/libaudiofoundation/include/media/DeviceDescriptorBase.h
index 140ce36..a4092eb 100644
--- a/media/libaudiofoundation/include/media/DeviceDescriptorBase.h
+++ b/media/libaudiofoundation/include/media/DeviceDescriptorBase.h
@@ -36,16 +36,21 @@
public:
// Note that empty name refers by convention to a generic device.
explicit DeviceDescriptorBase(audio_devices_t type);
- DeviceDescriptorBase(audio_devices_t type, const std::string& address);
- explicit DeviceDescriptorBase(const AudioDeviceTypeAddr& deviceTypeAddr);
+ DeviceDescriptorBase(audio_devices_t type, const std::string& address,
+ const FormatVector &encodedFormats = FormatVector{});
+ DeviceDescriptorBase(const AudioDeviceTypeAddr& deviceTypeAddr,
+ const FormatVector &encodedFormats = FormatVector{});
- virtual ~DeviceDescriptorBase() {}
+ virtual ~DeviceDescriptorBase() = default;
audio_devices_t type() const { return mDeviceTypeAddr.mType; }
const std::string& address() const { return mDeviceTypeAddr.address(); }
void setAddress(const std::string &address);
const AudioDeviceTypeAddr& getDeviceTypeAddr() const { return mDeviceTypeAddr; }
+ const FormatVector& encodedFormats() const { return mEncodedFormats; }
+ bool supportsFormat(audio_format_t format);
+
// AudioPortConfig
virtual sp<AudioPort> getAudioPort() const {
return static_cast<AudioPort*>(const_cast<DeviceDescriptorBase*>(this));
@@ -82,6 +87,7 @@
protected:
AudioDeviceTypeAddr mDeviceTypeAddr;
+ FormatVector mEncodedFormats;
uint32_t mEncapsulationModes = 0;
uint32_t mEncapsulationMetadataTypes = 0;
private:
diff --git a/media/libaudioprocessing/AudioMixer.cpp b/media/libaudioprocessing/AudioMixer.cpp
index e68c002..e6fdb1d 100644
--- a/media/libaudioprocessing/AudioMixer.cpp
+++ b/media/libaudioprocessing/AudioMixer.cpp
@@ -108,15 +108,11 @@
if (track->mHapticChannelCount > 0) {
track->mAdjustInChannelCount = track->channelCount + track->mHapticChannelCount;
- track->mAdjustOutChannelCount = track->channelCount + track->mMixerHapticChannelCount;
- track->mAdjustNonDestructiveInChannelCount = track->mAdjustOutChannelCount;
- track->mAdjustNonDestructiveOutChannelCount = track->channelCount;
+ track->mAdjustOutChannelCount = track->channelCount;
track->mKeepContractedChannels = track->mHapticPlaybackEnabled;
} else {
track->mAdjustInChannelCount = 0;
track->mAdjustOutChannelCount = 0;
- track->mAdjustNonDestructiveInChannelCount = 0;
- track->mAdjustNonDestructiveOutChannelCount = 0;
track->mKeepContractedChannels = false;
}
@@ -131,8 +127,7 @@
// do it after downmix since track format may change!
track->prepareForReformat();
- track->prepareForAdjustChannelsNonDestructive(mFrameCount);
- track->prepareForAdjustChannels();
+ track->prepareForAdjustChannels(mFrameCount);
// Resampler channels may have changed.
track->recreateResampler(mSampleRate);
@@ -193,6 +188,24 @@
// mDownmixerBufferProvider reset below.
}
+ // See if we should use our built-in non-effect downmixer.
+ if (mMixerInFormat == AUDIO_FORMAT_PCM_FLOAT
+ && mMixerChannelMask == AUDIO_CHANNEL_OUT_STEREO
+ && audio_channel_mask_get_representation(channelMask)
+ == AUDIO_CHANNEL_REPRESENTATION_POSITION) {
+ mDownmixerBufferProvider.reset(new ChannelMixBufferProvider(channelMask,
+ mMixerChannelMask, mMixerInFormat, kCopyBufferFrameCount));
+ if (static_cast<ChannelMixBufferProvider *>(mDownmixerBufferProvider.get())
+ ->isValid()) {
+ mDownmixRequiresFormat = mMixerInFormat;
+ reconfigureBufferProviders();
+ ALOGD("%s: Fallback using ChannelMix", __func__);
+ return NO_ERROR;
+ } else {
+ ALOGD("%s: ChannelMix not supported for channel mask %#x", __func__, channelMask);
+ }
+ }
+
// Effect downmixer does not accept the channel conversion. Let's use our remixer.
mDownmixerBufferProvider.reset(new RemixBufferProvider(channelMask,
mMixerChannelMask, mMixerInFormat, kCopyBufferFrameCount));
@@ -265,48 +278,20 @@
}
}
-status_t AudioMixer::Track::prepareForAdjustChannels()
+status_t AudioMixer::Track::prepareForAdjustChannels(size_t frames)
{
ALOGV("AudioMixer::prepareForAdjustChannels(%p) with inChannelCount: %u, outChannelCount: %u",
this, mAdjustInChannelCount, mAdjustOutChannelCount);
unprepareForAdjustChannels();
if (mAdjustInChannelCount != mAdjustOutChannelCount) {
- mAdjustChannelsBufferProvider.reset(new AdjustChannelsBufferProvider(
- mFormat, mAdjustInChannelCount, mAdjustOutChannelCount, kCopyBufferFrameCount));
- reconfigureBufferProviders();
- }
- return NO_ERROR;
-}
-
-void AudioMixer::Track::unprepareForAdjustChannelsNonDestructive()
-{
- ALOGV("AUDIOMIXER::unprepareForAdjustChannelsNonDestructive");
- if (mContractChannelsNonDestructiveBufferProvider.get() != nullptr) {
- mContractChannelsNonDestructiveBufferProvider.reset(nullptr);
- reconfigureBufferProviders();
- }
-}
-
-status_t AudioMixer::Track::prepareForAdjustChannelsNonDestructive(size_t frames)
-{
- ALOGV("AudioMixer::prepareForAdjustChannelsNonDestructive(%p) with inChannelCount: %u, "
- "outChannelCount: %u, keepContractedChannels: %d",
- this, mAdjustNonDestructiveInChannelCount, mAdjustNonDestructiveOutChannelCount,
- mKeepContractedChannels);
- unprepareForAdjustChannelsNonDestructive();
- if (mAdjustNonDestructiveInChannelCount != mAdjustNonDestructiveOutChannelCount) {
uint8_t* buffer = mKeepContractedChannels
? (uint8_t*)mainBuffer + frames * audio_bytes_per_frame(
mMixerChannelCount, mMixerFormat)
- : NULL;
- mContractChannelsNonDestructiveBufferProvider.reset(
- new AdjustChannelsBufferProvider(
- mFormat,
- mAdjustNonDestructiveInChannelCount,
- mAdjustNonDestructiveOutChannelCount,
- frames,
- mKeepContractedChannels ? mMixerFormat : AUDIO_FORMAT_INVALID,
- buffer));
+ : nullptr;
+ mAdjustChannelsBufferProvider.reset(new AdjustChannelsBufferProvider(
+ mFormat, mAdjustInChannelCount, mAdjustOutChannelCount, frames,
+ mKeepContractedChannels ? mMixerFormat : AUDIO_FORMAT_INVALID,
+ buffer, mMixerHapticChannelCount));
reconfigureBufferProviders();
}
return NO_ERROR;
@@ -314,9 +299,9 @@
void AudioMixer::Track::clearContractedBuffer()
{
- if (mContractChannelsNonDestructiveBufferProvider.get() != nullptr) {
+ if (mAdjustChannelsBufferProvider.get() != nullptr) {
static_cast<AdjustChannelsBufferProvider*>(
- mContractChannelsNonDestructiveBufferProvider.get())->clearContractedFrames();
+ mAdjustChannelsBufferProvider.get())->clearContractedFrames();
}
}
@@ -328,10 +313,6 @@
mAdjustChannelsBufferProvider->setBufferProvider(bufferProvider);
bufferProvider = mAdjustChannelsBufferProvider.get();
}
- if (mContractChannelsNonDestructiveBufferProvider.get() != nullptr) {
- mContractChannelsNonDestructiveBufferProvider->setBufferProvider(bufferProvider);
- bufferProvider = mContractChannelsNonDestructiveBufferProvider.get();
- }
if (mReformatBufferProvider.get() != nullptr) {
mReformatBufferProvider->setBufferProvider(bufferProvider);
bufferProvider = mReformatBufferProvider.get();
@@ -377,7 +358,7 @@
track->mainBuffer = valueBuf;
ALOGV("setParameter(TRACK, MAIN_BUFFER, %p)", valueBuf);
if (track->mKeepContractedChannels) {
- track->prepareForAdjustChannelsNonDestructive(mFrameCount);
+ track->prepareForAdjustChannels(mFrameCount);
}
invalidate();
}
@@ -405,7 +386,7 @@
track->mMixerFormat = format;
ALOGV("setParameter(TRACK, MIXER_FORMAT, %#x)", format);
if (track->mKeepContractedChannels) {
- track->prepareForAdjustChannelsNonDestructive(mFrameCount);
+ track->prepareForAdjustChannels(mFrameCount);
}
}
} break;
@@ -424,8 +405,7 @@
if (track->mHapticPlaybackEnabled != hapticPlaybackEnabled) {
track->mHapticPlaybackEnabled = hapticPlaybackEnabled;
track->mKeepContractedChannels = hapticPlaybackEnabled;
- track->prepareForAdjustChannelsNonDestructive(mFrameCount);
- track->prepareForAdjustChannels();
+ track->prepareForAdjustChannels(mFrameCount);
}
} break;
case HAPTIC_INTENSITY: {
@@ -518,8 +498,6 @@
track->mDownmixerBufferProvider->reset();
} else if (track->mReformatBufferProvider.get() != nullptr) {
track->mReformatBufferProvider->reset();
- } else if (track->mContractChannelsNonDestructiveBufferProvider.get() != nullptr) {
- track->mContractChannelsNonDestructiveBufferProvider->reset();
} else if (track->mAdjustChannelsBufferProvider.get() != nullptr) {
track->mAdjustChannelsBufferProvider->reset();
}
@@ -563,9 +541,7 @@
t->mMixerHapticChannelMask = AUDIO_CHANNEL_NONE;
t->mMixerHapticChannelCount = 0;
t->mAdjustInChannelCount = t->channelCount + t->mHapticChannelCount;
- t->mAdjustOutChannelCount = t->channelCount + t->mMixerHapticChannelCount;
- t->mAdjustNonDestructiveInChannelCount = t->mAdjustOutChannelCount;
- t->mAdjustNonDestructiveOutChannelCount = t->channelCount;
+ t->mAdjustOutChannelCount = t->channelCount;
t->mKeepContractedChannels = false;
// Check the downmixing (or upmixing) requirements.
status_t status = t->prepareForDownmix();
@@ -576,8 +552,7 @@
// prepareForDownmix() may change mDownmixRequiresFormat
ALOGVV("mMixerFormat:%#x mMixerInFormat:%#x\n", t->mMixerFormat, t->mMixerInFormat);
t->prepareForReformat();
- t->prepareForAdjustChannelsNonDestructive(mFrameCount);
- t->prepareForAdjustChannels();
+ t->prepareForAdjustChannels(mFrameCount);
return OK;
}
diff --git a/media/libaudioprocessing/BufferProviders.cpp b/media/libaudioprocessing/BufferProviders.cpp
index 6d31c12..4658db8 100644
--- a/media/libaudioprocessing/BufferProviders.cpp
+++ b/media/libaudioprocessing/BufferProviders.cpp
@@ -364,6 +364,29 @@
src, mInputChannels, mIdxAry, mSampleSize, frames);
}
+ChannelMixBufferProvider::ChannelMixBufferProvider(audio_channel_mask_t inputChannelMask,
+ audio_channel_mask_t outputChannelMask, audio_format_t format,
+ size_t bufferFrameCount) :
+ CopyBufferProvider(
+ audio_bytes_per_sample(format)
+ * audio_channel_count_from_out_mask(inputChannelMask),
+ audio_bytes_per_sample(format)
+ * audio_channel_count_from_out_mask(outputChannelMask),
+ bufferFrameCount)
+{
+ ALOGV("ChannelMixBufferProvider(%p)(%#x, %#x, %#x)",
+ this, format, inputChannelMask, outputChannelMask);
+ if (outputChannelMask == AUDIO_CHANNEL_OUT_STEREO && format == AUDIO_FORMAT_PCM_FLOAT) {
+ mIsValid = mChannelMix.setInputChannelMask(inputChannelMask);
+ }
+}
+
+void ChannelMixBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
+{
+ mChannelMix.process(static_cast<const float *>(src), static_cast<float *>(dst),
+ frames, false /* accumulate */);
+}
+
ReformatBufferProvider::ReformatBufferProvider(int32_t channelCount,
audio_format_t inputFormat, audio_format_t outputFormat,
size_t bufferFrameCount) :
@@ -630,7 +653,8 @@
AdjustChannelsBufferProvider::AdjustChannelsBufferProvider(
audio_format_t format, size_t inChannelCount, size_t outChannelCount,
- size_t frameCount, audio_format_t contractedFormat, void* contractedBuffer) :
+ size_t frameCount, audio_format_t contractedFormat, void* contractedBuffer,
+ size_t contractedOutChannelCount) :
CopyBufferProvider(
audio_bytes_per_frame(inChannelCount, format),
audio_bytes_per_frame(std::max(inChannelCount, outChannelCount), format),
@@ -640,15 +664,22 @@
mOutChannelCount(outChannelCount),
mSampleSizeInBytes(audio_bytes_per_sample(format)),
mFrameCount(frameCount),
- mContractedChannelCount(inChannelCount - outChannelCount),
- mContractedFormat(contractedFormat),
+ mContractedFormat(inChannelCount > outChannelCount
+ ? contractedFormat : AUDIO_FORMAT_INVALID),
+ mContractedInChannelCount(inChannelCount > outChannelCount
+ ? inChannelCount - outChannelCount : 0),
+ mContractedOutChannelCount(contractedOutChannelCount),
+ mContractedSampleSizeInBytes(audio_bytes_per_sample(contractedFormat)),
+ mContractedInputFrameSize(mContractedInChannelCount * mContractedSampleSizeInBytes),
mContractedBuffer(contractedBuffer),
mContractedWrittenFrames(0)
{
- ALOGV("AdjustChannelsBufferProvider(%p)(%#x, %zu, %zu, %zu, %#x, %p)", this, format,
- inChannelCount, outChannelCount, frameCount, contractedFormat, contractedBuffer);
+ ALOGV("AdjustChannelsBufferProvider(%p)(%#x, %zu, %zu, %zu, %#x, %p, %zu)",
+ this, format, inChannelCount, outChannelCount, frameCount, contractedFormat,
+ contractedBuffer, contractedOutChannelCount);
if (mContractedFormat != AUDIO_FORMAT_INVALID && mInChannelCount > mOutChannelCount) {
- mContractedFrameSize = audio_bytes_per_frame(mContractedChannelCount, mContractedFormat);
+ mContractedOutputFrameSize =
+ audio_bytes_per_frame(mContractedOutChannelCount, mContractedFormat);
}
}
@@ -667,25 +698,39 @@
void AdjustChannelsBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
{
- if (mInChannelCount > mOutChannelCount) {
- // For case multi to mono, adjust_channels has special logic that will mix first two input
- // channels into a single output channel. In that case, use adjust_channels_non_destructive
- // to keep only one channel data even when contracting to mono.
- adjust_channels_non_destructive(src, mInChannelCount, dst, mOutChannelCount,
- mSampleSizeInBytes, frames * mInChannelCount * mSampleSizeInBytes);
- if (mContractedFormat != AUDIO_FORMAT_INVALID
- && mContractedBuffer != nullptr) {
- const size_t contractedIdx = frames * mOutChannelCount * mSampleSizeInBytes;
+ // For case multi to mono, adjust_channels has special logic that will mix first two input
+ // channels into a single output channel. In that case, use adjust_channels_non_destructive
+ // to keep only one channel data even when contracting to mono.
+ adjust_channels_non_destructive(src, mInChannelCount, dst, mOutChannelCount,
+ mSampleSizeInBytes, frames * mInChannelCount * mSampleSizeInBytes);
+ if (mContractedFormat != AUDIO_FORMAT_INVALID
+ && mContractedBuffer != nullptr) {
+ const size_t contractedIdx = frames * mOutChannelCount * mSampleSizeInBytes;
+ uint8_t* oriBuf = (uint8_t*) dst + contractedIdx;
+ uint8_t* buf = (uint8_t*) mContractedBuffer
+ + mContractedWrittenFrames * mContractedOutputFrameSize;
+ if (mContractedInChannelCount > mContractedOutChannelCount) {
+ // Adjust the channels first as the contracted buffer may not have enough
+ // space for the data.
+ // Use adjust_channels_non_destructive to avoid mix first two channels into one single
+ // output channel when it is multi to mono.
+ adjust_channels_non_destructive(
+ oriBuf, mContractedInChannelCount, oriBuf, mContractedOutChannelCount,
+ mSampleSizeInBytes, frames * mContractedInChannelCount * mSampleSizeInBytes);
memcpy_by_audio_format(
- (uint8_t*) mContractedBuffer + mContractedWrittenFrames * mContractedFrameSize,
- mContractedFormat, (uint8_t*) dst + contractedIdx, mFormat,
- mContractedChannelCount * frames);
- mContractedWrittenFrames += frames;
+ buf, mContractedFormat, oriBuf, mFormat, mContractedOutChannelCount * frames);
+ } else {
+ // Copy the data first as the dst buffer may not have enough space for extra channel.
+ memcpy_by_audio_format(
+ buf, mContractedFormat, oriBuf, mFormat, mContractedInChannelCount * frames);
+ // Note that if the contracted data is from MONO to MULTICHANNEL, the first 2 channels
+ // will be duplicated with the original single input channel and all the other channels
+ // will be 0-filled.
+ adjust_channels(
+ buf, mContractedInChannelCount, buf, mContractedOutChannelCount,
+ mContractedSampleSizeInBytes, mContractedInputFrameSize * frames);
}
- } else {
- // Prefer expanding data from the end of each audio frame.
- adjust_channels(src, mInChannelCount, dst, mOutChannelCount,
- mSampleSizeInBytes, frames * mInChannelCount * mSampleSizeInBytes);
+ mContractedWrittenFrames += frames;
}
}
diff --git a/media/libaudioprocessing/include/media/AudioMixer.h b/media/libaudioprocessing/include/media/AudioMixer.h
index 5a9fa07..2993a60 100644
--- a/media/libaudioprocessing/include/media/AudioMixer.h
+++ b/media/libaudioprocessing/include/media/AudioMixer.h
@@ -80,7 +80,6 @@
mPostDownmixReformatBufferProvider.reset(nullptr);
mDownmixerBufferProvider.reset(nullptr);
mReformatBufferProvider.reset(nullptr);
- mContractChannelsNonDestructiveBufferProvider.reset(nullptr);
mAdjustChannelsBufferProvider.reset(nullptr);
}
@@ -95,10 +94,8 @@
void unprepareForDownmix();
status_t prepareForReformat();
void unprepareForReformat();
- status_t prepareForAdjustChannels();
+ status_t prepareForAdjustChannels(size_t frames);
void unprepareForAdjustChannels();
- status_t prepareForAdjustChannelsNonDestructive(size_t frames);
- void unprepareForAdjustChannelsNonDestructive();
void clearContractedBuffer();
bool setPlaybackRate(const AudioPlaybackRate &playbackRate);
void reconfigureBufferProviders();
@@ -114,24 +111,18 @@
* 2) mAdjustChannelsBufferProvider: Expands or contracts sample data from one interleaved
* channel format to another. Expanded channels are filled with zeros and put at the end
* of each audio frame. Contracted channels are copied to the end of the buffer.
- * 3) mContractChannelsNonDestructiveBufferProvider: Non-destructively contract sample data.
- * This is currently using at audio-haptic coupled playback to separate audio and haptic
- * data. Contracted channels could be written to given buffer.
- * 4) mReformatBufferProvider: If not NULL, performs the audio reformat to
+ * 3) mReformatBufferProvider: If not NULL, performs the audio reformat to
* match either mMixerInFormat or mDownmixRequiresFormat, if the downmixer
* requires reformat. For example, it may convert floating point input to
* PCM_16_bit if that's required by the downmixer.
- * 5) mDownmixerBufferProvider: If not NULL, performs the channel remixing to match
+ * 4) mDownmixerBufferProvider: If not NULL, performs the channel remixing to match
* the number of channels required by the mixer sink.
- * 6) mPostDownmixReformatBufferProvider: If not NULL, performs reformatting from
+ * 5) mPostDownmixReformatBufferProvider: If not NULL, performs reformatting from
* the downmixer requirements to the mixer engine input requirements.
- * 7) mTimestretchBufferProvider: Adds timestretching for playback rate
+ * 6) mTimestretchBufferProvider: Adds timestretching for playback rate
*/
AudioBufferProvider* mInputBufferProvider; // externally provided buffer provider.
- // TODO: combine mAdjustChannelsBufferProvider and
- // mContractChannelsNonDestructiveBufferProvider
std::unique_ptr<PassthruBufferProvider> mAdjustChannelsBufferProvider;
- std::unique_ptr<PassthruBufferProvider> mContractChannelsNonDestructiveBufferProvider;
std::unique_ptr<PassthruBufferProvider> mReformatBufferProvider;
std::unique_ptr<PassthruBufferProvider> mDownmixerBufferProvider;
std::unique_ptr<PassthruBufferProvider> mPostDownmixReformatBufferProvider;
@@ -153,8 +144,6 @@
uint32_t mMixerHapticChannelCount;
uint32_t mAdjustInChannelCount;
uint32_t mAdjustOutChannelCount;
- uint32_t mAdjustNonDestructiveInChannelCount;
- uint32_t mAdjustNonDestructiveOutChannelCount;
bool mKeepContractedChannels;
};
diff --git a/media/libaudioprocessing/include/media/BufferProviders.h b/media/libaudioprocessing/include/media/BufferProviders.h
index b038854..b3ab8a5 100644
--- a/media/libaudioprocessing/include/media/BufferProviders.h
+++ b/media/libaudioprocessing/include/media/BufferProviders.h
@@ -20,6 +20,7 @@
#include <stdint.h>
#include <sys/types.h>
+#include <audio_utils/ChannelMix.h>
#include <media/AudioBufferProvider.h>
#include <media/AudioResamplerPublic.h>
#include <system/audio.h>
@@ -129,6 +130,23 @@
static const int32_t SESSION_ID_INVALID_AND_IGNORED = -2;
};
+// ChannelMixBufferProvider derives from CopyBufferProvider to perform an
+// downmix to the proper channel count and mask.
+class ChannelMixBufferProvider : public CopyBufferProvider {
+public:
+ ChannelMixBufferProvider(audio_channel_mask_t inputChannelMask,
+ audio_channel_mask_t outputChannelMask, audio_format_t format,
+ size_t bufferFrameCount);
+
+ void copyFrames(void *dst, const void *src, size_t frames) override;
+
+ bool isValid() const { return mIsValid; }
+
+protected:
+ audio_utils::channels::ChannelMix mChannelMix;
+ bool mIsValid = false;
+};
+
// RemixBufferProvider derives from CopyBufferProvider to perform an
// upmix or downmix to the proper channel count and mask.
class RemixBufferProvider : public CopyBufferProvider {
@@ -223,17 +241,22 @@
// Extra expanded channels are filled with zeros and put at the end of each audio frame.
// Contracted channels are copied to the end of the output buffer(storage should be
// allocated appropriately).
-// Contracted channels could be written to output buffer.
+// Contracted channels could be written to output buffer and got adjusted. When the contracted
+// channels are adjusted in the contracted buffer, the input channel count will be calculated
+// as `inChannelCount - outChannelCount`. The output channel count is provided by caller, which
+// is `contractedOutChannelCount`. Currently, adjusting contracted channels is used for audio
+// coupled haptic playback. If the device supports two haptic channels while apps only provide
+// single haptic channel, the second haptic channel will be duplicated with the first haptic
+// channel's data. If the device supports single haptic channels while apps provide two haptic
+// channels, the second channel will be contracted.
class AdjustChannelsBufferProvider : public CopyBufferProvider {
public:
- AdjustChannelsBufferProvider(audio_format_t format, size_t inChannelCount,
- size_t outChannelCount, size_t frameCount) : AdjustChannelsBufferProvider(
- format, inChannelCount, outChannelCount,
- frameCount, AUDIO_FORMAT_INVALID, nullptr) { }
// Contracted data is converted to contractedFormat and put into contractedBuffer.
AdjustChannelsBufferProvider(audio_format_t format, size_t inChannelCount,
- size_t outChannelCount, size_t frameCount, audio_format_t contractedFormat,
- void* contractedBuffer);
+ size_t outChannelCount, size_t frameCount,
+ audio_format_t contractedFormat = AUDIO_FORMAT_INVALID,
+ void* contractedBuffer = nullptr,
+ size_t contractedOutChannelCount = 0);
//Overrides
status_t getNextBuffer(Buffer* pBuffer) override;
void copyFrames(void *dst, const void *src, size_t frames) override;
@@ -247,11 +270,14 @@
const size_t mOutChannelCount;
const size_t mSampleSizeInBytes;
const size_t mFrameCount;
- const size_t mContractedChannelCount;
const audio_format_t mContractedFormat;
+ const size_t mContractedInChannelCount;
+ const size_t mContractedOutChannelCount;
+ const size_t mContractedSampleSizeInBytes;
+ const size_t mContractedInputFrameSize; // contracted input frame size
void *mContractedBuffer;
size_t mContractedWrittenFrames;
- size_t mContractedFrameSize;
+ size_t mContractedOutputFrameSize; // contracted output frame size
};
// ----------------------------------------------------------------------------
} // namespace android
diff --git a/media/libmedia/tests/codeclist/Android.bp b/media/libmedia/tests/codeclist/Android.bp
index 57af9a9..2ed3126 100644
--- a/media/libmedia/tests/codeclist/Android.bp
+++ b/media/libmedia/tests/codeclist/Android.bp
@@ -28,6 +28,22 @@
test_suites: ["device-tests", "mts"],
gtest: true,
+ // Support multilib variants (using different suffix per sub-architecture), which is needed on
+ // build targets with secondary architectures, as the MTS test suite packaging logic flattens
+ // all test artifacts into a single `testcases` directory.
+ compile_multilib: "both",
+ multilib: {
+ lib32: {
+ suffix: "32",
+ },
+ lib64: {
+ suffix: "64",
+ },
+ },
+
+ // used within mainline MTS, but only to R, not to Q.
+ min_sdk_version: "30",
+
srcs: [
"CodecListTest.cpp",
],
@@ -35,13 +51,13 @@
shared_libs: [
"libbinder",
"liblog",
- "libmedia_codeclist",
+ "libmedia_codeclist", // available >= R
"libstagefright",
"libstagefright_foundation",
"libstagefright_xmlparser",
"libutils",
],
- compile_multilib: "first",
+
cflags: [
"-Werror",
"-Wall",
diff --git a/media/libmedia/tests/codeclist/AndroidTest.xml b/media/libmedia/tests/codeclist/AndroidTest.xml
new file mode 100644
index 0000000..eeaab8e
--- /dev/null
+++ b/media/libmedia/tests/codeclist/AndroidTest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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.
+-->
+<configuration description="Test module config for CodecList unit tests">
+ <option name="test-suite-tag" value="CodecListTest" />
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk30ModuleController" />
+
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+ <option name="cleanup" value="true" />
+ <option name="append-bitness" value="true" />
+ <option name="push" value="CodecListTest->/data/local/tmp/CodecListTest" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="CodecListTest" />
+ </test>
+
+
+</configuration>
diff --git a/media/libmediaplayerservice/Android.bp b/media/libmediaplayerservice/Android.bp
index 37f8103..c416a51 100644
--- a/media/libmediaplayerservice/Android.bp
+++ b/media/libmediaplayerservice/Android.bp
@@ -83,7 +83,6 @@
export_shared_lib_headers: [
"libmedia",
"framework-permission-aidl-cpp",
- "packagemanager_aidl-cpp",
],
include_dirs: [
diff --git a/media/libmediaplayerservice/fuzzer/Android.bp b/media/libmediaplayerservice/fuzzer/Android.bp
new file mode 100644
index 0000000..d83d3c9
--- /dev/null
+++ b/media/libmediaplayerservice/fuzzer/Android.bp
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2021 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 {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libmediaplayerservice_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: [
+ "frameworks_av_media_libmediaplayerservice_license",
+ ],
+}
+
+cc_defaults {
+ name: "libmediaplayerserviceFuzzer_defaults",
+ include_dirs: [
+ "frameworks/av/media/libmediaplayerservice",
+ ],
+ static_libs: [
+ "libmediaplayerservice",
+ "liblog",
+ ],
+ shared_libs: [
+ "framework-permission-aidl-cpp",
+ "libbinder",
+ "libcutils",
+ "libmedia",
+ "libstagefright",
+ "libutils",
+ "libstagefright_foundation",
+ ],
+ fuzz_config: {
+ cc: [
+ "android-media-fuzzing-reports@google.com",
+ ],
+ componentid: 155276,
+ },
+}
+
+cc_fuzz {
+ name: "mediarecorder_fuzzer",
+ srcs: [
+ "mediarecorder_fuzzer.cpp",
+ ],
+ defaults: [
+ "libmediaplayerserviceFuzzer_defaults",
+ ],
+ static_libs: [
+ "libstagefright_rtsp",
+ "libbase",
+ ],
+ shared_libs: [
+ "av-types-aidl-cpp",
+ "media_permission-aidl-cpp",
+ "libaudioclient_aidl_conversion",
+ "libandroid_net",
+ "libcamera_client",
+ "libgui",
+ "libmediametrics",
+ ],
+}
+
+cc_fuzz {
+ name: "metadataretriever_fuzzer",
+ srcs: [
+ "metadataretriever_fuzzer.cpp",
+ ],
+ defaults: [
+ "libmediaplayerserviceFuzzer_defaults",
+ ],
+ static_libs: [
+ "libplayerservice_datasource",
+ ],
+ shared_libs: [
+ "libdatasource",
+ "libdrmframework",
+ ],
+}
+
+cc_fuzz {
+ name: "mediaplayer_fuzzer",
+ srcs: [
+ "mediaplayer_fuzzer.cpp",
+ ],
+ defaults: [
+ "libmediaplayerserviceFuzzer_defaults",
+ ],
+ static_libs: [
+ "libplayerservice_datasource",
+ "libstagefright_nuplayer",
+ "libstagefright_rtsp",
+ "libstagefright_timedtext",
+ ],
+ shared_libs: [
+ "android.hardware.media.c2@1.0",
+ "android.hardware.media.omx@1.0",
+ "av-types-aidl-cpp",
+ "libaudioclient_aidl_conversion",
+ "libbase",
+ "libactivitymanager_aidl",
+ "libandroid_net",
+ "libaudioclient",
+ "libcamera_client",
+ "libcodec2_client",
+ "libcrypto",
+ "libdatasource",
+ "libdrmframework",
+ "libgui",
+ "libhidlbase",
+ "liblog",
+ "libmedia_codeclist",
+ "libmedia_omx",
+ "libmediadrm",
+ "libmediametrics",
+ "libmediautils",
+ "libmemunreachable",
+ "libnetd_client",
+ "libpowermanager",
+ "libstagefright_httplive",
+ ],
+}
diff --git a/media/libmediaplayerservice/fuzzer/README.md b/media/libmediaplayerservice/fuzzer/README.md
new file mode 100644
index 0000000..a93c809
--- /dev/null
+++ b/media/libmediaplayerservice/fuzzer/README.md
@@ -0,0 +1,83 @@
+# Fuzzer for libmediaplayerservice
+## Table of contents
++ [StagefrightMediaRecorder](#StagefrightMediaRecorder)
++ [StagefrightMetadataRetriever](#StagefrightMetadataRetriever)
++ [MediaPlayer](#MediaPlayer)
+
+# <a name="StagefrightMediaRecorder"></a> Fuzzer for StagefrightMediaRecorder
+
+StagefrightMediaRecorder supports the following parameters:
+1. Output Formats (parameter name: `setOutputFormat`)
+2. Audio Encoders (parameter name: `setAudioEncoder`)
+3. Video Encoders (parameter name: `setVideoEncoder`)
+4. Audio Sources (parameter name: `setAudioSource`)
+5. Video Sources (parameter name: `setVideoSource`)
+6. Microphone Direction (parameter name: `setMicrophoneDirection`)
+
+You can find the possible values in the fuzzer's source code.
+
+#### Steps to run
+1. Build the fuzzer
+```
+ $ mm -j$(nproc) mediarecorder_fuzzer
+```
+2. Run on device
+```
+ $ adb sync data
+ $ adb shell /data/fuzz/arm64/mediarecorder_fuzzer/mediarecorder_fuzzer
+```
+
+# <a name="StagefrightMetadataRetriever"></a> Fuzzer for StagefrightMetadataRetriever
+
+StagefrightMetadataRetriever supports the following data sources:
+1. Url (parameter name: `url`)
+2. File descriptor (parameter name: `fd`)
+3. DataSource (parameter name: `source`)
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+| `url` | Url of data source | Value obtained from FuzzedDataProvider |
+| `fd` | File descriptor value of input file | Value obtained from FuzzedDataProvider |
+| `source` | DataSource object | Data obtained from FuzzedDataProvider |
+
+#### Steps to run
+1. Build the fuzzer
+```
+ $ mm -j$(nproc) metadataretriever_fuzzer
+```
+2. To run on device
+```
+ $ adb sync data
+ $ adb shell /data/fuzz/arm64/metadataretriever_fuzzer/metadataretriever_fuzzer
+```
+
+# <a name="MediaPlayer"></a> Fuzzer for MediaPlayer
+
+MediaPlayerService supports the following data sources:
+1. Url (parameter name: `url`)
+2. File descriptor (parameter name: `fd`)
+3. IStreamSource (parameter name: `source`)
+4. IDataSource (parameter name: `source`)
+5. RTP Parameters (parameter name: `rtpParams`)
+
+MediaPlayerService supports the following parameters:
+1. Audio sessions (parameter name: `audioSessionId`)
+2. Audio stretch modes (parameter name: `mStretchMode`)
+3. Audio fallback modes (parameter name: `mFallbackMode`)
+4. Media parameter keys (parameter name: `key`)
+5. Audio Stream Types (parameter name: `streamType`)
+6. Media Event Types (parameter name: `msg`)
+7. Media Info Types (parameter name: `ext1`)
+
+You can find the possible values in the fuzzer's source code.
+
+#### Steps to run
+1. Build the fuzzer
+```
+ $ mm -j$(nproc) mediaplayer_fuzzer
+```
+2. To run on device
+```
+ $ adb sync data
+ $ adb shell /data/fuzz/arm64/mediaplayer_fuzzer/mediaplayer_fuzzer
+```
diff --git a/media/libmediaplayerservice/fuzzer/mediaplayer_fuzzer.cpp b/media/libmediaplayerservice/fuzzer/mediaplayer_fuzzer.cpp
new file mode 100644
index 0000000..7799f44
--- /dev/null
+++ b/media/libmediaplayerservice/fuzzer/mediaplayer_fuzzer.cpp
@@ -0,0 +1,368 @@
+/*
+ * Copyright (C) 2021 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.
+ *
+ */
+
+#include <MediaPlayerService.h>
+#include <camera/Camera.h>
+#include <datasource/FileSource.h>
+#include <gui/Surface.h>
+#include <gui/SurfaceComposerClient.h>
+#include <media/IMediaCodecList.h>
+#include <media/IMediaHTTPService.h>
+#include <media/IMediaPlayer.h>
+#include <media/IMediaRecorder.h>
+#include <media/IRemoteDisplay.h>
+#include <media/IRemoteDisplayClient.h>
+#include <media/stagefright/RemoteDataSource.h>
+#include <media/stagefright/foundation/base64.h>
+#include <thread>
+#include "fuzzer/FuzzedDataProvider.h"
+
+constexpr int32_t kUuidSize = 16;
+constexpr int32_t kMaxSleepTimeInMs = 100;
+constexpr int32_t kMinSleepTimeInMs = 0;
+constexpr int32_t kPlayCountMin = 1;
+constexpr int32_t kPlayCountMax = 10;
+constexpr int32_t kMaxDimension = 8192;
+constexpr int32_t kMinDimension = 0;
+
+using namespace std;
+using namespace android;
+
+constexpr audio_session_t kSupportedAudioSessions[] = {
+ AUDIO_SESSION_DEVICE, AUDIO_SESSION_OUTPUT_STAGE, AUDIO_SESSION_OUTPUT_MIX};
+
+constexpr audio_timestretch_stretch_mode_t kAudioStretchModes[] = {
+ AUDIO_TIMESTRETCH_STRETCH_DEFAULT, AUDIO_TIMESTRETCH_STRETCH_VOICE};
+
+constexpr audio_timestretch_fallback_mode_t kAudioFallbackModes[] = {
+ AUDIO_TIMESTRETCH_FALLBACK_CUT_REPEAT, AUDIO_TIMESTRETCH_FALLBACK_DEFAULT,
+ AUDIO_TIMESTRETCH_FALLBACK_MUTE, AUDIO_TIMESTRETCH_FALLBACK_FAIL};
+
+constexpr media_parameter_keys kMediaParamKeys[] = {
+ KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS, KEY_PARAMETER_AUDIO_CHANNEL_COUNT,
+ KEY_PARAMETER_PLAYBACK_RATE_PERMILLE, KEY_PARAMETER_AUDIO_ATTRIBUTES,
+ KEY_PARAMETER_RTP_ATTRIBUTES};
+
+constexpr audio_stream_type_t kAudioStreamTypes[] = {
+ AUDIO_STREAM_DEFAULT, AUDIO_STREAM_VOICE_CALL, AUDIO_STREAM_SYSTEM,
+ AUDIO_STREAM_RING, AUDIO_STREAM_MUSIC, AUDIO_STREAM_ALARM,
+ AUDIO_STREAM_NOTIFICATION, AUDIO_STREAM_BLUETOOTH_SCO, AUDIO_STREAM_ENFORCED_AUDIBLE,
+ AUDIO_STREAM_DTMF, AUDIO_STREAM_TTS, AUDIO_STREAM_ASSISTANT};
+
+constexpr media_event_type kMediaEventTypes[] = {MEDIA_NOP,
+ MEDIA_PREPARED,
+ MEDIA_PLAYBACK_COMPLETE,
+ MEDIA_BUFFERING_UPDATE,
+ MEDIA_SEEK_COMPLETE,
+ MEDIA_SET_VIDEO_SIZE,
+ MEDIA_STARTED,
+ MEDIA_PAUSED,
+ MEDIA_STOPPED,
+ MEDIA_SKIPPED,
+ MEDIA_NOTIFY_TIME,
+ MEDIA_TIMED_TEXT,
+ MEDIA_ERROR,
+ MEDIA_INFO,
+ MEDIA_SUBTITLE_DATA,
+ MEDIA_META_DATA,
+ MEDIA_DRM_INFO,
+ MEDIA_TIME_DISCONTINUITY,
+ MEDIA_IMS_RX_NOTICE,
+ MEDIA_AUDIO_ROUTING_CHANGED};
+
+constexpr media_info_type kMediaInfoTypes[] = {
+ MEDIA_INFO_UNKNOWN, MEDIA_INFO_STARTED_AS_NEXT,
+ MEDIA_INFO_RENDERING_START, MEDIA_INFO_VIDEO_TRACK_LAGGING,
+ MEDIA_INFO_BUFFERING_START, MEDIA_INFO_BUFFERING_END,
+ MEDIA_INFO_NETWORK_BANDWIDTH, MEDIA_INFO_BAD_INTERLEAVING,
+ MEDIA_INFO_NOT_SEEKABLE, MEDIA_INFO_METADATA_UPDATE,
+ MEDIA_INFO_PLAY_AUDIO_ERROR, MEDIA_INFO_PLAY_VIDEO_ERROR,
+ MEDIA_INFO_TIMED_TEXT_ERROR};
+
+const char *kUrlPrefix[] = {"data:", "http://", "https://", "rtsp://", "content://", "test://"};
+
+struct TestStreamSource : public IStreamSource {
+ void setListener(const sp<IStreamListener> & /*listener*/) override{};
+ void setBuffers(const Vector<sp<IMemory>> & /*buffers*/) override{};
+ void onBufferAvailable(size_t /*index*/) override{};
+ IBinder *onAsBinder() { return nullptr; };
+};
+
+class BinderDeathNotifier : public IBinder::DeathRecipient {
+ public:
+ void binderDied(const wp<IBinder> &) { abort(); }
+};
+
+class MediaPlayerServiceFuzzer {
+ public:
+ MediaPlayerServiceFuzzer(const uint8_t *data, size_t size)
+ : mFdp(data, size), mDataSourceFd(memfd_create("InputFile", MFD_ALLOW_SEALING)){};
+ ~MediaPlayerServiceFuzzer() { close(mDataSourceFd); };
+ void process(const uint8_t *data, size_t size);
+
+ private:
+ bool setDataSource(const uint8_t *data, size_t size);
+ void invokeMediaPlayer();
+ FuzzedDataProvider mFdp;
+ sp<IMediaPlayer> mMediaPlayer = nullptr;
+ sp<IMediaPlayerClient> mMediaPlayerClient = nullptr;
+ const int32_t mDataSourceFd;
+};
+
+bool MediaPlayerServiceFuzzer::setDataSource(const uint8_t *data, size_t size) {
+ status_t status = -1;
+ enum DataSourceType {http, fd, stream, file, socket, kMaxValue = socket};
+ switch (mFdp.ConsumeEnum<DataSourceType>()) {
+ case http: {
+ KeyedVector<String8, String8> headers;
+ headers.add(String8(mFdp.ConsumeRandomLengthString().c_str()),
+ String8(mFdp.ConsumeRandomLengthString().c_str()));
+
+ uint32_t dataBlobSize = mFdp.ConsumeIntegralInRange<uint16_t>(0, size);
+ vector<uint8_t> uriSuffix = mFdp.ConsumeBytes<uint8_t>(dataBlobSize);
+
+ string uri(mFdp.PickValueInArray(kUrlPrefix));
+ uri += ";base64,";
+ AString out;
+ encodeBase64(uriSuffix.data(), uriSuffix.size(), &out);
+ uri += out.c_str();
+ status = mMediaPlayer->setDataSource(nullptr /*httpService*/, uri.c_str(), &headers);
+ break;
+ }
+ case fd: {
+ write(mDataSourceFd, data, size);
+
+ status = mMediaPlayer->setDataSource(mDataSourceFd, 0, size);
+ break;
+ }
+ case stream: {
+ sp<IStreamSource> streamSource = sp<TestStreamSource>::make();
+ status = mMediaPlayer->setDataSource(streamSource);
+ break;
+ }
+ case file: {
+ write(mDataSourceFd, data, size);
+
+ sp<DataSource> dataSource = new FileSource(dup(mDataSourceFd), 0, size);
+ sp<IDataSource> iDataSource = RemoteDataSource::wrap(dataSource);
+ if (!iDataSource) {
+ return false;
+ }
+ status = mMediaPlayer->setDataSource(iDataSource);
+ break;
+ }
+ case socket: {
+ String8 rtpParams = String8(mFdp.ConsumeRandomLengthString().c_str());
+ struct sockaddr_in endpoint;
+ endpoint.sin_family = mFdp.ConsumeIntegral<unsigned short>();
+ endpoint.sin_port = mFdp.ConsumeIntegral<uint16_t>();
+ mMediaPlayer->setRetransmitEndpoint(&endpoint);
+ status = mMediaPlayer->setDataSource(rtpParams);
+ break;
+ }
+ }
+
+ if (status != 0) {
+ return false;
+ }
+ return true;
+}
+
+void MediaPlayerServiceFuzzer::invokeMediaPlayer() {
+ sp<SurfaceComposerClient> composerClient = new SurfaceComposerClient;
+ String8 name = String8(mFdp.ConsumeRandomLengthString().c_str());
+ uint32_t width = mFdp.ConsumeIntegralInRange<uint32_t>(kMinDimension, kMaxDimension);
+ uint32_t height = mFdp.ConsumeIntegralInRange<uint32_t>(kMinDimension, kMaxDimension);
+ uint32_t pixelFormat = mFdp.ConsumeIntegral<int32_t>();
+ uint32_t flags = mFdp.ConsumeIntegral<int32_t>();
+ sp<SurfaceControl> surfaceControl =
+ composerClient->createSurface(name, width, height, pixelFormat, flags);
+ if (surfaceControl) {
+ sp<Surface> surface = surfaceControl->getSurface();
+ mMediaPlayer->setVideoSurfaceTexture(surface->getIGraphicBufferProducer());
+ }
+
+ BufferingSettings buffering;
+ buffering.mInitialMarkMs = mFdp.ConsumeIntegral<int32_t>();
+ buffering.mResumePlaybackMarkMs = mFdp.ConsumeIntegral<int32_t>();
+ mMediaPlayer->setBufferingSettings(buffering);
+ mMediaPlayer->getBufferingSettings(&buffering);
+
+ mMediaPlayer->prepareAsync();
+ size_t playCount = mFdp.ConsumeIntegralInRange<size_t>(kPlayCountMin, kPlayCountMax);
+ for (size_t Idx = 0; Idx < playCount; ++Idx) {
+ mMediaPlayer->start();
+ this_thread::sleep_for(chrono::milliseconds(
+ mFdp.ConsumeIntegralInRange<int32_t>(kMinSleepTimeInMs, kMaxSleepTimeInMs)));
+ mMediaPlayer->pause();
+ this_thread::sleep_for(chrono::milliseconds(
+ mFdp.ConsumeIntegralInRange<int32_t>(kMinSleepTimeInMs, kMaxSleepTimeInMs)));
+ mMediaPlayer->stop();
+ }
+ bool state;
+ mMediaPlayer->isPlaying(&state);
+
+ AudioPlaybackRate rate;
+ rate.mSpeed = mFdp.ConsumeFloatingPoint<float>();
+ rate.mPitch = mFdp.ConsumeFloatingPoint<float>();
+ rate.mStretchMode = mFdp.PickValueInArray(kAudioStretchModes);
+ rate.mFallbackMode = mFdp.PickValueInArray(kAudioFallbackModes);
+ mMediaPlayer->setPlaybackSettings(rate);
+ mMediaPlayer->getPlaybackSettings(&rate);
+
+ AVSyncSettings *avSyncSettings = new AVSyncSettings();
+ float videoFpsHint = mFdp.ConsumeFloatingPoint<float>();
+ mMediaPlayer->setSyncSettings(*avSyncSettings, videoFpsHint);
+ mMediaPlayer->getSyncSettings(avSyncSettings, &videoFpsHint);
+ delete avSyncSettings;
+
+ mMediaPlayer->seekTo(mFdp.ConsumeIntegral<int32_t>());
+
+ int32_t msec;
+ mMediaPlayer->getCurrentPosition(&msec);
+ mMediaPlayer->getDuration(&msec);
+ mMediaPlayer->reset();
+
+ mMediaPlayer->notifyAt(mFdp.ConsumeIntegral<int64_t>());
+
+ mMediaPlayer->setAudioStreamType(mFdp.PickValueInArray(kAudioStreamTypes));
+ mMediaPlayer->setLooping(mFdp.ConsumeIntegral<int32_t>());
+ float left = mFdp.ConsumeFloatingPoint<float>();
+ float right = mFdp.ConsumeFloatingPoint<float>();
+ mMediaPlayer->setVolume(left, right);
+
+ Parcel request, reply;
+ request.writeInt32(mFdp.ConsumeIntegral<int32_t>());
+ request.setDataPosition(0);
+ mMediaPlayer->invoke(request, &reply);
+
+ Parcel filter;
+ filter.writeInt32(mFdp.ConsumeIntegral<int32_t>());
+ filter.setDataPosition(0);
+ mMediaPlayer->setMetadataFilter(filter);
+
+ bool updateOnly = mFdp.ConsumeBool();
+ bool applyFilter = mFdp.ConsumeBool();
+ mMediaPlayer->getMetadata(updateOnly, applyFilter, &reply);
+ mMediaPlayer->setAuxEffectSendLevel(mFdp.ConsumeFloatingPoint<float>());
+ mMediaPlayer->attachAuxEffect(mFdp.ConsumeIntegral<int32_t>());
+
+ int32_t key = mFdp.PickValueInArray(kMediaParamKeys);
+ request.writeInt32(mFdp.ConsumeIntegral<int32_t>());
+ request.setDataPosition(0);
+ mMediaPlayer->setParameter(key, request);
+ key = mFdp.PickValueInArray(kMediaParamKeys);
+ mMediaPlayer->getParameter(key, &reply);
+
+ struct sockaddr_in endpoint;
+ mMediaPlayer->getRetransmitEndpoint(&endpoint);
+
+ AttributionSourceState attributionSource;
+ attributionSource.packageName = mFdp.ConsumeRandomLengthString().c_str();
+ attributionSource.token = sp<BBinder>::make();
+ const sp<IMediaPlayerService> mpService(IMediaDeathNotifier::getMediaPlayerService());
+ sp<IMediaPlayer> mNextMediaPlayer = mpService->create(
+ mMediaPlayerClient, mFdp.PickValueInArray(kSupportedAudioSessions), attributionSource);
+ mMediaPlayer->setNextPlayer(mNextMediaPlayer);
+
+ const sp<media::VolumeShaper::Configuration> configuration =
+ sp<media::VolumeShaper::Configuration>::make();
+ const sp<media::VolumeShaper::Operation> operation = sp<media::VolumeShaper::Operation>::make();
+ mMediaPlayer->applyVolumeShaper(configuration, operation);
+
+ mMediaPlayer->getVolumeShaperState(mFdp.ConsumeIntegral<int32_t>());
+ uint8_t uuid[kUuidSize];
+ for (int32_t index = 0; index < kUuidSize; ++index) {
+ uuid[index] = mFdp.ConsumeIntegral<uint8_t>();
+ }
+ Vector<uint8_t> drmSessionId;
+ drmSessionId.push_back(mFdp.ConsumeIntegral<uint8_t>());
+ mMediaPlayer->prepareDrm(uuid, drmSessionId);
+ mMediaPlayer->releaseDrm();
+
+ audio_port_handle_t deviceId = mFdp.ConsumeIntegral<int32_t>();
+ mMediaPlayer->setOutputDevice(deviceId);
+ mMediaPlayer->getRoutedDeviceId(&deviceId);
+
+ mMediaPlayer->enableAudioDeviceCallback(mFdp.ConsumeBool());
+
+ sp<MediaPlayer> mediaPlayer = (MediaPlayer *)mMediaPlayer.get();
+
+ int32_t msg = mFdp.PickValueInArray(kMediaEventTypes);
+ int32_t ext1 = mFdp.PickValueInArray(kMediaInfoTypes);
+ int32_t ext2 = mFdp.ConsumeIntegral<int32_t>();
+ Parcel obj;
+ obj.writeInt32(mFdp.ConsumeIntegral<int32_t>());
+ obj.setDataPosition(0);
+ mediaPlayer->notify(msg, ext1, ext2, &obj);
+
+ int32_t mediaPlayerDumpFd = memfd_create("OutputDumpFile", MFD_ALLOW_SEALING);
+ Vector<String16> args;
+ args.push_back(String16(mFdp.ConsumeRandomLengthString().c_str()));
+ mediaPlayer->dump(mediaPlayerDumpFd, args);
+ close(mediaPlayerDumpFd);
+
+ mMediaPlayer->disconnect();
+}
+
+void MediaPlayerServiceFuzzer::process(const uint8_t *data, size_t size) {
+ MediaPlayerService::instantiate();
+
+ const sp<IMediaPlayerService> mpService(IMediaDeathNotifier::getMediaPlayerService());
+ if (!mpService) {
+ return;
+ }
+
+ sp<IMediaCodecList> mediaCodecList = mpService->getCodecList();
+
+ sp<IRemoteDisplayClient> remoteDisplayClient;
+ sp<IRemoteDisplay> remoteDisplay = mpService->listenForRemoteDisplay(
+ String16(mFdp.ConsumeRandomLengthString().c_str()) /*opPackageName*/, remoteDisplayClient,
+ String8(mFdp.ConsumeRandomLengthString().c_str()) /*iface*/);
+
+ mpService->addBatteryData(mFdp.ConsumeIntegral<uint32_t>());
+ Parcel reply;
+ mpService->pullBatteryData(&reply);
+
+ sp<MediaPlayerService> mediaPlayerService = (MediaPlayerService *)mpService.get();
+ AttributionSourceState attributionSource;
+ attributionSource.packageName = mFdp.ConsumeRandomLengthString().c_str();
+ attributionSource.token = sp<BBinder>::make();
+ mMediaPlayer = mediaPlayerService->create(
+ mMediaPlayerClient, mFdp.PickValueInArray(kSupportedAudioSessions), attributionSource);
+
+ int32_t mediaPlayerServiceDumpFd = memfd_create("OutputDumpFile", MFD_ALLOW_SEALING);
+ Vector<String16> args;
+ args.push_back(String16(mFdp.ConsumeRandomLengthString().c_str()));
+ mediaPlayerService->dump(mediaPlayerServiceDumpFd, args);
+ close(mediaPlayerServiceDumpFd);
+
+ if (!mMediaPlayer) {
+ return;
+ }
+
+ if (setDataSource(data, size)) {
+ invokeMediaPlayer();
+ }
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ MediaPlayerServiceFuzzer mpsFuzzer(data, size);
+ ProcessState::self()->startThreadPool();
+ mpsFuzzer.process(data, size);
+ return 0;
+};
diff --git a/media/libmediaplayerservice/fuzzer/mediarecorder_fuzzer.cpp b/media/libmediaplayerservice/fuzzer/mediarecorder_fuzzer.cpp
new file mode 100644
index 0000000..b0040fe
--- /dev/null
+++ b/media/libmediaplayerservice/fuzzer/mediarecorder_fuzzer.cpp
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2021 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.
+ *
+ */
+
+#include <media/stagefright/foundation/AString.h>
+#include "fuzzer/FuzzedDataProvider.h"
+
+#include <StagefrightRecorder.h>
+#include <camera/Camera.h>
+#include <camera/android/hardware/ICamera.h>
+#include <gui/IGraphicBufferProducer.h>
+#include <gui/Surface.h>
+#include <gui/SurfaceComposerClient.h>
+#include <media/stagefright/PersistentSurface.h>
+#include <thread>
+
+using namespace std;
+using namespace android;
+using namespace android::hardware;
+
+constexpr video_source kSupportedVideoSources[] = {VIDEO_SOURCE_DEFAULT, VIDEO_SOURCE_CAMERA,
+ VIDEO_SOURCE_SURFACE};
+
+constexpr audio_source_t kSupportedAudioSources[] = {
+ AUDIO_SOURCE_DEFAULT, AUDIO_SOURCE_MIC,
+ AUDIO_SOURCE_VOICE_UPLINK, AUDIO_SOURCE_VOICE_DOWNLINK,
+ AUDIO_SOURCE_VOICE_CALL, AUDIO_SOURCE_CAMCORDER,
+ AUDIO_SOURCE_VOICE_RECOGNITION, AUDIO_SOURCE_VOICE_COMMUNICATION,
+ AUDIO_SOURCE_REMOTE_SUBMIX, AUDIO_SOURCE_UNPROCESSED,
+ AUDIO_SOURCE_VOICE_PERFORMANCE, AUDIO_SOURCE_ECHO_REFERENCE,
+ AUDIO_SOURCE_FM_TUNER, AUDIO_SOURCE_HOTWORD};
+
+constexpr audio_microphone_direction_t kSupportedMicrophoneDirections[] = {
+ MIC_DIRECTION_UNSPECIFIED, MIC_DIRECTION_FRONT, MIC_DIRECTION_BACK, MIC_DIRECTION_EXTERNAL};
+
+struct RecordingConfig {
+ output_format outputFormat;
+ audio_encoder audioEncoder;
+ video_encoder videoEncoder;
+};
+
+const struct RecordingConfig kRecordingConfigList[] = {
+ {OUTPUT_FORMAT_AMR_NB, AUDIO_ENCODER_AMR_NB, VIDEO_ENCODER_DEFAULT},
+ {OUTPUT_FORMAT_AMR_WB, AUDIO_ENCODER_AMR_WB, VIDEO_ENCODER_DEFAULT},
+ {OUTPUT_FORMAT_AAC_ADTS, AUDIO_ENCODER_AAC, VIDEO_ENCODER_DEFAULT},
+ {OUTPUT_FORMAT_AAC_ADTS, AUDIO_ENCODER_HE_AAC, VIDEO_ENCODER_DEFAULT},
+ {OUTPUT_FORMAT_AAC_ADTS, AUDIO_ENCODER_AAC_ELD, VIDEO_ENCODER_DEFAULT},
+ {OUTPUT_FORMAT_OGG, AUDIO_ENCODER_OPUS, VIDEO_ENCODER_DEFAULT},
+ {OUTPUT_FORMAT_RTP_AVP, AUDIO_ENCODER_DEFAULT, VIDEO_ENCODER_DEFAULT},
+ {OUTPUT_FORMAT_MPEG2TS, AUDIO_ENCODER_AAC, VIDEO_ENCODER_H264},
+ {OUTPUT_FORMAT_WEBM, AUDIO_ENCODER_VORBIS, VIDEO_ENCODER_VP8},
+ {OUTPUT_FORMAT_THREE_GPP, AUDIO_ENCODER_DEFAULT, VIDEO_ENCODER_MPEG_4_SP},
+ {OUTPUT_FORMAT_MPEG_4, AUDIO_ENCODER_AAC, VIDEO_ENCODER_H264},
+ {OUTPUT_FORMAT_MPEG_4, AUDIO_ENCODER_DEFAULT, VIDEO_ENCODER_MPEG_4_SP},
+ {OUTPUT_FORMAT_MPEG_4, AUDIO_ENCODER_DEFAULT, VIDEO_ENCODER_HEVC}};
+
+const string kParametersList[] = {"max-duration",
+ "max-filesize",
+ "interleave-duration-us",
+ "param-movie-time-scale",
+ "param-geotag-longitude",
+ "param-geotag-latitude",
+ "param-track-time-status",
+ "audio-param-sampling-rate",
+ "audio-param-encoding-bitrate",
+ "audio-param-number-of-channels",
+ "audio-param-time-scale",
+ "video-param-rotation-angle-degrees",
+ "video-param-encoding-bitrate",
+ "video-param-bitrate-mode",
+ "video-param-i-frames-interval",
+ "video-param-encoder-profile",
+ "video-param-encoder-level",
+ "video-param-camera-id",
+ "video-param-time-scale",
+ "param-use-64bit-offset",
+ "time-lapse-enable",
+ "time-lapse-fps",
+ "rtp-param-local-ip",
+ "rtp-param-local-port",
+ "rtp-param-remote-port",
+ "rtp-param-self-id",
+ "rtp-param-opponent-id",
+ "rtp-param-payload-type",
+ "rtp-param-ext-cvo-extmap",
+ "rtp-param-ext-cvo-degrees",
+ "video-param-request-i-frame",
+ "rtp-param-set-socket-dscp",
+ "rtp-param-set-socket-network"};
+
+constexpr int32_t kMaxSleepTimeInMs = 100;
+constexpr int32_t kMinSleepTimeInMs = 0;
+constexpr int32_t kMinVideoSize = 2;
+constexpr int32_t kMaxVideoSize = 8192;
+constexpr int32_t kNumRecordMin = 1;
+constexpr int32_t kNumRecordMax = 10;
+
+class TestAudioDeviceCallback : public AudioSystem::AudioDeviceCallback {
+ public:
+ virtual ~TestAudioDeviceCallback() = default;
+
+ void onAudioDeviceUpdate(audio_io_handle_t /*audioIo*/,
+ audio_port_handle_t /*deviceId*/) override{};
+};
+
+class TestCamera : public ICamera {
+ public:
+ virtual ~TestCamera() = default;
+
+ binder::Status disconnect() override { return binder::Status::ok(); };
+ status_t connect(const sp<ICameraClient> & /*client*/) override { return 0; };
+ status_t lock() override { return 0; };
+ status_t unlock() override { return 0; };
+ status_t setPreviewTarget(const sp<IGraphicBufferProducer> & /*bufferProducer*/) override {
+ return 0;
+ };
+ void setPreviewCallbackFlag(int /*flag*/) override{};
+ status_t setPreviewCallbackTarget(
+ const sp<IGraphicBufferProducer> & /*callbackProducer*/) override {
+ return 0;
+ };
+ status_t startPreview() override { return 0; };
+ void stopPreview() override{};
+ bool previewEnabled() override { return true; };
+ status_t startRecording() override { return 0; };
+ void stopRecording() override{};
+ bool recordingEnabled() override { return true; };
+ void releaseRecordingFrame(const sp<IMemory> & /*mem*/) override{};
+ void releaseRecordingFrameHandle(native_handle_t * /*handle*/) override{};
+ void releaseRecordingFrameHandleBatch(const vector<native_handle_t *> & /*handles*/) override{};
+ status_t autoFocus() override { return 0; };
+ status_t cancelAutoFocus() override { return 0; };
+ status_t takePicture(int /*msgType*/) override { return 0; };
+ status_t setParameters(const String8 & /*params*/) override { return 0; };
+ String8 getParameters() const override { return String8(); };
+ status_t sendCommand(int32_t /*cmd*/, int32_t /*arg1*/, int32_t /*arg2*/) override {
+ return 0;
+ };
+ status_t setVideoBufferMode(int32_t /*videoBufferMode*/) override { return 0; };
+ status_t setVideoTarget(const sp<IGraphicBufferProducer> & /*bufferProducer*/) override {
+ return 0;
+ };
+ status_t setAudioRestriction(int32_t /*mode*/) override { return 0; };
+ int32_t getGlobalAudioRestriction() override { return 0; };
+ IBinder *onAsBinder() override { return reinterpret_cast<IBinder *>(this); };
+};
+
+class TestMediaRecorderClient : public IMediaRecorderClient {
+ public:
+ virtual ~TestMediaRecorderClient() = default;
+
+ void notify(int /*msg*/, int /*ext1*/, int /*ext2*/) override{};
+ IBinder *onAsBinder() override { return reinterpret_cast<IBinder *>(this); };
+};
+
+class MediaRecorderClientFuzzer {
+ public:
+ MediaRecorderClientFuzzer(const uint8_t *data, size_t size);
+ ~MediaRecorderClientFuzzer() { close(mMediaRecorderOutputFd); }
+ void process();
+
+ private:
+ void setConfig();
+ void getConfig();
+ void dumpInfo();
+
+ FuzzedDataProvider mFdp;
+ unique_ptr<MediaRecorderBase> mStfRecorder = nullptr;
+ SurfaceComposerClient mComposerClient;
+ sp<SurfaceControl> mSurfaceControl = nullptr;
+ sp<Surface> mSurface = nullptr;
+ const int32_t mMediaRecorderOutputFd;
+};
+
+void MediaRecorderClientFuzzer::getConfig() {
+ int32_t max;
+ mStfRecorder->getMaxAmplitude(&max);
+
+ int32_t deviceId = mFdp.ConsumeIntegral<int32_t>();
+ mStfRecorder->setInputDevice(deviceId);
+ mStfRecorder->getRoutedDeviceId(&deviceId);
+
+ vector<android::media::MicrophoneInfo> activeMicrophones{};
+ mStfRecorder->getActiveMicrophones(&activeMicrophones);
+
+ int32_t portId;
+ mStfRecorder->getPortId(&portId);
+
+ uint64_t bytes;
+ mStfRecorder->getRtpDataUsage(&bytes);
+
+ Parcel parcel;
+ mStfRecorder->getMetrics(&parcel);
+
+ sp<IGraphicBufferProducer> buffer = mStfRecorder->querySurfaceMediaSource();
+}
+
+void MediaRecorderClientFuzzer::dumpInfo() {
+ int32_t dumpFd = memfd_create("DumpFile", MFD_ALLOW_SEALING);
+ Vector<String16> args;
+ args.push_back(String16(mFdp.ConsumeRandomLengthString().c_str()));
+ mStfRecorder->dump(dumpFd, args);
+ close(dumpFd);
+}
+
+void MediaRecorderClientFuzzer::setConfig() {
+ mStfRecorder->setOutputFile(mMediaRecorderOutputFd);
+ mStfRecorder->setAudioSource(mFdp.PickValueInArray(kSupportedAudioSources));
+ mStfRecorder->setVideoSource(mFdp.PickValueInArray(kSupportedVideoSources));
+ mStfRecorder->setPreferredMicrophoneDirection(
+ mFdp.PickValueInArray(kSupportedMicrophoneDirections));
+ mStfRecorder->setPrivacySensitive(mFdp.ConsumeBool());
+ bool isPrivacySensitive;
+ mStfRecorder->isPrivacySensitive(&isPrivacySensitive);
+ mStfRecorder->setVideoSize(mFdp.ConsumeIntegralInRange<int32_t>(kMinVideoSize, kMaxVideoSize),
+ mFdp.ConsumeIntegralInRange<int32_t>(kMinVideoSize, kMaxVideoSize));
+ mStfRecorder->setVideoFrameRate(mFdp.ConsumeIntegral<int32_t>());
+ mStfRecorder->enableAudioDeviceCallback(mFdp.ConsumeBool());
+ mStfRecorder->setPreferredMicrophoneFieldDimension(mFdp.ConsumeFloatingPoint<float>());
+ mStfRecorder->setClientName(String16(mFdp.ConsumeRandomLengthString().c_str()));
+
+ int32_t Idx = mFdp.ConsumeIntegralInRange<int32_t>(0, size(kRecordingConfigList) - 1);
+ mStfRecorder->setOutputFormat(kRecordingConfigList[Idx].outputFormat);
+ mStfRecorder->setAudioEncoder(kRecordingConfigList[Idx].audioEncoder);
+ mStfRecorder->setVideoEncoder(kRecordingConfigList[Idx].videoEncoder);
+
+ int32_t nextOutputFd = memfd_create("NextOutputFile", MFD_ALLOW_SEALING);
+ mStfRecorder->setNextOutputFile(nextOutputFd);
+ close(nextOutputFd);
+
+ for (Idx = 0; Idx < size(kParametersList); ++Idx) {
+ if (mFdp.ConsumeBool()) {
+ int32_t value = mFdp.ConsumeIntegral<int32_t>();
+ mStfRecorder->setParameters(
+ String8((kParametersList[Idx] + "=" + to_string(value)).c_str()));
+ }
+ }
+}
+
+MediaRecorderClientFuzzer::MediaRecorderClientFuzzer(const uint8_t *data, size_t size)
+ : mFdp(data, size), mMediaRecorderOutputFd(memfd_create("OutputFile", MFD_ALLOW_SEALING)) {
+ AttributionSourceState attributionSource;
+ attributionSource.packageName = mFdp.ConsumeRandomLengthString().c_str();
+ attributionSource.token = sp<BBinder>::make();
+ mStfRecorder = make_unique<StagefrightRecorder>(attributionSource);
+
+ mSurfaceControl = mComposerClient.createSurface(
+ String8(mFdp.ConsumeRandomLengthString().c_str()), mFdp.ConsumeIntegral<uint32_t>(),
+ mFdp.ConsumeIntegral<uint32_t>(), mFdp.ConsumeIntegral<int32_t>(),
+ mFdp.ConsumeIntegral<int32_t>());
+ if (mSurfaceControl) {
+ mSurface = mSurfaceControl->getSurface();
+ mStfRecorder->setPreviewSurface(mSurface->getIGraphicBufferProducer());
+ }
+
+ sp<TestMediaRecorderClient> listener = sp<TestMediaRecorderClient>::make();
+ mStfRecorder->setListener(listener);
+
+ sp<TestCamera> testCamera = sp<TestCamera>::make();
+ sp<Camera> camera = Camera::create(testCamera);
+ mStfRecorder->setCamera(camera->remote(), camera->getRecordingProxy());
+
+ sp<PersistentSurface> persistentSurface = sp<PersistentSurface>::make();
+ mStfRecorder->setInputSurface(persistentSurface);
+
+ sp<TestAudioDeviceCallback> callback = sp<TestAudioDeviceCallback>::make();
+ mStfRecorder->setAudioDeviceCallback(callback);
+}
+
+void MediaRecorderClientFuzzer::process() {
+ setConfig();
+
+ mStfRecorder->init();
+ mStfRecorder->prepare();
+ size_t numRecord = mFdp.ConsumeIntegralInRange<size_t>(kNumRecordMin, kNumRecordMax);
+ for (size_t Idx = 0; Idx < numRecord; ++Idx) {
+ mStfRecorder->start();
+ this_thread::sleep_for(chrono::milliseconds(
+ mFdp.ConsumeIntegralInRange<int32_t>(kMinSleepTimeInMs, kMaxSleepTimeInMs)));
+ mStfRecorder->pause();
+ this_thread::sleep_for(chrono::milliseconds(
+ mFdp.ConsumeIntegralInRange<int32_t>(kMinSleepTimeInMs, kMaxSleepTimeInMs)));
+ mStfRecorder->resume();
+ this_thread::sleep_for(chrono::milliseconds(
+ mFdp.ConsumeIntegralInRange<int32_t>(kMinSleepTimeInMs, kMaxSleepTimeInMs)));
+ mStfRecorder->stop();
+ }
+ dumpInfo();
+ getConfig();
+
+ mStfRecorder->close();
+ mStfRecorder->reset();
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ MediaRecorderClientFuzzer mrcFuzzer(data, size);
+ mrcFuzzer.process();
+ return 0;
+}
diff --git a/media/libmediaplayerservice/fuzzer/metadataretriever_fuzzer.cpp b/media/libmediaplayerservice/fuzzer/metadataretriever_fuzzer.cpp
new file mode 100644
index 0000000..a7cb689
--- /dev/null
+++ b/media/libmediaplayerservice/fuzzer/metadataretriever_fuzzer.cpp
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2021 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.
+ *
+ */
+
+#include <StagefrightMetadataRetriever.h>
+#include <binder/ProcessState.h>
+#include <datasource/FileSource.h>
+#include <media/IMediaHTTPService.h>
+#include <media/stagefright/foundation/MediaDefs.h>
+#include <media/stagefright/foundation/base64.h>
+
+#include <fuzzer/FuzzedDataProvider.h>
+
+using namespace std;
+using namespace android;
+
+const char *kMimeTypes[] = {MEDIA_MIMETYPE_IMAGE_JPEG, MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC,
+ MEDIA_MIMETYPE_VIDEO_VP8, MEDIA_MIMETYPE_VIDEO_VP9,
+ MEDIA_MIMETYPE_VIDEO_AV1, MEDIA_MIMETYPE_VIDEO_AVC,
+ MEDIA_MIMETYPE_VIDEO_HEVC, MEDIA_MIMETYPE_VIDEO_MPEG4,
+ MEDIA_MIMETYPE_VIDEO_H263, MEDIA_MIMETYPE_VIDEO_MPEG2,
+ MEDIA_MIMETYPE_VIDEO_RAW, MEDIA_MIMETYPE_VIDEO_DOLBY_VISION,
+ MEDIA_MIMETYPE_VIDEO_SCRAMBLED, MEDIA_MIMETYPE_VIDEO_DIVX,
+ MEDIA_MIMETYPE_VIDEO_DIVX3, MEDIA_MIMETYPE_VIDEO_XVID,
+ MEDIA_MIMETYPE_VIDEO_MJPEG, MEDIA_MIMETYPE_AUDIO_AMR_NB,
+ MEDIA_MIMETYPE_AUDIO_AMR_WB, MEDIA_MIMETYPE_AUDIO_MPEG,
+ MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I, MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II,
+ MEDIA_MIMETYPE_AUDIO_MIDI, MEDIA_MIMETYPE_AUDIO_AAC,
+ MEDIA_MIMETYPE_AUDIO_QCELP, MEDIA_MIMETYPE_AUDIO_VORBIS,
+ MEDIA_MIMETYPE_AUDIO_OPUS, MEDIA_MIMETYPE_AUDIO_G711_ALAW,
+ MEDIA_MIMETYPE_AUDIO_G711_MLAW, MEDIA_MIMETYPE_AUDIO_RAW,
+ MEDIA_MIMETYPE_AUDIO_FLAC, MEDIA_MIMETYPE_AUDIO_AAC_ADTS,
+ MEDIA_MIMETYPE_AUDIO_MSGSM, MEDIA_MIMETYPE_AUDIO_AC3,
+ MEDIA_MIMETYPE_AUDIO_EAC3, MEDIA_MIMETYPE_AUDIO_EAC3_JOC,
+ MEDIA_MIMETYPE_AUDIO_AC4, MEDIA_MIMETYPE_AUDIO_SCRAMBLED,
+ MEDIA_MIMETYPE_AUDIO_ALAC, MEDIA_MIMETYPE_AUDIO_WMA,
+ MEDIA_MIMETYPE_AUDIO_MS_ADPCM, MEDIA_MIMETYPE_AUDIO_DVI_IMA_ADPCM,
+ MEDIA_MIMETYPE_CONTAINER_MPEG4, MEDIA_MIMETYPE_CONTAINER_WAV,
+ MEDIA_MIMETYPE_CONTAINER_OGG, MEDIA_MIMETYPE_CONTAINER_MATROSKA,
+ MEDIA_MIMETYPE_CONTAINER_MPEG2TS, MEDIA_MIMETYPE_CONTAINER_AVI,
+ MEDIA_MIMETYPE_CONTAINER_MPEG2PS, MEDIA_MIMETYPE_CONTAINER_HEIF,
+ MEDIA_MIMETYPE_TEXT_3GPP, MEDIA_MIMETYPE_TEXT_SUBRIP,
+ MEDIA_MIMETYPE_TEXT_VTT, MEDIA_MIMETYPE_TEXT_CEA_608,
+ MEDIA_MIMETYPE_TEXT_CEA_708, MEDIA_MIMETYPE_DATA_TIMED_ID3};
+
+class MetadataRetrieverFuzzer {
+ public:
+ MetadataRetrieverFuzzer(const uint8_t *data, size_t size)
+ : mFdp(data, size),
+ mMdRetriever(new StagefrightMetadataRetriever()),
+ mDataSourceFd(memfd_create("InputFile", MFD_ALLOW_SEALING)) {}
+ ~MetadataRetrieverFuzzer() { close(mDataSourceFd); }
+ bool setDataSource(const uint8_t *data, size_t size);
+ void getData();
+
+ private:
+ FuzzedDataProvider mFdp;
+ sp<StagefrightMetadataRetriever> mMdRetriever = nullptr;
+ const int32_t mDataSourceFd;
+};
+
+void MetadataRetrieverFuzzer::getData() {
+ int64_t timeUs = mFdp.ConsumeIntegral<int64_t>();
+ int32_t option = mFdp.ConsumeIntegral<int32_t>();
+ int32_t colorFormat = mFdp.ConsumeIntegral<int32_t>();
+ bool metaOnly = mFdp.ConsumeBool();
+ mMdRetriever->getFrameAtTime(timeUs, option, colorFormat, metaOnly);
+
+ int32_t index = mFdp.ConsumeIntegral<int32_t>();
+ colorFormat = mFdp.ConsumeIntegral<int32_t>();
+ metaOnly = mFdp.ConsumeBool();
+ bool thumbnail = mFdp.ConsumeBool();
+ mMdRetriever->getImageAtIndex(index, colorFormat, metaOnly, thumbnail);
+
+ index = mFdp.ConsumeIntegral<int32_t>();
+ colorFormat = mFdp.ConsumeIntegral<int32_t>();
+ int32_t left = mFdp.ConsumeIntegral<int32_t>();
+ int32_t top = mFdp.ConsumeIntegral<int32_t>();
+ int32_t right = mFdp.ConsumeIntegral<int32_t>();
+ int32_t bottom = mFdp.ConsumeIntegral<int32_t>();
+ mMdRetriever->getImageRectAtIndex(index, colorFormat, left, top, right, bottom);
+
+ index = mFdp.ConsumeIntegral<int32_t>();
+ colorFormat = mFdp.ConsumeIntegral<int32_t>();
+ metaOnly = mFdp.ConsumeBool();
+ mMdRetriever->getFrameAtIndex(index, colorFormat, metaOnly);
+
+ mMdRetriever->extractAlbumArt();
+
+ int32_t keyCode = mFdp.ConsumeIntegral<int32_t>();
+ mMdRetriever->extractMetadata(keyCode);
+}
+
+bool MetadataRetrieverFuzzer::setDataSource(const uint8_t *data, size_t size) {
+ status_t status = -1;
+
+ enum DataSourceChoice {FromHttp, FromFd, FromFileSource, kMaxValue = FromFileSource};
+ switch (mFdp.ConsumeEnum<DataSourceChoice>()) {
+ case FromHttp: {
+ KeyedVector<String8, String8> mHeaders;
+ mHeaders.add(String8(mFdp.ConsumeRandomLengthString().c_str()),
+ String8(mFdp.ConsumeRandomLengthString().c_str()));
+
+ uint32_t dataBlobSize = mFdp.ConsumeIntegralInRange<uint16_t>(0, size);
+ vector<uint8_t> uriSuffix = mFdp.ConsumeBytes<uint8_t>(dataBlobSize);
+
+ string uri("data:");
+ uri += ";base64,";
+ AString out;
+ encodeBase64(uriSuffix.data(), uriSuffix.size(), &out);
+ uri += out.c_str();
+ status = mMdRetriever->setDataSource(nullptr /*httpService*/, uri.c_str(), &mHeaders);
+ break;
+ }
+ case FromFd: {
+ write(mDataSourceFd, data, size);
+
+ status = mMdRetriever->setDataSource(mDataSourceFd, 0, size);
+ break;
+ }
+ case FromFileSource: {
+ write(mDataSourceFd, data, size);
+
+ sp<DataSource> dataSource = new FileSource(dup(mDataSourceFd), 0, size);
+ status = mMdRetriever->setDataSource(dataSource, mFdp.PickValueInArray(kMimeTypes));
+ break;
+ }
+ }
+
+ if (status != 0) {
+ return false;
+ }
+ return true;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ MetadataRetrieverFuzzer mrtFuzzer(data, size);
+ ProcessState::self()->startThreadPool();
+ if (mrtFuzzer.setDataSource(data, size)) {
+ mrtFuzzer.getData();
+ }
+ return 0;
+}
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index 1e9d4fe..e47e7ff 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -373,7 +373,6 @@
"libmedia",
"android.hidl.allocator@1.0",
"framework-permission-aidl-cpp",
- "packagemanager_aidl-cpp",
],
export_include_dirs: [
diff --git a/media/libstagefright/colorconversion/Android.bp b/media/libstagefright/colorconversion/Android.bp
index 06cebd3..7ff9b10 100644
--- a/media/libstagefright/colorconversion/Android.bp
+++ b/media/libstagefright/colorconversion/Android.bp
@@ -25,10 +25,6 @@
"SoftwareRenderer.cpp",
],
- include_dirs: [
- "frameworks/native/include/media/openmax",
- ],
-
shared_libs: [
"libui",
"libnativewindow",
@@ -37,6 +33,7 @@
header_libs: [
"libstagefright_headers",
"libstagefright_foundation_headers",
+ "media_plugin_headers",
],
static_libs: ["libyuv_static"],
diff --git a/media/libstagefright/filters/Android.bp b/media/libstagefright/filters/Android.bp
index acc9e87..b46a271 100644
--- a/media/libstagefright/filters/Android.bp
+++ b/media/libstagefright/filters/Android.bp
@@ -22,10 +22,6 @@
"ZeroFilter.cpp",
],
- include_dirs: [
- "frameworks/native/include/media/openmax",
- ],
-
cflags: [
"-Wno-multichar",
"-Werror",
diff --git a/media/libstagefright/foundation/Android.bp b/media/libstagefright/foundation/Android.bp
index dd2c66f..5f86c22 100644
--- a/media/libstagefright/foundation/Android.bp
+++ b/media/libstagefright/foundation/Android.bp
@@ -33,18 +33,13 @@
},
host_supported: true,
double_loadable: true,
- include_dirs: [
- "frameworks/av/include",
- "frameworks/native/include",
- "frameworks/native/libs/arect/include",
- "frameworks/native/libs/nativebase/include",
- ],
local_include_dirs: [
"include/media/stagefright/foundation",
],
header_libs: [
+ "av-headers",
// this is only needed for the vendor variant that removes libbinder, but vendor
// target below does not allow adding header_libs.
"libbinder_headers",
diff --git a/media/libstagefright/foundation/tests/AVCUtils/Android.bp b/media/libstagefright/foundation/tests/AVCUtils/Android.bp
index 594da56..ee7db21 100644
--- a/media/libstagefright/foundation/tests/AVCUtils/Android.bp
+++ b/media/libstagefright/foundation/tests/AVCUtils/Android.bp
@@ -43,10 +43,6 @@
"libstagefright_foundation",
],
- include_dirs: [
- "frameworks/av/media/libstagefright/foundation",
- ],
-
cflags: [
"-Werror",
"-Wall",
diff --git a/media/libstagefright/foundation/tests/Android.bp b/media/libstagefright/foundation/tests/Android.bp
index e50742e..e72ce43 100644
--- a/media/libstagefright/foundation/tests/Android.bp
+++ b/media/libstagefright/foundation/tests/Android.bp
@@ -18,10 +18,6 @@
"-Wall",
],
- include_dirs: [
- "frameworks/av/include",
- ],
-
shared_libs: [
"liblog",
"libstagefright_foundation",
diff --git a/media/libstagefright/tests/HEVC/Android.bp b/media/libstagefright/tests/HEVC/Android.bp
index 91bf385..7a0ba52 100644
--- a/media/libstagefright/tests/HEVC/Android.bp
+++ b/media/libstagefright/tests/HEVC/Android.bp
@@ -44,10 +44,6 @@
"libstagefright_foundation",
],
- include_dirs: [
- "frameworks/av/media/libstagefright",
- ],
-
cflags: [
"-Werror",
"-Wall",
diff --git a/media/libstagefright/tests/HEVC/HEVCUtilsUnitTest.cpp b/media/libstagefright/tests/HEVC/HEVCUtilsUnitTest.cpp
index 324a042..c43e1f8 100644
--- a/media/libstagefright/tests/HEVC/HEVCUtilsUnitTest.cpp
+++ b/media/libstagefright/tests/HEVC/HEVCUtilsUnitTest.cpp
@@ -21,7 +21,7 @@
#include <fstream>
#include <media/stagefright/foundation/ABitReader.h>
-#include "include/HevcUtils.h"
+#include <HevcUtils.h>
#include "HEVCUtilsTestEnvironment.h"
diff --git a/media/libstagefright/tests/extractorFactory/Android.bp b/media/libstagefright/tests/extractorFactory/Android.bp
index 13d5b89..a067284 100644
--- a/media/libstagefright/tests/extractorFactory/Android.bp
+++ b/media/libstagefright/tests/extractorFactory/Android.bp
@@ -51,10 +51,6 @@
"libstagefright_foundation",
],
- include_dirs: [
- "frameworks/av/media/libstagefright",
- ],
-
// TODO: (b/150181583)
compile_multilib: "first",
diff --git a/media/libstagefright/tests/fuzzers/Android.bp b/media/libstagefright/tests/fuzzers/Android.bp
index ea17a4d..250ffb9 100644
--- a/media/libstagefright/tests/fuzzers/Android.bp
+++ b/media/libstagefright/tests/fuzzers/Android.bp
@@ -74,6 +74,7 @@
srcs: [
"FrameDecoderFuzzer.cpp",
],
+ corpus: ["corpus/*"],
defaults: ["libstagefright_fuzzer_defaults"],
}
diff --git a/media/libstagefright/tests/fuzzers/FrameDecoderFuzzer.cpp b/media/libstagefright/tests/fuzzers/FrameDecoderFuzzer.cpp
index c251479..b346718 100644
--- a/media/libstagefright/tests/fuzzers/FrameDecoderFuzzer.cpp
+++ b/media/libstagefright/tests/fuzzers/FrameDecoderFuzzer.cpp
@@ -46,12 +46,15 @@
}
while (fdp.remaining_bytes()) {
- switch (fdp.ConsumeIntegralInRange<uint8_t>(0, 3)) {
- case 0:
- decoder->init(/*frameTimeUs*/ fdp.ConsumeIntegral<int64_t>(),
- /*option*/ fdp.ConsumeIntegral<int>(),
- /*colorFormat*/ fdp.ConsumeIntegral<int>());
+ uint8_t switchCase = fdp.ConsumeIntegralInRange<uint8_t>(0, 3);
+ switch (switchCase) {
+ case 0: {
+ int64_t frameTimeUs = fdp.ConsumeIntegral<int64_t>();
+ int option = fdp.ConsumeIntegral<int>();
+ int colorFormat = fdp.ConsumeIntegral<int>();
+ decoder->init(frameTimeUs, option, colorFormat);
break;
+ }
case 1:
decoder->extractFrame();
break;
diff --git a/media/libstagefright/tests/fuzzers/corpus/color_format_rgb_565.dat b/media/libstagefright/tests/fuzzers/corpus/color_format_rgb_565.dat
new file mode 100644
index 0000000..698e21d
--- /dev/null
+++ b/media/libstagefright/tests/fuzzers/corpus/color_format_rgb_565.dat
Binary files differ
diff --git a/media/libstagefright/tests/writer/Android.bp b/media/libstagefright/tests/writer/Android.bp
index 38d5ecc..49fb569 100644
--- a/media/libstagefright/tests/writer/Android.bp
+++ b/media/libstagefright/tests/writer/Android.bp
@@ -52,10 +52,6 @@
"libogg",
],
- include_dirs: [
- "frameworks/av/media/libstagefright",
- ],
-
cflags: [
"-Werror",
"-Wall",
diff --git a/media/libstagefright/tests/writer/WriterTest.cpp b/media/libstagefright/tests/writer/WriterTest.cpp
index d170e7c..398c592 100644
--- a/media/libstagefright/tests/writer/WriterTest.cpp
+++ b/media/libstagefright/tests/writer/WriterTest.cpp
@@ -36,7 +36,7 @@
#include <media/stagefright/MPEG2TSWriter.h>
#include <media/stagefright/MPEG4Writer.h>
#include <media/stagefright/OggWriter.h>
-#include <webm/WebmWriter.h>
+#include <WebmWriter.h>
#include "WriterTestEnvironment.h"
#include "WriterUtility.h"
diff --git a/media/libstagefright/webm/Android.bp b/media/libstagefright/webm/Android.bp
index 32a22ba..4209aea 100644
--- a/media/libstagefright/webm/Android.bp
+++ b/media/libstagefright/webm/Android.bp
@@ -33,7 +33,7 @@
"WebmWriter.cpp",
],
- include_dirs: ["frameworks/av/include"],
+ export_include_dirs: ["."],
shared_libs: [
"libdatasource",
@@ -44,6 +44,7 @@
],
header_libs: [
+ "av-headers",
"libmedia_headers",
"media_ndk_headers",
],
diff --git a/media/utils/Android.bp b/media/utils/Android.bp
index 6e29ac8..88b822d 100644
--- a/media/utils/Android.bp
+++ b/media/utils/Android.bp
@@ -72,7 +72,6 @@
export_shared_lib_headers: [
"libpermission",
- "packagemanager_aidl-cpp",
],
include_dirs: [
diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp
index 9c7b863..9620d24 100644
--- a/media/utils/ServiceUtilities.cpp
+++ b/media/utils/ServiceUtilities.cpp
@@ -71,6 +71,7 @@
switch (source) {
case AUDIO_SOURCE_HOTWORD:
return AppOpsManager::OP_RECORD_AUDIO_HOTWORD;
+ case AUDIO_SOURCE_ECHO_REFERENCE: // fallthrough
case AUDIO_SOURCE_REMOTE_SUBMIX:
return AppOpsManager::OP_RECORD_AUDIO_OUTPUT;
case AUDIO_SOURCE_VOICE_DOWNLINK:
diff --git a/media/utils/fuzzers/Android.bp b/media/utils/fuzzers/Android.bp
index c1698dc..c4dc24f 100644
--- a/media/utils/fuzzers/Android.bp
+++ b/media/utils/fuzzers/Android.bp
@@ -18,6 +18,7 @@
"libutils",
"libbinder",
"framework-permission-aidl-cpp",
+ "packagemanager_aidl-cpp",
],
cflags: [
diff --git a/services/audioflinger/Android.bp b/services/audioflinger/Android.bp
index f401fff..763c070 100644
--- a/services/audioflinger/Android.bp
+++ b/services/audioflinger/Android.bp
@@ -101,7 +101,6 @@
export_shared_lib_headers: [
"libpermission",
- "packagemanager_aidl-cpp",
],
cflags: [
diff --git a/services/audioflinger/FastMixer.cpp b/services/audioflinger/FastMixer.cpp
index fc34d95..26bd92d 100644
--- a/services/audioflinger/FastMixer.cpp
+++ b/services/audioflinger/FastMixer.cpp
@@ -89,6 +89,7 @@
// TODO: Add channel mask to NBAIO_Format.
// We assume that the channel mask must be a valid positional channel mask.
mSinkChannelMask = getChannelMaskFromCount(mSinkChannelCount);
+ mBalance.setChannelMask(mSinkChannelMask);
unsigned i;
for (i = 0; i < FastMixerState::sMaxFastTracks; ++i) {
diff --git a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
index 58d05c6..b444fd7 100644
--- a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
@@ -43,7 +43,7 @@
DeviceDescriptor(const AudioDeviceTypeAddr &deviceTypeAddr, const std::string &tagName = "",
const FormatVector &encodedFormats = FormatVector{});
- virtual ~DeviceDescriptor() {}
+ virtual ~DeviceDescriptor() = default;
virtual void addAudioProfile(const sp<AudioProfile> &profile) {
addAudioProfileAndSort(mProfiles, profile);
@@ -51,8 +51,6 @@
virtual const std::string getTagName() const { return mTagName; }
- const FormatVector& encodedFormats() const { return mEncodedFormats; }
-
audio_format_t getEncodedFormat() { return mCurrentEncodedFormat; }
void setEncodedFormat(audio_format_t format) {
@@ -63,8 +61,6 @@
bool hasCurrentEncodedFormat() const;
- bool supportsFormat(audio_format_t format);
-
void setDynamic() { mIsDynamic = true; }
bool isDynamic() const { return mIsDynamic; }
@@ -106,7 +102,6 @@
}
std::string mTagName; // Unique human readable identifier for a device port found in conf file.
- FormatVector mEncodedFormats;
audio_format_t mCurrentEncodedFormat;
bool mIsDynamic = false;
const std::string mDeclaredAddress; // Original device address
diff --git a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
index 81828ed..0e1548f 100644
--- a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
+++ b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
@@ -37,9 +37,7 @@
public:
IOProfile(const std::string &name, audio_port_role_t role)
: AudioPort(name, AUDIO_PORT_TYPE_MIX, role),
- maxOpenCount(1),
curOpenCount(0),
- maxActiveCount(1),
curActiveCount(0) {}
virtual ~IOProfile() = default;
@@ -194,21 +192,11 @@
return false;
}
- // Maximum number of input or output streams that can be simultaneously opened for this profile.
- // By convention 0 means no limit. To respect legacy behavior, initialized to 1 for output
- // profiles and 0 for input profiles
- uint32_t maxOpenCount;
// Number of streams currently opened for this profile.
uint32_t curOpenCount;
- // Maximum number of input or output streams that can be simultaneously active for this profile.
- // By convention 0 means no limit. To respect legacy behavior, initialized to 0 for output
- // profiles and 1 for input profiles
- uint32_t maxActiveCount;
// Number of streams currently active for this profile. This is not the number of active clients
// (AudioTrack or AudioRecord) but the number of active HAL streams.
uint32_t curActiveCount;
- // Mute duration while changing device on this output profile.
- uint32_t recommendedMuteDurationMs = 0;
private:
DeviceVector mSupportedDevices; // supported devices: this input/output can be routed from/to
diff --git a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
index c9c8ede..4a4ee12 100644
--- a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
@@ -54,7 +54,7 @@
DeviceDescriptor::DeviceDescriptor(const AudioDeviceTypeAddr &deviceTypeAddr,
const std::string &tagName,
const FormatVector &encodedFormats) :
- DeviceDescriptorBase(deviceTypeAddr), mTagName(tagName), mEncodedFormats(encodedFormats),
+ DeviceDescriptorBase(deviceTypeAddr, encodedFormats), mTagName(tagName),
mDeclaredAddress(DeviceDescriptorBase::address())
{
mCurrentEncodedFormat = AUDIO_FORMAT_DEFAULT;
@@ -109,20 +109,6 @@
return (mCurrentEncodedFormat != AUDIO_FORMAT_DEFAULT);
}
-bool DeviceDescriptor::supportsFormat(audio_format_t format)
-{
- if (mEncodedFormats.empty()) {
- return true;
- }
-
- for (const auto& devFormat : mEncodedFormats) {
- if (devFormat == format) {
- return true;
- }
- }
- return false;
-}
-
status_t DeviceDescriptor::applyAudioPortConfig(const struct audio_port_config *config,
audio_port_config *backupConfig)
{
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index a46da41..6221c05 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -5457,7 +5457,8 @@
if (!desc->isDuplicated()) {
// exact match on device
if (device_distinguishes_on_address(deviceType) && desc->supportsDevice(device)
- && desc->containsSingleDeviceSupportingEncodedFormats(device)) {
+ && desc->containsSingleDeviceSupportingEncodedFormats(device)
+ && !mAvailableOutputDevices.containsAtLeastOne(desc->supportedDevices())) {
outputs.add(mOutputs.keyAt(i));
} else if (!mAvailableOutputDevices.containsAtLeastOne(desc->supportedDevices())) {
ALOGV("checkOutputsForDevice(): disconnecting adding output %d",
diff --git a/services/audiopolicy/service/Spatializer.cpp b/services/audiopolicy/service/Spatializer.cpp
index 502a8d0..0fdbe20 100644
--- a/services/audiopolicy/service/Spatializer.cpp
+++ b/services/audiopolicy/service/Spatializer.cpp
@@ -627,6 +627,9 @@
status_t Spatializer::attachOutput(audio_io_handle_t output) {
std::shared_ptr<SpatializerPoseController> poseController;
+ bool outputChanged = false;
+ sp<media::INativeSpatializerCallback> callback;
+
{
std::lock_guard lock(mLock);
ALOGV("%s output %d mOutput %d", __func__, (int)output, (int)mOutput);
@@ -654,6 +657,7 @@
std::vector<SpatializerHeadTrackingMode>{mActualHeadTrackingMode});
mEngine->setEnabled(true);
+ outputChanged = mOutput != output;
mOutput = output;
if (mSupportsHeadTracking) {
@@ -668,26 +672,42 @@
mPoseController->setDisplayOrientation(mDisplayOrientation);
poseController = mPoseController;
}
+ callback = mSpatializerCallback;
}
if (poseController != nullptr) {
poseController->waitUntilCalculated();
}
+
+ if (outputChanged && callback != nullptr) {
+ callback->onOutputChanged(output);
+ }
+
return NO_ERROR;
}
audio_io_handle_t Spatializer::detachOutput() {
- std::lock_guard lock(mLock);
- ALOGV("%s mOutput %d", __func__, (int)mOutput);
audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
- if (mOutput == AUDIO_IO_HANDLE_NONE) {
- return output;
+ sp<media::INativeSpatializerCallback> callback;
+
+ {
+ std::lock_guard lock(mLock);
+ ALOGV("%s mOutput %d", __func__, (int)mOutput);
+ if (mOutput == AUDIO_IO_HANDLE_NONE) {
+ return output;
+ }
+ // remove FX instance
+ mEngine->setEnabled(false);
+ mEngine.clear();
+ output = mOutput;
+ mOutput = AUDIO_IO_HANDLE_NONE;
+ mPoseController.reset();
+
+ callback = mSpatializerCallback;
}
- // remove FX instance
- mEngine->setEnabled(false);
- mEngine.clear();
- output = mOutput;
- mOutput = AUDIO_IO_HANDLE_NONE;
- mPoseController.reset();
+
+ if (callback != nullptr) {
+ callback->onOutputChanged(AUDIO_IO_HANDLE_NONE);
+ }
return output;
}
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 6c6e938..425c50d 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -137,6 +137,7 @@
static constexpr int32_t kVendorClientState = ActivityManager::PROCESS_STATE_PERSISTENT_UI;
const String8 CameraService::kOfflineDevice("offline-");
+const String16 CameraService::kWatchAllClientsFlag("all");
// Set to keep track of logged service error events.
static std::set<String8> sServiceErrorEventSet;
@@ -1795,7 +1796,8 @@
LOG_ALWAYS_FATAL_IF(client.get() == nullptr, "%s: CameraService in invalid state",
__FUNCTION__);
- err = client->initialize(mCameraProviderManager, mMonitorTags);
+ String8 monitorTags = isClientWatched(client.get()) ? mMonitorTags : String8("");
+ err = client->initialize(mCameraProviderManager, monitorTags);
if (err != OK) {
ALOGE("%s: Could not initialize client from HAL.", __FUNCTION__);
// Errors could be from the HAL module open call or from AppOpsManager
@@ -1843,10 +1845,9 @@
// Set rotate-and-crop override behavior
if (mOverrideRotateAndCropMode != ANDROID_SCALER_ROTATE_AND_CROP_AUTO) {
client->setRotateAndCropOverride(mOverrideRotateAndCropMode);
- } else if ((effectiveApiLevel == API_2) &&
- CameraServiceProxyWrapper::isRotateAndCropOverrideNeeded(clientPackageName,
- orientation, facing) ) {
- client->setRotateAndCropOverride(ANDROID_SCALER_ROTATE_AND_CROP_90);
+ } else if (effectiveApiLevel == API_2) {
+ client->setRotateAndCropOverride(CameraServiceProxyWrapper::getRotateAndCropOverride(
+ clientPackageName, facing));
}
// Set camera muting behavior
@@ -1962,7 +1963,8 @@
return BAD_VALUE;
}
- auto err = offlineClient->initialize(mCameraProviderManager, mMonitorTags);
+ String8 monitorTags = isClientWatched(offlineClient.get()) ? mMonitorTags : String8("");
+ auto err = offlineClient->initialize(mCameraProviderManager, monitorTags);
if (err != OK) {
ALOGE("%s: Could not initialize offline client.", __FUNCTION__);
return err;
@@ -2248,13 +2250,9 @@
if (current != nullptr) {
const auto basicClient = current->getValue();
if (basicClient.get() != nullptr && basicClient->canCastToApiClient(API_2)) {
- if (CameraServiceProxyWrapper::isRotateAndCropOverrideNeeded(
- basicClient->getPackageName(), basicClient->getCameraOrientation(),
- basicClient->getCameraFacing())) {
- basicClient->setRotateAndCropOverride(ANDROID_SCALER_ROTATE_AND_CROP_90);
- } else {
- basicClient->setRotateAndCropOverride(ANDROID_SCALER_ROTATE_AND_CROP_NONE);
- }
+ basicClient->setRotateAndCropOverride(
+ CameraServiceProxyWrapper::getRotateAndCropOverride(
+ basicClient->getPackageName(), basicClient->getCameraFacing()));
}
}
}
@@ -2632,6 +2630,7 @@
for (auto& i : mActiveClientManager.getAll()) {
auto clientSp = i->getValue();
if (clientSp.get() == client) {
+ cacheClientTagDumpIfNeeded(client->mCameraIdStr, clientSp.get());
mActiveClientManager.remove(i);
}
}
@@ -2708,7 +2707,11 @@
return sp<BasicClient>{nullptr};
}
- return clientDescriptorPtr->getValue();
+ sp<BasicClient> client = clientDescriptorPtr->getValue();
+ if (client.get() != nullptr) {
+ cacheClientTagDumpIfNeeded(clientDescriptorPtr->getKey(), client.get());
+ }
+ return client;
}
void CameraService::doUserSwitch(const std::vector<int32_t>& newUserIds) {
@@ -3127,6 +3130,21 @@
return OK;
}
+status_t CameraService::BasicClient::startWatchingTags(const String8&, int) {
+ // Can't watch tags directly, must go through CameraService::startWatchingTags
+ return OK;
+}
+
+status_t CameraService::BasicClient::stopWatchingTags(int) {
+ // Can't watch tags directly, must go through CameraService::stopWatchingTags
+ return OK;
+}
+
+status_t CameraService::BasicClient::dumpWatchedEventsToVector(std::vector<std::string> &) {
+ // Can't watch tags directly, must go through CameraService::dumpWatchedEventsToVector
+ return OK;
+}
+
String16 CameraService::BasicClient::getPackageName() const {
return mClientPackageName;
}
@@ -4148,7 +4166,7 @@
// Dump camera traces if there were any
dprintf(fd, "\n");
- camera3::CameraTraces::dump(fd, args);
+ camera3::CameraTraces::dump(fd);
// Process dump arguments, if any
int n = args.size();
@@ -4242,6 +4260,30 @@
dprintf(fd, "\n");
}
+void CameraService::cacheClientTagDumpIfNeeded(const char *cameraId, BasicClient* client) {
+ Mutex::Autolock lock(mLogLock);
+ if (!isClientWatchedLocked(client)) { return; }
+
+ std::vector<std::string> dumpVector;
+ client->dumpWatchedEventsToVector(dumpVector);
+
+ if (dumpVector.empty()) { return; }
+
+ std::string dumpString;
+ size_t i = dumpVector.size();
+
+ // Store the string in reverse order (latest last)
+ while (i > 0) {
+ i--;
+ dumpString += cameraId;
+ dumpString += ":";
+ dumpString += dumpVector[i]; // implicitly ends with '\n'
+ }
+
+ const String16 &packageName = client->getPackageName();
+ mWatchedClientsDumpCache[packageName] = dumpString;
+}
+
void CameraService::handleTorchClientBinderDied(const wp<IBinder> &who) {
Mutex::Autolock al(mTorchClientMapMutex);
for (size_t i = 0; i < mTorchClientMap.size(); i++) {
@@ -4546,9 +4588,11 @@
return handleGetImageDumpMask(out);
} else if (args.size() >= 2 && args[0] == String16("set-camera-mute")) {
return handleSetCameraMute(args);
+ } else if (args.size() >= 2 && args[0] == String16("watch")) {
+ return handleWatchCommand(args, out);
} else if (args.size() == 1 && args[0] == String16("help")) {
printHelp(out);
- return NO_ERROR;
+ return OK;
}
printHelp(err);
return BAD_VALUE;
@@ -4692,6 +4736,233 @@
return OK;
}
+status_t CameraService::handleWatchCommand(const Vector<String16>& args, int outFd) {
+ if (args.size() >= 3 && args[1] == String16("start")) {
+ return startWatchingTags(args, outFd);
+ } else if (args.size() == 2 && args[1] == String16("dump")) {
+ return camera3::CameraTraces::dump(outFd);
+ } else if (args.size() == 2 && args[1] == String16("stop")) {
+ return stopWatchingTags(outFd);
+ } else if (args.size() >= 2 && args[1] == String16("print")) {
+ return printWatchedTags(args, outFd);
+ }
+ dprintf(outFd, "Camera service watch commands:\n"
+ " start -m <comma_separated_tag_list> [-c <comma_separated_client_list>]\n"
+ " starts watching the provided tags for clients with provided package\n"
+ " recognizes tag shorthands like '3a'\n"
+ " watches all clients if no client is passed, or if 'all' is listed\n"
+ " dump dumps camera trace\n"
+ " stop stops watching all tags\n"
+ " print [-n <refresh_interval_ms>]\n"
+ " prints the monitored information in real time\n"
+ " Hit Ctrl+C to exit\n");
+ return BAD_VALUE;
+}
+
+status_t CameraService::startWatchingTags(const Vector<String16> &args, int outFd) {
+ Mutex::Autolock lock(mLogLock);
+ size_t tagsIdx; // index of '-m'
+ String16 tags("");
+ for (tagsIdx = 2; tagsIdx < args.size() && args[tagsIdx] != String16("-m"); tagsIdx++);
+ if (tagsIdx < args.size() - 1) {
+ tags = args[tagsIdx + 1];
+ } else {
+ dprintf(outFd, "No tags provided.\n");
+ return BAD_VALUE;
+ }
+
+ size_t clientsIdx; // index of '-c'
+ String16 clients = kWatchAllClientsFlag; // watch all clients if no clients are provided
+ for (clientsIdx = 2; clientsIdx < args.size() && args[clientsIdx] != String16("-c");
+ clientsIdx++);
+ if (clientsIdx < args.size() - 1) {
+ clients = args[clientsIdx + 1];
+ }
+ parseClientsToWatchLocked(String8(clients));
+
+ // track tags to initialize future clients with the monitoring information
+ mMonitorTags = String8(tags);
+
+ bool serviceLock = tryLock(mServiceLock);
+ int numWatchedClients = 0;
+ auto cameraClients = mActiveClientManager.getAll();
+ for (const auto &clientDescriptor: cameraClients) {
+ if (clientDescriptor == nullptr) { continue; }
+ sp<BasicClient> client = clientDescriptor->getValue();
+ if (client.get() == nullptr) { continue; }
+
+ if (isClientWatchedLocked(client.get())) {
+ client->startWatchingTags(mMonitorTags, outFd);
+ numWatchedClients++;
+ }
+ }
+ dprintf(outFd, "Started watching %d active clients\n", numWatchedClients);
+
+ if (serviceLock) { mServiceLock.unlock(); }
+ return OK;
+}
+
+status_t CameraService::stopWatchingTags(int outFd) {
+ // clear mMonitorTags to prevent new clients from monitoring tags at initialization
+ Mutex::Autolock lock(mLogLock);
+ mMonitorTags = String8::empty();
+
+ mWatchedClientPackages.clear();
+ mWatchedClientsDumpCache.clear();
+
+ bool serviceLock = tryLock(mServiceLock);
+ auto cameraClients = mActiveClientManager.getAll();
+ for (const auto &clientDescriptor : cameraClients) {
+ if (clientDescriptor == nullptr) { continue; }
+ sp<BasicClient> client = clientDescriptor->getValue();
+ if (client.get() == nullptr) { continue; }
+ client->stopWatchingTags(outFd);
+ }
+ dprintf(outFd, "Stopped watching all clients.\n");
+ if (serviceLock) { mServiceLock.unlock(); }
+ return OK;
+}
+
+status_t CameraService::printWatchedTags(const Vector<String16> &args, int outFd) {
+ // Figure outFd refresh interval, if present in args
+ useconds_t refreshTimeoutMs = 1000; // refresh every 1s by default
+ if (args.size() > 2) {
+ size_t intervalIdx; // index of '-n'
+ for (intervalIdx = 2; intervalIdx < args.size() && String16("-n") != args[intervalIdx];
+ intervalIdx++);
+
+ size_t intervalValIdx = intervalIdx + 1;
+ if (intervalValIdx < args.size()) {
+ refreshTimeoutMs = strtol(String8(args[intervalValIdx].string()), nullptr, 10);
+ if (errno) { return BAD_VALUE; }
+ }
+ }
+
+ mLogLock.lock();
+ bool serviceLock = tryLock(mServiceLock);
+ // get all watched clients that are currently connected
+ std::set<String16> connectedMoniterdClients;
+ for (const auto &clientDescriptor: mActiveClientManager.getAll()) {
+ if (clientDescriptor == nullptr) { continue; }
+
+ sp<BasicClient> client = clientDescriptor->getValue();
+ if (client.get() == nullptr) { continue; }
+ if (!isClientWatchedLocked(client.get())) { continue; }
+
+ connectedMoniterdClients.emplace(client->getPackageName());
+ }
+ if (serviceLock) { mServiceLock.unlock(); }
+
+ // Print entries in mWatchedClientsDumpCache for clients that are not connected
+ for (const auto &kv: mWatchedClientsDumpCache) {
+ const String16 &package = kv.first;
+ if (connectedMoniterdClients.find(package) != connectedMoniterdClients.end()) {
+ continue;
+ }
+
+ dprintf(outFd, "Client: %s\n", String8(package).string());
+ dprintf(outFd, "%s\n", kv.second.c_str());
+ }
+ mLogLock.unlock();
+
+ if (connectedMoniterdClients.empty()) {
+ dprintf(outFd, "No watched client active.\n");
+ return OK;
+ }
+
+ // For connected watched clients, print monitored tags live
+ return printWatchedTagsUntilInterrupt(refreshTimeoutMs * 1000, outFd);
+}
+
+status_t CameraService::printWatchedTagsUntilInterrupt(useconds_t refreshMicros, int outFd) {
+ std::unordered_map<std::string, std::string> cameraToLastEvent;
+ auto cameraClients = mActiveClientManager.getAll();
+
+ if (cameraClients.empty()) {
+ dprintf(outFd, "No clients connected.\n");
+ return OK;
+ }
+
+ dprintf(outFd, "Press Ctrl + C to exit...\n\n");
+ while (true) {
+ for (const auto& clientDescriptor : cameraClients) {
+ Mutex::Autolock lock(mLogLock);
+ if (clientDescriptor == nullptr) { continue; }
+ const char* cameraId = clientDescriptor->getKey().string();
+
+ // This also initializes the map entries with an empty string
+ const std::string& lastPrintedEvent = cameraToLastEvent[cameraId];
+
+ sp<BasicClient> client = clientDescriptor->getValue();
+ if (client.get() == nullptr) { continue; }
+ if (!isClientWatchedLocked(client.get())) { continue; }
+
+ std::vector<std::string> latestEvents;
+ client->dumpWatchedEventsToVector(latestEvents);
+
+ if (!latestEvents.empty()) {
+ printNewWatchedEvents(outFd,
+ cameraId,
+ client->getPackageName(),
+ latestEvents,
+ lastPrintedEvent);
+ cameraToLastEvent[cameraId] = latestEvents[0];
+ }
+ }
+ usleep(refreshMicros); // convert ms to us
+ }
+ return OK;
+}
+
+void CameraService::printNewWatchedEvents(int outFd,
+ const char *cameraId,
+ const String16 &packageName,
+ const std::vector<std::string> &events,
+ const std::string &lastPrintedEvent) {
+ if (events.empty()) { return; }
+
+ // index of lastPrintedEvent in events.
+ // lastPrintedIdx = events.size() if lastPrintedEvent is not in events
+ size_t lastPrintedIdx;
+ for (lastPrintedIdx = 0;
+ lastPrintedIdx < events.size() && lastPrintedEvent != events[lastPrintedIdx];
+ lastPrintedIdx++);
+
+ if (lastPrintedIdx == 0) { return; } // early exit if no new event in `events`
+
+ const char *printPackageName = String8(packageName).string();
+ // print events in chronological order (latest event last)
+ size_t idxToPrint = lastPrintedIdx;
+ do {
+ idxToPrint--;
+ dprintf(outFd, "%s:%s %s", cameraId, printPackageName, events[idxToPrint].c_str());
+ } while (idxToPrint != 0);
+}
+
+void CameraService::parseClientsToWatchLocked(String8 clients) {
+ mWatchedClientPackages.clear();
+
+ const char *allSentinel = String8(kWatchAllClientsFlag).string();
+
+ char *tokenized = clients.lockBuffer(clients.size());
+ char *savePtr;
+ char *nextClient = strtok_r(tokenized, ",", &savePtr);
+
+ while (nextClient != nullptr) {
+ if (strcmp(nextClient, allSentinel) == 0) {
+ // Don't need to track any other package if 'all' is present
+ mWatchedClientPackages.clear();
+ mWatchedClientPackages.emplace(kWatchAllClientsFlag);
+ break;
+ }
+
+ // track package names
+ mWatchedClientPackages.emplace(nextClient);
+ nextClient = strtok_r(nullptr, ",", &savePtr);
+ }
+ clients.unlockBuffer();
+}
+
status_t CameraService::printHelp(int out) {
return dprintf(out, "Camera service commands:\n"
" get-uid-state <PACKAGE> [--user USER_ID] gets the uid state\n"
@@ -4704,9 +4975,20 @@
" Valid values 0=OFF, 1=ON for JPEG\n"
" get-image-dump-mask returns the current image-dump-mask value\n"
" set-camera-mute <0/1> enable or disable camera muting\n"
+ " watch <start|stop|dump|live> manages tag monitoring in connected clients\n"
" help print this message\n");
}
+bool CameraService::isClientWatched(const BasicClient *client) {
+ Mutex::Autolock lock(mLogLock);
+ return isClientWatchedLocked(client);
+}
+
+bool CameraService::isClientWatchedLocked(const BasicClient *client) {
+ return mWatchedClientPackages.find(kWatchAllClientsFlag) != mWatchedClientPackages.end() ||
+ mWatchedClientPackages.find(client->getPackageName()) != mWatchedClientPackages.end();
+}
+
int32_t CameraService::updateAudioRestriction() {
Mutex::Autolock lock(mServiceLock);
return updateAudioRestrictionLocked();
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 7f18794..cb26763 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -280,6 +280,10 @@
// Internal dump method to be called by CameraService
virtual status_t dumpClient(int fd, const Vector<String16>& args) = 0;
+ virtual status_t startWatchingTags(const String8 &tags, int outFd);
+ virtual status_t stopWatchingTags(int outFd);
+ virtual status_t dumpWatchedEventsToVector(std::vector<std::string> &out);
+
// Return the package name for this client
virtual String16 getPackageName() const;
@@ -833,6 +837,14 @@
RingBuffer<String8> mEventLog;
Mutex mLogLock;
+ // set of client package names to watch. if this set contains 'all', then all clients will
+ // be watched. Access should be guarded by mLogLock
+ std::set<String16> mWatchedClientPackages;
+ // cache of last monitored tags dump immediately before the client disconnects. If a client
+ // re-connects, its entry is not updated until it disconnects again. Access should be guarded
+ // by mLogLock
+ std::map<String16, std::string> mWatchedClientsDumpCache;
+
// The last monitored tags set by client
String8 mMonitorTags;
@@ -965,6 +977,8 @@
*/
void dumpEventLog(int fd);
+ void cacheClientTagDumpIfNeeded(const char *cameraId, BasicClient *client);
+
/**
* This method will acquire mServiceLock
*/
@@ -1157,9 +1171,47 @@
// Set the camera mute state
status_t handleSetCameraMute(const Vector<String16>& args);
+ // Handle 'watch' command as passed through 'cmd'
+ status_t handleWatchCommand(const Vector<String16> &args, int outFd);
+
+ // Enable tag monitoring of the given tags in provided clients
+ status_t startWatchingTags(const Vector<String16> &args, int outFd);
+
+ // Disable tag monitoring
+ status_t stopWatchingTags(int outFd);
+
+ // Print events of monitored tags in all cached and attached clients
+ status_t printWatchedTags(const Vector<String16> &args, int outFd);
+
+ // Print events of monitored tags in all attached clients as they are captured. New events are
+ // fetched every `refreshMicros` us
+ // NOTE: This function does not terminate unless interrupted.
+ status_t printWatchedTagsUntilInterrupt(useconds_t refreshMicros, int outFd);
+
+ // Print all events in vector `events' that came after lastPrintedEvent
+ static void printNewWatchedEvents(int outFd,
+ const char *cameraId,
+ const String16 &packageName,
+ const std::vector<std::string> &events,
+ const std::string &lastPrintedEvent);
+
+ // Parses comma separated clients list and adds them to mWatchedClientPackages.
+ // Does not acquire mLogLock before modifying mWatchedClientPackages. It is the caller's
+ // responsibility to acquire mLogLock before calling this function.
+ void parseClientsToWatchLocked(String8 clients);
+
// Prints the shell command help
status_t printHelp(int out);
+ // Returns true if client should monitor tags based on the contents of mWatchedClientPackages.
+ // Acquires mLogLock before querying mWatchedClientPackages.
+ bool isClientWatched(const BasicClient *client);
+
+ // Returns true if client should monitor tags based on the contents of mWatchedClientPackages.
+ // Does not acquire mLogLock before querying mWatchedClientPackages. It is the caller's
+ // responsibility to acquire mLogLock before calling this functions.
+ bool isClientWatchedLocked(const BasicClient *client);
+
/**
* Get the current system time as a formatted string.
*/
@@ -1190,6 +1242,10 @@
// Use separate keys for offline devices.
static const String8 kOfflineDevice;
+ // Sentinel value to be stored in `mWatchedClientsPackages` to indicate that all clients should
+ // be watched.
+ static const String16 kWatchAllClientsFlag;
+
// TODO: right now each BasicClient holds one AppOpsManager instance.
// We can refactor the code so all of clients share this instance
AppOpsManager mAppOps;
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 1f3d478..67ec150 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -1797,6 +1797,35 @@
return dumpDevice(fd, args);
}
+status_t CameraDeviceClient::startWatchingTags(const String8 &tags, int out) {
+ sp<CameraDeviceBase> device = mDevice;
+ if (!device) {
+ dprintf(out, " Device is detached.");
+ return OK;
+ }
+ device->startWatchingTags(tags);
+ return OK;
+}
+
+status_t CameraDeviceClient::stopWatchingTags(int out) {
+ sp<CameraDeviceBase> device = mDevice;
+ if (!device) {
+ dprintf(out, " Device is detached.");
+ return OK;
+ }
+ device->stopWatchingTags();
+ return OK;
+}
+
+status_t CameraDeviceClient::dumpWatchedEventsToVector(std::vector<std::string> &out) {
+ sp<CameraDeviceBase> device = mDevice;
+ if (!device) {
+ return OK;
+ }
+ device->dumpWatchedEventsToVector(out);
+ return OK;
+}
+
void CameraDeviceClient::notifyError(int32_t errorCode,
const CaptureResultExtras& resultExtras) {
// Thread safe. Don't bother locking.
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 76b3f53..288f2d7 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -199,6 +199,10 @@
virtual status_t dumpClient(int fd, const Vector<String16>& args);
+ virtual status_t startWatchingTags(const String8 &tags, int out);
+ virtual status_t stopWatchingTags(int out);
+ virtual status_t dumpWatchedEventsToVector(std::vector<std::string> &out);
+
/**
* Device listener interface
*/
diff --git a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
index 652842b..10fa33f 100644
--- a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
@@ -110,6 +110,18 @@
return OK;
}
+status_t CameraOfflineSessionClient::startWatchingTags(const String8 &tags, int outFd) {
+ return BasicClient::startWatchingTags(tags, outFd);
+}
+
+status_t CameraOfflineSessionClient::stopWatchingTags(int outFd) {
+ return BasicClient::stopWatchingTags(outFd);
+}
+
+status_t CameraOfflineSessionClient::dumpWatchedEventsToVector(std::vector<std::string> &out) {
+ return BasicClient::dumpWatchedEventsToVector(out);
+}
+
binder::Status CameraOfflineSessionClient::disconnect() {
Mutex::Autolock icl(mBinderSerializationLock);
diff --git a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
index b5238b8..920a176 100644
--- a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
+++ b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
@@ -71,6 +71,10 @@
status_t dumpClient(int /*fd*/, const Vector<String16>& /*args*/) override;
+ status_t startWatchingTags(const String8 &tags, int outFd) override;
+ status_t stopWatchingTags(int outFd) override;
+ status_t dumpWatchedEventsToVector(std::vector<std::string> &out) override;
+
status_t initialize(sp<CameraProviderManager> /*manager*/,
const String8& /*monitorTags*/) override;
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
index 1147e23..0283d01 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
@@ -155,6 +155,38 @@
}
template <typename TClientBase>
+status_t Camera2ClientBase<TClientBase>::startWatchingTags(const String8 &tags, int out) {
+ sp<CameraDeviceBase> device = mDevice;
+ if (!device) {
+ dprintf(out, " Device is detached");
+ return OK;
+ }
+
+ return device->startWatchingTags(tags);
+}
+
+template <typename TClientBase>
+status_t Camera2ClientBase<TClientBase>::stopWatchingTags(int out) {
+ sp<CameraDeviceBase> device = mDevice;
+ if (!device) {
+ dprintf(out, " Device is detached");
+ return OK;
+ }
+
+ return device->stopWatchingTags();
+}
+
+template <typename TClientBase>
+status_t Camera2ClientBase<TClientBase>::dumpWatchedEventsToVector(std::vector<std::string> &out) {
+ sp<CameraDeviceBase> device = mDevice;
+ if (!device) {
+ // Nothing to dump if the device is detached
+ return OK;
+ }
+ return device->dumpWatchedEventsToVector(out);
+}
+
+template <typename TClientBase>
status_t Camera2ClientBase<TClientBase>::dumpDevice(
int fd,
const Vector<String16>& args) {
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.h b/services/camera/libcameraservice/common/Camera2ClientBase.h
index b593bfa..ba6a230 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.h
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.h
@@ -61,6 +61,9 @@
virtual status_t initialize(sp<CameraProviderManager> manager, const String8& monitorTags);
virtual status_t dumpClient(int fd, const Vector<String16>& args);
+ virtual status_t startWatchingTags(const String8 &tags, int out);
+ virtual status_t stopWatchingTags(int out);
+ virtual status_t dumpWatchedEventsToVector(std::vector<std::string> &out);
/**
* NotificationListener implementation
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index 3c95ed3..8168821 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -97,6 +97,9 @@
virtual status_t disconnect() = 0;
virtual status_t dump(int fd, const Vector<String16> &args) = 0;
+ virtual status_t startWatchingTags(const String8 &tags) = 0;
+ virtual status_t stopWatchingTags() = 0;
+ virtual status_t dumpWatchedEventsToVector(std::vector<std::string> &out) = 0;
/**
* The physical camera device's static characteristics metadata buffer
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index 91fc483..75b2f80 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -1631,6 +1631,7 @@
case 3:
deviceInfo = initializeDeviceInfo<DeviceInfo3>(name, mProviderTagid,
id, minor);
+ deviceInfo->notifyDeviceStateChange(mDeviceState);
break;
default:
ALOGE("%s: Device %s: Unknown HIDL device HAL major version %d:", __FUNCTION__,
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 67f99bf..8925b15 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -848,6 +848,21 @@
return OK;
}
+status_t Camera3Device::startWatchingTags(const String8 &tags) {
+ mTagMonitor.parseTagsToMonitor(tags);
+ return OK;
+}
+
+status_t Camera3Device::stopWatchingTags() {
+ mTagMonitor.disableMonitoring();
+ return OK;
+}
+
+status_t Camera3Device::dumpWatchedEventsToVector(std::vector<std::string> &out) {
+ mTagMonitor.getLatestMonitoredTagEvents(out);
+ return OK;
+}
+
const CameraMetadata& Camera3Device::infoPhysical(const String8& physicalId) const {
ALOGVV("%s: E", __FUNCTION__);
if (CC_UNLIKELY(mStatus == STATUS_UNINITIALIZED ||
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 4ffdc5f..f2394ad 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -106,6 +106,9 @@
status_t initialize(sp<CameraProviderManager> manager, const String8& monitorTags) override;
status_t disconnect() override;
status_t dump(int fd, const Vector<String16> &args) override;
+ status_t startWatchingTags(const String8 &tags) override;
+ status_t stopWatchingTags() override;
+ status_t dumpWatchedEventsToVector(std::vector<std::string> &out) override;
const CameraMetadata& info() const override;
const CameraMetadata& infoPhysical(const String8& physicalId) const override;
diff --git a/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.cpp b/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.cpp
index 76927c0..8d170f1 100644
--- a/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.cpp
+++ b/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.cpp
@@ -120,13 +120,11 @@
proxyBinder->pingForUserUpdate();
}
-bool CameraServiceProxyWrapper::isRotateAndCropOverrideNeeded(
- String16 packageName, int sensorOrientation, int lensFacing) {
+int CameraServiceProxyWrapper::getRotateAndCropOverride(String16 packageName, int lensFacing) {
sp<ICameraServiceProxy> proxyBinder = getCameraServiceProxy();
if (proxyBinder == nullptr) return true;
- bool ret = true;
- auto status = proxyBinder->isRotateAndCropOverrideNeeded(packageName, sensorOrientation,
- lensFacing, &ret);
+ int ret = 0;
+ auto status = proxyBinder->getRotateAndCropOverride(packageName, lensFacing, &ret);
if (!status.isOk()) {
ALOGE("%s: Failed during top activity orientation query: %s", __FUNCTION__,
status.exceptionMessage().c_str());
diff --git a/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.h b/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.h
index ad9db68..a51e568 100644
--- a/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.h
+++ b/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.h
@@ -91,9 +91,8 @@
// Ping camera service proxy for user update
static void pingCameraServiceProxy();
- // Check whether the current top activity needs a rotate and crop override.
- static bool isRotateAndCropOverrideNeeded(String16 packageName, int sensorOrientation,
- int lensFacing);
+ // Return the current top activity rotate and crop override.
+ static int getRotateAndCropOverride(String16 packageName, int lensFacing);
};
} // android
diff --git a/services/camera/libcameraservice/utils/CameraTraces.cpp b/services/camera/libcameraservice/utils/CameraTraces.cpp
index 0198690..0cd4f5d 100644
--- a/services/camera/libcameraservice/utils/CameraTraces.cpp
+++ b/services/camera/libcameraservice/utils/CameraTraces.cpp
@@ -64,7 +64,7 @@
ATRACE_END();
}
-status_t CameraTraces::dump(int fd, const Vector<String16> &args __attribute__((unused))) {
+status_t CameraTraces::dump(int fd) {
ALOGV("%s: fd = %d", __FUNCTION__, fd);
Mutex::Autolock al(sImpl.tracesLock);
List<ProcessCallStack>& pcsList = sImpl.pcsList;
diff --git a/services/camera/libcameraservice/utils/CameraTraces.h b/services/camera/libcameraservice/utils/CameraTraces.h
index 13ca16d..71fa334 100644
--- a/services/camera/libcameraservice/utils/CameraTraces.h
+++ b/services/camera/libcameraservice/utils/CameraTraces.h
@@ -42,7 +42,7 @@
*
* <p>Each line is indented by DUMP_INDENT spaces.</p>
*/
- static status_t dump(int fd, const Vector<String16>& args);
+ static status_t dump(int fd);
private:
enum {
diff --git a/services/camera/libcameraservice/utils/TagMonitor.cpp b/services/camera/libcameraservice/utils/TagMonitor.cpp
index 4488098..461f5e9 100644
--- a/services/camera/libcameraservice/utils/TagMonitor.cpp
+++ b/services/camera/libcameraservice/utils/TagMonitor.cpp
@@ -239,38 +239,59 @@
} else {
dprintf(fd, " Tag monitoring disabled (enable with -m <name1,..,nameN>)\n");
}
- if (mMonitoringEvents.size() > 0) {
- dprintf(fd, " Monitored tag event log:\n");
- for (const auto& event : mMonitoringEvents) {
- int indentation = (event.source == REQUEST) ? 15 : 30;
- dprintf(fd, " f%d:%" PRId64 "ns:%*s%*s%s.%s: ",
- event.frameNumber, event.timestamp,
- 2, event.cameraId.c_str(),
- indentation,
- event.source == REQUEST ? "REQ:" : "RES:",
- get_local_camera_metadata_section_name_vendor_id(event.tag,
- mVendorTagId),
- get_local_camera_metadata_tag_name_vendor_id(event.tag,
- mVendorTagId));
- if (event.newData.size() == 0) {
- dprintf(fd, " (Removed)\n");
- } else {
- printData(fd, event.newData.data(), event.tag,
- event.type, event.newData.size() / camera_metadata_type_size[event.type],
- indentation + 18, event.outputStreamIds, event.inputStreamId);
- }
- }
- }
+ if (mMonitoringEvents.size() == 0) { return; }
+
+ dprintf(fd, " Monitored tag event log:\n");
+
+ std::vector<std::string> eventStrs;
+ dumpMonitoredTagEventsToVectorLocked(eventStrs);
+ for (const std::string &eventStr : eventStrs) {
+ dprintf(fd, " %s", eventStr.c_str());
+ }
}
-// TODO: Consolidate with printData from camera_metadata.h
+void TagMonitor::getLatestMonitoredTagEvents(std::vector<std::string> &out) {
+ std::lock_guard<std::mutex> lock(mMonitorMutex);
+ dumpMonitoredTagEventsToVectorLocked(out);
+}
+
+void TagMonitor::dumpMonitoredTagEventsToVectorLocked(std::vector<std::string> &vec) {
+ if (mMonitoringEvents.size() == 0) { return; }
+
+ for (const auto& event : mMonitoringEvents) {
+ int indentation = (event.source == REQUEST) ? 15 : 30;
+ String8 eventString = String8::format("f%d:%" PRId64 "ns:%*s%*s%s.%s: ",
+ event.frameNumber, event.timestamp,
+ 2, event.cameraId.c_str(),
+ indentation,
+ event.source == REQUEST ? "REQ:" : "RES:",
+ get_local_camera_metadata_section_name_vendor_id(event.tag, mVendorTagId),
+ get_local_camera_metadata_tag_name_vendor_id(event.tag, mVendorTagId));
+ if (event.newData.size() == 0) {
+ eventString += " (Removed)";
+ } else {
+ eventString += getEventDataString(event.newData.data(),
+ event.tag,
+ event.type,
+ event.newData.size() / camera_metadata_type_size[event.type],
+ indentation + 18,
+ event.outputStreamIds,
+ event.inputStreamId);
+ }
+ vec.emplace_back(eventString.string());
+ }
+}
#define CAMERA_METADATA_ENUM_STRING_MAX_SIZE 29
-void TagMonitor::printData(int fd, const uint8_t *data_ptr, uint32_t tag,
- int type, int count, int indentation, const std::unordered_set<int32_t> &outputStreamIds,
- int32_t inputStreamId) {
+String8 TagMonitor::getEventDataString(const uint8_t* data_ptr,
+ uint32_t tag,
+ int type,
+ int count,
+ int indentation,
+ const std::unordered_set<int32_t>& outputStreamIds,
+ int32_t inputStreamId) {
static int values_per_line[NUM_TYPES] = {
[TYPE_BYTE] = 16,
[TYPE_INT32] = 8,
@@ -279,6 +300,7 @@
[TYPE_DOUBLE] = 4,
[TYPE_RATIONAL] = 4,
};
+
size_t type_size = camera_metadata_type_size[type];
char value_string_tmp[CAMERA_METADATA_ENUM_STRING_MAX_SIZE];
uint32_t value;
@@ -286,10 +308,11 @@
int lines = count / values_per_line[type];
if (count % values_per_line[type] != 0) lines++;
+ String8 returnStr = String8();
int index = 0;
int j, k;
for (j = 0; j < lines; j++) {
- dprintf(fd, "%*s[", (j != 0) ? indentation + 4 : 0, "");
+ returnStr.appendFormat("%*s[", (j != 0) ? indentation + 4 : 0, "");
for (k = 0;
k < values_per_line[type] && count > 0;
k++, count--, index += type_size) {
@@ -302,10 +325,9 @@
value_string_tmp,
sizeof(value_string_tmp))
== OK) {
- dprintf(fd, "%s ", value_string_tmp);
+ returnStr += value_string_tmp;
} else {
- dprintf(fd, "%hhu ",
- *(data_ptr + index));
+ returnStr.appendFormat("%hhu", *(data_ptr + index));
}
break;
case TYPE_INT32:
@@ -316,47 +338,43 @@
value_string_tmp,
sizeof(value_string_tmp))
== OK) {
- dprintf(fd, "%s ", value_string_tmp);
+ returnStr += value_string_tmp;
} else {
- dprintf(fd, "%" PRId32 " ",
- *(int32_t*)(data_ptr + index));
+ returnStr.appendFormat("%" PRId32 " ", *(int32_t*)(data_ptr + index));
}
break;
case TYPE_FLOAT:
- dprintf(fd, "%0.8f ",
- *(float*)(data_ptr + index));
+ returnStr.appendFormat("%0.8f", *(float*)(data_ptr + index));
break;
case TYPE_INT64:
- dprintf(fd, "%" PRId64 " ",
- *(int64_t*)(data_ptr + index));
+ returnStr.appendFormat("%" PRId64 " ", *(int64_t*)(data_ptr + index));
break;
case TYPE_DOUBLE:
- dprintf(fd, "%0.8f ",
- *(double*)(data_ptr + index));
+ returnStr.appendFormat("%0.8f ", *(double*)(data_ptr + index));
break;
case TYPE_RATIONAL: {
int32_t numerator = *(int32_t*)(data_ptr + index);
int32_t denominator = *(int32_t*)(data_ptr + index + 4);
- dprintf(fd, "(%d / %d) ",
- numerator, denominator);
+ returnStr.appendFormat("(%d / %d) ", numerator, denominator);
break;
}
default:
- dprintf(fd, "??? ");
+ returnStr += "??? ";
}
}
- dprintf(fd, "] ");
- if (outputStreamIds.size() > 0) {
- dprintf(fd, "output stream ids: ");
+ returnStr += "] ";
+ if (!outputStreamIds.empty()) {
+ returnStr += "output stream ids: ";
for (const auto &id : outputStreamIds) {
- dprintf(fd, " %d ", id);
+ returnStr.appendFormat(" %d ", id);
}
}
if (inputStreamId != -1) {
- dprintf(fd, "input stream id: %d", inputStreamId);
+ returnStr.appendFormat("input stream id: %d", inputStreamId);
}
- dprintf(fd, "\n");
+ returnStr += "\n";
}
+ return returnStr;
}
template<typename T>
diff --git a/services/camera/libcameraservice/utils/TagMonitor.h b/services/camera/libcameraservice/utils/TagMonitor.h
index f6df4b7..088d6fe 100644
--- a/services/camera/libcameraservice/utils/TagMonitor.h
+++ b/services/camera/libcameraservice/utils/TagMonitor.h
@@ -74,11 +74,23 @@
// Dump current event log to the provided fd
void dumpMonitoredMetadata(int fd);
- private:
+ // Dumps the latest monitored Tag events to the passed vector.
+ // NOTE: The events are appended to the vector in reverser chronological order
+ // (i.e. most recent first)
+ void getLatestMonitoredTagEvents(std::vector<std::string> &out);
- static void printData(int fd, const uint8_t *data_ptr, uint32_t tag,
- int type, int count, int indentation,
- const std::unordered_set<int32_t> &outputStreamIds, int32_t inputStreamId);
+ private:
+ // Dumps monitored tag events to the passed vector without acquiring
+ // mMonitorMutex. mMonitorMutex must be acquired before calling this
+ // function.
+ void dumpMonitoredTagEventsToVectorLocked(std::vector<std::string> &out);
+
+ static String8 getEventDataString(const uint8_t *data_ptr,
+ uint32_t tag, int type,
+ int count,
+ int indentation,
+ const std::unordered_set<int32_t> &outputStreamIds,
+ int32_t inputStreamId);
void monitorSingleMetadata(TagMonitor::eventSource source, int64_t frameNumber,
nsecs_t timestamp, const std::string& cameraId, uint32_t tag,
diff --git a/services/medialog/Android.bp b/services/medialog/Android.bp
index cfc4c40..8088ef0 100644
--- a/services/medialog/Android.bp
+++ b/services/medialog/Android.bp
@@ -26,6 +26,7 @@
"libmediautils",
"libnblog",
"libutils",
+ "packagemanager_aidl-cpp",
],
cflags: [
diff --git a/services/mediametrics/Android.bp b/services/mediametrics/Android.bp
index 04fc430..74e4715 100644
--- a/services/mediametrics/Android.bp
+++ b/services/mediametrics/Android.bp
@@ -114,6 +114,7 @@
"libmediautils",
"libutils",
"mediametricsservice-aidl-cpp",
+ "packagemanager_aidl-cpp",
],
header_libs: [
"libaudioutils_headers",
@@ -178,7 +179,6 @@
export_shared_lib_headers: [
"libstatspull",
"libstatssocket",
- "packagemanager_aidl-cpp",
],
static_libs: [
diff --git a/services/mediametrics/fuzzer/Android.bp b/services/mediametrics/fuzzer/Android.bp
index b03e518..9da7282 100644
--- a/services/mediametrics/fuzzer/Android.bp
+++ b/services/mediametrics/fuzzer/Android.bp
@@ -56,6 +56,7 @@
"libstatssocket",
"libutils",
"mediametricsservice-aidl-cpp",
+ "packagemanager_aidl-cpp",
],
include_dirs: [
diff --git a/services/mediametrics/tests/Android.bp b/services/mediametrics/tests/Android.bp
index 3baf739..f46fbad 100644
--- a/services/mediametrics/tests/Android.bp
+++ b/services/mediametrics/tests/Android.bp
@@ -33,6 +33,7 @@
"libmediautils",
"libutils",
"mediametricsservice-aidl-cpp",
+ "packagemanager_aidl-cpp",
],
header_libs: [
diff --git a/services/oboeservice/Android.bp b/services/oboeservice/Android.bp
index 4c58040..3563d66 100644
--- a/services/oboeservice/Android.bp
+++ b/services/oboeservice/Android.bp
@@ -68,6 +68,7 @@
"aaudio-aidl-cpp",
"framework-permission-aidl-cpp",
"libaudioclient_aidl_conversion",
+ "packagemanager_aidl-cpp",
],
export_shared_lib_headers: [