Merge "Use ERROR_CAMERA_DISCONNECTED on id remap" into main
diff --git a/camera/Android.bp b/camera/Android.bp
index e5ae954..7de8a62 100644
--- a/camera/Android.bp
+++ b/camera/Android.bp
@@ -101,6 +101,7 @@
],
shared_libs: [
+ "camera_platform_flags_c_lib",
"libbase",
"libcutils",
"libutils",
diff --git a/camera/Camera.cpp b/camera/Camera.cpp
index 35b8e21..6b040ab 100644
--- a/camera/Camera.cpp
+++ b/camera/Camera.cpp
@@ -245,7 +245,7 @@
ALOGV("getParameters");
String8 params;
sp <::android::hardware::ICamera> c = mCamera;
- if (c != 0) params = mCamera->getParameters();
+ if (c != 0) params = c->getParameters();
return params;
}
@@ -269,7 +269,7 @@
ALOGV("setPreviewCallbackFlags");
sp <::android::hardware::ICamera> c = mCamera;
if (c == 0) return;
- mCamera->setPreviewCallbackFlag(flag);
+ c->setPreviewCallbackFlag(flag);
}
status_t Camera::setPreviewCallbackTarget(
diff --git a/camera/CameraSessionStats.cpp b/camera/CameraSessionStats.cpp
index 36bf24c..f0630dd 100644
--- a/camera/CameraSessionStats.cpp
+++ b/camera/CameraSessionStats.cpp
@@ -16,6 +16,7 @@
// #define LOG_NDEBUG 0
#define LOG_TAG "CameraSessionStats"
+
#include <utils/Log.h>
#include <utils/String16.h>
@@ -414,6 +415,12 @@
return err;
}
+ bool usedUltraWide = false;
+ if ((err = parcel->readBool(&usedUltraWide)) != OK) {
+ ALOGE("%s: Failed to read ultrawide usage from parcel", __FUNCTION__);
+ return err;
+ }
+
int32_t sessionIdx;
if ((err = parcel->readInt32(&sessionIdx)) != OK) {
ALOGE("%s: Failed to read session index from parcel", __FUNCTION__);
@@ -443,6 +450,7 @@
mStreamStats = std::move(streamStats);
mUserTag = toStdString(userTag);
mVideoStabilizationMode = videoStabilizationMode;
+ mUsedUltraWide = usedUltraWide;
mSessionIndex = sessionIdx;
mCameraExtensionSessionStats = extStats;
@@ -541,6 +549,10 @@
ALOGE("%s: Failed to write video stabilization mode!", __FUNCTION__);
return err;
}
+ if ((err = parcel->writeBool(mUsedUltraWide)) != OK) {
+ ALOGE("%s: Failed to write ultrawide usage!", __FUNCTION__);
+ return err;
+ }
if ((err = parcel->writeInt32(mSessionIndex)) != OK) {
ALOGE("%s: Failed to write session index!", __FUNCTION__);
diff --git a/camera/camera_platform.aconfig b/camera/camera_platform.aconfig
index fc11518..074413f 100644
--- a/camera/camera_platform.aconfig
+++ b/camera/camera_platform.aconfig
@@ -2,7 +2,21 @@
flag {
namespace: "camera_platform"
- name: "initial_test_flag"
- description: "Flag infrastructure test flag"
- bug: "292631208"
+ name: "camera_hsum_permission"
+ description: "Camera access by headless system user"
+ bug: "273539631"
+}
+
+flag {
+ namespace: "camera_platform"
+ name: "log_ultrawide_usage"
+ description: "Enable measuring how much usage there is for ultrawide-angle cameras"
+ bug: "300515796"
+}
+
+flag {
+ namespace: "camera_platform"
+ name: "camera_manual_flash_strength_control"
+ description: "Flash brightness level control in manual flash mode"
+ bug: "238348881"
}
diff --git a/camera/include/camera/CameraSessionStats.h b/camera/include/camera/CameraSessionStats.h
index 70ca0b3..158ac2a 100644
--- a/camera/include/camera/CameraSessionStats.h
+++ b/camera/include/camera/CameraSessionStats.h
@@ -161,6 +161,7 @@
std::vector<CameraStreamStats> mStreamStats;
std::string mUserTag;
int mVideoStabilizationMode;
+ bool mUsedUltraWide;
int mSessionIndex;
CameraExtensionSessionStats mCameraExtensionSessionStats;
diff --git a/camera/ndk/impl/ACameraMetadata.cpp b/camera/ndk/impl/ACameraMetadata.cpp
index 61c7551..b6b8012 100644
--- a/camera/ndk/impl/ACameraMetadata.cpp
+++ b/camera/ndk/impl/ACameraMetadata.cpp
@@ -540,6 +540,7 @@
case ACAMERA_CONTROL_AUTOFRAMING:
case ACAMERA_EDGE_MODE:
case ACAMERA_FLASH_MODE:
+ case ACAMERA_FLASH_STRENGTH_LEVEL:
case ACAMERA_HOT_PIXEL_MODE:
case ACAMERA_JPEG_GPS_COORDINATES:
case ACAMERA_JPEG_GPS_PROCESSING_METHOD:
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index 4a589bc..c0b0313 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -2358,6 +2358,125 @@
*/
ACAMERA_FLASH_STATE = // byte (acamera_metadata_enum_android_flash_state_t)
ACAMERA_FLASH_START + 5,
+ /**
+ * <p>Flash strength level to be used when manual flash control is active.</p>
+ *
+ * <p>Type: int32</p>
+ *
+ * <p>This tag may appear in:
+ * <ul>
+ * <li>ACameraMetadata from ACameraCaptureSession_captureCallback_result callbacks</li>
+ * <li>ACaptureRequest</li>
+ * </ul></p>
+ *
+ * <p>Flash strength level to use in capture mode i.e. when the applications control
+ * flash with either SINGLE or TORCH mode.</p>
+ * <p>Use android.flash.info.singleStrengthMaxLevel and
+ * android.flash.info.torchStrengthMaxLevel to check whether the device supports
+ * flash strength control or not.
+ * If the values of android.flash.info.singleStrengthMaxLevel and
+ * android.flash.info.torchStrengthMaxLevel are greater than 1,
+ * then the device supports manual flash strength control.</p>
+ * <p>If the ACAMERA_FLASH_MODE <code>==</code> TORCH the value must be >= 1
+ * and <= android.flash.info.torchStrengthMaxLevel.
+ * If the application doesn't set the key and
+ * android.flash.info.torchStrengthMaxLevel > 1,
+ * then the flash will be fired at the default level set by HAL in
+ * android.flash.info.torchStrengthDefaultLevel.
+ * If the ACAMERA_FLASH_MODE <code>==</code> SINGLE, then the value must be >= 1
+ * and <= android.flash.info.singleStrengthMaxLevel.
+ * If the application does not set this key and
+ * android.flash.info.singleStrengthMaxLevel > 1,
+ * then the flash will be fired at the default level set by HAL
+ * in android.flash.info.singleStrengthDefaultLevel.
+ * If ACAMERA_CONTROL_AE_MODE is set to any of ON_AUTO_FLASH, ON_ALWAYS_FLASH,
+ * ON_AUTO_FLASH_REDEYE, ON_EXTERNAL_FLASH values, then the strengthLevel will be ignored.</p>
+ *
+ * @see ACAMERA_CONTROL_AE_MODE
+ * @see ACAMERA_FLASH_MODE
+ */
+ ACAMERA_FLASH_STRENGTH_LEVEL = // int32
+ ACAMERA_FLASH_START + 6,
+ /**
+ * <p>Maximum flash brightness level for manual flash control in SINGLE mode.</p>
+ *
+ * <p>Type: int32</p>
+ *
+ * <p>This tag may appear in:
+ * <ul>
+ * <li>ACameraMetadata from ACameraManager_getCameraCharacteristics</li>
+ * </ul></p>
+ *
+ * <p>Maximum flash brightness level in camera capture mode and
+ * ACAMERA_FLASH_MODE set to SINGLE.
+ * Value will be > 1 if the manual flash strength control feature is supported,
+ * otherwise the value will be equal to 1.
+ * Note that this level is just a number of supported levels (the granularity of control).
+ * There is no actual physical power units tied to this level.</p>
+ *
+ * @see ACAMERA_FLASH_MODE
+ */
+ ACAMERA_FLASH_SINGLE_STRENGTH_MAX_LEVEL = // int32
+ ACAMERA_FLASH_START + 7,
+ /**
+ * <p>Default flash brightness level for manual flash control in SINGLE mode.</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>android.flash.info.singleStrengthMaxLevel</code>.
+ * Note for devices that do not support the manual flash strength control
+ * feature, this level will always be equal to 1.</p>
+ */
+ ACAMERA_FLASH_SINGLE_STRENGTH_DEFAULT_LEVEL = // int32
+ ACAMERA_FLASH_START + 8,
+ /**
+ * <p>Maximum flash brightness level for manual flash control in TORCH mode</p>
+ *
+ * <p>Type: int32</p>
+ *
+ * <p>This tag may appear in:
+ * <ul>
+ * <li>ACameraMetadata from ACameraManager_getCameraCharacteristics</li>
+ * </ul></p>
+ *
+ * <p>Maximum flash brightness level in camera capture mode and
+ * ACAMERA_FLASH_MODE set to TORCH.
+ * Value will be > 1 if the manual flash strength control feature is supported,
+ * otherwise the value will be equal to 1.</p>
+ * <p>Note that this level is just a number of supported levels(the granularity of control).
+ * There is no actual physical power units tied to this level.
+ * There is no relation between android.flash.info.torchStrengthMaxLevel and
+ * android.flash.info.singleStrengthMaxLevel i.e. the ratio of
+ * android.flash.info.torchStrengthMaxLevel:android.flash.info.singleStrengthMaxLevel
+ * is not guaranteed to be the ratio of actual brightness.</p>
+ *
+ * @see ACAMERA_FLASH_MODE
+ */
+ ACAMERA_FLASH_TORCH_STRENGTH_MAX_LEVEL = // int32
+ ACAMERA_FLASH_START + 9,
+ /**
+ * <p>Default flash brightness level for manual flash control in TORCH mode</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 android.flash.info.torchStrengthMaxLevel.
+ * Note for the devices that do not support the manual flash strength control feature,
+ * this level will always be equal to 1.</p>
+ */
+ ACAMERA_FLASH_TORCH_STRENGTH_DEFAULT_LEVEL = // int32
+ ACAMERA_FLASH_START + 10,
ACAMERA_FLASH_END,
/**
diff --git a/camera/tests/fuzzer/Android.bp b/camera/tests/fuzzer/Android.bp
index bae8706..9aecba4 100644
--- a/camera/tests/fuzzer/Android.bp
+++ b/camera/tests/fuzzer/Android.bp
@@ -28,6 +28,7 @@
"libcamera_client",
],
shared_libs: [
+ "camera_platform_flags_c_lib",
"libbase",
"libcutils",
"libutils",
diff --git a/drm/mediadrm/plugins/clearkey/aidl/Android.bp b/drm/mediadrm/plugins/clearkey/aidl/Android.bp
index eaf5051..0b0d46a 100644
--- a/drm/mediadrm/plugins/clearkey/aidl/Android.bp
+++ b/drm/mediadrm/plugins/clearkey/aidl/Android.bp
@@ -8,21 +8,7 @@
}
cc_defaults {
- name: "aidl_clearkey_service_defaults",
- vendor: true,
-
- srcs: [
- "CreatePluginFactories.cpp",
- "CryptoPlugin.cpp",
- "DrmFactory.cpp",
- "DrmPlugin.cpp",
- ],
-
- relative_install_path: "hw",
-
- cflags: ["-Wall", "-Werror", "-Wthread-safety"],
-
- include_dirs: ["frameworks/av/include"],
+ name: "aidl_clearkey_service_defaults-use-shared-deps",
shared_libs: [
"libbase",
@@ -39,6 +25,46 @@
"libclearkeybase",
"libjsoncpp",
],
+}
+
+cc_defaults {
+ name: "aidl_clearkey_service_defaults-use-static-deps",
+
+ stl: "c++_static",
+
+ shared_libs: [
+ "libbinder_ndk",
+ "libcrypto",
+ "liblog",
+ ],
+
+ static_libs: [
+ "android.hardware.common-V2-ndk",
+ "android.hardware.drm-V1-ndk",
+ "libbase",
+ "libclearkeybase",
+ "libjsoncpp",
+ "libprotobuf-cpp-lite",
+ "libutils",
+ ],
+}
+
+cc_defaults {
+ name: "aidl_clearkey_service_defaults",
+ vendor: true,
+
+ srcs: [
+ "CreatePluginFactories.cpp",
+ "CryptoPlugin.cpp",
+ "DrmFactory.cpp",
+ "DrmPlugin.cpp",
+ ],
+
+ relative_install_path: "hw",
+
+ cflags: ["-Wall", "-Werror", "-Wthread-safety"],
+
+ include_dirs: ["frameworks/av/include"],
local_include_dirs: ["include"],
@@ -49,7 +75,10 @@
cc_binary {
name: "android.hardware.drm-service.clearkey",
- defaults: ["aidl_clearkey_service_defaults"],
+ defaults: [
+ "aidl_clearkey_service_defaults",
+ "aidl_clearkey_service_defaults-use-shared-deps",
+ ],
srcs: ["Service.cpp"],
init_rc: ["android.hardware.drm-service.clearkey.rc"],
vintf_fragments: ["android.hardware.drm-service.clearkey.xml"],
@@ -57,17 +86,31 @@
cc_binary {
name: "android.hardware.drm-service-lazy.clearkey",
- defaults: ["aidl_clearkey_service_defaults"],
+ defaults: [
+ "aidl_clearkey_service_defaults",
+ "aidl_clearkey_service_defaults-use-shared-deps",
+ ],
overrides: ["android.hardware.drm-service.clearkey"],
srcs: ["ServiceLazy.cpp"],
init_rc: ["android.hardware.drm-service-lazy.clearkey.rc"],
vintf_fragments: ["android.hardware.drm-service.clearkey.xml"],
}
+cc_binary {
+ name: "android.hardware.drm-service.clearkey.apex",
+ stem: "android.hardware.drm-service.clearkey",
+ defaults: [
+ "aidl_clearkey_service_defaults",
+ "aidl_clearkey_service_defaults-use-static-deps",
+ ],
+ srcs: ["Service.cpp"],
+ installable: false, // installed in APEX
+}
+
phony {
name: "android.hardware.drm@latest-service.clearkey",
required: [
- "android.hardware.drm-service.clearkey",
+ "com.android.hardware.drm.clearkey",
],
}
@@ -123,3 +166,34 @@
],
},
}
+
+apex {
+ name: "com.android.hardware.drm.clearkey",
+ manifest: "manifest.json",
+ file_contexts: "file_contexts",
+ key: "com.android.hardware.key",
+ certificate: ":com.android.hardware.certificate",
+ vendor: true,
+ updatable: false,
+
+ binaries: [
+ "android.hardware.drm-service.clearkey.apex",
+ ],
+ prebuilts: [
+ "android.hardware.drm-service.clearkey.apex.rc",
+ "android.hardware.drm-service.clearkey.xml"
+ ],
+}
+
+prebuilt_etc {
+ name: "android.hardware.drm-service.clearkey.apex.rc",
+ src: "android.hardware.drm-service.clearkey.apex.rc",
+ installable: false,
+}
+
+prebuilt_etc {
+ name: "android.hardware.drm-service.clearkey.xml",
+ src: "android.hardware.drm-service.clearkey.xml",
+ sub_dir: "vintf",
+ installable: false,
+}
diff --git a/drm/mediadrm/plugins/clearkey/aidl/android.hardware.drm-service.clearkey.apex.rc b/drm/mediadrm/plugins/clearkey/aidl/android.hardware.drm-service.clearkey.apex.rc
new file mode 100644
index 0000000..f4645b3
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/aidl/android.hardware.drm-service.clearkey.apex.rc
@@ -0,0 +1,7 @@
+service vendor.drm-clearkey-service /apex/com.android.hardware.drm.clearkey/bin/hw/android.hardware.drm-service.clearkey
+ class hal
+ user media
+ group mediadrm drmrpc
+ ioprio rt 4
+ task_profiles ProcessCapacityHigh
+ interface aidl android.hardware.drm.IDrmFactory/clearkey
diff --git a/drm/mediadrm/plugins/clearkey/aidl/file_contexts b/drm/mediadrm/plugins/clearkey/aidl/file_contexts
new file mode 100644
index 0000000..e9e6ca2
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/aidl/file_contexts
@@ -0,0 +1,3 @@
+(/.*)? u:object_r:vendor_file:s0
+/etc(/.*)? u:object_r:vendor_configs_file:s0
+/bin/hw/android\.hardware\.drm-service(-lazy)?\.clearkey u:object_r:hal_drm_clearkey_aidl_exec:s0
diff --git a/drm/mediadrm/plugins/clearkey/aidl/manifest.json b/drm/mediadrm/plugins/clearkey/aidl/manifest.json
new file mode 100644
index 0000000..369dc21
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/aidl/manifest.json
@@ -0,0 +1,4 @@
+{
+ "name": "com.android.hardware.drm.clearkey",
+ "version": 1
+}
diff --git a/media/aconfig/Android.bp b/media/aconfig/Android.bp
new file mode 100644
index 0000000..4b489e2
--- /dev/null
+++ b/media/aconfig/Android.bp
@@ -0,0 +1,16 @@
+aconfig_declarations {
+ name: "aconfig_mediacodec_flags",
+ package: "com.android.media.codec.flags",
+ srcs: ["mediacodec_flags.aconfig"],
+}
+
+java_aconfig_library {
+ name: "aconfig_mediacodec_flags_java_lib",
+ aconfig_declarations: "aconfig_mediacodec_flags",
+ defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
+
+cc_aconfig_library {
+ name: "aconfig_mediacodec_flags_c_lib",
+ aconfig_declarations: "aconfig_mediacodec_flags",
+}
diff --git a/media/aconfig/mediacodec_flags.aconfig b/media/aconfig/mediacodec_flags.aconfig
new file mode 100644
index 0000000..67ba3e5
--- /dev/null
+++ b/media/aconfig/mediacodec_flags.aconfig
@@ -0,0 +1,8 @@
+package: "com.android.media.codec.flags"
+
+flag {
+ name: "large_audio_frame"
+ namespace: "codec_fwk"
+ description: "Feature flags for large audio frame support"
+ bug: "297219557"
+}
diff --git a/media/codec2/components/base/Android.bp b/media/codec2/components/base/Android.bp
index 664647a..4b189b4 100644
--- a/media/codec2/components/base/Android.bp
+++ b/media/codec2/components/base/Android.bp
@@ -42,6 +42,10 @@
"libnativewindow_headers",
],
+ static_libs: [
+ "libyuv_static", // for conversion routines
+ ],
+
shared_libs: [
"libcutils", // for properties
"liblog", // for ALOG
diff --git a/media/codec2/components/base/SimpleC2Component.cpp b/media/codec2/components/base/SimpleC2Component.cpp
index 55a1164..06a21f6 100644
--- a/media/codec2/components/base/SimpleC2Component.cpp
+++ b/media/codec2/components/base/SimpleC2Component.cpp
@@ -21,8 +21,10 @@
#include <android/hardware_buffer.h>
#include <cutils/properties.h>
#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/AUtils.h>
#include <inttypes.h>
+#include <libyuv.h>
#include <C2Config.h>
#include <C2Debug.h>
@@ -32,6 +34,15 @@
#include <SimpleC2Component.h>
namespace android {
+
+// libyuv version required for I410ToAB30Matrix and I210ToAB30Matrix.
+#if LIBYUV_VERSION >= 1780
+#include <algorithm>
+#define HAVE_LIBYUV_I410_I210_TO_AB30 1
+#else
+#define HAVE_LIBYUV_I410_I210_TO_AB30 0
+#endif
+
constexpr uint8_t kNeutralUVBitDepth8 = 128;
constexpr uint16_t kNeutralUVBitDepth10 = 512;
@@ -506,6 +517,120 @@
}
}
+void convertPlanar16ToY410OrRGBA1010102(uint8_t* dst, const uint16_t* srcY, const uint16_t* srcU,
+ const uint16_t* srcV, size_t srcYStride, size_t srcUStride,
+ size_t srcVStride, size_t dstStride, size_t width,
+ size_t height,
+ std::shared_ptr<const C2ColorAspectsStruct> aspects,
+ CONV_FORMAT_T format) {
+ bool processed = false;
+#if HAVE_LIBYUV_I410_I210_TO_AB30
+ if (format == CONV_FORMAT_I444) {
+ libyuv::I410ToAB30Matrix(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride, dst,
+ dstStride, &libyuv::kYuvV2020Constants, width, height);
+ processed = true;
+ } else if (format == CONV_FORMAT_I422) {
+ libyuv::I210ToAB30Matrix(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride, dst,
+ dstStride, &libyuv::kYuvV2020Constants, width, height);
+ processed = true;
+ }
+#endif // HAVE_LIBYUV_I410_I210_TO_AB30
+ if (!processed) {
+ convertYUV420Planar16ToY410OrRGBA1010102(
+ (uint32_t*)dst, srcY, srcU, srcV, srcYStride, srcUStride, srcVStride,
+ dstStride / sizeof(uint32_t), width, height,
+ std::static_pointer_cast<const C2ColorAspectsStruct>(aspects));
+ }
+}
+
+void convertPlanar16ToP010(uint16_t* dstY, uint16_t* dstUV, const uint16_t* srcY,
+ const uint16_t* srcU, const uint16_t* srcV, size_t srcYStride,
+ size_t srcUStride, size_t srcVStride, size_t dstYStride,
+ size_t dstUStride, size_t dstVStride, size_t width, size_t height,
+ bool isMonochrome, CONV_FORMAT_T format, uint16_t* tmpFrameBuffer,
+ size_t tmpFrameBufferSize) {
+#if LIBYUV_VERSION >= 1779
+ if ((format == CONV_FORMAT_I444) || (format == CONV_FORMAT_I422)) {
+ // TODO(https://crbug.com/libyuv/952): replace this block with libyuv::I410ToP010
+ // and libyuv::I210ToP010 when they are available. Note it may be safe to alias dstY
+ // in I010ToP010, but the libyuv API doesn't make any guarantees.
+ const size_t tmpSize = dstYStride * height + dstUStride * align(height, 2);
+ CHECK(tmpSize <= tmpFrameBufferSize);
+
+ uint16_t* const tmpY = tmpFrameBuffer;
+ uint16_t* const tmpU = tmpY + dstYStride * height;
+ uint16_t* const tmpV = tmpU + dstUStride * align(height, 2) / 2;
+ if (format == CONV_FORMAT_I444) {
+ libyuv::I410ToI010(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride, tmpY,
+ dstYStride, tmpU, dstUStride, tmpV, dstUStride, width, height);
+ } else {
+ libyuv::I210ToI010(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride, tmpY,
+ dstYStride, tmpU, dstUStride, tmpV, dstUStride, width, height);
+ }
+ libyuv::I010ToP010(tmpY, dstYStride, tmpU, dstUStride, tmpV, dstVStride, dstY, dstYStride,
+ dstUV, dstUStride, width, height);
+ } else {
+ convertYUV420Planar16ToP010(dstY, dstUV, srcY, srcU, srcV, srcYStride, srcUStride,
+ srcVStride, dstYStride, dstUStride, width, height,
+ isMonochrome);
+ }
+#else // LIBYUV_VERSION < 1779
+ convertYUV420Planar16ToP010(dstY, dstUV, srcY, srcU, srcV, srcYStride, srcUStride, srcVStride,
+ dstYStride, dstUStride, width, height, isMonochrome);
+#endif // LIBYUV_VERSION >= 1779
+}
+
+void convertPlanar16ToYV12(uint8_t* dstY, uint8_t* dstU, uint8_t* dstV, const uint16_t* srcY,
+ const uint16_t* srcU, const uint16_t* srcV, size_t srcYStride,
+ size_t srcUStride, size_t srcVStride, size_t dstYStride,
+ size_t dstUStride, size_t dstVStride, size_t width, size_t height,
+ bool isMonochrome, CONV_FORMAT_T format, uint16_t* tmpFrameBuffer,
+ size_t tmpFrameBufferSize) {
+#if LIBYUV_VERSION >= 1779
+ if (format == CONV_FORMAT_I444) {
+ // TODO(https://crbug.com/libyuv/950): replace this block with libyuv::I410ToI420
+ // when it's available.
+ const size_t tmpSize = dstYStride * height + dstUStride * align(height, 2);
+ CHECK(tmpSize <= tmpFrameBufferSize);
+
+ uint16_t* const tmpY = tmpFrameBuffer;
+ uint16_t* const tmpU = tmpY + dstYStride * height;
+ uint16_t* const tmpV = tmpU + dstUStride * align(height, 2) / 2;
+ libyuv::I410ToI010(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride, tmpY, dstYStride,
+ tmpU, dstUStride, tmpV, dstVStride, width, height);
+ libyuv::I010ToI420(tmpY, dstYStride, tmpU, dstUStride, tmpV, dstUStride, dstY, dstYStride,
+ dstU, dstUStride, dstV, dstVStride, width, height);
+ } else if (format == CONV_FORMAT_I422) {
+ libyuv::I210ToI420(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride, dstY, dstYStride,
+ dstU, dstUStride, dstV, dstVStride, width, height);
+ } else {
+ convertYUV420Planar16ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride, srcUStride,
+ srcVStride, dstYStride, dstUStride, width, height,
+ isMonochrome);
+ }
+#else // LIBYUV_VERSION < 1779
+ convertYUV420Planar16ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride, srcUStride,
+ srcVStride, dstYStride, dstUStride, width, height, isMonochrome);
+#endif // LIBYUV_VERSION >= 1779
+}
+
+void convertPlanar8ToYV12(uint8_t* dstY, uint8_t* dstU, uint8_t* dstV, const uint8_t* srcY,
+ const uint8_t* srcU, const uint8_t* srcV, size_t srcYStride,
+ size_t srcUStride, size_t srcVStride, size_t dstYStride,
+ size_t dstUStride, size_t dstVStride, uint32_t width, uint32_t height,
+ bool isMonochrome, CONV_FORMAT_T format) {
+ if (format == CONV_FORMAT_I444) {
+ libyuv::I444ToI420(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride, dstY, dstYStride,
+ dstU, dstUStride, dstV, dstVStride, width, height);
+ } else if (format == CONV_FORMAT_I422) {
+ libyuv::I422ToI420(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride, dstY, dstYStride,
+ dstU, dstUStride, dstV, dstVStride, width, height);
+ } else {
+ convertYUV420Planar8ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride, srcUStride,
+ srcVStride, dstYStride, dstUStride, dstVStride, width, height,
+ isMonochrome);
+ }
+}
std::unique_ptr<C2Work> SimpleC2Component::WorkQueue::pop_front() {
std::unique_ptr<C2Work> work = std::move(mQueue.front().work);
mQueue.pop_front();
diff --git a/media/codec2/components/base/include/SimpleC2Component.h b/media/codec2/components/base/include/SimpleC2Component.h
index bc27474..b28c47e 100644
--- a/media/codec2/components/base/include/SimpleC2Component.h
+++ b/media/codec2/components/base/include/SimpleC2Component.h
@@ -31,6 +31,12 @@
namespace android {
+typedef enum {
+ CONV_FORMAT_I420,
+ CONV_FORMAT_I422,
+ CONV_FORMAT_I444,
+} CONV_FORMAT_T;
+
void convertYUV420Planar8ToYV12(uint8_t *dstY, uint8_t *dstU, uint8_t *dstV, const uint8_t *srcY,
const uint8_t *srcU, const uint8_t *srcV, size_t srcYStride,
size_t srcUStride, size_t srcVStride, size_t dstYStride,
@@ -66,6 +72,30 @@
const uint32_t* srcRGBA, size_t srcRGBStride, size_t width,
size_t height, C2Color::matrix_t colorMatrix,
C2Color::range_t colorRange);
+void convertPlanar16ToY410OrRGBA1010102(uint8_t* dst, const uint16_t* srcY, const uint16_t* srcU,
+ const uint16_t* srcV, size_t srcYStride, size_t srcUStride,
+ size_t srcVStride, size_t dstStride, size_t width,
+ size_t height,
+ std::shared_ptr<const C2ColorAspectsStruct> aspects,
+ CONV_FORMAT_T format);
+
+void convertPlanar16ToP010(uint16_t* dstY, uint16_t* dstUV, const uint16_t* srcY,
+ const uint16_t* srcU, const uint16_t* srcV, size_t srcYStride,
+ size_t srcUStride, size_t srcVStride, size_t dstYStride,
+ size_t dstUStride, size_t dstVStride, size_t width, size_t height,
+ bool isMonochrome, CONV_FORMAT_T format, uint16_t* tmpFrameBuffer,
+ size_t tmpFrameBufferSize);
+void convertPlanar16ToYV12(uint8_t* dstY, uint8_t* dstU, uint8_t* dstV, const uint16_t* srcY,
+ const uint16_t* srcU, const uint16_t* srcV, size_t srcYStride,
+ size_t srcUStride, size_t srcVStride, size_t dstYStride,
+ size_t dstUStride, size_t dstVStride, size_t width, size_t height,
+ bool isMonochrome, CONV_FORMAT_T format, uint16_t* tmpFrameBuffer,
+ size_t tmpFrameBufferSize);
+void convertPlanar8ToYV12(uint8_t* dstY, uint8_t* dstU, uint8_t* dstV, const uint8_t* srcY,
+ const uint8_t* srcU, const uint8_t* srcV, size_t srcYStride,
+ size_t srcUStride, size_t srcVStride, size_t dstYStride,
+ size_t dstUStride, size_t dstVStride, uint32_t width, uint32_t height,
+ bool isMonochrome, CONV_FORMAT_T format);
class SimpleC2Component
: public C2Component, public std::enable_shared_from_this<SimpleC2Component> {
diff --git a/media/codec2/components/dav1d/Android.bp b/media/codec2/components/dav1d/Android.bp
index f7850ad..c9387dd 100644
--- a/media/codec2/components/dav1d/Android.bp
+++ b/media/codec2/components/dav1d/Android.bp
@@ -15,6 +15,7 @@
defaults: [
"libcodec2_soft-defaults",
"libcodec2_soft_sanitize_all-defaults",
+ "libcodec2_soft_sanitize_cfi-defaults",
],
cflags: [
@@ -22,9 +23,8 @@
"-Wno-unused-variable",
],
- srcs: ["C2SoftDav1dDec.cpp"],
+ srcs: ["C2SoftDav1dDec.cpp", "C2SoftDav1dDump.cpp"],
static_libs: [
- "libyuv_static",
"libdav1d_8bit",
"libdav1d_16bit",
],
diff --git a/media/codec2/components/dav1d/C2SoftDav1dDec.cpp b/media/codec2/components/dav1d/C2SoftDav1dDec.cpp
index b0cef41..3f96cb3 100644
--- a/media/codec2/components/dav1d/C2SoftDav1dDec.cpp
+++ b/media/codec2/components/dav1d/C2SoftDav1dDec.cpp
@@ -26,30 +26,13 @@
#include <Codec2CommonUtils.h>
#include <Codec2Mapper.h>
#include <SimpleC2Interface.h>
-#include <libyuv.h>
#include <log/log.h>
#include <media/stagefright/foundation/AUtils.h>
#include <media/stagefright/foundation/MediaDefs.h>
#include "C2SoftDav1dDec.h"
-// libyuv version required for I410ToAB30Matrix and I210ToAB30Matrix.
-#if LIBYUV_VERSION >= 1780
-#include <algorithm>
-#define HAVE_LIBYUV_I410_I210_TO_AB30 1
-#else
-#define HAVE_LIBYUV_I410_I210_TO_AB30 0
-#endif
-
namespace android {
-// Flag to enable dumping the bitsteram and the decoded pictures to files.
-static const bool ENABLE_DUMPING_FILES_DEFAULT = false;
-static const char ENABLE_DUMPING_FILES_PROPERTY[] = "debug.dav1d.enabledumping";
-
-// The number of frames to dump to a file
-static const int NUM_FRAMES_TO_DUMP_DEFAULT = INT_MAX;
-static const char NUM_FRAMES_TO_DUMP_PROPERTY[] = "debug.dav1d.numframestodump";
-
// The number of threads used for the dav1d decoder.
static const int NUM_THREADS_DAV1D_DEFAULT = 0;
static const char NUM_THREADS_DAV1D_PROPERTY[] = "debug.dav1d.numthreads";
@@ -522,37 +505,8 @@
}
bool C2SoftDav1dDec::initDecoder() {
- nsecs_t now = systemTime();
#ifdef FILE_DUMP_ENABLE
- snprintf(mInDataFileName, 256, "%s_%" PRId64 "d.%s", DUMP_FILE_PATH, now, INPUT_DATA_DUMP_EXT);
- snprintf(mInSizeFileName, 256, "%s_%" PRId64 "d.%s", DUMP_FILE_PATH, now, INPUT_SIZE_DUMP_EXT);
- snprintf(mDav1dOutYuvFileName, 256, "%s_%" PRId64 "dx.%s", DUMP_FILE_PATH, now,
- OUTPUT_YUV_DUMP_EXT);
-
- bool enableDumping = android::base::GetBoolProperty(ENABLE_DUMPING_FILES_PROPERTY,
- ENABLE_DUMPING_FILES_DEFAULT);
-
- num_frames_to_dump =
- android::base::GetIntProperty(NUM_FRAMES_TO_DUMP_PROPERTY, NUM_FRAMES_TO_DUMP_DEFAULT);
-
- if (enableDumping) {
- ALOGD("enableDumping = %d, num_frames_to_dump = %d", enableDumping, num_frames_to_dump);
-
- mInDataFile = fopen(mInDataFileName, "wb");
- if (mInDataFile == nullptr) {
- ALOGD("Could not open file %s", mInDataFileName);
- }
-
- mInSizeFile = fopen(mInSizeFileName, "wb");
- if (mInSizeFile == nullptr) {
- ALOGD("Could not open file %s", mInSizeFileName);
- }
-
- mDav1dOutYuvFile = fopen(mDav1dOutYuvFileName, "wb");
- if (mDav1dOutYuvFile == nullptr) {
- ALOGD("Could not open file %s", mDav1dOutYuvFileName);
- }
- }
+ mC2SoftDav1dDump.initDumping();
#endif
mSignalledError = false;
mSignalledOutputEos = false;
@@ -601,20 +555,7 @@
mInputBufferIndex = 0;
}
#ifdef FILE_DUMP_ENABLE
- if (mInDataFile != nullptr) {
- fclose(mInDataFile);
- mInDataFile = nullptr;
- }
-
- if (mInSizeFile != nullptr) {
- fclose(mInSizeFile);
- mInSizeFile = nullptr;
- }
-
- if (mDav1dOutYuvFile != nullptr) {
- fclose(mDav1dOutYuvFile);
- mDav1dOutYuvFile = nullptr;
- }
+ mC2SoftDav1dDump.destroyDumping();
#endif
}
@@ -657,6 +598,10 @@
}
}
+static void freeCallback(const uint8_t */*data*/, void */*cookie*/) {
+ return;
+}
+
void C2SoftDav1dDec::process(const std::unique_ptr<C2Work>& work,
const std::shared_ptr<C2BlockPool>& pool) {
work->result = C2_OK;
@@ -709,65 +654,24 @@
seq.max_height, (long)in_frameIndex);
}
- // insert OBU TD if it is not present.
- // TODO: b/286852962
- uint8_t obu_type = (bitstream[0] >> 3) & 0xf;
Dav1dData data;
- uint8_t* ptr = (obu_type == DAV1D_OBU_TD) ? dav1d_data_create(&data, inSize)
- : dav1d_data_create(&data, inSize + 2);
- if (ptr == nullptr) {
- ALOGE("dav1d_data_create failed!");
+ res = dav1d_data_wrap(&data, bitstream, inSize, freeCallback, nullptr);
+ if (res != 0) {
+ ALOGE("Decoder wrap error %s!", strerror(DAV1D_ERR(res)));
i_ret = -1;
-
} else {
data.m.timestamp = in_frameIndex;
+ // ALOGV("inSize=%ld, in_frameIndex=%ld, timestamp=%ld",
+ // inSize, frameIndex, data.m.timestamp);
- int new_Size;
- if (obu_type != DAV1D_OBU_TD) {
- new_Size = (int)(inSize + 2);
-
- // OBU TD
- ptr[0] = 0x12;
- ptr[1] = 0;
-
- memcpy(ptr + 2, bitstream, inSize);
- } else {
- new_Size = (int)(inSize);
- // TODO: b/277797541 - investigate how to wrap this pointer in Dav1dData to
- // avoid memcopy operations.
- memcpy(ptr, bitstream, new_Size);
- }
-
- // ALOGV("memcpy(ptr,bitstream,inSize=%ld,new_Size=%d,in_frameIndex=%ld,timestamp=%ld,"
- // "ptr[0,1,2,3,4]=%x,%x,%x,%x,%x)",
- // inSize, new_Size, frameIndex, data.m.timestamp, ptr[0], ptr[1], ptr[2],
- // ptr[3], ptr[4]);
// Dump the bitstream data (inputBuffer) if dumping is enabled.
#ifdef FILE_DUMP_ENABLE
- if (mInDataFile) {
- int ret = fwrite(ptr, 1, new_Size, mInDataFile);
-
- if (ret != new_Size) {
- ALOGE("Error in fwrite %s, requested %d, returned %d", mInDataFileName,
- new_Size, ret);
- }
- }
-
- // Dump the size per inputBuffer if dumping is enabled.
- if (mInSizeFile) {
- int ret = fwrite(&new_Size, 1, 4, mInSizeFile);
-
- if (ret != 4) {
- ALOGE("Error in fwrite %s, requested %d, returned %d", mInSizeFileName, 4,
- ret);
- }
- }
+ mC2SoftDav1dDump.dumpInput(ptr, new_Size);
#endif
bool b_draining = false;
- int res;
do {
res = dav1d_send_data(mDav1dCtx, &data);
@@ -1010,49 +914,6 @@
return true;
}
-#ifdef FILE_DUMP_ENABLE
-void C2SoftDav1dDec::writeDav1dOutYuvFile(const Dav1dPicture& p) {
- if (mDav1dOutYuvFile != NULL) {
- uint8_t* ptr;
- const int hbd = p.p.bpc > 8;
-
- ptr = (uint8_t*)p.data[0];
- for (int y = 0; y < p.p.h; y++) {
- int iSize = p.p.w << hbd;
- int ret = fwrite(ptr, 1, iSize, mDav1dOutYuvFile);
- if (ret != iSize) {
- ALOGE("Error in fwrite %s, requested %d, returned %d", mDav1dOutYuvFileName, iSize,
- ret);
- break;
- }
-
- ptr += p.stride[0];
- }
-
- if (p.p.layout != DAV1D_PIXEL_LAYOUT_I400) {
- // u/v
- const int ss_ver = p.p.layout == DAV1D_PIXEL_LAYOUT_I420;
- const int ss_hor = p.p.layout != DAV1D_PIXEL_LAYOUT_I444;
- const int cw = (p.p.w + ss_hor) >> ss_hor;
- const int ch = (p.p.h + ss_ver) >> ss_ver;
- for (int pl = 1; pl <= 2; pl++) {
- ptr = (uint8_t*)p.data[pl];
- for (int y = 0; y < ch; y++) {
- int iSize = cw << hbd;
- int ret = fwrite(ptr, 1, cw << hbd, mDav1dOutYuvFile);
- if (ret != iSize) {
- ALOGE("Error in fwrite %s, requested %d, returned %d", mDav1dOutYuvFileName,
- iSize, ret);
- break;
- }
- ptr += p.stride[1];
- }
- }
- }
- }
-}
-#endif
-
bool C2SoftDav1dDec::outputBuffer(const std::shared_ptr<C2BlockPool>& pool,
const std::unique_ptr<C2Work>& work) {
if (!(work && pool)) return false;
@@ -1114,16 +975,6 @@
// out_frameIndex that the decoded picture returns from dav1d.
int64_t out_frameIndex = img.m.timestamp;
-#if LIBYUV_VERSION < 1779
- if (!(img.p.layout != DAV1D_PIXEL_LAYOUT_I400 || img.p.layout != DAV1D_PIXEL_LAYOUT_I420)) {
- ALOGE("image_format %d not supported", img.p.layout);
- mSignalledError = true;
- work->workletsProcessed = 1u;
- work->result = C2_CORRUPTED;
- return false;
- }
-#endif
-
const bool isMonochrome = img.p.layout == DAV1D_PIXEL_LAYOUT_I400;
int bitdepth = img.p.bpc;
@@ -1141,17 +992,6 @@
allowRGBA1010102 = true;
}
format = getHalPixelFormatForBitDepth10(allowRGBA1010102);
-#if !HAVE_LIBYUV_I410_I210_TO_AB30
- if ((format == HAL_PIXEL_FORMAT_RGBA_1010102) &&
- (is_img_ready ? img.p.layout == DAV1D_PIXEL_LAYOUT_I420
- : buffer->image_format != libgav1::kImageFormatYuv420)) {
- ALOGE("Only YUV420 output is supported when targeting RGBA_1010102");
- mSignalledError = true;
- work->result = C2_OMITTED;
- work->workletsProcessed = 1u;
- return false;
- }
-#endif
}
if (mHalPixelFormat != format) {
@@ -1206,6 +1046,19 @@
size_t dstUStride = layout.planes[C2PlanarLayout::PLANE_U].rowInc;
size_t dstVStride = layout.planes[C2PlanarLayout::PLANE_V].rowInc;
+ CONV_FORMAT_T convFormat;
+ switch (img.p.layout) {
+ case DAV1D_PIXEL_LAYOUT_I444:
+ convFormat = CONV_FORMAT_I444;
+ break;
+ case DAV1D_PIXEL_LAYOUT_I422:
+ convFormat = CONV_FORMAT_I422;
+ break;
+ default:
+ convFormat = CONV_FORMAT_I420;
+ break;
+ }
+
if (bitdepth == 10) {
// TODO: b/277797541 - Investigate if we can ask DAV1D to output the required format during
// decompression to avoid color conversion.
@@ -1217,146 +1070,67 @@
size_t srcVStride = img.stride[1] / 2;
if (format == HAL_PIXEL_FORMAT_RGBA_1010102) {
- bool processed = false;
-#if HAVE_LIBYUV_I410_I210_TO_AB30
- if (img.p.layout == DAV1D_PIXEL_LAYOUT_I444) {
- libyuv::I410ToAB30Matrix(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride, dstY,
- dstYStride, &libyuv::kYuvV2020Constants, mWidth, mHeight);
- processed = true;
- } else if (img.p.layout == DAV1D_PIXEL_LAYOUT_I422) {
- libyuv::I210ToAB30Matrix(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride, dstY,
- dstYStride, &libyuv::kYuvV2020Constants, mWidth, mHeight);
- processed = true;
- }
-#endif // HAVE_LIBYUV_I410_I210_TO_AB30
- if (!processed) {
- if (isMonochrome) {
- const size_t tmpSize = mWidth;
- const bool needFill = tmpSize > mTmpFrameBufferSize;
- if (!allocTmpFrameBuffer(tmpSize)) {
- ALOGE("Error allocating temp conversion buffer (%zu bytes)", tmpSize);
- setError(work, C2_NO_MEMORY);
- return false;
- }
- srcU = srcV = mTmpFrameBuffer.get();
- srcUStride = srcVStride = 0;
- if (needFill) {
- std::fill_n(mTmpFrameBuffer.get(), tmpSize, 512);
- }
+ if (isMonochrome) {
+ const size_t tmpSize = mWidth;
+ const bool needFill = tmpSize > mTmpFrameBufferSize;
+ if (!allocTmpFrameBuffer(tmpSize)) {
+ ALOGE("Error allocating temp conversion buffer (%zu bytes)", tmpSize);
+ setError(work, C2_NO_MEMORY);
+ return false;
}
- convertYUV420Planar16ToY410OrRGBA1010102(
- (uint32_t*)dstY, srcY, srcU, srcV, srcYStride, srcUStride, srcVStride,
- dstYStride / sizeof(uint32_t), mWidth, mHeight,
- std::static_pointer_cast<const C2ColorAspectsStruct>(codedColorAspects));
+ srcU = srcV = mTmpFrameBuffer.get();
+ srcUStride = srcVStride = 0;
+ if (needFill) {
+ std::fill_n(mTmpFrameBuffer.get(), tmpSize, 512);
+ }
}
+ convertPlanar16ToY410OrRGBA1010102(
+ dstY, srcY, srcU, srcV, srcYStride, srcUStride, srcVStride,
+ dstYStride, mWidth, mHeight,
+ std::static_pointer_cast<const C2ColorAspectsStruct>(codedColorAspects),
+ convFormat);
} else if (format == HAL_PIXEL_FORMAT_YCBCR_P010) {
dstYStride /= 2;
dstUStride /= 2;
dstVStride /= 2;
-#if LIBYUV_VERSION >= 1779
+ size_t tmpSize = 0;
if ((img.p.layout == DAV1D_PIXEL_LAYOUT_I444) ||
(img.p.layout == DAV1D_PIXEL_LAYOUT_I422)) {
- // TODO(https://crbug.com/libyuv/952): replace this block with libyuv::I410ToP010
- // and libyuv::I210ToP010 when they are available. Note it may be safe to alias dstY
- // in I010ToP010, but the libyuv API doesn't make any guarantees.
- const size_t tmpSize = dstYStride * mHeight + dstUStride * align(mHeight, 2);
+ tmpSize = dstYStride * mHeight + dstUStride * align(mHeight, 2);
if (!allocTmpFrameBuffer(tmpSize)) {
ALOGE("Error allocating temp conversion buffer (%zu bytes)", tmpSize);
setError(work, C2_NO_MEMORY);
return false;
}
- uint16_t* const tmpY = mTmpFrameBuffer.get();
- uint16_t* const tmpU = tmpY + dstYStride * mHeight;
- uint16_t* const tmpV = tmpU + dstUStride * align(mHeight, 2) / 2;
- if (img.p.layout == DAV1D_PIXEL_LAYOUT_I444) {
- libyuv::I410ToI010(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride, tmpY,
- dstYStride, tmpU, dstUStride, tmpV, dstUStride, mWidth,
- mHeight);
- } else {
- libyuv::I210ToI010(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride, tmpY,
- dstYStride, tmpU, dstUStride, tmpV, dstUStride, mWidth,
- mHeight);
- }
- libyuv::I010ToP010(tmpY, dstYStride, tmpU, dstUStride, tmpV, dstVStride,
- (uint16_t*)dstY, dstYStride, (uint16_t*)dstU, dstUStride, mWidth,
- mHeight);
- } else {
- convertYUV420Planar16ToP010((uint16_t*)dstY, (uint16_t*)dstU, srcY, srcU, srcV,
- srcYStride, srcUStride, srcVStride, dstYStride,
- dstUStride, mWidth, mHeight, isMonochrome);
}
-#else // LIBYUV_VERSION < 1779
- convertYUV420Planar16ToP010((uint16_t*)dstY, (uint16_t*)dstU, srcY, srcU, srcV,
- srcYStride, srcUStride, srcVStride, dstYStride, dstUStride,
- mWidth, mHeight, isMonochrome);
-#endif // LIBYUV_VERSION >= 1779
+ convertPlanar16ToP010((uint16_t*)dstY, (uint16_t*)dstU, srcY, srcU, srcV, srcYStride,
+ srcUStride, srcVStride, dstYStride, dstUStride, dstVStride,
+ mWidth, mHeight, isMonochrome, convFormat, mTmpFrameBuffer.get(),
+ tmpSize);
} else {
-#if LIBYUV_VERSION >= 1779
+ size_t tmpSize = 0;
if (img.p.layout == DAV1D_PIXEL_LAYOUT_I444) {
- // TODO(https://crbug.com/libyuv/950): replace this block with libyuv::I410ToI420
- // when it's available.
- const size_t tmpSize = dstYStride * mHeight + dstUStride * align(mHeight, 2);
+ tmpSize = dstYStride * mHeight + dstUStride * align(mHeight, 2);
if (!allocTmpFrameBuffer(tmpSize)) {
ALOGE("Error allocating temp conversion buffer (%zu bytes)", tmpSize);
setError(work, C2_NO_MEMORY);
return false;
}
- uint16_t* const tmpY = mTmpFrameBuffer.get();
- uint16_t* const tmpU = tmpY + dstYStride * mHeight;
- uint16_t* const tmpV = tmpU + dstUStride * align(mHeight, 2) / 2;
- libyuv::I410ToI010(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride, tmpY,
- dstYStride, tmpU, dstUStride, tmpV, dstVStride, mWidth, mHeight);
- libyuv::I010ToI420(tmpY, dstYStride, tmpU, dstUStride, tmpV, dstUStride, dstY,
- dstYStride, dstU, dstUStride, dstV, dstVStride, mWidth, mHeight);
- } else if (img.p.layout == DAV1D_PIXEL_LAYOUT_I422) {
- libyuv::I210ToI420(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride, dstY,
- dstYStride, dstU, dstUStride, dstV, dstVStride, mWidth, mHeight);
- } else {
- convertYUV420Planar16ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride,
- srcUStride, srcVStride, dstYStride, dstUStride, mWidth,
- mHeight, isMonochrome);
}
-#else // LIBYUV_VERSION < 1779
- convertYUV420Planar16ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride, srcUStride,
- srcVStride, dstYStride, dstUStride, mWidth, mHeight,
- isMonochrome);
-#endif // LIBYUV_VERSION >= 1779
+ convertPlanar16ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride, srcUStride,
+ srcVStride, dstYStride, dstUStride, dstVStride, mWidth, mHeight,
+ isMonochrome, convFormat, mTmpFrameBuffer.get(), tmpSize);
}
- // Dump the output buffer if dumping is enabled (debug only).
-#ifdef FILE_DUMP_ENABLE
- FILE* fp_out = mDav1dOutYuvFile;
-
// if(mOutputBufferIndex % 100 == 0)
ALOGV("output a 10bit picture %dx%d from dav1d "
"(mInputBufferIndex=%d,mOutputBufferIndex=%d,format=%d).",
mWidth, mHeight, mInputBufferIndex, mOutputBufferIndex, format);
- if (fp_out && mOutputBufferIndex <= num_frames_to_dump) {
- for (int i = 0; i < mHeight; i++) {
- int ret = fwrite((uint8_t*)srcY + i * srcYStride * 2, 1, mWidth * 2, fp_out);
- if (ret != mWidth * 2) {
- ALOGE("Error in fwrite, requested %d, returned %d", mWidth * 2, ret);
- break;
- }
- }
-
- for (int i = 0; i < mHeight / 2; i++) {
- int ret = fwrite((uint8_t*)srcU + i * srcUStride * 2, 1, mWidth, fp_out);
- if (ret != mWidth) {
- ALOGE("Error in fwrite, requested %d, returned %d", mWidth, ret);
- break;
- }
- }
-
- for (int i = 0; i < mHeight / 2; i++) {
- int ret = fwrite((uint8_t*)srcV + i * srcVStride * 2, 1, mWidth, fp_out);
- if (ret != mWidth) {
- ALOGE("Error in fwrite, requested %d, returned %d", mWidth, ret);
- break;
- }
- }
- }
+ // Dump the output buffer if dumping is enabled (debug only).
+#ifdef FILE_DUMP_ENABLE
+ mC2SoftDav1dDump.dumpOutput<uint16_t>(srcY, srcU, srcV, srcYStride, srcUStride, srcVStride,
+ mWidth, mHeight);
#endif
} else {
const uint8_t* srcY = (const uint8_t*)img.data[0];
@@ -1367,51 +1141,19 @@
size_t srcUStride = img.stride[1];
size_t srcVStride = img.stride[1];
- // Dump the output buffer is dumping is enabled (debug only)
-#ifdef FILE_DUMP_ENABLE
- FILE* fp_out = mDav1dOutYuvFile;
// if(mOutputBufferIndex % 100 == 0)
ALOGV("output a 8bit picture %dx%d from dav1d "
"(mInputBufferIndex=%d,mOutputBufferIndex=%d,format=%d).",
mWidth, mHeight, mInputBufferIndex, mOutputBufferIndex, format);
- if (fp_out && mOutputBufferIndex <= num_frames_to_dump) {
- for (int i = 0; i < mHeight; i++) {
- int ret = fwrite((uint8_t*)srcY + i * srcYStride, 1, mWidth, fp_out);
- if (ret != mWidth) {
- ALOGE("Error in fwrite, requested %d, returned %d", mWidth, ret);
- break;
- }
- }
-
- for (int i = 0; i < mHeight / 2; i++) {
- int ret = fwrite((uint8_t*)srcU + i * srcUStride, 1, mWidth / 2, fp_out);
- if (ret != mWidth / 2) {
- ALOGE("Error in fwrite, requested %d, returned %d", mWidth / 2, ret);
- break;
- }
- }
-
- for (int i = 0; i < mHeight / 2; i++) {
- int ret = fwrite((uint8_t*)srcV + i * srcVStride, 1, mWidth / 2, fp_out);
- if (ret != mWidth / 2) {
- ALOGE("Error in fwrite, requested %d, returned %d", mWidth / 2, ret);
- break;
- }
- }
- }
+ // Dump the output buffer is dumping is enabled (debug only)
+#ifdef FILE_DUMP_ENABLE
+ mC2SoftDav1dDump.dumpOutput<uint8_t>(srcY, srcU, srcV, srcYStride, srcUStride, srcVStride,
+ mWidth, mHeight);
#endif
- if (img.p.layout == DAV1D_PIXEL_LAYOUT_I444) {
- libyuv::I444ToI420(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride, dstY,
- dstYStride, dstU, dstUStride, dstV, dstVStride, mWidth, mHeight);
- } else if (img.p.layout == DAV1D_PIXEL_LAYOUT_I422) {
- libyuv::I422ToI420(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride, dstY,
- dstYStride, dstU, dstUStride, dstV, dstVStride, mWidth, mHeight);
- } else {
- convertYUV420Planar8ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride, srcUStride,
- srcVStride, dstYStride, dstUStride, dstVStride, mWidth,
- mHeight, isMonochrome);
- }
+ convertPlanar8ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride, srcUStride, srcVStride,
+ dstYStride, dstUStride, dstVStride, mWidth, mHeight, isMonochrome,
+ convFormat);
}
dav1d_picture_unref(&img);
diff --git a/media/codec2/components/dav1d/C2SoftDav1dDec.h b/media/codec2/components/dav1d/C2SoftDav1dDec.h
index 5201456..e3d2a93 100644
--- a/media/codec2/components/dav1d/C2SoftDav1dDec.h
+++ b/media/codec2/components/dav1d/C2SoftDav1dDec.h
@@ -28,12 +28,9 @@
#include <dav1d/dav1d.h>
#include <deque>
+#include <C2SoftDav1dDump.h>
//#define FILE_DUMP_ENABLE 1
-#define DUMP_FILE_PATH "/data/local/tmp/dump"
-#define INPUT_DATA_DUMP_EXT "av1"
-#define INPUT_SIZE_DUMP_EXT "size"
-#define OUTPUT_YUV_DUMP_EXT "yuv"
namespace android {
@@ -122,17 +119,7 @@
void flushDav1d();
#ifdef FILE_DUMP_ENABLE
- char mInDataFileName[256];
- char mInSizeFileName[256];
- char mDav1dOutYuvFileName[256];
-
- FILE* mInDataFile = nullptr;
- FILE* mInSizeFile = nullptr;
- FILE* mDav1dOutYuvFile = nullptr;
-
- void writeDav1dOutYuvFile(const Dav1dPicture& p);
-
- int num_frames_to_dump = 0;
+ C2SoftDav1dDump mC2SoftDav1dDump;
#endif
C2_DO_NOT_COPY(C2SoftDav1dDec);
diff --git a/media/codec2/components/dav1d/C2SoftDav1dDump.cpp b/media/codec2/components/dav1d/C2SoftDav1dDump.cpp
new file mode 100644
index 0000000..ec8d6cd
--- /dev/null
+++ b/media/codec2/components/dav1d/C2SoftDav1dDump.cpp
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+//#define LOG_NDEBUG 0
+#define LOG_TAG "C2SoftDav1dDump"
+#include "C2SoftDav1dDump.h"
+
+namespace android {
+
+// Flag to enable dumping the bitsteram and the decoded pictures to files.
+static const bool ENABLE_DUMPING_FILES_DEFAULT = true;
+static const char ENABLE_DUMPING_FILES_PROPERTY[] = "debug.dav1d.enabledumping";
+
+// The number of frames to dump to a file
+static const int NUM_FRAMES_TO_DUMP_DEFAULT = INT_MAX;
+static const char NUM_FRAMES_TO_DUMP_PROPERTY[] = "debug.dav1d.numframestodump";
+
+// start dumping from this frame
+static const int STARTING_FRAME_TO_DUMP_DEFAULT = 0;
+static const char STARTING_FRAME_TO_DUMP_PROPERTY[] = "debug.dav1d.startingframetodump";
+
+void C2SoftDav1dDump::initDumping() {
+ nsecs_t now = systemTime();
+ snprintf(mInDataFileName, kFileNameLength, "%s_%" PRId64 "d.%s", DUMP_FILE_PATH, now,
+ INPUT_DATA_DUMP_EXT);
+ snprintf(mInSizeFileName, kFileNameLength, "%s_%" PRId64 "d.%s", DUMP_FILE_PATH, now,
+ INPUT_SIZE_DUMP_EXT);
+ snprintf(mDav1dOutYuvFileName, kFileNameLength, "%s_%" PRId64 "dx.%s", DUMP_FILE_PATH, now,
+ OUTPUT_YUV_DUMP_EXT);
+
+ mFramesToDump =
+ android::base::GetIntProperty(NUM_FRAMES_TO_DUMP_PROPERTY, NUM_FRAMES_TO_DUMP_DEFAULT);
+ mFirstFrameToDump = android::base::GetIntProperty(STARTING_FRAME_TO_DUMP_PROPERTY,
+ STARTING_FRAME_TO_DUMP_DEFAULT);
+ bool enableDumping = android::base::GetBoolProperty(ENABLE_DUMPING_FILES_PROPERTY,
+ ENABLE_DUMPING_FILES_DEFAULT);
+ ALOGD("enableDumping = %d, mFramesToDump = %d", enableDumping, mFramesToDump);
+
+ if (enableDumping) {
+ mInDataFile = fopen(mInDataFileName, "wb");
+ if (mInDataFile == nullptr) {
+ ALOGD("Could not open file %s", mInDataFileName);
+ }
+
+ mInSizeFile = fopen(mInSizeFileName, "wb");
+ if (mInSizeFile == nullptr) {
+ ALOGD("Could not open file %s", mInSizeFileName);
+ }
+
+ mDav1dOutYuvFile = fopen(mDav1dOutYuvFileName, "wb");
+ if (mDav1dOutYuvFile == nullptr) {
+ ALOGD("Could not open file %s", mDav1dOutYuvFileName);
+ }
+ }
+}
+
+void C2SoftDav1dDump::destroyDumping() {
+ if (mInDataFile != nullptr) {
+ fclose(mInDataFile);
+ mInDataFile = nullptr;
+ }
+
+ if (mInSizeFile != nullptr) {
+ fclose(mInSizeFile);
+ mInSizeFile = nullptr;
+ }
+
+ if (mDav1dOutYuvFile != nullptr) {
+ fclose(mDav1dOutYuvFile);
+ mDav1dOutYuvFile = nullptr;
+ }
+}
+
+void C2SoftDav1dDump::dumpInput(uint8_t* ptr, int size) {
+ if (mInDataFile) {
+ int ret = fwrite(ptr, 1, size, mInDataFile);
+
+ if (ret != size) {
+ ALOGE("Error in fwrite %s, requested %d, returned %d", mInDataFileName, size, ret);
+ }
+ }
+
+ // Dump the size per inputBuffer if dumping is enabled.
+ if (mInSizeFile) {
+ int ret = fwrite(&size, 1, 4, mInSizeFile);
+
+ if (ret != 4) {
+ ALOGE("Error in fwrite %s, requested %d, returned %d", mInSizeFileName, 4, ret);
+ }
+ }
+}
+
+template <typename T>
+void C2SoftDav1dDump::dumpOutput(const T* srcY, const T* srcU, const T* srcV, size_t srcYStride,
+ size_t srcUStride, size_t srcVStride, int width, int height) {
+ mOutputCount++;
+ FILE* fp_out = mDav1dOutYuvFile;
+ int typeSize = sizeof(T);
+ if (fp_out && mOutputCount >= mFirstFrameToDump &&
+ mOutputCount <= (mFirstFrameToDump + mFramesToDump - 1)) {
+ for (int i = 0; i < height; i++) {
+ int ret =
+ fwrite((uint8_t*)srcY + i * srcYStride * typeSize, 1, width * typeSize, fp_out);
+ if (ret != width * typeSize) {
+ ALOGE("Error in fwrite, requested %d, returned %d", width * typeSize, ret);
+ break;
+ }
+ }
+
+ for (int i = 0; i < height / 2; i++) {
+ int ret = fwrite((uint8_t*)srcU + i * srcUStride * typeSize, 1, width * typeSize / 2,
+ fp_out);
+ if (ret != width * typeSize / 2) {
+ ALOGE("Error in fwrite, requested %d, returned %d", width * typeSize / 2, ret);
+ break;
+ }
+ }
+
+ for (int i = 0; i < height / 2; i++) {
+ int ret = fwrite((uint8_t*)srcV + i * srcVStride * typeSize, 1, width * typeSize / 2,
+ fp_out);
+ if (ret != width * typeSize / 2) {
+ ALOGE("Error in fwrite, requested %d, returned %d", width * typeSize / 2, ret);
+ break;
+ }
+ }
+ }
+}
+
+void C2SoftDav1dDump::writeDav1dOutYuvFile(const Dav1dPicture& p) {
+ if (mDav1dOutYuvFile != NULL) {
+ uint8_t* ptr;
+ const int hbd = p.p.bpc > 8;
+
+ ptr = (uint8_t*)p.data[0];
+ for (int y = 0; y < p.p.h; y++) {
+ int iSize = p.p.w << hbd;
+ int ret = fwrite(ptr, 1, iSize, mDav1dOutYuvFile);
+ if (ret != iSize) {
+ ALOGE("Error in fwrite %s, requested %d, returned %d", mDav1dOutYuvFileName, iSize,
+ ret);
+ break;
+ }
+
+ ptr += p.stride[0];
+ }
+
+ if (p.p.layout != DAV1D_PIXEL_LAYOUT_I400) {
+ // u/v
+ const int ss_ver = p.p.layout == DAV1D_PIXEL_LAYOUT_I420;
+ const int ss_hor = p.p.layout != DAV1D_PIXEL_LAYOUT_I444;
+ const int cw = (p.p.w + ss_hor) >> ss_hor;
+ const int ch = (p.p.h + ss_ver) >> ss_ver;
+ for (int pl = 1; pl <= 2; pl++) {
+ ptr = (uint8_t*)p.data[pl];
+ for (int y = 0; y < ch; y++) {
+ int iSize = cw << hbd;
+ int ret = fwrite(ptr, 1, cw << hbd, mDav1dOutYuvFile);
+ if (ret != iSize) {
+ ALOGE("Error in fwrite %s, requested %d, returned %d", mDav1dOutYuvFileName,
+ iSize, ret);
+ break;
+ }
+ ptr += p.stride[1];
+ }
+ }
+ }
+ }
+}
+
+template void C2SoftDav1dDump::dumpOutput<uint8_t>(const uint8_t* srcY, const uint8_t* srcU,
+ const uint8_t* srcV, size_t srcYStride,
+ size_t srcUStride, size_t srcVStride, int width,
+ int height);
+template void C2SoftDav1dDump::dumpOutput<uint16_t>(const uint16_t* srcY, const uint16_t* srcU,
+ const uint16_t* srcV, size_t srcYStride,
+ size_t srcUStride, size_t srcVStride, int width,
+ int height);
+} // namespace android
\ No newline at end of file
diff --git a/media/codec2/components/dav1d/C2SoftDav1dDump.h b/media/codec2/components/dav1d/C2SoftDav1dDump.h
new file mode 100644
index 0000000..ea7a48a
--- /dev/null
+++ b/media/codec2/components/dav1d/C2SoftDav1dDump.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <android-base/properties.h>
+#include <Codec2CommonUtils.h>
+#include <Codec2Mapper.h>
+#include <dav1d/dav1d.h>
+
+#define DUMP_FILE_PATH "/data/local/tmp/dump"
+#define INPUT_DATA_DUMP_EXT "av1"
+#define INPUT_SIZE_DUMP_EXT "size"
+#define OUTPUT_YUV_DUMP_EXT "yuv"
+
+namespace android {
+constexpr size_t kFileNameLength = 256;
+
+class C2SoftDav1dDump {
+ public:
+ void initDumping();
+ void destroyDumping();
+ void dumpInput(uint8_t* ptr, int new_size);
+ template <typename T>
+ void dumpOutput(const T* srcY, const T* srcU, const T* srcV, size_t srcYStride,
+ size_t srcUStride, size_t srcVStride, int width, int height);
+ void writeDav1dOutYuvFile(const Dav1dPicture& p);
+
+ private:
+ int mFramesToDump = 0;
+ int mFirstFrameToDump = 0;
+ int mOutputCount = 0;
+
+ char mInDataFileName[kFileNameLength];
+ char mInSizeFileName[kFileNameLength];
+ char mDav1dOutYuvFileName[kFileNameLength];
+
+ FILE* mInDataFile = nullptr;
+ FILE* mInSizeFile = nullptr;
+ FILE* mDav1dOutYuvFile = nullptr;
+};
+} // namespace android
diff --git a/media/codec2/hal/aidl/Android.bp b/media/codec2/hal/aidl/Android.bp
index b19f78c..a6a6b77 100644
--- a/media/codec2/hal/aidl/Android.bp
+++ b/media/codec2/hal/aidl/Android.bp
@@ -6,6 +6,7 @@
// use libcodec2-aidl-client-defaults instead
cc_library {
name: "libcodec2_aidl_client",
+ min_sdk_version: "31",
srcs: [
"BufferTypes.cpp",
@@ -50,105 +51,101 @@
}
// DO NOT DEPEND ON THIS DIRECTLY
-// use libcodec2-hidl-defaults instead
-//cc_library {
-// name: "libcodec2_hidl@1.0",
-// vendor_available: true,
-// min_sdk_version: "29",
-// apex_available: [
-// "//apex_available:platform",
-// "com.android.media.swcodec",
-// ],
-//
-// defaults: ["hidl_defaults"],
-//
-// srcs: [
-// "Component.cpp",
-// "ComponentInterface.cpp",
-// "ComponentStore.cpp",
-// "Configurable.cpp",
-// "InputBufferManager.cpp",
-// "InputSurface.cpp",
-// "InputSurfaceConnection.cpp",
-// "types.cpp",
-// ],
-//
-// header_libs: [
-// "libbinder_headers",
-// "libcodec2_hal_common",
-// "libcodec2_internal", // private
-// "libsystem_headers",
-// ],
-//
-// shared_libs: [
-// "android.hardware.graphics.bufferqueue@1.0",
-// "android.hardware.graphics.bufferqueue@2.0",
-// "android.hardware.graphics.common@1.0",
-// "android.hardware.media@1.0",
-// "android.hardware.media.bufferpool@2.0",
-// "android.hardware.media.c2@1.0",
-// "android.hardware.media.omx@1.0",
-// "libbase",
-// "libcodec2",
-// "libcodec2_vndk",
-// "libcodec2_hidl_plugin_stub",
-// "libcutils",
-// "libhidlbase",
-// "liblog",
-// "libstagefright_bufferpool@2.0.1",
-// "libstagefright_bufferqueue_helper_novndk",
-// "libui",
-// "libutils",
-// ],
-//
-// target: {
-// vendor: {
-// exclude_shared_libs: [
-// "libstagefright_bufferqueue_helper_novndk",
-// "libcodec2_hidl_plugin_stub",
-// ],
-// shared_libs: [
-// "libstagefright_bufferqueue_helper",
-// "libcodec2_hidl_plugin",
-// ],
-// },
-// apex: {
-// exclude_shared_libs: [
-// "libcodec2_hidl_plugin",
-// "libcodec2_hidl_plugin_stub",
-// ],
-// },
-// },
-//
-// export_include_dirs: [
-// "include",
-// ],
-//
-// export_shared_lib_headers: [
-// "android.hardware.media.c2@1.0",
-// "libcodec2",
-// "libcodec2_vndk",
-// "libhidlbase",
-// "libstagefright_bufferpool@2.0.1",
-// "libui",
-// ],
-//}
-//
-//// public dependency for Codec 2.0 HAL service implementations
-//cc_defaults {
-// name: "libcodec2-hidl-defaults@1.0",
-// defaults: ["libcodec2-impl-defaults"],
-//
-// shared_libs: [
-// "android.hardware.media.c2@1.0",
-// "libcodec2_hidl@1.0",
-// ],
-//}
+// use libcodec2-aidl-defaults instead
+cc_library {
+ name: "libcodec2_aidl",
+ min_sdk_version: "31",
+ vendor_available: true,
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.media.swcodec",
+ "test_com.android.media.swcodec",
+ ],
+
+ srcs: [
+ "BufferTypes.cpp",
+ "Component.cpp",
+ "ComponentInterface.cpp",
+ "ComponentStore.cpp",
+ "Configurable.cpp",
+ "InputBufferManager.cpp",
+ "ParamTypes.cpp",
+ ],
+
+ header_libs: [
+ "libcodec2_internal", // private
+ ],
+
+ shared_libs: [
+ "android.hardware.common-V2-ndk",
+ "android.hardware.media.bufferpool2-V1-ndk",
+ "android.hardware.media.c2-V1-ndk",
+ "libbase",
+ "libbinder_ndk",
+ "libcodec2",
+ "libcodec2_hal_common",
+ "libcodec2_hidl_plugin_stub",
+ "libcodec2_vndk",
+ "libcutils",
+ "libhidlbase",
+ "liblog",
+ "libnativewindow",
+ "libstagefright_aidl_bufferpool2",
+ "libstagefright_bufferpool@2.0.1",
+ "libui",
+ "libutils",
+ ],
+
+ static_libs: [
+ "libaidlcommonsupport",
+ ],
+
+ target: {
+ vendor: {
+ exclude_shared_libs: [
+ "libcodec2_hidl_plugin_stub",
+ ],
+ shared_libs: [
+ "libcodec2_hidl_plugin",
+ ],
+ },
+ apex: {
+ exclude_shared_libs: [
+ "libcodec2_hidl_plugin_stub",
+ "libcodec2_hidl_plugin",
+ ],
+ },
+ },
+
+ export_include_dirs: [
+ "include",
+ ],
+
+ export_shared_lib_headers: [
+ "android.hardware.media.c2-V1-ndk",
+ "libcodec2",
+ "libstagefright_bufferpool@2.0.1",
+ "libui",
+ ],
+}
+
+// public dependency for Codec 2.0 HAL service implementations
+cc_defaults {
+ name: "libcodec2-aidl-defaults",
+ min_sdk_version: "31",
+ defaults: ["libcodec2-impl-defaults"],
+
+ shared_libs: [
+ "android.hardware.media.c2-V1-ndk",
+ "libbinder_ndk",
+ "libcodec2_aidl",
+ ],
+}
// public dependency for Codec 2.0 HAL client
cc_defaults {
name: "libcodec2-aidl-client-defaults",
- min_sdk_version: "34",
+ min_sdk_version: "31",
defaults: ["libcodec2-impl-defaults"],
shared_libs: [
@@ -156,3 +153,28 @@
"libcodec2_aidl_client",
],
}
+
+cc_fuzz {
+ name: "libcodec2-aidl-fuzzer",
+ vendor: true,
+ srcs: [
+ "fuzzer.cpp",
+ ],
+ defaults: [
+ "libcodec2-aidl-defaults",
+ "service_fuzzer_defaults",
+ ],
+ shared_libs: [
+ "libcodec2_vndk",
+
+ "libcodec2_soft_avcdec",
+ "libcodec2_soft_avcenc",
+ "libcodec2_soft_aacdec",
+ "libcodec2_soft_aacenc",
+ ],
+ fuzz_config: {
+ cc: [
+ "wonsik@google.com",
+ ],
+ },
+}
diff --git a/media/codec2/hal/aidl/Component.cpp b/media/codec2/hal/aidl/Component.cpp
index 7994d32..9c21a5b 100644
--- a/media/codec2/hal/aidl/Component.cpp
+++ b/media/codec2/hal/aidl/Component.cpp
@@ -15,40 +15,42 @@
*/
//#define LOG_NDEBUG 0
-#define LOG_TAG "Codec2-Component@1.2"
+#define LOG_TAG "Codec2-Component-Aidl"
#include <android-base/logging.h>
-#include <codec2/hidl/1.2/Component.h>
-#include <codec2/hidl/1.2/ComponentStore.h>
-#include <codec2/hidl/1.2/InputBufferManager.h>
+#include <codec2/aidl/Component.h>
+#include <codec2/aidl/ComponentStore.h>
+#include <codec2/aidl/InputBufferManager.h>
#ifndef __ANDROID_APEX__
#include <FilterWrapper.h>
#endif
-#include <hidl/HidlBinderSupport.h>
+#include <android/binder_auto_utils.h>
+#include <android/binder_interface_utils.h>
#include <utils/Timers.h>
-#include <C2BqBufferPriv.h>
#include <C2Debug.h>
#include <C2PlatformSupport.h>
#include <chrono>
#include <thread>
+namespace aidl {
namespace android {
namespace hardware {
namespace media {
namespace c2 {
-namespace V1_2 {
namespace utils {
-using namespace ::android;
+using ::aidl::android::hardware::common::NativeHandle;
+using ::aidl::android::hardware::media::bufferpool2::IClientManager;
+using ::ndk::ScopedAStatus;
// ComponentListener wrapper
struct Component::Listener : public C2Component::Listener {
- Listener(const sp<Component>& component) :
+ Listener(const std::shared_ptr<Component>& component) :
mComponent(component),
mListener(component->mListener) {
}
@@ -56,9 +58,9 @@
virtual void onError_nb(
std::weak_ptr<C2Component> /* c2component */,
uint32_t errorCode) override {
- sp<IComponentListener> listener = mListener.promote();
+ std::shared_ptr<IComponentListener> listener = mListener.lock();
if (listener) {
- Return<void> transStatus = listener->onError(Status::OK, errorCode);
+ ScopedAStatus transStatus = listener->onError(Status{Status::OK}, errorCode);
if (!transStatus.isOk()) {
LOG(ERROR) << "Component::Listener::onError_nb -- "
<< "transaction failed.";
@@ -70,20 +72,20 @@
std::weak_ptr<C2Component> /* c2component */,
std::vector<std::shared_ptr<C2SettingResult>> c2settingResult
) override {
- sp<IComponentListener> listener = mListener.promote();
+ std::shared_ptr<IComponentListener> listener = mListener.lock();
if (listener) {
- hidl_vec<SettingResult> settingResults(c2settingResult.size());
+ std::vector<SettingResult> settingResults(c2settingResult.size());
size_t ix = 0;
for (const std::shared_ptr<C2SettingResult> &c2result :
c2settingResult) {
if (c2result) {
- if (!objcpy(&settingResults[ix++], *c2result)) {
+ if (!ToAidl(&settingResults[ix++], *c2result)) {
break;
}
}
}
settingResults.resize(ix);
- Return<void> transStatus = listener->onTripped(settingResults);
+ ScopedAStatus transStatus = listener->onTripped(settingResults);
if (!transStatus.isOk()) {
LOG(ERROR) << "Component::Listener::onTripped_nb -- "
<< "transaction failed.";
@@ -106,113 +108,57 @@
}
}
- sp<IComponentListener> listener = mListener.promote();
+ std::shared_ptr<IComponentListener> listener = mListener.lock();
if (listener) {
WorkBundle workBundle;
- sp<Component> strongComponent = mComponent.promote();
- beginTransferBufferQueueBlocks(c2workItems, true);
- if (!objcpy(&workBundle, c2workItems, strongComponent ?
+ std::shared_ptr<Component> strongComponent = mComponent.lock();
+ // TODO
+ // beginTransferBufferQueueBlocks(c2workItems, true);
+ if (!ToAidl(&workBundle, c2workItems, strongComponent ?
&strongComponent->mBufferPoolSender : nullptr)) {
LOG(ERROR) << "Component::Listener::onWorkDone_nb -- "
<< "received corrupted work items.";
- endTransferBufferQueueBlocks(c2workItems, false, true);
+ // TODO
+ // endTransferBufferQueueBlocks(c2workItems, false, true);
return;
}
- Return<void> transStatus = listener->onWorkDone(workBundle);
+ ScopedAStatus transStatus = listener->onWorkDone(workBundle);
if (!transStatus.isOk()) {
LOG(ERROR) << "Component::Listener::onWorkDone_nb -- "
<< "transaction failed.";
- endTransferBufferQueueBlocks(c2workItems, false, true);
+ // TODO
+ // endTransferBufferQueueBlocks(c2workItems, false, true);
return;
}
- endTransferBufferQueueBlocks(c2workItems, true, true);
+ // TODO
+ // endTransferBufferQueueBlocks(c2workItems, true, true);
}
}
protected:
- wp<Component> mComponent;
- wp<IComponentListener> mListener;
+ std::weak_ptr<Component> mComponent;
+ std::weak_ptr<IComponentListener> mListener;
};
-// Component::Sink
-struct Component::Sink : public IInputSink {
- std::shared_ptr<Component> mComponent;
- sp<IConfigurable> mConfigurable;
-
- virtual Return<Status> queue(const WorkBundle& workBundle) override {
- return mComponent->queue(workBundle);
- }
-
- virtual Return<sp<IConfigurable>> getConfigurable() override {
- return mConfigurable;
- }
-
- Sink(const std::shared_ptr<Component>& component);
- virtual ~Sink() override;
-
- // Process-wide map: Component::Sink -> C2Component.
- static std::mutex sSink2ComponentMutex;
- static std::map<IInputSink*, std::weak_ptr<C2Component>> sSink2Component;
-
- static std::shared_ptr<C2Component> findLocalComponent(
- const sp<IInputSink>& sink);
+// Component::DeathContext
+struct Component::DeathContext {
+ std::weak_ptr<Component> mWeakComp;
};
-std::mutex
- Component::Sink::sSink2ComponentMutex{};
-std::map<IInputSink*, std::weak_ptr<C2Component>>
- Component::Sink::sSink2Component{};
-
-Component::Sink::Sink(const std::shared_ptr<Component>& component)
- : mComponent{component},
- mConfigurable{[&component]() -> sp<IConfigurable> {
- Return<sp<IComponentInterface>> ret1 = component->getInterface();
- if (!ret1.isOk()) {
- LOG(ERROR) << "Sink::Sink -- component's transaction failed.";
- return nullptr;
- }
- Return<sp<IConfigurable>> ret2 =
- static_cast<sp<IComponentInterface>>(ret1)->
- getConfigurable();
- if (!ret2.isOk()) {
- LOG(ERROR) << "Sink::Sink -- interface's transaction failed.";
- return nullptr;
- }
- return static_cast<sp<IConfigurable>>(ret2);
- }()} {
- std::lock_guard<std::mutex> lock(sSink2ComponentMutex);
- sSink2Component.emplace(this, component->mComponent);
-}
-
-Component::Sink::~Sink() {
- std::lock_guard<std::mutex> lock(sSink2ComponentMutex);
- sSink2Component.erase(this);
-}
-
-std::shared_ptr<C2Component> Component::Sink::findLocalComponent(
- const sp<IInputSink>& sink) {
- std::lock_guard<std::mutex> lock(sSink2ComponentMutex);
- auto i = sSink2Component.find(sink.get());
- if (i == sSink2Component.end()) {
- return nullptr;
- }
- return i->second.lock();
-}
-
// Component
Component::Component(
const std::shared_ptr<C2Component>& component,
- const sp<IComponentListener>& listener,
- const sp<ComponentStore>& store,
- const sp<::android::hardware::media::bufferpool::V2_0::
- IClientManager>& clientPoolManager)
+ const std::shared_ptr<IComponentListener>& listener,
+ const std::shared_ptr<ComponentStore>& store,
+ const std::shared_ptr<IClientManager>& clientPoolManager)
: mComponent{component},
- mInterface{new ComponentInterface(component->intf(),
- store->getParameterCache())},
+ mInterface{SharedRefBase::make<ComponentInterface>(
+ component->intf(), store->getParameterCache())},
mListener{listener},
mStore{store},
- mBufferPoolSender{clientPoolManager} {
+ mBufferPoolSender{clientPoolManager},
+ mDeathContext(nullptr) {
// Retrieve supported parameters from store
// TODO: We could cache this per component/interface type
mInit = mInterface->status();
@@ -223,11 +169,11 @@
}
// Methods from ::android::hardware::media::c2::V1_1::IComponent
-Return<Status> Component::queue(const WorkBundle& workBundle) {
+ScopedAStatus Component::queue(const WorkBundle& workBundle) {
std::list<std::unique_ptr<C2Work>> c2works;
- if (!objcpy(&c2works, workBundle)) {
- return Status::CORRUPTED;
+ if (!FromAidl(&c2works, workBundle)) {
+ return ScopedAStatus::fromServiceSpecificError(Status::CORRUPTED);
}
// Register input buffers.
@@ -238,10 +184,14 @@
}
}
- return static_cast<Status>(mComponent->queue_nb(&c2works));
+ c2_status_t err = mComponent->queue_nb(&c2works);
+ if (err == C2_OK) {
+ return ScopedAStatus::ok();
+ }
+ return ScopedAStatus::fromServiceSpecificError(err);
}
-Return<void> Component::flush(flush_cb _hidl_cb) {
+ScopedAStatus Component::flush(WorkBundle *flushedWorkBundle) {
std::list<std::unique_ptr<C2Work>> c2flushedWorks;
c2_status_t c2res = mComponent->flush_sm(
C2Component::FLUSH_COMPONENT,
@@ -260,80 +210,29 @@
}
}
- WorkBundle flushedWorkBundle;
- Status res = static_cast<Status>(c2res);
- beginTransferBufferQueueBlocks(c2flushedWorks, true);
+ // TODO
+ // beginTransferBufferQueueBlocks(c2flushedWorks, true);
if (c2res == C2_OK) {
- if (!objcpy(&flushedWorkBundle, c2flushedWorks, &mBufferPoolSender)) {
- res = Status::CORRUPTED;
+ if (!ToAidl(flushedWorkBundle, c2flushedWorks, &mBufferPoolSender)) {
+ c2res = C2_CORRUPTED;
}
}
- _hidl_cb(res, flushedWorkBundle);
- endTransferBufferQueueBlocks(c2flushedWorks, true, true);
- return Void();
+ // TODO
+ // endTransferBufferQueueBlocks(c2flushedWorks, true, true);
+ if (c2res == C2_OK) {
+ return ScopedAStatus::ok();
+ }
+ return ScopedAStatus::fromServiceSpecificError(c2res);
}
-Return<Status> Component::drain(bool withEos) {
- return static_cast<Status>(mComponent->drain_nb(withEos ?
+ScopedAStatus Component::drain(bool withEos) {
+ c2_status_t res = mComponent->drain_nb(withEos ?
C2Component::DRAIN_COMPONENT_WITH_EOS :
- C2Component::DRAIN_COMPONENT_NO_EOS));
-}
-
-Return<Status> Component::setOutputSurface(
- uint64_t blockPoolId,
- const sp<HGraphicBufferProducer2>& surface) {
- std::shared_ptr<C2BlockPool> pool;
- GetCodec2BlockPool(blockPoolId, mComponent, &pool);
- if (pool && pool->getAllocatorId() == C2PlatformAllocatorStore::BUFFERQUEUE) {
- std::shared_ptr<C2BufferQueueBlockPool> bqPool =
- std::static_pointer_cast<C2BufferQueueBlockPool>(pool);
- C2BufferQueueBlockPool::OnRenderCallback cb =
- [this](uint64_t producer, int32_t slot, int64_t nsecs) {
- // TODO: batch this
- hidl_vec<IComponentListener::RenderedFrame> rendered;
- rendered.resize(1);
- rendered[0] = { producer, slot, nsecs };
- (void)mListener->onFramesRendered(rendered).isOk();
- };
- if (bqPool) {
- bqPool->setRenderCallback(cb);
- bqPool->configureProducer(surface);
- }
+ C2Component::DRAIN_COMPONENT_NO_EOS);
+ if (res == C2_OK) {
+ return ScopedAStatus::ok();
}
- return Status::OK;
-}
-
-Return<void> Component::connectToInputSurface(
- const sp<IInputSurface>& inputSurface,
- connectToInputSurface_cb _hidl_cb) {
- Status status;
- sp<IInputSurfaceConnection> connection;
- auto transStatus = inputSurface->connect(
- asInputSink(),
- [&status, &connection](
- Status s, const sp<IInputSurfaceConnection>& c) {
- status = s;
- connection = c;
- }
- );
- _hidl_cb(status, connection);
- return Void();
-}
-
-Return<void> Component::connectToOmxInputSurface(
- const sp<HGraphicBufferProducer1>& producer,
- const sp<::android::hardware::media::omx::V1_0::
- IGraphicBufferSource>& source,
- connectToOmxInputSurface_cb _hidl_cb) {
- (void)producer;
- (void)source;
- (void)_hidl_cb;
- return Void();
-}
-
-Return<Status> Component::disconnectFromInputSurface() {
- // TODO implement
- return Status::OK;
+ return ScopedAStatus::fromServiceSpecificError(res);
}
namespace /* unnamed */ {
@@ -390,177 +289,165 @@
} // unnamed namespace
-Return<void> Component::createBlockPool(
- uint32_t allocatorId,
- createBlockPool_cb _hidl_cb) {
- std::shared_ptr<C2BlockPool> blockPool;
+ScopedAStatus Component::createBlockPool(
+ const IComponent::BlockPoolAllocator &allocator,
+ IComponent::BlockPool *blockPool) {
+ std::shared_ptr<C2BlockPool> c2BlockPool;
+ static constexpr IComponent::BlockPoolAllocator::Tag ALLOCATOR_ID =
+ IComponent::BlockPoolAllocator::allocatorId;
+ static constexpr IComponent::BlockPoolAllocator::Tag IGBA =
+ IComponent::BlockPoolAllocator::igba;
+ c2_status_t status = C2_OK;
+ switch (allocator.getTag()) {
+ case ALLOCATOR_ID:
#ifdef __ANDROID_APEX__
- c2_status_t status = CreateCodec2BlockPool(
- static_cast<C2PlatformAllocatorStore::id_t>(allocatorId),
- mComponent,
- &blockPool);
+ status = ::android::CreateCodec2BlockPool(
+ static_cast<::android::C2PlatformAllocatorStore::id_t>(
+ allocator.get<ALLOCATOR_ID>()),
+ mComponent,
+ &c2BlockPool);
#else
- c2_status_t status = ComponentStore::GetFilterWrapper()->createBlockPool(
- static_cast<C2PlatformAllocatorStore::id_t>(allocatorId),
- mComponent,
- &blockPool);
+ status = ComponentStore::GetFilterWrapper()->createBlockPool(
+ static_cast<::android::C2PlatformAllocatorStore::id_t>(
+ allocator.get<ALLOCATOR_ID>()),
+ mComponent,
+ &c2BlockPool);
#endif
- if (status != C2_OK) {
- blockPool = nullptr;
+ if (status != C2_OK) {
+ blockPool = nullptr;
+ }
+ break;
+ case IGBA:
+ // FIXME
+ break;
+ default:
+ break;
}
if (blockPool) {
mBlockPoolsMutex.lock();
- mBlockPools.emplace(blockPool->getLocalId(), blockPool);
+ mBlockPools.emplace(c2BlockPool->getLocalId(), c2BlockPool);
mBlockPoolsMutex.unlock();
} else if (status == C2_OK) {
status = C2_CORRUPTED;
}
- _hidl_cb(static_cast<Status>(status),
- blockPool ? blockPool->getLocalId() : 0,
- new CachedConfigurable(
- std::make_unique<BlockPoolIntf>(blockPool)));
- return Void();
+ blockPool->blockPoolId = c2BlockPool ? c2BlockPool->getLocalId() : 0;
+ blockPool->configurable = SharedRefBase::make<CachedConfigurable>(
+ std::make_unique<BlockPoolIntf>(c2BlockPool));
+ if (status == C2_OK) {
+ return ScopedAStatus::ok();
+ }
+ return ScopedAStatus::fromServiceSpecificError(status);
}
-Return<Status> Component::destroyBlockPool(uint64_t blockPoolId) {
+ScopedAStatus Component::destroyBlockPool(int64_t blockPoolId) {
std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
- return mBlockPools.erase(blockPoolId) == 1 ?
- Status::OK : Status::CORRUPTED;
+ if (mBlockPools.erase(blockPoolId) == 1) {
+ return ScopedAStatus::ok();
+ }
+ return ScopedAStatus::fromServiceSpecificError(Status::CORRUPTED);
}
-Return<Status> Component::start() {
- return static_cast<Status>(mComponent->start());
+ScopedAStatus Component::start() {
+ c2_status_t status = mComponent->start();
+ if (status == C2_OK) {
+ return ScopedAStatus::ok();
+ }
+ return ScopedAStatus::fromServiceSpecificError(status);
}
-Return<Status> Component::stop() {
+ScopedAStatus Component::stop() {
InputBufferManager::unregisterFrameData(mListener);
- return static_cast<Status>(mComponent->stop());
+ c2_status_t status = mComponent->stop();
+ if (status == C2_OK) {
+ return ScopedAStatus::ok();
+ }
+ return ScopedAStatus::fromServiceSpecificError(status);
}
-Return<Status> Component::reset() {
- Status status = static_cast<Status>(mComponent->reset());
+ScopedAStatus Component::reset() {
+ c2_status_t status = mComponent->reset();
{
std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
mBlockPools.clear();
}
InputBufferManager::unregisterFrameData(mListener);
- return status;
+ if (status == C2_OK) {
+ return ScopedAStatus::ok();
+ }
+ return ScopedAStatus::fromServiceSpecificError(status);
}
-Return<Status> Component::release() {
- Status status = static_cast<Status>(mComponent->release());
+ScopedAStatus Component::release() {
+ c2_status_t status = mComponent->release();
{
std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
mBlockPools.clear();
}
InputBufferManager::unregisterFrameData(mListener);
- return status;
-}
-
-Return<sp<IComponentInterface>> Component::getInterface() {
- return sp<IComponentInterface>(mInterface);
-}
-
-Return<sp<IInputSink>> Component::asInputSink() {
- std::lock_guard<std::mutex> lock(mSinkMutex);
- if (!mSink) {
- mSink = new Sink(shared_from_this());
+ if (status == C2_OK) {
+ return ScopedAStatus::ok();
}
- return {mSink};
+ return ScopedAStatus::fromServiceSpecificError(status);
}
-Return<void> Component::configureVideoTunnel(
- uint32_t avSyncHwId, configureVideoTunnel_cb _hidl_cb) {
+ScopedAStatus Component::getInterface(
+ std::shared_ptr<IComponentInterface> *intf) {
+ *intf = mInterface;
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus Component::configureVideoTunnel(
+ int32_t avSyncHwId, NativeHandle *handle) {
(void)avSyncHwId;
- _hidl_cb(Status::OMITTED, hidl_handle{});
- return Void();
+ (void)handle;
+ return ScopedAStatus::fromServiceSpecificError(Status::OMITTED);
}
-Return<Status> Component::setOutputSurfaceWithSyncObj(
- uint64_t blockPoolId, const sp<HGraphicBufferProducer2>& surface,
- const SurfaceSyncObj& syncObject) {
- std::shared_ptr<C2BlockPool> pool;
- GetCodec2BlockPool(blockPoolId, mComponent, &pool);
- if (pool && pool->getAllocatorId() == C2PlatformAllocatorStore::BUFFERQUEUE) {
- std::shared_ptr<C2BufferQueueBlockPool> bqPool =
- std::static_pointer_cast<C2BufferQueueBlockPool>(pool);
- C2BufferQueueBlockPool::OnRenderCallback cb =
- [this](uint64_t producer, int32_t slot, int64_t nsecs) {
- // TODO: batch this
- hidl_vec<IComponentListener::RenderedFrame> rendered;
- rendered.resize(1);
- rendered[0] = { producer, slot, nsecs };
- (void)mListener->onFramesRendered(rendered).isOk();
- };
- if (bqPool) {
- const native_handle_t *h = syncObject.syncMemory;
- native_handle_t *syncMemory = h ? native_handle_clone(h) : nullptr;
- uint64_t bqId = syncObject.bqId;
- uint32_t generationId = syncObject.generationId;
- uint64_t consumerUsage = syncObject.consumerUsage;
-
- bqPool->setRenderCallback(cb);
- bqPool->configureProducer(surface, syncMemory, bqId,
- generationId, consumerUsage);
+void Component::initListener(const std::shared_ptr<Component>& self) {
+ if (__builtin_available(android __ANDROID_API_T__, *)) {
+ std::shared_ptr<C2Component::Listener> c2listener =
+ std::make_shared<Listener>(self);
+ c2_status_t res = mComponent->setListener_vb(c2listener, C2_DONT_BLOCK);
+ if (res != C2_OK) {
+ mInit = res;
}
+
+ mDeathRecipient = ::ndk::ScopedAIBinder_DeathRecipient(
+ AIBinder_DeathRecipient_new(OnBinderDied));
+ mDeathContext = new DeathContext{weak_from_this()};
+ AIBinder_DeathRecipient_setOnUnlinked(mDeathRecipient.get(), OnBinderUnlinked);
+ AIBinder_linkToDeath(mListener->asBinder().get(), mDeathRecipient.get(), mDeathContext);
+ } else {
+ mInit = C2_NO_INIT;
}
- return Status::OK;
}
-std::shared_ptr<C2Component> Component::findLocalComponent(
- const sp<IInputSink>& sink) {
- return Component::Sink::findLocalComponent(sink);
+// static
+void Component::OnBinderDied(void *cookie) {
+ DeathContext *context = (DeathContext *)cookie;
+ std::shared_ptr<Component> comp = context->mWeakComp.lock();
+ if (comp) {
+ comp->release();
+ }
}
-void Component::initListener(const sp<Component>& self) {
- std::shared_ptr<C2Component::Listener> c2listener =
- std::make_shared<Listener>(self);
- c2_status_t res = mComponent->setListener_vb(c2listener, C2_DONT_BLOCK);
- if (res != C2_OK) {
- mInit = res;
- }
-
- struct ListenerDeathRecipient : public HwDeathRecipient {
- ListenerDeathRecipient(const wp<Component>& comp)
- : component{comp} {
- }
-
- virtual void serviceDied(
- uint64_t /* cookie */,
- const wp<::android::hidl::base::V1_0::IBase>& /* who */
- ) override {
- auto strongComponent = component.promote();
- if (strongComponent) {
- LOG(INFO) << "Client died ! release the component !!";
- strongComponent->release();
- } else {
- LOG(ERROR) << "Client died ! no component to release !!";
- }
- }
-
- wp<Component> component;
- };
-
- mDeathRecipient = new ListenerDeathRecipient(self);
- Return<bool> transStatus = mListener->linkToDeath(
- mDeathRecipient, 0);
- if (!transStatus.isOk()) {
- LOG(ERROR) << "Listener linkToDeath() transaction failed.";
- }
- if (!static_cast<bool>(transStatus)) {
- LOG(DEBUG) << "Listener linkToDeath() call failed.";
- }
+// static
+void Component::OnBinderUnlinked(void *cookie) {
+ delete (DeathContext *)cookie;
}
Component::~Component() {
InputBufferManager::unregisterFrameData(mListener);
mStore->reportComponentDeath(this);
+ if (mDeathRecipient.get()) {
+ AIBinder_unlinkToDeath(mListener->asBinder().get(), mDeathRecipient.get(), mDeathContext);
+ }
}
} // namespace utils
-} // namespace V1_2
} // namespace c2
} // namespace media
} // namespace hardware
} // namespace android
+} // namespace aidl
diff --git a/media/codec2/hal/aidl/ComponentInterface.cpp b/media/codec2/hal/aidl/ComponentInterface.cpp
index 12078e0..2d812c9 100644
--- a/media/codec2/hal/aidl/ComponentInterface.cpp
+++ b/media/codec2/hal/aidl/ComponentInterface.cpp
@@ -18,28 +18,26 @@
#define LOG_TAG "Codec2-ComponentInterface"
#include <android-base/logging.h>
-#include <codec2/hidl/1.0/Component.h>
-#include <codec2/hidl/1.0/ComponentInterface.h>
-#include <codec2/hidl/1.0/ComponentStore.h>
+#include <android/binder_auto_utils.h>
+#include <codec2/aidl/ComponentInterface.h>
+#include <codec2/aidl/Configurable.h>
-#include <hidl/HidlBinderSupport.h>
#include <utils/Timers.h>
-#include <C2BqBufferPriv.h>
#include <C2Debug.h>
#include <C2PlatformSupport.h>
#include <chrono>
#include <thread>
+namespace aidl {
namespace android {
namespace hardware {
namespace media {
namespace c2 {
-namespace V1_0 {
namespace utils {
-using namespace ::android;
+using ::ndk::ScopedAStatus;
namespace /* unnamed */ {
@@ -89,7 +87,8 @@
const std::shared_ptr<C2ComponentInterface>& intf,
const std::shared_ptr<ParameterCache>& cache)
: mInterface{intf},
- mConfigurable{new CachedConfigurable(std::make_unique<CompIntf>(intf))} {
+ mConfigurable{SharedRefBase::make<CachedConfigurable>(
+ std::make_unique<CompIntf>(intf))} {
mInit = mConfigurable->init(cache);
}
@@ -97,14 +96,16 @@
return mInit;
}
-Return<sp<IConfigurable>> ComponentInterface::getConfigurable() {
- return mConfigurable;
+ScopedAStatus ComponentInterface::getConfigurable(
+ std::shared_ptr<IConfigurable> *configurable) {
+ *configurable = mConfigurable;
+ return ScopedAStatus::ok();
}
} // namespace utils
-} // namespace V1_0
} // namespace c2
} // namespace media
} // namespace hardware
} // namespace android
+} // namespace aidl
diff --git a/media/codec2/hal/aidl/ComponentStore.cpp b/media/codec2/hal/aidl/ComponentStore.cpp
index 9fac5d5..2489683 100644
--- a/media/codec2/hal/aidl/ComponentStore.cpp
+++ b/media/codec2/hal/aidl/ComponentStore.cpp
@@ -15,15 +15,16 @@
*/
//#define LOG_NDEBUG 0
-#define LOG_TAG "Codec2-ComponentStore@1.2"
+#define LOG_TAG "Codec2-ComponentStore-Aidl"
#include <android-base/logging.h>
-#include <codec2/hidl/1.2/ComponentStore.h>
-#include <codec2/hidl/1.2/InputSurface.h>
-#include <codec2/hidl/1.2/types.h>
+#include <bufferpool2/ClientManager.h>
+#include <codec2/aidl/Component.h>
+#include <codec2/aidl/ComponentInterface.h>
+#include <codec2/aidl/ComponentStore.h>
+#include <codec2/aidl/ParamTypes.h>
#include <android-base/file.h>
-#include <media/stagefright/bqhelper/GraphicBufferSource.h>
#include <utils/Errors.h>
#include <C2PlatformSupport.h>
@@ -43,16 +44,19 @@
#include <FilterWrapper.h>
#endif
+namespace aidl {
namespace android {
namespace hardware {
namespace media {
namespace c2 {
-namespace V1_2 {
namespace utils {
-using namespace ::android;
-using ::android::GraphicBufferSource;
-using namespace ::android::hardware::media::bufferpool::V2_0::implementation;
+#ifndef __ANDROID_APEX__
+using ::android::DefaultFilterPlugin;
+using ::android::FilterWrapper;
+#endif
+
+using ::ndk::ScopedAStatus;
namespace /* unnamed */ {
@@ -131,12 +135,13 @@
};
ComponentStore::ComponentStore(const std::shared_ptr<C2ComponentStore>& store)
- : mConfigurable{new CachedConfigurable(std::make_unique<StoreIntf>(store))},
+ : mConfigurable{SharedRefBase::make<CachedConfigurable>(std::make_unique<StoreIntf>(store))},
mParameterCache{std::make_shared<StoreParameterCache>(this)},
mStore{store} {
- std::shared_ptr<C2ComponentStore> platformStore = android::GetCodec2PlatformComponentStore();
- SetPreferredCodec2ComponentStore(store);
+ std::shared_ptr<C2ComponentStore> platformStore =
+ ::android::GetCodec2PlatformComponentStore();
+ ::android::SetPreferredCodec2ComponentStore(store);
// Retrieve struct descriptors
mParamReflector = mStore->getParamReflector();
@@ -194,93 +199,78 @@
}
#endif
-// Methods from ::android::hardware::media::c2::V1_0::IComponentStore
-Return<void> ComponentStore::createComponent(
- const hidl_string& name,
- const sp<IComponentListener>& listener,
- const sp<IClientManager>& pool,
- createComponent_cb _hidl_cb) {
+// Methods from ::aidl::android::hardware::media::c2::IComponentStore
+ScopedAStatus ComponentStore::createComponent(
+ const std::string& name,
+ const std::shared_ptr<IComponentListener>& listener,
+ const std::shared_ptr<IClientManager>& pool,
+ std::shared_ptr<IComponent> *component) {
- sp<Component> component;
std::shared_ptr<C2Component> c2component;
- Status status = static_cast<Status>(
- mStore->createComponent(name, &c2component));
+ c2_status_t status =
+ mStore->createComponent(name, &c2component);
- if (status == Status::OK) {
+ if (status == C2_OK) {
#ifndef __ANDROID_APEX__
c2component = GetFilterWrapper()->maybeWrapComponent(c2component);
#endif
onInterfaceLoaded(c2component->intf());
- component = new Component(c2component, listener, this, pool);
+ std::shared_ptr<Component> comp =
+ SharedRefBase::make<Component>(c2component, listener, shared_from_this(), pool);
+ *component = comp;
if (!component) {
- status = Status::CORRUPTED;
+ status = C2_CORRUPTED;
} else {
- reportComponentBirth(component.get());
- if (component->status() != C2_OK) {
- status = static_cast<Status>(component->status());
+ reportComponentBirth(comp.get());
+ if (comp->status() != C2_OK) {
+ status = comp->status();
} else {
- component->initListener(component);
- if (component->status() != C2_OK) {
- status = static_cast<Status>(component->status());
+ comp->initListener(comp);
+ if (comp->status() != C2_OK) {
+ status = comp->status();
}
}
}
}
- _hidl_cb(status, component);
- return Void();
+ if (status == C2_OK) {
+ return ScopedAStatus::ok();
+ }
+ return ScopedAStatus::fromServiceSpecificError(status);
}
-Return<void> ComponentStore::createInterface(
- const hidl_string& name,
- createInterface_cb _hidl_cb) {
+ScopedAStatus ComponentStore::createInterface(
+ const std::string& name,
+ std::shared_ptr<IComponentInterface> *intf) {
std::shared_ptr<C2ComponentInterface> c2interface;
c2_status_t res = mStore->createInterface(name, &c2interface);
- sp<IComponentInterface> interface;
if (res == C2_OK) {
#ifndef __ANDROID_APEX__
c2interface = GetFilterWrapper()->maybeWrapInterface(c2interface);
#endif
onInterfaceLoaded(c2interface);
- interface = new ComponentInterface(c2interface, mParameterCache);
+ *intf = SharedRefBase::make<ComponentInterface>(c2interface, mParameterCache);
+ return ScopedAStatus::ok();
}
- _hidl_cb(static_cast<Status>(res), interface);
- return Void();
+ return ScopedAStatus::fromServiceSpecificError(res);
}
-Return<void> ComponentStore::listComponents(listComponents_cb _hidl_cb) {
+ScopedAStatus ComponentStore::listComponents(
+ std::vector<IComponentStore::ComponentTraits> *traits) {
std::vector<std::shared_ptr<const C2Component::Traits>> c2traits =
mStore->listComponents();
- hidl_vec<IComponentStore::ComponentTraits> traits(c2traits.size());
+ traits->resize(c2traits.size());
size_t ix = 0;
for (const std::shared_ptr<const C2Component::Traits> &c2trait : c2traits) {
if (c2trait) {
- if (objcpy(&traits[ix], *c2trait)) {
+ if (ToAidl(&traits->at(ix), *c2trait)) {
++ix;
} else {
break;
}
}
}
- traits.resize(ix);
- _hidl_cb(Status::OK, traits);
- return Void();
-}
-
-Return<void> ComponentStore::createInputSurface(createInputSurface_cb _hidl_cb) {
- sp<GraphicBufferSource> source = new GraphicBufferSource();
- if (source->initCheck() != OK) {
- _hidl_cb(Status::CORRUPTED, nullptr);
- return Void();
- }
- using namespace std::placeholders;
- sp<InputSurface> inputSurface = new InputSurface(
- mParameterCache,
- std::make_shared<C2ReflectorHelper>(),
- source->getHGraphicBufferProducer(),
- source);
- _hidl_cb(inputSurface ? Status::OK : Status::NO_MEMORY,
- inputSurface);
- return Void();
+ traits->resize(ix);
+ return ScopedAStatus::ok();
}
void ComponentStore::onInterfaceLoaded(const std::shared_ptr<C2ComponentInterface> &intf) {
@@ -293,15 +283,16 @@
}
}
-Return<void> ComponentStore::getStructDescriptors(
- const hidl_vec<uint32_t>& indices,
- getStructDescriptors_cb _hidl_cb) {
- hidl_vec<StructDescriptor> descriptors(indices.size());
+ScopedAStatus ComponentStore::getStructDescriptors(
+ const std::vector<int32_t>& indices,
+ std::vector<StructDescriptor> *descriptors) {
+ descriptors->resize(indices.size());
size_t dstIx = 0;
- Status res = Status::OK;
+ int32_t res = Status::OK;
for (size_t srcIx = 0; srcIx < indices.size(); ++srcIx) {
std::lock_guard<std::mutex> lock(mStructDescriptorsMutex);
- const C2Param::CoreIndex coreIndex = C2Param::CoreIndex(indices[srcIx]).coreIndex();
+ const C2Param::CoreIndex coreIndex =
+ C2Param::CoreIndex(uint32_t(indices[srcIx])).coreIndex();
const auto item = mStructDescriptors.find(coreIndex);
if (item == mStructDescriptors.end()) {
// not in the cache, and not known to be unsupported, query local reflector
@@ -312,7 +303,7 @@
mUnsupportedStructDescriptors.emplace(coreIndex);
} else {
mStructDescriptors.insert({ coreIndex, structDesc });
- if (objcpy(&descriptors[dstIx], *structDesc)) {
+ if (ToAidl(&descriptors->at(dstIx), *structDesc)) {
++dstIx;
continue;
}
@@ -322,7 +313,7 @@
}
res = Status::NOT_FOUND;
} else if (item->second) {
- if (objcpy(&descriptors[dstIx], *item->second)) {
+ if (ToAidl(&descriptors->at(dstIx), *item->second)) {
++dstIx;
continue;
}
@@ -333,96 +324,31 @@
break;
}
}
- descriptors.resize(dstIx);
- _hidl_cb(res, descriptors);
- return Void();
+ descriptors->resize(dstIx);
+ if (res == Status::OK) {
+ return ScopedAStatus::ok();
+ }
+ return ScopedAStatus::fromServiceSpecificError(res);
}
-Return<sp<IClientManager>> ComponentStore::getPoolClientManager() {
- return ClientManager::getInstance();
+ScopedAStatus ComponentStore::getPoolClientManager(
+ std::shared_ptr<IClientManager> *manager) {
+ using ::aidl::android::hardware::media::bufferpool2::implementation::ClientManager;
+ *manager = ClientManager::getInstance();
+ return ScopedAStatus::ok();
}
-Return<Status> ComponentStore::copyBuffer(const Buffer& src, const Buffer& dst) {
+ScopedAStatus ComponentStore::copyBuffer(const Buffer& src, const Buffer& dst) {
// TODO implement
(void)src;
(void)dst;
- return Status::OMITTED;
+ return ScopedAStatus::fromServiceSpecificError(Status::OMITTED);
}
-Return<sp<IConfigurable>> ComponentStore::getConfigurable() {
- return mConfigurable;
-}
-
-// Methods from ::android::hardware::media::c2::V1_1::IComponentStore
-Return<void> ComponentStore::createComponent_1_1(
- const hidl_string& name,
- const sp<IComponentListener>& listener,
- const sp<IClientManager>& pool,
- createComponent_1_1_cb _hidl_cb) {
-
- sp<Component> component;
- std::shared_ptr<C2Component> c2component;
- Status status = static_cast<Status>(
- mStore->createComponent(name, &c2component));
-
- if (status == Status::OK) {
-#ifndef __ANDROID_APEX__
- c2component = GetFilterWrapper()->maybeWrapComponent(c2component);
-#endif
- onInterfaceLoaded(c2component->intf());
- component = new Component(c2component, listener, this, pool);
- if (!component) {
- status = Status::CORRUPTED;
- } else {
- reportComponentBirth(component.get());
- if (component->status() != C2_OK) {
- status = static_cast<Status>(component->status());
- } else {
- component->initListener(component);
- if (component->status() != C2_OK) {
- status = static_cast<Status>(component->status());
- }
- }
- }
- }
- _hidl_cb(status, component);
- return Void();
-}
-
-// Methods from ::android::hardware::media::c2::V1_2::IComponentStore
-Return<void> ComponentStore::createComponent_1_2(
- const hidl_string& name,
- const sp<IComponentListener>& listener,
- const sp<IClientManager>& pool,
- createComponent_1_2_cb _hidl_cb) {
-
- sp<Component> component;
- std::shared_ptr<C2Component> c2component;
- Status status = static_cast<Status>(
- mStore->createComponent(name, &c2component));
-
- if (status == Status::OK) {
-#ifndef __ANDROID_APEX__
- c2component = GetFilterWrapper()->maybeWrapComponent(c2component);
-#endif
- onInterfaceLoaded(c2component->intf());
- component = new Component(c2component, listener, this, pool);
- if (!component) {
- status = Status::CORRUPTED;
- } else {
- reportComponentBirth(component.get());
- if (component->status() != C2_OK) {
- status = static_cast<Status>(component->status());
- } else {
- component->initListener(component);
- if (component->status() != C2_OK) {
- status = static_cast<Status>(component->status());
- }
- }
- }
- }
- _hidl_cb(status, component);
- return Void();
+ScopedAStatus ComponentStore::getConfigurable(
+ std::shared_ptr<IConfigurable> *configurable) {
+ *configurable = mConfigurable;
+ return ScopedAStatus::ok();
}
// Called from createComponent() after a successful creation of `component`.
@@ -495,16 +421,9 @@
}
// Dumps information when lshal is called.
-Return<void> ComponentStore::debug(
- const hidl_handle& handle,
- const hidl_vec<hidl_string>& /* args */) {
+binder_status_t ComponentStore::dump(
+ int fd, [[maybe_unused]] const char** args, [[maybe_unused]] uint32_t numArgs) {
LOG(INFO) << "debug -- dumping...";
- const native_handle_t *h = handle.getNativeHandle();
- if (!h || h->numFds != 1) {
- LOG(ERROR) << "debug -- dumping failed -- "
- "invalid file descriptor to dump to";
- return Void();
- }
std::ostringstream out;
{ // Populate "out".
@@ -546,17 +465,17 @@
<< mStore->getName() << std::endl;
}
- if (!android::base::WriteStringToFd(out.str(), h->data[0])) {
+ if (!::android::base::WriteStringToFd(out.str(), fd)) {
PLOG(WARNING) << "debug -- dumping failed -- write()";
} else {
LOG(INFO) << "debug -- dumping succeeded";
}
- return Void();
+ return STATUS_OK;
}
} // namespace utils
-} // namespace V1_2
} // namespace c2
} // namespace media
} // namespace hardware
} // namespace android
+} // namespace aidl
diff --git a/media/codec2/hal/aidl/Configurable.cpp b/media/codec2/hal/aidl/Configurable.cpp
index 530576d..0326263 100644
--- a/media/codec2/hal/aidl/Configurable.cpp
+++ b/media/codec2/hal/aidl/Configurable.cpp
@@ -15,23 +15,23 @@
*/
//#define LOG_NDEBUG 0
-#define LOG_TAG "Codec2-Configurable"
+#define LOG_TAG "Codec2-Configurable-Aidl"
#include <android-base/logging.h>
-#include <codec2/hidl/1.0/Configurable.h>
-#include <codec2/hidl/1.0/ComponentStore.h>
-#include <codec2/hidl/1.0/types.h>
+#include <android/binder_auto_utils.h>
+#include <codec2/aidl/Configurable.h>
+#include <codec2/aidl/ParamTypes.h>
#include <C2ParamInternal.h>
+namespace aidl {
namespace android {
namespace hardware {
namespace media {
namespace c2 {
-namespace V1_0 {
namespace utils {
-using namespace ::android;
+using ::ndk::ScopedAStatus;
CachedConfigurable::CachedConfigurable(
std::unique_ptr<ConfigurableC2Intf>&& intf)
@@ -47,19 +47,21 @@
}
// Methods from ::android::hardware::media::c2::V1_0::IConfigurable follow.
-Return<uint32_t> CachedConfigurable::getId() {
- return mIntf->getId();
+
+ScopedAStatus CachedConfigurable::getId(int32_t* id) {
+ *id = mIntf->getId();
+ return ScopedAStatus::ok();
}
-Return<void> CachedConfigurable::getName(getName_cb _hidl_cb) {
- _hidl_cb(mIntf->getName());
- return Void();
+ScopedAStatus CachedConfigurable::getName(std::string* name) {
+ *name = mIntf->getName();
+ return ScopedAStatus::ok();
}
-Return<void> CachedConfigurable::query(
- const hidl_vec<uint32_t>& indices,
+ScopedAStatus CachedConfigurable::query(
+ const std::vector<int32_t>& indices,
bool mayBlock,
- query_cb _hidl_cb) {
+ Params* params) {
typedef C2Param::Index Index;
std::vector<Index> c2heapParamIndices(
(Index*)indices.data(),
@@ -70,27 +72,24 @@
mayBlock ? C2_MAY_BLOCK : C2_DONT_BLOCK,
&c2heapParams);
- hidl_vec<uint8_t> params;
- if (!createParamsBlob(¶ms, c2heapParams)) {
+ if (!CreateParamsBlob(params, c2heapParams)) {
LOG(WARNING) << "query -- invalid output params.";
}
- _hidl_cb(static_cast<Status>(c2res), params);
- return Void();
+ if (c2res == C2_OK) {
+ return ScopedAStatus::ok();
+ }
+ return ScopedAStatus::fromServiceSpecificError(c2res);
}
-Return<void> CachedConfigurable::config(
- const hidl_vec<uint8_t>& inParams,
+ScopedAStatus CachedConfigurable::config(
+ const Params& params,
bool mayBlock,
- config_cb _hidl_cb) {
+ ConfigResult* result) {
// inParams is not writable, so create a copy as config modifies the parameters
- hidl_vec<uint8_t> inParamsCopy = inParams;
std::vector<C2Param*> c2params;
- if (!parseParamsBlob(&c2params, inParamsCopy)) {
+ if (!ParseParamsBlob(&c2params, params)) {
LOG(WARNING) << "config -- invalid input params.";
- _hidl_cb(Status::CORRUPTED,
- hidl_vec<SettingResult>(),
- hidl_vec<uint8_t>());
- return Void();
+ return ScopedAStatus::fromServiceSpecificError(C2_CORRUPTED);
}
// TODO: check if blob was invalid
std::vector<std::unique_ptr<C2SettingResult>> c2failures;
@@ -98,12 +97,12 @@
c2params,
mayBlock ? C2_MAY_BLOCK : C2_DONT_BLOCK,
&c2failures);
- hidl_vec<SettingResult> failures(c2failures.size());
+ result->failures.resize(c2failures.size());
{
size_t ix = 0;
for (const std::unique_ptr<C2SettingResult>& c2result : c2failures) {
if (c2result) {
- if (objcpy(&failures[ix], *c2result)) {
+ if (ToAidl(&result->failures[ix], *c2result)) {
++ix;
} else {
LOG(DEBUG) << "config -- invalid setting results.";
@@ -111,28 +110,29 @@
}
}
}
- failures.resize(ix);
+ result->failures.resize(ix);
}
- hidl_vec<uint8_t> outParams;
- if (!createParamsBlob(&outParams, c2params)) {
+ if (!CreateParamsBlob(&result->params, c2params)) {
LOG(DEBUG) << "config -- invalid output params.";
}
- _hidl_cb((Status)c2res, failures, outParams);
- return Void();
+ if (c2res == C2_OK) {
+ return ScopedAStatus::ok();
+ }
+ return ScopedAStatus::fromServiceSpecificError(c2res);
}
-Return<void> CachedConfigurable::querySupportedParams(
- uint32_t start,
- uint32_t count,
- querySupportedParams_cb _hidl_cb) {
+ScopedAStatus CachedConfigurable::querySupportedParams(
+ int32_t start,
+ int32_t count,
+ std::vector<ParamDescriptor>* paramDesc) {
C2LinearRange request = C2LinearCapacity(mSupportedParams.size()).range(
start, count);
- hidl_vec<ParamDescriptor> params(request.size());
- Status res = Status::OK;
+ paramDesc->resize(request.size());
+ int32_t res = Status::OK;
size_t dstIx = 0;
for (size_t srcIx = request.offset(); srcIx < request.endOffset(); ++srcIx) {
if (mSupportedParams[srcIx]) {
- if (objcpy(¶ms[dstIx], *mSupportedParams[srcIx])) {
+ if (ToAidl(&(*paramDesc)[dstIx], *mSupportedParams[srcIx])) {
++dstIx;
} else {
res = Status::CORRUPTED;
@@ -143,26 +143,28 @@
res = Status::BAD_INDEX;
}
}
- params.resize(dstIx);
- _hidl_cb(res, params);
- return Void();
+ paramDesc->resize(dstIx);
+ if (res == Status::OK) {
+ return ScopedAStatus::ok();
+ }
+ return ScopedAStatus::fromServiceSpecificError(res);
}
-Return<void> CachedConfigurable::querySupportedValues(
- const hidl_vec<FieldSupportedValuesQuery>& inFields,
+ScopedAStatus CachedConfigurable::querySupportedValues(
+ const std::vector<FieldSupportedValuesQuery>& fields,
bool mayBlock,
- querySupportedValues_cb _hidl_cb) {
+ std::vector<FieldSupportedValuesQueryResult>* result) {
std::vector<C2FieldSupportedValuesQuery> c2fields;
{
// C2FieldSupportedValuesQuery objects are restricted in that some
// members are const.
// C2ParamField - required for its constructor - has no constructors
// from fields. Use C2ParamInspector.
- for (const FieldSupportedValuesQuery &query : inFields) {
+ for (const FieldSupportedValuesQuery &query : fields) {
c2fields.emplace_back(_C2ParamInspector::CreateParamField(
- query.field.index,
+ (uint32_t)query.field.index,
query.field.fieldId.offset,
- query.field.fieldId.size),
+ query.field.fieldId.sizeBytes),
query.type == FieldSupportedValuesQuery::Type::POSSIBLE ?
C2FieldSupportedValuesQuery::POSSIBLE :
C2FieldSupportedValuesQuery::CURRENT);
@@ -171,26 +173,28 @@
c2_status_t c2res = mIntf->querySupportedValues(
c2fields,
mayBlock ? C2_MAY_BLOCK : C2_DONT_BLOCK);
- hidl_vec<FieldSupportedValuesQueryResult> outFields(inFields.size());
+ result->resize(fields.size());
size_t dstIx = 0;
- for (const C2FieldSupportedValuesQuery &result : c2fields) {
- if (objcpy(&outFields[dstIx], result)) {
+ for (const C2FieldSupportedValuesQuery &res : c2fields) {
+ if (ToAidl(&(*result)[dstIx], res)) {
++dstIx;
} else {
- outFields.resize(dstIx);
+ result->resize(dstIx);
c2res = C2_CORRUPTED;
LOG(WARNING) << "querySupportedValues -- invalid output params.";
break;
}
}
- _hidl_cb((Status)c2res, outFields);
- return Void();
+ if (c2res == C2_OK) {
+ return ScopedAStatus::ok();
+ }
+ return ScopedAStatus::fromServiceSpecificError(c2res);
}
} // namespace utils
-} // namespace V1_0
} // namespace c2
} // namespace media
} // namespace hardware
} // namespace android
+} // namespace aidl
diff --git a/media/codec2/hal/aidl/InputBufferManager.cpp b/media/codec2/hal/aidl/InputBufferManager.cpp
index 8c0d0a4..5c58155 100644
--- a/media/codec2/hal/aidl/InputBufferManager.cpp
+++ b/media/codec2/hal/aidl/InputBufferManager.cpp
@@ -15,13 +15,12 @@
*/
//#define LOG_NDEBUG 0
-#define LOG_TAG "Codec2-InputBufferManager"
+#define LOG_TAG "Codec2-InputBufferManager-Aidl"
#include <android-base/logging.h>
-#include <codec2/hidl/1.0/InputBufferManager.h>
-#include <codec2/hidl/1.0/types.h>
+#include <codec2/aidl/InputBufferManager.h>
-#include <android/hardware/media/c2/1.0/IComponentListener.h>
+#include <aidl/android/hardware/media/c2/IComponentListener.h>
#include <android-base/logging.h>
#include <C2Buffer.h>
@@ -29,29 +28,29 @@
#include <chrono>
+namespace aidl {
namespace android {
namespace hardware {
namespace media {
namespace c2 {
-namespace V1_0 {
namespace utils {
using namespace ::android;
void InputBufferManager::registerFrameData(
- const sp<IComponentListener>& listener,
+ const std::shared_ptr<IComponentListener>& listener,
const C2FrameData& input) {
getInstance()._registerFrameData(listener, input);
}
void InputBufferManager::unregisterFrameData(
- const wp<IComponentListener>& listener,
+ const std::weak_ptr<IComponentListener>& listener,
const C2FrameData& input) {
getInstance()._unregisterFrameData(listener, input);
}
void InputBufferManager::unregisterFrameData(
- const wp<IComponentListener>& listener) {
+ const std::weak_ptr<IComponentListener>& listener) {
getInstance()._unregisterFrameData(listener);
}
@@ -61,7 +60,7 @@
}
void InputBufferManager::_registerFrameData(
- const sp<IComponentListener>& listener,
+ const std::shared_ptr<IComponentListener>& listener,
const C2FrameData& input) {
uint64_t frameIndex = input.ordinal.frameIndex.peeku();
LOG(VERBOSE) << "InputBufferManager::_registerFrameData -- called with "
@@ -109,13 +108,11 @@
//
// This is called from onWorkDone() and flush().
void InputBufferManager::_unregisterFrameData(
- const wp<IComponentListener>& listener,
+ const std::weak_ptr<IComponentListener>& listener,
const C2FrameData& input) {
uint64_t frameIndex = input.ordinal.frameIndex.peeku();
LOG(VERBOSE) << "InputBufferManager::_unregisterFrameData -- called with "
- << "listener @ 0x" << std::hex << listener.unsafe_get()
- << ", frameIndex = " << std::dec << frameIndex
- << ".";
+ << "frameIndex = " << frameIndex << ".";
std::lock_guard<std::mutex> lock(mMutex);
auto findListener = mTrackedBuffersMap.find(listener);
@@ -134,11 +131,7 @@
if (status != C2_OK) {
LOG(DEBUG) << "InputBufferManager::_unregisterFrameData "
<< "-- unregisterOnDestroyNotify() failed "
- << "(listener @ 0x"
- << std::hex
- << bufferId->listener.unsafe_get()
- << ", frameIndex = "
- << std::dec << bufferId->frameIndex
+ << "(frameIndex = " << bufferId->frameIndex
<< ", bufferIndex = " << bufferId->bufferIndex
<< ") => status = " << status
<< ".";
@@ -173,10 +166,8 @@
// This is called when the component cleans up all input buffers, i.e., when
// reset(), release(), stop() or ~Component() is called.
void InputBufferManager::_unregisterFrameData(
- const wp<IComponentListener>& listener) {
- LOG(VERBOSE) << "InputBufferManager::_unregisterFrameData -- called with "
- << "listener @ 0x" << std::hex << listener.unsafe_get()
- << std::dec << ".";
+ const std::weak_ptr<IComponentListener>& listener) {
+ LOG(VERBOSE) << "InputBufferManager::_unregisterFrameData.";
std::lock_guard<std::mutex> lock(mMutex);
auto findListener = mTrackedBuffersMap.find(listener);
@@ -196,11 +187,7 @@
if (status != C2_OK) {
LOG(DEBUG) << "InputBufferManager::_unregisterFrameData "
<< "-- unregisterOnDestroyNotify() failed "
- << "(listener @ 0x"
- << std::hex
- << bufferId->listener.unsafe_get()
- << ", frameIndex = "
- << std::dec << bufferId->frameIndex
+ << "(frameIndex = " << bufferId->frameIndex
<< ", bufferIndex = " << bufferId->bufferIndex
<< ") => status = " << status
<< ".";
@@ -256,16 +243,14 @@
<< "buf @ 0x" << std::hex << buf
<< ", arg @ 0x" << std::hex << arg
<< std::dec << " -- "
- << "listener @ 0x" << std::hex << bufferId->listener.unsafe_get()
- << ", frameIndex = " << std::dec << bufferId->frameIndex
+ << ", frameIndex = " << bufferId->frameIndex
<< ", bufferIndex = " << bufferId->bufferIndex
<< ".";
auto findListener = mTrackedBuffersMap.find(bufferId->listener);
if (findListener == mTrackedBuffersMap.end()) {
LOG(VERBOSE) << "InputBufferManager::_onBufferDestroyed -- "
<< "received invalid listener: "
- << "listener @ 0x" << std::hex << bufferId->listener.unsafe_get()
- << " (frameIndex = " << std::dec << bufferId->frameIndex
+ << " (frameIndex = " << bufferId->frameIndex
<< ", bufferIndex = " << bufferId->bufferIndex
<< ").";
return;
@@ -278,8 +263,7 @@
LOG(DEBUG) << "InputBufferManager::_onBufferDestroyed -- "
<< "received invalid frame index: "
<< "frameIndex = " << bufferId->frameIndex
- << " (listener @ 0x" << std::hex << bufferId->listener.unsafe_get()
- << ", bufferIndex = " << std::dec << bufferId->bufferIndex
+ << ", bufferIndex = " << bufferId->bufferIndex
<< ").";
return;
}
@@ -291,8 +275,7 @@
<< "received invalid buffer index: "
<< "bufferIndex = " << bufferId->bufferIndex
<< " (frameIndex = " << bufferId->frameIndex
- << ", listener @ 0x" << std::hex << bufferId->listener.unsafe_get()
- << std::dec << ").";
+ << ").";
return;
}
@@ -320,9 +303,9 @@
bool InputBufferManager::processNotifications(nsecs_t* timeToRetryNs) {
struct Notification {
- sp<IComponentListener> listener;
- hidl_vec<IComponentListener::InputBuffer> inputBuffers;
- Notification(const sp<IComponentListener>& l, size_t s)
+ std::shared_ptr<IComponentListener> listener;
+ std::vector<IComponentListener::InputBuffer> inputBuffers;
+ Notification(const std::shared_ptr<IComponentListener>& l, size_t s)
: listener(l), inputBuffers(s) {}
};
std::list<Notification> notifications;
@@ -336,7 +319,7 @@
nsecs_t timeNowNs = systemTime();
for (auto it = mDeathNotifications.begin();
it != mDeathNotifications.end(); ) {
- sp<IComponentListener> listener = it->first.promote();
+ std::shared_ptr<IComponentListener> listener = it->first.lock();
if (!listener) {
++it;
continue;
@@ -371,7 +354,7 @@
// Create the argument for the callback.
notifications.emplace_back(listener, deathNotifications.count);
- hidl_vec<IComponentListener::InputBuffer> &inputBuffers =
+ std::vector<IComponentListener::InputBuffer> &inputBuffers =
notifications.back().inputBuffers;
size_t i = 0;
for (std::pair<const uint64_t, std::vector<size_t>>& p :
@@ -466,11 +449,9 @@
}
} // namespace utils
-} // namespace V1_0
} // namespace c2
} // namespace media
} // namespace hardware
} // namespace android
-
-
+} // namespace aidl
diff --git a/media/codec2/hal/aidl/InputSurface.cpp b/media/codec2/hal/aidl/InputSurface.cpp
deleted file mode 100644
index c3c32e9..0000000
--- a/media/codec2/hal/aidl/InputSurface.cpp
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "Codec2-InputSurface"
-#include <android-base/logging.h>
-
-#include <codec2/hidl/1.0/InputSurface.h>
-#include <codec2/hidl/1.0/InputSurfaceConnection.h>
-
-#include <C2Component.h>
-#include <C2Config.h>
-
-#include <memory>
-
-namespace android {
-namespace hardware {
-namespace media {
-namespace c2 {
-namespace V1_0 {
-namespace utils {
-
-using namespace ::android;
-
-// Derived class of C2InterfaceHelper
-class InputSurface::Interface : public C2InterfaceHelper {
-public:
- explicit Interface(
- const std::shared_ptr<C2ReflectorHelper> &helper)
- : C2InterfaceHelper(helper) {
-
- setDerivedInstance(this);
-
- addParameter(
- DefineParam(mEos, C2_PARAMKEY_INPUT_SURFACE_EOS)
- .withDefault(new C2InputSurfaceEosTuning(false))
- .withFields({C2F(mEos, value).oneOf({true, false})})
- .withSetter(EosSetter)
- .build());
- }
-
- static C2R EosSetter(bool mayBlock, C2P<C2InputSurfaceEosTuning> &me) {
- (void)mayBlock;
- return me.F(me.v.value).validatePossible(me.v.value);
- }
-
- bool eos() const { return mEos->value; }
-
-private:
- std::shared_ptr<C2InputSurfaceEosTuning> mEos;
-};
-
-// Derived class of ConfigurableC2Intf
-class InputSurface::ConfigurableIntf : public ConfigurableC2Intf {
-public:
- ConfigurableIntf(
- const std::shared_ptr<InputSurface::Interface> &intf,
- const sp<GraphicBufferSource> &source)
- : ConfigurableC2Intf("input-surface", 0),
- mIntf(intf),
- mSource(source) {
- }
-
- virtual ~ConfigurableIntf() override = default;
-
- virtual c2_status_t query(
- const std::vector<C2Param::Index> &indices,
- c2_blocking_t mayBlock,
- std::vector<std::unique_ptr<C2Param>>* const params
- ) const override {
- return mIntf->query({}, indices, mayBlock, params);
- }
-
- virtual c2_status_t config(
- const std::vector<C2Param*> ¶ms,
- c2_blocking_t mayBlock,
- std::vector<std::unique_ptr<C2SettingResult>>* const failures
- ) override {
- c2_status_t err = mIntf->config(params, mayBlock, failures);
- if (mIntf->eos()) {
- sp<GraphicBufferSource> source = mSource.promote();
- if (source == nullptr || source->signalEndOfInputStream() != OK) {
- // TODO: put something in |failures|
- err = C2_BAD_VALUE;
- }
- // TODO: reset eos?
- }
- return err;
- }
-
- virtual c2_status_t querySupportedParams(
- std::vector<std::shared_ptr<C2ParamDescriptor>>* const params
- ) const override {
- return mIntf->querySupportedParams(params);
- }
-
- virtual c2_status_t querySupportedValues(
- std::vector<C2FieldSupportedValuesQuery>& fields,
- c2_blocking_t mayBlock) const override {
- return mIntf->querySupportedValues(fields, mayBlock);
- }
-
-private:
- const std::shared_ptr<InputSurface::Interface> mIntf;
- wp<GraphicBufferSource> mSource;
-};
-
-Return<sp<InputSurface::HGraphicBufferProducer>> InputSurface::getGraphicBufferProducer() {
- return mProducer;
-}
-
-Return<sp<IConfigurable>> InputSurface::getConfigurable() {
- return mConfigurable;
-}
-
-Return<void> InputSurface::connect(
- const sp<IInputSink>& sink,
- connect_cb _hidl_cb) {
- Status status;
- sp<InputSurfaceConnection> connection;
- if (!sink) {
- _hidl_cb(Status::BAD_VALUE, nullptr);
- return Void();
- }
- std::shared_ptr<C2Component> comp = Component::findLocalComponent(sink);
- if (comp) {
- connection = new InputSurfaceConnection(mSource, comp, mParameterCache);
- } else {
- connection = new InputSurfaceConnection(mSource, sink, mParameterCache);
- }
- if (!connection->init()) {
- connection = nullptr;
- status = Status::BAD_VALUE;
- } else {
- status = Status::OK;
- }
- _hidl_cb(status, connection);
- return Void();
-}
-
-// Constructor is exclusive to ComponentStore.
-InputSurface::InputSurface(
- const std::shared_ptr<ParameterCache>& cache,
- const std::shared_ptr<C2ReflectorHelper>& reflector,
- const sp<HGraphicBufferProducer>& producer,
- const sp<GraphicBufferSource>& source)
- : mParameterCache{cache},
- mProducer{producer},
- mSource{source},
- mIntf{std::make_shared<Interface>(reflector)},
- mConfigurable{new CachedConfigurable(
- std::make_unique<ConfigurableIntf>(
- mIntf, source))} {
-
- mConfigurable->init(mParameterCache);
-}
-
-} // namespace utils
-} // namespace V1_0
-} // namespace c2
-} // namespace media
-} // namespace hardware
-} // namespace android
-
diff --git a/media/codec2/hal/aidl/InputSurfaceConnection.cpp b/media/codec2/hal/aidl/InputSurfaceConnection.cpp
deleted file mode 100644
index 7c2e014..0000000
--- a/media/codec2/hal/aidl/InputSurfaceConnection.cpp
+++ /dev/null
@@ -1,531 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "Codec2-InputSurfaceConnection"
-#include <android-base/logging.h>
-
-#include <codec2/hidl/1.0/InputSurfaceConnection.h>
-#include <codec2/hidl/1.0/InputSurfaceConnection.h>
-
-#include <memory>
-#include <list>
-#include <mutex>
-#include <atomic>
-
-#include <hidl/HidlSupport.h>
-#include <media/stagefright/bqhelper/ComponentWrapper.h>
-#include <system/graphics.h>
-#include <ui/GraphicBuffer.h>
-#include <utils/Errors.h>
-
-#include <C2.h>
-#include <C2AllocatorGralloc.h>
-#include <C2BlockInternal.h>
-#include <C2Buffer.h>
-#include <C2Component.h>
-#include <C2Config.h>
-#include <C2Debug.h>
-#include <C2PlatformSupport.h>
-#include <C2Work.h>
-
-namespace android {
-namespace hardware {
-namespace media {
-namespace c2 {
-namespace V1_0 {
-namespace utils {
-
-constexpr int32_t kBufferCount = 16;
-
-using namespace ::android;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Return;
-
-namespace /* unnamed */ {
-
-class Buffer2D : public C2Buffer {
-public:
- explicit Buffer2D(C2ConstGraphicBlock block) : C2Buffer({ block }) {
- }
-};
-
-} // unnamed namespace
-
-// Derived class of ComponentWrapper for use with
-// GraphicBufferSource::configure().
-//
-struct InputSurfaceConnection::Impl : public ComponentWrapper {
-
- Impl(const sp<GraphicBufferSource>& source,
- const std::shared_ptr<C2Component>& localComp)
- : mSource{source}, mLocalComp{localComp}, mSink{}, mFrameIndex{0} {
- std::shared_ptr<C2ComponentInterface> intf = localComp->intf();
- mSinkName = intf ? intf->getName() : "";
- }
-
- Impl(const sp<GraphicBufferSource>& source,
- const sp<IInputSink>& sink)
- : mSource{source}, mLocalComp{}, mSink{sink}, mFrameIndex{0} {
- Return<sp<IConfigurable>> transResult = sink->getConfigurable();
- if (!transResult.isOk()) {
- LOG(ERROR) << "Remote sink is dead.";
- return;
- }
- mSinkConfigurable =
- static_cast<sp<IConfigurable>>(transResult);
- if (!mSinkConfigurable) {
- LOG(ERROR) << "Remote sink is not configurable.";
- mSinkName = "";
- return;
- }
-
- hidl_string name;
- Return<void> transStatus = mSinkConfigurable->getName(
- [&name](const hidl_string& n) {
- name = n;
- });
- if (!transStatus.isOk()) {
- LOG(ERROR) << "Remote sink's configurable is dead.";
- mSinkName = "";
- return;
- }
- mSinkName = name.c_str();
- }
-
- virtual ~Impl() {
- mSource->stop();
- mSource->release();
- }
-
- bool init() {
- if (mSource == nullptr) {
- return false;
- }
- status_t err = mSource->initCheck();
- if (err != OK) {
- LOG(WARNING) << "Impl::init -- GraphicBufferSource init failed: "
- << "status = " << err << ".";
- return false;
- }
-
- // TODO: read settings properly from the interface
- C2StreamPictureSizeInfo::input inputSize;
- C2StreamUsageTuning::input usage;
- c2_status_t c2Status = queryFromSink({ &inputSize, &usage },
- {},
- C2_MAY_BLOCK,
- nullptr);
- if (c2Status != C2_OK) {
- LOG(WARNING) << "Impl::init -- cannot query information from "
- "the component interface: "
- << "status = " << asString(c2Status) << ".";
- return false;
- }
-
- // TODO: proper color aspect & dataspace
- android_dataspace dataSpace = HAL_DATASPACE_BT709;
-
- // TODO: use the usage read from intf
- // uint32_t grallocUsage =
- // C2AndroidMemoryUsage(C2MemoryUsage(usage.value)).
- // asGrallocUsage();
-
- uint32_t grallocUsage =
- mSinkName.compare(0, 11, "c2.android.") == 0 ?
- GRALLOC_USAGE_SW_READ_OFTEN :
- GRALLOC_USAGE_HW_VIDEO_ENCODER;
-
- err = mSource->configure(
- this, dataSpace, kBufferCount,
- inputSize.width, inputSize.height,
- grallocUsage);
- if (err != OK) {
- LOG(WARNING) << "Impl::init -- GBS configure failed: "
- << "status = " << err << ".";
- return false;
- }
- for (int32_t i = 0; i < kBufferCount; ++i) {
- if (mSource->onInputBufferAdded(i) != OK) {
- LOG(WARNING) << "Impl::init: failed to populate GBS slots.";
- return false;
- }
- }
- if (mSource->start() != OK) {
- LOG(WARNING) << "Impl::init -- GBS failed to start.";
- return false;
- }
- mAllocatorMutex.lock();
- c2_status_t c2err = GetCodec2PlatformAllocatorStore()->fetchAllocator(
- C2AllocatorStore::PLATFORM_START + 1, // GRALLOC
- &mAllocator);
- mAllocatorMutex.unlock();
- if (c2err != OK) {
- LOG(WARNING) << "Impl::init -- failed to fetch gralloc allocator: "
- << "status = " << asString(c2err) << ".";
- return false;
- }
- return true;
- }
-
- // From ComponentWrapper
- virtual status_t submitBuffer(
- int32_t bufferId,
- const sp<GraphicBuffer>& buffer,
- int64_t timestamp,
- int fenceFd) override {
- LOG(VERBOSE) << "Impl::submitBuffer -- bufferId = " << bufferId << ".";
- // TODO: Use fd to construct fence
- (void)fenceFd;
-
- std::shared_ptr<C2GraphicAllocation> alloc;
- C2Handle* handle = WrapNativeCodec2GrallocHandle(
- buffer->handle,
- buffer->width, buffer->height,
- buffer->format, buffer->usage, buffer->stride);
- mAllocatorMutex.lock();
- c2_status_t err = mAllocator->priorGraphicAllocation(handle, &alloc);
- mAllocatorMutex.unlock();
- if (err != OK) {
- native_handle_close(handle);
- native_handle_delete(handle);
- return UNKNOWN_ERROR;
- }
- std::shared_ptr<C2GraphicBlock> block =
- _C2BlockFactory::CreateGraphicBlock(alloc);
-
- std::unique_ptr<C2Work> work(new C2Work);
- work->input.flags = (C2FrameData::flags_t)0;
- work->input.ordinal.timestamp = timestamp;
- work->input.ordinal.frameIndex = mFrameIndex.fetch_add(
- 1, std::memory_order_relaxed);
- work->input.buffers.clear();
- std::shared_ptr<C2Buffer> c2Buffer(
- // TODO: fence
- new Buffer2D(block->share(
- C2Rect(block->width(), block->height()), ::C2Fence())),
- [bufferId, source = mSource](C2Buffer* ptr) {
- delete ptr;
- if (source != nullptr) {
- // TODO: fence
- (void)source->onInputBufferEmptied(bufferId, -1);
- }
- });
- work->input.buffers.push_back(c2Buffer);
- work->worklets.clear();
- work->worklets.emplace_back(new C2Worklet);
- std::list<std::unique_ptr<C2Work>> items;
- items.push_back(std::move(work));
-
- err = queueToSink(&items);
- return (err == C2_OK) ? OK : UNKNOWN_ERROR;
- }
-
- virtual status_t submitEos(int32_t bufferId) override {
- LOG(VERBOSE) << "Impl::submitEos -- bufferId = " << bufferId << ".";
- (void)bufferId;
-
- std::unique_ptr<C2Work> work(new C2Work);
- work->input.flags = (C2FrameData::flags_t)0;
- work->input.ordinal.frameIndex = mFrameIndex.fetch_add(
- 1, std::memory_order_relaxed);
- work->input.buffers.clear();
- work->worklets.clear();
- work->worklets.emplace_back(new C2Worklet);
- std::list<std::unique_ptr<C2Work>> items;
- items.push_back(std::move(work));
-
- c2_status_t err = queueToSink(&items);
- return (err == C2_OK) ? OK : UNKNOWN_ERROR;
- }
-
- virtual void dispatchDataSpaceChanged(
- int32_t dataSpace, int32_t aspects, int32_t pixelFormat) override {
- // TODO
- (void)dataSpace;
- (void)aspects;
- (void)pixelFormat;
- }
-
- // Configurable interface for InputSurfaceConnection::Impl.
- //
- // This class is declared as an inner class so that it will have access to
- // all Impl's members.
- struct ConfigurableIntf : public ConfigurableC2Intf {
- sp<Impl> mConnection;
- ConfigurableIntf(const sp<Impl>& connection)
- : ConfigurableC2Intf{"input-surface-connection", 0},
- mConnection{connection} {}
- virtual c2_status_t config(
- const std::vector<C2Param*> ¶ms,
- c2_blocking_t mayBlock,
- std::vector<std::unique_ptr<C2SettingResult>> *const failures
- ) override;
- virtual c2_status_t query(
- const std::vector<C2Param::Index> &indices,
- c2_blocking_t mayBlock,
- std::vector<std::unique_ptr<C2Param>> *const params) const override;
- virtual c2_status_t querySupportedParams(
- std::vector<std::shared_ptr<C2ParamDescriptor>> *const params
- ) const override;
- virtual c2_status_t querySupportedValues(
- std::vector<C2FieldSupportedValuesQuery> &fields,
- c2_blocking_t mayBlock) const override;
- };
-
-private:
- c2_status_t queryFromSink(
- const std::vector<C2Param*> &stackParams,
- const std::vector<C2Param::Index> &heapParamIndices,
- c2_blocking_t mayBlock,
- std::vector<std::unique_ptr<C2Param>>* const heapParams) {
- if (mLocalComp) {
- std::shared_ptr<C2ComponentInterface> intf = mLocalComp->intf();
- if (intf) {
- return intf->query_vb(stackParams,
- heapParamIndices,
- mayBlock,
- heapParams);
- } else {
- LOG(ERROR) << "queryFromSink -- "
- << "component does not have an interface.";
- return C2_BAD_STATE;
- }
- }
-
- CHECK(mSink) << "-- queryFromSink "
- << "-- connection has no sink.";
- CHECK(mSinkConfigurable) << "-- queryFromSink "
- << "-- sink has no configurable.";
-
- hidl_vec<ParamIndex> indices(
- stackParams.size() + heapParamIndices.size());
- size_t numIndices = 0;
- for (C2Param* const& stackParam : stackParams) {
- if (!stackParam) {
- LOG(DEBUG) << "queryFromSink -- null stack param encountered.";
- continue;
- }
- indices[numIndices++] = static_cast<ParamIndex>(stackParam->index());
- }
- size_t numStackIndices = numIndices;
- for (const C2Param::Index& index : heapParamIndices) {
- indices[numIndices++] =
- static_cast<ParamIndex>(static_cast<uint32_t>(index));
- }
- indices.resize(numIndices);
- if (heapParams) {
- heapParams->reserve(heapParams->size() + numIndices);
- }
- c2_status_t status;
- Return<void> transStatus = mSinkConfigurable->query(
- indices,
- mayBlock == C2_MAY_BLOCK,
- [&status, &numStackIndices, &stackParams, heapParams](
- Status s, const Params& p) {
- status = static_cast<c2_status_t>(s);
- if (status != C2_OK && status != C2_BAD_INDEX) {
- LOG(DEBUG) << "queryFromSink -- call failed: "
- << "status = " << asString(status) << ".";
- return;
- }
- std::vector<C2Param*> paramPointers;
- if (!parseParamsBlob(¶mPointers, p)) {
- LOG(DEBUG) << "queryFromSink -- error while "
- << "parsing params.";
- status = C2_CORRUPTED;
- return;
- }
- size_t i = 0;
- for (auto it = paramPointers.begin();
- it != paramPointers.end(); ) {
- C2Param* paramPointer = *it;
- if (numStackIndices > 0) {
- --numStackIndices;
- if (!paramPointer) {
- LOG(DEBUG) << "queryFromSink -- "
- "null stack param.";
- ++it;
- continue;
- }
- for (; i < stackParams.size() &&
- !stackParams[i]; ) {
- ++i;
- }
- CHECK(i < stackParams.size());
- if (stackParams[i]->index() !=
- paramPointer->index()) {
- LOG(DEBUG) << "queryFromSink -- "
- "param skipped (index = "
- << stackParams[i]->index() << ").";
- stackParams[i++]->invalidate();
- continue;
- }
- if (!stackParams[i++]->updateFrom(*paramPointer)) {
- LOG(DEBUG) << "queryFromSink -- "
- "param update failed (index = "
- << paramPointer->index() << ").";
- }
- } else {
- if (!paramPointer) {
- LOG(DEBUG) << "queryFromSink -- "
- "null heap param.";
- ++it;
- continue;
- }
- if (!heapParams) {
- LOG(WARNING) << "queryFromSink -- "
- "too many stack params.";
- break;
- }
- heapParams->emplace_back(C2Param::Copy(*paramPointer));
- }
- ++it;
- }
- });
- if (!transStatus.isOk()) {
- LOG(ERROR) << "queryFromSink -- transaction failed.";
- return C2_CORRUPTED;
- }
- return status;
- }
-
- c2_status_t queueToSink(std::list<std::unique_ptr<C2Work>>* const items) {
- if (mLocalComp) {
- return mLocalComp->queue_nb(items);
- }
-
- CHECK(mSink) << "-- queueToSink "
- << "-- connection has no sink.";
-
- WorkBundle workBundle;
- if (!objcpy(&workBundle, *items, nullptr)) {
- LOG(ERROR) << "queueToSink -- bad input.";
- return C2_CORRUPTED;
- }
- Return<Status> transStatus = mSink->queue(workBundle);
- if (!transStatus.isOk()) {
- LOG(ERROR) << "queueToSink -- transaction failed.";
- return C2_CORRUPTED;
- }
- c2_status_t status =
- static_cast<c2_status_t>(static_cast<Status>(transStatus));
- if (status != C2_OK) {
- LOG(DEBUG) << "queueToSink -- call failed: "
- << asString(status);
- }
- return status;
- }
-
- sp<GraphicBufferSource> mSource;
- std::shared_ptr<C2Component> mLocalComp;
- sp<IInputSink> mSink;
- sp<IConfigurable> mSinkConfigurable;
- std::string mSinkName;
-
- // Needed for ComponentWrapper implementation
- std::mutex mAllocatorMutex;
- std::shared_ptr<C2Allocator> mAllocator;
- std::atomic_uint64_t mFrameIndex;
-
-};
-
-InputSurfaceConnection::InputSurfaceConnection(
- const sp<GraphicBufferSource>& source,
- const std::shared_ptr<C2Component>& comp,
- const std::shared_ptr<ParameterCache>& cache)
- : mImpl{new Impl(source, comp)},
- mConfigurable{new CachedConfigurable(
- std::make_unique<Impl::ConfigurableIntf>(mImpl))} {
- mConfigurable->init(cache);
-}
-
-InputSurfaceConnection::InputSurfaceConnection(
- const sp<GraphicBufferSource>& source,
- const sp<IInputSink>& sink,
- const std::shared_ptr<ParameterCache>& cache)
- : mImpl{new Impl(source, sink)},
- mConfigurable{new CachedConfigurable(
- std::make_unique<Impl::ConfigurableIntf>(mImpl))} {
- mConfigurable->init(cache);
-}
-
-Return<Status> InputSurfaceConnection::disconnect() {
- std::lock_guard<std::mutex> lock(mImplMutex);
- mImpl = nullptr;
- return Status::OK;
-}
-
-InputSurfaceConnection::~InputSurfaceConnection() {
- mImpl = nullptr;
-}
-
-bool InputSurfaceConnection::init() {
- std::lock_guard<std::mutex> lock(mImplMutex);
- return mImpl->init();
-}
-
-Return<sp<IConfigurable>> InputSurfaceConnection::getConfigurable() {
- return mConfigurable;
-}
-
-// Configurable interface for InputSurfaceConnection::Impl
-c2_status_t InputSurfaceConnection::Impl::ConfigurableIntf::config(
- const std::vector<C2Param*> ¶ms,
- c2_blocking_t mayBlock,
- std::vector<std::unique_ptr<C2SettingResult>> *const failures) {
- // TODO: implement
- (void)params;
- (void)mayBlock;
- (void)failures;
- return C2_OK;
-}
-
-c2_status_t InputSurfaceConnection::Impl::ConfigurableIntf::query(
- const std::vector<C2Param::Index> &indices,
- c2_blocking_t mayBlock,
- std::vector<std::unique_ptr<C2Param>> *const params) const {
- // TODO: implement
- (void)indices;
- (void)mayBlock;
- (void)params;
- return C2_OK;
-}
-
-c2_status_t InputSurfaceConnection::Impl::ConfigurableIntf::querySupportedParams(
- std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const {
- // TODO: implement
- (void)params;
- return C2_OK;
-}
-
-c2_status_t InputSurfaceConnection::Impl::ConfigurableIntf::querySupportedValues(
- std::vector<C2FieldSupportedValuesQuery> &fields,
- c2_blocking_t mayBlock) const {
- // TODO: implement
- (void)fields;
- (void)mayBlock;
- return C2_OK;
-}
-
-} // namespace utils
-} // namespace V1_0
-} // namespace c2
-} // namespace media
-} // namespace hardware
-} // namespace android
-
diff --git a/media/codec2/hal/aidl/fuzzer.cpp b/media/codec2/hal/aidl/fuzzer.cpp
new file mode 100644
index 0000000..c1a2762
--- /dev/null
+++ b/media/codec2/hal/aidl/fuzzer.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <fuzzbinder/libbinder_ndk_driver.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+#include <C2PlatformSupport.h>
+
+#include <android/binder_interface_utils.h>
+#include <codec2/aidl/ComponentStore.h>
+
+using aidl::android::hardware::media::c2::utils::ComponentStore;
+using android::fuzzService;
+using ndk::SharedRefBase;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ std::shared_ptr<C2ComponentStore> store = ::android::GetCodec2PlatformComponentStore();
+ std::shared_ptr<ComponentStore> binder = SharedRefBase::make<ComponentStore>(store);
+
+ fuzzService(binder->asBinder().get(), FuzzedDataProvider(data, size));
+
+ return 0;
+}
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/Component.h b/media/codec2/hal/aidl/include/codec2/aidl/Component.h
index e343655..d5ea92b 100644
--- a/media/codec2/hal/aidl/include/codec2/aidl/Component.h
+++ b/media/codec2/hal/aidl/include/codec2/aidl/Component.h
@@ -14,21 +14,19 @@
* limitations under the License.
*/
-#ifndef CODEC2_HIDL_V1_0_UTILS_COMPONENT_H
-#define CODEC2_HIDL_V1_0_UTILS_COMPONENT_H
+#ifndef CODEC2_AIDL_UTILS_COMPONENT_H
+#define CODEC2_AIDL_UTILS_COMPONENT_H
-#include <codec2/hidl/1.0/ComponentInterface.h>
-#include <codec2/hidl/1.0/Configurable.h>
-#include <codec2/hidl/1.0/types.h>
+#include <codec2/aidl/ComponentInterface.h>
+#include <codec2/aidl/Configurable.h>
+#include <codec2/aidl/BufferTypes.h>
+#include <codec2/aidl/ParamTypes.h>
-#include <android/hardware/media/bufferpool/2.0/IClientManager.h>
-#include <android/hardware/media/c2/1.0/IComponent.h>
-#include <android/hardware/media/c2/1.0/IComponentInterface.h>
-#include <android/hardware/media/c2/1.0/IComponentListener.h>
-#include <android/hardware/media/c2/1.0/IComponentStore.h>
-#include <android/hardware/media/c2/1.0/IInputSink.h>
-#include <hidl/Status.h>
-#include <hwbinder/IBinder.h>
+#include <aidl/android/hardware/media/bufferpool2/IClientManager.h>
+#include <aidl/android/hardware/media/c2/BnComponent.h>
+#include <aidl/android/hardware/media/c2/IComponentInterface.h>
+#include <aidl/android/hardware/media/c2/IComponentListener.h>
+#include <aidl/android/hardware/media/c2/IComponentStore.h>
#include <C2Component.h>
#include <C2Buffer.h>
@@ -38,86 +36,50 @@
#include <memory>
#include <mutex>
+namespace aidl {
namespace android {
namespace hardware {
namespace media {
namespace c2 {
-namespace V1_0 {
namespace utils {
-using ::android::hardware::hidl_array;
-using ::android::hardware::hidl_memory;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::hardware::IBinder;
-using ::android::sp;
-using ::android::wp;
struct ComponentStore;
-struct Component : public IComponent,
+struct Component : public BnComponent,
public std::enable_shared_from_this<Component> {
Component(
const std::shared_ptr<C2Component>&,
- const sp<IComponentListener>& listener,
- const sp<ComponentStore>& store,
- const sp<::android::hardware::media::bufferpool::V2_0::
- IClientManager>& clientPoolManager);
+ const std::shared_ptr<IComponentListener>& listener,
+ const std::shared_ptr<ComponentStore>& store,
+ const std::shared_ptr<bufferpool2::IClientManager>& clientPoolManager);
c2_status_t status() const;
- typedef ::android::hardware::graphics::bufferqueue::V1_0::
- IGraphicBufferProducer HGraphicBufferProducer1;
- typedef ::android::hardware::graphics::bufferqueue::V2_0::
- IGraphicBufferProducer HGraphicBufferProducer2;
-
// Methods from IComponent follow.
- virtual Return<Status> queue(const WorkBundle& workBundle) override;
- virtual Return<void> flush(flush_cb _hidl_cb) override;
- virtual Return<Status> drain(bool withEos) override;
- virtual Return<Status> setOutputSurface(
- uint64_t blockPoolId,
- const sp<HGraphicBufferProducer2>& surface) override;
- virtual Return<void> connectToInputSurface(
- const sp<IInputSurface>& inputSurface,
- connectToInputSurface_cb _hidl_cb) override;
- virtual Return<void> connectToOmxInputSurface(
- const sp<HGraphicBufferProducer1>& producer,
- const sp<::android::hardware::media::omx::V1_0::
- IGraphicBufferSource>& source,
- connectToOmxInputSurface_cb _hidl_cb) override;
- virtual Return<Status> disconnectFromInputSurface() override;
- virtual Return<void> createBlockPool(
- uint32_t allocatorId,
- createBlockPool_cb _hidl_cb) override;
- virtual Return<Status> destroyBlockPool(uint64_t blockPoolId) override;
- virtual Return<Status> start() override;
- virtual Return<Status> stop() override;
- virtual Return<Status> reset() override;
- virtual Return<Status> release() override;
- virtual Return<sp<IComponentInterface>> getInterface() override;
- virtual Return<sp<IInputSink>> asInputSink() override;
-
- // Returns a C2Component associated to the given sink if the sink is indeed
- // a local component. Returns nullptr otherwise.
- //
- // This function is used by InputSurface::connect().
- static std::shared_ptr<C2Component> findLocalComponent(
- const sp<IInputSink>& sink);
+ ::ndk::ScopedAStatus queue(const WorkBundle& workBundle) override;
+ ::ndk::ScopedAStatus flush(WorkBundle *workBundle) override;
+ ::ndk::ScopedAStatus drain(bool withEos) override;
+ ::ndk::ScopedAStatus createBlockPool(
+ const IComponent::BlockPoolAllocator &allocator,
+ IComponent::BlockPool *blockPool) override;
+ ::ndk::ScopedAStatus destroyBlockPool(int64_t blockPoolId) override;
+ ::ndk::ScopedAStatus start() override;
+ ::ndk::ScopedAStatus stop() override;
+ ::ndk::ScopedAStatus reset() override;
+ ::ndk::ScopedAStatus release() override;
+ ::ndk::ScopedAStatus getInterface(
+ std::shared_ptr<IComponentInterface> *intf) override;
+ ::ndk::ScopedAStatus configureVideoTunnel(
+ int32_t avSyncHwId,
+ common::NativeHandle* handle) override;
protected:
c2_status_t mInit;
std::shared_ptr<C2Component> mComponent;
- sp<ComponentInterface> mInterface;
- sp<IComponentListener> mListener;
- sp<ComponentStore> mStore;
- ::android::hardware::media::c2::V1_0::utils::DefaultBufferPoolSender
- mBufferPoolSender;
-
- struct Sink;
- std::mutex mSinkMutex;
- sp<Sink> mSink;
+ std::shared_ptr<ComponentInterface> mInterface;
+ std::shared_ptr<IComponentListener> mListener;
+ std::shared_ptr<ComponentStore> mStore;
+ DefaultBufferPoolSender mBufferPoolSender;
std::mutex mBlockPoolsMutex;
// This map keeps C2BlockPool objects that are created by createBlockPool()
@@ -125,7 +87,7 @@
// destroyBlockPool(), reset() or release(), or by destroying the component.
std::map<uint64_t, std::shared_ptr<C2BlockPool>> mBlockPools;
- void initListener(const sp<Component>& self);
+ void initListener(const std::shared_ptr<Component>& self);
virtual ~Component() override;
@@ -133,15 +95,18 @@
struct Listener;
- using HwDeathRecipient = ::android::hardware::hidl_death_recipient;
- sp<HwDeathRecipient> mDeathRecipient;
+ ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
+ static void OnBinderDied(void *cookie);
+ static void OnBinderUnlinked(void *cookie);
+ struct DeathContext;
+ DeathContext *mDeathContext;
};
} // namespace utils
-} // namespace V1_0
} // namespace c2
} // namespace media
} // namespace hardware
} // namespace android
+} // namespace aidl
-#endif // CODEC2_HIDL_V1_0_UTILS_COMPONENT_H
+#endif // CODEC2_AIDL_UTILS_COMPONENT_H
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/ComponentInterface.h b/media/codec2/hal/aidl/include/codec2/aidl/ComponentInterface.h
index 9102f92..7723bee 100644
--- a/media/codec2/hal/aidl/include/codec2/aidl/ComponentInterface.h
+++ b/media/codec2/hal/aidl/include/codec2/aidl/ComponentInterface.h
@@ -14,14 +14,13 @@
* limitations under the License.
*/
-#ifndef CODEC2_HIDL_V1_0_UTILS_COMPONENT_INTERFACE_H
-#define CODEC2_HIDL_V1_0_UTILS_COMPONENT_INTERFACE_H
+#ifndef CODEC2_AIDL_UTILS_COMPONENT_INTERFACE_H
+#define CODEC2_AIDL_UTILS_COMPONENT_INTERFACE_H
-#include <codec2/hidl/1.0/Configurable.h>
-#include <codec2/hidl/1.0/types.h>
+#include <codec2/aidl/Configurable.h>
+#include <codec2/aidl/ParamTypes.h>
-#include <android/hardware/media/c2/1.0/IComponentInterface.h>
-#include <hidl/Status.h>
+#include <aidl/android/hardware/media/c2/BnComponentInterface.h>
#include <C2Component.h>
#include <C2Buffer.h>
@@ -29,38 +28,35 @@
#include <memory>
+namespace aidl {
namespace android {
namespace hardware {
namespace media {
namespace c2 {
-namespace V1_0 {
namespace utils {
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::sp;
-
struct ComponentStore;
-struct ComponentInterface : public IComponentInterface {
+struct ComponentInterface : public BnComponentInterface {
ComponentInterface(
const std::shared_ptr<C2ComponentInterface>& interface,
const std::shared_ptr<ParameterCache>& cache);
c2_status_t status() const;
- virtual Return<sp<IConfigurable>> getConfigurable() override;
+ ::ndk::ScopedAStatus getConfigurable(
+ std::shared_ptr<IConfigurable> *intf) override;
protected:
std::shared_ptr<C2ComponentInterface> mInterface;
- sp<CachedConfigurable> mConfigurable;
+ std::shared_ptr<CachedConfigurable> mConfigurable;
c2_status_t mInit;
};
} // namespace utils
-} // namespace V1_0
} // namespace c2
} // namespace media
} // namespace hardware
} // namespace android
+} // namespace aidl
-#endif // CODEC2_HIDL_V1_0_UTILS_COMPONENT_INTERFACE_H
+#endif // CODEC2_AIDL_UTILS_COMPONENT_INTERFACE_H
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/ComponentStore.h b/media/codec2/hal/aidl/include/codec2/aidl/ComponentStore.h
index 27e2a05..7fc5d2f 100644
--- a/media/codec2/hal/aidl/include/codec2/aidl/ComponentStore.h
+++ b/media/codec2/hal/aidl/include/codec2/aidl/ComponentStore.h
@@ -14,16 +14,15 @@
* limitations under the License.
*/
-#ifndef CODEC2_HIDL_V1_0_UTILS_COMPONENTSTORE_H
-#define CODEC2_HIDL_V1_0_UTILS_COMPONENTSTORE_H
+#ifndef CODEC2_AIDL_UTILS_COMPONENTSTORE_H
+#define CODEC2_AIDL_UTILS_COMPONENTSTORE_H
-#include <codec2/hidl/1.0/Component.h>
-#include <codec2/hidl/1.0/ComponentInterface.h>
-#include <codec2/hidl/1.0/Configurable.h>
+#include <android/binder_auto_utils.h>
+#include <codec2/aidl/ComponentInterface.h>
+#include <codec2/aidl/Configurable.h>
-#include <android/hardware/media/bufferpool/2.0/IClientManager.h>
-#include <android/hardware/media/c2/1.0/IComponentStore.h>
-#include <hidl/Status.h>
+#include <aidl/android/hardware/media/bufferpool2/IClientManager.h>
+#include <aidl/android/hardware/media/c2/BnComponentStore.h>
#include <C2Component.h>
#include <C2Param.h>
@@ -38,23 +37,21 @@
namespace android {
class FilterWrapper;
+} // namespace android
+namespace aidl {
+namespace android {
namespace hardware {
namespace media {
namespace c2 {
-namespace V1_0 {
namespace utils {
-using ::android::hardware::media::bufferpool::V2_0::IClientManager;
+struct Component;
-using ::android::hardware::hidl_handle;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::sp;
+using ::aidl::android::hardware::media::bufferpool2::IClientManager;
-struct ComponentStore : public IComponentStore {
+struct ComponentStore : public BnComponentStore,
+ public std::enable_shared_from_this<ComponentStore> {
ComponentStore(const std::shared_ptr<C2ComponentStore>& store);
virtual ~ComponentStore();
@@ -76,38 +73,38 @@
*/
std::shared_ptr<ParameterCache> getParameterCache() const;
- static std::shared_ptr<FilterWrapper> GetFilterWrapper();
+ static std::shared_ptr<::android::FilterWrapper> GetFilterWrapper();
- // Methods from ::android::hardware::media::c2::V1_0::IComponentStore.
- virtual Return<void> createComponent(
- const hidl_string& name,
- const sp<IComponentListener>& listener,
- const sp<IClientManager>& pool,
- createComponent_cb _hidl_cb) override;
- virtual Return<void> createInterface(
- const hidl_string& name,
- createInterface_cb _hidl_cb) override;
- virtual Return<void> listComponents(listComponents_cb _hidl_cb) override;
- virtual Return<void> createInputSurface(
- createInputSurface_cb _hidl_cb) override;
- virtual Return<void> getStructDescriptors(
- const hidl_vec<uint32_t>& indices,
- getStructDescriptors_cb _hidl_cb) override;
- virtual Return<sp<IClientManager>> getPoolClientManager() override;
- virtual Return<Status> copyBuffer(
+ // Methods from ::aidl::android::hardware::media::c2::IComponentStore.
+ virtual ::ndk::ScopedAStatus createComponent(
+ const std::string& name,
+ const std::shared_ptr<IComponentListener>& listener,
+ const std::shared_ptr<IClientManager>& pool,
+ std::shared_ptr<IComponent> *component) override;
+ virtual ::ndk::ScopedAStatus createInterface(
+ const std::string& name,
+ std::shared_ptr<IComponentInterface> *intf) override;
+ virtual ::ndk::ScopedAStatus listComponents(
+ std::vector<IComponentStore::ComponentTraits>* traits) override;
+ virtual ::ndk::ScopedAStatus getStructDescriptors(
+ const std::vector<int32_t>& indices,
+ std::vector<StructDescriptor> *descs) override;
+ virtual ::ndk::ScopedAStatus getPoolClientManager(
+ std::shared_ptr<IClientManager> *manager) override;
+ virtual ::ndk::ScopedAStatus copyBuffer(
const Buffer& src,
const Buffer& dst) override;
- virtual Return<sp<IConfigurable>> getConfigurable() override;
+ virtual ::ndk::ScopedAStatus getConfigurable(
+ std::shared_ptr<IConfigurable> *configurable) override;
/**
* Dumps information when lshal is called.
*/
- virtual Return<void> debug(
- const hidl_handle& handle,
- const hidl_vec<hidl_string>& args) override;
+ virtual binder_status_t dump(
+ int fd, const char** args, uint32_t numArgs) override;
protected:
- sp<CachedConfigurable> mConfigurable;
+ std::shared_ptr<CachedConfigurable> mConfigurable;
struct StoreParameterCache;
std::shared_ptr<StoreParameterCache> mParameterCache;
@@ -153,10 +150,10 @@
};
} // namespace utils
-} // namespace V1_0
} // namespace c2
} // namespace media
} // namespace hardware
} // namespace android
+} // namespace aidl
-#endif // CODEC2_HIDL_V1_0_UTILS_COMPONENTSTORE_H
+#endif // CODEC2_AIDL_UTILS_COMPONENTSTORE_H
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/Configurable.h b/media/codec2/hal/aidl/include/codec2/aidl/Configurable.h
index 8f49a97..6cc2c1b 100644
--- a/media/codec2/hal/aidl/include/codec2/aidl/Configurable.h
+++ b/media/codec2/hal/aidl/include/codec2/aidl/Configurable.h
@@ -14,11 +14,10 @@
* limitations under the License.
*/
-#ifndef CODEC2_HIDL_V1_0_UTILS_CONFIGURABLE_H
-#define CODEC2_HIDL_V1_0_UTILS_CONFIGURABLE_H
+#ifndef CODEC2_AIDL_UTILS_CONFIGURABLE_H
+#define CODEC2_AIDL_UTILS_CONFIGURABLE_H
-#include <android/hardware/media/c2/1.0/IConfigurable.h>
-#include <hidl/Status.h>
+#include <aidl/android/hardware/media/c2/BnConfigurable.h>
#include <C2Component.h>
#include <C2Param.h>
@@ -26,18 +25,13 @@
#include <memory>
+namespace aidl {
namespace android {
namespace hardware {
namespace media {
namespace c2 {
-namespace V1_0 {
namespace utils {
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::sp;
-
struct ComponentStore;
/**
@@ -102,7 +96,7 @@
*
* Note that caching happens
*/
-struct CachedConfigurable : public IConfigurable {
+struct CachedConfigurable : public BnConfigurable {
CachedConfigurable(std::unique_ptr<ConfigurableC2Intf>&& intf);
// Populates mSupportedParams.
@@ -110,29 +104,29 @@
// Methods from ::android::hardware::media::c2::V1_0::IConfigurable
- virtual Return<uint32_t> getId() override;
+ virtual ::ndk::ScopedAStatus getId(int32_t* id) override;
- virtual Return<void> getName(getName_cb _hidl_cb) override;
+ virtual ::ndk::ScopedAStatus getName(std::string* name) override;
- virtual Return<void> query(
- const hidl_vec<uint32_t>& indices,
+ virtual ::ndk::ScopedAStatus query(
+ const std::vector<int32_t>& indices,
bool mayBlock,
- query_cb _hidl_cb) override;
+ Params* params) override;
- virtual Return<void> config(
- const hidl_vec<uint8_t>& inParams,
+ virtual ::ndk::ScopedAStatus config(
+ const ::aidl::android::hardware::media::c2::Params& params,
bool mayBlock,
- config_cb _hidl_cb) override;
+ ConfigResult* result) override;
- virtual Return<void> querySupportedParams(
- uint32_t start,
- uint32_t count,
- querySupportedParams_cb _hidl_cb) override;
+ virtual ::ndk::ScopedAStatus querySupportedParams(
+ int32_t start,
+ int32_t count,
+ std::vector<ParamDescriptor>* paramDesc) override;
- virtual Return<void> querySupportedValues(
- const hidl_vec<FieldSupportedValuesQuery>& inFields,
+ virtual ::ndk::ScopedAStatus querySupportedValues(
+ const std::vector<FieldSupportedValuesQuery>& fields,
bool mayBlock,
- querySupportedValues_cb _hidl_cb) override;
+ std::vector<FieldSupportedValuesQueryResult>* result) override;
protected:
// Common Codec2.0 interface wrapper
@@ -143,11 +137,11 @@
};
} // namespace utils
-} // namespace V1_0
} // namespace c2
} // namespace media
} // namespace hardware
} // namespace android
+} // namespace aidl
-#endif // CODEC2_HIDL_V1_0_UTILS_CONFIGURABLE_H
+#endif // CODEC2_AIDL_UTILS_CONFIGURABLE_H
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/InputBufferManager.h b/media/codec2/hal/aidl/include/codec2/aidl/InputBufferManager.h
index 42fa557..4e107a8 100644
--- a/media/codec2/hal/aidl/include/codec2/aidl/InputBufferManager.h
+++ b/media/codec2/hal/aidl/include/codec2/aidl/InputBufferManager.h
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-#ifndef CODEC2_HIDL_V1_0_UTILS_INPUT_BUFFER_MANAGER_H
-#define CODEC2_HIDL_V1_0_UTILS_INPUT_BUFFER_MANAGER_H
+#ifndef CODEC2_AIDL_UTILS_INPUT_BUFFER_MANAGER_H
+#define CODEC2_AIDL_UTILS_INPUT_BUFFER_MANAGER_H
-#include <android/hardware/media/c2/1.0/IComponentListener.h>
+#include <aidl/android/hardware/media/c2/IComponentListener.h>
#include <utils/Timers.h>
#include <C2Buffer.h>
@@ -27,15 +27,13 @@
#include <map>
#include <thread>
+namespace aidl {
namespace android {
namespace hardware {
namespace media {
namespace c2 {
-namespace V1_0 {
namespace utils {
-using namespace ::android;
-
/**
* InputBufferManager
* ==================
@@ -118,7 +116,7 @@
* \param input Input frame data whose input buffers are to be tracked.
*/
static void registerFrameData(
- const sp<IComponentListener>& listener,
+ const std::shared_ptr<IComponentListener>& listener,
const C2FrameData& input);
/**
@@ -134,7 +132,7 @@
* \param input Previously registered frame data.
*/
static void unregisterFrameData(
- const wp<IComponentListener>& listener,
+ const std::weak_ptr<IComponentListener>& listener,
const C2FrameData& input);
/**
@@ -150,7 +148,7 @@
* \param listener Previously registered listener.
*/
static void unregisterFrameData(
- const wp<IComponentListener>& listener);
+ const std::weak_ptr<IComponentListener>& listener);
/**
* Set the notification interval.
@@ -161,13 +159,13 @@
private:
void _registerFrameData(
- const sp<IComponentListener>& listener,
+ const std::shared_ptr<IComponentListener>& listener,
const C2FrameData& input);
void _unregisterFrameData(
- const wp<IComponentListener>& listener,
+ const std::weak_ptr<IComponentListener>& listener,
const C2FrameData& input);
void _unregisterFrameData(
- const wp<IComponentListener>& listener);
+ const std::weak_ptr<IComponentListener>& listener);
void _setNotificationInterval(nsecs_t notificationIntervalNs);
// The callback function tied to C2Buffer objects.
@@ -184,11 +182,11 @@
// Note that the "key" is bufferIndex according to operator<(). This is
// designed to work with TrackedBuffersMap defined below.
struct TrackedBuffer {
- wp<IComponentListener> listener;
+ std::weak_ptr<IComponentListener> listener;
uint64_t frameIndex;
size_t bufferIndex;
std::weak_ptr<C2Buffer> buffer;
- TrackedBuffer(const wp<IComponentListener>& listener,
+ TrackedBuffer(const std::weak_ptr<IComponentListener>& listener,
uint64_t frameIndex,
size_t bufferIndex,
const std::shared_ptr<C2Buffer>& buffer)
@@ -204,9 +202,10 @@
// However, the value of the innermost map is TrackedBuffer, which also
// contains an extra copy of listener and frameIndex. This is needed
// because onBufferDestroyed() needs to know listener and frameIndex too.
- typedef std::map<wp<IComponentListener>,
+ typedef std::map<std::weak_ptr<IComponentListener>,
std::map<uint64_t,
- std::set<TrackedBuffer*>>> TrackedBuffersMap;
+ std::set<TrackedBuffer*>>,
+ std::owner_less<std::weak_ptr<IComponentListener>>> TrackedBuffersMap;
// Storage for pending (unsent) death notifications for one listener.
// Each pair in member named "indices" are (frameIndex, bufferIndex) from
@@ -261,7 +260,9 @@
// A DeathNotifications object is associated to each listener. An entry in
// this map will be removed if its associated DeathNotifications has count =
// 0 and lastSentNs < systemTime() - mNotificationIntervalNs.
- std::map<wp<IComponentListener>, DeathNotifications> mDeathNotifications;
+ std::map<std::weak_ptr<IComponentListener>,
+ DeathNotifications,
+ std::owner_less<std::weak_ptr<IComponentListener>>> mDeathNotifications;
// Condition variable signaled when an entry is added to mDeathNotifications.
std::condition_variable mOnBufferDestroyed;
@@ -290,11 +291,11 @@
};
} // namespace utils
-} // namespace V1_0
} // namespace c2
} // namespace media
} // namespace hardware
} // namespace android
+} // namespace aidl
-#endif // CODEC2_HIDL_V1_0_UTILS_INPUT_BUFFER_MANAGER_H
+#endif // CODEC2_AIDL_UTILS_INPUT_BUFFER_MANAGER_H
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/InputSurface.h b/media/codec2/hal/aidl/include/codec2/aidl/InputSurface.h
deleted file mode 100644
index 062dcd9..0000000
--- a/media/codec2/hal/aidl/include/codec2/aidl/InputSurface.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright 2018 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.
- */
-
-#ifndef CODEC2_HIDL_V1_0_UTILS_INPUTSURFACE_H
-#define CODEC2_HIDL_V1_0_UTILS_INPUTSURFACE_H
-
-#include <codec2/hidl/1.0/ComponentStore.h>
-
-#include <android/hardware/graphics/bufferqueue/2.0/IGraphicBufferProducer.h>
-#include <android/hardware/media/c2/1.0/IInputSink.h>
-#include <android/hardware/media/c2/1.0/IInputSurface.h>
-#include <hidl/Status.h>
-#include <media/stagefright/bqhelper/GraphicBufferSource.h>
-
-#include <util/C2InterfaceHelper.h>
-
-namespace android {
-namespace hardware {
-namespace media {
-namespace c2 {
-namespace V1_0 {
-namespace utils {
-
-using ::android::hardware::hidl_handle;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::sp;
-
-struct InputSurface : public IInputSurface {
-
- typedef ::android::hardware::graphics::bufferqueue::V2_0::
- IGraphicBufferProducer HGraphicBufferProducer;
-
- typedef ::android::
- GraphicBufferSource GraphicBufferSource;
-
- virtual Return<sp<HGraphicBufferProducer>> getGraphicBufferProducer() override;
-
- virtual Return<sp<IConfigurable>> getConfigurable() override;
-
- virtual Return<void> connect(
- const sp<IInputSink>& sink,
- connect_cb _hidl_cb) override;
-
- InputSurface(
- const std::shared_ptr<ParameterCache>& cache,
- const std::shared_ptr<C2ReflectorHelper>& reflector,
- const sp<HGraphicBufferProducer>& base,
- const sp<GraphicBufferSource>& source);
-
-protected:
-
- class Interface;
- class ConfigurableIntf;
-
- std::shared_ptr<ParameterCache> mParameterCache;
- sp<HGraphicBufferProducer> mProducer;
- sp<GraphicBufferSource> mSource;
- std::shared_ptr<Interface> mIntf;
- sp<CachedConfigurable> mConfigurable;
-
- virtual ~InputSurface() override = default;
-};
-
-} // namespace utils
-} // namespace V1_0
-} // namespace c2
-} // namespace media
-} // namespace hardware
-} // namespace android
-
-#endif // CODEC2_HIDL_V1_0_UTILS_INPUTSURFACE_H
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/InputSurfaceConnection.h b/media/codec2/hal/aidl/include/codec2/aidl/InputSurfaceConnection.h
deleted file mode 100644
index 475ce8b..0000000
--- a/media/codec2/hal/aidl/include/codec2/aidl/InputSurfaceConnection.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright 2018 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.
- */
-
-#ifndef CODEC2_HIDL_V1_0_UTILS_INPUTSURFACECONNECTION_H
-#define CODEC2_HIDL_V1_0_UTILS_INPUTSURFACECONNECTION_H
-
-#include <codec2/hidl/1.0/Component.h>
-#include <codec2/hidl/1.0/Configurable.h>
-
-#include <android/hardware/media/c2/1.0/IComponent.h>
-#include <android/hardware/media/c2/1.0/IConfigurable.h>
-#include <android/hardware/media/c2/1.0/IInputSurfaceConnection.h>
-
-#include <media/stagefright/bqhelper/GraphicBufferSource.h>
-
-#include <hidl/HidlSupport.h>
-#include <hidl/Status.h>
-
-#include <C2Component.h>
-
-#include <memory>
-#include <mutex>
-
-namespace android {
-namespace hardware {
-namespace media {
-namespace c2 {
-namespace V1_0 {
-namespace utils {
-
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::sp;
-using ::android::GraphicBufferSource;
-
-// An InputSurfaceConnection connects an InputSurface to a sink, which may be an
-// IInputSink or a local C2Component. This can be specified by choosing the
-// corresponding constructor. The reason for distinguishing these two cases is
-// that when an InputSurfaceConnection lives in the same process as the
-// component that processes the buffers, data parceling is not needed.
-struct InputSurfaceConnection : public IInputSurfaceConnection {
-
- virtual Return<Status> disconnect() override;
-
- virtual Return<sp<IConfigurable>> getConfigurable() override;
-
-protected:
-
- InputSurfaceConnection(
- const sp<GraphicBufferSource>& source,
- const std::shared_ptr<C2Component>& comp,
- const std::shared_ptr<ParameterCache>& cache);
-
- InputSurfaceConnection(
- const sp<GraphicBufferSource>& source,
- const sp<IInputSink>& sink,
- const std::shared_ptr<ParameterCache>& cache);
-
- bool init();
-
- friend struct InputSurface;
-
- InputSurfaceConnection() = delete;
- InputSurfaceConnection(const InputSurfaceConnection&) = delete;
- void operator=(const InputSurfaceConnection&) = delete;
-
- struct Impl;
-
- std::mutex mImplMutex;
- sp<Impl> mImpl;
- sp<CachedConfigurable> mConfigurable;
-
- virtual ~InputSurfaceConnection() override;
-};
-
-} // namespace utils
-} // namespace V1_0
-} // namespace c2
-} // namespace media
-} // namespace hardware
-} // namespace android
-
-#endif // CODEC2_HIDL_V1_0_UTILS_INPUTSURFACECONNECTION_H
diff --git a/media/codec2/hal/client/Android.bp b/media/codec2/hal/client/Android.bp
index 22aa35e..0b5b940 100644
--- a/media/codec2/hal/client/Android.bp
+++ b/media/codec2/hal/client/Android.bp
@@ -23,6 +23,7 @@
name: "libcodec2_client",
srcs: [
+ "GraphicBufferAllocator.cpp",
"GraphicsTracker.cpp",
"client.cpp",
"output.cpp",
diff --git a/media/codec2/hal/client/GraphicBufferAllocator.cpp b/media/codec2/hal/client/GraphicBufferAllocator.cpp
new file mode 100644
index 0000000..bbef1b5
--- /dev/null
+++ b/media/codec2/hal/client/GraphicBufferAllocator.cpp
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gui/IProducerListener.h>
+#include <media/stagefright/foundation/ADebug.h>
+
+#include <codec2/aidl/GraphicBufferAllocator.h>
+#include <codec2/aidl/GraphicsTracker.h>
+
+namespace aidl::android::hardware::media::c2::implementation {
+
+class OnBufferReleasedListener : public ::android::BnProducerListener {
+private:
+ uint32_t mGeneration;
+ std::weak_ptr<GraphicBufferAllocator> mAllocator;
+public:
+ OnBufferReleasedListener(
+ uint32_t generation,
+ const std::shared_ptr<GraphicBufferAllocator> &allocator)
+ : mGeneration(generation), mAllocator(allocator) {}
+ virtual ~OnBufferReleasedListener() = default;
+ virtual void onBufferReleased() {
+ auto p = mAllocator.lock();
+ if (p) {
+ p->onBufferReleased(mGeneration);
+ }
+ }
+ virtual bool needsReleaseNotify() { return true; }
+};
+
+::ndk::ScopedAStatus GraphicBufferAllocator::allocate(
+ const IGraphicBufferAllocator::Description& in_desc,
+ IGraphicBufferAllocator::Allocation* _aidl_return) {
+ AHardwareBuffer *buf;
+ ::android::sp<::android::Fence> fence;
+ c2_status_t ret = allocate(
+ in_desc.width, in_desc.height, in_desc.format, in_desc.usage,
+ &buf, &fence);
+ if (ret == C2_OK) {
+ _aidl_return->buffer.reset(buf);
+ _aidl_return->fence = ::ndk::ScopedFileDescriptor(fence->dup());
+ return ::ndk::ScopedAStatus::ok();
+ }
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(ret);
+}
+
+::ndk::ScopedAStatus GraphicBufferAllocator::deallocate(int64_t in_id, bool* _aidl_return) {
+ *_aidl_return = deallocate(in_id, ::android::Fence::NO_FENCE);
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus GraphicBufferAllocator::getWaitableFds(
+ IGraphicBufferAllocator::WaitableFds* _aidl_return) {
+ int allocFd;
+ int statusFd;
+ c2_status_t ret = mGraphicsTracker->getWaitableFds(&allocFd, &statusFd);
+ if (ret == C2_OK) {
+ _aidl_return->allocEvent.set(allocFd);
+ _aidl_return->statusEvent.set(statusFd);
+ return ::ndk::ScopedAStatus::ok();
+ }
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(ret);
+}
+
+bool GraphicBufferAllocator::configure(
+ const ::android::sp<IGraphicBufferProducer>& igbp,
+ uint32_t generation,
+ int maxDequeueBufferCount) {
+ c2_status_t ret = C2_OK;
+
+ ret = mGraphicsTracker->configureGraphics(igbp, generation);
+ if (ret != C2_OK) {
+ ALOGE("configuring igbp failed gen #(%d), configuring max dequeue count didn't happen",
+ (unsigned int)generation);
+ return false;
+ }
+
+ ret = mGraphicsTracker->configureMaxDequeueCount(maxDequeueBufferCount);
+ if (ret != C2_OK) {
+ ALOGE("configuring max dequeue count to %d failed", maxDequeueBufferCount);
+ return false;
+ }
+ return true;
+}
+
+void GraphicBufferAllocator::updateMaxDequeueBufferCount(int count) {
+ c2_status_t ret = mGraphicsTracker->configureMaxDequeueCount(count);
+ if (ret != C2_OK) {
+ ALOGE("updating max dequeue buffer count failed %d", ret);
+ }
+}
+
+void GraphicBufferAllocator::reset() {
+ mGraphicsTracker->stop();
+}
+
+const ::android::sp<::android::IProducerListener> GraphicBufferAllocator::createReleaseListener(
+ uint32_t generation) {
+ return new OnBufferReleasedListener(generation, ref<GraphicBufferAllocator>());
+}
+
+void GraphicBufferAllocator::onBufferReleased(uint32_t generation) {
+ mGraphicsTracker->onReleased(generation);
+}
+
+c2_status_t GraphicBufferAllocator::allocate(
+ uint32_t width, uint32_t height, ::android::PixelFormat format, uint64_t usage,
+ AHardwareBuffer **buf, ::android::sp<::android::Fence> *fence) {
+ return mGraphicsTracker->allocate(width, height, format, usage, buf, fence);
+}
+
+bool GraphicBufferAllocator::deallocate(const uint64_t id,
+ const ::android::sp<::android::Fence> &fence) {
+ c2_status_t ret = mGraphicsTracker->deallocate(id, fence);
+ if (ret != C2_OK) {
+ ALOGW("deallocate() %llu was not successful %d", (unsigned long long)id, ret);
+ return false;
+ }
+ return true;
+}
+
+c2_status_t GraphicBufferAllocator::displayBuffer(
+ const C2ConstGraphicBlock& block,
+ const IGraphicBufferProducer::QueueBufferInput& input,
+ IGraphicBufferProducer::QueueBufferOutput *output) {
+ return mGraphicsTracker->render(block, input, output);
+}
+
+GraphicBufferAllocator::~GraphicBufferAllocator() {}
+
+std::shared_ptr<GraphicBufferAllocator> GraphicBufferAllocator::CreateGraphicBufferAllocator(
+ int maxDequeueCount) {
+ return ::ndk::SharedRefBase::make<GraphicBufferAllocator>(maxDequeueCount);
+}
+
+GraphicBufferAllocator::GraphicBufferAllocator(int maxDequeueCount)
+ : mGraphicsTracker(GraphicsTracker::CreateGraphicsTracker(maxDequeueCount)) {}
+
+} // namespace aidl::android::hardware::media::c2::implementation
diff --git a/media/codec2/hal/client/client.cpp b/media/codec2/hal/client/client.cpp
index b680931..e7dd7c2 100644
--- a/media/codec2/hal/client/client.cpp
+++ b/media/codec2/hal/client/client.cpp
@@ -1954,7 +1954,8 @@
std::shared_ptr<Codec2Client::Configurable>* configurable) {
if (mAidlBase) {
c2_aidl::IComponent::BlockPool aidlBlockPool;
- ::ndk::ScopedAStatus transStatus = mAidlBase->createBlockPool(id, &aidlBlockPool);
+ ::ndk::ScopedAStatus transStatus = mAidlBase->createBlockPool(static_cast<int32_t>(id),
+ &aidlBlockPool);
c2_status_t status = GetC2Status(transStatus, "createBlockPool");
if (status != C2_OK) {
return status;
diff --git a/media/codec2/hal/client/include/codec2/aidl/GraphicBufferAllocator.h b/media/codec2/hal/client/include/codec2/aidl/GraphicBufferAllocator.h
new file mode 100644
index 0000000..f9c8aca
--- /dev/null
+++ b/media/codec2/hal/client/include/codec2/aidl/GraphicBufferAllocator.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/media/c2/BnGraphicBufferAllocator.h>
+
+#include <android-base/unique_fd.h>
+#include <gui/IGraphicBufferProducer.h>
+
+#include <memory>
+
+#include <C2Buffer.h>
+
+namespace aidl::android::hardware::media::c2::implementation {
+
+// forward declarations
+class GraphicsTracker;
+
+struct GraphicBufferAllocator : public BnGraphicBufferAllocator {
+public:
+ // HAL interfaces
+ ::ndk::ScopedAStatus allocate(const IGraphicBufferAllocator::Description& in_desc,
+ IGraphicBufferAllocator::Allocation* _aidl_return) override;
+
+ ::ndk::ScopedAStatus deallocate(int64_t in_id, bool* _aidl_return) override;
+
+ ::ndk::ScopedAStatus getWaitableFds(
+ IGraphicBufferAllocator::WaitableFds* _aidl_return) override;
+
+ /**
+ * Configuring Surface/BufferQueue for the interface.
+ *
+ * Configure Surface, generation # and max dequeueBuffer() count for
+ * allocate interface.
+ *
+ * @param igbp Surface where to allocate.
+ * @param generation Generation # for allocations.
+ * @param maxDequeueBufferCount
+ * Maximum # of pending allocations.
+ */
+ bool configure(const ::android::sp<::android::IGraphicBufferProducer>& igbp,
+ uint32_t generation,
+ int maxDequeueBufferCount);
+
+ /**
+ * Update max dequeue buffer count of BufferQueue.
+ *
+ * BufferQueue does not update this value if count is smaller
+ * than the currently dequeued count.
+ * TODO: better to update the value inside this interface.
+ * for return value inspection from BQ, also for delayed updates.
+ *
+ * @param count the new value to update
+ */
+ void updateMaxDequeueBufferCount(int count);
+
+ void reset();
+
+ /**
+ * Create a listener for buffer being released.
+ *
+ * Surface will register this listener and notify whenever the consumer
+ * releases a buffer.
+ *
+ * @param generation generation # for the BufferQueue.
+ * @return IProducerListener can be used when connect# to Surface.
+ */
+ const ::android::sp<::android::IProducerListener> createReleaseListener(
+ uint32_t generation);
+
+ /**
+ * Notifies a buffer being released.
+ *
+ * @param generation generation # for the BufferQueue.
+ */
+ void onBufferReleased(uint32_t generation);
+
+ /**
+ * Allocates a buffer.
+ *
+ * @param width width of the requested buffer.
+ * @param height height of the requested buffer.
+ * @param format format of the requested buffer.
+ * @param usage usage of the requested buffer.
+ * @param buf out param for created buffer.
+ * @param fence out param for a pending fence.
+ *
+ * @return OK When an allocation was created.
+ * C2_BAD_STATE Client is not in the state for allocating
+ * C2_BLOCKING operation is blocked. Waitable fds can be
+ * used to know when it unblocks.
+ * C2_CORRUPTED Failed with a serious reason.
+ */
+ c2_status_t allocate(uint32_t width, uint32_t height,
+ ::android::PixelFormat format, uint64_t usage,
+ AHardwareBuffer **buf, ::android::sp<::android::Fence> *fence);
+
+ /**
+ * De-allocate a buffer.
+ *
+ * @param id unique id for a buffer.
+ * @param fence write fence if it's deallocated due to
+ * cancellation of displaying
+ */
+ bool deallocate(const uint64_t id, const ::android::sp<::android::Fence> &fence);
+
+ /**
+ * Display a graphic buffer to BufferQueue.
+ *
+ * @param block block to display to Surface.
+ * @param input input parameter for displaying.
+ * @param output out parameter from Surface.
+ */
+ c2_status_t displayBuffer(
+ const C2ConstGraphicBlock& block,
+ const ::android::IGraphicBufferProducer::QueueBufferInput& input,
+ ::android::IGraphicBufferProducer::QueueBufferOutput *output);
+
+ ~GraphicBufferAllocator();
+
+ /**
+ * Create the interface.
+ *
+ * The interface and codec instance's relationship is 1 to 1.
+ * The interface will be cretaed in the beginning of Codec createion. And
+ * lives until the instance destroyed.
+ *
+ * @param maxDequeueCount Initial max allocatable count
+ */
+ static std::shared_ptr<GraphicBufferAllocator> CreateGraphicBufferAllocator(
+ int maxDequeueCount);
+private:
+ GraphicBufferAllocator(int maxDequeueCount);
+
+ std::shared_ptr<GraphicsTracker> mGraphicsTracker;
+
+ friend class ::ndk::SharedRefBase;
+};
+
+} // namespace aidl::android::hardware::media::c2::implementation
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/Android.bp b/media/codec2/hal/hidl/1.0/vts/functional/Android.bp
index 0ae133c..1c5c7d6 100644
--- a/media/codec2/hal/hidl/1.0/vts/functional/Android.bp
+++ b/media/codec2/hal/hidl/1.0/vts/functional/Android.bp
@@ -29,10 +29,8 @@
srcs: [
"res/bbb_aac_stereo_128kbps_48000hz.aac",
"res/bbb_aac_stereo_128kbps_48000hz.info",
- "res/bbb_aac_stereo_128kbps_48000hz_multi_frame.info",
"res/bbb_amrwb_1ch_14kbps_16000hz.amrwb",
"res/bbb_amrwb_1ch_14kbps_16000hz.info",
- "res/bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info",
"res/bbb_flac_stereo_680kbps_48000hz.flac",
"res/bbb_flac_stereo_680kbps_48000hz.info",
"res/bbb_g711alaw_1ch_8khz.info",
@@ -43,7 +41,6 @@
"res/bbb_gsm_1ch_8khz_13kbps.raw",
"res/bbb_mp3_stereo_192kbps_48000hz.info",
"res/bbb_mp3_stereo_192kbps_48000hz.mp3",
- "res/bbb_mp3_stereo_192kbps_48000hz_multi_frame.info",
"res/bbb_opus_stereo_128kbps_48000hz.info",
"res/bbb_opus_stereo_128kbps_48000hz.opus",
"res/bbb_raw_1ch_8khz_s32le.info",
@@ -52,7 +49,6 @@
"res/bbb_vorbis_stereo_128kbps_48000hz.vorbis",
"res/sine_amrnb_1ch_12kbps_8000hz.amrnb",
"res/sine_amrnb_1ch_12kbps_8000hz.info",
- "res/sine_amrnb_1ch_12kbps_8000hz_multi_frame.info",
],
}
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp b/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
index 8b0ea91..222c3d2 100644
--- a/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
+++ b/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
@@ -44,17 +44,9 @@
std::vector<CompToFiles> gCompToFiles = {
{"mp4a-latm", "bbb_aac_stereo_128kbps_48000hz.aac", "bbb_aac_stereo_128kbps_48000hz.info"},
- {"mp4a-latm", "bbb_aac_stereo_128kbps_48000hz.aac",
- "bbb_aac_stereo_128kbps_48000hz_multi_frame.info"},
{"mpeg", "bbb_mp3_stereo_192kbps_48000hz.mp3", "bbb_mp3_stereo_192kbps_48000hz.info"},
- {"mpeg", "bbb_mp3_stereo_192kbps_48000hz.mp3",
- "bbb_mp3_stereo_192kbps_48000hz_multi_frame.info"},
{"3gpp", "sine_amrnb_1ch_12kbps_8000hz.amrnb", "sine_amrnb_1ch_12kbps_8000hz.info"},
- {"3gpp", "sine_amrnb_1ch_12kbps_8000hz.amrnb",
- "sine_amrnb_1ch_12kbps_8000hz_multi_frame.info"},
{"amr-wb", "bbb_amrwb_1ch_14kbps_16000hz.amrwb", "bbb_amrwb_1ch_14kbps_16000hz.info"},
- {"amr-wb", "bbb_amrwb_1ch_14kbps_16000hz.amrwb",
- "bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info"},
{"vorbis", "bbb_vorbis_stereo_128kbps_48000hz.vorbis",
"bbb_vorbis_stereo_128kbps_48000hz.info"},
{"opus", "bbb_opus_stereo_128kbps_48000hz.opus", "bbb_opus_stereo_128kbps_48000hz.info"},
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.xml b/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.xml
index a22f8cf..6c04683 100644
--- a/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.xml
+++ b/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.xml
@@ -23,10 +23,8 @@
<!-- Files used for audio testing -->
<option name="push-file" key="bbb_aac_stereo_128kbps_48000hz.aac" value="/data/local/tmp/media/bbb_aac_stereo_128kbps_48000hz.aac" />
<option name="push-file" key="bbb_aac_stereo_128kbps_48000hz.info" value="/data/local/tmp/media/bbb_aac_stereo_128kbps_48000hz.info" />
- <option name="push-file" key="bbb_aac_stereo_128kbps_48000hz_multi_frame.info" value="/data/local/tmp/media/bbb_aac_stereo_128kbps_48000hz_multi_frame.info" />
<option name="push-file" key="bbb_amrwb_1ch_14kbps_16000hz.amrwb" value="/data/local/tmp/media/bbb_amrwb_1ch_14kbps_16000hz.amrwb" />
<option name="push-file" key="bbb_amrwb_1ch_14kbps_16000hz.info" value="/data/local/tmp/media/bbb_amrwb_1ch_14kbps_16000hz.info" />
- <option name="push-file" key="bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info" value="/data/local/tmp/media/bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info" />
<option name="push-file" key="bbb_flac_stereo_680kbps_48000hz.flac" value="/data/local/tmp/media/bbb_flac_stereo_680kbps_48000hz.flac" />
<option name="push-file" key="bbb_flac_stereo_680kbps_48000hz.info" value="/data/local/tmp/media/bbb_flac_stereo_680kbps_48000hz.info" />
<option name="push-file" key="bbb_g711alaw_1ch_8khz.info" value="/data/local/tmp/media/bbb_g711alaw_1ch_8khz.info" />
@@ -37,7 +35,6 @@
<option name="push-file" key="bbb_gsm_1ch_8khz_13kbps.raw" value="/data/local/tmp/media/bbb_gsm_1ch_8khz_13kbps.raw" />
<option name="push-file" key="bbb_mp3_stereo_192kbps_48000hz.info" value="/data/local/tmp/media/bbb_mp3_stereo_192kbps_48000hz.info" />
<option name="push-file" key="bbb_mp3_stereo_192kbps_48000hz.mp3" value="/data/local/tmp/media/bbb_mp3_stereo_192kbps_48000hz.mp3" />
- <option name="push-file" key="bbb_mp3_stereo_192kbps_48000hz_multi_frame.info" value="/data/local/tmp/media/bbb_mp3_stereo_192kbps_48000hz_multi_frame.info" />
<option name="push-file" key="bbb_opus_stereo_128kbps_48000hz.info" value="/data/local/tmp/media/bbb_opus_stereo_128kbps_48000hz.info" />
<option name="push-file" key="bbb_opus_stereo_128kbps_48000hz.opus" value="/data/local/tmp/media/bbb_opus_stereo_128kbps_48000hz.opus" />
<option name="push-file" key="bbb_raw_1ch_8khz_s32le.info" value="/data/local/tmp/media/bbb_raw_1ch_8khz_s32le.info" />
@@ -46,7 +43,6 @@
<option name="push-file" key="bbb_vorbis_stereo_128kbps_48000hz.vorbis" value="/data/local/tmp/media/bbb_vorbis_stereo_128kbps_48000hz.vorbis" />
<option name="push-file" key="sine_amrnb_1ch_12kbps_8000hz.amrnb" value="/data/local/tmp/media/sine_amrnb_1ch_12kbps_8000hz.amrnb" />
<option name="push-file" key="sine_amrnb_1ch_12kbps_8000hz.info" value="/data/local/tmp/media/sine_amrnb_1ch_12kbps_8000hz.info" />
- <option name="push-file" key="sine_amrnb_1ch_12kbps_8000hz_multi_frame.info" value="/data/local/tmp/media/sine_amrnb_1ch_12kbps_8000hz_multi_frame.info" />
</target_preparer>
@@ -55,4 +51,4 @@
<option name="module-name" value="vts_media_c2_v1_0_audio_dec_test" />
<option name="native-test-flag" value="-P /data/local/tmp/media/" />
</test>
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/res/bbb_aac_stereo_128kbps_48000hz_multi_frame.info b/media/codec2/hal/hidl/1.0/vts/functional/res/bbb_aac_stereo_128kbps_48000hz_multi_frame.info
deleted file mode 100644
index 182af20..0000000
--- a/media/codec2/hal/hidl/1.0/vts/functional/res/bbb_aac_stereo_128kbps_48000hz_multi_frame.info
+++ /dev/null
@@ -1,443 +0,0 @@
-5 32 0
-5 32 0
-337 1 0
-322 1 21333
-279 1 42666
-563 1 64000
-635 1 106666
-634 1 149333
-629 1 192000
-680 1 234666
-688 1 277333
-1036 1 320000
-1040 1 384000
-1009 1 448000
-1020 1 512000
-1357 1 576000
-1353 1 661333
-1351 1 746666
-1351 1 832000
-343 1 917333
-335 1 938666
-339 1 960000
-342 1 981333
-348 1 1002666
-350 1 1024000
-351 1 1045333
-342 1 1066666
-366 1 1088000
-340 1 1109333
-354 1 1130666
-340 1 1152000
-334 1 1173333
-338 1 1194666
-340 1 1216000
-351 1 1237333
-346 1 1258666
-331 1 1280000
-321 1 1301333
-343 1 1322666
-342 1 1344000
-345 1 1365333
-326 1 1386666
-342 1 1408000
-356 1 1429333
-351 1 1450666
-343 1 1472000
-347 1 1493333
-349 1 1514666
-350 1 1536000
-330 1 1557333
-341 1 1578666
-340 1 1600000
-330 1 1621333
-340 1 1642666
-335 1 1664000
-344 1 1685333
-359 1 1706666
-337 1 1728000
-346 1 1749333
-330 1 1770666
-351 1 1792000
-355 1 1813333
-352 1 1834666
-325 1 1856000
-342 1 1877333
-327 1 1898666
-349 1 1920000
-326 1 1941333
-337 1 1962666
-378 1 1984000
-321 1 2005333
-319 1 2026666
-346 1 2048000
-352 1 2069333
-349 1 2090666
-331 1 2112000
-330 1 2133333
-329 1 2154666
-333 1 2176000
-367 1 2197333
-362 1 2218666
-337 1 2240000
-337 1 2261333
-360 1 2282666
-333 1 2304000
-317 1 2325333
-344 1 2346666
-335 1 2368000
-337 1 2389333
-349 1 2410666
-336 1 2432000
-348 1 2453333
-349 1 2474666
-342 1 2496000
-359 1 2517333
-340 1 2538666
-340 1 2560000
-348 1 2581333
-334 1 2602666
-328 1 2624000
-341 1 2645333
-339 1 2666666
-337 1 2688000
-350 1 2709333
-326 1 2730666
-360 1 2752000
-344 1 2773333
-340 1 2794666
-343 1 2816000
-361 1 2837333
-329 1 2858666
-345 1 2880000
-345 1 2901333
-330 1 2922666
-342 1 2944000
-344 1 2965333
-330 1 2986666
-329 1 3008000
-335 1 3029333
-366 1 3050666
-328 1 3072000
-349 1 3093333
-339 1 3114666
-340 1 3136000
-335 1 3157333
-327 1 3178666
-348 1 3200000
-339 1 3221333
-334 1 3242666
-350 1 3264000
-325 1 3285333
-361 1 3306666
-338 1 3328000
-350 1 3349333
-353 1 3370666
-327 1 3392000
-346 1 3413333
-348 1 3434666
-339 1 3456000
-342 1 3477333
-334 1 3498666
-350 1 3520000
-354 1 3541333
-363 1 3562666
-322 1 3584000
-337 1 3605333
-355 1 3626666
-329 1 3648000
-324 1 3669333
-338 1 3690666
-356 1 3712000
-330 1 3733333
-321 1 3754666
-337 1 3776000
-345 1 3797333
-335 1 3818666
-348 1 3840000
-342 1 3861333
-348 1 3882666
-335 1 3904000
-344 1 3925333
-357 1 3946666
-368 1 3968000
-324 1 3989333
-343 1 4010666
-341 1 4032000
-329 1 4053333
-356 1 4074666
-317 1 4096000
-351 1 4117333
-340 1 4138666
-340 1 4160000
-332 1 4181333
-355 1 4202666
-357 1 4224000
-327 1 4245333
-338 1 4266666
-323 1 4288000
-346 1 4309333
-352 1 4330666
-347 1 4352000
-343 1 4373333
-311 1 4394666
-338 1 4416000
-365 1 4437333
-349 1 4458666
-327 1 4480000
-355 1 4501333
-319 1 4522666
-349 1 4544000
-351 1 4565333
-337 1 4586666
-340 1 4608000
-349 1 4629333
-316 1 4650666
-344 1 4672000
-334 1 4693333
-344 1 4714666
-347 1 4736000
-348 1 4757333
-334 1 4778666
-338 1 4800000
-331 1 4821333
-344 1 4842666
-342 1 4864000
-336 1 4885333
-326 1 4906666
-364 1 4928000
-350 1 4949333
-350 1 4970666
-363 1 4992000
-358 1 5013333
-305 1 5034666
-344 1 5056000
-346 1 5077333
-342 1 5098666
-330 1 5120000
-318 1 5141333
-361 1 5162666
-354 1 5184000
-313 1 5205333
-330 1 5226666
-350 1 5248000
-347 1 5269333
-346 1 5290666
-357 1 5312000
-325 1 5333333
-335 1 5354666
-331 1 5376000
-366 1 5397333
-329 1 5418666
-349 1 5440000
-371 1 5461333
-326 1 5482666
-333 1 5504000
-319 1 5525333
-327 1 5546666
-353 1 5568000
-356 1 5589333
-348 1 5610666
-338 1 5632000
-331 1 5653333
-341 1 5674666
-362 1 5696000
-326 1 5717333
-359 1 5738666
-315 1 5760000
-376 1 5781333
-343 1 5802666
-354 1 5824000
-353 1 5845333
-344 1 5866666
-334 1 5888000
-345 1 5909333
-355 1 5930666
-322 1 5952000
-334 1 5973333
-353 1 5994666
-338 1 6016000
-351 1 6037333
-334 1 6058666
-339 1 6080000
-345 1 6101333
-347 1 6122666
-355 1 6144000
-312 1 6165333
-352 1 6186666
-354 1 6208000
-318 1 6229333
-344 1 6250666
-363 1 6272000
-321 1 6293333
-339 1 6314666
-356 1 6336000
-334 1 6357333
-354 1 6378666
-325 1 6400000
-321 1 6421333
-341 1 6442666
-337 1 6464000
-351 1 6485333
-343 1 6506666
-341 1 6528000
-344 1 6549333
-341 1 6570666
-364 1 6592000
-319 1 6613333
-348 1 6634666
-332 1 6656000
-333 1 6677333
-343 1 6698666
-348 1 6720000
-347 1 6741333
-350 1 6762666
-342 1 6784000
-341 1 6805333
-326 1 6826666
-351 1 6848000
-329 1 6869333
-323 1 6890666
-350 1 6912000
-361 1 6933333
-326 1 6954666
-345 1 6976000
-345 1 6997333
-311 1 7018666
-349 1 7040000
-358 1 7061333
-352 1 7082666
-347 1 7104000
-364 1 7125333
-328 1 7146666
-318 1 7168000
-351 1 7189333
-340 1 7210666
-341 1 7232000
-355 1 7253333
-336 1 7274666
-352 1 7296000
-341 1 7317333
-334 1 7338666
-348 1 7360000
-342 1 7381333
-335 1 7402666
-342 1 7424000
-359 1 7445333
-349 1 7466666
-329 1 7488000
-356 1 7509333
-292 1 7530666
-316 1 7552000
-318 1 7573333
-320 1 7594666
-342 1 7616000
-285 1 7637333
-326 1 7658666
-352 1 7680000
-392 1 7701333
-364 1 7722666
-384 1 7744000
-334 1 7765333
-317 1 7786666
-326 1 7808000
-373 1 7829333
-354 1 7850666
-329 1 7872000
-347 1 7893333
-353 1 7914666
-338 1 7936000
-317 1 7957333
-354 1 7978666
-345 1 8000000
-350 1 8021333
-351 1 8042666
-332 1 8064000
-358 1 8085333
-315 1 8106666
-336 1 8128000
-358 1 8149333
-343 1 8170666
-319 1 8192000
-370 1 8213333
-344 1 8234666
-361 1 8256000
-343 1 8277333
-337 1 8298666
-354 1 8320000
-332 1 8341333
-348 1 8362666
-328 1 8384000
-345 1 8405333
-340 1 8426666
-346 1 8448000
-341 1 8469333
-344 1 8490666
-342 1 8512000
-341 1 8533333
-345 1 8554666
-337 1 8576000
-335 1 8597333
-335 1 8618666
-340 1 8640000
-345 1 8661333
-341 1 8682666
-342 1 8704000
-338 1 8725333
-343 1 8746666
-336 1 8768000
-338 1 8789333
-353 1 8810666
-339 1 8832000
-329 1 8853333
-349 1 8874666
-323 1 8896000
-351 1 8917333
-359 1 8938666
-357 1 8960000
-341 1 8981333
-333 1 9002666
-335 1 9024000
-328 1 9045333
-347 1 9066666
-343 1 9088000
-369 1 9109333
-331 1 9130666
-344 1 9152000
-330 1 9173333
-346 1 9194666
-337 1 9216000
-341 1 9237333
-338 1 9258666
-329 1 9280000
-360 1 9301333
-336 1 9322666
-341 1 9344000
-341 1 9365333
-345 1 9386666
-351 1 9408000
-349 1 9429333
-336 1 9450666
-326 1 9472000
-349 1 9493333
-343 1 9514666
-357 1 9536000
-342 1 9557333
-325 1 9578666
-346 1 9600000
-326 1 9621333
-402 1 9642666
-331 1 9664000
-339 1 9685333
-371 1 9706666
-314 1 9728000
-310 1 9749333
-364 1 9770666
-338 1 9792000
-339 1 9813333
-337 1 9834666
-355 1 9856000
-351 1 9877333
-332 1 9898666
-316 1 9920000
-474 1 9941333
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/res/bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info b/media/codec2/hal/hidl/1.0/vts/functional/res/bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info
deleted file mode 100644
index c420009..0000000
--- a/media/codec2/hal/hidl/1.0/vts/functional/res/bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info
+++ /dev/null
@@ -1,460 +0,0 @@
-41 1 0
-41 1 20000
-82 1 40000
-82 1 80000
-82 1 120000
-82 1 160000
-82 1 200000
-82 1 240000
-82 1 280000
-82 1 320000
-82 1 360000
-123 1 400000
-123 1 460000
-123 1 520000
-123 1 580000
-123 1 640000
-164 1 700000
-164 1 780000
-164 1 860000
-164 1 940000
-164 1 1020000
-41 1 1100000
-41 1 1120000
-41 1 1140000
-41 1 1160000
-41 1 1180000
-41 1 1200000
-41 1 1220000
-41 1 1240000
-41 1 1260000
-41 1 1280000
-41 1 1300000
-41 1 1320000
-41 1 1340000
-41 1 1360000
-41 1 1380000
-41 1 1400000
-41 1 1420000
-41 1 1440000
-41 1 1460000
-41 1 1480000
-41 1 1500000
-41 1 1520000
-41 1 1540000
-41 1 1560000
-41 1 1580000
-41 1 1600000
-41 1 1620000
-41 1 1640000
-41 1 1660000
-41 1 1680000
-41 1 1700000
-41 1 1720000
-41 1 1740000
-41 1 1760000
-41 1 1780000
-41 1 1800000
-41 1 1820000
-41 1 1840000
-41 1 1860000
-41 1 1880000
-41 1 1900000
-41 1 1920000
-41 1 1940000
-41 1 1960000
-41 1 1980000
-41 1 2000000
-41 1 2020000
-41 1 2040000
-41 1 2060000
-41 1 2080000
-41 1 2100000
-41 1 2120000
-41 1 2140000
-41 1 2160000
-41 1 2180000
-41 1 2200000
-41 1 2220000
-41 1 2240000
-41 1 2260000
-41 1 2280000
-41 1 2300000
-41 1 2320000
-41 1 2340000
-41 1 2360000
-41 1 2380000
-41 1 2400000
-41 1 2420000
-41 1 2440000
-41 1 2460000
-41 1 2480000
-41 1 2500000
-41 1 2520000
-41 1 2540000
-41 1 2560000
-41 1 2580000
-41 1 2600000
-41 1 2620000
-41 1 2640000
-41 1 2660000
-41 1 2680000
-41 1 2700000
-41 1 2720000
-41 1 2740000
-41 1 2760000
-41 1 2780000
-41 1 2800000
-41 1 2820000
-41 1 2840000
-41 1 2860000
-41 1 2880000
-41 1 2900000
-41 1 2920000
-41 1 2940000
-41 1 2960000
-41 1 2980000
-41 1 3000000
-41 1 3020000
-41 1 3040000
-41 1 3060000
-41 1 3080000
-41 1 3100000
-41 1 3120000
-41 1 3140000
-41 1 3160000
-41 1 3180000
-41 1 3200000
-41 1 3220000
-41 1 3240000
-41 1 3260000
-41 1 3280000
-41 1 3300000
-41 1 3320000
-41 1 3340000
-41 1 3360000
-41 1 3380000
-41 1 3400000
-41 1 3420000
-41 1 3440000
-41 1 3460000
-41 1 3480000
-41 1 3500000
-41 1 3520000
-41 1 3540000
-41 1 3560000
-41 1 3580000
-41 1 3600000
-41 1 3620000
-41 1 3640000
-41 1 3660000
-41 1 3680000
-41 1 3700000
-41 1 3720000
-41 1 3740000
-41 1 3760000
-41 1 3780000
-41 1 3800000
-41 1 3820000
-41 1 3840000
-41 1 3860000
-41 1 3880000
-41 1 3900000
-41 1 3920000
-41 1 3940000
-41 1 3960000
-41 1 3980000
-41 1 4000000
-41 1 4020000
-41 1 4040000
-41 1 4060000
-41 1 4080000
-41 1 4100000
-41 1 4120000
-41 1 4140000
-41 1 4160000
-41 1 4180000
-41 1 4200000
-41 1 4220000
-41 1 4240000
-41 1 4260000
-41 1 4280000
-41 1 4300000
-41 1 4320000
-41 1 4340000
-41 1 4360000
-41 1 4380000
-41 1 4400000
-41 1 4420000
-41 1 4440000
-41 1 4460000
-41 1 4480000
-41 1 4500000
-41 1 4520000
-41 1 4540000
-41 1 4560000
-41 1 4580000
-41 1 4600000
-41 1 4620000
-41 1 4640000
-41 1 4660000
-41 1 4680000
-41 1 4700000
-41 1 4720000
-41 1 4740000
-41 1 4760000
-41 1 4780000
-41 1 4800000
-41 1 4820000
-41 1 4840000
-41 1 4860000
-41 1 4880000
-41 1 4900000
-41 1 4920000
-41 1 4940000
-41 1 4960000
-41 1 4980000
-41 1 5000000
-41 1 5020000
-41 1 5040000
-41 1 5060000
-41 1 5080000
-41 1 5100000
-41 1 5120000
-41 1 5140000
-41 1 5160000
-41 1 5180000
-41 1 5200000
-41 1 5220000
-41 1 5240000
-41 1 5260000
-41 1 5280000
-41 1 5300000
-41 1 5320000
-41 1 5340000
-41 1 5360000
-41 1 5380000
-41 1 5400000
-41 1 5420000
-41 1 5440000
-41 1 5460000
-41 1 5480000
-41 1 5500000
-41 1 5520000
-41 1 5540000
-41 1 5560000
-41 1 5580000
-41 1 5600000
-41 1 5620000
-41 1 5640000
-41 1 5660000
-41 1 5680000
-41 1 5700000
-41 1 5720000
-41 1 5740000
-41 1 5760000
-41 1 5780000
-41 1 5800000
-41 1 5820000
-41 1 5840000
-41 1 5860000
-41 1 5880000
-41 1 5900000
-41 1 5920000
-41 1 5940000
-41 1 5960000
-41 1 5980000
-41 1 6000000
-41 1 6020000
-41 1 6040000
-41 1 6060000
-41 1 6080000
-41 1 6100000
-41 1 6120000
-41 1 6140000
-41 1 6160000
-41 1 6180000
-41 1 6200000
-41 1 6220000
-41 1 6240000
-41 1 6260000
-41 1 6280000
-41 1 6300000
-41 1 6320000
-41 1 6340000
-41 1 6360000
-41 1 6380000
-41 1 6400000
-41 1 6420000
-41 1 6440000
-41 1 6460000
-41 1 6480000
-41 1 6500000
-41 1 6520000
-41 1 6540000
-41 1 6560000
-41 1 6580000
-41 1 6600000
-41 1 6620000
-41 1 6640000
-41 1 6660000
-41 1 6680000
-41 1 6700000
-41 1 6720000
-41 1 6740000
-41 1 6760000
-41 1 6780000
-41 1 6800000
-41 1 6820000
-41 1 6840000
-41 1 6860000
-41 1 6880000
-41 1 6900000
-41 1 6920000
-41 1 6940000
-41 1 6960000
-41 1 6980000
-41 1 7000000
-41 1 7020000
-41 1 7040000
-41 1 7060000
-41 1 7080000
-41 1 7100000
-41 1 7120000
-41 1 7140000
-41 1 7160000
-41 1 7180000
-41 1 7200000
-41 1 7220000
-41 1 7240000
-41 1 7260000
-41 1 7280000
-41 1 7300000
-41 1 7320000
-41 1 7340000
-41 1 7360000
-41 1 7380000
-41 1 7400000
-41 1 7420000
-41 1 7440000
-41 1 7460000
-41 1 7480000
-41 1 7500000
-41 1 7520000
-41 1 7540000
-41 1 7560000
-41 1 7580000
-41 1 7600000
-41 1 7620000
-41 1 7640000
-41 1 7660000
-41 1 7680000
-41 1 7700000
-41 1 7720000
-41 1 7740000
-41 1 7760000
-41 1 7780000
-41 1 7800000
-41 1 7820000
-41 1 7840000
-41 1 7860000
-41 1 7880000
-41 1 7900000
-41 1 7920000
-41 1 7940000
-41 1 7960000
-41 1 7980000
-41 1 8000000
-41 1 8020000
-41 1 8040000
-41 1 8060000
-41 1 8080000
-41 1 8100000
-41 1 8120000
-41 1 8140000
-41 1 8160000
-41 1 8180000
-41 1 8200000
-41 1 8220000
-41 1 8240000
-41 1 8260000
-41 1 8280000
-41 1 8300000
-41 1 8320000
-41 1 8340000
-41 1 8360000
-41 1 8380000
-41 1 8400000
-41 1 8420000
-41 1 8440000
-41 1 8460000
-41 1 8480000
-41 1 8500000
-41 1 8520000
-41 1 8540000
-41 1 8560000
-41 1 8580000
-41 1 8600000
-41 1 8620000
-41 1 8640000
-41 1 8660000
-41 1 8680000
-41 1 8700000
-41 1 8720000
-41 1 8740000
-41 1 8760000
-41 1 8780000
-41 1 8800000
-41 1 8820000
-41 1 8840000
-41 1 8860000
-41 1 8880000
-41 1 8900000
-41 1 8920000
-41 1 8940000
-41 1 8960000
-41 1 8980000
-41 1 9000000
-41 1 9020000
-41 1 9040000
-41 1 9060000
-41 1 9080000
-41 1 9100000
-41 1 9120000
-41 1 9140000
-41 1 9160000
-41 1 9180000
-41 1 9200000
-41 1 9220000
-41 1 9240000
-41 1 9260000
-41 1 9280000
-41 1 9300000
-41 1 9320000
-41 1 9340000
-41 1 9360000
-41 1 9380000
-41 1 9400000
-41 1 9420000
-41 1 9440000
-41 1 9460000
-41 1 9480000
-41 1 9500000
-41 1 9520000
-41 1 9540000
-41 1 9560000
-41 1 9580000
-41 1 9600000
-41 1 9620000
-41 1 9640000
-41 1 9660000
-41 1 9680000
-41 1 9700000
-41 1 9720000
-41 1 9740000
-41 1 9760000
-41 1 9780000
-41 1 9800000
-41 1 9820000
-41 1 9840000
-41 1 9860000
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/res/bbb_mp3_stereo_192kbps_48000hz_multi_frame.info b/media/codec2/hal/hidl/1.0/vts/functional/res/bbb_mp3_stereo_192kbps_48000hz_multi_frame.info
deleted file mode 100644
index 575c75f..0000000
--- a/media/codec2/hal/hidl/1.0/vts/functional/res/bbb_mp3_stereo_192kbps_48000hz_multi_frame.info
+++ /dev/null
@@ -1,385 +0,0 @@
-576 1 0
-576 1 24000
-1152 1 48000
-1152 1 96000
-1152 1 144000
-1152 1 192000
-1728 1 240000
-1728 1 312000
-1728 1 384000
-1728 1 456000
-1728 1 528000
-2304 1 600000
-2304 1 696000
-2304 1 792000
-2304 1 888000
-2304 1 984000
-576 1 1080000
-576 1 1104000
-576 1 1128000
-576 1 1152000
-576 1 1176000
-576 1 1200000
-576 1 1224000
-576 1 1248000
-576 1 1272000
-576 1 1296000
-576 1 1320000
-576 1 1344000
-576 1 1368000
-576 1 1392000
-576 1 1416000
-576 1 1440000
-576 1 1464000
-576 1 1488000
-576 1 1512000
-576 1 1536000
-576 1 1560000
-576 1 1584000
-576 1 1608000
-576 1 1632000
-576 1 1656000
-576 1 1680000
-576 1 1704000
-576 1 1728000
-576 1 1752000
-576 1 1776000
-576 1 1800000
-576 1 1824000
-576 1 1848000
-576 1 1872000
-576 1 1896000
-576 1 1920000
-576 1 1944000
-576 1 1968000
-576 1 1992000
-576 1 2016000
-576 1 2040000
-576 1 2064000
-576 1 2088000
-576 1 2112000
-576 1 2136000
-576 1 2160000
-576 1 2184000
-576 1 2208000
-576 1 2232000
-576 1 2256000
-576 1 2280000
-576 1 2304000
-576 1 2328000
-576 1 2352000
-576 1 2376000
-576 1 2400000
-576 1 2424000
-576 1 2448000
-576 1 2472000
-576 1 2496000
-576 1 2520000
-576 1 2544000
-576 1 2568000
-576 1 2592000
-576 1 2616000
-576 1 2640000
-576 1 2664000
-576 1 2688000
-576 1 2712000
-576 1 2736000
-576 1 2760000
-576 1 2784000
-576 1 2808000
-576 1 2832000
-576 1 2856000
-576 1 2880000
-576 1 2904000
-576 1 2928000
-576 1 2952000
-576 1 2976000
-576 1 3000000
-576 1 3024000
-576 1 3048000
-576 1 3072000
-576 1 3096000
-576 1 3120000
-576 1 3144000
-576 1 3168000
-576 1 3192000
-576 1 3216000
-576 1 3240000
-576 1 3264000
-576 1 3288000
-576 1 3312000
-576 1 3336000
-576 1 3360000
-576 1 3384000
-576 1 3408000
-576 1 3432000
-576 1 3456000
-576 1 3480000
-576 1 3504000
-576 1 3528000
-576 1 3552000
-576 1 3576000
-576 1 3600000
-576 1 3624000
-576 1 3648000
-576 1 3672000
-576 1 3696000
-576 1 3720000
-576 1 3744000
-576 1 3768000
-576 1 3792000
-576 1 3816000
-576 1 3840000
-576 1 3864000
-576 1 3888000
-576 1 3912000
-576 1 3936000
-576 1 3960000
-576 1 3984000
-576 1 4008000
-576 1 4032000
-576 1 4056000
-576 1 4080000
-576 1 4104000
-576 1 4128000
-576 1 4152000
-576 1 4176000
-576 1 4200000
-576 1 4224000
-576 1 4248000
-576 1 4272000
-576 1 4296000
-576 1 4320000
-576 1 4344000
-576 1 4368000
-576 1 4392000
-576 1 4416000
-576 1 4440000
-576 1 4464000
-576 1 4488000
-576 1 4512000
-576 1 4536000
-576 1 4560000
-576 1 4584000
-576 1 4608000
-576 1 4632000
-576 1 4656000
-576 1 4680000
-576 1 4704000
-576 1 4728000
-576 1 4752000
-576 1 4776000
-576 1 4800000
-576 1 4824000
-576 1 4848000
-576 1 4872000
-576 1 4896000
-576 1 4920000
-576 1 4944000
-576 1 4968000
-576 1 4992000
-576 1 5016000
-576 1 5040000
-576 1 5064000
-576 1 5088000
-576 1 5112000
-576 1 5136000
-576 1 5160000
-576 1 5184000
-576 1 5208000
-576 1 5232000
-576 1 5256000
-576 1 5280000
-576 1 5304000
-576 1 5328000
-576 1 5352000
-576 1 5376000
-576 1 5400000
-576 1 5424000
-576 1 5448000
-576 1 5472000
-576 1 5496000
-576 1 5520000
-576 1 5544000
-576 1 5568000
-576 1 5592000
-576 1 5616000
-576 1 5640000
-576 1 5664000
-576 1 5688000
-576 1 5712000
-576 1 5736000
-576 1 5760000
-576 1 5784000
-576 1 5808000
-576 1 5832000
-576 1 5856000
-576 1 5880000
-576 1 5904000
-576 1 5928000
-576 1 5952000
-576 1 5976000
-576 1 6000000
-576 1 6024000
-576 1 6048000
-576 1 6072000
-576 1 6096000
-576 1 6120000
-576 1 6144000
-576 1 6168000
-576 1 6192000
-576 1 6216000
-576 1 6240000
-576 1 6264000
-576 1 6288000
-576 1 6312000
-576 1 6336000
-576 1 6360000
-576 1 6384000
-576 1 6408000
-576 1 6432000
-576 1 6456000
-576 1 6480000
-576 1 6504000
-576 1 6528000
-576 1 6552000
-576 1 6576000
-576 1 6600000
-576 1 6624000
-576 1 6648000
-576 1 6672000
-576 1 6696000
-576 1 6720000
-576 1 6744000
-576 1 6768000
-576 1 6792000
-576 1 6816000
-576 1 6840000
-576 1 6864000
-576 1 6888000
-576 1 6912000
-576 1 6936000
-576 1 6960000
-576 1 6984000
-576 1 7008000
-576 1 7032000
-576 1 7056000
-576 1 7080000
-576 1 7104000
-576 1 7128000
-576 1 7152000
-576 1 7176000
-576 1 7200000
-576 1 7224000
-576 1 7248000
-576 1 7272000
-576 1 7296000
-576 1 7320000
-576 1 7344000
-576 1 7368000
-576 1 7392000
-576 1 7416000
-576 1 7440000
-576 1 7464000
-576 1 7488000
-576 1 7512000
-576 1 7536000
-576 1 7560000
-576 1 7584000
-576 1 7608000
-576 1 7632000
-576 1 7656000
-576 1 7680000
-576 1 7704000
-576 1 7728000
-576 1 7752000
-576 1 7776000
-576 1 7800000
-576 1 7824000
-576 1 7848000
-576 1 7872000
-576 1 7896000
-576 1 7920000
-576 1 7944000
-576 1 7968000
-576 1 7992000
-576 1 8016000
-576 1 8040000
-576 1 8064000
-576 1 8088000
-576 1 8112000
-576 1 8136000
-576 1 8160000
-576 1 8184000
-576 1 8208000
-576 1 8232000
-576 1 8256000
-576 1 8280000
-576 1 8304000
-576 1 8328000
-576 1 8352000
-576 1 8376000
-576 1 8400000
-576 1 8424000
-576 1 8448000
-576 1 8472000
-576 1 8496000
-576 1 8520000
-576 1 8544000
-576 1 8568000
-576 1 8592000
-576 1 8616000
-576 1 8640000
-576 1 8664000
-576 1 8688000
-576 1 8712000
-576 1 8736000
-576 1 8760000
-576 1 8784000
-576 1 8808000
-576 1 8832000
-576 1 8856000
-576 1 8880000
-576 1 8904000
-576 1 8928000
-576 1 8952000
-576 1 8976000
-576 1 9000000
-576 1 9024000
-576 1 9048000
-576 1 9072000
-576 1 9096000
-576 1 9120000
-576 1 9144000
-576 1 9168000
-576 1 9192000
-576 1 9216000
-576 1 9240000
-576 1 9264000
-576 1 9288000
-576 1 9312000
-576 1 9336000
-576 1 9360000
-576 1 9384000
-576 1 9408000
-576 1 9432000
-576 1 9456000
-576 1 9480000
-576 1 9504000
-576 1 9528000
-576 1 9552000
-576 1 9576000
-576 1 9600000
-576 1 9624000
-576 1 9648000
-576 1 9672000
-576 1 9696000
-576 1 9720000
-576 1 9744000
-576 1 9768000
-576 1 9792000
-576 1 9816000
-576 1 9840000
-576 1 9864000
-576 1 9888000
-576 1 9912000
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/res/sine_amrnb_1ch_12kbps_8000hz_multi_frame.info b/media/codec2/hal/hidl/1.0/vts/functional/res/sine_amrnb_1ch_12kbps_8000hz_multi_frame.info
deleted file mode 100644
index 0176eaf4..0000000
--- a/media/codec2/hal/hidl/1.0/vts/functional/res/sine_amrnb_1ch_12kbps_8000hz_multi_frame.info
+++ /dev/null
@@ -1,807 +0,0 @@
-32 1 0
-32 1 20000
-64 1 40000
-64 1 80000
-64 1 120000
-96 1 160000
-96 1 220000
-96 1 280000
-96 1 340000
-128 1 400000
-128 1 480000
-128 1 560000
-128 1 640000
-128 1 720000
-32 1 800000
-32 1 820000
-32 1 840000
-32 1 860000
-32 1 880000
-32 1 900000
-32 1 920000
-32 1 940000
-32 1 960000
-32 1 980000
-32 1 1000000
-32 1 1020000
-32 1 1040000
-32 1 1060000
-32 1 1080000
-32 1 1100000
-32 1 1120000
-32 1 1140000
-32 1 1160000
-32 1 1180000
-32 1 1200000
-32 1 1220000
-32 1 1240000
-32 1 1260000
-32 1 1280000
-32 1 1300000
-32 1 1320000
-32 1 1340000
-32 1 1360000
-32 1 1380000
-32 1 1400000
-32 1 1420000
-32 1 1440000
-32 1 1460000
-32 1 1480000
-32 1 1500000
-32 1 1520000
-32 1 1540000
-32 1 1560000
-32 1 1580000
-32 1 1600000
-32 1 1620000
-32 1 1640000
-32 1 1660000
-32 1 1680000
-32 1 1700000
-32 1 1720000
-32 1 1740000
-32 1 1760000
-32 1 1780000
-32 1 1800000
-32 1 1820000
-32 1 1840000
-32 1 1860000
-32 1 1880000
-32 1 1900000
-32 1 1920000
-32 1 1940000
-32 1 1960000
-32 1 1980000
-32 1 2000000
-32 1 2020000
-32 1 2040000
-32 1 2060000
-32 1 2080000
-32 1 2100000
-32 1 2120000
-32 1 2140000
-32 1 2160000
-32 1 2180000
-32 1 2200000
-32 1 2220000
-32 1 2240000
-32 1 2260000
-32 1 2280000
-32 1 2300000
-32 1 2320000
-32 1 2340000
-32 1 2360000
-32 1 2380000
-32 1 2400000
-32 1 2420000
-32 1 2440000
-32 1 2460000
-32 1 2480000
-32 1 2500000
-32 1 2520000
-32 1 2540000
-32 1 2560000
-32 1 2580000
-32 1 2600000
-32 1 2620000
-32 1 2640000
-32 1 2660000
-32 1 2680000
-32 1 2700000
-32 1 2720000
-32 1 2740000
-32 1 2760000
-32 1 2780000
-32 1 2800000
-32 1 2820000
-32 1 2840000
-32 1 2860000
-32 1 2880000
-32 1 2900000
-32 1 2920000
-32 1 2940000
-32 1 2960000
-32 1 2980000
-32 1 3000000
-32 1 3020000
-32 1 3040000
-32 1 3060000
-32 1 3080000
-32 1 3100000
-32 1 3120000
-32 1 3140000
-32 1 3160000
-32 1 3180000
-32 1 3200000
-32 1 3220000
-32 1 3240000
-32 1 3260000
-32 1 3280000
-32 1 3300000
-32 1 3320000
-32 1 3340000
-32 1 3360000
-32 1 3380000
-32 1 3400000
-32 1 3420000
-32 1 3440000
-32 1 3460000
-32 1 3480000
-32 1 3500000
-32 1 3520000
-32 1 3540000
-32 1 3560000
-32 1 3580000
-32 1 3600000
-32 1 3620000
-32 1 3640000
-32 1 3660000
-32 1 3680000
-32 1 3700000
-32 1 3720000
-32 1 3740000
-32 1 3760000
-32 1 3780000
-32 1 3800000
-32 1 3820000
-32 1 3840000
-32 1 3860000
-32 1 3880000
-32 1 3900000
-32 1 3920000
-32 1 3940000
-32 1 3960000
-32 1 3980000
-32 1 4000000
-32 1 4020000
-32 1 4040000
-32 1 4060000
-32 1 4080000
-32 1 4100000
-32 1 4120000
-32 1 4140000
-32 1 4160000
-32 1 4180000
-32 1 4200000
-32 1 4220000
-32 1 4240000
-32 1 4260000
-32 1 4280000
-32 1 4300000
-32 1 4320000
-32 1 4340000
-32 1 4360000
-32 1 4380000
-32 1 4400000
-32 1 4420000
-32 1 4440000
-32 1 4460000
-32 1 4480000
-32 1 4500000
-32 1 4520000
-32 1 4540000
-32 1 4560000
-32 1 4580000
-32 1 4600000
-32 1 4620000
-32 1 4640000
-32 1 4660000
-32 1 4680000
-32 1 4700000
-32 1 4720000
-32 1 4740000
-32 1 4760000
-32 1 4780000
-32 1 4800000
-32 1 4820000
-32 1 4840000
-32 1 4860000
-32 1 4880000
-32 1 4900000
-32 1 4920000
-32 1 4940000
-32 1 4960000
-32 1 4980000
-32 1 5000000
-32 1 5020000
-32 1 5040000
-32 1 5060000
-32 1 5080000
-32 1 5100000
-32 1 5120000
-32 1 5140000
-32 1 5160000
-32 1 5180000
-32 1 5200000
-32 1 5220000
-32 1 5240000
-32 1 5260000
-32 1 5280000
-32 1 5300000
-32 1 5320000
-32 1 5340000
-32 1 5360000
-32 1 5380000
-32 1 5400000
-32 1 5420000
-32 1 5440000
-32 1 5460000
-32 1 5480000
-32 1 5500000
-32 1 5520000
-32 1 5540000
-32 1 5560000
-32 1 5580000
-32 1 5600000
-32 1 5620000
-32 1 5640000
-32 1 5660000
-32 1 5680000
-32 1 5700000
-32 1 5720000
-32 1 5740000
-32 1 5760000
-32 1 5780000
-32 1 5800000
-32 1 5820000
-32 1 5840000
-32 1 5860000
-32 1 5880000
-32 1 5900000
-32 1 5920000
-32 1 5940000
-32 1 5960000
-32 1 5980000
-32 1 6000000
-32 1 6020000
-32 1 6040000
-32 1 6060000
-32 1 6080000
-32 1 6100000
-32 1 6120000
-32 1 6140000
-32 1 6160000
-32 1 6180000
-32 1 6200000
-32 1 6220000
-32 1 6240000
-32 1 6260000
-32 1 6280000
-32 1 6300000
-32 1 6320000
-32 1 6340000
-32 1 6360000
-32 1 6380000
-32 1 6400000
-32 1 6420000
-32 1 6440000
-32 1 6460000
-32 1 6480000
-32 1 6500000
-32 1 6520000
-32 1 6540000
-32 1 6560000
-32 1 6580000
-32 1 6600000
-32 1 6620000
-32 1 6640000
-32 1 6660000
-32 1 6680000
-32 1 6700000
-32 1 6720000
-32 1 6740000
-32 1 6760000
-32 1 6780000
-32 1 6800000
-32 1 6820000
-32 1 6840000
-32 1 6860000
-32 1 6880000
-32 1 6900000
-32 1 6920000
-32 1 6940000
-32 1 6960000
-32 1 6980000
-32 1 7000000
-32 1 7020000
-32 1 7040000
-32 1 7060000
-32 1 7080000
-32 1 7100000
-32 1 7120000
-32 1 7140000
-32 1 7160000
-32 1 7180000
-32 1 7200000
-32 1 7220000
-32 1 7240000
-32 1 7260000
-32 1 7280000
-32 1 7300000
-32 1 7320000
-32 1 7340000
-32 1 7360000
-32 1 7380000
-32 1 7400000
-32 1 7420000
-32 1 7440000
-32 1 7460000
-32 1 7480000
-32 1 7500000
-32 1 7520000
-32 1 7540000
-32 1 7560000
-32 1 7580000
-32 1 7600000
-32 1 7620000
-32 1 7640000
-32 1 7660000
-32 1 7680000
-32 1 7700000
-32 1 7720000
-32 1 7740000
-32 1 7760000
-32 1 7780000
-32 1 7800000
-32 1 7820000
-32 1 7840000
-32 1 7860000
-32 1 7880000
-32 1 7900000
-32 1 7920000
-32 1 7940000
-32 1 7960000
-32 1 7980000
-32 1 8000000
-32 1 8020000
-32 1 8040000
-32 1 8060000
-32 1 8080000
-32 1 8100000
-32 1 8120000
-32 1 8140000
-32 1 8160000
-32 1 8180000
-32 1 8200000
-32 1 8220000
-32 1 8240000
-32 1 8260000
-32 1 8280000
-32 1 8300000
-32 1 8320000
-32 1 8340000
-32 1 8360000
-32 1 8380000
-32 1 8400000
-32 1 8420000
-32 1 8440000
-32 1 8460000
-32 1 8480000
-32 1 8500000
-32 1 8520000
-32 1 8540000
-32 1 8560000
-32 1 8580000
-32 1 8600000
-32 1 8620000
-32 1 8640000
-32 1 8660000
-32 1 8680000
-32 1 8700000
-32 1 8720000
-32 1 8740000
-32 1 8760000
-32 1 8780000
-32 1 8800000
-32 1 8820000
-32 1 8840000
-32 1 8860000
-32 1 8880000
-32 1 8900000
-32 1 8920000
-32 1 8940000
-32 1 8960000
-32 1 8980000
-32 1 9000000
-32 1 9020000
-32 1 9040000
-32 1 9060000
-32 1 9080000
-32 1 9100000
-32 1 9120000
-32 1 9140000
-32 1 9160000
-32 1 9180000
-32 1 9200000
-32 1 9220000
-32 1 9240000
-32 1 9260000
-32 1 9280000
-32 1 9300000
-32 1 9320000
-32 1 9340000
-32 1 9360000
-32 1 9380000
-32 1 9400000
-32 1 9420000
-32 1 9440000
-32 1 9460000
-32 1 9480000
-32 1 9500000
-32 1 9520000
-32 1 9540000
-32 1 9560000
-32 1 9580000
-32 1 9600000
-32 1 9620000
-32 1 9640000
-32 1 9660000
-32 1 9680000
-32 1 9700000
-32 1 9720000
-32 1 9740000
-32 1 9760000
-32 1 9780000
-32 1 9800000
-32 1 9820000
-32 1 9840000
-32 1 9860000
-32 1 9880000
-32 1 9900000
-32 1 9920000
-32 1 9940000
-32 1 9960000
-32 1 9980000
-32 1 10000000
-32 1 10020000
-32 1 10040000
-32 1 10060000
-32 1 10080000
-32 1 10100000
-32 1 10120000
-32 1 10140000
-32 1 10160000
-32 1 10180000
-32 1 10200000
-32 1 10220000
-32 1 10240000
-32 1 10260000
-32 1 10280000
-32 1 10300000
-32 1 10320000
-32 1 10340000
-32 1 10360000
-32 1 10380000
-32 1 10400000
-32 1 10420000
-32 1 10440000
-32 1 10460000
-32 1 10480000
-32 1 10500000
-32 1 10520000
-32 1 10540000
-32 1 10560000
-32 1 10580000
-32 1 10600000
-32 1 10620000
-32 1 10640000
-32 1 10660000
-32 1 10680000
-32 1 10700000
-32 1 10720000
-32 1 10740000
-32 1 10760000
-32 1 10780000
-32 1 10800000
-32 1 10820000
-32 1 10840000
-32 1 10860000
-32 1 10880000
-32 1 10900000
-32 1 10920000
-32 1 10940000
-32 1 10960000
-32 1 10980000
-32 1 11000000
-32 1 11020000
-32 1 11040000
-32 1 11060000
-32 1 11080000
-32 1 11100000
-32 1 11120000
-32 1 11140000
-32 1 11160000
-32 1 11180000
-32 1 11200000
-32 1 11220000
-32 1 11240000
-32 1 11260000
-32 1 11280000
-32 1 11300000
-32 1 11320000
-32 1 11340000
-32 1 11360000
-32 1 11380000
-32 1 11400000
-32 1 11420000
-32 1 11440000
-32 1 11460000
-32 1 11480000
-32 1 11500000
-32 1 11520000
-32 1 11540000
-32 1 11560000
-32 1 11580000
-32 1 11600000
-32 1 11620000
-32 1 11640000
-32 1 11660000
-32 1 11680000
-32 1 11700000
-32 1 11720000
-32 1 11740000
-32 1 11760000
-32 1 11780000
-32 1 11800000
-32 1 11820000
-32 1 11840000
-32 1 11860000
-32 1 11880000
-32 1 11900000
-32 1 11920000
-32 1 11940000
-32 1 11960000
-32 1 11980000
-32 1 12000000
-32 1 12020000
-32 1 12040000
-32 1 12060000
-32 1 12080000
-32 1 12100000
-32 1 12120000
-32 1 12140000
-32 1 12160000
-32 1 12180000
-32 1 12200000
-32 1 12220000
-32 1 12240000
-32 1 12260000
-32 1 12280000
-32 1 12300000
-32 1 12320000
-32 1 12340000
-32 1 12360000
-32 1 12380000
-32 1 12400000
-32 1 12420000
-32 1 12440000
-32 1 12460000
-32 1 12480000
-32 1 12500000
-32 1 12520000
-32 1 12540000
-32 1 12560000
-32 1 12580000
-32 1 12600000
-32 1 12620000
-32 1 12640000
-32 1 12660000
-32 1 12680000
-32 1 12700000
-32 1 12720000
-32 1 12740000
-32 1 12760000
-32 1 12780000
-32 1 12800000
-32 1 12820000
-32 1 12840000
-32 1 12860000
-32 1 12880000
-32 1 12900000
-32 1 12920000
-32 1 12940000
-32 1 12960000
-32 1 12980000
-32 1 13000000
-32 1 13020000
-32 1 13040000
-32 1 13060000
-32 1 13080000
-32 1 13100000
-32 1 13120000
-32 1 13140000
-32 1 13160000
-32 1 13180000
-32 1 13200000
-32 1 13220000
-32 1 13240000
-32 1 13260000
-32 1 13280000
-32 1 13300000
-32 1 13320000
-32 1 13340000
-32 1 13360000
-32 1 13380000
-32 1 13400000
-32 1 13420000
-32 1 13440000
-32 1 13460000
-32 1 13480000
-32 1 13500000
-32 1 13520000
-32 1 13540000
-32 1 13560000
-32 1 13580000
-32 1 13600000
-32 1 13620000
-32 1 13640000
-32 1 13660000
-32 1 13680000
-32 1 13700000
-32 1 13720000
-32 1 13740000
-32 1 13760000
-32 1 13780000
-32 1 13800000
-32 1 13820000
-32 1 13840000
-32 1 13860000
-32 1 13880000
-32 1 13900000
-32 1 13920000
-32 1 13940000
-32 1 13960000
-32 1 13980000
-32 1 14000000
-32 1 14020000
-32 1 14040000
-32 1 14060000
-32 1 14080000
-32 1 14100000
-32 1 14120000
-32 1 14140000
-32 1 14160000
-32 1 14180000
-32 1 14200000
-32 1 14220000
-32 1 14240000
-32 1 14260000
-32 1 14280000
-32 1 14300000
-32 1 14320000
-32 1 14340000
-32 1 14360000
-32 1 14380000
-32 1 14400000
-32 1 14420000
-32 1 14440000
-32 1 14460000
-32 1 14480000
-32 1 14500000
-32 1 14520000
-32 1 14540000
-32 1 14560000
-32 1 14580000
-32 1 14600000
-32 1 14620000
-32 1 14640000
-32 1 14660000
-32 1 14680000
-32 1 14700000
-32 1 14720000
-32 1 14740000
-32 1 14760000
-32 1 14780000
-32 1 14800000
-32 1 14820000
-32 1 14840000
-32 1 14860000
-32 1 14880000
-32 1 14900000
-32 1 14920000
-32 1 14940000
-32 1 14960000
-32 1 14980000
-32 1 15000000
-32 1 15020000
-32 1 15040000
-32 1 15060000
-32 1 15080000
-32 1 15100000
-32 1 15120000
-32 1 15140000
-32 1 15160000
-32 1 15180000
-32 1 15200000
-32 1 15220000
-32 1 15240000
-32 1 15260000
-32 1 15280000
-32 1 15300000
-32 1 15320000
-32 1 15340000
-32 1 15360000
-32 1 15380000
-32 1 15400000
-32 1 15420000
-32 1 15440000
-32 1 15460000
-32 1 15480000
-32 1 15500000
-32 1 15520000
-32 1 15540000
-32 1 15560000
-32 1 15580000
-32 1 15600000
-32 1 15620000
-32 1 15640000
-32 1 15660000
-32 1 15680000
-32 1 15700000
-32 1 15720000
-32 1 15740000
-32 1 15760000
-32 1 15780000
-32 1 15800000
-32 1 15820000
-32 1 15840000
-32 1 15860000
-32 1 15880000
-32 1 15900000
-32 1 15920000
-32 1 15940000
-32 1 15960000
-32 1 15980000
-32 1 16000000
-32 1 16020000
-32 1 16040000
-32 1 16060000
-32 1 16080000
-32 1 16100000
-32 1 16120000
-32 1 16140000
-32 1 16160000
-32 1 16180000
-32 1 16200000
-32 1 16220000
-32 1 16240000
-32 1 16260000
-32 1 16280000
-32 1 16300000
-32 1 16320000
-32 1 16340000
-32 1 16360000
-32 1 16380000
-32 1 16400000
-32 1 16420000
-32 1 16440000
-32 1 16460000
-32 1 16480000
-32 1 16500000
-32 1 16520000
-32 1 16540000
-32 1 16560000
-32 1 16580000
-32 1 16600000
-32 1 16620000
-32 1 16640000
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp b/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
index c19701d..d561adc 100644
--- a/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
+++ b/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
@@ -685,7 +685,7 @@
if (mDisableTest) GTEST_SKIP() << "Test is disabled";
if (!(strcasestr(mMime.c_str(), "avc") || strcasestr(mMime.c_str(), "hevc") ||
strcasestr(mMime.c_str(), "vp8") || strcasestr(mMime.c_str(), "vp9") ||
- strcasestr(mMime.c_str(), "mpeg2"))) {
+ strcasestr(mMime.c_str(), "mpeg2") || strcasestr(mMime.c_str(), "av01"))) {
return;
}
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp b/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp
index 8305feb..db68b96 100644
--- a/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp
+++ b/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp
@@ -500,7 +500,7 @@
description("Encodes input file");
if (mDisableTest) GTEST_SKIP() << "Test is disabled";
- bool signalEOS = std::get<3>(GetParam());
+ bool signalEOS = std::get<2>(GetParam());
// Send an empty frame to receive CSD data from encoder.
bool sendEmptyFirstFrame = std::get<3>(GetParam());
mConfigBPictures = std::get<4>(GetParam());
diff --git a/media/codec2/hal/services/Android.bp b/media/codec2/hal/services/Android.bp
index 524519c..663e159 100644
--- a/media/codec2/hal/services/Android.bp
+++ b/media/codec2/hal/services/Android.bp
@@ -39,13 +39,17 @@
}
cc_binary {
- name: "android.hardware.media.c2@1.2-default-service",
+ name: "android.hardware.media.c2-default-service",
vendor: true,
relative_install_path: "hw",
- init_rc: ["android.hardware.media.c2@1.2-default-service.rc"],
+ init_rc: ["android.hardware.media.c2-default-service.rc"],
- defaults: ["libcodec2-hidl-defaults"],
+ defaults: [
+ "libcodec2-hidl-defaults",
+ "libcodec2-aidl-defaults",
+ ],
+
srcs: [
"vendor.cpp",
],
@@ -54,13 +58,14 @@
shared_libs: [
"libavservices_minijail",
"libbinder",
+ "libbinder_ndk",
],
- required: ["android.hardware.media.c2@1.2-default-seccomp_policy"],
+ required: ["android.hardware.media.c2-default-seccomp_policy"],
- // The content in manifest_media_c2_V1_1_default.xml can be included
+ // The content in manifest_media_c2_default.xml can be included
// directly in the main device manifest.xml file or via vintf_fragments.
// (Remove the line below if the entry is already in the main manifest.)
- vintf_fragments: ["manifest_media_c2_V1_1_default.xml"],
+ vintf_fragments: ["manifest_media_c2_default.xml"],
// Remove this line to enable this module.
enabled: false,
@@ -73,30 +78,29 @@
// Files in the "seccomp_policy" subdirectory are only provided as examples.
// They may not work on some devices and/or architectures without modification.
prebuilt_etc {
- name: "android.hardware.media.c2@1.2-default-seccomp_policy",
+ name: "android.hardware.media.c2-default-seccomp_policy",
vendor: true,
sub_dir: "seccomp_policy",
// If a specific architecture is targeted, multiple choices are not needed.
arch: {
arm: {
- src: "seccomp_policy/android.hardware.media.c2@1.2-default-arm.policy",
+ src: "seccomp_policy/android.hardware.media.c2-default-arm.policy",
},
arm64: {
- src: "seccomp_policy/android.hardware.media.c2@1.2-default-arm64.policy",
+ src: "seccomp_policy/android.hardware.media.c2-default-arm64.policy",
},
riscv64: {
- src: "seccomp_policy/android.hardware.media.c2@1.2-default-riscv64.policy",
+ src: "seccomp_policy/android.hardware.media.c2-default-riscv64.policy",
},
x86: {
- src: "seccomp_policy/android.hardware.media.c2@1.2-default-x86.policy",
+ src: "seccomp_policy/android.hardware.media.c2-default-x86.policy",
},
x86_64: {
- src: "seccomp_policy/android.hardware.media.c2@1.2-default-x86_64.policy",
+ src: "seccomp_policy/android.hardware.media.c2-default-x86_64.policy",
},
},
// This may be removed.
required: ["crash_dump.policy"],
}
-
diff --git a/media/codec2/hal/services/android.hardware.media.c2-default-service.rc b/media/codec2/hal/services/android.hardware.media.c2-default-service.rc
new file mode 100644
index 0000000..dcc8e71
--- /dev/null
+++ b/media/codec2/hal/services/android.hardware.media.c2-default-service.rc
@@ -0,0 +1,7 @@
+service android-hardware-media-c2-hal /vendor/bin/hw/android.hardware.media.c2-default-service
+ class hal
+ user mediacodec
+ group camera mediadrm drmrpc
+ ioprio rt 4
+ task_profiles ProcessCapacityHigh
+
diff --git a/media/codec2/hal/services/android.hardware.media.c2@1.2-default-service.rc b/media/codec2/hal/services/android.hardware.media.c2@1.2-default-service.rc
deleted file mode 100644
index 12da593..0000000
--- a/media/codec2/hal/services/android.hardware.media.c2@1.2-default-service.rc
+++ /dev/null
@@ -1,7 +0,0 @@
-service android-hardware-media-c2-hal-1-2 /vendor/bin/hw/android.hardware.media.c2@1.2-default-service
- class hal
- user mediacodec
- group camera mediadrm drmrpc
- ioprio rt 4
- task_profiles ProcessCapacityHigh
-
diff --git a/media/codec2/hal/services/manifest_media_c2_V1_0_default.xml b/media/codec2/hal/services/manifest_media_c2_V1_0_default.xml
deleted file mode 100644
index e97c3ce..0000000
--- a/media/codec2/hal/services/manifest_media_c2_V1_0_default.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<manifest version="1.0" type="device">
- <hal>
- <name>android.hardware.media.c2</name>
- <transport>hwbinder</transport>
- <version>1.0</version>
- <interface>
- <name>IComponentStore</name>
- <instance>default</instance>
- </interface>
- </hal>
-</manifest>
diff --git a/media/codec2/hal/services/manifest_media_c2_V1_1_default.xml b/media/codec2/hal/services/manifest_media_c2_V1_1_default.xml
deleted file mode 100644
index bf0d72f..0000000
--- a/media/codec2/hal/services/manifest_media_c2_V1_1_default.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<manifest version="1.0" type="device">
- <hal>
- <name>android.hardware.media.c2</name>
- <transport>hwbinder</transport>
- <version>1.1</version>
- <interface>
- <name>IComponentStore</name>
- <instance>default</instance>
- </interface>
- </hal>
-</manifest>
diff --git a/media/codec2/hal/services/manifest_media_c2_V1_2_default.xml b/media/codec2/hal/services/manifest_media_c2_V1_2_default.xml
deleted file mode 100644
index a5e8d87..0000000
--- a/media/codec2/hal/services/manifest_media_c2_V1_2_default.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<manifest version="1.0" type="device">
- <hal>
- <name>android.hardware.media.c2</name>
- <transport>hwbinder</transport>
- <version>1.2</version>
- <interface>
- <name>IComponentStore</name>
- <instance>default</instance>
- </interface>
- </hal>
-</manifest>
diff --git a/media/codec2/hal/services/manifest_media_c2_default.xml b/media/codec2/hal/services/manifest_media_c2_default.xml
new file mode 100644
index 0000000..5e3d060
--- /dev/null
+++ b/media/codec2/hal/services/manifest_media_c2_default.xml
@@ -0,0 +1,18 @@
+<manifest version="1.0" type="device">
+ <!-- HIDL fragment -->
+ <hal>
+ <name>android.hardware.media.c2</name>
+ <transport>hwbinder</transport>
+ <version>1.2</version>
+ <interface>
+ <name>IComponentStore</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <!-- AIDL fragment -->
+ <hal format="aidl">
+ <name>android.hardware.media.c2</name>
+ <version>1</version>
+ <fqname>IComponentStore/default</fqname>
+ </hal>
+</manifest>
diff --git a/media/codec2/hal/services/seccomp_policy/android.hardware.media.c2@1.2-default-arm.policy b/media/codec2/hal/services/seccomp_policy/android.hardware.media.c2-default-arm.policy
similarity index 100%
rename from media/codec2/hal/services/seccomp_policy/android.hardware.media.c2@1.2-default-arm.policy
rename to media/codec2/hal/services/seccomp_policy/android.hardware.media.c2-default-arm.policy
diff --git a/media/codec2/hal/services/seccomp_policy/android.hardware.media.c2@1.2-default-arm64.policy b/media/codec2/hal/services/seccomp_policy/android.hardware.media.c2-default-arm64.policy
similarity index 100%
rename from media/codec2/hal/services/seccomp_policy/android.hardware.media.c2@1.2-default-arm64.policy
rename to media/codec2/hal/services/seccomp_policy/android.hardware.media.c2-default-arm64.policy
diff --git a/media/codec2/hal/services/seccomp_policy/android.hardware.media.c2@1.2-default-riscv64.policy b/media/codec2/hal/services/seccomp_policy/android.hardware.media.c2-default-riscv64.policy
similarity index 100%
rename from media/codec2/hal/services/seccomp_policy/android.hardware.media.c2@1.2-default-riscv64.policy
rename to media/codec2/hal/services/seccomp_policy/android.hardware.media.c2-default-riscv64.policy
diff --git a/media/codec2/hal/services/seccomp_policy/android.hardware.media.c2@1.2-default-x86.policy b/media/codec2/hal/services/seccomp_policy/android.hardware.media.c2-default-x86.policy
similarity index 100%
rename from media/codec2/hal/services/seccomp_policy/android.hardware.media.c2@1.2-default-x86.policy
rename to media/codec2/hal/services/seccomp_policy/android.hardware.media.c2-default-x86.policy
diff --git a/media/codec2/hal/services/seccomp_policy/android.hardware.media.c2@1.2-default-x86_64.policy b/media/codec2/hal/services/seccomp_policy/android.hardware.media.c2-default-x86_64.policy
similarity index 100%
rename from media/codec2/hal/services/seccomp_policy/android.hardware.media.c2@1.2-default-x86_64.policy
rename to media/codec2/hal/services/seccomp_policy/android.hardware.media.c2-default-x86_64.policy
diff --git a/media/codec2/hal/services/vendor.cpp b/media/codec2/hal/services/vendor.cpp
index 0d0684d..7cb7e6d 100644
--- a/media/codec2/hal/services/vendor.cpp
+++ b/media/codec2/hal/services/vendor.cpp
@@ -15,29 +15,43 @@
*/
//#define LOG_NDEBUG 0
-#define LOG_TAG "android.hardware.media.c2@1.2-service"
+#define LOG_TAG "android.hardware.media.c2-service"
#include <android-base/logging.h>
-#include <binder/ProcessState.h>
-#include <codec2/hidl/1.2/ComponentStore.h>
-#include <hidl/HidlTransportSupport.h>
#include <minijail.h>
#include <util/C2InterfaceHelper.h>
#include <C2Component.h>
#include <C2Config.h>
+// HIDL
+#include <binder/ProcessState.h>
+#include <codec2/hidl/1.2/ComponentStore.h>
+#include <hidl/HidlTransportSupport.h>
+
+// AIDL
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <codec2/aidl/ComponentStore.h>
+#include <codec2/aidl/ParamTypes.h>
+
// This is the absolute on-device path of the prebuild_etc module
-// "android.hardware.media.c2@1.1-default-seccomp_policy" in Android.bp.
+// "android.hardware.media.c2-default-seccomp_policy" in Android.bp.
static constexpr char kBaseSeccompPolicyPath[] =
"/vendor/etc/seccomp_policy/"
- "android.hardware.media.c2@1.2-default-seccomp-policy";
+ "android.hardware.media.c2-default-seccomp_policy";
// Additional seccomp permissions can be added in this file.
// This file does not exist by default.
static constexpr char kExtSeccompPolicyPath[] =
"/vendor/etc/seccomp_policy/"
- "android.hardware.media.c2@1.2-extended-seccomp-policy";
+ "android.hardware.media.c2-extended-seccomp_policy";
+
+// We want multiple threads to be running so that a blocking operation
+// on one codec does not block the other codecs.
+// For HIDL: Extra threads may be needed to handle a stacked IPC sequence that
+// contains alternating binder and hwbinder calls. (See b/35283480.)
+static constexpr int kThreadCount = 8;
class StoreImpl : public C2ComponentStore {
public:
@@ -125,12 +139,12 @@
addParameter(
DefineParam(mDmaBufUsageInfo, "dmabuf-usage")
- .withDefault(new C2StoreDmaBufUsageInfo())
+ .withDefault(C2StoreDmaBufUsageInfo::AllocShared(128))
.withFields({
- C2F(mDmaBufUsageInfo, usage).flags({C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE}),
- C2F(mDmaBufUsageInfo, capacity).inRange(0, UINT32_MAX, 1024),
- C2F(mDmaBufUsageInfo, heapName).any(),
- C2F(mDmaBufUsageInfo, allocFlags).flags({}),
+ C2F(mDmaBufUsageInfo, m.usage).flags({C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE}),
+ C2F(mDmaBufUsageInfo, m.capacity).inRange(0, UINT32_MAX, 1024),
+ C2F(mDmaBufUsageInfo, m.allocFlags).flags({}),
+ C2F(mDmaBufUsageInfo, m.heapName).any(),
})
.withSetter(SetDmaBufUsage)
.build());
@@ -162,21 +176,49 @@
Interface mInterface;
};
-int main(int /* argc */, char** /* argv */) {
- using namespace ::android;
- LOG(DEBUG) << "android.hardware.media.c2@1.2-service starting...";
+void runAidlService() {
+ ABinderProcess_setThreadPoolMaxThreadCount(kThreadCount);
+ ABinderProcess_startThreadPool();
- // Set up minijail to limit system calls.
- signal(SIGPIPE, SIG_IGN);
- SetUpMinijail(kBaseSeccompPolicyPath, kExtSeccompPolicyPath);
+ // Create IComponentStore service.
+ using namespace ::aidl::android::hardware::media::c2;
+ std::shared_ptr<IComponentStore> store;
+
+ // TODO: Replace this with
+ // store = new utils::ComponentStore(
+ // /* implementation of C2ComponentStore */);
+ LOG(DEBUG) << "Instantiating Codec2's IComponentStore service...";
+ store = ::ndk::SharedRefBase::make<utils::ComponentStore>(
+ std::make_shared<StoreImpl>());
+
+ if (store == nullptr) {
+ LOG(ERROR) << "Cannot create Codec2's IComponentStore service.";
+ } else {
+ const std::string serviceName =
+ std::string(IComponentStore::descriptor) + "/default";
+ binder_exception_t ex = AServiceManager_addService(
+ store->asBinder().get(), serviceName.c_str());
+ if (ex != EX_NONE) {
+ LOG(ERROR) << "Cannot register Codec2's IComponentStore service"
+ " with instance name << \""
+ << serviceName << "\".";
+ } else {
+ LOG(DEBUG) << "Codec2's IComponentStore service registered. "
+ "Instance name: \"" << serviceName << "\".";
+ }
+ }
+
+ ABinderProcess_joinThreadPool();
+}
+
+void runHidlService() {
+ using namespace ::android;
// Enable vndbinder to allow vendor-to-vendor binder calls.
ProcessState::initWithDriver("/dev/vndbinder");
ProcessState::self()->startThreadPool();
- // Extra threads may be needed to handle a stacked IPC sequence that
- // contains alternating binder and hwbinder calls. (See b/35283480.)
- hardware::configureRpcThreadpool(8, true /* callerWillJoin */);
+ hardware::configureRpcThreadpool(kThreadCount, true /* callerWillJoin */);
// Create IComponentStore service.
{
@@ -206,5 +248,20 @@
}
hardware::joinRpcThreadpool();
+}
+
+int main(int /* argc */, char** /* argv */) {
+ const bool aidlEnabled = ::aidl::android::hardware::media::c2::utils::IsEnabled();
+ LOG(DEBUG) << "android.hardware.media.c2" << (aidlEnabled ? "-V1" : "@1.2")
+ << "-service starting...";
+
+ // Set up minijail to limit system calls.
+ signal(SIGPIPE, SIG_IGN);
+ android::SetUpMinijail(kBaseSeccompPolicyPath, kExtSeccompPolicyPath);
+ if (aidlEnabled) {
+ runAidlService();
+ } else {
+ runHidlService();
+ }
return 0;
}
diff --git a/media/codec2/sfplugin/C2OMXNode.cpp b/media/codec2/sfplugin/C2OMXNode.cpp
index 92cfe31..bba022b 100644
--- a/media/codec2/sfplugin/C2OMXNode.cpp
+++ b/media/codec2/sfplugin/C2OMXNode.cpp
@@ -202,8 +202,10 @@
android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_WARN_ALWAYS);
mQueueThread->run("C2OMXNode", PRIORITY_AUDIO);
- Mutexed<android_dataspace>::Locked ds(mDataspace);
- *ds = HAL_DATASPACE_UNKNOWN;
+ android_dataspace ds = HAL_DATASPACE_UNKNOWN;
+ mDataspace.lock().set(ds);
+ uint32_t pf = PIXEL_FORMAT_UNKNOWN;
+ mPixelFormat.lock().set(pf);
}
status_t C2OMXNode::freeNode() {
@@ -521,8 +523,8 @@
ALOGD("dataspace changed to %#x pixel format: %#x", dataSpace, pixelFormat);
mQueueThread->setDataspace(dataSpace);
- Mutexed<android_dataspace>::Locked ds(mDataspace);
- *ds = dataSpace;
+ mDataspace.lock().set(dataSpace);
+ mPixelFormat.lock().set(pixelFormat);
return OK;
}
@@ -559,6 +561,10 @@
return *mDataspace.lock();
}
+uint32_t C2OMXNode::getPixelFormat() {
+ return *mPixelFormat.lock();
+}
+
void C2OMXNode::setPriority(int priority) {
mQueueThread->setPriority(priority);
}
diff --git a/media/codec2/sfplugin/C2OMXNode.h b/media/codec2/sfplugin/C2OMXNode.h
index 6669318..c8ce336 100644
--- a/media/codec2/sfplugin/C2OMXNode.h
+++ b/media/codec2/sfplugin/C2OMXNode.h
@@ -99,6 +99,11 @@
android_dataspace getDataspace();
/**
+ * Returns dataspace information from GraphicBufferSource.
+ */
+ uint32_t getPixelFormat();
+
+ /**
* Sets priority of the queue thread.
*/
void setPriority(int priority);
@@ -112,6 +117,7 @@
uint32_t mHeight;
uint64_t mUsage;
Mutexed<android_dataspace> mDataspace;
+ Mutexed<uint32_t> mPixelFormat;
// WORKAROUND: timestamp adjustment
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index 1153fb6..e2512dc 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -45,6 +45,7 @@
#include <media/stagefright/CCodec.h>
#include <media/stagefright/BufferProducerWrapper.h>
#include <media/stagefright/MediaCodecConstants.h>
+#include <media/stagefright/MediaCodecMetricsConstants.h>
#include <media/stagefright/PersistentSurface.h>
#include <media/stagefright/RenderedFrameInfo.h>
#include <utils/NativeHandle.h>
@@ -430,6 +431,10 @@
return mNode->getDataspace();
}
+ uint32_t getPixelFormat() override {
+ return mNode->getPixelFormat();
+ }
+
private:
sp<HGraphicBufferSource> mSource;
sp<C2OMXNode> mNode;
@@ -1536,6 +1541,9 @@
config->queryConfiguration(comp);
+ mMetrics = new AMessage;
+ mChannel->resetBuffersPixelFormat((config->mDomain & Config::IS_ENCODER) ? true : false);
+
mCallback->onComponentConfigured(config->mInputFormat, config->mOutputFormat);
}
@@ -2499,6 +2507,21 @@
}
mChannel->onWorkDone(
std::move(work), outputFormat, initData ? initData.get() : nullptr);
+ // log metrics to MediaCodec
+ if (mMetrics->countEntries() == 0) {
+ Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
+ const std::unique_ptr<Config> &config = *configLocked;
+ uint32_t pf = PIXEL_FORMAT_UNKNOWN;
+ if (!config->mInputSurface) {
+ pf = mChannel->getBuffersPixelFormat(config->mDomain & Config::IS_ENCODER);
+ } else {
+ pf = config->mInputSurface->getPixelFormat();
+ }
+ if (pf != PIXEL_FORMAT_UNKNOWN) {
+ mMetrics->setInt64(kCodecPixelFormat, pf);
+ mCallback->onMetricsUpdated(mMetrics);
+ }
+ }
break;
}
case kWhatWatch: {
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index 7665d6b..718bc8f 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -1046,6 +1046,15 @@
if (desiredRenderTimeNs < nowNs) {
desiredRenderTimeNs = nowNs;
}
+
+ // If the render time is more than a second from now, then pretend the frame is supposed to be
+ // rendered immediately, because that's what SurfaceFlinger heuristics will do. This is a tight
+ // coupling, but is really the only way to optimize away unnecessary present fence checks in
+ // processRenderedFrames.
+ if (desiredRenderTimeNs > nowNs + 1*1000*1000*1000LL) {
+ desiredRenderTimeNs = nowNs;
+ }
+
// We've just queued a frame to the surface, so keep track of it and later check to see if it is
// actually rendered.
TrackedFrame frame;
@@ -2166,8 +2175,15 @@
if (notifyClient && !buffer && !flags) {
if (mTunneled && drop && outputFormat) {
- ALOGV("[%s] onWorkDone: Keep tunneled, drop frame with format change (%lld)",
- mName, work->input.ordinal.frameIndex.peekull());
+ if (mOutputFormat != outputFormat) {
+ ALOGV("[%s] onWorkDone: Keep tunneled, drop frame with format change (%lld)",
+ mName, work->input.ordinal.frameIndex.peekull());
+ mOutputFormat = outputFormat;
+ } else {
+ ALOGV("[%s] onWorkDone: Not reporting output buffer without format change (%lld)",
+ mName, work->input.ordinal.frameIndex.peekull());
+ notifyClient = false;
+ }
} else {
ALOGV("[%s] onWorkDone: Not reporting output buffer (%lld)",
mName, work->input.ordinal.frameIndex.peekull());
@@ -2368,6 +2384,46 @@
mDescrambler = descrambler;
}
+uint32_t CCodecBufferChannel::getBuffersPixelFormat(bool isEncoder) {
+ if (isEncoder) {
+ return getInputBuffersPixelFormat();
+ } else {
+ return getOutputBuffersPixelFormat();
+ }
+}
+
+uint32_t CCodecBufferChannel::getInputBuffersPixelFormat() {
+ Mutexed<Input>::Locked input(mInput);
+ if (input->buffers == nullptr) {
+ return PIXEL_FORMAT_UNKNOWN;
+ }
+ return input->buffers->getPixelFormatIfApplicable();
+}
+
+uint32_t CCodecBufferChannel::getOutputBuffersPixelFormat() {
+ Mutexed<Output>::Locked output(mOutput);
+ if (output->buffers == nullptr) {
+ return PIXEL_FORMAT_UNKNOWN;
+ }
+ return output->buffers->getPixelFormatIfApplicable();
+}
+
+void CCodecBufferChannel::resetBuffersPixelFormat(bool isEncoder) {
+ if (isEncoder) {
+ Mutexed<Input>::Locked input(mInput);
+ if (input->buffers == nullptr) {
+ return;
+ }
+ input->buffers->resetPixelFormatIfApplicable();
+ } else {
+ Mutexed<Output>::Locked output(mOutput);
+ if (output->buffers == nullptr) {
+ return;
+ }
+ output->buffers->resetPixelFormatIfApplicable();
+ }
+}
+
status_t toStatusT(c2_status_t c2s, c2_operation_t c2op) {
// C2_OK is always translated to OK.
if (c2s == C2_OK) {
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.h b/media/codec2/sfplugin/CCodecBufferChannel.h
index 2bdb7bc..775bbbf 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.h
+++ b/media/codec2/sfplugin/CCodecBufferChannel.h
@@ -207,7 +207,20 @@
void setMetaMode(MetaMode mode);
+ /**
+ * get pixel format from output buffers.
+ *
+ * @return 0 if no valid pixel format found.
+ */
+ uint32_t getBuffersPixelFormat(bool isEncoder);
+
+ void resetBuffersPixelFormat(bool isEncoder);
+
private:
+ uint32_t getInputBuffersPixelFormat();
+
+ uint32_t getOutputBuffersPixelFormat();
+
class QueueGuard;
/**
@@ -303,6 +316,7 @@
std::shared_ptr<C2BlockPool> mInputAllocator;
QueueSync mQueueSync;
std::vector<std::unique_ptr<C2Param>> mParamsToBeSet;
+ sp<AMessage> mOutputFormat;
struct Input {
Input();
diff --git a/media/codec2/sfplugin/CCodecBuffers.cpp b/media/codec2/sfplugin/CCodecBuffers.cpp
index 0f4a8d8..670923b 100644
--- a/media/codec2/sfplugin/CCodecBuffers.cpp
+++ b/media/codec2/sfplugin/CCodecBuffers.cpp
@@ -18,6 +18,7 @@
#define LOG_TAG "CCodecBuffers"
#include <utils/Log.h>
+#include <C2AllocatorGralloc.h>
#include <C2PlatformSupport.h>
#include <media/stagefright/foundation/ADebug.h>
@@ -121,6 +122,10 @@
buffer->setFormat(mFormatWithImageData);
}
+uint32_t CCodecBuffers::getPixelFormatIfApplicable() { return PIXEL_FORMAT_UNKNOWN; }
+
+bool CCodecBuffers::resetPixelFormatIfApplicable() { return false; }
+
// InputBuffers
sp<Codec2Buffer> InputBuffers::cloneAndReleaseBuffer(const sp<MediaCodecBuffer> &buffer) {
@@ -1043,7 +1048,8 @@
const char *componentName, const char *name)
: InputBuffers(componentName, name),
mImpl(mName),
- mLocalBufferPool(LocalBufferPool::Create()) { }
+ mLocalBufferPool(LocalBufferPool::Create()),
+ mPixelFormat(PIXEL_FORMAT_UNKNOWN) { }
bool GraphicInputBuffers::requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) {
sp<Codec2Buffer> newBuffer = createNewBuffer();
@@ -1109,8 +1115,16 @@
sp<Codec2Buffer> GraphicInputBuffers::createNewBuffer() {
C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
+ mPixelFormat = extractPixelFormat(mFormat);
return AllocateInputGraphicBuffer(
- mPool, mFormat, extractPixelFormat(mFormat), usage, mLocalBufferPool);
+ mPool, mFormat, mPixelFormat, usage, mLocalBufferPool);
+}
+
+uint32_t GraphicInputBuffers::getPixelFormatIfApplicable() { return mPixelFormat; }
+
+bool GraphicInputBuffers::resetPixelFormatIfApplicable() {
+ mPixelFormat = PIXEL_FORMAT_UNKNOWN;
+ return true;
}
// OutputBuffersArray
@@ -1269,6 +1283,8 @@
*index = mImpl.assignSlot(newBuffer);
handleImageData(newBuffer);
*clientBuffer = newBuffer;
+
+ extractPixelFormatFromC2Buffer(buffer);
ALOGV("[%s] registered buffer %zu", mName, *index);
return OK;
}
@@ -1309,6 +1325,32 @@
return mImpl.numActiveSlots();
}
+bool FlexOutputBuffers::extractPixelFormatFromC2Buffer(const std::shared_ptr<C2Buffer> &buffer) {
+ if (buffer == nullptr) {
+ return false;
+ }
+ const C2BufferData &data = buffer->data();
+ // only extract the first pixel format in a metric session.
+ if (mPixelFormat != PIXEL_FORMAT_UNKNOWN || data.type() != C2BufferData::GRAPHIC
+ || data.graphicBlocks().empty()) {
+ return false;
+ }
+ const C2Handle *const handle = data.graphicBlocks().front().handle();
+ uint32_t pf = ExtractFormatFromCodec2GrallocHandle(handle);
+ if (pf == PIXEL_FORMAT_UNKNOWN) {
+ return false;
+ }
+ mPixelFormat = pf;
+ return true;
+}
+
+bool FlexOutputBuffers::resetPixelFormatIfApplicable() {
+ mPixelFormat = PIXEL_FORMAT_UNKNOWN;
+ return true;
+}
+
+uint32_t FlexOutputBuffers::getPixelFormatIfApplicable() { return mPixelFormat; }
+
// LinearOutputBuffers
void LinearOutputBuffers::flush(
diff --git a/media/codec2/sfplugin/CCodecBuffers.h b/media/codec2/sfplugin/CCodecBuffers.h
index 6335f13..a3754c6 100644
--- a/media/codec2/sfplugin/CCodecBuffers.h
+++ b/media/codec2/sfplugin/CCodecBuffers.h
@@ -81,6 +81,16 @@
*/
void handleImageData(const sp<Codec2Buffer> &buffer);
+ /**
+ * Get the first pixel format of a metric session.
+ */
+ virtual uint32_t getPixelFormatIfApplicable();
+
+ /**
+ * Reset the pixel format when a new metric session started.
+ */
+ virtual bool resetPixelFormatIfApplicable();
+
protected:
std::string mComponentName; ///< name of component for debugging
std::string mChannelName; ///< name of channel for debugging
@@ -938,12 +948,17 @@
size_t numActiveSlots() const final;
+ uint32_t getPixelFormatIfApplicable() override;
+
+ bool resetPixelFormatIfApplicable() override;
+
protected:
sp<Codec2Buffer> createNewBuffer() override;
private:
FlexBuffersImpl mImpl;
std::shared_ptr<LocalBufferPool> mLocalBufferPool;
+ uint32_t mPixelFormat;
};
class DummyInputBuffers : public InputBuffers {
@@ -1107,8 +1122,20 @@
*/
virtual std::function<sp<Codec2Buffer>()> getAlloc() = 0;
+ uint32_t getPixelFormatIfApplicable() override;
+
+ bool resetPixelFormatIfApplicable() override;
private:
FlexBuffersImpl mImpl;
+
+ uint32_t mPixelFormat;
+
+ /**
+ * extract pixel format from C2Buffer when register.
+ *
+ * \param buffer The C2Buffer used to extract pixel format.
+ */
+ bool extractPixelFormatFromC2Buffer(const std::shared_ptr<C2Buffer> &buffer);
};
class LinearOutputBuffers : public FlexOutputBuffers {
diff --git a/media/codec2/sfplugin/InputSurfaceWrapper.h b/media/codec2/sfplugin/InputSurfaceWrapper.h
index 44ba78a..a57c0f1 100644
--- a/media/codec2/sfplugin/InputSurfaceWrapper.h
+++ b/media/codec2/sfplugin/InputSurfaceWrapper.h
@@ -112,8 +112,14 @@
*/
virtual android_dataspace getDataspace() { return mDataSpace; }
+ /**
+ * Returns pixel format information from GraphicBufferSource.
+ */
+ virtual uint32_t getPixelFormat() { return mPixelFormat; }
+
protected:
android_dataspace mDataSpace;
+ uint32_t mPixelFormat;
};
} // namespace android
diff --git a/media/codec2/sfplugin/include/media/stagefright/CCodec.h b/media/codec2/sfplugin/include/media/stagefright/CCodec.h
index 13713bc..3b23470 100644
--- a/media/codec2/sfplugin/include/media/stagefright/CCodec.h
+++ b/media/codec2/sfplugin/include/media/stagefright/CCodec.h
@@ -205,6 +205,8 @@
Mutexed<std::unique_ptr<CCodecConfig>> mConfig;
Mutexed<std::list<std::unique_ptr<C2Work>>> mWorkDoneQueue;
+ sp<AMessage> mMetrics;
+
friend class CCodecCallbackImpl;
DISALLOW_EVIL_CONSTRUCTORS(CCodec);
diff --git a/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp b/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp
index 9004bcf..261fd05 100644
--- a/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp
+++ b/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp
@@ -621,8 +621,8 @@
uint8_t maxLvlChroma = colorRange == C2Color::RANGE_FULL ? 255 : 240;
#define CLIP3(min,v,max) (((v) < (min)) ? (min) : (((max) > (v)) ? (v) : (max)))
- for (size_t y = 0; y < src.height(); ++y) {
- for (size_t x = 0; x < src.width(); ++x) {
+ for (size_t y = 0; y < src.crop().height; ++y) {
+ for (size_t x = 0; x < src.crop().width; ++x) {
uint8_t r = *pRed;
uint8_t g = *pGreen;
uint8_t b = *pBlue;
diff --git a/media/codec2/sfplugin/utils/Codec2CommonUtils.cpp b/media/codec2/sfplugin/utils/Codec2CommonUtils.cpp
index 43533fd..7492cab 100644
--- a/media/codec2/sfplugin/utils/Codec2CommonUtils.cpp
+++ b/media/codec2/sfplugin/utils/Codec2CommonUtils.cpp
@@ -114,7 +114,6 @@
.usage = AHARDWAREBUFFER_USAGE_CPU_READ_RARELY |
AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN |
AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
- AHARDWAREBUFFER_USAGE_COMPOSER_OVERLAY |
AHARDWAREBUFFER_USAGE_VIDEO_ENCODE,
.stride = 0,
.rfu0 = 0,
diff --git a/media/codec2/vndk/C2AllocatorGralloc.cpp b/media/codec2/vndk/C2AllocatorGralloc.cpp
index 0803dc3..1ffa78f 100644
--- a/media/codec2/vndk/C2AllocatorGralloc.cpp
+++ b/media/codec2/vndk/C2AllocatorGralloc.cpp
@@ -188,6 +188,14 @@
return res;
}
+ static uint32_t getPixelFormat(const C2Handle *const handle) {
+ if (handle == nullptr) {
+ return 0;
+ }
+ const ExtraData *xd = GetExtraData(handle);
+ return xd->format;
+ }
+
static bool MigrateNativeHandle(
native_handle_t *handle,
uint32_t generation, uint64_t igbp_id, uint32_t igbp_slot) {
@@ -334,6 +342,10 @@
generation, igbp_id, igbp_slot);
}
+uint32_t ExtractFormatFromCodec2GrallocHandle(const C2Handle *const handle) {
+ return C2HandleGralloc::getPixelFormat(handle);
+}
+
bool MigrateNativeCodec2GrallocHandle(
native_handle_t *handle,
uint32_t generation, uint64_t igbp_id, uint32_t igbp_slot) {
diff --git a/media/codec2/vndk/include/C2AllocatorGralloc.h b/media/codec2/vndk/include/C2AllocatorGralloc.h
index 1da3e14..4b4a45d 100644
--- a/media/codec2/vndk/include/C2AllocatorGralloc.h
+++ b/media/codec2/vndk/include/C2AllocatorGralloc.h
@@ -46,6 +46,13 @@
uint32_t generation = 0, uint64_t igbp_id = 0, uint32_t igbp_slot = 0);
/**
+ * Extract pixel format from the extra data of gralloc handle.
+ *
+ * @return 0 when no valid pixel format exists.
+ */
+uint32_t ExtractFormatFromCodec2GrallocHandle(const C2Handle *const handle);
+
+/**
* When the gralloc handle is migrated to another bufferqueue, update
* bufferqueue information.
*
diff --git a/media/libaudioclient/tests/audiosystem_tests.cpp b/media/libaudioclient/tests/audiosystem_tests.cpp
index 45baa94..d9789f1 100644
--- a/media/libaudioclient/tests/audiosystem_tests.cpp
+++ b/media/libaudioclient/tests/audiosystem_tests.cpp
@@ -21,9 +21,9 @@
#include <set>
#include <gtest/gtest.h>
+#include <log/log.h>
#include <media/AidlConversionCppNdk.h>
#include <media/IAudioFlinger.h>
-#include <utils/Log.h>
#include "audio_test_utils.h"
@@ -277,23 +277,30 @@
GTEST_SKIP() << "No output devices returned by the audio system";
}
+ bool sourceFound = false, sinkFound = false;
for (const auto& port : ports) {
if (port.role == AUDIO_PORT_ROLE_SOURCE && port.type == AUDIO_PORT_TYPE_DEVICE) {
sourcePort = port;
+ sourceFound = true;
}
if (port.role == AUDIO_PORT_ROLE_SINK && port.type == AUDIO_PORT_TYPE_DEVICE &&
port.ext.device.type == AUDIO_DEVICE_OUT_SPEAKER) {
sinkPort = port;
+ sinkFound = true;
}
+ if (sourceFound && sinkFound) break;
+ }
+ if (!sourceFound || !sinkFound) {
+ GTEST_SKIP() << "No ports suitable for testing";
}
audioPatch.sources[0] = sourcePort.active_config;
audioPatch.sinks[0] = sinkPort.active_config;
status = AudioSystem::createAudioPatch(&audioPatch, &audioPatchHandle);
- EXPECT_EQ(OK, status) << "AudioSystem::createAudiopatch failed between source "
- << sourcePort.ext.device.address << " and sink "
- << sinkPort.ext.device.address;
+ EXPECT_EQ(OK, status) << "AudioSystem::createAudioPatch failed between source "
+ << audio_device_to_string(sourcePort.ext.device.type) << " and sink "
+ << audio_device_to_string(sinkPort.ext.device.type);
// verify that patch is established between source and the sink.
ASSERT_NO_FATAL_FAILURE(anyPatchContainsInputDevice(sourcePort.id, patchFound));
@@ -302,8 +309,8 @@
EXPECT_NE(AUDIO_PORT_HANDLE_NONE, audioPatchHandle);
status = AudioSystem::releaseAudioPatch(audioPatchHandle);
EXPECT_EQ(OK, status) << "AudioSystem::releaseAudioPatch failed between source "
- << sourcePort.ext.device.address << " and sink "
- << sinkPort.ext.device.address;
+ << audio_device_to_string(sourcePort.ext.device.type) << " and sink "
+ << audio_device_to_string(sinkPort.ext.device.type);
// verify that no patch is established between source and the sink after releaseAudioPatch.
ASSERT_NO_FATAL_FAILURE(anyPatchContainsInputDevice(sourcePort.id, patchFound));
@@ -608,28 +615,37 @@
android::media::audio::common::AudioPort GenerateUniqueDeviceAddress(
const android::media::audio::common::AudioPort& port) {
+ // Point-to-point connections do not use addresses.
+ static const std::set<std::string> kPointToPointConnections = {
+ AudioDeviceDescription::CONNECTION_ANALOG(), AudioDeviceDescription::CONNECTION_HDMI(),
+ AudioDeviceDescription::CONNECTION_HDMI_ARC(),
+ AudioDeviceDescription::CONNECTION_HDMI_EARC(),
+ AudioDeviceDescription::CONNECTION_SPDIF()};
static int nextId = 0;
using Tag = AudioDeviceAddress::Tag;
+ const auto& deviceDescription = port.ext.get<AudioPortExt::Tag::device>().device.type;
AudioDeviceAddress address;
- switch (suggestDeviceAddressTag(port.ext.get<AudioPortExt::Tag::device>().device.type)) {
- case Tag::id:
- address = AudioDeviceAddress::make<Tag::id>(std::to_string(++nextId));
- break;
- case Tag::mac:
- address = AudioDeviceAddress::make<Tag::mac>(
- std::vector<uint8_t>{1, 2, 3, 4, 5, static_cast<uint8_t>(++nextId & 0xff)});
- break;
- case Tag::ipv4:
- address = AudioDeviceAddress::make<Tag::ipv4>(
- std::vector<uint8_t>{192, 168, 0, static_cast<uint8_t>(++nextId & 0xff)});
- break;
- case Tag::ipv6:
- address = AudioDeviceAddress::make<Tag::ipv6>(std::vector<int32_t>{
- 0xfc00, 0x0123, 0x4567, 0x89ab, 0xcdef, 0, 0, ++nextId & 0xffff});
- break;
- case Tag::alsa:
- address = AudioDeviceAddress::make<Tag::alsa>(std::vector<int32_t>{1, ++nextId});
- break;
+ if (kPointToPointConnections.count(deviceDescription.connection) == 0) {
+ switch (suggestDeviceAddressTag(deviceDescription)) {
+ case Tag::id:
+ address = AudioDeviceAddress::make<Tag::id>(std::to_string(++nextId));
+ break;
+ case Tag::mac:
+ address = AudioDeviceAddress::make<Tag::mac>(
+ std::vector<uint8_t>{1, 2, 3, 4, 5, static_cast<uint8_t>(++nextId & 0xff)});
+ break;
+ case Tag::ipv4:
+ address = AudioDeviceAddress::make<Tag::ipv4>(
+ std::vector<uint8_t>{192, 168, 0, static_cast<uint8_t>(++nextId & 0xff)});
+ break;
+ case Tag::ipv6:
+ address = AudioDeviceAddress::make<Tag::ipv6>(std::vector<int32_t>{
+ 0xfc00, 0x0123, 0x4567, 0x89ab, 0xcdef, 0, 0, ++nextId & 0xffff});
+ break;
+ case Tag::alsa:
+ address = AudioDeviceAddress::make<Tag::alsa>(std::vector<int32_t>{1, ++nextId});
+ break;
+ }
}
android::media::audio::common::AudioPort result = port;
result.ext.get<AudioPortExt::Tag::device>().device.address = std::move(address);
@@ -689,3 +705,24 @@
EXPECT_EQ(AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, deviceState);
}
}
+
+class TestExecutionTracer : public ::testing::EmptyTestEventListener {
+ public:
+ void OnTestStart(const ::testing::TestInfo& test_info) override {
+ TraceTestState("Started", test_info);
+ }
+ void OnTestEnd(const ::testing::TestInfo& test_info) override {
+ TraceTestState("Completed", test_info);
+ }
+
+ private:
+ static void TraceTestState(const std::string& state, const ::testing::TestInfo& test_info) {
+ ALOGI("%s %s::%s", state.c_str(), test_info.test_suite_name(), test_info.name());
+ }
+};
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
+ return RUN_ALL_TESTS();
+}
diff --git a/media/libaudiofoundation/AudioContainers.cpp b/media/libaudiofoundation/AudioContainers.cpp
index 202a400..3034b9a 100644
--- a/media/libaudiofoundation/AudioContainers.cpp
+++ b/media/libaudiofoundation/AudioContainers.cpp
@@ -119,4 +119,15 @@
return ss.str();
}
+std::string dumpMixerBehaviors(const MixerBehaviorSet& mixerBehaviors) {
+ std::stringstream ss;
+ for (auto it = mixerBehaviors.begin(); it != mixerBehaviors.end(); ++it) {
+ if (it != mixerBehaviors.begin()) {
+ ss << ", ";
+ }
+ ss << (*it);
+ }
+ return ss.str();
+}
+
} // namespace android
diff --git a/media/libaudiofoundation/include/media/AudioContainers.h b/media/libaudiofoundation/include/media/AudioContainers.h
index 88dcee9..f22ee40 100644
--- a/media/libaudiofoundation/include/media/AudioContainers.h
+++ b/media/libaudiofoundation/include/media/AudioContainers.h
@@ -126,6 +126,8 @@
std::string dumpDeviceTypes(const DeviceTypeSet& deviceTypes);
+std::string dumpMixerBehaviors(const MixerBehaviorSet& mixerBehaviors);
+
/**
* Return human readable string for device types.
*/
diff --git a/media/libaudiohal/impl/DeviceHalAidl.cpp b/media/libaudiohal/impl/DeviceHalAidl.cpp
index 99e3565..835080f 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalAidl.cpp
@@ -42,6 +42,7 @@
using aidl::android::media::audio::common::AudioDevice;
using aidl::android::media::audio::common::AudioDeviceAddress;
using aidl::android::media::audio::common::AudioDeviceType;
+using aidl::android::media::audio::common::AudioFormatDescription;
using aidl::android::media::audio::common::AudioFormatType;
using aidl::android::media::audio::common::AudioInputFlags;
using aidl::android::media::audio::common::AudioIoFlags;
@@ -97,9 +98,15 @@
}
void setPortConfigFromConfig(AudioPortConfig* portConfig, const AudioConfig& config) {
- portConfig->sampleRate = Int{ .value = config.base.sampleRate };
- portConfig->channelMask = config.base.channelMask;
- portConfig->format = config.base.format;
+ if (config.base.sampleRate != 0) {
+ portConfig->sampleRate = Int{ .value = config.base.sampleRate };
+ }
+ if (config.base.channelMask != AudioChannelLayout{}) {
+ portConfig->channelMask = config.base.channelMask;
+ }
+ if (config.base.format != AudioFormatDescription{}) {
+ portConfig->format = config.base.format;
+ }
}
// Note: these converters are for types defined in different AIDL files. Although these
@@ -706,7 +713,11 @@
aidlPatch.sourcePortConfigIds.clear();
aidlPatch.sinkPortConfigIds.clear();
}
- ALOGD("%s: sources: %s, sinks: %s",
+ // The IDs will be found by 'fillPortConfigs', however the original 'aidlSources' and
+ // 'aidlSinks' will not be updated because 'setAudioPatch' only needs IDs. Here we log
+ // the source arguments, where only the audio configuration and device specifications
+ // are relevant.
+ ALOGD("%s: [disregard IDs] sources: %s, sinks: %s",
__func__, ::android::internal::ToString(aidlSources).c_str(),
::android::internal::ToString(aidlSinks).c_str());
auto fillPortConfigs = [&](
@@ -1032,11 +1043,12 @@
// There is not AIDL API defined for `prepareToDisconnectExternalDevice`.
// Call `setConnectedState` instead.
// TODO(b/279824103): call prepareToDisconnectExternalDevice when it is added.
- const status_t status = setConnectedState(port, false /*connected*/);
- if (status == NO_ERROR) {
+ if (const status_t status = setConnectedState(port, false /*connected*/); status == NO_ERROR) {
mDeviceDisconnectionNotified.insert(port->id);
}
- return status;
+ // Return that there was no error as otherwise the disconnection procedure will not be
+ // considered complete for upper layers, and 'setConnectedState' will not be called again.
+ return NO_ERROR;
}
status_t DeviceHalAidl::setConnectedState(const struct audio_port_v7 *port, bool connected) {
@@ -1069,10 +1081,14 @@
matchDevice.address = AudioDeviceAddress::make<AudioDeviceAddress::id>();
auto portsIt = findPort(matchDevice);
if (portsIt == mPorts.end()) {
- ALOGW("%s: device port for device %s is not found in the module %s",
- __func__, matchDevice.toString().c_str(), mInstance.c_str());
+ // Since 'setConnectedState' is called for all modules, it is normal when the device
+ // port not found in every one of them.
return BAD_VALUE;
+ } else {
+ ALOGD("%s: device port for device %s found in the module %s",
+ __func__, matchDevice.toString().c_str(), mInstance.c_str());
}
+ resetUnusedPatchesAndPortConfigs();
// Use the ID of the "template" port, use all the information from the provided port.
aidlPort.id = portsIt->first;
AudioPort connectedPort;
@@ -1083,20 +1099,32 @@
"%s: module %s, duplicate port ID received from HAL: %s, existing port: %s",
__func__, mInstance.c_str(), connectedPort.toString().c_str(),
it->second.toString().c_str());
+ mConnectedPorts[connectedPort.id] = false;
} else { // !connected
AudioDevice matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
auto portsIt = findPort(matchDevice);
if (portsIt == mPorts.end()) {
- ALOGW("%s: device port for device %s is not found in the module %s",
- __func__, matchDevice.toString().c_str(), mInstance.c_str());
+ // Since 'setConnectedState' is called for all modules, it is normal when the device
+ // port not found in every one of them.
return BAD_VALUE;
+ } else {
+ ALOGD("%s: device port for device %s found in the module %s",
+ __func__, matchDevice.toString().c_str(), mInstance.c_str());
}
- // Any streams opened on the external device must be closed by this time,
- // thus we can clean up patches and port configs that were created for them.
resetUnusedPatchesAndPortConfigs();
- RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->disconnectExternalDevice(
- portsIt->second.id)));
- mPorts.erase(portsIt);
+ // Streams are closed by AudioFlinger independently from device disconnections.
+ // It is possible that the stream has not been closed yet.
+ const int32_t portId = portsIt->second.id;
+ if (!isPortHeldByAStream(portId)) {
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+ mModule->disconnectExternalDevice(portId)));
+ mPorts.erase(portsIt);
+ mConnectedPorts.erase(portId);
+ } else {
+ ALOGD("%s: since device port ID %d is used by a stream, "
+ "external device disconnection postponed", __func__, portId);
+ mConnectedPorts[portId] = true;
+ }
}
return updateRoutes();
}
@@ -1104,6 +1132,7 @@
status_t DeviceHalAidl::setSimulateDeviceConnections(bool enabled) {
TIME_CHECK();
if (!mModule) return NO_INIT;
+ resetUnusedPatchesAndPortConfigs();
ModuleDebug debug{ .simulateDeviceConnections = enabled };
status_t status = statusTFromBinderStatus(mModule->setModuleDebug(debug));
// This is important to log as it affects HAL behavior.
@@ -1518,7 +1547,7 @@
}
RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(requestedPortConfig, &portConfigIt,
created));
- } else if (!flags.has_value()) {
+ } else if (portConfigIt == mPortConfigs.end() && !flags.has_value()) {
ALOGW("%s: mix port config for %s, handle %d not found in the module %s, "
"and was not created as flags are not specified",
__func__, config.toString().c_str(), ioHandle, mInstance.c_str());
@@ -1593,8 +1622,25 @@
} else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
return mPorts.find(mDefaultOutputPortId);
}
- return std::find_if(mPorts.begin(), mPorts.end(),
- [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
+ if (device.address.getTag() != AudioDeviceAddress::id ||
+ !device.address.get<AudioDeviceAddress::id>().empty()) {
+ return std::find_if(mPorts.begin(), mPorts.end(),
+ [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
+ }
+ // For connection w/o an address, two ports can be found: the template port,
+ // and a connected port (if exists). Make sure we return the connected port.
+ DeviceHalAidl::Ports::iterator portIt = mPorts.end();
+ for (auto it = mPorts.begin(); it != mPorts.end(); ++it) {
+ if (audioDeviceMatches(device, it->second)) {
+ if (mConnectedPorts.find(it->first) != mConnectedPorts.end()) {
+ return it;
+ } else {
+ // Will return 'it' if there is no connected port.
+ portIt = it;
+ }
+ }
+ }
+ return portIt;
}
DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(
@@ -1672,6 +1718,28 @@
p.ext.template get<Tag::mix>().handle == ioHandle; });
}
+bool DeviceHalAidl::isPortHeldByAStream(int32_t portId) {
+ // It is assumed that mStreams has already been cleaned up.
+ for (const auto& streamPair : mStreams) {
+ int32_t patchId = streamPair.second;
+ auto patchIt = mPatches.find(patchId);
+ if (patchIt == mPatches.end()) continue;
+ for (int32_t id : patchIt->second.sourcePortConfigIds) {
+ auto portConfigIt = mPortConfigs.find(id);
+ if (portConfigIt != mPortConfigs.end() && portConfigIt->second.portId == portId) {
+ return true;
+ }
+ }
+ for (int32_t id : patchIt->second.sinkPortConfigIds) {
+ auto portConfigIt = mPortConfigs.find(id);
+ if (portConfigIt != mPortConfigs.end() && portConfigIt->second.portId == portId) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
void DeviceHalAidl::resetPatch(int32_t patchId) {
if (auto it = mPatches.find(patchId); it != mPatches.end()) {
mPatches.erase(it);
@@ -1721,10 +1789,10 @@
// The assumption is that port configs are used to create patches
// (or to open streams, but that involves creation of patches, too). Thus,
// orphaned port configs can and should be reset.
- std::set<int32_t> portConfigIds;
+ std::map<int32_t, int32_t /*portID*/> portConfigIds;
std::transform(mPortConfigs.begin(), mPortConfigs.end(),
std::inserter(portConfigIds, portConfigIds.end()),
- [](const auto& pcPair) { return pcPair.first; });
+ [](const auto& pcPair) { return std::make_pair(pcPair.first, pcPair.second.portId); });
for (const auto& p : mPatches) {
for (int32_t id : p.second.sourcePortConfigIds) portConfigIds.erase(id);
for (int32_t id : p.second.sinkPortConfigIds) portConfigIds.erase(id);
@@ -1732,7 +1800,28 @@
for (int32_t id : mInitialPortConfigIds) {
portConfigIds.erase(id);
}
- for (int32_t id : portConfigIds) resetPortConfig(id);
+ std::set<int32_t> retryDeviceDisconnection;
+ for (const auto& portConfigAndIdPair : portConfigIds) {
+ resetPortConfig(portConfigAndIdPair.first);
+ if (const auto it = mConnectedPorts.find(portConfigAndIdPair.second);
+ it != mConnectedPorts.end() && it->second) {
+ retryDeviceDisconnection.insert(portConfigAndIdPair.second);
+ }
+ }
+ for (int32_t portId : retryDeviceDisconnection) {
+ if (!isPortHeldByAStream(portId)) {
+ TIME_CHECK();
+ if (auto status = mModule->disconnectExternalDevice(portId); status.isOk()) {
+ mPorts.erase(portId);
+ mConnectedPorts.erase(portId);
+ ALOGD("%s: executed postponed external device disconnection for port ID %d",
+ __func__, portId);
+ }
+ }
+ }
+ if (!retryDeviceDisconnection.empty()) {
+ updateRoutes();
+ }
}
status_t DeviceHalAidl::updateRoutes() {
diff --git a/media/libaudiohal/impl/DeviceHalAidl.h b/media/libaudiohal/impl/DeviceHalAidl.h
index 6b34bf4..6f45f1f 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.h
+++ b/media/libaudiohal/impl/DeviceHalAidl.h
@@ -191,6 +191,8 @@
Status status = Status::UNKNOWN;
MicrophoneInfoProvider::Info info;
};
+ // IDs of ports for connected external devices, and whether they are held by streams.
+ using ConnectedPorts = std::map<int32_t /*port ID*/, bool>;
using Patches = std::map<int32_t /*patch ID*/,
::aidl::android::hardware::audio::core::AudioPatch>;
using PortConfigs = std::map<int32_t /*port config ID*/,
@@ -261,6 +263,7 @@
const ::aidl::android::media::audio::common::AudioConfig& config,
const std::optional<::aidl::android::media::audio::common::AudioIoFlags>& flags,
int32_t ioHandle);
+ bool isPortHeldByAStream(int32_t portId);
status_t prepareToOpenStream(
int32_t aidlHandle,
const ::aidl::android::media::audio::common::AudioDevice& aidlDevice,
@@ -318,6 +321,7 @@
std::mutex mLock;
std::map<void*, Callbacks> mCallbacks GUARDED_BY(mLock);
std::set<audio_port_handle_t> mDeviceDisconnectionNotified;
+ ConnectedPorts mConnectedPorts;
};
} // namespace android
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
index 4e34fca..196b432 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
@@ -101,6 +101,8 @@
const void* pCmdData __unused, uint32_t* replySize,
void* pReplyData) {
if (!replySize || *replySize < sizeof(int) || !pReplyData) {
+ ALOGE("%s parameter invalid, replySize %s pReplyData %p", __func__,
+ numericPointerToString(replySize).c_str(), pReplyData);
return BAD_VALUE;
}
@@ -110,8 +112,10 @@
status_t EffectConversionHelperAidl::handleSetParameter(uint32_t cmdSize, const void* pCmdData,
uint32_t* replySize, void* pReplyData) {
- if (cmdSize < sizeof(effect_param_t) || !pCmdData || !replySize ||
- *replySize < sizeof(int) || !pReplyData) {
+ if (cmdSize < sizeof(effect_param_t) || !pCmdData || !replySize || *replySize < sizeof(int) ||
+ !pReplyData) {
+ ALOGE("%s parameter invalid, cmdSize %u pCmdData %p replySize %s pReplyData %p", __func__,
+ cmdSize, pCmdData, numericPointerToString(replySize).c_str(), pReplyData);
return BAD_VALUE;
}
@@ -130,8 +134,8 @@
status_t EffectConversionHelperAidl::handleGetParameter(uint32_t cmdSize, const void* pCmdData,
uint32_t* replySize, void* pReplyData) {
if (cmdSize < sizeof(effect_param_t) || !pCmdData || !replySize || !pReplyData) {
- ALOGE("%s illegal cmdSize %u pCmdData %p replySize %p replyData %p", __func__, cmdSize,
- pCmdData, replySize, pReplyData);
+ ALOGE("%s illegal cmdSize %u pCmdData %p replySize %s replyData %p", __func__, cmdSize,
+ pCmdData, numericPointerToString(replySize).c_str(), pReplyData);
return BAD_VALUE;
}
@@ -158,28 +162,29 @@
uint32_t* replySize, void* pReplyData) {
if (!replySize || *replySize != sizeof(int) || !pReplyData ||
cmdSize != sizeof(effect_config_t)) {
- ALOGE("%s parameter invalid %u %p %p %p", __func__, cmdSize, pCmdData, replySize,
- pReplyData);
+ ALOGE("%s parameter invalid, cmdSize %u pCmdData %p replySize %s pReplyData %p", __func__,
+ cmdSize, pCmdData, numericPointerToString(replySize).c_str(), pReplyData);
return BAD_VALUE;
}
effect_config_t* config = (effect_config_t*)pCmdData;
Parameter::Common common = {
+ .session = mCommon.session,
+ .ioHandle = mCommon.ioHandle,
.input =
VALUE_OR_RETURN_STATUS(::aidl::android::legacy2aidl_buffer_config_t_AudioConfig(
config->inputCfg, mIsInputStream)),
.output =
VALUE_OR_RETURN_STATUS(::aidl::android::legacy2aidl_buffer_config_t_AudioConfig(
- config->outputCfg, mIsInputStream)),
- .session = mCommon.session,
- .ioHandle = mCommon.ioHandle};
+ config->outputCfg, mIsInputStream))};
State state;
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getState(&state)));
// in case of buffer/ioHandle re-configure for an opened effect, close it and re-open
if (state != State::INIT && mCommon != common) {
- ALOGI("%s at state %s, closing effect", __func__,
- android::internal::ToString(state).c_str());
+ ALOGI("%s at state %s, common parameter change from %s to %s, closing effect", __func__,
+ android::internal::ToString(state).c_str(), mCommon.toString().c_str(),
+ common.toString().c_str());
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->close()));
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getState(&state)));
mStatusQ.reset();
@@ -224,13 +229,19 @@
const void* pCmdData __unused,
uint32_t* replySize, void* pReplyData) {
if (!replySize || *replySize != sizeof(effect_config_t) || !pReplyData) {
- ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
+ ALOGE("%s parameter invalid, replySize %s pReplyData %p", __func__,
+ numericPointerToString(replySize).c_str(), pReplyData);
return BAD_VALUE;
}
Parameter param;
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(
Parameter::Id::make<Parameter::Id::commonTag>(Parameter::common), ¶m)));
+ if (param.getTag() != Parameter::common) {
+ *replySize = 0;
+ ALOGW("%s no valid common tag return from HAL: %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
const auto& common = param.get<Parameter::common>();
effect_config_t* pConfig = (effect_config_t*)pReplyData;
@@ -244,41 +255,44 @@
status_t EffectConversionHelperAidl::handleReset(uint32_t cmdSize __unused,
const void* pCmdData __unused, uint32_t* replySize,
void* pReplyData) {
- if (!replySize || !pReplyData) {
- ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
+ if (!replySize || *replySize != sizeof(int) || !pReplyData) {
+ ALOGE("%s parameter invalid, replySize %s pReplyData %p", __func__,
+ numericPointerToString(replySize).c_str(), pReplyData);
return BAD_VALUE;
}
- return statusTFromBinderStatus(mEffect->command(CommandId::RESET));
+ return *(int *)pReplyData = statusTFromBinderStatus(mEffect->command(CommandId::RESET));
}
status_t EffectConversionHelperAidl::handleEnable(uint32_t cmdSize __unused,
const void* pCmdData __unused,
uint32_t* replySize, void* pReplyData) {
- if (!replySize || !pReplyData) {
- ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
+ if (!replySize || *replySize != sizeof(int) || !pReplyData) {
+ ALOGE("%s parameter invalid, replySize %s pReplyData %p", __func__,
+ numericPointerToString(replySize).c_str(), pReplyData);
return BAD_VALUE;
}
- return statusTFromBinderStatus(mEffect->command(CommandId::START));
+ return *(int *)pReplyData = statusTFromBinderStatus(mEffect->command(CommandId::START));
}
status_t EffectConversionHelperAidl::handleDisable(uint32_t cmdSize __unused,
const void* pCmdData __unused,
uint32_t* replySize, void* pReplyData) {
- if (!replySize || !pReplyData) {
- ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
+ if (!replySize || *replySize != sizeof(int) || !pReplyData) {
+ ALOGE("%s parameter invalid, replySize %s pReplyData %p", __func__,
+ numericPointerToString(replySize).c_str(), pReplyData);
return BAD_VALUE;
}
- return statusTFromBinderStatus(mEffect->command(CommandId::STOP));
+ return *(int *)pReplyData = statusTFromBinderStatus(mEffect->command(CommandId::STOP));
}
status_t EffectConversionHelperAidl::handleSetAudioSource(uint32_t cmdSize, const void* pCmdData,
uint32_t* replySize, void* pReplyData) {
if (cmdSize != sizeof(uint32_t) || !pCmdData || !replySize || !pReplyData) {
- ALOGE("%s parameter invalid %u %p %p %p", __func__, cmdSize, pCmdData, replySize,
- pReplyData);
+ ALOGE("%s parameter invalid, cmdSize %u pCmdData %p replySize %s pReplyData %p", __func__,
+ cmdSize, pCmdData, numericPointerToString(replySize).c_str(), pReplyData);
return BAD_VALUE;
}
if (!getDescriptor().common.flags.audioSourceIndication) {
@@ -297,8 +311,8 @@
status_t EffectConversionHelperAidl::handleSetAudioMode(uint32_t cmdSize, const void* pCmdData,
uint32_t* replySize, void* pReplyData) {
if (cmdSize != sizeof(uint32_t) || !pCmdData || !replySize || !pReplyData) {
- ALOGE("%s parameter invalid %u %p %p %p", __func__, cmdSize, pCmdData, replySize,
- pReplyData);
+ ALOGE("%s parameter invalid, cmdSize %u pCmdData %p replySize %s pReplyData %p", __func__,
+ cmdSize, pCmdData, numericPointerToString(replySize).c_str(), pReplyData);
return BAD_VALUE;
}
if (!getDescriptor().common.flags.audioModeIndication) {
@@ -316,8 +330,8 @@
status_t EffectConversionHelperAidl::handleSetDevice(uint32_t cmdSize, const void* pCmdData,
uint32_t* replySize, void* pReplyData) {
if (cmdSize != sizeof(uint32_t) || !pCmdData || !replySize || !pReplyData) {
- ALOGE("%s parameter invalid %u %p %p %p", __func__, cmdSize, pCmdData, replySize,
- pReplyData);
+ ALOGE("%s parameter invalid, cmdSize %u pCmdData %p replySize %s pReplyData %p", __func__,
+ cmdSize, pCmdData, numericPointerToString(replySize).c_str(), pReplyData);
return BAD_VALUE;
}
if (!getDescriptor().common.flags.deviceIndication) {
@@ -353,14 +367,28 @@
}
constexpr uint32_t unityGain = 1 << 24;
- Parameter::VolumeStereo volume = {.left = (float)(*(uint32_t*)pCmdData) / unityGain,
- .right = (float)(*(uint32_t*)pCmdData + 1) / unityGain};
+ uint32_t vl = *(uint32_t*)pCmdData;
+ uint32_t vr = *((uint32_t*)pCmdData + 1);
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
- mEffect->setParameter(Parameter::make<Parameter::volumeStereo>(volume))));
+ mEffect->setParameter(Parameter::make<Parameter::volumeStereo>(Parameter::VolumeStereo(
+ {.left = (float)vl / unityGain, .right = (float)vr / unityGain})))));
- // write unity gain back if volume was successfully set
+ // get volume from effect and set if changed, return the volume in command if HAL not return
+ // correct parameter.
+ Parameter::Id id = Parameter::Id::make<Parameter::Id::commonTag>(Parameter::volumeStereo);
+ Parameter volParam;
+ const status_t getParamStatus = statusTFromBinderStatus(mEffect->getParameter(id, &volParam));
+ if (getParamStatus != OK || volParam.getTag() != Parameter::volumeStereo) {
+ ALOGW("%s no valid volume return from HAL, status %d: %s, return volume in command",
+ __func__, getParamStatus, volParam.toString().c_str());
+ } else {
+ Parameter::VolumeStereo appliedVolume = volParam.get<Parameter::volumeStereo>();
+ vl = (uint32_t)(appliedVolume.left * unityGain);
+ vr = (uint32_t)(appliedVolume.right * unityGain);
+ }
+
if (replySize && *replySize == 2 * sizeof(uint32_t) && pReplyData) {
- constexpr uint32_t vol_ret[2] = {unityGain, unityGain};
+ uint32_t vol_ret[2] = {vl, vr};
memcpy(pReplyData, vol_ret, sizeof(vol_ret));
}
return OK;
@@ -369,8 +397,8 @@
status_t EffectConversionHelperAidl::handleSetOffload(uint32_t cmdSize, const void* pCmdData,
uint32_t* replySize, void* pReplyData) {
if (cmdSize < sizeof(effect_offload_param_t) || !pCmdData || !replySize || !pReplyData) {
- ALOGE("%s parameter invalid %u %p %p %p", __func__, cmdSize, pCmdData, replySize,
- pReplyData);
+ ALOGE("%s parameter invalid, cmdSize %u pCmdData %p replySize %s pReplyData %p", __func__,
+ cmdSize, pCmdData, numericPointerToString(replySize).c_str(), pReplyData);
return BAD_VALUE;
}
effect_offload_param_t* offload = (effect_offload_param_t*)pCmdData;
@@ -402,7 +430,8 @@
uint32_t* replySize,
void* pReplyData) {
if (!replySize || !pReplyData) {
- ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
+ ALOGE("%s parameter invalid replySize %s pReplyData %p", __func__,
+ numericPointerToString(replySize).c_str(), pReplyData);
return BAD_VALUE;
}
@@ -422,7 +451,8 @@
uint32_t* replySize,
void* pReplyData) {
if (!replySize || !pReplyData) {
- ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
+ ALOGE("%s parameter invalid, replySize %s pReplyData %p", __func__,
+ numericPointerToString(replySize).c_str(), pReplyData);
return BAD_VALUE;
}
@@ -447,8 +477,9 @@
efGroup);
status = (status == OK) ? BAD_VALUE : status;
}
- } else if (isBypassing()) {
- // for effect with bypass (no processing) flag, it's okay to not have statusQ
+ } else if (isBypassingOrTunnel()) {
+ // for effect with bypass (no processing) or offloadIndication flag, it's okay to not have
+ // statusQ
return OK;
}
@@ -456,12 +487,22 @@
return status;
}
+bool EffectConversionHelperAidl::isBypassingOrTunnel() const {
+ return isBypassing() || isTunnel();
+}
+
bool EffectConversionHelperAidl::isBypassing() const {
return mEffect &&
(mDesc.common.flags.bypass ||
(mIsProxyEffect && std::static_pointer_cast<EffectProxy>(mEffect)->isBypassing()));
}
+bool EffectConversionHelperAidl::isTunnel() const {
+ return mEffect &&
+ (mDesc.common.flags.hwAcceleratorMode == Flags::HardwareAccelerator::TUNNEL ||
+ (mIsProxyEffect && std::static_pointer_cast<EffectProxy>(mEffect)->isTunnel()));
+}
+
Descriptor EffectConversionHelperAidl::getDescriptor() const {
if (!mIsProxyEffect) {
return mDesc;
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.h b/media/libaudiohal/impl/EffectConversionHelperAidl.h
index 85e877e..5db334c 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.h
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.h
@@ -41,7 +41,10 @@
std::shared_ptr<DataMQ> getInputMQ() { return mInputQ; }
std::shared_ptr<DataMQ> getOutputMQ() { return mOutputQ; }
std::shared_ptr<android::hardware::EventFlag> getEventFlagGroup() { return mEfGroup; }
+
bool isBypassing() const;
+ bool isTunnel() const;
+ bool isBypassingOrTunnel() const;
::aidl::android::hardware::audio::effect::Descriptor getDescriptor() const;
@@ -72,6 +75,11 @@
static constexpr int kDefaultframeCount = 0x100;
+ template <typename T, typename = std::enable_if_t<std::is_arithmetic_v<T>>>
+ static inline std::string numericPointerToString(T* pt) {
+ return pt ? std::to_string(*pt) : "nullptr";
+ }
+
using AudioChannelLayout = aidl::android::media::audio::common::AudioChannelLayout;
const aidl::android::media::audio::common::AudioConfig kDefaultAudioConfig = {
.base = {.sampleRate = 44100,
diff --git a/media/libaudiohal/impl/EffectHalAidl.cpp b/media/libaudiohal/impl/EffectHalAidl.cpp
index 642d352..f26444c 100644
--- a/media/libaudiohal/impl/EffectHalAidl.cpp
+++ b/media/libaudiohal/impl/EffectHalAidl.cpp
@@ -173,7 +173,7 @@
mConversion->isBypassing()
? "bypassing"
: aidl::android::hardware::audio::effect::toString(state).c_str());
- return OK;
+ return -ENODATA;
}
auto statusQ = mConversion->getStatusMQ();
diff --git a/media/libaudiohal/impl/EffectProxy.cpp b/media/libaudiohal/impl/EffectProxy.cpp
index 7b5e195..1099b6d 100644
--- a/media/libaudiohal/impl/EffectProxy.cpp
+++ b/media/libaudiohal/impl/EffectProxy.cpp
@@ -278,6 +278,11 @@
return mSubEffects[mActiveSubIdx].descriptor.common.flags.bypass;
}
+bool EffectProxy::isTunnel() const {
+ return mSubEffects[mActiveSubIdx].descriptor.common.flags.hwAcceleratorMode ==
+ Flags::HardwareAccelerator::TUNNEL;
+}
+
binder_status_t EffectProxy::dump(int fd, const char** args, uint32_t numArgs) {
const std::string dumpString = toString();
write(fd, dumpString.c_str(), dumpString.size());
diff --git a/media/libaudiohal/impl/EffectProxy.h b/media/libaudiohal/impl/EffectProxy.h
index 18e1567..0d62642 100644
--- a/media/libaudiohal/impl/EffectProxy.h
+++ b/media/libaudiohal/impl/EffectProxy.h
@@ -98,6 +98,7 @@
}
bool isBypassing() const;
+ bool isTunnel() const;
// call dump for all sub-effects
binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
diff --git a/media/libaudiohal/impl/StreamHalAidl.cpp b/media/libaudiohal/impl/StreamHalAidl.cpp
index f9aea37..c058386 100644
--- a/media/libaudiohal/impl/StreamHalAidl.cpp
+++ b/media/libaudiohal/impl/StreamHalAidl.cpp
@@ -840,7 +840,7 @@
parameters, String8(AudioParameter::keyOffloadCodecDelaySamples),
[&](int value) {
// The legacy keys are misnamed, the value is in frames.
- return value > 0 ? mOffloadMetadata.delayFrames = value, OK : BAD_VALUE;
+ return value >= 0 ? mOffloadMetadata.delayFrames = value, OK : BAD_VALUE;
}))) {
updateMetadata = true;
}
@@ -848,7 +848,7 @@
parameters, String8(AudioParameter::keyOffloadCodecPaddingSamples),
[&](int value) {
// The legacy keys are misnamed, the value is in frames.
- return value > 0 ? mOffloadMetadata.paddingFrames = value, OK : BAD_VALUE;
+ return value >= 0 ? mOffloadMetadata.paddingFrames = value, OK : BAD_VALUE;
}))) {
updateMetadata = true;
}
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.cpp
index 89f8b83..f77c093 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.cpp
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.cpp
@@ -227,7 +227,7 @@
RETURN_IF_ERROR(param.readFromValue(&enable));
return DynamicsProcessing::ChannelConfig(
- {.enable = VALUE_OR_RETURN(convertIntegral<bool>(enable)), .channel = channel});
+ {.channel = channel, .enable = VALUE_OR_RETURN(convertIntegral<bool>(enable))});
}
ConversionResult<DynamicsProcessing::EqBandConfig>
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index df64676..1a37622 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -17,7 +17,7 @@
#ifndef LVM_FLOAT
typedef float LVM_FLOAT;
#endif
-#define LOG_TAG "Bundle"
+#define LOG_TAG "EffectBundle"
#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array)[0])
//#define LOG_NDEBUG 0
@@ -1191,11 +1191,13 @@
// 0 if the configuration is supported
//----------------------------------------------------------------------------
int VirtualizerIsDeviceSupported(audio_devices_t deviceType) {
+ ALOGV("%s: deviceType:%#x", __func__, deviceType);
switch (deviceType) {
case AUDIO_DEVICE_OUT_WIRED_HEADSET:
case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
case AUDIO_DEVICE_OUT_USB_HEADSET:
+ case AUDIO_DEVICE_OUT_BLE_HEADSET:
// case AUDIO_DEVICE_OUT_USB_DEVICE: // For USB testing of the virtualizer only.
return 0;
default:
@@ -3372,10 +3374,10 @@
if (pContext->EffectType == LVM_BASS_BOOST) {
if ((device == AUDIO_DEVICE_OUT_SPEAKER) ||
(device == AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT) ||
- (device == AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)) {
- ALOGV("\tEFFECT_CMD_SET_DEVICE device is invalid for LVM_BASS_BOOST %d",
- *(int32_t*)pCmdData);
- ALOGV("\tEFFECT_CMD_SET_DEVICE temporary disable LVM_BAS_BOOST");
+ device == AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER ||
+ device == AUDIO_DEVICE_OUT_BLE_SPEAKER) {
+ ALOGV("%s: EFFECT_CMD_SET_DEVICE device %#x is invalid for LVM_BASS_BOOST",
+ __func__, device);
// If a device doesn't support bassboost the effect must be temporarily disabled
// the effect must still report its original state as this can only be changed
diff --git a/media/libmedia/include/media/mediametadataretriever.h b/media/libmedia/include/media/mediametadataretriever.h
index fba1a30..9074574 100644
--- a/media/libmedia/include/media/mediametadataretriever.h
+++ b/media/libmedia/include/media/mediametadataretriever.h
@@ -96,13 +96,19 @@
status_t setDataSource(
const sp<IDataSource>& dataSource, const char *mime = NULL);
sp<IMemory> getFrameAtTime(int64_t timeUs, int option,
- int colorFormat = HAL_PIXEL_FORMAT_RGB_565, bool metaOnly = false);
+ int colorFormat, bool metaOnly = false);
+ sp<IMemory> getFrameAtTime(int64_t timeUs, int option,
+ bool metaOnly = false);
sp<IMemory> getImageAtIndex(int index,
- int colorFormat = HAL_PIXEL_FORMAT_RGB_565, bool metaOnly = false, bool thumbnail = false);
+ int colorFormat, bool metaOnly = false, bool thumbnail = false);
+ sp<IMemory> getImageAtIndex(int index,
+ bool metaOnly = false, bool thumbnail = false);
sp<IMemory> getImageRectAtIndex(
int index, int colorFormat, int left, int top, int right, int bottom);
sp<IMemory> getFrameAtIndex(
- int index, int colorFormat = HAL_PIXEL_FORMAT_RGB_565, bool metaOnly = false);
+ int index, int colorFormat, bool metaOnly = false);
+ sp<IMemory> getFrameAtIndex(
+ int index, bool metaOnly = false);
sp<IMemory> extractAlbumArt();
const char* extractMetadata(int keyCode);
diff --git a/media/libmedia/mediametadataretriever.cpp b/media/libmedia/mediametadataretriever.cpp
index 40fd022..9731ea4 100644
--- a/media/libmedia/mediametadataretriever.cpp
+++ b/media/libmedia/mediametadataretriever.cpp
@@ -138,6 +138,11 @@
}
sp<IMemory> MediaMetadataRetriever::getFrameAtTime(
+ int64_t timeUs, int option, bool metaOnly) {
+ return getFrameAtTime(timeUs, option, HAL_PIXEL_FORMAT_RGB_565, metaOnly);
+}
+
+sp<IMemory> MediaMetadataRetriever::getFrameAtTime(
int64_t timeUs, int option, int colorFormat, bool metaOnly)
{
ALOGV("getFrameAtTime: time(%" PRId64 " us) option(%d) colorFormat(%d) metaOnly(%d)",
@@ -151,6 +156,11 @@
}
sp<IMemory> MediaMetadataRetriever::getImageAtIndex(
+ int index, bool metaOnly, bool thumbnail) {
+ return getImageAtIndex(index, HAL_PIXEL_FORMAT_RGB_565, metaOnly, thumbnail);
+}
+
+sp<IMemory> MediaMetadataRetriever::getImageAtIndex(
int index, int colorFormat, bool metaOnly, bool thumbnail) {
ALOGV("getImageAtIndex: index(%d) colorFormat(%d) metaOnly(%d) thumbnail(%d)",
index, colorFormat, metaOnly, thumbnail);
@@ -176,6 +186,11 @@
}
sp<IMemory> MediaMetadataRetriever::getFrameAtIndex(
+ int index, bool metaOnly) {
+ return getFrameAtIndex(index, HAL_PIXEL_FORMAT_RGB_565, metaOnly);
+}
+
+sp<IMemory> MediaMetadataRetriever::getFrameAtIndex(
int index, int colorFormat, bool metaOnly) {
ALOGV("getFrameAtIndex: index(%d), colorFormat(%d) metaOnly(%d)",
index, colorFormat, metaOnly);
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 2223f24..cf29a25 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -1594,6 +1594,15 @@
if (desiredRenderTimeNs < nowNs) {
desiredRenderTimeNs = nowNs;
}
+
+ // If the render time is more than a second from now, then pretend the frame is supposed to be
+ // rendered immediately, because that's what SurfaceFlinger heuristics will do. This is a tight
+ // coupling, but is really the only way to optimize away unnecessary present fence checks in
+ // processRenderedFrames.
+ if (desiredRenderTimeNs > nowNs + 1*1000*1000*1000LL) {
+ desiredRenderTimeNs = nowNs;
+ }
+
// We've just queued a frame to the surface, so keep track of it and later check to see if it is
// actually rendered.
TrackedFrame frame;
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index d80cfa6..6765a6f 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -785,6 +785,7 @@
kWhatOutputBuffersChanged = 'outC',
kWhatFirstTunnelFrameReady = 'ftfR',
kWhatPollForRenderedBuffers = 'plrb',
+ kWhatMetricsUpdated = 'mtru',
};
class CryptoAsyncCallback : public CryptoAsync::CryptoAsyncCallback {
@@ -882,6 +883,7 @@
virtual void onOutputFramesRendered(const std::list<RenderedFrameInfo> &done) override;
virtual void onOutputBuffersChanged() override;
virtual void onFirstTunnelFrameReady() override;
+ virtual void onMetricsUpdated(const sp<AMessage> &updatedMetrics) override;
private:
const sp<AMessage> mNotify;
};
@@ -1008,6 +1010,13 @@
notify->post();
}
+void CodecCallback::onMetricsUpdated(const sp<AMessage> &updatedMetrics) {
+ sp<AMessage> notify(mNotify->dup());
+ notify->setInt32("what", kWhatMetricsUpdated);
+ notify->setMessage("updated-metrics", updatedMetrics);
+ notify->post();
+}
+
static MediaResourceSubType toMediaResourceSubType(MediaCodec::Domain domain) {
switch (domain) {
case MediaCodec::DOMAIN_VIDEO: return MediaResourceSubType::kVideoCodec;
@@ -1792,23 +1801,21 @@
mFramesInput++;
}
- const int64_t nowNs = systemTime(SYSTEM_TIME_MONOTONIC);
- BufferFlightTiming_t startdata = { presentationUs, nowNs };
+ // mutex access to mBuffersInFlight and other stats
+ Mutex::Autolock al(mLatencyLock);
- {
- // mutex access to mBuffersInFlight and other stats
- Mutex::Autolock al(mLatencyLock);
-
-
- // XXX: we *could* make sure that the time is later than the end of queue
- // as part of a consistency check...
+ // XXX: we *could* make sure that the time is later than the end of queue
+ // as part of a consistency check...
+ if (!mTunneled) {
+ const int64_t nowNs = systemTime(SYSTEM_TIME_MONOTONIC);
+ BufferFlightTiming_t startdata = { presentationUs, nowNs };
mBuffersInFlight.push_back(startdata);
-
- if (mIsLowLatencyModeOn && mIndexOfFirstFrameWhenLowLatencyOn < 0) {
- mIndexOfFirstFrameWhenLowLatencyOn = mInputBufferCounter;
- }
- ++mInputBufferCounter;
}
+
+ if (mIsLowLatencyModeOn && mIndexOfFirstFrameWhenLowLatencyOn < 0) {
+ mIndexOfFirstFrameWhenLowLatencyOn = mInputBufferCounter;
+ }
+ ++mInputBufferCounter;
}
// when we get a buffer back from the codec
@@ -4382,6 +4389,49 @@
break;
}
+ case kWhatMetricsUpdated:
+ {
+ sp<AMessage> updatedMetrics;
+ CHECK(msg->findMessage("updated-metrics", &updatedMetrics));
+
+ size_t numEntries = updatedMetrics->countEntries();
+ AMessage::Type type;
+ for (size_t i = 0; i < numEntries; ++i) {
+ const char *name = updatedMetrics->getEntryNameAt(i, &type);
+ AMessage::ItemData itemData = updatedMetrics->getEntryAt(i);
+ switch (type) {
+ case AMessage::kTypeInt32: {
+ int32_t metricValue;
+ itemData.find(&metricValue);
+ mediametrics_setInt32(mMetricsHandle, name, metricValue);
+ break;
+ }
+ case AMessage::kTypeInt64: {
+ int64_t metricValue;
+ itemData.find(&metricValue);
+ mediametrics_setInt64(mMetricsHandle, name, metricValue);
+ break;
+ }
+ case AMessage::kTypeDouble: {
+ double metricValue;
+ itemData.find(&metricValue);
+ mediametrics_setDouble(mMetricsHandle, name, metricValue);
+ break;
+ }
+ case AMessage::kTypeString: {
+ AString metricValue;
+ itemData.find(&metricValue);
+ mediametrics_setCString(mMetricsHandle, name, metricValue.c_str());
+ break;
+ }
+ // ToDo: add support for other types
+ default:
+ ALOGW("Updated metrics type not supported.");
+ }
+ }
+ break;
+ }
+
case kWhatEOS:
{
// We already notify the client of this by using the
diff --git a/media/libstagefright/VideoRenderQualityTracker.cpp b/media/libstagefright/VideoRenderQualityTracker.cpp
index e920bd1..90d5405 100644
--- a/media/libstagefright/VideoRenderQualityTracker.cpp
+++ b/media/libstagefright/VideoRenderQualityTracker.cpp
@@ -15,7 +15,11 @@
*/
#define LOG_TAG "VideoRenderQualityTracker"
+#define ATRACE_TAG ATRACE_TAG_VIDEO
+
#include <utils/Log.h>
+#include <utils/Trace.h>
+#include <utils/Mutex.h>
#include <media/stagefright/VideoRenderQualityTracker.h>
@@ -25,8 +29,10 @@
#include <stdio.h>
#include <sys/time.h>
+#include <android-base/macros.h>
#include <android-base/parsebool.h>
#include <android-base/parseint.h>
+#include <android-base/properties.h>
namespace android {
@@ -38,6 +44,7 @@
typedef VideoRenderQualityTracker::Configuration::GetServerConfigurableFlagFn
GetServerConfigurableFlagFn;
+typedef VideoRenderQualityTracker::TraceTriggerFn TraceTriggerFn;
static void getServerConfigurableFlag(GetServerConfigurableFlagFn getServerConfigurableFlagFn,
char const *flagNameSuffix, bool *value) {
@@ -149,6 +156,10 @@
getFlag(judderEventMax, "judder_event_max");
getFlag(judderEventDetailsMax, "judder_event_details_max");
getFlag(judderEventDistanceToleranceMs, "judder_event_distance_tolerance_ms");
+ getFlag(traceTriggerEnabled, "trace_trigger_enabled");
+ getFlag(traceTriggerThrottleMs, "trace_trigger_throttle_ms");
+ getFlag(traceMinFreezeDurationMs, "trace_minimum_freeze_duration_ms");
+ getFlag(traceMaxFreezeDurationMs, "trace_maximum_freeze_duration_ms");
#undef getFlag
return c;
}
@@ -186,15 +197,25 @@
judderEventMax = 0; // enabled only when debugging
judderEventDetailsMax = 20;
judderEventDistanceToleranceMs = 5000; // lump judder occurrences together when 5s or less
+
+ // Perfetto trigger configuration.
+ traceTriggerEnabled = android::base::GetProperty(
+ "ro.build.type", "user") != "user"; // Enabled for non-user builds for debugging.
+ traceTriggerThrottleMs = 5 * 60 * 1000; // 5 mins.
+ traceMinFreezeDurationMs = 400;
+ traceMaxFreezeDurationMs = 1500;
}
-VideoRenderQualityTracker::VideoRenderQualityTracker() : mConfiguration(Configuration()) {
+VideoRenderQualityTracker::VideoRenderQualityTracker()
+ : mConfiguration(Configuration()), mTraceTriggerFn(triggerTrace) {
configureHistograms(mMetrics, mConfiguration);
clear();
}
-VideoRenderQualityTracker::VideoRenderQualityTracker(const Configuration &configuration) :
- mConfiguration(configuration) {
+VideoRenderQualityTracker::VideoRenderQualityTracker(const Configuration &configuration,
+ const TraceTriggerFn traceTriggerFn)
+ : mConfiguration(configuration),
+ mTraceTriggerFn(traceTriggerFn == nullptr ? triggerTrace : traceTriggerFn) {
configureHistograms(mMetrics, mConfiguration);
clear();
}
@@ -231,6 +252,11 @@
resetIfDiscontinuity(contentTimeUs, -1);
+ if (mTraceFrameSkippedToken == -1) {
+ mTraceFrameSkippedToken = contentTimeUs;
+ ATRACE_ASYNC_BEGIN("Video frame(s) skipped", mTraceFrameSkippedToken);
+ }
+
// Frames skipped at the end of playback shouldn't be counted as skipped frames, since the
// app could be terminating the playback. The pending count will be added to the metrics if and
// when the next frame is rendered.
@@ -261,11 +287,25 @@
return;
}
+ if (mTraceFrameSkippedToken != -1) {
+ ATRACE_ASYNC_END("Video frame(s) skipped", mTraceFrameSkippedToken);
+ mTraceFrameSkippedToken = -1;
+ }
+
int64_t actualRenderTimeUs = actualRenderTimeNs / 1000;
if (mLastRenderTimeUs != -1) {
- mRenderDurationMs += (actualRenderTimeUs - mLastRenderTimeUs) / 1000;
+ int64_t frameRenderDurationMs = (actualRenderTimeUs - mLastRenderTimeUs) / 1000;
+ mRenderDurationMs += frameRenderDurationMs;
+ if (mConfiguration.traceTriggerEnabled
+ // Threshold for visible video freeze.
+ && frameRenderDurationMs >= mConfiguration.traceMinFreezeDurationMs
+ // Threshold for removing long render durations which could be video pause.
+ && frameRenderDurationMs < mConfiguration.traceMaxFreezeDurationMs) {
+ triggerTraceWithThrottle(mTraceTriggerFn, mConfiguration, actualRenderTimeUs);
+ }
}
+
// Now that a frame has been rendered, the previously skipped frames can be processed as skipped
// frames since the app is not skipping them to terminate playback.
for (int64_t contentTimeUs : mPendingSkippedFrameContentTimeUsList) {
@@ -738,4 +778,42 @@
return false;
}
+void VideoRenderQualityTracker::triggerTraceWithThrottle(const TraceTriggerFn traceTriggerFn,
+ const Configuration &c,
+ const int64_t triggerTimeUs) {
+ static int64_t lastTriggerUs = -1;
+ static Mutex updateLastTriggerLock;
+
+ Mutex::Autolock autoLock(updateLastTriggerLock);
+ if (lastTriggerUs != -1) {
+ int32_t sinceLastTriggerMs = int32_t((triggerTimeUs - lastTriggerUs) / 1000);
+ // Throttle the trace trigger calls to reduce continuous PID fork calls in a short time
+ // to impact device performance, and reduce spamming trace reports.
+ if (sinceLastTriggerMs < c.traceTriggerThrottleMs) {
+ ALOGI("Not triggering trace - not enough time since last trigger");
+ return;
+ }
+ }
+ lastTriggerUs = triggerTimeUs;
+ (*traceTriggerFn)();
+}
+
+void VideoRenderQualityTracker::triggerTrace() {
+ // Trigger perfetto to stop always-on-tracing (AOT) to collect trace into a file for video
+ // freeze event, the collected trace categories are configured by AOT.
+ const char* args[] = {"/system/bin/trigger_perfetto", "com.android.codec-video-freeze", NULL};
+ pid_t pid = fork();
+ if (pid < 0) {
+ ALOGI("Failed to fork for triggering trace");
+ return;
+ }
+ if (pid == 0) {
+ // child process.
+ execvp(args[0], const_cast<char**>(args));
+ ALOGW("Failed to trigger trace %s", args[1]);
+ _exit(1);
+ }
+ ALOGI("Triggered trace %s", args[1]);
+}
+
} // namespace android
diff --git a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
index a4b3e2f..e091cb8 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
@@ -286,9 +286,11 @@
return;
}
- // decoder deals in ms, OMX in us.
- outHeader->nTimeStamp = mPvToOmxTimeMap.valueFor(timestamp);
- mPvToOmxTimeMap.removeItem(timestamp);
+ if (mPvToOmxTimeMap.indexOfKey(timestamp) >= 0) {
+ // decoder deals in ms, OMX in us.
+ outHeader->nTimeStamp = mPvToOmxTimeMap.valueFor(timestamp);
+ mPvToOmxTimeMap.removeItem(timestamp);
+ }
inHeader->nOffset += bufferSize;
inHeader->nFilledLen = 0;
diff --git a/media/libstagefright/codecs/on2/enc/SoftVP8Encoder.cpp b/media/libstagefright/codecs/on2/enc/SoftVP8Encoder.cpp
index 04737a9..9198b7c 100644
--- a/media/libstagefright/codecs/on2/enc/SoftVP8Encoder.cpp
+++ b/media/libstagefright/codecs/on2/enc/SoftVP8Encoder.cpp
@@ -120,6 +120,11 @@
OMX_ERRORTYPE SoftVP8Encoder::internalGetVp8Params(
OMX_VIDEO_PARAM_VP8TYPE* vp8Params) {
+ if (!isValidOMXParam(vp8Params)) {
+ android_errorWriteLog(0x534e4554, "273936274");
+ return OMX_ErrorBadParameter;
+ }
+
if (vp8Params->nPortIndex != kOutputPortIndex) {
return OMX_ErrorUnsupportedIndex;
}
@@ -133,6 +138,11 @@
OMX_ERRORTYPE SoftVP8Encoder::internalSetVp8Params(
const OMX_VIDEO_PARAM_VP8TYPE* vp8Params) {
+ if (!isValidOMXParam(vp8Params)) {
+ android_errorWriteLog(0x534e4554, "273937171");
+ return OMX_ErrorBadParameter;
+ }
+
if (vp8Params->nPortIndex != kOutputPortIndex) {
return OMX_ErrorUnsupportedIndex;
}
diff --git a/media/libstagefright/codecs/on2/enc/SoftVP9Encoder.cpp b/media/libstagefright/codecs/on2/enc/SoftVP9Encoder.cpp
index 1ea1c85..f8495c2 100644
--- a/media/libstagefright/codecs/on2/enc/SoftVP9Encoder.cpp
+++ b/media/libstagefright/codecs/on2/enc/SoftVP9Encoder.cpp
@@ -119,6 +119,11 @@
OMX_ERRORTYPE SoftVP9Encoder::internalGetVp9Params(
OMX_VIDEO_PARAM_VP9TYPE *vp9Params) {
+ if (!isValidOMXParam(vp9Params)) {
+ android_errorWriteLog(0x534e4554, "273936553");
+ return OMX_ErrorBadParameter;
+ }
+
if (vp9Params->nPortIndex != kOutputPortIndex) {
return OMX_ErrorUnsupportedIndex;
}
@@ -133,6 +138,11 @@
OMX_ERRORTYPE SoftVP9Encoder::internalSetVp9Params(
const OMX_VIDEO_PARAM_VP9TYPE *vp9Params) {
+ if (!isValidOMXParam(vp9Params)) {
+ android_errorWriteLog(0x534e4554, "273937136");
+ return OMX_ErrorBadParameter;
+ }
+
if (vp9Params->nPortIndex != kOutputPortIndex) {
return OMX_ErrorUnsupportedIndex;
}
diff --git a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
index e9b4341..cbedb72 100644
--- a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
+++ b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
@@ -485,6 +485,11 @@
OMX_ERRORTYPE SoftVPXEncoder::internalGetAndroidVpxParams(
OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *vpxAndroidParams) {
+ if (!isValidOMXParam(vpxAndroidParams)) {
+ android_errorWriteLog(0x534e4554, "273936601");
+ return OMX_ErrorBadParameter;
+ }
+
if (vpxAndroidParams->nPortIndex != kOutputPortIndex) {
return OMX_ErrorUnsupportedIndex;
}
@@ -501,6 +506,10 @@
OMX_ERRORTYPE SoftVPXEncoder::internalSetAndroidVpxParams(
const OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *vpxAndroidParams) {
+ if (!isValidOMXParam(vpxAndroidParams)) {
+ android_errorWriteLog(0x534e4554, "273937551");
+ return OMX_ErrorBadParameter;
+ }
if (vpxAndroidParams->nPortIndex != kOutputPortIndex) {
return OMX_ErrorUnsupportedIndex;
}
diff --git a/media/libstagefright/exports.lds b/media/libstagefright/exports.lds
index 7fe6d6c..ee38550 100644
--- a/media/libstagefright/exports.lds
+++ b/media/libstagefright/exports.lds
@@ -171,7 +171,6 @@
FixedDiv1_C;
FixedDiv_C;
fixed_invtbl8;
- GetARGBBlend;
H420ToABGR;
H420ToARGB;
H422ToABGR;
diff --git a/media/libstagefright/include/media/stagefright/CodecBase.h b/media/libstagefright/include/media/stagefright/CodecBase.h
index 90347f9..6f06bc6 100644
--- a/media/libstagefright/include/media/stagefright/CodecBase.h
+++ b/media/libstagefright/include/media/stagefright/CodecBase.h
@@ -182,6 +182,12 @@
* Notify MediaCodec that the first tunnel frame is ready.
*/
virtual void onFirstTunnelFrameReady() = 0;
+ /**
+ * Notify MediaCodec that there are metrics to be updated.
+ *
+ * @param updatedMetrics metrics need to be updated.
+ */
+ virtual void onMetricsUpdated(const sp<AMessage> &updatedMetrics) = 0;
};
/**
diff --git a/media/libstagefright/include/media/stagefright/MediaCodecMetricsConstants.h b/media/libstagefright/include/media/stagefright/MediaCodecMetricsConstants.h
new file mode 100644
index 0000000..2c40904
--- /dev/null
+++ b/media/libstagefright/include/media/stagefright/MediaCodecMetricsConstants.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2018 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.
+ *
+ */
+
+#ifndef MEDIA_CODEC_METRICS_CONSTANTS_H_
+#define MEDIA_CODEC_METRICS_CONSTANTS_H_
+
+namespace android {
+
+// key for media statistics
+// Other keys are in MediaCodec.cpp
+// NB: These are not yet exposed as public Java API constants.
+inline constexpr char kCodecPixelFormat[] =
+ "android.media.mediacodec.pixel-format";
+
+}
+
+#endif // MEDIA_CODEC_METRICS_CONSTANTS_H_
\ No newline at end of file
diff --git a/media/libstagefright/include/media/stagefright/VideoRenderQualityTracker.h b/media/libstagefright/include/media/stagefright/VideoRenderQualityTracker.h
index a656e6e..cf53f27 100644
--- a/media/libstagefright/include/media/stagefright/VideoRenderQualityTracker.h
+++ b/media/libstagefright/include/media/stagefright/VideoRenderQualityTracker.h
@@ -200,6 +200,21 @@
// The maximum distance in time between two judder occurrences such that both will be
// lumped into the same judder event.
int32_t judderEventDistanceToleranceMs;
+ //
+ // Whether or not Perfetto trace trigger is enabled.
+ bool traceTriggerEnabled;
+ //
+ // The throttle time for Perfetto trace trigger to avoid triggering multiple traces for
+ // the same event in a short time.
+ int32_t traceTriggerThrottleMs;
+ //
+ // The minimum frame render duration to recognize video freeze event to collect trace.
+ int32_t traceMinFreezeDurationMs;
+ //
+ // The maximum frame render duration to recognize video freeze event. A frame render
+ // duration that is larger than the max duration would not trigger trace collection for
+ // video freeze because it's highly possible a video pause.
+ int32_t traceMaxFreezeDurationMs;
};
struct FreezeEvent {
@@ -256,8 +271,11 @@
Details details;
};
+ typedef void (*TraceTriggerFn)();
+
VideoRenderQualityTracker();
- VideoRenderQualityTracker(const Configuration &configuration);
+ VideoRenderQualityTracker(const Configuration &configuration,
+ const TraceTriggerFn traceTriggerFn = nullptr);
// Called when a tunnel mode frame has been queued.
void onTunnelFrameQueued(int64_t contentTimeUs);
@@ -376,6 +394,14 @@
JudderEvent &e, const VideoRenderQualityMetrics & m,
const Configuration &c, JudderEvent *judderEventOut);
+ // Trigger trace collection for video freeze.
+ static void triggerTrace();
+
+ // Trigger collection of a Perfetto Always-On-Tracing (AOT) trace file for video freeze,
+ // triggerTimeUs is used as a throttle to avoid triggering multiple traces in a short time.
+ static void triggerTraceWithThrottle(TraceTriggerFn traceTriggerFn,
+ const Configuration &c, const int64_t triggerTimeUs);
+
// Check to see if a discontinuity has occurred by examining the content time and the
// app-desired render time. If so, reset some internal state.
bool resetIfDiscontinuity(int64_t contentTimeUs, int64_t desiredRenderTimeUs);
@@ -394,6 +420,9 @@
// Configurable elements of the metrics algorithms.
const Configuration mConfiguration;
+ // The function for triggering trace collection for video freeze.
+ const TraceTriggerFn mTraceTriggerFn;
+
// Metrics are updated every time a frame event occurs - skipped, dropped, rendered.
VideoRenderQualityMetrics mMetrics;
@@ -445,6 +474,9 @@
// Frame durations derived from timestamps captured by the display subsystem, indicating the
// wall clock atime at which the frame is actually rendered.
FrameDurationUs mActualFrameDurationUs;
+
+ // Token of async atrace for video frame dropped/skipped by the app.
+ int64_t mTraceFrameSkippedToken= -1;
};
} // namespace android
diff --git a/media/libstagefright/tests/VideoRenderQualityTracker_test.cpp b/media/libstagefright/tests/VideoRenderQualityTracker_test.cpp
index 7823922..3b70636 100644
--- a/media/libstagefright/tests/VideoRenderQualityTracker_test.cpp
+++ b/media/libstagefright/tests/VideoRenderQualityTracker_test.cpp
@@ -36,10 +36,11 @@
class Helper {
public:
Helper(double contentFrameDurationMs, const Configuration &configuration) :
- mVideoRenderQualityTracker(configuration) {
+ mVideoRenderQualityTracker(configuration, testTraceTrigger) {
mContentFrameDurationUs = int64_t(contentFrameDurationMs * 1000);
mMediaTimeUs = 0;
mClockTimeNs = 0;
+ sTraceTriggeredCount = 0;
}
void changeContentFrameDuration(double contentFrameDurationMs) {
@@ -100,6 +101,10 @@
return e;
}
+ int getTraceTriggeredCount() {
+ return sTraceTriggeredCount;
+ }
+
private:
VideoRenderQualityTracker mVideoRenderQualityTracker;
int64_t mContentFrameDurationUs;
@@ -107,8 +112,16 @@
int64_t mClockTimeNs;
VideoRenderQualityTracker::FreezeEvent mFreezeEvent;
VideoRenderQualityTracker::JudderEvent mJudderEvent;
+
+ static int sTraceTriggeredCount;
+
+ static void testTraceTrigger() {
+ sTraceTriggeredCount++;
+ };
};
+int Helper::sTraceTriggeredCount = 0;
+
class VideoRenderQualityTrackerTest : public ::testing::Test {
public:
VideoRenderQualityTrackerTest() {}
@@ -139,6 +152,10 @@
EXPECT_EQ(c.judderEventMax, d.judderEventMax);
EXPECT_EQ(c.judderEventDetailsMax, d.judderEventDetailsMax);
EXPECT_EQ(c.judderEventDistanceToleranceMs, d.judderEventDistanceToleranceMs);
+ EXPECT_EQ(c.traceTriggerEnabled, d.traceTriggerEnabled);
+ EXPECT_EQ(c.traceTriggerThrottleMs, d.traceTriggerThrottleMs);
+ EXPECT_EQ(c.traceMinFreezeDurationMs, d.traceMinFreezeDurationMs);
+ EXPECT_EQ(c.traceMaxFreezeDurationMs, d.traceMaxFreezeDurationMs);
}
TEST_F(VideoRenderQualityTrackerTest, getFromServerConfigurableFlags_withEmpty) {
@@ -166,6 +183,10 @@
EXPECT_EQ(c.judderEventMax, d.judderEventMax);
EXPECT_EQ(c.judderEventDetailsMax, d.judderEventDetailsMax);
EXPECT_EQ(c.judderEventDistanceToleranceMs, d.judderEventDistanceToleranceMs);
+ EXPECT_EQ(c.traceTriggerEnabled, d.traceTriggerEnabled);
+ EXPECT_EQ(c.traceTriggerThrottleMs, d.traceTriggerThrottleMs);
+ EXPECT_EQ(c.traceMinFreezeDurationMs, d.traceMinFreezeDurationMs);
+ EXPECT_EQ(c.traceMaxFreezeDurationMs, d.traceMaxFreezeDurationMs);
}
TEST_F(VideoRenderQualityTrackerTest, getFromServerConfigurableFlags_withInvalid) {
@@ -193,6 +214,10 @@
EXPECT_EQ(c.judderEventMax, d.judderEventMax);
EXPECT_EQ(c.judderEventDetailsMax, d.judderEventDetailsMax);
EXPECT_EQ(c.judderEventDistanceToleranceMs, d.judderEventDistanceToleranceMs);
+ EXPECT_EQ(c.traceTriggerEnabled, d.traceTriggerEnabled);
+ EXPECT_EQ(c.traceTriggerThrottleMs, d.traceTriggerThrottleMs);
+ EXPECT_EQ(c.traceMinFreezeDurationMs, d.traceMinFreezeDurationMs);
+ EXPECT_EQ(c.traceMaxFreezeDurationMs, d.traceMaxFreezeDurationMs);
}
TEST_F(VideoRenderQualityTrackerTest, getFromServerConfigurableFlags_withAlmostValid) {
@@ -232,6 +257,14 @@
return "10*10";
} else if (flag == "render_metrics_judder_event_distance_tolerance_ms") {
return "140-a";
+ } else if (flag == "render_metrics_trace_trigger_enabled") {
+ return "fals";
+ } else if (flag == "render_metrics_trace_trigger_throttle_ms") {
+ return "12345678901234";
+ } else if (flag == "render_metrics_trace_minimum_freeze_duration_ms") {
+ return "10b0";
+ } else if (flag == "render_metrics_trace_maximum_freeze_duration_ms") {
+ return "100a";
}
return "";
}
@@ -255,6 +288,10 @@
EXPECT_EQ(c.judderEventMax, d.judderEventMax);
EXPECT_EQ(c.judderEventDetailsMax, d.judderEventDetailsMax);
EXPECT_EQ(c.judderEventDistanceToleranceMs, d.judderEventDistanceToleranceMs);
+ EXPECT_EQ(c.traceTriggerEnabled, d.traceTriggerEnabled);
+ EXPECT_EQ(c.traceTriggerThrottleMs, d.traceTriggerThrottleMs);
+ EXPECT_EQ(c.traceMinFreezeDurationMs, d.traceMinFreezeDurationMs);
+ EXPECT_EQ(c.traceMaxFreezeDurationMs, d.traceMaxFreezeDurationMs);
}
TEST_F(VideoRenderQualityTrackerTest, getFromServerConfigurableFlags_withValid) {
@@ -294,6 +331,14 @@
return "10000";
} else if (flag == "render_metrics_judder_event_distance_tolerance_ms") {
return "11000";
+ } else if (flag == "render_metrics_trace_trigger_enabled") {
+ return "true";
+ } else if (flag == "render_metrics_trace_trigger_throttle_ms") {
+ return "50000";
+ } else if (flag == "render_metrics_trace_minimum_freeze_duration_ms") {
+ return "1000";
+ } else if (flag == "render_metrics_trace_maximum_freeze_duration_ms") {
+ return "5000";
}
return "";
}
@@ -353,6 +398,11 @@
EXPECT_NE(c.judderEventDetailsMax, d.judderEventDetailsMax);
EXPECT_EQ(c.judderEventDistanceToleranceMs, 11000);
EXPECT_NE(c.judderEventDistanceToleranceMs, d.judderEventDistanceToleranceMs);
+
+ EXPECT_EQ(c.traceTriggerEnabled, true);
+ EXPECT_EQ(c.traceTriggerThrottleMs, 50000);
+ EXPECT_EQ(c.traceMinFreezeDurationMs, 1000);
+ EXPECT_EQ(c.traceMaxFreezeDurationMs, 5000);
}
TEST_F(VideoRenderQualityTrackerTest, countsReleasedFrames) {
@@ -1024,4 +1074,75 @@
EXPECT_EQ(h.getMetrics().judderScore, 10 + 300 + 2000);
}
+TEST_F(VideoRenderQualityTrackerTest,
+ freezesForTraceDuration_withThrottle_throttlesTraceTrigger) {
+ Configuration c;
+ c.enabled = true;
+ c.traceTriggerEnabled = true; // The trigger is enabled, so traces should be triggered.
+ // The value of traceTriggerThrottleMs must be larger than traceMinFreezeDurationMs. Otherwise,
+ // the throttle does work.
+ c.traceTriggerThrottleMs = 200;
+ c.traceMinFreezeDurationMs = 40;
+ int32_t freeze = c.traceMinFreezeDurationMs;
+
+ Helper h(20, c);
+ // Freeze triggers separated by 80ms which is less than the threshold.
+ h.render({
+ freeze, // Freeze duration does not check trace trigger.
+ 20, // Trace triggered.
+ 20, // Throttle time: 20/200ms
+ 20, // Throttle time: 40/200ms
+ freeze, // Throttle time: 80/200ms
+ 20, // Throttle time: 100/200ms (Trace not triggered)
+ });
+ EXPECT_EQ(h.getTraceTriggeredCount(), 1);
+ // Next freeze trigger is separated by 200ms which breaks the throttle threshold.
+ h.render({
+ 20, // Throttle time: 120/200ms
+ 20, // Throttle time: 140/200ms
+ 20, // Throttle time: 160/200ms
+ freeze, // Throttle time: 200/200ms
+ 20, // Trace triggered.
+ });
+ EXPECT_EQ(h.getTraceTriggeredCount(), 2);
+ // Next freeze trigger is separated by 80ms which is less than the threshold.
+ h.render({
+ 20, // Throttle time: 20/200ms
+ 20, // Throttle time: 40/200ms
+ freeze, // Throttle time: 80/200ms
+ 20, // Throttle time: 100/200ms (Trace not triggered)
+ });
+ EXPECT_EQ(h.getTraceTriggeredCount(), 2);
+}
+
+TEST_F(VideoRenderQualityTrackerTest, freezeForTraceDuration_triggersTrace) {
+ Configuration c;
+ c.enabled = true;
+ c.traceTriggerEnabled = true; // The trigger is enabled, so traces should be triggered.
+ c.traceTriggerThrottleMs = 0; // Disable throttle in the test case.
+ int32_t freeze1 = c.traceMinFreezeDurationMs;
+ int32_t freeze2 = c.traceMaxFreezeDurationMs - 1;
+ int32_t couldBeAPause = c.traceMaxFreezeDurationMs + 1;
+
+ Helper h(20, c);
+ h.render({freeze1, 20, freeze2, 20, couldBeAPause, 20});
+
+ EXPECT_EQ(h.getTraceTriggeredCount(), 2);
+}
+
+TEST_F(VideoRenderQualityTrackerTest,
+ freezeForTraceDuration_withTraceDisabled_doesNotTriggerTrace) {
+ Configuration c;
+ c.enabled = true;
+ c.traceTriggerEnabled = false; // The trigger is disabled, so no traces should be triggered.
+ c.traceTriggerThrottleMs = 0; // Disable throttle in the test case.
+ int32_t freeze1 = c.traceMinFreezeDurationMs;
+ int32_t freeze2 = c.traceMaxFreezeDurationMs - 1;
+ int32_t couldBeAPause = c.traceMaxFreezeDurationMs + 1;
+
+ Helper h(20, c);
+ h.render({freeze1, 20, freeze2, 20, couldBeAPause, 20});
+
+ EXPECT_EQ(h.getTraceTriggeredCount(), 0);
+}
} // android
diff --git a/media/module/codecserviceregistrant/fuzzer/codecServiceRegistrant_fuzzer.cpp b/media/module/codecserviceregistrant/fuzzer/codecServiceRegistrant_fuzzer.cpp
index e5983e4..fba4230 100644
--- a/media/module/codecserviceregistrant/fuzzer/codecServiceRegistrant_fuzzer.cpp
+++ b/media/module/codecserviceregistrant/fuzzer/codecServiceRegistrant_fuzzer.cpp
@@ -17,6 +17,7 @@
#include "fuzzer/FuzzedDataProvider.h"
#include <C2Config.h>
#include <C2Param.h>
+#include <android/api-level.h>
using namespace std;
@@ -59,11 +60,31 @@
if (!store) {
return;
}
- android::sp<V1_1::IComponentStore> storeV1_1 =
+
+ int32_t platformVersion = android_get_device_api_level();
+ if (platformVersion >= __ANDROID_API_S__) {
+ android::sp<V1_2::IComponentStore> storeV1_2 =
+ new V1_2::utils::ComponentStore(store);
+ if (storeV1_2->registerAsService(string(kServiceName)) != android::OK) {
+ return;
+ }
+ } else if (platformVersion == __ANDROID_API_R__) {
+ android::sp<V1_1::IComponentStore> storeV1_1 =
new V1_1::utils::ComponentStore(store);
- if (storeV1_1->registerAsService(string(kServiceName)) != android::OK) {
+ if (storeV1_1->registerAsService(string(kServiceName)) != android::OK) {
+ return;
+ }
+ } else if (platformVersion == __ANDROID_API_Q__) {
+ android::sp<V1_0::IComponentStore> storeV1_0 =
+ new V1_0::utils::ComponentStore(store);
+ if (storeV1_0->registerAsService(string(kServiceName)) != android::OK) {
+ return;
+ }
+ }
+ else {
return;
}
+
string const preferredStoreName = string(kServiceName);
sp<IComponentStore> preferredStore =
IComponentStore::getService(preferredStoreName.c_str());
diff --git a/media/mtp/tests/MtpFuzzer/mtp_packet_fuzzer.cpp b/media/mtp/tests/MtpFuzzer/mtp_packet_fuzzer.cpp
index 6fc2a96..e4df321 100644
--- a/media/mtp/tests/MtpFuzzer/mtp_packet_fuzzer.cpp
+++ b/media/mtp/tests/MtpFuzzer/mtp_packet_fuzzer.cpp
@@ -18,6 +18,7 @@
#include <MtpPacket.h>
#include <MtpPacketFuzzerUtils.h>
#include <fuzzer/FuzzedDataProvider.h>
+#include <mtp.h>
using namespace android;
@@ -35,7 +36,8 @@
};
void MtpPacketFuzzer::process() {
- MtpPacket mtpPacket(mFdp.ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize)); /*bufferSize*/
+ MtpPacket mtpPacket(mFdp.ConsumeIntegralInRange<size_t>(MTP_CONTAINER_HEADER_SIZE,
+ kMaxSize)); /*bufferSize*/
while (mFdp.remaining_bytes() > 0) {
auto mtpPacketAPI = mFdp.PickValueInArray<const std::function<void()>>({
[&]() {
diff --git a/media/ndk/include/media/NdkImageReader.h b/media/ndk/include/media/NdkImageReader.h
index 48a0a82..b722b74 100644
--- a/media/ndk/include/media/NdkImageReader.h
+++ b/media/ndk/include/media/NdkImageReader.h
@@ -534,6 +534,11 @@
* Get the native_handle_t corresponding to the ANativeWindow owned by the
* AImageReader provided.
*
+ * This is deprecated in API level 35 and will return AMEDIA_ERROR_UNKNOWN.
+ * The native_handle_t is no longer used with AIDL interfaces and
+ * ANativeWindow is used directly instead.
+ * Use AImageRead_getWindow to get the ANativeWindow and use that object.
+ *
* @param reader The image reader of interest.
* @param handle The output native_handle_t. This native handle is owned by
* this image reader.
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/FrameReleaseQueue.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/FrameReleaseQueue.java
index 306aeee..d182f88 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/FrameReleaseQueue.java
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/FrameReleaseQueue.java
@@ -22,6 +22,7 @@
import java.nio.ByteBuffer;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.CompletableFuture;
public class FrameReleaseQueue {
private static final String TAG = "FrameReleaseQueue";
@@ -61,31 +62,31 @@
// first frame of loop
firstReleaseTime = getCurSysTime();
nextReleaseTime = firstReleaseTime + mWaitTime;
- popAndRelease(curFrameInfo, true);
+ popAndRelease(true);
} else if (!doFrameRelease.get() && mFrameInfoQueue.size() == 1) {
// EOS
Log.i(TAG, "EOS");
- popAndRelease(curFrameInfo, false);
+ popAndRelease(false);
} else {
nextReleaseTime += mWaitTime;
int curSysTime = getCurSysTime();
int curMediaTime = curSysTime - firstReleaseTime;
while (curFrameInfo != null && curFrameInfo.displayTime > 0 &&
curFrameInfo.displayTime <= curMediaTime) {
- if (!((curMediaTime - curFrameInfo.displayTime) < THRESHOLD_TIME)) {
+ if (!((curMediaTime - curFrameInfo.displayTime) <= THRESHOLD_TIME)) {
Log.d(TAG, "Dropping expired frame " + curFrameInfo.number +
" display time " + curFrameInfo.displayTime +
" current time " + curMediaTime);
- popAndRelease(curFrameInfo, false);
+ popAndRelease(false);
} else {
- popAndRelease(curFrameInfo, true);
+ popAndRelease(true);
}
curFrameInfo = mFrameInfoQueue.peek();
}
if (curFrameInfo != null && curFrameInfo.displayTime > curMediaTime) {
if ((curFrameInfo.displayTime - curMediaTime) < THRESHOLD_TIME) {
// release the frame now as we are already there
- popAndRelease(curFrameInfo, true);
+ popAndRelease(true);
}
}
}
@@ -148,20 +149,22 @@
return (int)(System.nanoTime()/1000000);
}
- private void popAndRelease(FrameInfo curFrameInfo, boolean renderThisFrame) {
+ private void popAndRelease(boolean renderThisFrame) {
+ final boolean actualRender = (renderThisFrame && mRender);
try {
- curFrameInfo = mFrameInfoQueue.take();
+ final FrameInfo curFrameInfo = mFrameInfoQueue.take();
+
+ CompletableFuture future = CompletableFuture.runAsync(() -> {
+ try {
+ mCodec.releaseOutputBuffer(curFrameInfo.bufferId, actualRender);
+ } catch (IllegalStateException e) {
+ e.printStackTrace();
+ }
+ });
+
} catch (InterruptedException e) {
Log.e(TAG, "Threw InterruptedException on take");
}
- boolean actualRender = (renderThisFrame && mRender);
- try {
- mCodec.releaseOutputBuffer(curFrameInfo.bufferId, actualRender);
- } catch (IllegalStateException e) {
- Log.e(TAG,
- "Threw IllegalStateException on releaseOutputBuffer for frame "
- + curFrameInfo.number);
- }
}
public void stopFrameRelease() {
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 8dbe067..e0b907f 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -280,7 +280,7 @@
void AudioFlinger::onFirstRef()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
mMode = AUDIO_MODE_NORMAL;
@@ -306,19 +306,19 @@
status_t AudioFlinger::setVibratorInfos(
const std::vector<media::AudioVibratorInfo>& vibratorInfos) {
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
mAudioVibratorInfos = vibratorInfos;
return NO_ERROR;
}
status_t AudioFlinger::updateSecondaryOutputs(
const TrackSecondaryOutputsMap& trackSecondaryOutputs) {
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
for (const auto& [trackId, secondaryOutputs] : trackSecondaryOutputs) {
size_t i = 0;
for (; i < mPlaybackThreads.size(); ++i) {
IAfPlaybackThread* thread = mPlaybackThreads.valueAt(i).get();
- Mutex::Autolock _tl(thread->mutex());
+ audio_utils::lock_guard _tl(thread->mutex());
sp<IAfTrack> track = thread->getTrackById_l(trackId);
if (track != nullptr) {
ALOGD("%s trackId: %u", __func__, trackId);
@@ -334,13 +334,13 @@
status_t AudioFlinger::getMmapPolicyInfos(
AudioMMapPolicyType policyType, std::vector<AudioMMapPolicyInfo> *policyInfos) {
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (const auto it = mPolicyInfos.find(policyType); it != mPolicyInfos.end()) {
*policyInfos = it->second;
return NO_ERROR;
}
if (mDevicesFactoryHal->getHalVersion() > kMaxAAudioPropertyDeviceHalVersion) {
- AutoMutex lock(mHardwareLock);
+ audio_utils::lock_guard lock(hardwareMutex());
for (size_t i = 0; i < mAudioHwDevs.size(); ++i) {
AudioHwDevice *dev = mAudioHwDevs.valueAt(i);
std::vector<AudioMMapPolicyInfo> infos;
@@ -361,20 +361,20 @@
}
int32_t AudioFlinger::getAAudioMixerBurstCount() const {
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
return mAAudioBurstsPerBuffer;
}
int32_t AudioFlinger::getAAudioHardwareBurstMinUsec() const {
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
return mAAudioHwBurstMinMicros;
}
status_t AudioFlinger::setDeviceConnectedState(const struct audio_port_v7 *port,
media::DeviceConnectedState state) {
status_t final_result = NO_INIT;
- Mutex::Autolock _l(mLock);
- AutoMutex lock(mHardwareLock);
+ audio_utils::lock_guard _l(mutex());
+ audio_utils::lock_guard lock(hardwareMutex());
mHardwareStatus = AUDIO_HW_SET_CONNECTED_STATE;
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
sp<DeviceHalInterface> dev = mAudioHwDevs.valueAt(i)->hwDevice();
@@ -394,8 +394,8 @@
status_t AudioFlinger::setSimulateDeviceConnections(bool enabled) {
bool at_least_one_succeeded = false;
status_t last_error = INVALID_OPERATION;
- Mutex::Autolock _l(mLock);
- AutoMutex lock(mHardwareLock);
+ audio_utils::lock_guard _l(mutex());
+ audio_utils::lock_guard lock(hardwareMutex());
mHardwareStatus = AUDIO_HW_SET_SIMULATE_CONNECTIONS;
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
sp<DeviceHalInterface> dev = mAudioHwDevs.valueAt(i)->hwDevice();
@@ -438,7 +438,7 @@
}
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
- // no mHardwareLock needed, as there are no other references to this
+ // no hardwareMutex() needed, as there are no other references to this
delete mAudioHwDevs.valueAt(i);
}
@@ -560,6 +560,9 @@
return ret;
}
+ // use unique_lock as we may selectively unlock.
+ audio_utils::unique_lock l(mutex());
+
// at this stage, a MmapThread was created when openOutput() or openInput() was called by
// audio policy manager and we can retrieve it
const sp<IAfMmapThread> thread = mMmapThreads.valueFor(io);
@@ -572,12 +575,14 @@
config->channel_mask = thread->channelMask();
config->format = thread->format();
} else {
+ l.unlock();
if (direction == MmapStreamInterface::DIRECTION_OUTPUT) {
AudioSystem::releaseOutput(portId);
} else {
AudioSystem::releaseInput(portId);
}
ret = NO_INIT;
+ // we don't reacquire the lock here as nothing left to do.
}
ALOGV("%s done status %d portId %d", __FUNCTION__, ret, portId);
@@ -587,7 +592,7 @@
status_t AudioFlinger::addEffectToHal(
const struct audio_port_config *device, const sp<EffectHalInterface>& effect) {
- AutoMutex lock(mHardwareLock);
+ audio_utils::lock_guard lock(hardwareMutex());
AudioHwDevice *audioHwDevice = mAudioHwDevs.valueFor(device->ext.device.hw_module);
if (audioHwDevice == nullptr) {
return NO_INIT;
@@ -597,7 +602,7 @@
status_t AudioFlinger::removeEffectFromHal(
const struct audio_port_config *device, const sp<EffectHalInterface>& effect) {
- AutoMutex lock(mHardwareLock);
+ audio_utils::lock_guard lock(hardwareMutex());
AudioHwDevice *audioHwDevice = mAudioHwDevs.valueFor(device->ext.device.hw_module);
if (audioHwDevice == nullptr) {
return NO_INIT;
@@ -617,11 +622,11 @@
{
// if module is 0, the request comes from an old policy manager and we should load
// well known modules
- AutoMutex lock(mHardwareLock);
+ audio_utils::lock_guard lock(hardwareMutex());
if (module == 0) {
ALOGW("findSuitableHwDev_l() loading well know audio hw modules");
for (size_t i = 0; i < arraysize(audio_interfaces); i++) {
- loadHwModule_l(audio_interfaces[i]);
+ loadHwModule_ll(audio_interfaces[i]);
}
// then try to find a module supporting the requested device.
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
@@ -644,7 +649,7 @@
return NULL;
}
-void AudioFlinger::dumpClients(int fd, const Vector<String16>& args __unused)
+void AudioFlinger::dumpClients_ll(int fd, const Vector<String16>& args __unused)
{
String8 result;
@@ -678,7 +683,7 @@
}
-void AudioFlinger::dumpInternals(int fd, const Vector<String16>& args __unused)
+void AudioFlinger::dumpInternals_l(int fd, const Vector<String16>& args __unused)
{
const size_t SIZE = 256;
char buffer[SIZE];
@@ -717,15 +722,15 @@
dumpPermissionDenial(fd, args);
} else {
// get state of hardware lock
- const bool hardwareLocked = afutils::dumpTryLock(mHardwareLock);
+ const bool hardwareLocked = afutils::dumpTryLock(hardwareMutex());
if (!hardwareLocked) {
String8 result(kHardwareLockedString);
write(fd, result.c_str(), result.size());
} else {
- mHardwareLock.unlock();
+ hardwareMutex().unlock();
}
- const bool locked = afutils::dumpTryLock(mLock);
+ const bool locked = afutils::dumpTryLock(mutex());
// failed to lock - AudioFlinger is probably deadlocked
if (!locked) {
@@ -733,7 +738,7 @@
write(fd, result.c_str(), result.size());
}
- const bool clientLocked = afutils::dumpTryLock(mClientLock);
+ const bool clientLocked = afutils::dumpTryLock(clientMutex());
if (!clientLocked) {
String8 result(kClientLockedString);
write(fd, result.c_str(), result.size());
@@ -746,12 +751,12 @@
write(fd, result.c_str(), result.size());
}
- dumpClients(fd, args);
+ dumpClients_ll(fd, args);
if (clientLocked) {
- mClientLock.unlock();
+ clientMutex().unlock();
}
- dumpInternals(fd, args);
+ dumpInternals_l(fd, args);
// dump playback threads
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
@@ -806,7 +811,7 @@
BUFLOG_RESET;
if (locked) {
- mLock.unlock();
+ mutex().unlock();
}
#ifdef TEE_SINK
@@ -878,7 +883,7 @@
sp<Client> AudioFlinger::registerPid(pid_t pid)
{
- Mutex::Autolock _cl(mClientLock);
+ audio_utils::lock_guard _cl(clientMutex());
// If pid is already in the mClients wp<> map, then use that entry
// (for which promote() is always != 0), otherwise create a new entry and Client.
sp<Client> client = mClients.valueFor(pid).promote();
@@ -901,7 +906,7 @@
// If allocation fails, consult the vector of previously unregistered writers
// and garbage-collect one or more them until an allocation succeeds
if (shared == 0) {
- Mutex::Autolock _l(mUnregisteredWritersLock);
+ audio_utils::lock_guard _l(unregisteredWritersMutex());
for (size_t count = mUnregisteredWriters.size(); count > 0; count--) {
{
// Pick the oldest stale writer to garbage-collect
@@ -941,7 +946,7 @@
}
// Rather than removing the writer immediately, append it to a queue of old writers to
// be garbage-collected later. This allows us to continue to view old logs for a while.
- Mutex::Autolock _l(mUnregisteredWritersLock);
+ audio_utils::lock_guard _l(unregisteredWritersMutex());
mUnregisteredWriters.push(writer);
}
@@ -1037,7 +1042,7 @@
}
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
IAfPlaybackThread* thread = checkPlaybackThread_l(output.outputId);
if (thread == NULL) {
ALOGE("no playback thread found for output handle %d", output.outputId);
@@ -1088,8 +1093,8 @@
output.portId = portId;
if (lStatus == NO_ERROR) {
- // no risk of deadlock because AudioFlinger::mLock is held
- Mutex::Autolock _dl(thread->mutex());
+ // no risk of deadlock because AudioFlinger::mutex() is held
+ audio_utils::lock_guard _dl(thread->mutex());
// Connect secondary outputs. Failure on a secondary output must not imped the primary
// Any secondary output setup failure will lead to a desync between the AP and AF until
// the track is destroyed.
@@ -1097,8 +1102,9 @@
// move effect chain to this output thread if an effect on same session was waiting
// for a track to be created
if (effectThread != nullptr) {
- Mutex::Autolock _sl(effectThread->mutex());
- if (moveEffectChain_l(sessionId, effectThread, thread) == NO_ERROR) {
+ // No thread safety analysis: double lock on a thread capability.
+ audio_utils::lock_guard_no_thread_safety_analysis _sl(effectThread->mutex());
+ if (moveEffectChain_ll(sessionId, effectThread, thread) == NO_ERROR) {
effectThreadId = thread->id();
effectIds = thread->getEffectIds_l(sessionId);
}
@@ -1127,11 +1133,11 @@
if (lStatus != NO_ERROR) {
// remove local strong reference to Client before deleting the Track so that the
- // Client destructor is called by the TrackBase destructor with mClientLock held
- // Don't hold mClientLock when releasing the reference on the track as the
+ // Client destructor is called by the TrackBase destructor with clientMutex() held
+ // Don't hold clientMutex() when releasing the reference on the track as the
// destructor will acquire it.
{
- Mutex::Autolock _cl(mClientLock);
+ audio_utils::lock_guard _cl(clientMutex());
client.clear();
}
track.clear();
@@ -1156,7 +1162,7 @@
uint32_t AudioFlinger::sampleRate(audio_io_handle_t ioHandle) const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
IAfThreadBase* const thread = checkThread_l(ioHandle);
if (thread == NULL) {
ALOGW("sampleRate() unknown thread %d", ioHandle);
@@ -1167,7 +1173,7 @@
audio_format_t AudioFlinger::format(audio_io_handle_t output) const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
IAfPlaybackThread* const thread = checkPlaybackThread_l(output);
if (thread == NULL) {
ALOGW("format() unknown thread %d", output);
@@ -1178,7 +1184,7 @@
size_t AudioFlinger::frameCount(audio_io_handle_t ioHandle) const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
IAfThreadBase* const thread = checkThread_l(ioHandle);
if (thread == NULL) {
ALOGW("frameCount() unknown thread %d", ioHandle);
@@ -1191,7 +1197,7 @@
size_t AudioFlinger::frameCountHAL(audio_io_handle_t ioHandle) const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
IAfThreadBase* const thread = checkThread_l(ioHandle);
if (thread == NULL) {
ALOGW("frameCountHAL() unknown thread %d", ioHandle);
@@ -1202,7 +1208,7 @@
uint32_t AudioFlinger::latency(audio_io_handle_t output) const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
IAfPlaybackThread* const thread = checkPlaybackThread_l(output);
if (thread == NULL) {
ALOGW("latency(): no playback thread found for output handle %d", output);
@@ -1223,12 +1229,12 @@
return PERMISSION_DENIED;
}
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
mMasterVolume = value;
// Set master volume in the HALs which support it.
{
- AutoMutex lock(mHardwareLock);
+ audio_utils::lock_guard lock(hardwareMutex());
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
AudioHwDevice *dev = mAudioHwDevs.valueAt(i);
@@ -1270,7 +1276,7 @@
return BAD_VALUE;
}
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
// short cut.
if (mMasterBalance == balance) return NO_ERROR;
@@ -1304,7 +1310,7 @@
}
{ // scope for the lock
- AutoMutex lock(mHardwareLock);
+ audio_utils::lock_guard lock(hardwareMutex());
if (mPrimaryHardwareDev == nullptr) {
return INVALID_OPERATION;
}
@@ -1315,7 +1321,7 @@
}
if (NO_ERROR == ret) {
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
mMode = mode;
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
mPlaybackThreads.valueAt(i)->setMode(mode);
@@ -1341,7 +1347,7 @@
return PERMISSION_DENIED;
}
- AutoMutex lock(mHardwareLock);
+ audio_utils::lock_guard lock(hardwareMutex());
if (mPrimaryHardwareDev == nullptr) {
return INVALID_OPERATION;
}
@@ -1369,7 +1375,7 @@
if (ret != NO_ERROR) {
return false;
}
- AutoMutex lock(mHardwareLock);
+ audio_utils::lock_guard lock(hardwareMutex());
if (mPrimaryHardwareDev == nullptr) {
return false;
}
@@ -1390,7 +1396,7 @@
{
ALOGV("AudioFlinger::setRecordSilenced(portId:%d, silenced:%d)", portId, silenced);
- AutoMutex lock(mLock);
+ audio_utils::lock_guard lock(mutex());
for (size_t i = 0; i < mRecordThreads.size(); i++) {
mRecordThreads[i]->setRecordSilenced(portId, silenced);
}
@@ -1411,12 +1417,12 @@
return PERMISSION_DENIED;
}
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
mMasterMute = muted;
// Set master mute in the HALs which support it.
{
- AutoMutex lock(mHardwareLock);
+ audio_utils::lock_guard lock(hardwareMutex());
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
AudioHwDevice *dev = mAudioHwDevs.valueAt(i);
@@ -1442,20 +1448,20 @@
float AudioFlinger::masterVolume() const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
return masterVolume_l();
}
status_t AudioFlinger::getMasterBalance(float *balance) const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
*balance = getMasterBalance_l();
return NO_ERROR; // if called through binder, may return a transactional error
}
bool AudioFlinger::masterMute() const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
return masterMute_l();
}
@@ -1474,7 +1480,8 @@
return mMasterMute;
}
-status_t AudioFlinger::checkStreamType(audio_stream_type_t stream) const
+/* static */
+status_t AudioFlinger::checkStreamType(audio_stream_type_t stream)
{
if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
ALOGW("checkStreamType() invalid stream %d", stream);
@@ -1507,7 +1514,7 @@
LOG_ALWAYS_FATAL_IF(stream == AUDIO_STREAM_PATCH && value != 1.0f,
"AUDIO_STREAM_PATCH must have full scale volume");
- AutoMutex lock(mLock);
+ audio_utils::lock_guard lock(mutex());
sp<VolumeInterface> volumeInterface = getVolumeInterface_l(output);
if (volumeInterface == NULL) {
return BAD_VALUE;
@@ -1522,7 +1529,7 @@
if (output == AUDIO_IO_HANDLE_NONE) {
return BAD_VALUE;
}
- AutoMutex lock(mLock);
+ audio_utils::lock_guard lock(mutex());
IAfPlaybackThread* const thread = checkPlaybackThread_l(output);
if (thread == nullptr) {
return BAD_VALUE;
@@ -1535,7 +1542,7 @@
if (output == AUDIO_IO_HANDLE_NONE) {
return BAD_VALUE;
}
- AutoMutex lock(mLock);
+ audio_utils::lock_guard lock(mutex());
IAfPlaybackThread* const thread = checkPlaybackThread_l(output);
if (thread == nullptr) {
return BAD_VALUE;
@@ -1544,7 +1551,7 @@
}
status_t AudioFlinger::setBluetoothVariableLatencyEnabled(bool enabled) {
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
status_t status = INVALID_OPERATION;
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
// Success if at least one PlaybackThread supports Bluetooth latency modes
@@ -1570,7 +1577,7 @@
if (support == nullptr) {
return BAD_VALUE;
}
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(hardwareMutex());
*support = false;
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
if (mAudioHwDevs.valueAt(i)->supportsBluetoothVariableLatency()) {
@@ -1609,7 +1616,7 @@
return BAD_VALUE;
}
- AutoMutex lock(mLock);
+ audio_utils::lock_guard lock(mutex());
mStreamTypes[stream].mute = muted;
std::vector<sp<VolumeInterface>> volumeInterfaces = getAllVolumeInterfaces_l();
for (size_t i = 0; i < volumeInterfaces.size(); i++) {
@@ -1629,7 +1636,7 @@
return 0.0f;
}
- AutoMutex lock(mLock);
+ audio_utils::lock_guard lock(mutex());
sp<VolumeInterface> volumeInterface = getVolumeInterface_l(output);
if (volumeInterface == NULL) {
return 0.0f;
@@ -1645,7 +1652,7 @@
return true;
}
- AutoMutex lock(mLock);
+ audio_utils::lock_guard lock(mutex());
return streamMute_l(stream);
}
@@ -1664,7 +1671,7 @@
}
}
-// forwardAudioHwSyncToDownstreamPatches_l() must be called with AudioFlinger::mLock held
+// forwardAudioHwSyncToDownstreamPatches_l() must be called with AudioFlinger::mutex() held
void AudioFlinger::forwardParametersToDownstreamPatches_l(
audio_io_handle_t upStream, const String8& keyValuePairs,
const std::function<bool(const sp<IAfPlaybackThread>&)>& useThread)
@@ -1769,11 +1776,11 @@
// AUDIO_IO_HANDLE_NONE means the parameters are global to the audio hardware interface
if (ioHandle == AUDIO_IO_HANDLE_NONE) {
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
// result will remain NO_INIT if no audio device is present
status_t final_result = NO_INIT;
{
- AutoMutex lock(mHardwareLock);
+ audio_utils::lock_guard lock(hardwareMutex());
mHardwareStatus = AUDIO_HW_SET_PARAMETER;
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
sp<DeviceHalInterface> dev = mAudioHwDevs.valueAt(i)->hwDevice();
@@ -1812,7 +1819,7 @@
// and the thread is exited once the lock is released
sp<IAfThreadBase> thread;
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
thread = checkPlaybackThread_l(ioHandle);
if (thread == 0) {
thread = checkRecordThread_l(ioHandle);
@@ -1831,6 +1838,7 @@
}
if (thread != 0) {
status_t result = thread->setParameters(filteredKeyValuePairs);
+ audio_utils::lock_guard _l(mutex());
forwardParametersToDownstreamPatches_l(thread->id(), filteredKeyValuePairs);
return result;
}
@@ -1842,12 +1850,12 @@
ALOGVV("getParameters() io %d, keys %s, calling pid %d",
ioHandle, keys.c_str(), IPCThreadState::self()->getCallingPid());
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (ioHandle == AUDIO_IO_HANDLE_NONE) {
String8 out_s8;
- AutoMutex lock(mHardwareLock);
+ audio_utils::lock_guard lock(hardwareMutex());
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
String8 s;
mHardwareStatus = AUDIO_HW_GET_PARAMETER;
@@ -1885,7 +1893,7 @@
return 0;
}
- AutoMutex lock(mHardwareLock);
+ audio_utils::lock_guard lock(hardwareMutex());
if (mPrimaryHardwareDev == nullptr) {
return 0;
}
@@ -1957,7 +1965,7 @@
uint32_t AudioFlinger::getInputFramesLost(audio_io_handle_t ioHandle) const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
IAfRecordThread* const recordThread = checkRecordThread_l(ioHandle);
if (recordThread != NULL) {
@@ -1978,7 +1986,7 @@
return PERMISSION_DENIED;
}
- AutoMutex lock(mHardwareLock);
+ audio_utils::lock_guard lock(hardwareMutex());
if (mPrimaryHardwareDev == nullptr) {
return INVALID_OPERATION;
}
@@ -1997,7 +2005,7 @@
status_t AudioFlinger::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames,
audio_io_handle_t output) const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
IAfPlaybackThread* const playbackThread = checkPlaybackThread_l(output);
if (playbackThread != NULL) {
@@ -2009,14 +2017,14 @@
void AudioFlinger::registerClient(const sp<media::IAudioFlingerClient>& client)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (client == 0) {
return;
}
pid_t pid = IPCThreadState::self()->getCallingPid();
const uid_t uid = IPCThreadState::self()->getCallingUid();
{
- Mutex::Autolock _cl(mClientLock);
+ audio_utils::lock_guard _cl(clientMutex());
if (mNotificationClients.indexOfKey(pid) < 0) {
sp<NotificationClient> notificationClient = new NotificationClient(this,
client,
@@ -2032,9 +2040,10 @@
}
}
- // mClientLock should not be held here because ThreadBase::sendIoConfigEvent() will lock the
- // ThreadBase mutex and the locking order is ThreadBase::mLock then AudioFlinger::mClientLock.
- // the config change is always sent from playback or record threads to avoid deadlock
+ // clientMutex() should not be held here because ThreadBase::sendIoConfigEvent()
+ // will lock the ThreadBase::mutex() and the locking order is
+ // ThreadBase::mutex() then AudioFlinger::clientMutex().
+ // The config change is always sent from playback or record threads to avoid deadlock
// with AudioSystem::gLock
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
mPlaybackThreads.valueAt(i)->sendIoConfigEvent(AUDIO_OUTPUT_REGISTERED, pid);
@@ -2049,9 +2058,9 @@
{
std::vector<sp<IAfEffectModule>> removedEffects;
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
{
- Mutex::Autolock _cl(mClientLock);
+ audio_utils::lock_guard _cl(clientMutex());
mNotificationClients.removeItem(pid);
}
@@ -2083,7 +2092,8 @@
}
}
-void AudioFlinger::ioConfigChanged(audio_io_config_event_t event,
+// Hold either AudioFlinger::mutex or ThreadBase::mutex
+void AudioFlinger::ioConfigChanged_l(audio_io_config_event_t event,
const sp<AudioIoDescriptor>& ioDesc,
pid_t pid) {
media::AudioIoConfigEvent eventAidl = VALUE_OR_FATAL(
@@ -2091,7 +2101,7 @@
media::AudioIoDescriptor descAidl = VALUE_OR_FATAL(
legacy2aidl_AudioIoDescriptor_AudioIoDescriptor(ioDesc));
- Mutex::Autolock _l(mClientLock);
+ audio_utils::lock_guard _l(clientMutex());
size_t size = mNotificationClients.size();
for (size_t i = 0; i < size; i++) {
if ((pid == 0) || (mNotificationClients.keyAt(i) == pid)) {
@@ -2108,7 +2118,7 @@
convertContainer<std::vector<media::audio::common::AudioLatencyMode>>(
modes, legacy2aidl_audio_latency_mode_t_AudioLatencyMode));
- Mutex::Autolock _l(mClientLock);
+ audio_utils::lock_guard _l(clientMutex());
size_t size = mNotificationClients.size();
for (size_t i = 0; i < size; i++) {
mNotificationClients.valueAt(i)->audioFlingerClient()
@@ -2116,7 +2126,7 @@
}
}
-// removeClient_l() must be called with AudioFlinger::mClientLock held
+// removeClient_l() must be called with AudioFlinger::clientMutex() held
void AudioFlinger::removeClient_l(pid_t pid)
{
ALOGV("removeClient_l() pid %d, calling pid %d", pid,
@@ -2124,7 +2134,7 @@
mClients.removeItem(pid);
}
-// getEffectThread_l() must be called with AudioFlinger::mLock held
+// getEffectThread_l() must be called with AudioFlinger::mutex() held
sp<IAfThreadBase> AudioFlinger::getEffectThread_l(audio_session_t sessionId,
int effectId)
{
@@ -2183,9 +2193,9 @@
void AudioFlinger::MediaLogNotifier::requestMerge() {
- AutoMutex _l(mMutex);
+ audio_utils::lock_guard _l(mMutex);
mPendingRequests = true;
- mCond.signal();
+ mCondition.notify_one();
}
bool AudioFlinger::MediaLogNotifier::threadLoop() {
@@ -2195,10 +2205,10 @@
}
// Wait until there are pending requests
{
- AutoMutex _l(mMutex);
+ audio_utils::unique_lock _l(mMutex);
mPendingRequests = false; // to ignore past requests
while (!mPendingRequests) {
- mCond.wait(mMutex);
+ mCondition.wait(_l);
// TODO may also need an exitPending check
}
mPendingRequests = false;
@@ -2309,7 +2319,7 @@
}
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
IAfRecordThread* const thread = checkRecordThread_l(output.inputId);
if (thread == NULL) {
ALOGW("createRecord() checkRecordThread_l failed, input handle %d", output.inputId);
@@ -2366,7 +2376,7 @@
// session and move it to this thread.
sp<IAfEffectChain> chain = getOrphanEffectChain_l(sessionId);
if (chain != 0) {
- Mutex::Autolock _l2(thread->mutex());
+ audio_utils::lock_guard _l2(thread->mutex());
thread->addEffectChain_l(chain);
}
break;
@@ -2385,11 +2395,11 @@
Exit:
if (lStatus != NO_ERROR) {
// remove local strong reference to Client before deleting the RecordTrack so that the
- // Client destructor is called by the TrackBase destructor with mClientLock held
- // Don't hold mClientLock when releasing the reference on the track as the
+ // Client destructor is called by the TrackBase destructor with clientMutex() held
+ // Don't hold clientMutex() when releasing the reference on the track as the
// destructor will acquire it.
{
- Mutex::Autolock _cl(mClientLock);
+ audio_utils::lock_guard _cl(clientMutex());
client.clear();
}
recordTrack.clear();
@@ -2410,8 +2420,8 @@
if (config == nullptr) {
return BAD_VALUE;
}
- Mutex::Autolock _l(mLock);
- AutoMutex lock(mHardwareLock);
+ audio_utils::lock_guard _l(mutex());
+ audio_utils::lock_guard lock(hardwareMutex());
RETURN_STATUS_IF_ERROR(
mDevicesFactoryHal->getSurroundSoundConfig(&config->surroundSoundConfig));
RETURN_STATUS_IF_ERROR(mDevicesFactoryHal->getEngineConfig(&config->engineConfig));
@@ -2419,7 +2429,7 @@
RETURN_STATUS_IF_ERROR(mDevicesFactoryHal->getDeviceNames(&hwModuleNames));
std::set<AudioMode> allSupportedModes;
for (const auto& name : hwModuleNames) {
- AudioHwDevice* module = loadHwModule_l(name.c_str());
+ AudioHwDevice* module = loadHwModule_ll(name.c_str());
if (module == nullptr) continue;
media::AudioHwModule aidlModule;
if (module->hwDevice()->getAudioPorts(&aidlModule.ports) == OK &&
@@ -2454,14 +2464,15 @@
if (!settingsAllowed()) {
return AUDIO_MODULE_HANDLE_NONE;
}
- Mutex::Autolock _l(mLock);
- AutoMutex lock(mHardwareLock);
- AudioHwDevice* module = loadHwModule_l(name);
+ audio_utils::lock_guard _l(mutex());
+ audio_utils::lock_guard lock(hardwareMutex());
+ AudioHwDevice* module = loadHwModule_ll(name);
return module != nullptr ? module->handle() : AUDIO_MODULE_HANDLE_NONE;
}
-// loadHwModule_l() must be called with AudioFlinger::mLock and AudioFlinger::mHardwareLock held
-AudioHwDevice* AudioFlinger::loadHwModule_l(const char *name)
+// loadHwModule_l() must be called with AudioFlinger::mutex()
+// and AudioFlinger::hardwareMutex() held
+AudioHwDevice* AudioFlinger::loadHwModule_ll(const char *name)
{
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
if (strncmp(mAudioHwDevs.valueAt(i)->moduleName(), name, strlen(name)) == 0) {
@@ -2567,14 +2578,14 @@
uint32_t AudioFlinger::getPrimaryOutputSamplingRate() const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
IAfPlaybackThread* const thread = fastPlaybackThread_l();
return thread != NULL ? thread->sampleRate() : 0;
}
size_t AudioFlinger::getPrimaryOutputFrameCount() const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
IAfPlaybackThread* const thread = fastPlaybackThread_l();
return thread != NULL ? thread->frameCountHAL() : 0;
}
@@ -2587,7 +2598,7 @@
if (!isAudioServerOrSystemServerUid(uid)) {
return PERMISSION_DENIED;
}
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (mIsDeviceTypeKnown) {
return INVALID_OPERATION;
}
@@ -2645,8 +2656,8 @@
module = config->ext.mix.hw_module;
}
- Mutex::Autolock _l(mLock);
- AutoMutex lock(mHardwareLock);
+ audio_utils::lock_guard _l(mutex());
+ audio_utils::lock_guard lock(hardwareMutex());
ssize_t index = mAudioHwDevs.indexOfKey(module);
if (index < 0) {
ALOGW("%s() bad hw module %d", __func__, module);
@@ -2659,7 +2670,7 @@
audio_hw_sync_t AudioFlinger::getAudioHwSyncForSession(audio_session_t sessionId)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
ssize_t index = mHwAvSyncIds.indexOfKey(sessionId);
if (index >= 0) {
@@ -2670,7 +2681,7 @@
sp<DeviceHalInterface> dev;
{
- AutoMutex lock(mHardwareLock);
+ audio_utils::lock_guard lock(hardwareMutex());
if (mPrimaryHardwareDev == nullptr) {
return AUDIO_HW_SYNC_INVALID;
}
@@ -2719,7 +2730,7 @@
status_t AudioFlinger::systemReady()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
ALOGI("%s", __FUNCTION__);
if (mSystemReady) {
ALOGW("%s called twice", __FUNCTION__);
@@ -2762,7 +2773,7 @@
status_t AudioFlinger::getMicrophones(std::vector<media::MicrophoneInfoFw>* microphones) const
{
- AutoMutex lock(mHardwareLock);
+ audio_utils::lock_guard lock(hardwareMutex());
status_t status = INVALID_OPERATION;
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
@@ -2786,7 +2797,7 @@
return status;
}
-// setAudioHwSyncForSession_l() must be called with AudioFlinger::mLock held
+// setAudioHwSyncForSession_l() must be called with AudioFlinger::mutex() held
void AudioFlinger::setAudioHwSyncForSession_l(
IAfPlaybackThread* const thread, audio_session_t sessionId)
{
@@ -2925,7 +2936,7 @@
return BAD_VALUE;
}
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
const sp<IAfThreadBase> thread = openOutput_l(module, &output, &halConfig,
&mixerConfig, deviceType, address, flags);
@@ -2936,11 +2947,11 @@
latencyMs = playbackThread->latency();
// notify client processes of the new output creation
- playbackThread->ioConfigChanged(AUDIO_OUTPUT_OPENED);
+ playbackThread->ioConfigChanged_l(AUDIO_OUTPUT_OPENED);
// the first primary output opened designates the primary hw device if no HW module
// named "primary" was already loaded.
- AutoMutex lock(mHardwareLock);
+ audio_utils::lock_guard lock(hardwareMutex());
if ((mPrimaryHardwareDev == nullptr) && (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
ALOGI("Using module %d as the primary audio interface", module);
mPrimaryHardwareDev = playbackThread->getOutput()->audioHwDev;
@@ -2950,7 +2961,7 @@
mHardwareStatus = AUDIO_HW_IDLE;
}
} else {
- thread->ioConfigChanged(AUDIO_OUTPUT_OPENED);
+ thread->ioConfigChanged_l(AUDIO_OUTPUT_OPENED);
}
response->output = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(output));
response->config = VALUE_OR_RETURN_STATUS(
@@ -2967,7 +2978,7 @@
audio_io_handle_t AudioFlinger::openDuplicateOutput(audio_io_handle_t output1,
audio_io_handle_t output2)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
IAfPlaybackThread* const thread1 = checkMixerThread_l(output1);
IAfPlaybackThread* const thread2 = checkMixerThread_l(output2);
@@ -2983,7 +2994,7 @@
thread->addOutputTrack(thread2);
mPlaybackThreads.add(id, thread);
// notify client processes of the new output creation
- thread->ioConfigChanged(AUDIO_OUTPUT_OPENED);
+ thread->ioConfigChanged_l(AUDIO_OUTPUT_OPENED);
return id;
}
@@ -2999,7 +3010,7 @@
sp<IAfPlaybackThread> playbackThread;
sp<IAfMmapPlaybackThread> mmapThread;
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
playbackThread = checkPlaybackThread_l(output);
if (playbackThread != NULL) {
ALOGV("closeOutput() %d", output);
@@ -3024,11 +3035,11 @@
checkPlaybackThread_l(mPlaybackThreads.keyAt(0));
if (dstThread != NULL) {
// audioflinger lock is held so order of thread lock acquisition doesn't matter
- Mutex::Autolock _dl(dstThread->mutex());
- Mutex::Autolock _sl(playbackThread->mutex());
+ // Use scoped_lock to avoid deadlock order issues with duplicating threads.
+ audio_utils::scoped_lock sl(dstThread->mutex(), playbackThread->mutex());
Vector<sp<IAfEffectChain>> effectChains = playbackThread->getEffectChains_l();
for (size_t i = 0; i < effectChains.size(); i ++) {
- moveEffectChain_l(effectChains[i]->sessionId(), playbackThread.get(),
+ moveEffectChain_ll(effectChains[i]->sessionId(), playbackThread.get(),
dstThread);
}
}
@@ -3043,7 +3054,7 @@
mMmapThreads.removeItem(output);
ALOGD("closing mmapThread %p", mmapThread.get());
}
- ioConfigChanged(AUDIO_OUTPUT_CLOSED, sp<AudioIoDescriptor>::make(output));
+ ioConfigChanged_l(AUDIO_OUTPUT_CLOSED, sp<AudioIoDescriptor>::make(output));
mPatchPanel->notifyStreamClosed(output);
}
// The thread entity (active unit of execution) is no longer running here,
@@ -3065,6 +3076,7 @@
return NO_ERROR;
}
+/* static */
void AudioFlinger::closeOutputFinish(const sp<IAfPlaybackThread>& thread)
{
AudioStreamOut *out = thread->clearOutput();
@@ -3082,7 +3094,7 @@
status_t AudioFlinger::suspendOutput(audio_io_handle_t output)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
IAfPlaybackThread* const thread = checkPlaybackThread_l(output);
if (thread == NULL) {
@@ -3097,7 +3109,7 @@
status_t AudioFlinger::restoreOutput(audio_io_handle_t output)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
IAfPlaybackThread* const thread = checkPlaybackThread_l(output);
if (thread == NULL) {
@@ -3114,7 +3126,7 @@
status_t AudioFlinger::openInput(const media::OpenInputRequest& request,
media::OpenInputResponse* response)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
AudioDeviceTypeAddr device = VALUE_OR_RETURN_STATUS(
aidl2legacy_AudioDeviceTypeAddress(request.device));
@@ -3145,7 +3157,7 @@
if (thread != 0) {
// notify client processes of the new input creation
- thread->ioConfigChanged(AUDIO_INPUT_OPENED);
+ thread->ioConfigChanged_l(AUDIO_INPUT_OPENED);
return NO_ERROR;
}
return NO_INIT;
@@ -3251,7 +3263,7 @@
sp<IAfRecordThread> recordThread;
sp<IAfMmapCaptureThread> mmapThread;
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
recordThread = checkRecordThread_l(input);
if (recordThread != 0) {
ALOGV("closeInput() %d", input);
@@ -3264,7 +3276,7 @@
// new capture on the same session
sp<IAfEffectChain> chain;
{
- Mutex::Autolock _sl(recordThread->mutex());
+ audio_utils::lock_guard _sl(recordThread->mutex());
const Vector<sp<IAfEffectChain>> effectChains = recordThread->getEffectChains_l();
// Note: maximum one chain per record thread
if (effectChains.size() != 0) {
@@ -3282,7 +3294,7 @@
continue;
}
if (t->hasAudioSession(chain->sessionId()) != 0) {
- Mutex::Autolock _l2(t->mutex());
+ audio_utils::lock_guard _l2(t->mutex());
ALOGV("closeInput() found thread %d for effect session %d",
t->id(), chain->sessionId());
t->addEffectChain_l(chain);
@@ -3304,9 +3316,9 @@
dumpToThreadLog_l(mmapThread);
mMmapThreads.removeItem(input);
}
- ioConfigChanged(AUDIO_INPUT_CLOSED, sp<AudioIoDescriptor>::make(input));
+ ioConfigChanged_l(AUDIO_INPUT_CLOSED, sp<AudioIoDescriptor>::make(input));
}
- // FIXME: calling thread->exit() without mLock held should not be needed anymore now that
+ // FIXME: calling thread->exit() without mutex() held should not be needed anymore now that
// we have a different lock for notification client
if (recordThread != 0) {
closeInputFinish(recordThread);
@@ -3336,7 +3348,7 @@
}
status_t AudioFlinger::invalidateTracks(const std::vector<audio_port_handle_t> &portIds) {
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
ALOGV("%s", __func__);
std::set<audio_port_handle_t> portIdSet(portIds.begin(), portIds.end());
@@ -3371,7 +3383,7 @@
void AudioFlinger::acquireAudioSessionId(
audio_session_t audioSession, pid_t pid, uid_t uid)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
pid_t caller = IPCThreadState::self()->getCallingPid();
ALOGV("acquiring %d from %d, for %d", audioSession, caller, pid);
const uid_t callerUid = IPCThreadState::self()->getCallingUid();
@@ -3383,7 +3395,7 @@
}
{
- Mutex::Autolock _cl(mClientLock);
+ audio_utils::lock_guard _cl(clientMutex());
// Ignore requests received from processes not known as notification client. The request
// is likely proxied by mediaserver (e.g CameraService) and releaseAudioSessionId() can be
// called from a different pid leaving a stale session reference. Also we don't know how
@@ -3411,7 +3423,7 @@
{
std::vector<sp<IAfEffectModule>> removedEffects;
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
pid_t caller = IPCThreadState::self()->getCallingPid();
ALOGV("releasing %d from %d for %d", audioSession, caller, pid);
const uid_t callerUid = IPCThreadState::self()->getCallingUid();
@@ -3466,7 +3478,7 @@
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
sp<IAfPlaybackThread> t = mPlaybackThreads.valueAt(i);
- Mutex::Autolock _l(t->mutex());
+ audio_utils::lock_guard _l(t->mutex());
const Vector<sp<IAfEffectChain>> threadChains = t->getEffectChains_l();
for (size_t j = 0; j < threadChains.size(); j++) {
sp<IAfEffectChain> ec = threadChains[j];
@@ -3478,7 +3490,7 @@
for (size_t i = 0; i < mRecordThreads.size(); i++) {
sp<IAfRecordThread> t = mRecordThreads.valueAt(i);
- Mutex::Autolock _l(t->mutex());
+ audio_utils::lock_guard _l(t->mutex());
const Vector<sp<IAfEffectChain>> threadChains = t->getEffectChains_l();
for (size_t j = 0; j < threadChains.size(); j++) {
sp<IAfEffectChain> ec = threadChains[j];
@@ -3488,7 +3500,7 @@
for (size_t i = 0; i < mMmapThreads.size(); i++) {
const sp<IAfMmapThread> t = mMmapThreads.valueAt(i);
- Mutex::Autolock _l(t->mutex());
+ audio_utils::lock_guard _l(t->mutex());
const Vector<sp<IAfEffectChain>> threadChains = t->getEffectChains_l();
for (size_t j = 0; j < threadChains.size(); j++) {
sp<IAfEffectChain> ec = threadChains[j];
@@ -3516,7 +3528,7 @@
}
}
if (!found) {
- Mutex::Autolock _l(t->mutex());
+ audio_utils::lock_guard _l(t->mutex());
// remove all effects from the chain
while (ec->numberOfEffects()) {
sp<IAfEffectModule> effect = ec->getEffectModule(0);
@@ -3568,7 +3580,7 @@
return removedEffects;
}
-// dumpToThreadLog_l() must be called with AudioFlinger::mLock held
+// dumpToThreadLog_l() must be called with AudioFlinger::mutex() held
void AudioFlinger::dumpToThreadLog_l(const sp<IAfThreadBase> &thread)
{
constexpr int THREAD_DUMP_TIMEOUT_MS = 2;
@@ -3580,7 +3592,7 @@
}
}
-// checkThread_l() must be called with AudioFlinger::mLock held
+// checkThread_l() must be called with AudioFlinger::mutex() held
IAfThreadBase* AudioFlinger::checkThread_l(audio_io_handle_t ioHandle) const
{
IAfThreadBase* thread = checkMmapThread_l(ioHandle);
@@ -3599,7 +3611,7 @@
return thread;
}
-// checkOutputThread_l() must be called with AudioFlinger::mLock held
+// checkOutputThread_l() must be called with AudioFlinger::mutex() held
sp<IAfThreadBase> AudioFlinger::checkOutputThread_l(audio_io_handle_t ioHandle) const
{
if (audio_unique_id_get_use(ioHandle) != AUDIO_UNIQUE_ID_USE_OUTPUT) {
@@ -3613,33 +3625,33 @@
return thread;
}
-// checkPlaybackThread_l() must be called with AudioFlinger::mLock held
+// checkPlaybackThread_l() must be called with AudioFlinger::mutex() held
IAfPlaybackThread* AudioFlinger::checkPlaybackThread_l(audio_io_handle_t output) const
{
return mPlaybackThreads.valueFor(output).get();
}
-// checkMixerThread_l() must be called with AudioFlinger::mLock held
+// checkMixerThread_l() must be called with AudioFlinger::mutex() held
IAfPlaybackThread* AudioFlinger::checkMixerThread_l(audio_io_handle_t output) const
{
IAfPlaybackThread * const thread = checkPlaybackThread_l(output);
return thread != nullptr && thread->type() != IAfThreadBase::DIRECT ? thread : nullptr;
}
-// checkRecordThread_l() must be called with AudioFlinger::mLock held
+// checkRecordThread_l() must be called with AudioFlinger::mutex() held
IAfRecordThread* AudioFlinger::checkRecordThread_l(audio_io_handle_t input) const
{
return mRecordThreads.valueFor(input).get();
}
-// checkMmapThread_l() must be called with AudioFlinger::mLock held
+// checkMmapThread_l() must be called with AudioFlinger::mutex() held
IAfMmapThread* AudioFlinger::checkMmapThread_l(audio_io_handle_t io) const
{
return mMmapThreads.valueFor(io).get();
}
-// checkPlaybackThread_l() must be called with AudioFlinger::mLock held
+// checkPlaybackThread_l() must be called with AudioFlinger::mutex() held
sp<VolumeInterface> AudioFlinger::getVolumeInterface_l(audio_io_handle_t output) const
{
sp<VolumeInterface> volumeInterface = mPlaybackThreads.valueFor(output).get();
@@ -3695,7 +3707,7 @@
IAfPlaybackThread* AudioFlinger::primaryPlaybackThread_l() const
{
- AutoMutex lock(mHardwareLock);
+ audio_utils::lock_guard lock(hardwareMutex());
if (mPrimaryHardwareDev == nullptr) {
return nullptr;
}
@@ -3720,7 +3732,8 @@
return {};
}
- return thread->outDeviceTypes();
+ audio_utils::lock_guard l(thread->mutex());
+ return thread->outDeviceTypes_l();
}
IAfPlaybackThread* AudioFlinger::fastPlaybackThread_l() const
@@ -3784,7 +3797,7 @@
// The frameCount should also not be smaller than the secondary thread min frame
// count
size_t minFrameCount = AudioSystem::calculateMinFrameCount(
- [&] { Mutex::Autolock _l(secondaryThread->mutex());
+ [&] { audio_utils::lock_guard _l(secondaryThread->mutex());
return secondaryThread->latency_l(); }(),
secondaryThread->frameCount(), // normal frame count
secondaryThread->sampleRate(),
@@ -3852,7 +3865,7 @@
const audioflinger::SyncEventCallback& callBack,
const wp<IAfTrackBase>& cookie)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
auto event = sp<audioflinger::SyncEvent>::make(
type, triggerSession, listenerSession, callBack, cookie);
@@ -3889,7 +3902,7 @@
status_t AudioFlinger::queryNumberEffects(uint32_t *numEffects) const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (mEffectsFactoryHal.get()) {
return mEffectsFactoryHal->queryNumberEffects(numEffects);
} else {
@@ -3899,7 +3912,7 @@
status_t AudioFlinger::queryEffect(uint32_t index, effect_descriptor_t *descriptor) const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (mEffectsFactoryHal.get()) {
return mEffectsFactoryHal->getDescriptor(index, descriptor);
} else {
@@ -3916,7 +3929,7 @@
return BAD_VALUE;
}
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (!mEffectsFactoryHal.get()) {
return -ENODEV;
@@ -4036,7 +4049,11 @@
lStatus = BAD_VALUE;
goto Exit;
}
- IAfPlaybackThread* const thread = checkPlaybackThread_l(io);
+ IAfPlaybackThread* thread;
+ {
+ audio_utils::lock_guard l(mutex());
+ thread = checkPlaybackThread_l(io);
+ }
if (thread == nullptr) {
ALOGE("%s: invalid output %d specified for AUDIO_SESSION_OUTPUT_STAGE", __func__, io);
lStatus = BAD_VALUE;
@@ -4127,7 +4144,7 @@
ALOGV("createEffect got output %d", io);
}
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (sessionId == AUDIO_SESSION_DEVICE) {
sp<Client> client = registerPid(currentPid);
@@ -4136,8 +4153,8 @@
&descOut, device, client, effectClient, mPatchPanel->patches_l(),
&enabledOut, &lStatus, probe, request.notifyFramesProcessed);
if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
- // remove local strong reference to Client with mClientLock held
- Mutex::Autolock _cl(mClientLock);
+ // remove local strong reference to Client with clientMutex() held
+ audio_utils::lock_guard _cl(clientMutex());
client.clear();
} else {
// handle must be valid here, but check again to be safe.
@@ -4230,7 +4247,7 @@
// session and used it instead of creating a new one.
sp<IAfEffectChain> chain = getOrphanEffectChain_l(sessionId);
if (chain != 0) {
- Mutex::Autolock _l2(thread->mutex());
+ audio_utils::lock_guard _l2(thread->mutex());
thread->addEffectChain_l(chain);
}
}
@@ -4257,8 +4274,8 @@
&descOut, &enabledOut, &lStatus, pinned, probe,
request.notifyFramesProcessed);
if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
- // remove local strong reference to Client with mClientLock held
- Mutex::Autolock _cl(mClientLock);
+ // remove local strong reference to Client with clientMutex() held
+ audio_utils::lock_guard _cl(clientMutex());
client.clear();
} else {
// handle must be valid here, but check again to be safe.
@@ -4306,7 +4323,7 @@
NO_THREAD_SAFETY_ANALYSIS
{
ALOGV("%s() session %d, srcIo %d, dstIo %d", __func__, sessionId, srcIo, dstIo);
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (srcIo == dstIo) {
ALOGW("%s() same dst and src outputs %d", __func__, dstIo);
return NO_ERROR;
@@ -4320,7 +4337,7 @@
if (dstRecordThread != nullptr) {
dstRecordThread->mutex().lock();
}
- status_t ret = moveEffectChain_l(sessionId, srcRecordThread, dstRecordThread);
+ status_t ret = moveEffectChain_ll(sessionId, srcRecordThread, dstRecordThread);
if (srcRecordThread != nullptr) {
srcRecordThread->mutex().unlock();
}
@@ -4340,9 +4357,8 @@
return BAD_VALUE;
}
- Mutex::Autolock _dl(dstThread->mutex());
- Mutex::Autolock _sl(srcThread->mutex());
- return moveEffectChain_l(sessionId, srcThread, dstThread);
+ audio_utils::scoped_lock _ll(dstThread->mutex(), srcThread->mutex());
+ return moveEffectChain_ll(sessionId, srcThread, dstThread);
}
@@ -4350,38 +4366,38 @@
audio_session_t sessionId,
bool suspended)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
sp<IAfThreadBase> thread = getEffectThread_l(sessionId, effectId);
if (thread == nullptr) {
return;
}
- Mutex::Autolock _sl(thread->mutex());
+ audio_utils::lock_guard _sl(thread->mutex());
sp<IAfEffectModule> effect = thread->getEffect_l(sessionId, effectId);
thread->setEffectSuspended_l(&effect->desc().type, suspended, sessionId);
}
-// moveEffectChain_l must be called with both srcThread and dstThread mLocks held
-status_t AudioFlinger::moveEffectChain_l(audio_session_t sessionId,
+// moveEffectChain_ll must be called with the AudioFlinger::mutex()
+// and both srcThread and dstThread mutex()s held
+status_t AudioFlinger::moveEffectChain_ll(audio_session_t sessionId,
IAfPlaybackThread* srcThread, IAfPlaybackThread* dstThread)
-NO_THREAD_SAFETY_ANALYSIS // requires srcThread and dstThread locks
{
- ALOGV("moveEffectChain_l() session %d from thread %p to thread %p",
- sessionId, srcThread, dstThread);
+ ALOGV("%s: session %d from thread %p to thread %p",
+ __func__, sessionId, srcThread, dstThread);
sp<IAfEffectChain> chain = srcThread->getEffectChain_l(sessionId);
if (chain == 0) {
- ALOGW("moveEffectChain_l() effect chain for session %d not on source thread %p",
- sessionId, srcThread);
+ ALOGW("%s: effect chain for session %d not on source thread %p",
+ __func__, sessionId, srcThread);
return INVALID_OPERATION;
}
// Check whether the destination thread and all effects in the chain are compatible
if (!chain->isCompatibleWithThread_l(dstThread)) {
- ALOGW("moveEffectChain_l() effect chain failed because"
+ ALOGW("%s: effect chain failed because"
" destination thread %p is not compatible with effects in the chain",
- dstThread);
+ __func__, dstThread);
return INVALID_OPERATION;
}
@@ -4403,7 +4419,7 @@
effect = chain->getEffectFromId_l(0)) {
srcThread->removeEffect_l(effect);
removed.add(effect);
- status = dstThread->addEffect_l(effect);
+ status = dstThread->addEffect_ll(effect);
if (status != NO_ERROR) {
errorString = StringPrintf(
"cannot add effect %p to destination thread", effect.get());
@@ -4429,7 +4445,7 @@
for (const auto& effect : removed) {
dstThread->removeEffect_l(effect); // Note: Depending on error location, the last
// effect may not have been placed on dstThread.
- if (srcThread->addEffect_l(effect) == NO_ERROR) {
+ if (srcThread->addEffect_ll(effect) == NO_ERROR) {
++restored;
if (dstChain == nullptr) {
dstChain = effect->getCallback()->chain().promote();
@@ -4445,7 +4461,7 @@
// If we do not take the dstChain lock, it is possible that processing is ongoing
// while we are starting the effect. This can cause glitches with volume,
// see b/202360137.
- dstChain->lock();
+ dstChain->mutex().lock();
for (const auto& effect : removed) {
if (effect->state() == IAfEffectModule::ACTIVE ||
effect->state() == IAfEffectModule::STOPPING) {
@@ -4453,7 +4469,7 @@
effect->start();
}
}
- dstChain->unlock();
+ dstChain->mutex().unlock();
}
if (status != NO_ERROR) {
@@ -4474,11 +4490,10 @@
}
-// moveEffectChain_l must be called with both srcThread (if not null) and dstThread (if not null)
-// mLocks held
-status_t AudioFlinger::moveEffectChain_l(audio_session_t sessionId,
+// moveEffectChain_ll must be called with both srcThread (if not null) and dstThread (if not null)
+// mutex()s held
+status_t AudioFlinger::moveEffectChain_ll(audio_session_t sessionId,
IAfRecordThread* srcThread, IAfRecordThread* dstThread)
-NO_THREAD_SAFETY_ANALYSIS // requires srcThread and dstThread locks
{
sp<IAfEffectChain> chain = nullptr;
if (srcThread != 0) {
@@ -4520,13 +4535,12 @@
const sp<IAfPlaybackThread>& dstThread, sp<IAfPlaybackThread>* srcThread)
{
status_t status = NO_ERROR;
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
const sp<IAfThreadBase> threadBase = getEffectThread_l(AUDIO_SESSION_OUTPUT_MIX, EffectId);
const sp<IAfPlaybackThread> thread = threadBase ? threadBase->asIAfPlaybackThread() : nullptr;
if (EffectId != 0 && thread != 0 && dstThread != thread.get()) {
- Mutex::Autolock _dl(dstThread->mutex());
- Mutex::Autolock _sl(thread->mutex());
+ audio_utils::scoped_lock _ll(dstThread->mutex(), thread->mutex());
sp<IAfEffectChain> srcChain = thread->getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
sp<IAfEffectChain> dstChain;
if (srcChain == 0) {
@@ -4538,16 +4552,16 @@
return INVALID_OPERATION;
}
thread->removeEffect_l(effect);
- status = dstThread->addEffect_l(effect);
+ status = dstThread->addEffect_ll(effect);
if (status != NO_ERROR) {
- thread->addEffect_l(effect);
+ thread->addEffect_ll(effect);
status = INVALID_OPERATION;
goto Exit;
}
dstChain = effect->getCallback()->chain().promote();
if (dstChain == 0) {
- thread->addEffect_l(effect);
+ thread->addEffect_ll(effect);
status = INVALID_OPERATION;
}
@@ -4566,7 +4580,6 @@
}
bool AudioFlinger::isNonOffloadableGlobalEffectEnabled_l() const
-NO_THREAD_SAFETY_ANALYSIS // thread lock for getEffectChain_l.
{
if (mGlobalEffectEnableTime != 0 &&
((systemTime() - mGlobalEffectEnableTime) < kMinGlobalEffectEnabletimeNs)) {
@@ -4574,8 +4587,9 @@
}
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
- sp<IAfEffectChain> ec =
- mPlaybackThreads.valueAt(i)->getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
+ const auto thread = mPlaybackThreads.valueAt(i);
+ audio_utils::lock_guard l(thread->mutex());
+ const sp<IAfEffectChain> ec = thread->getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
if (ec != 0 && ec->isNonOffloadableEnabled()) {
return true;
}
@@ -4585,7 +4599,7 @@
void AudioFlinger::onNonOffloadableGlobalEffectEnable()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
mGlobalEffectEnableTime = systemTime();
@@ -4630,7 +4644,7 @@
bool AudioFlinger::updateOrphanEffectChains(const sp<IAfEffectModule>& effect)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
return updateOrphanEffectChains_l(effect);
}
@@ -4657,8 +4671,8 @@
status_t AudioFlinger::listAudioPorts(unsigned int* num_ports,
struct audio_port* ports) const
{
- Mutex::Autolock _l(mLock);
- return mPatchPanel->listAudioPorts(num_ports, ports);
+ audio_utils::lock_guard _l(mutex());
+ return mPatchPanel->listAudioPorts_l(num_ports, ports);
}
/* Get supported attributes for a given audio port */
@@ -4668,8 +4682,8 @@
return status;
}
- Mutex::Autolock _l(mLock);
- return mPatchPanel->getAudioPort(port);
+ audio_utils::lock_guard _l(mutex());
+ return mPatchPanel->getAudioPort_l(port);
}
/* Connect a patch between several source and sink ports */
@@ -4681,23 +4695,23 @@
return status;
}
- Mutex::Autolock _l(mLock);
- return mPatchPanel->createAudioPatch(patch, handle);
+ audio_utils::lock_guard _l(mutex());
+ return mPatchPanel->createAudioPatch_l(patch, handle);
}
/* Disconnect a patch */
status_t AudioFlinger::releaseAudioPatch(audio_patch_handle_t handle)
{
- Mutex::Autolock _l(mLock);
- return mPatchPanel->releaseAudioPatch(handle);
+ audio_utils::lock_guard _l(mutex());
+ return mPatchPanel->releaseAudioPatch_l(handle);
}
/* List connected audio ports and they attributes */
status_t AudioFlinger::listAudioPatches(
unsigned int* num_patches, struct audio_patch* patches) const
{
- Mutex::Autolock _l(mLock);
- return mPatchPanel->listAudioPatches(num_patches, patches);
+ audio_utils::lock_guard _l(mutex());
+ return mPatchPanel->listAudioPatches_l(num_patches, patches);
}
// ----------------------------------------------------------------------------
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 6516756..6af8015 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -29,6 +29,7 @@
#include "PatchCommandThread.h"
// External classes
+#include <audio_utils/mutex.h>
#include <audio_utils/FdToString.h>
#include <audio_utils/SimpleLog.h>
#include <media/IAudioFlinger.h>
@@ -64,187 +65,213 @@
// ---- begin IAudioFlinger interface
- status_t dump(int fd, const Vector<String16>& args) final;
+ status_t dump(int fd, const Vector<String16>& args) final EXCLUDES_AudioFlinger_Mutex;
status_t createTrack(const media::CreateTrackRequest& input,
- media::CreateTrackResponse& output) final;
+ media::CreateTrackResponse& output) final EXCLUDES_AudioFlinger_Mutex;
status_t createRecord(const media::CreateRecordRequest& input,
- media::CreateRecordResponse& output) final;
+ media::CreateRecordResponse& output) final EXCLUDES_AudioFlinger_Mutex;
- uint32_t sampleRate(audio_io_handle_t ioHandle) const final;
- audio_format_t format(audio_io_handle_t output) const final;
- size_t frameCount(audio_io_handle_t ioHandle) const final;
- size_t frameCountHAL(audio_io_handle_t ioHandle) const final;
- uint32_t latency(audio_io_handle_t output) const final;
+ uint32_t sampleRate(audio_io_handle_t ioHandle) const final EXCLUDES_AudioFlinger_Mutex;
+ audio_format_t format(audio_io_handle_t output) const final EXCLUDES_AudioFlinger_Mutex;
+ size_t frameCount(audio_io_handle_t ioHandle) const final EXCLUDES_AudioFlinger_Mutex;
+ size_t frameCountHAL(audio_io_handle_t ioHandle) const final EXCLUDES_AudioFlinger_Mutex;
+ uint32_t latency(audio_io_handle_t output) const final EXCLUDES_AudioFlinger_Mutex;
- status_t setMasterVolume(float value) final;
- status_t setMasterMute(bool muted) final;
- float masterVolume() const final;
- bool masterMute() const final;
+ status_t setMasterVolume(float value) final EXCLUDES_AudioFlinger_Mutex;
+ status_t setMasterMute(bool muted) final EXCLUDES_AudioFlinger_Mutex;
+ float masterVolume() const final EXCLUDES_AudioFlinger_Mutex;
+ bool masterMute() const final EXCLUDES_AudioFlinger_Mutex;
// Balance value must be within -1.f (left only) to 1.f (right only) inclusive.
- status_t setMasterBalance(float balance) final;
- status_t getMasterBalance(float* balance) const final;
+ status_t setMasterBalance(float balance) final EXCLUDES_AudioFlinger_Mutex;
+ status_t getMasterBalance(float* balance) const final EXCLUDES_AudioFlinger_Mutex;
status_t setStreamVolume(audio_stream_type_t stream, float value,
- audio_io_handle_t output) final;
- status_t setStreamMute(audio_stream_type_t stream, bool muted) final;
+ audio_io_handle_t output) final EXCLUDES_AudioFlinger_Mutex;
+ status_t setStreamMute(audio_stream_type_t stream, bool muted) final
+ EXCLUDES_AudioFlinger_Mutex;
float streamVolume(audio_stream_type_t stream,
- audio_io_handle_t output) const final;
- bool streamMute(audio_stream_type_t stream) const final;
+ audio_io_handle_t output) const final EXCLUDES_AudioFlinger_Mutex;
+ bool streamMute(audio_stream_type_t stream) const final EXCLUDES_AudioFlinger_Mutex;
- status_t setMode(audio_mode_t mode) final;
+ status_t setMode(audio_mode_t mode) final EXCLUDES_AudioFlinger_Mutex;
- status_t setMicMute(bool state) final;
- bool getMicMute() const final;
+ status_t setMicMute(bool state) final EXCLUDES_AudioFlinger_Mutex;
+ bool getMicMute() const final EXCLUDES_AudioFlinger_Mutex;
- void setRecordSilenced(audio_port_handle_t portId, bool silenced) final;
+ void setRecordSilenced(audio_port_handle_t portId, bool silenced) final
+ EXCLUDES_AudioFlinger_Mutex;
- status_t setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs) final;
- String8 getParameters(audio_io_handle_t ioHandle, const String8& keys) const final;
+ status_t setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs) final
+ EXCLUDES_AudioFlinger_Mutex;
+ String8 getParameters(audio_io_handle_t ioHandle, const String8& keys) const final
+ EXCLUDES_AudioFlinger_Mutex;
- void registerClient(const sp<media::IAudioFlingerClient>& client) final;
+ void registerClient(const sp<media::IAudioFlingerClient>& client) final
+ EXCLUDES_AudioFlinger_Mutex;
size_t getInputBufferSize(uint32_t sampleRate, audio_format_t format,
- audio_channel_mask_t channelMask) const final;
+ audio_channel_mask_t channelMask) const final EXCLUDES_AudioFlinger_Mutex;
status_t openOutput(const media::OpenOutputRequest& request,
- media::OpenOutputResponse* response) final;
+ media::OpenOutputResponse* response) final EXCLUDES_AudioFlinger_Mutex;
audio_io_handle_t openDuplicateOutput(audio_io_handle_t output1,
- audio_io_handle_t output2) final;
+ audio_io_handle_t output2) final EXCLUDES_AudioFlinger_Mutex;
- status_t closeOutput(audio_io_handle_t output) final;
+ status_t closeOutput(audio_io_handle_t output) final EXCLUDES_AudioFlinger_Mutex;
- status_t suspendOutput(audio_io_handle_t output) final;
+ status_t suspendOutput(audio_io_handle_t output) final EXCLUDES_AudioFlinger_Mutex;
- status_t restoreOutput(audio_io_handle_t output) final;
+ status_t restoreOutput(audio_io_handle_t output) final EXCLUDES_AudioFlinger_Mutex;
status_t openInput(const media::OpenInputRequest& request,
- media::OpenInputResponse* response) final;
+ media::OpenInputResponse* response) final EXCLUDES_AudioFlinger_Mutex;
- status_t closeInput(audio_io_handle_t input) final;
+ status_t closeInput(audio_io_handle_t input) final EXCLUDES_AudioFlinger_Mutex;
- status_t setVoiceVolume(float volume) final;
+ status_t setVoiceVolume(float volume) final EXCLUDES_AudioFlinger_Mutex;
status_t getRenderPosition(uint32_t* halFrames, uint32_t* dspFrames,
- audio_io_handle_t output) const final;
+ audio_io_handle_t output) const final EXCLUDES_AudioFlinger_Mutex;
- uint32_t getInputFramesLost(audio_io_handle_t ioHandle) const final;
+ uint32_t getInputFramesLost(audio_io_handle_t ioHandle) const final
+ EXCLUDES_AudioFlinger_Mutex;
// This is the binder API. For the internal API see nextUniqueId().
- audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t use) final;
+ audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t use) final
+ EXCLUDES_AudioFlinger_Mutex;
- void acquireAudioSessionId(audio_session_t audioSession, pid_t pid, uid_t uid) final;
+ void acquireAudioSessionId(audio_session_t audioSession, pid_t pid, uid_t uid) final
+ EXCLUDES_AudioFlinger_Mutex;
- void releaseAudioSessionId(audio_session_t audioSession, pid_t pid) final;
+ void releaseAudioSessionId(audio_session_t audioSession, pid_t pid) final
+ EXCLUDES_AudioFlinger_Mutex;
- status_t queryNumberEffects(uint32_t* numEffects) const final;
+ status_t queryNumberEffects(uint32_t* numEffects) const final EXCLUDES_AudioFlinger_Mutex;
- status_t queryEffect(uint32_t index, effect_descriptor_t* descriptor) const final;
+ status_t queryEffect(uint32_t index, effect_descriptor_t* descriptor) const final
+ EXCLUDES_AudioFlinger_Mutex;
status_t getEffectDescriptor(const effect_uuid_t* pUuid,
const effect_uuid_t* pTypeUuid,
uint32_t preferredTypeFlag,
- effect_descriptor_t* descriptor) const final;
+ effect_descriptor_t* descriptor) const final EXCLUDES_AudioFlinger_Mutex;
status_t createEffect(const media::CreateEffectRequest& request,
- media::CreateEffectResponse* response) final;
+ media::CreateEffectResponse* response) final EXCLUDES_AudioFlinger_Mutex;
status_t moveEffects(audio_session_t sessionId, audio_io_handle_t srcOutput,
- audio_io_handle_t dstOutput) final;
+ audio_io_handle_t dstOutput) final EXCLUDES_AudioFlinger_Mutex;
void setEffectSuspended(int effectId,
audio_session_t sessionId,
- bool suspended) final;
+ bool suspended) final EXCLUDES_AudioFlinger_Mutex;
- audio_module_handle_t loadHwModule(const char* name) final;
+ audio_module_handle_t loadHwModule(const char* name) final EXCLUDES_AudioFlinger_Mutex;
- uint32_t getPrimaryOutputSamplingRate() const final;
- size_t getPrimaryOutputFrameCount() const final;
+ uint32_t getPrimaryOutputSamplingRate() const final EXCLUDES_AudioFlinger_Mutex;
+ size_t getPrimaryOutputFrameCount() const final EXCLUDES_AudioFlinger_Mutex;
- status_t setLowRamDevice(bool isLowRamDevice, int64_t totalMemory) final;
+ status_t setLowRamDevice(bool isLowRamDevice, int64_t totalMemory) final
+ EXCLUDES_AudioFlinger_Mutex;
/* Get attributes for a given audio port */
- status_t getAudioPort(struct audio_port_v7* port) const final;
+ status_t getAudioPort(struct audio_port_v7* port) const final EXCLUDES_AudioFlinger_Mutex;
/* Create an audio patch between several source and sink ports */
status_t createAudioPatch(const struct audio_patch *patch,
- audio_patch_handle_t* handle) final;
+ audio_patch_handle_t* handle) final EXCLUDES_AudioFlinger_Mutex;
/* Release an audio patch */
- status_t releaseAudioPatch(audio_patch_handle_t handle) final;
+ status_t releaseAudioPatch(audio_patch_handle_t handle) final EXCLUDES_AudioFlinger_Mutex;
/* List existing audio patches */
status_t listAudioPatches(unsigned int* num_patches,
- struct audio_patch* patches) const final;
+ struct audio_patch* patches) const final EXCLUDES_AudioFlinger_Mutex;
/* Set audio port configuration */
- status_t setAudioPortConfig(const struct audio_port_config* config) final;
+ status_t setAudioPortConfig(const struct audio_port_config* config) final
+ EXCLUDES_AudioFlinger_Mutex;
/* Get the HW synchronization source used for an audio session */
- audio_hw_sync_t getAudioHwSyncForSession(audio_session_t sessionId) final;
+ audio_hw_sync_t getAudioHwSyncForSession(audio_session_t sessionId) final
+ EXCLUDES_AudioFlinger_Mutex;
/* Indicate JAVA services are ready (scheduling, power management ...) */
- status_t systemReady() final;
+ status_t systemReady() final EXCLUDES_AudioFlinger_Mutex;
status_t audioPolicyReady() final { mAudioPolicyReady.store(true); return NO_ERROR; }
- status_t getMicrophones(std::vector<media::MicrophoneInfoFw>* microphones) const final;
+ status_t getMicrophones(std::vector<media::MicrophoneInfoFw>* microphones) const final
+ EXCLUDES_AudioFlinger_Mutex;
- status_t setAudioHalPids(const std::vector<pid_t>& pids) final;
+ status_t setAudioHalPids(const std::vector<pid_t>& pids) final
+ EXCLUDES_AudioFlinger_Mutex;
- status_t setVibratorInfos(const std::vector<media::AudioVibratorInfo>& vibratorInfos) final;
+ status_t setVibratorInfos(const std::vector<media::AudioVibratorInfo>& vibratorInfos) final
+ EXCLUDES_AudioFlinger_Mutex;
status_t updateSecondaryOutputs(
- const TrackSecondaryOutputsMap& trackSecondaryOutputs) final;
+ const TrackSecondaryOutputsMap& trackSecondaryOutputs) final
+ EXCLUDES_AudioFlinger_Mutex;
status_t getMmapPolicyInfos(
media::audio::common::AudioMMapPolicyType policyType,
- std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos) final;
+ std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos) final
+ EXCLUDES_AudioFlinger_Mutex;
- int32_t getAAudioMixerBurstCount() const final;
+ int32_t getAAudioMixerBurstCount() const final EXCLUDES_AudioFlinger_Mutex;
- int32_t getAAudioHardwareBurstMinUsec() const final;
+ int32_t getAAudioHardwareBurstMinUsec() const final EXCLUDES_AudioFlinger_Mutex;
status_t setDeviceConnectedState(const struct audio_port_v7* port,
- media::DeviceConnectedState state) final;
+ media::DeviceConnectedState state) final EXCLUDES_AudioFlinger_Mutex;
- status_t setSimulateDeviceConnections(bool enabled) final;
+ status_t setSimulateDeviceConnections(bool enabled) final EXCLUDES_AudioFlinger_Mutex;
status_t setRequestedLatencyMode(
- audio_io_handle_t output, audio_latency_mode_t mode) final;
+ audio_io_handle_t output, audio_latency_mode_t mode) final
+ EXCLUDES_AudioFlinger_Mutex;
status_t getSupportedLatencyModes(audio_io_handle_t output,
- std::vector<audio_latency_mode_t>* modes) const final;
+ std::vector<audio_latency_mode_t>* modes) const final EXCLUDES_AudioFlinger_Mutex;
- status_t setBluetoothVariableLatencyEnabled(bool enabled) final;
+ status_t setBluetoothVariableLatencyEnabled(bool enabled) final EXCLUDES_AudioFlinger_Mutex;
- status_t isBluetoothVariableLatencyEnabled(bool* enabled) const final;
+ status_t isBluetoothVariableLatencyEnabled(bool* enabled) const final
+ EXCLUDES_AudioFlinger_Mutex;
- status_t supportsBluetoothVariableLatency(bool* support) const final;
+ status_t supportsBluetoothVariableLatency(bool* support) const final
+ EXCLUDES_AudioFlinger_Mutex;
status_t getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback,
- sp<media::ISoundDose>* soundDose) const final;
+ sp<media::ISoundDose>* soundDose) const final EXCLUDES_AudioFlinger_Mutex;
- status_t invalidateTracks(const std::vector<audio_port_handle_t>& portIds) final;
+ status_t invalidateTracks(const std::vector<audio_port_handle_t>& portIds) final
+ EXCLUDES_AudioFlinger_Mutex;
- status_t getAudioPolicyConfig(media::AudioPolicyConfig* config) final;
+ status_t getAudioPolicyConfig(media::AudioPolicyConfig* config) final
+ EXCLUDES_AudioFlinger_Mutex;
status_t onTransactWrapper(TransactionCode code, const Parcel& data, uint32_t flags,
- const std::function<status_t()>& delegate) final;
+ const std::function<status_t()>& delegate) final EXCLUDES_AudioFlinger_Mutex;
// ---- end of IAudioFlinger interface
// ---- begin IAfClientCallback interface
- Mutex& clientMutex() const final { return mClientLock; }
- void removeClient_l(pid_t pid) final;
- void removeNotificationClient(pid_t pid) final;
+ audio_utils::mutex& clientMutex() const final
+ RETURN_CAPABILITY(audio_utils::AudioFlinger_ClientMutex) {
+ return mClientMutex;
+ }
+ void removeClient_l(pid_t pid) REQUIRES(clientMutex()) final;
+ void removeNotificationClient(pid_t pid) final EXCLUDES_AudioFlinger_Mutex;
status_t moveAuxEffectToIo(
int effectId,
const sp<IAfPlaybackThread>& dstThread,
- sp<IAfPlaybackThread>* srcThread) final;
+ sp<IAfPlaybackThread>* srcThread) final EXCLUDES_AudioFlinger_Mutex;
// ---- end of IAfClientCallback interface
@@ -255,31 +282,35 @@
// below also used by IAfMelReporterCallback, IAfPatchPanelCallback
const sp<PatchCommandThread>& getPatchCommandThread() final { return mPatchCommandThread; }
status_t addEffectToHal(
- const struct audio_port_config* device, const sp<EffectHalInterface>& effect) final;
+ const struct audio_port_config* device, const sp<EffectHalInterface>& effect) final
+ EXCLUDES_AudioFlinger_HardwareMutex;
status_t removeEffectFromHal(
- const struct audio_port_config* device, const sp<EffectHalInterface>& effect) final;
+ const struct audio_port_config* device, const sp<EffectHalInterface>& effect) final
+ EXCLUDES_AudioFlinger_HardwareMutex;
// ---- end of IAfDeviceEffectManagerCallback interface
// ---- begin IAfMelReporterCallback interface
// below also used by IAfThreadCallback
- Mutex& mutex() const final { return mLock; }
- sp<IAfThreadBase> checkOutputThread_l(audio_io_handle_t ioHandle) const final REQUIRES(mLock);
+ audio_utils::mutex& mutex() const final
+ RETURN_CAPABILITY(audio_utils::AudioFlinger_Mutex)
+ EXCLUDES_BELOW_AudioFlinger_Mutex { return mMutex; }
+ sp<IAfThreadBase> checkOutputThread_l(audio_io_handle_t ioHandle) const final
+ REQUIRES(mutex());
// ---- end of IAfMelReporterCallback interface
// ---- begin IAfPatchPanelCallback interface
- void closeThreadInternal_l(const sp<IAfPlaybackThread>& thread) final;
- void closeThreadInternal_l(const sp<IAfRecordThread>& thread) final;
+ void closeThreadInternal_l(const sp<IAfPlaybackThread>& thread) final REQUIRES(mutex());
+ void closeThreadInternal_l(const sp<IAfRecordThread>& thread) final REQUIRES(mutex());
// return thread associated with primary hardware device, or NULL
- IAfPlaybackThread* primaryPlaybackThread_l() const final;
- IAfPlaybackThread* checkPlaybackThread_l(audio_io_handle_t output) const final;
- IAfRecordThread* checkRecordThread_l(audio_io_handle_t input) const final;
- IAfMmapThread* checkMmapThread_l(audio_io_handle_t io) const final;
- void lock() const final ACQUIRE(mLock) { mLock.lock(); }
- void unlock() const final RELEASE(mLock) { mLock.unlock(); }
+ IAfPlaybackThread* primaryPlaybackThread_l() const final REQUIRES(mutex());
+ IAfPlaybackThread* checkPlaybackThread_l(audio_io_handle_t output) const final
+ REQUIRES(mutex());
+ IAfRecordThread* checkRecordThread_l(audio_io_handle_t input) const final REQUIRES(mutex());
+ IAfMmapThread* checkMmapThread_l(audio_io_handle_t io) const final REQUIRES(mutex());
sp<IAfThreadBase> openInput_l(audio_module_handle_t module,
audio_io_handle_t* input,
audio_config_t* config,
@@ -288,36 +319,41 @@
audio_source_t source,
audio_input_flags_t flags,
audio_devices_t outputDevice,
- const String8& outputDeviceAddress) final;
+ const String8& outputDeviceAddress) final REQUIRES(mutex());
sp<IAfThreadBase> openOutput_l(audio_module_handle_t module,
audio_io_handle_t* output,
audio_config_t* halConfig,
audio_config_base_t* mixerConfig,
audio_devices_t deviceType,
const String8& address,
- audio_output_flags_t flags) final;
+ audio_output_flags_t flags) final REQUIRES(mutex());
const DefaultKeyedVector<audio_module_handle_t, AudioHwDevice*>&
- getAudioHwDevs_l() const final { return mAudioHwDevs; }
+ getAudioHwDevs_l() const final REQUIRES(mutex()) { return mAudioHwDevs; }
void updateDownStreamPatches_l(const struct audio_patch* patch,
- const std::set<audio_io_handle_t>& streams) final;
- void updateOutDevicesForRecordThreads_l(const DeviceDescriptorBaseVector& devices) final;
+ const std::set<audio_io_handle_t>& streams) final REQUIRES(mutex());
+ void updateOutDevicesForRecordThreads_l(const DeviceDescriptorBaseVector& devices) final
+ REQUIRES(mutex());
// ---- end of IAfPatchPanelCallback interface
// ----- begin IAfThreadCallback interface
- bool isNonOffloadableGlobalEffectEnabled_l() const final;
+ bool isNonOffloadableGlobalEffectEnabled_l() const final
+ REQUIRES(mutex()) EXCLUDES_ThreadBase_Mutex;
bool btNrecIsOff() const final { return mBtNrecIsOff.load(); }
- float masterVolume_l() const final;
- bool masterMute_l() const final;
- float getMasterBalance_l() const;
- // no range check, AudioFlinger::mLock held
- bool streamMute_l(audio_stream_type_t stream) const final { return mStreamTypes[stream].mute; }
+ float masterVolume_l() const final REQUIRES(mutex());
+ bool masterMute_l() const final REQUIRES(mutex());
+ float getMasterBalance_l() const REQUIRES(mutex());
+ // no range check, AudioFlinger::mutex() held
+ bool streamMute_l(audio_stream_type_t stream) const final REQUIRES(mutex()) {
+ return mStreamTypes[stream].mute;
+ }
audio_mode_t getMode() const final { return mMode; }
bool isLowRamDevice() const final { return mIsLowRamDevice; }
uint32_t getScreenState() const final { return mScreenState; }
- std::optional<media::AudioVibratorInfo> getDefaultVibratorInfo_l() const final;
+ std::optional<media::AudioVibratorInfo> getDefaultVibratorInfo_l() const final
+ REQUIRES(mutex());
const sp<IAfPatchPanel>& getPatchPanel() const final { return mPatchPanel; }
const sp<MelReporter>& getMelReporter() const final { return mMelReporter; }
const sp<EffectsFactoryHalInterface>& getEffectsFactoryHal() const final {
@@ -329,34 +365,39 @@
// effect belongs to an effect chain in mOrphanEffectChains, the chain is updated
// and removed from mOrphanEffectChains if it does not contain any effect.
// Return true if the effect was found in mOrphanEffectChains, false otherwise.
- bool updateOrphanEffectChains(const sp<IAfEffectModule>& effect) final;
+ bool updateOrphanEffectChains(const sp<IAfEffectModule>& effect) final
+ EXCLUDES_AudioFlinger_Mutex;
- status_t moveEffectChain_l(audio_session_t sessionId,
- IAfPlaybackThread* srcThread, IAfPlaybackThread* dstThread) final;
+ status_t moveEffectChain_ll(audio_session_t sessionId,
+ IAfPlaybackThread* srcThread, IAfPlaybackThread* dstThread) final
+ REQUIRES(mutex(), audio_utils::ThreadBase_Mutex);
// This is a helper that is called during incoming binder calls.
// Requests media.log to start merging log buffers
void requestLogMerge() final;
- sp<NBLog::Writer> newWriter_l(size_t size, const char *name) final;
+ sp<NBLog::Writer> newWriter_l(size_t size, const char *name) final REQUIRES(mutex());
void unregisterWriter(const sp<NBLog::Writer>& writer) final;
sp<audioflinger::SyncEvent> createSyncEvent(AudioSystem::sync_event_t type,
audio_session_t triggerSession,
audio_session_t listenerSession,
const audioflinger::SyncEventCallback& callBack,
- const wp<IAfTrackBase>& cookie) final;
+ const wp<IAfTrackBase>& cookie) final EXCLUDES_AudioFlinger_Mutex;
- void ioConfigChanged(audio_io_config_event_t event,
+ // Hold either AudioFlinger::mutex or ThreadBase::mutex
+ void ioConfigChanged_l(audio_io_config_event_t event,
const sp<AudioIoDescriptor>& ioDesc,
- pid_t pid = 0) final;
- void onNonOffloadableGlobalEffectEnable() final;
+ pid_t pid = 0) final EXCLUDES_AudioFlinger_ClientMutex;
+ void onNonOffloadableGlobalEffectEnable() final EXCLUDES_AudioFlinger_Mutex;
void onSupportedLatencyModesChanged(
- audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes) final;
+ audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes) final
+ EXCLUDES_AudioFlinger_ClientMutex;
// ---- end of IAfThreadCallback interface
/* List available audio ports and their attributes */
- status_t listAudioPorts(unsigned int* num_ports, struct audio_port* ports) const;
+ status_t listAudioPorts(unsigned int* num_ports, struct audio_port* ports) const
+ EXCLUDES_AudioFlinger_Mutex;
sp<EffectsFactoryHalInterface> getEffectsFactory();
@@ -373,7 +414,7 @@
audio_session_t *sessionId,
const sp<MmapStreamCallback>& callback,
sp<MmapStreamInterface>& interface,
- audio_port_handle_t *handle);
+ audio_port_handle_t *handle) EXCLUDES_AudioFlinger_Mutex;
private:
// FIXME The 400 is temporarily too high until a leak of writers in media.log is fixed.
static const size_t kLogMemorySize = 400 * 1024;
@@ -381,32 +422,33 @@
// When a log writer is unregistered, it is done lazily so that media.log can continue to see it
// for as long as possible. The memory is only freed when it is needed for another log writer.
Vector< sp<NBLog::Writer> > mUnregisteredWriters;
- Mutex mUnregisteredWritersLock;
+ audio_utils::mutex& unregisteredWritersMutex() const { return mUnregisteredWritersMutex; }
+ mutable audio_utils::mutex mUnregisteredWritersMutex;
AudioFlinger() ANDROID_API;
~AudioFlinger() override;
// call in any IAudioFlinger method that accesses mPrimaryHardwareDev
- status_t initCheck() const { return mPrimaryHardwareDev == NULL ?
+ status_t initCheck() const { return mPrimaryHardwareDev == NULL ?
NO_INIT : NO_ERROR; }
// RefBase
void onFirstRef() override;
AudioHwDevice* findSuitableHwDev_l(audio_module_handle_t module,
- audio_devices_t deviceType);
+ audio_devices_t deviceType) REQUIRES(mutex());
// incremented by 2 when screen state changes, bit 0 == 1 means "off"
- // AudioFlinger::setParameters() updates with mLock.
+ // AudioFlinger::setParameters() updates with mutex().
std::atomic_uint32_t mScreenState{};
void dumpPermissionDenial(int fd, const Vector<String16>& args);
- void dumpClients(int fd, const Vector<String16>& args);
- void dumpInternals(int fd, const Vector<String16>& args);
+ void dumpClients_ll(int fd, const Vector<String16>& args) REQUIRES(mutex(), clientMutex());
+ void dumpInternals_l(int fd, const Vector<String16>& args) REQUIRES(mutex());
SimpleLog mThreadLog{16}; // 16 Thread history limit
- void dumpToThreadLog_l(const sp<IAfThreadBase>& thread);
+ void dumpToThreadLog_l(const sp<IAfThreadBase>& thread) REQUIRES(mutex());
// --- Notification Client ---
class NotificationClient : public IBinder::DeathRecipient {
@@ -453,8 +495,8 @@
bool mPendingRequests;
// Mutex and condition variable around mPendingRequests' value
- Mutex mMutex;
- Condition mCond;
+ audio_utils::mutex mMutex;
+ audio_utils::condition_variable mCondition;
// Duration of the sleep period after a processed request
static const int kPostTriggerSleepPeriod = 1000000;
@@ -467,7 +509,8 @@
// If none found, AUDIO_IO_HANDLE_NONE is returned.
template <typename T>
static audio_io_handle_t findIoHandleBySessionId_l(
- audio_session_t sessionId, const T& threads) {
+ audio_session_t sessionId, const T& threads)
+ REQUIRES(audio_utils::AudioFlinger_Mutex) {
audio_io_handle_t io = AUDIO_IO_HANDLE_NONE;
for (size_t i = 0; i < threads.size(); i++) {
@@ -482,14 +525,14 @@
return io;
}
- IAfThreadBase* checkThread_l(audio_io_handle_t ioHandle) const;
- IAfPlaybackThread* checkMixerThread_l(audio_io_handle_t output) const;
+ IAfThreadBase* checkThread_l(audio_io_handle_t ioHandle) const REQUIRES(mutex());
+ IAfPlaybackThread* checkMixerThread_l(audio_io_handle_t output) const REQUIRES(mutex());
- sp<VolumeInterface> getVolumeInterface_l(audio_io_handle_t output) const;
- std::vector<sp<VolumeInterface>> getAllVolumeInterfaces_l() const;
+ sp<VolumeInterface> getVolumeInterface_l(audio_io_handle_t output) const REQUIRES(mutex());
+ std::vector<sp<VolumeInterface>> getAllVolumeInterfaces_l() const REQUIRES(mutex());
- void closeOutputFinish(const sp<IAfPlaybackThread>& thread);
+ static void closeOutputFinish(const sp<IAfPlaybackThread>& thread);
void closeInputFinish(const sp<IAfRecordThread>& thread);
// Allocate an audio_unique_id_t.
@@ -506,25 +549,27 @@
// used by IAfDeviceEffectManagerCallback, IAfPatchPanelCallback, IAfThreadCallback
audio_unique_id_t nextUniqueId(audio_unique_id_use_t use) final;
- status_t moveEffectChain_l(audio_session_t sessionId,
- IAfRecordThread* srcThread, IAfRecordThread* dstThread);
+ status_t moveEffectChain_ll(audio_session_t sessionId,
+ IAfRecordThread* srcThread, IAfRecordThread* dstThread)
+ REQUIRES(mutex(), audio_utils::ThreadBase_Mutex);
// return thread associated with primary hardware device, or NULL
- DeviceTypeSet primaryOutputDevice_l() const;
+ DeviceTypeSet primaryOutputDevice_l() const REQUIRES(mutex());
// return the playback thread with smallest HAL buffer size, and prefer fast
- IAfPlaybackThread* fastPlaybackThread_l() const;
+ IAfPlaybackThread* fastPlaybackThread_l() const REQUIRES(mutex());
- sp<IAfThreadBase> getEffectThread_l(audio_session_t sessionId, int effectId);
+ sp<IAfThreadBase> getEffectThread_l(audio_session_t sessionId, int effectId)
+ REQUIRES(mutex());
- IAfThreadBase* hapticPlaybackThread_l() const;
+ IAfThreadBase* hapticPlaybackThread_l() const REQUIRES(mutex());
void updateSecondaryOutputsForTrack_l(
IAfTrack* track,
IAfPlaybackThread* thread,
- const std::vector<audio_io_handle_t>& secondaryOutputs) const;
+ const std::vector<audio_io_handle_t>& secondaryOutputs) const REQUIRES(mutex());
- bool isSessionAcquired_l(audio_session_t audioSession);
+ bool isSessionAcquired_l(audio_session_t audioSession) REQUIRES(mutex());
// Store an effect chain to mOrphanEffectChains keyed vector.
// Called when a thread exits and effects are still attached to it.
@@ -533,20 +578,21 @@
// return ALREADY_EXISTS if a chain with the same session already exists in
// mOrphanEffectChains. Note that this should never happen as there is only one
// chain for a given session and it is attached to only one thread at a time.
- status_t putOrphanEffectChain_l(const sp<IAfEffectChain>& chain);
+ status_t putOrphanEffectChain_l(const sp<IAfEffectChain>& chain) REQUIRES(mutex());
// Get an effect chain for the specified session in mOrphanEffectChains and remove
// it if found. Returns 0 if not found (this is the most common case).
- sp<IAfEffectChain> getOrphanEffectChain_l(audio_session_t session);
+ sp<IAfEffectChain> getOrphanEffectChain_l(audio_session_t session) REQUIRES(mutex());
- std::vector< sp<IAfEffectModule> > purgeStaleEffects_l();
+ std::vector< sp<IAfEffectModule> > purgeStaleEffects_l() REQUIRES(mutex());
- std::vector< sp<IAfEffectModule> > purgeOrphanEffectChains_l();
- bool updateOrphanEffectChains_l(const sp<IAfEffectModule>& effect);
+ std::vector< sp<IAfEffectModule> > purgeOrphanEffectChains_l() REQUIRES(mutex());
+ bool updateOrphanEffectChains_l(const sp<IAfEffectModule>& effect) REQUIRES(mutex());
- void broadcastParametersToRecordThreads_l(const String8& keyValuePairs);
- void forwardParametersToDownstreamPatches_l(
+ void broadcastParametersToRecordThreads_l(const String8& keyValuePairs) REQUIRES(mutex());
+ void forwardParametersToDownstreamPatches_l(
audio_io_handle_t upStream, const String8& keyValuePairs,
- const std::function<bool(const sp<IAfPlaybackThread>&)>& useThread = nullptr);
+ const std::function<bool(const sp<IAfPlaybackThread>&)>& useThread = nullptr)
+ REQUIRES(mutex());
// for mAudioSessionRefs only
struct AudioSessionRef {
@@ -558,22 +604,24 @@
int mCnt;
};
- mutable Mutex mLock;
+ mutable audio_utils::mutex mMutex;
// protects mClients and mNotificationClients.
- // must be locked after mLock and ThreadBase::mLock if both must be locked
- // avoids acquiring AudioFlinger::mLock from inside thread loop.
+ // must be locked after mutex() and ThreadBase::mutex() if both must be locked
+ // avoids acquiring AudioFlinger::mutex() from inside thread loop.
- mutable Mutex mClientLock;
+ mutable audio_utils::mutex mClientMutex;
- // protected by mClientLock
- DefaultKeyedVector< pid_t, wp<Client> > mClients; // see ~Client()
+ DefaultKeyedVector<pid_t, wp<Client>> mClients GUARDED_BY(clientMutex()); // see ~Client()
- mutable Mutex mHardwareLock;
- // NOTE: If both mLock and mHardwareLock mutexes must be held,
- // always take mLock before mHardwareLock
+ audio_utils::mutex& hardwareMutex() const { return mHardwareMutex; }
+
+ mutable audio_utils::mutex mHardwareMutex;
+ // NOTE: If both mMutex and mHardwareMutex mutexes must be held,
+ // always take mMutex before mHardwareMutex
std::atomic<AudioHwDevice*> mPrimaryHardwareDev = nullptr;
- DefaultKeyedVector<audio_module_handle_t, AudioHwDevice*> mAudioHwDevs{nullptr /* defValue */};
+ DefaultKeyedVector<audio_module_handle_t, AudioHwDevice*> mAudioHwDevs
+ GUARDED_BY(hardwareMutex()) {nullptr /* defValue */};
const sp<DevicesFactoryHalInterface> mDevicesFactoryHal =
DevicesFactoryHalInterface::create();
@@ -608,20 +656,18 @@
};
mutable hardware_call_state mHardwareStatus = AUDIO_HW_IDLE; // for dump only
+ DefaultKeyedVector<audio_io_handle_t, sp<IAfPlaybackThread>> mPlaybackThreads
+ GUARDED_BY(mutex());
+ stream_type_t mStreamTypes[AUDIO_STREAM_CNT] GUARDED_BY(mutex());
- DefaultKeyedVector<audio_io_handle_t, sp<IAfPlaybackThread>> mPlaybackThreads;
- stream_type_t mStreamTypes[AUDIO_STREAM_CNT];
+ float mMasterVolume GUARDED_BY(mutex()) = 1.f;
+ bool mMasterMute GUARDED_BY(mutex()) = false;
+ float mMasterBalance GUARDED_BY(mutex()) = 0.f;
- // member variables below are protected by mLock
- float mMasterVolume = 1.f;
- bool mMasterMute = false;
- float mMasterBalance = 0.f;
- // end of variables protected by mLock
+ DefaultKeyedVector<audio_io_handle_t, sp<IAfRecordThread>> mRecordThreads GUARDED_BY(mutex());
- DefaultKeyedVector<audio_io_handle_t, sp<IAfRecordThread>> mRecordThreads;
-
- // protected by mClientLock
- DefaultKeyedVector< pid_t, sp<NotificationClient> > mNotificationClients;
+ DefaultKeyedVector<pid_t, sp<NotificationClient>> mNotificationClients
+ GUARDED_BY(clientMutex());
// updated by atomic_fetch_add_explicit
volatile atomic_uint_fast32_t mNextUniqueIds[AUDIO_UNIQUE_ID_USE_MAX]; // ctor init
@@ -629,34 +675,36 @@
std::atomic<audio_mode_t> mMode = AUDIO_MODE_INVALID;
std::atomic<bool> mBtNrecIsOff = false;
- // protected by mLock
- Vector<AudioSessionRef*> mAudioSessionRefs;
+ Vector<AudioSessionRef*> mAudioSessionRefs GUARDED_BY(mutex());
- AudioHwDevice* loadHwModule_l(const char *name);
+ AudioHwDevice* loadHwModule_ll(const char *name) REQUIRES(mutex(), hardwareMutex());
// sync events awaiting for a session to be created.
- std::list<sp<audioflinger::SyncEvent>> mPendingSyncEvents;
+ std::list<sp<audioflinger::SyncEvent>> mPendingSyncEvents GUARDED_BY(mutex());
// Effect chains without a valid thread
- DefaultKeyedVector<audio_session_t, sp<IAfEffectChain>> mOrphanEffectChains;
+ DefaultKeyedVector<audio_session_t, sp<IAfEffectChain>> mOrphanEffectChains
+ GUARDED_BY(mutex());
// list of sessions for which a valid HW A/V sync ID was retrieved from the HAL
- DefaultKeyedVector< audio_session_t , audio_hw_sync_t >mHwAvSyncIds;
+ DefaultKeyedVector<audio_session_t, audio_hw_sync_t> mHwAvSyncIds GUARDED_BY(mutex());
// list of MMAP stream control threads. Those threads allow for wake lock, routing
// and volume control for activity on the associated MMAP stream at the HAL.
// Audio data transfer is directly handled by the client creating the MMAP stream
- DefaultKeyedVector<audio_io_handle_t, sp<IAfMmapThread>> mMmapThreads;
+ DefaultKeyedVector<audio_io_handle_t, sp<IAfMmapThread>> mMmapThreads GUARDED_BY(mutex());
- sp<Client> registerPid(pid_t pid); // always returns non-0
+ sp<Client> registerPid(pid_t pid) EXCLUDES_AudioFlinger_ClientMutex; // always returns non-0
// for use from destructor
- status_t closeOutput_nonvirtual(audio_io_handle_t output);
- status_t closeInput_nonvirtual(audio_io_handle_t input);
- void setAudioHwSyncForSession_l(IAfPlaybackThread* thread, audio_session_t sessionId);
+ status_t closeOutput_nonvirtual(audio_io_handle_t output) EXCLUDES_AudioFlinger_Mutex;
+ status_t closeInput_nonvirtual(audio_io_handle_t input) EXCLUDES_AudioFlinger_Mutex;
+ void setAudioHwSyncForSession_l(IAfPlaybackThread* thread, audio_session_t sessionId)
+ REQUIRES(mutex());
- status_t checkStreamType(audio_stream_type_t stream) const;
+ static status_t checkStreamType(audio_stream_type_t stream);
+ // no mutex needed.
void filterReservedParameters(String8& keyValuePairs, uid_t callingUid);
void logFilteredParameters(size_t originalKVPSize, const String8& originalKVPs,
size_t rejectedKVPSize, const String8& rejectedKVPs,
@@ -667,12 +715,13 @@
size_t getClientSharedHeapSize() const;
std::atomic<bool> mIsLowRamDevice = true;
- bool mIsDeviceTypeKnown = false;
- int64_t mTotalMemory = 0;
+ bool mIsDeviceTypeKnown GUARDED_BY(mutex()) = false;
+ int64_t mTotalMemory GUARDED_BY(mutex()) = 0;
std::atomic<size_t> mClientSharedHeapSize = kMinimumClientSharedHeapSizeBytes;
static constexpr size_t kMinimumClientSharedHeapSizeBytes = 1024 * 1024; // 1MB
- nsecs_t mGlobalEffectEnableTime = 0; // when a global effect was last enabled
+ // when a global effect was last enabled
+ nsecs_t mGlobalEffectEnableTime GUARDED_BY(mutex()) = 0;
/* const */ sp<IAfPatchPanel> mPatchPanel;
@@ -683,26 +732,28 @@
/* const */ sp<DeviceEffectManager> mDeviceEffectManager; // set onFirstRef
/* const */ sp<MelReporter> mMelReporter; // set onFirstRef
- bool mSystemReady = false;
+ bool mSystemReady GUARDED_BY(mutex()) = false;
std::atomic<bool> mAudioPolicyReady = false;
- mediautils::UidInfo mUidInfo;
+ mediautils::UidInfo mUidInfo GUARDED_BY(mutex());
+ // no mutex needed.
SimpleLog mRejectedSetParameterLog;
SimpleLog mAppSetParameterLog;
SimpleLog mSystemSetParameterLog;
- std::vector<media::AudioVibratorInfo> mAudioVibratorInfos;
+ std::vector<media::AudioVibratorInfo> mAudioVibratorInfos GUARDED_BY(mutex());
static inline constexpr const char *mMetricsId = AMEDIAMETRICS_KEY_AUDIO_FLINGER;
std::map<media::audio::common::AudioMMapPolicyType,
- std::vector<media::audio::common::AudioMMapPolicyInfo>> mPolicyInfos;
- int32_t mAAudioBurstsPerBuffer = 0;
- int32_t mAAudioHwBurstMinMicros = 0;
+ std::vector<media::audio::common::AudioMMapPolicyInfo>> mPolicyInfos
+ GUARDED_BY(mutex());
+ int32_t mAAudioBurstsPerBuffer GUARDED_BY(mutex()) = 0;
+ int32_t mAAudioHwBurstMinMicros GUARDED_BY(mutex()) = 0;
/** Interface for interacting with the AudioService. */
- mediautils::atomic_sp<IAudioManager> mAudioManager;
+ mediautils::atomic_sp<IAudioManager> mAudioManager;
// Bluetooth Variable latency control logic is enabled or disabled
std::atomic<bool> mBluetoothLatencyModesEnabled = true;
diff --git a/services/audioflinger/Client.h b/services/audioflinger/Client.h
index b2e3cf7..ff0d751 100644
--- a/services/audioflinger/Client.h
+++ b/services/audioflinger/Client.h
@@ -17,8 +17,8 @@
#pragma once
#include <afutils/AllocatorFactory.h>
+#include <audio_utils/mutex.h>
#include <android-base/macros.h> // DISALLOW_COPY_AND_ASSIGN
-#include <utils/Mutex.h>
#include <utils/RefBase.h> // avoid transitive dependency
// TODO(b/291318727) Move to nested namespace
@@ -28,13 +28,16 @@
class IAfClientCallback : public virtual RefBase {
public:
- virtual Mutex& clientMutex() const = 0;
- virtual void removeClient_l(pid_t pid) = 0;
- virtual void removeNotificationClient(pid_t pid) = 0;
+ virtual audio_utils::mutex& clientMutex() const
+ RETURN_CAPABILITY(audio_utils::AudioFlinger_ClientMutex) = 0;
+ virtual void removeClient_l(pid_t pid) REQUIRES(clientMutex()) = 0;
+ virtual void removeNotificationClient(pid_t pid) EXCLUDES_AudioFlinger_Mutex = 0;
+
+ // used indirectly by clients.
virtual status_t moveAuxEffectToIo(
int effectId,
const sp<IAfPlaybackThread>& dstThread,
- sp<IAfPlaybackThread>* srcThread) = 0; // used by indirectly by clients.
+ sp<IAfPlaybackThread>* srcThread) EXCLUDES_AudioFlinger_Mutex = 0;
};
class Client : public RefBase {
diff --git a/services/audioflinger/DeviceEffectManager.cpp b/services/audioflinger/DeviceEffectManager.cpp
index 588616d..201d147 100644
--- a/services/audioflinger/DeviceEffectManager.cpp
+++ b/services/audioflinger/DeviceEffectManager.cpp
@@ -38,7 +38,7 @@
DeviceEffectManager::DeviceEffectManager(
const sp<IAfDeviceEffectManagerCallback>& afDeviceEffectManagerCallback)
: mAfDeviceEffectManagerCallback(afDeviceEffectManagerCallback),
- mMyCallback(new DeviceEffectManagerCallback(*this)) {}
+ mMyCallback(sp<DeviceEffectManagerCallback>::make(*this)) {}
void DeviceEffectManager::onFirstRef() {
mAfDeviceEffectManagerCallback->getPatchCommandThread()->addListener(this);
@@ -59,7 +59,7 @@
ALOGV("%s handle %d mHalHandle %d device sink %08x",
__func__, handle, patch.mHalHandle,
patch.mAudioPatch.num_sinks > 0 ? patch.mAudioPatch.sinks[0].ext.device.type : 0);
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
for (auto& effectProxies : mDeviceEffects) {
for (auto& effect : effectProxies.second) {
const status_t status = effect->onCreatePatch(handle, patch);
@@ -71,7 +71,7 @@
void DeviceEffectManager::onReleaseAudioPatch(audio_patch_handle_t handle) {
ALOGV("%s", __func__);
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
for (auto& effectProxies : mDeviceEffects) {
for (auto& effect : effectProxies.second) {
effect->onReleasePatch(handle);
@@ -84,7 +84,7 @@
ALOGV("%s oldhandle %d newHandle %d mHalHandle %d device sink %08x",
__func__, oldHandle, newHandle, patch.mHalHandle,
patch.mAudioPatch.num_sinks > 0 ? patch.mAudioPatch.sinks[0].ext.device.type : 0);
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
for (auto& effectProxies : mDeviceEffects) {
for (auto& effect : effectProxies.second) {
const status_t status = effect->onUpdatePatch(oldHandle, newHandle, patch);
@@ -94,7 +94,7 @@
}
}
-// DeviceEffectManager::createEffect_l() must be called with AudioFlinger::mLock held
+// DeviceEffectManager::createEffect_l() must be called with AudioFlinger::mutex() held
sp<IAfEffectHandle> DeviceEffectManager::createEffect_l(
effect_descriptor_t *descriptor,
const AudioDeviceTypeAddr& device,
@@ -117,7 +117,7 @@
}
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
auto iter = mDeviceEffects.find(device);
if (iter != mDeviceEffects.end()) {
effectsForDevice = iter->second;
@@ -161,6 +161,7 @@
return handle;
}
+/* static */
status_t DeviceEffectManager::checkEffectCompatibility(
const effect_descriptor_t *desc) {
const sp<EffectsFactoryHalInterface> effectsFactory =
@@ -187,6 +188,7 @@
return NO_ERROR;
}
+/* static */
status_t DeviceEffectManager::createEffectHal(
const effect_uuid_t *pEffectUuid, int32_t sessionId, int32_t deviceId,
sp<EffectHalInterface> *effect) {
@@ -203,7 +205,7 @@
void DeviceEffectManager::dump(int fd)
NO_THREAD_SAFETY_ANALYSIS // conditional try lock
{
- const bool locked = afutils::dumpTryLock(mLock);
+ const bool locked = afutils::dumpTryLock(mutex());
if (!locked) {
String8 result("DeviceEffectManager may be deadlocked\n");
write(fd, result.c_str(), result.size());
@@ -222,13 +224,13 @@
}
if (locked) {
- mLock.unlock();
+ mutex().unlock();
}
}
size_t DeviceEffectManager::removeEffect(const sp<IAfDeviceEffectProxy>& effect)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
const auto& iter = mDeviceEffects.find(effect->device());
if (iter != mDeviceEffects.end()) {
const auto& iterEffect = std::find_if(
diff --git a/services/audioflinger/DeviceEffectManager.h b/services/audioflinger/DeviceEffectManager.h
index cb7fad1..faba806 100644
--- a/services/audioflinger/DeviceEffectManager.h
+++ b/services/audioflinger/DeviceEffectManager.h
@@ -20,8 +20,6 @@
#include "IAfEffect.h"
#include "PatchCommandThread.h"
-#include <utils/Mutex.h> // avoid transitive dependency
-
namespace android {
class IAfDeviceEffectManagerCallback : public virtual RefBase {
@@ -30,9 +28,11 @@
virtual audio_unique_id_t nextUniqueId(audio_unique_id_use_t use) = 0;
virtual const sp<PatchCommandThread>& getPatchCommandThread() = 0;
virtual status_t addEffectToHal(
- const struct audio_port_config* device, const sp<EffectHalInterface>& effect) = 0;
+ const struct audio_port_config* device, const sp<EffectHalInterface>& effect)
+ EXCLUDES_AudioFlinger_HardwareMutex = 0;
virtual status_t removeEffectFromHal(
- const struct audio_port_config* device, const sp<EffectHalInterface>& effect) = 0;
+ const struct audio_port_config* device, const sp<EffectHalInterface>& effect)
+ EXCLUDES_AudioFlinger_HardwareMutex= 0;
};
class DeviceEffectManagerCallback;
@@ -53,10 +53,10 @@
int *enabled,
status_t *status,
bool probe,
- bool notifyFramesProcessed);
+ bool notifyFramesProcessed) REQUIRES(audio_utils::AudioFlinger_Mutex);
size_t removeEffect(const sp<IAfDeviceEffectProxy>& effect);
- status_t createEffectHal(const effect_uuid_t *pEffectUuid,
+ static status_t createEffectHal(const effect_uuid_t *pEffectUuid,
int32_t sessionId, int32_t deviceId,
sp<EffectHalInterface> *effect);
status_t addEffectToHal(const struct audio_port_config *device,
@@ -71,19 +71,25 @@
// PatchCommandThread::PatchCommandListener implementation
void onCreateAudioPatch(audio_patch_handle_t handle,
- const IAfPatchPanel::Patch& patch) final;
- void onReleaseAudioPatch(audio_patch_handle_t handle) final;
+ const IAfPatchPanel::Patch& patch) final
+ EXCLUDES_DeviceEffectManager_Mutex;
+ void onReleaseAudioPatch(audio_patch_handle_t handle) final
+ EXCLUDES_DeviceEffectManager_Mutex;
void onUpdateAudioPatch(audio_patch_handle_t oldHandle,
- audio_patch_handle_t newHandle,
- const IAfPatchPanel::Patch& patch) final;
+ audio_patch_handle_t newHandle, const IAfPatchPanel::Patch& patch) final
+ EXCLUDES_DeviceEffectManager_Mutex;
private:
- status_t checkEffectCompatibility(const effect_descriptor_t *desc);
+ static status_t checkEffectCompatibility(const effect_descriptor_t *desc);
- Mutex mLock;
+ audio_utils::mutex& mutex() const RETURN_CAPABILITY(audio_utils::DeviceEffectManager_Mutex) {
+ return mMutex;
+ }
+ mutable audio_utils::mutex mMutex;
const sp<IAfDeviceEffectManagerCallback> mAfDeviceEffectManagerCallback;
const sp<DeviceEffectManagerCallback> mMyCallback;
- std::map<AudioDeviceTypeAddr, std::vector<sp<IAfDeviceEffectProxy>>> mDeviceEffects;
+ std::map<AudioDeviceTypeAddr, std::vector<sp<IAfDeviceEffectProxy>>>
+ mDeviceEffects GUARDED_BY(mutex());
};
class DeviceEffectManagerCallback : public EffectCallbackInterface {
@@ -92,55 +98,54 @@
: mManager(manager) {}
status_t createEffectHal(const effect_uuid_t *pEffectUuid,
- int32_t sessionId, int32_t deviceId,
- sp<EffectHalInterface> *effect) override {
+ int32_t sessionId, int32_t deviceId, sp<EffectHalInterface> *effect) final {
return mManager.createEffectHal(pEffectUuid, sessionId, deviceId, effect);
}
status_t allocateHalBuffer(size_t size __unused,
- sp<EffectBufferHalInterface>* buffer __unused) override { return NO_ERROR; }
- bool updateOrphanEffectChains(const sp<IAfEffectBase>& effect __unused) override {
+ sp<EffectBufferHalInterface>* buffer __unused) final { return NO_ERROR; }
+ bool updateOrphanEffectChains(const sp<IAfEffectBase>& effect __unused) final {
return false;
}
- audio_io_handle_t io() const override { return AUDIO_IO_HANDLE_NONE; }
- bool isOutput() const override { return false; }
- bool isOffload() const override { return false; }
- bool isOffloadOrDirect() const override { return false; }
- bool isOffloadOrMmap() const override { return false; }
- bool isSpatializer() const override { return false; }
+ audio_io_handle_t io() const final { return AUDIO_IO_HANDLE_NONE; }
+ bool isOutput() const final { return false; }
+ bool isOffload() const final { return false; }
+ bool isOffloadOrDirect() const final { return false; }
+ bool isOffloadOrMmap() const final { return false; }
+ bool isSpatializer() const final { return false; }
- uint32_t sampleRate() const override { return 0; }
- audio_channel_mask_t inChannelMask(int id __unused) const override {
+ uint32_t sampleRate() const final { return 0; }
+ audio_channel_mask_t inChannelMask(int id __unused) const final {
return AUDIO_CHANNEL_NONE;
}
- uint32_t inChannelCount(int id __unused) const override { return 0; }
- audio_channel_mask_t outChannelMask() const override { return AUDIO_CHANNEL_NONE; }
- uint32_t outChannelCount() const override { return 0; }
+ uint32_t inChannelCount(int id __unused) const final { return 0; }
+ audio_channel_mask_t outChannelMask() const final { return AUDIO_CHANNEL_NONE; }
+ uint32_t outChannelCount() const final { return 0; }
- audio_channel_mask_t hapticChannelMask() const override { return AUDIO_CHANNEL_NONE; }
- size_t frameCount() const override { return 0; }
- uint32_t latency() const override { return 0; }
+ audio_channel_mask_t hapticChannelMask() const final { return AUDIO_CHANNEL_NONE; }
+ size_t frameCount() const final { return 0; }
+ uint32_t latency() const final { return 0; }
- status_t addEffectToHal(const sp<EffectHalInterface>& /* effect */) override {
+ status_t addEffectToHal(const sp<EffectHalInterface>& /* effect */) final {
return NO_ERROR;
}
- status_t removeEffectFromHal(const sp<EffectHalInterface>& /* effect */) override {
+ status_t removeEffectFromHal(const sp<EffectHalInterface>& /* effect */) final {
return NO_ERROR;
}
- bool disconnectEffectHandle(IAfEffectHandle *handle, bool unpinIfLast) override;
- void setVolumeForOutput(float left __unused, float right __unused) const override {}
+ bool disconnectEffectHandle(IAfEffectHandle *handle, bool unpinIfLast) final;
+ void setVolumeForOutput(float left __unused, float right __unused) const final {}
// check if effects should be suspended or restored when a given effect is enable or disabled
void checkSuspendOnEffectEnabled(const sp<IAfEffectBase>& effect __unused,
- bool enabled __unused, bool threadLocked __unused) override {}
- void resetVolume() override {}
- product_strategy_t strategy() const override { return static_cast<product_strategy_t>(0); }
- int32_t activeTrackCnt() const override { return 0; }
- void onEffectEnable(const sp<IAfEffectBase>& effect __unused) override {}
- void onEffectDisable(const sp<IAfEffectBase>& effect __unused) override {}
+ bool enabled __unused, bool threadLocked __unused) final {}
+ void resetVolume() final {}
+ product_strategy_t strategy() const final { return static_cast<product_strategy_t>(0); }
+ int32_t activeTrackCnt() const final { return 0; }
+ void onEffectEnable(const sp<IAfEffectBase>& effect __unused) final {}
+ void onEffectDisable(const sp<IAfEffectBase>& effect __unused) final {}
- wp<IAfEffectChain> chain() const override { return nullptr; }
+ wp<IAfEffectChain> chain() const final { return nullptr; }
bool isAudioPolicyReady() const final;
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 22733a6..589050c 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -109,7 +109,7 @@
{
}
-// must be called with EffectModule::mLock held
+// must be called with EffectModule::mutex() held
status_t EffectBase::setEnabled_l(bool enabled)
{
@@ -155,7 +155,7 @@
{
status_t status;
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
status = setEnabled_l(enabled);
}
if (fromHandle) {
@@ -190,13 +190,13 @@
void EffectBase::setSuspended(bool suspended)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
mSuspended = suspended;
}
bool EffectBase::suspended() const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
return mSuspended;
}
@@ -204,7 +204,7 @@
{
status_t status;
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
int priority = handle->priority();
size_t size = mHandles.size();
IAfEffectHandle *controlHandle = nullptr;
@@ -250,7 +250,7 @@
product_strategy_t strategy = PRODUCT_STRATEGY_NONE;
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if ((isInternal_l() && !mPolicyRegistered)
|| !getCallback()->isAudioPolicyReady()) {
@@ -284,7 +284,7 @@
return NO_ERROR;
}
}
- mPolicyLock.lock();
+ policyMutex().lock();
ALOGV("%s name %s id %d session %d doRegister %d registered %d doEnable %d enabled %d",
__func__, mDescriptor.name, mId, mSessionId, doRegister, registered, doEnable, enabled);
if (doRegister) {
@@ -302,7 +302,7 @@
if (registered && doEnable) {
status = AudioSystem::setEffectEnabled(mId, enabled);
}
- mPolicyLock.unlock();
+ policyMutex().unlock();
return status;
}
@@ -310,7 +310,7 @@
ssize_t EffectBase::removeHandle(IAfEffectHandle *handle)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
return removeHandle_l(handle);
}
@@ -348,7 +348,7 @@
return mHandles.size();
}
-// must be called with EffectModule::mLock held
+// must be called with EffectModule::mutex() held
IAfEffectHandle *EffectBase::controlHandle_l()
{
// the first valid handle in the list has control over the module
@@ -371,12 +371,12 @@
return mHandles.size();
}
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
ssize_t numHandles = removeHandle_l(handle);
if ((numHandles == 0) && (!mPinned || unpinIfLast)) {
- mLock.unlock();
+ mutex().unlock();
callback->updateOrphanEffectChains(this);
- mLock.lock();
+ mutex().lock();
}
return numHandles;
}
@@ -384,7 +384,7 @@
bool EffectBase::purgeHandles()
{
bool enabled = false;
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
IAfEffectHandle *handle = controlHandle_l();
if (handle != NULL) {
enabled = handle->enabled();
@@ -509,7 +509,7 @@
result.appendFormat("\tEffect ID %d:\n", mId);
- const bool locked = afutils::dumpTryLock(mLock);
+ const bool locked = afutils::dumpTryLock(mutex());
// failed to lock - AudioFlinger is probably deadlocked
if (!locked) {
result.append("\t\tCould not lock Fx mutex:\n");
@@ -548,7 +548,7 @@
}
}
if (locked) {
- mLock.unlock();
+ mutex().unlock();
}
write(fd, result.c_str(), result.length());
@@ -617,7 +617,7 @@
}
bool EffectModule::updateState() {
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
bool started = false;
switch (mState) {
@@ -673,7 +673,7 @@
void EffectModule::process()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (mState == DESTROYED || mEffectInterface == 0 || mInBuffer == 0 || mOutBuffer == 0) {
return;
@@ -830,7 +830,10 @@
if (mStatus != NO_ERROR || mEffectInterface == 0) {
return;
}
- mEffectInterface->command(EFFECT_CMD_RESET, 0, NULL, 0, NULL);
+
+ int reply = 0;
+ uint32_t replySize = sizeof(reply);
+ mEffectInterface->command(EFFECT_CMD_RESET, 0, NULL, &replySize, &reply);
}
status_t EffectModule::configure()
@@ -1015,7 +1018,7 @@
status_t EffectModule::init()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (mEffectInterface == 0) {
return NO_INIT;
}
@@ -1045,12 +1048,12 @@
}
}
-// start() must be called with PlaybackThread::mLock or EffectChain::mLock held
+// start() must be called with PlaybackThread::mutex() or EffectChain::mutex() held
status_t EffectModule::start()
{
status_t status;
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
status = start_l();
}
if (status == NO_ERROR) {
@@ -1085,7 +1088,7 @@
status_t EffectModule::stop()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
return stop_l();
}
@@ -1122,7 +1125,7 @@
return status;
}
-// must be called with EffectChain::mLock held
+// must be called with EffectChain::mutex() held
void EffectModule::release_l()
{
if (mEffectInterface != 0) {
@@ -1158,7 +1161,7 @@
int32_t maxReplySize,
std::vector<uint8_t>* reply)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
ALOGVV("command(), cmdCode: %d, mEffectInterface: %p", cmdCode, mEffectInterface.get());
if (mState == DESTROYED || mEffectInterface == 0) {
@@ -1355,7 +1358,7 @@
status_t EffectModule::setVolume(uint32_t *left, uint32_t *right, bool controller)
{
- AutoLockReentrant _l(mLock, mSetVolumeReentrantTid);
+ AutoLockReentrant _l(mutex(), mSetVolumeReentrantTid);
if (mStatus != NO_ERROR) {
return mStatus;
}
@@ -1409,7 +1412,7 @@
return NO_ERROR;
}
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (mStatus != NO_ERROR) {
return mStatus;
}
@@ -1439,7 +1442,7 @@
status_t EffectModule::setMode(audio_mode_t mode)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (mStatus != NO_ERROR) {
return mStatus;
}
@@ -1461,7 +1464,7 @@
status_t EffectModule::setAudioSource(audio_source_t source)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (mStatus != NO_ERROR) {
return mStatus;
}
@@ -1479,7 +1482,7 @@
status_t EffectModule::setOffloaded(bool offloaded, audio_io_handle_t io)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (mStatus != NO_ERROR) {
return mStatus;
}
@@ -1512,7 +1515,7 @@
bool EffectModule::isOffloaded() const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
return mOffloaded;
}
@@ -1583,7 +1586,7 @@
status_t EffectModule::getConfigs(
audio_config_base_t* inputCfg, audio_config_base_t* outputCfg, bool* isOutput) const {
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (mConfig.inputCfg.mask == 0 || mConfig.outputCfg.mask == 0) {
return NO_INIT;
}
@@ -1618,7 +1621,7 @@
EffectBase::dump(fd, args);
String8 result;
- const bool locked = afutils::dumpTryLock(mLock);
+ const bool locked = afutils::dumpTryLock(mutex());
result.append("\t\tStatus Engine:\n");
result.appendFormat("\t\t%03d %p\n",
@@ -1661,7 +1664,7 @@
}
if (locked) {
- mLock.unlock();
+ mutex().unlock();
}
}
@@ -1784,7 +1787,7 @@
Status EffectHandle::enable(int32_t* _aidl_return)
{
- AutoMutex _l(mLock);
+ audio_utils::lock_guard _l(mutex());
ALOGV("enable %p", this);
sp<IAfEffectBase> effect = mEffect.promote();
if (effect == 0 || mDisconnected) {
@@ -1823,7 +1826,7 @@
Status EffectHandle::disable(int32_t* _aidl_return)
{
ALOGV("disable %p", this);
- AutoMutex _l(mLock);
+ audio_utils::lock_guard _l(mutex());
sp<IAfEffectBase> effect = mEffect.promote();
if (effect == 0 || mDisconnected) {
RETURN(DEAD_OBJECT);
@@ -1856,7 +1859,7 @@
void EffectHandle::disconnect(bool unpinIfLast)
{
- AutoMutex _l(mLock);
+ audio_utils::lock_guard _l(mutex());
ALOGV("disconnect(%s) %p", unpinIfLast ? "true" : "false", this);
if (mDisconnected) {
if (unpinIfLast) {
@@ -1883,7 +1886,7 @@
}
mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to
// Client destructor must run with AudioFlinger client mutex locked
- Mutex::Autolock _l2(mClient->afClientCallback()->clientMutex());
+ audio_utils::lock_guard _l2(mClient->afClientCallback()->clientMutex());
mClient.clear();
}
}
@@ -1895,7 +1898,7 @@
Status EffectHandle::getConfig(
media::EffectConfig* _config, int32_t* _aidl_return) {
- AutoMutex _l(mLock);
+ audio_utils::lock_guard _l(mutex());
sp<IAfEffectBase> effect = mEffect.promote();
if (effect == nullptr || mDisconnected) {
RETURN(DEAD_OBJECT);
@@ -1962,7 +1965,7 @@
return disable(_aidl_return);
}
- AutoMutex _l(mLock);
+ audio_utils::lock_guard _l(mutex());
sp<IAfEffectBase> effect = mEffect.promote();
if (effect == 0 || mDisconnected) {
RETURN(DEAD_OBJECT);
@@ -2176,7 +2179,7 @@
std::vector<int> EffectChain::getEffectIds() const
{
std::vector<int> ids;
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
for (size_t i = 0; i < mEffects.size(); i++) {
ids.push_back(mEffects[i]->id());
}
@@ -2185,11 +2188,11 @@
void EffectChain::clearInputBuffer()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
clearInputBuffer_l();
}
-// Must be called with EffectChain::mLock locked
+// Must be called with EffectChain::mutex() locked
void EffectChain::clearInputBuffer_l()
{
if (mInBuffer == NULL) {
@@ -2202,7 +2205,7 @@
mInBuffer->commit();
}
-// Must be called with EffectChain::mLock locked
+// Must be called with EffectChain::mutex() locked
void EffectChain::process_l()
{
// never process effects when:
@@ -2261,7 +2264,7 @@
audio_session_t sessionId,
bool pinned)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
effect = new EffectModule(mEffectCallback, desc, id, sessionId, pinned, AUDIO_PORT_HANDLE_NONE);
status_t lStatus = effect->status();
if (lStatus == NO_ERROR) {
@@ -2276,10 +2279,10 @@
// addEffect_l() must be called with IAfThreadBase::mutex() held
status_t EffectChain::addEffect_l(const sp<IAfEffectModule>& effect)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
return addEffect_ll(effect);
}
-// addEffect_l() must be called with IAfThreadBase::mLock and EffectChain::mutex() held
+// addEffect_l() must be called with IAfThreadBase::mutex() and EffectChain::mutex() held
status_t EffectChain::addEffect_ll(const sp<IAfEffectModule>& effect)
{
effect->setCallback(mEffectCallback);
@@ -2446,7 +2449,7 @@
size_t EffectChain::removeEffect_l(const sp<IAfEffectModule>& effect,
bool release)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
size_t size = mEffects.size();
uint32_t type = effect->desc().flags & EFFECT_FLAG_TYPE_MASK;
@@ -2533,7 +2536,7 @@
return false;
}
-// setVolume_l() must be called with IAfThreadBase::mLock or EffectChain::mLock held
+// setVolume_l() must be called with IAfThreadBase::mutex() or EffectChain::mutex() held
bool EffectChain::setVolume_l(uint32_t *left, uint32_t *right, bool force)
{
uint32_t newLeft = *left;
@@ -2609,7 +2612,7 @@
return volumeControlIndex.has_value();
}
-// resetVolume_l() must be called with IAfThreadBase::mutex() or EffectChain::mLock held
+// resetVolume_l() must be called with IAfThreadBase::mutex() or EffectChain::mutex() held
void EffectChain::resetVolume_l()
{
if ((mLeftVolume != UINT_MAX) && (mRightVolume != UINT_MAX)) {
@@ -2620,7 +2623,7 @@
}
// containsHapticGeneratingEffect_l must be called with
-// IAfThreadBase::mutex() or EffectChain::mLock held
+// IAfThreadBase::mutex() or EffectChain::mutex() held
bool EffectChain::containsHapticGeneratingEffect_l()
{
for (size_t i = 0; i < mEffects.size(); ++i) {
@@ -2633,7 +2636,7 @@
void EffectChain::setHapticIntensity_l(int id, os::HapticScale intensity)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
for (size_t i = 0; i < mEffects.size(); ++i) {
mEffects[i]->setHapticIntensity(id, intensity);
}
@@ -2641,7 +2644,7 @@
void EffectChain::syncHalEffectsState()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
for (size_t i = 0; i < mEffects.size(); i++) {
if (mEffects[i]->state() == EffectModule::ACTIVE ||
mEffects[i]->state() == EffectModule::STOPPING) {
@@ -2659,7 +2662,7 @@
result.appendFormat(" %zu effects for session %d\n", numEffects, mSessionId);
if (numEffects) {
- const bool locked = afutils::dumpTryLock(mLock);
+ const bool locked = afutils::dumpTryLock(mutex());
// failed to lock - AudioFlinger is probably deadlocked
if (!locked) {
result.append("\tCould not lock mutex:\n");
@@ -2682,7 +2685,7 @@
}
if (locked) {
- mLock.unlock();
+ mutex().unlock();
}
} else {
write(fd, result.c_str(), result.size());
@@ -2731,12 +2734,12 @@
sp<IAfEffectModule> effect = desc->mEffect.promote();
if (effect != 0) {
effect->setSuspended(false);
- effect->lock();
+ effect->mutex().lock();
IAfEffectHandle *handle = effect->controlHandle_l();
if (handle != NULL && !handle->disconnected()) {
effect->setEnabled_l(handle->enabled());
}
- effect->unlock();
+ effect->mutex().unlock();
}
desc->mEffect.clear();
}
@@ -2886,7 +2889,7 @@
bool EffectChain::isNonOffloadableEnabled() const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
return isNonOffloadableEnabled_l();
}
@@ -2903,7 +2906,7 @@
void EffectChain::setThread(const sp<IAfThreadBase>& thread)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
mEffectCallback->setThread(thread);
}
@@ -2932,7 +2935,7 @@
bool EffectChain::isRawCompatible() const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
for (const auto &effect : mEffects) {
if (effect->isProcessImplemented()) {
return false;
@@ -2944,7 +2947,7 @@
bool EffectChain::isFastCompatible() const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
for (const auto &effect : mEffects) {
if (effect->isProcessImplemented()
&& effect->isImplementationSoftware()) {
@@ -2956,7 +2959,7 @@
}
bool EffectChain::isBitPerfectCompatible() const {
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
for (const auto &effect : mEffects) {
if (effect->isProcessImplemented()
&& effect->isImplementationSoftware()) {
@@ -2967,10 +2970,10 @@
return true;
}
-// isCompatibleWithThread_l() must be called with thread->mLock held
+// isCompatibleWithThread_l() must be called with thread->mutex() held
bool EffectChain::isCompatibleWithThread_l(const sp<IAfThreadBase>& thread) const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
for (size_t i = 0; i < mEffects.size(); i++) {
if (thread->checkEffectCompatibility_l(&(mEffects[i]->desc()), mSessionId) != NO_ERROR) {
return false;
@@ -3083,7 +3086,10 @@
return t->sampleRate();
}
-audio_channel_mask_t EffectChain::EffectCallback::inChannelMask(int id) const {
+audio_channel_mask_t EffectChain::EffectCallback::inChannelMask(int id) const
+NO_THREAD_SAFETY_ANALYSIS
+// calling function 'hasAudioSession_l' requires holding mutex 'ThreadBase_Mutex' exclusively
+{
const sp<IAfThreadBase> t = thread().promote();
if (t == nullptr) {
return AUDIO_CHANNEL_NONE;
@@ -3119,7 +3125,10 @@
return audio_channel_count_from_out_mask(inChannelMask(id));
}
-audio_channel_mask_t EffectChain::EffectCallback::outChannelMask() const {
+audio_channel_mask_t EffectChain::EffectCallback::outChannelMask() const
+NO_THREAD_SAFETY_ANALYSIS
+// calling function 'hasAudioSession_l' requires holding mutex 'ThreadBase_Mutex' exclusively
+{
const sp<IAfThreadBase> t = thread().promote();
if (t == nullptr) {
return AUDIO_CHANNEL_NONE;
@@ -3274,7 +3283,7 @@
status_t DeviceEffectProxy::setEnabled(bool enabled, bool fromHandle)
{
status_t status = EffectBase::setEnabled(enabled, fromHandle);
- Mutex::Autolock _l(mProxyLock);
+ audio_utils::lock_guard _l(proxyMutex());
if (status == NO_ERROR) {
for (auto& handle : mEffectHandles) {
Status bs;
@@ -3320,7 +3329,7 @@
const IAfPatchPanel::Patch& /* patch */) {
status_t status = NAME_NOT_FOUND;
ALOGV("%s", __func__);
- Mutex::Autolock _l(mProxyLock);
+ audio_utils::lock_guard _l(proxyMutex());
if (mEffectHandles.find(oldPatchHandle) != mEffectHandles.end()) {
ALOGV("%s replacing effect from handle %d to handle %d", __func__, oldPatchHandle,
newPatchHandle);
@@ -3344,7 +3353,7 @@
ALOGV("%s sink %d checkPort status %d", __func__, i, status);
}
if (status == NO_ERROR || status == ALREADY_EXISTS) {
- Mutex::Autolock _l(mProxyLock);
+ audio_utils::lock_guard _l(proxyMutex());
size_t erasedHandle = mEffectHandles.erase(patchHandle);
ALOGV("%s %s effecthandle %p for patch %d",
__func__, (erasedHandle == 0 ? "adding" : "replacing"), handle.get(), patchHandle);
@@ -3357,7 +3366,10 @@
}
status_t DeviceEffectProxy::checkPort(const IAfPatchPanel::Patch& patch,
- const struct audio_port_config *port, sp<IAfEffectHandle> *handle) {
+ const struct audio_port_config *port, sp<IAfEffectHandle> *handle)
+NO_THREAD_SAFETY_ANALYSIS
+// calling function 'createEffect_l' requires holding mutex 'AudioFlinger_Mutex' exclusively
+{
ALOGV("%s type %d device type %d address %s device ID %d patch.isSoftware() %d",
__func__, port->type, port->ext.device.type,
@@ -3379,7 +3391,7 @@
status_t status = NAME_NOT_FOUND;
if (mDescriptor.flags & EFFECT_FLAG_HW_ACC_TUNNEL) {
- Mutex::Autolock _l(mProxyLock);
+ audio_utils::lock_guard _l(proxyMutex());
if (mHalEffect != nullptr && mDevicePort.id == port->id) {
ALOGV("%s reusing HAL effect", __func__);
} else {
@@ -3446,7 +3458,7 @@
void DeviceEffectProxy::onReleasePatch(audio_patch_handle_t patchHandle) {
sp<IAfEffectHandle> effect;
{
- Mutex::Autolock _l(mProxyLock);
+ audio_utils::lock_guard _l(proxyMutex());
if (mEffectHandles.find(patchHandle) != mEffectHandles.end()) {
effect = mEffectHandles.at(patchHandle);
mEffectHandles.erase(patchHandle);
@@ -3457,7 +3469,7 @@
size_t DeviceEffectProxy::removeEffect(const sp<IAfEffectModule>& effect)
{
- Mutex::Autolock _l(mProxyLock);
+ audio_utils::lock_guard _l(proxyMutex());
if (effect == mHalEffect) {
mHalEffect->release_l();
mHalEffect.clear();
@@ -3485,7 +3497,7 @@
status_t DeviceEffectProxy::command(
int32_t cmdCode, const std::vector<uint8_t>& cmdData, int32_t maxReplySize,
std::vector<uint8_t>* reply) {
- Mutex::Autolock _l(mProxyLock);
+ audio_utils::lock_guard _l(proxyMutex());
status_t status = EffectBase::command(cmdCode, cmdData, maxReplySize, reply);
if (status == NO_ERROR) {
for (auto& handle : mEffectHandles) {
@@ -3535,7 +3547,7 @@
const Vector<String16> args;
EffectBase::dump(fd, args);
- const bool locked = afutils::dumpTryLock(mProxyLock);
+ const bool locked = afutils::dumpTryLock(proxyMutex());
if (!locked) {
String8 result("DeviceEffectProxy may be deadlocked\n");
write(fd, result.c_str(), result.size());
@@ -3565,7 +3577,7 @@
}
if (locked) {
- mProxyLock.unlock();
+ proxyMutex().unlock();
}
}
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index aa5935a..2ece5dc 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -111,8 +111,7 @@
bool isPinned() const final { return mPinned; }
void unPin() final { mPinned = false; }
- void lock() ACQUIRE(mLock) final { mLock.lock(); }
- void unlock() RELEASE(mLock) final { mLock.unlock(); }
+ audio_utils::mutex& mutex() const final { return mMutex; }
status_t updatePolicyState() final;
@@ -135,7 +134,8 @@
DISALLOW_COPY_AND_ASSIGN(EffectBase);
- mutable Mutex mLock; // mutex for process, commands and handles list protection
+ // mutex for process, commands and handles list protection
+ mutable audio_utils::mutex mMutex;
mediautils::atomic_sp<EffectCallbackInterface> mCallback; // parent effect chain
const int mId; // this instance unique ID
const audio_session_t mSessionId; // audio session ID
@@ -148,9 +148,10 @@
// First handle in mHandles has highest priority and controls the effect module
// Audio policy effect state management
- // Mutex protecting transactions with audio policy manager as mLock cannot
+ // Mutex protecting transactions with audio policy manager as mutex() cannot
// be held to avoid cross deadlocks with audio policy mutex
- Mutex mPolicyLock;
+ audio_utils::mutex& policyMutex() const { return mPolicyMutex; }
+ mutable audio_utils::mutex mPolicyMutex;
// Effect is registered in APM or not
bool mPolicyRegistered = false;
// Effect enabled state communicated to APM. Enabled state corresponds to
@@ -272,9 +273,10 @@
uint32_t mInChannelCountRequested;
uint32_t mOutChannelCountRequested;
+ template <typename MUTEX>
class AutoLockReentrant {
public:
- AutoLockReentrant(Mutex& mutex, pid_t allowedTid)
+ AutoLockReentrant(MUTEX& mutex, pid_t allowedTid)
: mMutex(gettid() == allowedTid ? nullptr : &mutex)
{
if (mMutex != nullptr) mMutex->lock();
@@ -283,7 +285,7 @@
if (mMutex != nullptr) mMutex->unlock();
}
private:
- Mutex * const mMutex;
+ MUTEX * const mMutex;
};
static constexpr pid_t INVALID_PID = (pid_t)-1;
@@ -364,7 +366,8 @@
private:
DISALLOW_COPY_AND_ASSIGN(EffectHandle);
- Mutex mLock; // protects IEffect method calls
+ audio_utils::mutex& mutex() const { return mMutex; }
+ mutable audio_utils::mutex mMutex; // protects IEffect method calls
const wp<IAfEffectBase> mEffect; // pointer to controlled EffectModule
const sp<media::IEffectClient> mEffectClient; // callback interface for client notifications
/*const*/ sp<Client> mClient; // client for shared memory allocation, see
@@ -397,12 +400,8 @@
void process_l() final;
- void lock() ACQUIRE(mLock) final {
- mLock.lock();
- }
- void unlock() RELEASE(mLock) final {
- mLock.unlock();
- }
+ audio_utils::mutex& mutex() const final { return mMutex; }
+
status_t createEffect_l(sp<IAfEffectModule>& effect,
effect_descriptor_t *desc,
int id,
@@ -488,9 +487,11 @@
// Is this EffectChain compatible with the bit-perfect audio flag.
bool isBitPerfectCompatible() const final;
- // isCompatibleWithThread_l() must be called with thread->mLock held
- bool isCompatibleWithThread_l(const sp<IAfThreadBase>& thread) const final;
+ // isCompatibleWithThread_l() must be called with thread->mutex() held
+ bool isCompatibleWithThread_l(const sp<IAfThreadBase>& thread) const final
+ REQUIRES(audio_utils::ThreadBase_Mutex);
+ // Requires either IAfThreadBase::mutex() or EffectChain::mutex() held
bool containsHapticGeneratingEffect_l() final;
void setHapticIntensity_l(int id, os::HapticScale intensity) final;
@@ -624,7 +625,7 @@
std::optional<size_t> findVolumeControl_l(size_t from, size_t to) const;
- mutable Mutex mLock; // mutex protecting effect list
+ mutable audio_utils::mutex mMutex; // mutex protecting effect list
Vector<sp<IAfEffectModule>> mEffects; // list of effect modules
audio_session_t mSessionId; // audio session ID
sp<EffectBufferHalInterface> mInBuffer; // chain input buffer
@@ -762,9 +763,10 @@
const sp<DeviceEffectManagerCallback> mManagerCallback;
const sp<ProxyCallback> mMyCallback;
- mutable Mutex mProxyLock;
- std::map<audio_patch_handle_t, sp<IAfEffectHandle>> mEffectHandles; // protected by mProxyLock
- sp<IAfEffectModule> mHalEffect; // protected by mProxyLock
+ audio_utils::mutex& proxyMutex() const { return mProxyMutex; }
+ mutable audio_utils::mutex mProxyMutex;
+ std::map<audio_patch_handle_t, sp<IAfEffectHandle>> mEffectHandles; // protected by mProxyMutex
+ sp<IAfEffectModule> mHalEffect; // protected by mProxyMutex
struct audio_port_config mDevicePort = { .id = AUDIO_PORT_HANDLE_NONE };
const bool mNotifyFramesProcessed;
};
diff --git a/services/audioflinger/IAfEffect.h b/services/audioflinger/IAfEffect.h
index c4f0de3..8c5bc4b 100644
--- a/services/audioflinger/IAfEffect.h
+++ b/services/audioflinger/IAfEffect.h
@@ -21,6 +21,7 @@
#include <android/media/AudioVibratorInfo.h>
#include <android/media/BnEffect.h>
#include <android/media/BnEffectClient.h>
+#include <audio_utils/mutex.h>
#include <media/AudioCommonTypes.h> // product_strategy_t
#include <media/AudioDeviceTypeAddr.h>
#include <media/audiohal/EffectHalInterface.h>
@@ -141,8 +142,7 @@
virtual ssize_t removeHandle_l(IAfEffectHandle *handle) = 0;
virtual IAfEffectHandle* controlHandle_l() = 0;
- virtual void lock() = 0;
- virtual void unlock() = 0;
+ virtual audio_utils::mutex& mutex() const = 0;
};
class IAfEffectModule : public virtual IAfEffectBase {
@@ -218,8 +218,7 @@
virtual void process_l() = 0;
- virtual void lock() = 0;
- virtual void unlock() = 0;
+ virtual audio_utils::mutex& mutex() const = 0;
virtual status_t createEffect_l(sp<IAfEffectModule>& effect,
effect_descriptor_t *desc,
diff --git a/services/audioflinger/IAfPatchPanel.h b/services/audioflinger/IAfPatchPanel.h
index 20e092d..5a6621e 100644
--- a/services/audioflinger/IAfPatchPanel.h
+++ b/services/audioflinger/IAfPatchPanel.h
@@ -45,8 +45,7 @@
mRecordThreadHandle(recordThreadHandle) {}
SoftwarePatch(const SoftwarePatch&) = default;
- // Must be called under AudioFlinger::mLock
- status_t getLatencyMs_l(double* latencyMs) const;
+ status_t getLatencyMs_l(double* latencyMs) const REQUIRES(audio_utils::AudioFlinger_Mutex);
audio_patch_handle_t getPatchHandle() const { return mPatchHandle; };
audio_io_handle_t getPlaybackThreadHandle() const { return mPlaybackThreadHandle; };
audio_io_handle_t getRecordThreadHandle() const { return mRecordThreadHandle; };
@@ -60,12 +59,14 @@
class IAfPatchPanelCallback : public virtual RefBase {
public:
- virtual void closeThreadInternal_l(const sp<IAfPlaybackThread>& thread) = 0;
- virtual void closeThreadInternal_l(const sp<IAfRecordThread>& thread) = 0;
- virtual IAfPlaybackThread* primaryPlaybackThread_l() const = 0;
- virtual IAfPlaybackThread* checkPlaybackThread_l(audio_io_handle_t output) const = 0;
- virtual IAfRecordThread* checkRecordThread_l(audio_io_handle_t input) const = 0;
- virtual IAfMmapThread* checkMmapThread_l(audio_io_handle_t io) const = 0;
+ virtual void closeThreadInternal_l(const sp<IAfPlaybackThread>& thread) REQUIRES(mutex()) = 0;
+ virtual void closeThreadInternal_l(const sp<IAfRecordThread>& thread) REQUIRES(mutex()) = 0;
+ virtual IAfPlaybackThread* primaryPlaybackThread_l() const REQUIRES(mutex()) = 0;
+ virtual IAfPlaybackThread* checkPlaybackThread_l(audio_io_handle_t output) const
+ REQUIRES(mutex()) = 0;
+ virtual IAfRecordThread* checkRecordThread_l(audio_io_handle_t input) const
+ REQUIRES(mutex()) = 0;
+ virtual IAfMmapThread* checkMmapThread_l(audio_io_handle_t io) const REQUIRES(mutex()) = 0;
virtual sp<IAfThreadBase> openInput_l(audio_module_handle_t module,
audio_io_handle_t* input,
audio_config_t* config,
@@ -74,23 +75,25 @@
audio_source_t source,
audio_input_flags_t flags,
audio_devices_t outputDevice,
- const String8& outputDeviceAddress) = 0;
+ const String8& outputDeviceAddress) REQUIRES(mutex()) = 0;
virtual sp<IAfThreadBase> openOutput_l(audio_module_handle_t module,
audio_io_handle_t* output,
audio_config_t* halConfig,
audio_config_base_t* mixerConfig,
audio_devices_t deviceType,
const String8& address,
- audio_output_flags_t flags) = 0;
- virtual void lock() const = 0;
- virtual void unlock() const = 0;
+ audio_output_flags_t flags) REQUIRES(mutex()) = 0;
+ virtual audio_utils::mutex& mutex() const
+ RETURN_CAPABILITY(audio_utils::AudioFlinger_Mutex) = 0;
virtual const DefaultKeyedVector<audio_module_handle_t, AudioHwDevice*>&
- getAudioHwDevs_l() const = 0;
+ getAudioHwDevs_l() const REQUIRES(mutex()) = 0;
virtual audio_unique_id_t nextUniqueId(audio_unique_id_use_t use) = 0;
virtual const sp<PatchCommandThread>& getPatchCommandThread() = 0;
virtual void updateDownStreamPatches_l(
- const struct audio_patch* patch, const std::set<audio_io_handle_t>& streams) = 0;
- virtual void updateOutDevicesForRecordThreads_l(const DeviceDescriptorBaseVector& devices) = 0;
+ const struct audio_patch* patch, const std::set<audio_io_handle_t>& streams)
+ REQUIRES(mutex()) = 0;
+ virtual void updateOutDevicesForRecordThreads_l(const DeviceDescriptorBaseVector& devices)
+ REQUIRES(mutex()) = 0;
};
class IAfPatchPanel : public virtual RefBase {
@@ -134,9 +137,12 @@
sp<const ThreadType> const_thread() const { return mThread; }
sp<const TrackType> const_track() const { return mTrack; }
- void closeConnections(const sp<IAfPatchPanel>& panel) {
+ void closeConnections_l(const sp<IAfPatchPanel>& panel)
+ REQUIRES(audio_utils::AudioFlinger_Mutex)
+ NO_THREAD_SAFETY_ANALYSIS // this is broken in clang
+ {
if (mHandle != AUDIO_PATCH_HANDLE_NONE) {
- panel->releaseAudioPatch(mHandle);
+ panel->releaseAudioPatch_l(mHandle);
mHandle = AUDIO_PATCH_HANDLE_NONE;
}
if (mThread != nullptr) {
@@ -218,8 +224,10 @@
friend void swap(Patch& a, Patch& b) noexcept { a.swap(b); }
- status_t createConnections(const sp<IAfPatchPanel>& panel);
- void clearConnections(const sp<IAfPatchPanel>& panel);
+ status_t createConnections_l(const sp<IAfPatchPanel>& panel)
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
+ void clearConnections_l(const sp<IAfPatchPanel>& panel)
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
bool isSoftware() const {
return mRecord.handle() != AUDIO_PATCH_HANDLE_NONE ||
mPlayback.handle() != AUDIO_PATCH_HANDLE_NONE;
@@ -251,22 +259,27 @@
};
/* List connected audio ports and their attributes */
- virtual status_t listAudioPorts(unsigned int* num_ports, struct audio_port* ports) = 0;
+ virtual status_t listAudioPorts_l(unsigned int* num_ports, struct audio_port* ports)
+ REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
/* Get supported attributes for a given audio port */
- virtual status_t getAudioPort(struct audio_port_v7* port) = 0;
+ virtual status_t getAudioPort_l(struct audio_port_v7* port)
+ REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
/* Create a patch between several source and sink ports */
- virtual status_t createAudioPatch(
+ virtual status_t createAudioPatch_l(
const struct audio_patch* patch,
audio_patch_handle_t* handle,
- bool endpointPatch = false) = 0;
+ bool endpointPatch = false)
+ REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
/* Release a patch */
- virtual status_t releaseAudioPatch(audio_patch_handle_t handle) = 0;
+ virtual status_t releaseAudioPatch_l(audio_patch_handle_t handle)
+ REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
/* List connected audio devices and they attributes */
- virtual status_t listAudioPatches(unsigned int* num_patches, struct audio_patch* patches) = 0;
+ virtual status_t listAudioPatches_l(unsigned int* num_patches, struct audio_patch* patches)
+ REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
// Retrieves all currently estrablished software patches for a stream
// opened on an intermediate module.
@@ -281,13 +294,14 @@
virtual void dump(int fd) const = 0;
- // Must be called under AudioFlinger::mLock
+ virtual const std::map<audio_patch_handle_t, Patch>& patches_l() const
+ REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
- virtual const std::map<audio_patch_handle_t, Patch>& patches_l() const = 0;
+ virtual status_t getLatencyMs_l(audio_patch_handle_t patchHandle, double* latencyMs) const
+ REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
- virtual status_t getLatencyMs_l(audio_patch_handle_t patchHandle, double* latencyMs) const = 0;
-
- virtual void closeThreadInternal_l(const sp<IAfThreadBase>& thread) const = 0;
+ virtual void closeThreadInternal_l(const sp<IAfThreadBase>& thread) const
+ REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
};
} // namespace android
diff --git a/services/audioflinger/IAfThread.h b/services/audioflinger/IAfThread.h
index 6ee1ec9..7084be9 100644
--- a/services/audioflinger/IAfThread.h
+++ b/services/audioflinger/IAfThread.h
@@ -19,6 +19,7 @@
#include <android/media/IAudioTrackCallback.h>
#include <android/media/IEffectClient.h>
#include <audiomanager/IAudioManager.h>
+#include <audio_utils/mutex.h>
#include <audio_utils/MelProcessor.h>
#include <binder/MemoryDealer.h>
#include <datapath/AudioStreamIn.h>
@@ -30,7 +31,6 @@
#include <media/audiohal/StreamHalInterface.h>
#include <media/nblog/NBLog.h>
#include <timing/SyncEvent.h>
-#include <utils/Mutex.h>
#include <utils/RefBase.h>
#include <vibrator/ExternalVibration.h>
@@ -67,44 +67,57 @@
// and hence may be used by the Effect / Track framework.
class IAfThreadCallback : public virtual RefBase {
public:
- virtual Mutex& mutex() const = 0;
- virtual bool isNonOffloadableGlobalEffectEnabled_l() const = 0; // Tracks
+ virtual audio_utils::mutex& mutex() const
+ RETURN_CAPABILITY(audio_utils::AudioFlinger_Mutex) = 0;
+ virtual bool isNonOffloadableGlobalEffectEnabled_l() const
+ REQUIRES(mutex()) EXCLUDES_ThreadBase_Mutex = 0; // Tracks
virtual audio_unique_id_t nextUniqueId(audio_unique_id_use_t use) = 0;
virtual bool btNrecIsOff() const = 0;
- virtual float masterVolume_l() const = 0;
- virtual bool masterMute_l() const = 0;
- virtual float getMasterBalance_l() const = 0;
- virtual bool streamMute_l(audio_stream_type_t stream) const = 0;
+ virtual float masterVolume_l() const
+ REQUIRES(mutex()) = 0;
+ virtual bool masterMute_l() const
+ REQUIRES(mutex()) = 0;
+ virtual float getMasterBalance_l() const
+ REQUIRES(mutex()) = 0;
+ virtual bool streamMute_l(audio_stream_type_t stream) const
+ REQUIRES(mutex()) = 0;
virtual audio_mode_t getMode() const = 0;
virtual bool isLowRamDevice() const = 0;
virtual bool isAudioPolicyReady() const = 0; // Effects
virtual uint32_t getScreenState() const = 0;
- virtual std::optional<media::AudioVibratorInfo> getDefaultVibratorInfo_l() const = 0;
+ virtual std::optional<media::AudioVibratorInfo> getDefaultVibratorInfo_l() const
+ REQUIRES(mutex()) = 0;
virtual const sp<IAfPatchPanel>& getPatchPanel() const = 0;
virtual const sp<MelReporter>& getMelReporter() const = 0;
virtual const sp<EffectsFactoryHalInterface>& getEffectsFactoryHal() const = 0;
virtual sp<IAudioManager> getOrCreateAudioManager() = 0; // Tracks
- virtual bool updateOrphanEffectChains(const sp<IAfEffectModule>& effect) = 0;
- virtual status_t moveEffectChain_l(audio_session_t sessionId,
- IAfPlaybackThread* srcThread, IAfPlaybackThread* dstThread) = 0;
+ virtual bool updateOrphanEffectChains(const sp<IAfEffectModule>& effect)
+ EXCLUDES_AudioFlinger_Mutex = 0;
+ virtual status_t moveEffectChain_ll(audio_session_t sessionId,
+ IAfPlaybackThread* srcThread, IAfPlaybackThread* dstThread)
+ REQUIRES(mutex(), audio_utils::ThreadBase_Mutex) = 0;
virtual void requestLogMerge() = 0;
- virtual sp<NBLog::Writer> newWriter_l(size_t size, const char *name) = 0;
+ virtual sp<NBLog::Writer> newWriter_l(size_t size, const char *name)
+ REQUIRES(mutex()) = 0;
virtual void unregisterWriter(const sp<NBLog::Writer>& writer) = 0;
virtual sp<audioflinger::SyncEvent> createSyncEvent(AudioSystem::sync_event_t type,
audio_session_t triggerSession,
audio_session_t listenerSession,
const audioflinger::SyncEventCallback& callBack,
- const wp<IAfTrackBase>& cookie) = 0;
+ const wp<IAfTrackBase>& cookie)
+ EXCLUDES_AudioFlinger_Mutex = 0;
- virtual void ioConfigChanged(audio_io_config_event_t event,
+ // Hold either AudioFlinger::mutex or ThreadBase::mutex
+ virtual void ioConfigChanged_l(audio_io_config_event_t event,
const sp<AudioIoDescriptor>& ioDesc,
- pid_t pid = 0) = 0;
- virtual void onNonOffloadableGlobalEffectEnable() = 0;
+ pid_t pid = 0) EXCLUDES_AudioFlinger_ClientMutex = 0;
+ virtual void onNonOffloadableGlobalEffectEnable() EXCLUDES_AudioFlinger_Mutex = 0;
virtual void onSupportedLatencyModesChanged(
- audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes) = 0;
+ audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes)
+ EXCLUDES_AudioFlinger_ClientMutex = 0;
};
class IAfThreadBase : public virtual RefBase {
@@ -128,7 +141,7 @@
static bool isValidPcmSinkFormat(audio_format_t format);
virtual status_t readyToRun() = 0;
- virtual void clearPowerManager() = 0;
+ virtual void clearPowerManager() EXCLUDES_ThreadBase_Mutex = 0;
virtual status_t initCheck() const = 0;
virtual type_t type() const = 0;
virtual bool isDuplicating() const = 0;
@@ -144,21 +157,23 @@
virtual size_t frameCount() const = 0;
virtual audio_channel_mask_t hapticChannelMask() const = 0;
virtual uint32_t hapticChannelCount() const = 0;
- virtual uint32_t latency_l() const = 0;
- virtual void setVolumeForOutput_l(float left, float right) const = 0;
+ virtual uint32_t latency_l() const = 0; // NO_THREAD_SAFETY_ANALYSIS
+ virtual void setVolumeForOutput_l(float left, float right) const REQUIRES(mutex()) = 0;
// Return's the HAL's frame count i.e. fast mixer buffer size.
virtual size_t frameCountHAL() const = 0;
virtual size_t frameSize() const = 0;
// Should be "virtual status_t requestExitAndWait()" and override same
// method in Thread, but Thread::requestExitAndWait() is not yet virtual.
- virtual void exit() = 0;
- virtual bool checkForNewParameter_l(const String8& keyValuePair, status_t& status) = 0;
- virtual status_t setParameters(const String8& keyValuePairs) = 0;
- virtual String8 getParameters(const String8& keys) = 0;
- virtual void ioConfigChanged(
+ virtual void exit() EXCLUDES_ThreadBase_Mutex = 0;
+ virtual bool checkForNewParameter_l(const String8& keyValuePair, status_t& status)
+ REQUIRES(mutex()) = 0;
+ virtual status_t setParameters(const String8& keyValuePairs) EXCLUDES_ThreadBase_Mutex = 0;
+ virtual String8 getParameters(const String8& keys) EXCLUDES_ThreadBase_Mutex = 0;
+ virtual void ioConfigChanged_l(
audio_io_config_event_t event, pid_t pid = 0,
- audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE) = 0;
+ audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE)
+ /* holds either AF::mutex or TB::mutex */ = 0;
// sendConfigEvent_l() must be called with ThreadBase::mLock held
// Can temporarily release the lock if waiting for a reply from
@@ -166,38 +181,53 @@
// status_t sendConfigEvent_l(sp<ConfigEvent>& event);
virtual void sendIoConfigEvent(
audio_io_config_event_t event, pid_t pid = 0,
- audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE) = 0;
+ audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE) EXCLUDES_ThreadBase_Mutex = 0;
virtual void sendIoConfigEvent_l(
audio_io_config_event_t event, pid_t pid = 0,
- audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE) = 0;
- virtual void sendPrioConfigEvent(pid_t pid, pid_t tid, int32_t prio, bool forApp) = 0;
- virtual void sendPrioConfigEvent_l(pid_t pid, pid_t tid, int32_t prio, bool forApp) = 0;
- virtual status_t sendSetParameterConfigEvent_l(const String8& keyValuePair) = 0;
+ audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE) REQUIRES(mutex()) = 0;
+ virtual void sendPrioConfigEvent(pid_t pid, pid_t tid, int32_t prio, bool forApp)
+ EXCLUDES_ThreadBase_Mutex = 0;
+ virtual void sendPrioConfigEvent_l(pid_t pid, pid_t tid, int32_t prio, bool forApp)
+ REQUIRES(mutex()) = 0;
+ virtual status_t sendSetParameterConfigEvent_l(const String8& keyValuePair)
+ REQUIRES(mutex()) = 0;
virtual status_t sendCreateAudioPatchConfigEvent(
- const struct audio_patch* patch, audio_patch_handle_t* handle) = 0;
- virtual status_t sendReleaseAudioPatchConfigEvent(audio_patch_handle_t handle) = 0;
+ const struct audio_patch* patch, audio_patch_handle_t* handle)
+ EXCLUDES_ThreadBase_Mutex = 0;
+ virtual status_t sendReleaseAudioPatchConfigEvent(audio_patch_handle_t handle)
+ EXCLUDES_ThreadBase_Mutex = 0;
virtual status_t sendUpdateOutDeviceConfigEvent(
- const DeviceDescriptorBaseVector& outDevices) = 0;
- virtual void sendResizeBufferConfigEvent_l(int32_t maxSharedAudioHistoryMs) = 0;
- virtual void sendCheckOutputStageEffectsEvent() = 0;
- virtual void sendCheckOutputStageEffectsEvent_l() = 0;
- virtual void sendHalLatencyModesChangedEvent_l() = 0;
+ const DeviceDescriptorBaseVector& outDevices) EXCLUDES_ThreadBase_Mutex = 0;
+ virtual void sendResizeBufferConfigEvent_l(int32_t maxSharedAudioHistoryMs)
+ REQUIRES(mutex()) = 0;
+ virtual void sendCheckOutputStageEffectsEvent() EXCLUDES_ThreadBase_Mutex = 0;
+ virtual void sendCheckOutputStageEffectsEvent_l()
+ REQUIRES(mutex()) = 0;
+ virtual void sendHalLatencyModesChangedEvent_l()
+ REQUIRES(mutex()) = 0;
- virtual void processConfigEvents_l() = 0;
- virtual void setCheckOutputStageEffects() = 0;
- virtual void cacheParameters_l() = 0;
+ virtual void processConfigEvents_l()
+ REQUIRES(mutex()) = 0;
+ virtual void setCheckOutputStageEffects() = 0; // no mutex needed
+ virtual void cacheParameters_l()
+ REQUIRES(mutex()) = 0;
virtual status_t createAudioPatch_l(
- const struct audio_patch* patch, audio_patch_handle_t* handle) = 0;
- virtual status_t releaseAudioPatch_l(const audio_patch_handle_t handle) = 0;
- virtual void updateOutDevices(const DeviceDescriptorBaseVector& outDevices) = 0;
- virtual void toAudioPortConfig(struct audio_port_config* config) = 0;
- virtual void resizeInputBuffer_l(int32_t maxSharedAudioHistoryMs) = 0;
+ const struct audio_patch* patch, audio_patch_handle_t* handle)
+ REQUIRES(mutex()) = 0;
+ virtual status_t releaseAudioPatch_l(const audio_patch_handle_t handle)
+ REQUIRES(mutex()) = 0;
+ virtual void updateOutDevices(const DeviceDescriptorBaseVector& outDevices)
+ EXCLUDES_ThreadBase_Mutex = 0;
+ virtual void toAudioPortConfig(struct audio_port_config* config)
+ EXCLUDES_ThreadBase_Mutex = 0;
+ virtual void resizeInputBuffer_l(int32_t maxSharedAudioHistoryMs)
+ REQUIRES(mutex()) = 0;
// see note at declaration of mStandby, mOutDevice and mInDevice
virtual bool inStandby() const = 0;
- virtual const DeviceTypeSet outDeviceTypes() const = 0;
- virtual audio_devices_t inDeviceType() const = 0;
- virtual DeviceTypeSet getDeviceTypes() const = 0;
+ virtual const DeviceTypeSet outDeviceTypes_l() const REQUIRES(mutex()) = 0;
+ virtual audio_devices_t inDeviceType_l() const REQUIRES(mutex()) = 0;
+ virtual DeviceTypeSet getDeviceTypes_l() const REQUIRES(mutex()) = 0;
virtual const AudioDeviceTypeAddrVector& outDeviceTypeAddrs() const = 0;
virtual const AudioDeviceTypeAddr& inDeviceTypeAddr() const = 0;
virtual bool isOutput() const = 0;
@@ -213,7 +243,8 @@
status_t* status /*non-NULL*/,
bool pinned,
bool probe,
- bool notifyFramesProcessed) = 0;
+ bool notifyFramesProcessed)
+ REQUIRES(audio_utils::AudioFlinger_Mutex) EXCLUDES_ThreadBase_Mutex = 0;
// return values for hasAudioSession (bit field)
enum effect_state {
@@ -230,57 +261,76 @@
};
// get effect chain corresponding to session Id.
- virtual sp<IAfEffectChain> getEffectChain(audio_session_t sessionId) const = 0;
+ virtual sp<IAfEffectChain> getEffectChain(audio_session_t sessionId) const
+ EXCLUDES_ThreadBase_Mutex = 0;
// same as getEffectChain() but must be called with ThreadBase mutex locked
- virtual sp<IAfEffectChain> getEffectChain_l(audio_session_t sessionId) const = 0;
- virtual std::vector<int> getEffectIds_l(audio_session_t sessionId) const = 0;
+ virtual sp<IAfEffectChain> getEffectChain_l(audio_session_t sessionId) const
+ REQUIRES(mutex()) = 0;
+ virtual std::vector<int> getEffectIds_l(audio_session_t sessionId) const
+ REQUIRES(mutex()) = 0;
// add an effect chain to the chain list (mEffectChains)
- virtual status_t addEffectChain_l(const sp<IAfEffectChain>& chain) = 0;
+ virtual status_t addEffectChain_l(const sp<IAfEffectChain>& chain)
+ REQUIRES(mutex()) = 0;
// remove an effect chain from the chain list (mEffectChains)
- virtual size_t removeEffectChain_l(const sp<IAfEffectChain>& chain) = 0;
+ virtual size_t removeEffectChain_l(const sp<IAfEffectChain>& chain)
+ REQUIRES(mutex()) = 0;
// lock all effect chains Mutexes. Must be called before releasing the
// ThreadBase mutex before processing the mixer and effects. This guarantees the
// integrity of the chains during the process.
// Also sets the parameter 'effectChains' to current value of mEffectChains.
- virtual void lockEffectChains_l(Vector<sp<IAfEffectChain>>& effectChains) = 0;
+ virtual void lockEffectChains_l(Vector<sp<IAfEffectChain>>& effectChains)
+ REQUIRES(mutex()) = 0;
// unlock effect chains after process
- virtual void unlockEffectChains(const Vector<sp<IAfEffectChain>>& effectChains) = 0;
+ virtual void unlockEffectChains(const Vector<sp<IAfEffectChain>>& effectChains)
+ EXCLUDES_ThreadBase_Mutex = 0;
// get a copy of mEffectChains vector
- virtual Vector<sp<IAfEffectChain>> getEffectChains_l() const = 0;
+ virtual Vector<sp<IAfEffectChain>> getEffectChains_l() const
+ REQUIRES(mutex()) = 0;
// set audio mode to all effect chains
- virtual void setMode(audio_mode_t mode) = 0;
+ virtual void setMode(audio_mode_t mode)
+ EXCLUDES_ThreadBase_Mutex = 0;
// get effect module with corresponding ID on specified audio session
- virtual sp<IAfEffectModule> getEffect(audio_session_t sessionId, int effectId) const = 0;
- virtual sp<IAfEffectModule> getEffect_l(audio_session_t sessionId, int effectId) const = 0;
+ virtual sp<IAfEffectModule> getEffect(audio_session_t sessionId, int effectId) const
+ EXCLUDES_ThreadBase_Mutex = 0;
+ virtual sp<IAfEffectModule> getEffect_l(audio_session_t sessionId, int effectId) const
+ REQUIRES(mutex()) = 0;
// add and effect module. Also creates the effect chain is none exists for
// the effects audio session. Only called in a context of moving an effect
// from one thread to another
- virtual status_t addEffect_l(const sp<IAfEffectModule>& effect) = 0;
+ virtual status_t addEffect_ll(const sp<IAfEffectModule>& effect)
+ REQUIRES(audio_utils::AudioFlinger_Mutex, mutex()) = 0;
// remove and effect module. Also removes the effect chain is this was the last
// effect
- virtual void removeEffect_l(const sp<IAfEffectModule>& effect, bool release = false) = 0;
+ virtual void removeEffect_l(const sp<IAfEffectModule>& effect, bool release = false)
+ REQUIRES(mutex()) = 0;
// disconnect an effect handle from module and destroy module if last handle
- virtual void disconnectEffectHandle(IAfEffectHandle* handle, bool unpinIfLast) = 0;
+ virtual void disconnectEffectHandle(IAfEffectHandle* handle, bool unpinIfLast)
+ EXCLUDES_ThreadBase_Mutex = 0;
// detach all tracks connected to an auxiliary effect
- virtual void detachAuxEffect_l(int effectId) = 0;
+ virtual void detachAuxEffect_l(int effectId) REQUIRES(mutex()) = 0;
// returns a combination of:
// - EFFECT_SESSION if effects on this audio session exist in one chain
// - TRACK_SESSION if tracks on this audio session exist
// - FAST_SESSION if fast tracks on this audio session exist
// - SPATIALIZED_SESSION if spatialized tracks on this audio session exist
- virtual uint32_t hasAudioSession_l(audio_session_t sessionId) const = 0;
- virtual uint32_t hasAudioSession(audio_session_t sessionId) const = 0;
+ virtual uint32_t hasAudioSession_l(audio_session_t sessionId) const REQUIRES(mutex()) = 0;
+ virtual uint32_t hasAudioSession(audio_session_t sessionId) const
+ EXCLUDES_ThreadBase_Mutex = 0;
// the value returned by default implementation is not important as the
// strategy is only meaningful for PlaybackThread which implements this method
- virtual product_strategy_t getStrategyForSession_l(audio_session_t sessionId) const = 0;
+ virtual product_strategy_t getStrategyForSession_l(audio_session_t sessionId) const
+ REQUIRES(mutex()) = 0;
// check if some effects must be suspended/restored when an effect is enabled
// or disabled
virtual void checkSuspendOnEffectEnabled(
- bool enabled, audio_session_t sessionId, bool threadLocked) = 0;
+ bool enabled, audio_session_t sessionId, bool threadLocked)
+ EXCLUDES_ThreadBase_Mutex = 0;
- virtual status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event) = 0;
+ virtual status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event)
+ EXCLUDES_ThreadBase_Mutex = 0;
+ // internally static, perhaps make static member.
virtual bool isValidSyncEvent(const sp<audioflinger::SyncEvent>& event) const = 0;
// Return a reference to a per-thread heap which can be used to allocate IMemory
@@ -293,41 +343,48 @@
virtual sp<IMemory> pipeMemory() const = 0;
- virtual void systemReady() = 0;
+ virtual void systemReady() EXCLUDES_ThreadBase_Mutex = 0;
// checkEffectCompatibility_l() must be called with ThreadBase::mLock held
virtual status_t checkEffectCompatibility_l(
- const effect_descriptor_t* desc, audio_session_t sessionId) = 0;
+ const effect_descriptor_t* desc, audio_session_t sessionId) REQUIRES(mutex()) = 0;
- virtual void broadcast_l() = 0;
+ virtual void broadcast_l() REQUIRES(mutex()) = 0;
- virtual bool isTimestampCorrectionEnabled() const = 0;
+ virtual bool isTimestampCorrectionEnabled_l() const REQUIRES(mutex()) = 0;
virtual bool isMsdDevice() const = 0;
- virtual void dump(int fd, const Vector<String16>& args) = 0;
+ virtual void dump(int fd, const Vector<String16>& args) EXCLUDES_ThreadBase_Mutex = 0;
// deliver stats to mediametrics.
- virtual void sendStatistics(bool force) = 0;
+ virtual void sendStatistics(bool force) EXCLUDES_ThreadBase_Mutex = 0;
- virtual Mutex& mutex() const = 0;
+ virtual audio_utils::mutex& mutex() const
+ RETURN_CAPABILITY(audio_utils::ThreadBase_Mutex) = 0;
- virtual void onEffectEnable(const sp<IAfEffectModule>& effect) = 0;
- virtual void onEffectDisable() = 0;
+ virtual void onEffectEnable(const sp<IAfEffectModule>& effect) EXCLUDES_ThreadBase_Mutex = 0;
+ virtual void onEffectDisable() EXCLUDES_ThreadBase_Mutex = 0;
// invalidateTracksForAudioSession_l must be called with holding mLock.
- virtual void invalidateTracksForAudioSession_l(audio_session_t sessionId) const = 0;
+ virtual void invalidateTracksForAudioSession_l(audio_session_t sessionId) const
+ REQUIRES(mutex()) = 0;
// Invalidate all the tracks with the given audio session.
- virtual void invalidateTracksForAudioSession(audio_session_t sessionId) const = 0;
+ virtual void invalidateTracksForAudioSession(audio_session_t sessionId) const
+ EXCLUDES_ThreadBase_Mutex = 0;
virtual bool isStreamInitialized() const = 0;
- virtual void startMelComputation_l(const sp<audio_utils::MelProcessor>& processor) = 0;
- virtual void stopMelComputation_l() = 0;
+ virtual void startMelComputation_l(const sp<audio_utils::MelProcessor>& processor)
+ REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
+ virtual void stopMelComputation_l()
+ REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
- virtual product_strategy_t getStrategyForStream(audio_stream_type_t stream) const = 0;
+ virtual product_strategy_t getStrategyForStream(audio_stream_type_t stream) const
+ EXCLUDES_AUDIO_ALL = 0;
virtual void setEffectSuspended_l(
- const effect_uuid_t* type, bool suspend, audio_session_t sessionId) = 0;
+ const effect_uuid_t* type, bool suspend, audio_session_t sessionId)
+ REQUIRES(mutex()) = 0;
// Dynamic cast to derived interface
virtual sp<IAfDirectOutputThread> asIAfDirectOutputThread() { return nullptr; }
@@ -375,7 +432,7 @@
// return estimated latency in milliseconds, as reported by HAL
virtual uint32_t latency() const = 0; // should be in IAfThreadBase?
- virtual uint32_t& fastTrackAvailMask_l() = 0;
+ virtual uint32_t& fastTrackAvailMask_l() REQUIRES(mutex()) = 0;
virtual sp<IAfTrack> createTrack_l(
const sp<Client>& client,
@@ -399,65 +456,73 @@
const sp<media::IAudioTrackCallback>& callback,
bool isSpatialized,
bool isBitPerfect,
- audio_output_flags_t* afTrackFlags) = 0;
+ audio_output_flags_t* afTrackFlags)
+ REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
- virtual status_t addTrack_l(const sp<IAfTrack>& track) = 0;
- virtual bool destroyTrack_l(const sp<IAfTrack>& track) = 0;
- virtual bool isTrackActive(const sp<IAfTrack>& track) const = 0;
- virtual void addOutputTrack_l(const sp<IAfTrack>& track) = 0;
+ virtual status_t addTrack_l(const sp<IAfTrack>& track) REQUIRES(mutex()) = 0;
+ virtual bool destroyTrack_l(const sp<IAfTrack>& track) REQUIRES(mutex()) = 0;
+ virtual bool isTrackActive(const sp<IAfTrack>& track) const REQUIRES(mutex()) = 0;
+ virtual void addOutputTrack_l(const sp<IAfTrack>& track) REQUIRES(mutex()) = 0;
- virtual AudioStreamOut* getOutput_l() const = 0;
- virtual AudioStreamOut* getOutput() const = 0;
- virtual AudioStreamOut* clearOutput() = 0;
+ virtual AudioStreamOut* getOutput_l() const REQUIRES(mutex()) = 0;
+ virtual AudioStreamOut* getOutput() const EXCLUDES_ThreadBase_Mutex = 0;
+ virtual AudioStreamOut* clearOutput() EXCLUDES_ThreadBase_Mutex = 0;
// a very large number of suspend() will eventually wraparound, but unlikely
virtual void suspend() = 0;
virtual void restore() = 0;
virtual bool isSuspended() const = 0;
- virtual status_t getRenderPosition(uint32_t* halFrames, uint32_t* dspFrames) const = 0;
+ virtual status_t getRenderPosition(uint32_t* halFrames, uint32_t* dspFrames) const
+ EXCLUDES_ThreadBase_Mutex = 0;
// Consider also removing and passing an explicit mMainBuffer initialization
// parameter to AF::IAfTrack::Track().
virtual float* sinkBuffer() const = 0;
- virtual status_t attachAuxEffect(const sp<IAfTrack>& track, int EffectId) = 0;
- virtual status_t attachAuxEffect_l(const sp<IAfTrack>& track, int EffectId) = 0;
+ virtual status_t attachAuxEffect(const sp<IAfTrack>& track, int EffectId)
+ EXCLUDES_ThreadBase_Mutex = 0;
+ virtual status_t attachAuxEffect_l(const sp<IAfTrack>& track, int EffectId)
+ REQUIRES(mutex()) = 0;
// called with AudioFlinger lock held
- virtual bool invalidateTracks_l(audio_stream_type_t streamType) = 0;
- virtual bool invalidateTracks_l(std::set<audio_port_handle_t>& portIds) = 0;
- virtual void invalidateTracks(audio_stream_type_t streamType) = 0;
+ virtual bool invalidateTracks_l(audio_stream_type_t streamType) REQUIRES(mutex()) = 0;
+ virtual bool invalidateTracks_l(std::set<audio_port_handle_t>& portIds) REQUIRES(mutex()) = 0;
+ virtual void invalidateTracks(audio_stream_type_t streamType)
+ EXCLUDES_ThreadBase_Mutex = 0;
// Invalidate tracks by a set of port ids. The port id will be removed from
// the given set if the corresponding track is found and invalidated.
- virtual void invalidateTracks(std::set<audio_port_handle_t>& portIds) = 0;
+ virtual void invalidateTracks(std::set<audio_port_handle_t>& portIds)
+ EXCLUDES_ThreadBase_Mutex = 0;
- virtual status_t getTimestamp_l(AudioTimestamp& timestamp) = 0;
- virtual void addPatchTrack(const sp<IAfPatchTrack>& track) = 0;
- virtual void deletePatchTrack(const sp<IAfPatchTrack>& track) = 0;
+ virtual status_t getTimestamp_l(AudioTimestamp& timestamp) REQUIRES(mutex()) = 0;
+ virtual void addPatchTrack(const sp<IAfPatchTrack>& track) EXCLUDES_ThreadBase_Mutex = 0;
+ virtual void deletePatchTrack(const sp<IAfPatchTrack>& track) EXCLUDES_ThreadBase_Mutex = 0;
// Return the asynchronous signal wait time.
- virtual int64_t computeWaitTimeNs_l() const = 0;
+ virtual int64_t computeWaitTimeNs_l() const REQUIRES(mutex()) = 0;
// returns true if the track is allowed to be added to the thread.
virtual bool isTrackAllowed_l(
audio_channel_mask_t channelMask, audio_format_t format, audio_session_t sessionId,
- uid_t uid) const = 0;
+ uid_t uid) const REQUIRES(mutex()) = 0;
virtual bool supportsHapticPlayback() const = 0;
- virtual void setDownStreamPatch(const struct audio_patch* patch) = 0;
+ virtual void setDownStreamPatch(const struct audio_patch* patch)
+ EXCLUDES_ThreadBase_Mutex = 0;
- virtual IAfTrack* getTrackById_l(audio_port_handle_t trackId) = 0;
+ virtual IAfTrack* getTrackById_l(audio_port_handle_t trackId) REQUIRES(mutex()) = 0;
virtual bool hasMixer() const = 0;
virtual status_t setRequestedLatencyMode(audio_latency_mode_t mode) = 0;
- virtual status_t getSupportedLatencyModes(std::vector<audio_latency_mode_t>* modes) = 0;
+ virtual status_t getSupportedLatencyModes(std::vector<audio_latency_mode_t>* modes)
+ EXCLUDES_ThreadBase_Mutex = 0;
virtual status_t setBluetoothVariableLatencyEnabled(bool enabled) = 0;
- virtual void setStandby() = 0;
- virtual void setStandby_l() = 0;
- virtual bool waitForHalStart() = 0;
+ virtual void setStandby() EXCLUDES_ThreadBase_Mutex = 0;
+ virtual void setStandby_l() REQUIRES(mutex()) = 0;
+ virtual bool waitForHalStart() EXCLUDES_ThreadBase_Mutex = 0;
virtual bool hasFastMixer() const = 0;
virtual FastTrackUnderruns getFastTrackUnderruns(size_t fastIndex) const = 0;
@@ -477,9 +542,9 @@
const sp<IAfThreadCallback>& afThreadCallback, IAfPlaybackThread* mainThread,
audio_io_handle_t id, bool systemReady);
- virtual void addOutputTrack(IAfPlaybackThread* thread) = 0;
+ virtual void addOutputTrack(IAfPlaybackThread* thread) EXCLUDES_ThreadBase_Mutex = 0;
virtual uint32_t waitTimeMs() const = 0;
- virtual void removeOutputTrack(IAfPlaybackThread* thread) = 0;
+ virtual void removeOutputTrack(IAfPlaybackThread* thread) EXCLUDES_ThreadBase_Mutex = 0;
};
class IAfRecordThread : public virtual IAfThreadBase {
@@ -503,42 +568,50 @@
pid_t tid,
status_t* status /*non-NULL*/,
audio_port_handle_t portId,
- int32_t maxSharedAudioHistoryMs) = 0;
- virtual void destroyTrack_l(const sp<IAfRecordTrack>& track) = 0;
- virtual void removeTrack_l(const sp<IAfRecordTrack>& track) = 0;
+ int32_t maxSharedAudioHistoryMs)
+ REQUIRES(audio_utils::AudioFlinger_Mutex) EXCLUDES_ThreadBase_Mutex = 0;
+ virtual void destroyTrack_l(const sp<IAfRecordTrack>& track) REQUIRES(mutex()) = 0;
+ virtual void removeTrack_l(const sp<IAfRecordTrack>& track) REQUIRES(mutex()) = 0;
virtual status_t start(
IAfRecordTrack* recordTrack, AudioSystem::sync_event_t event,
- audio_session_t triggerSession) = 0;
+ audio_session_t triggerSession) EXCLUDES_ThreadBase_Mutex = 0;
// ask the thread to stop the specified track, and
// return true if the caller should then do it's part of the stopping process
- virtual bool stop(IAfRecordTrack* recordTrack) = 0;
+ virtual bool stop(IAfRecordTrack* recordTrack) EXCLUDES_ThreadBase_Mutex = 0;
+ // NO_THREAD_SAFETY_ANALYSIS: consider atomics
virtual AudioStreamIn* getInput() const = 0;
virtual AudioStreamIn* clearInput() = 0;
virtual status_t getActiveMicrophones(
- std::vector<media::MicrophoneInfoFw>* activeMicrophones) const = 0;
- virtual status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction) = 0;
- virtual status_t setPreferredMicrophoneFieldDimension(float zoom) = 0;
+ std::vector<media::MicrophoneInfoFw>* activeMicrophones)
+ const EXCLUDES_ThreadBase_Mutex = 0;
+ virtual status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction)
+ EXCLUDES_ThreadBase_Mutex = 0;
+ virtual status_t setPreferredMicrophoneFieldDimension(float zoom)
+ EXCLUDES_ThreadBase_Mutex = 0;
- virtual void addPatchTrack(const sp<IAfPatchRecord>& record) = 0;
- virtual void deletePatchTrack(const sp<IAfPatchRecord>& record) = 0;
+ virtual void addPatchTrack(const sp<IAfPatchRecord>& record)
+ EXCLUDES_ThreadBase_Mutex = 0;
+ virtual void deletePatchTrack(const sp<IAfPatchRecord>& record)
+ EXCLUDES_ThreadBase_Mutex = 0;
virtual bool fastTrackAvailable() const = 0;
virtual void setFastTrackAvailable(bool available) = 0;
- virtual void setRecordSilenced(audio_port_handle_t portId, bool silenced) = 0;
+ virtual void setRecordSilenced(audio_port_handle_t portId, bool silenced)
+ EXCLUDES_ThreadBase_Mutex = 0;
virtual bool hasFastCapture() const = 0;
- virtual void checkBtNrec() = 0;
- virtual uint32_t getInputFramesLost() const = 0;
+ virtual void checkBtNrec() EXCLUDES_ThreadBase_Mutex = 0;
+ virtual uint32_t getInputFramesLost() const EXCLUDES_ThreadBase_Mutex = 0;
virtual status_t shareAudioHistory(
const std::string& sharedAudioPackageName,
audio_session_t sharedSessionId = AUDIO_SESSION_NONE,
- int64_t sharedAudioStartMs = -1) = 0;
- virtual void resetAudioHistory_l() = 0;
+ int64_t sharedAudioStartMs = -1) EXCLUDES_ThreadBase_Mutex = 0;
+ virtual void resetAudioHistory_l() REQUIRES(mutex()) = 0;
};
class IAfMmapThread : public virtual IAfThreadBase {
@@ -557,26 +630,32 @@
audio_session_t sessionId,
const sp<MmapStreamCallback>& callback,
audio_port_handle_t deviceId,
- audio_port_handle_t portId) = 0;
- virtual void disconnect() = 0;
+ audio_port_handle_t portId) EXCLUDES_ThreadBase_Mutex = 0;
+ virtual void disconnect() EXCLUDES_ThreadBase_Mutex = 0;
// MmapStreamInterface handling (see adapter)
virtual status_t createMmapBuffer(
- int32_t minSizeFrames, struct audio_mmap_buffer_info* info) = 0;
- virtual status_t getMmapPosition(struct audio_mmap_position* position) const = 0;
+ int32_t minSizeFrames, struct audio_mmap_buffer_info* info)
+ EXCLUDES_ThreadBase_Mutex = 0;
+ virtual status_t getMmapPosition(struct audio_mmap_position* position) const
+ EXCLUDES_ThreadBase_Mutex = 0;
virtual status_t start(
const AudioClient& client, const audio_attributes_t* attr,
- audio_port_handle_t* handle) = 0;
- virtual status_t stop(audio_port_handle_t handle) = 0;
- virtual status_t standby() = 0;
- virtual status_t getExternalPosition(uint64_t* position, int64_t* timeNanos) const = 0;
- virtual status_t reportData(const void* buffer, size_t frameCount) = 0;
+ audio_port_handle_t* handle) EXCLUDES_ThreadBase_Mutex = 0;
+ virtual status_t stop(audio_port_handle_t handle) EXCLUDES_ThreadBase_Mutex = 0;
+ virtual status_t standby() EXCLUDES_ThreadBase_Mutex = 0;
+ virtual status_t getExternalPosition(uint64_t* position, int64_t* timeNanos) const
+ EXCLUDES_ThreadBase_Mutex = 0;
+ virtual status_t reportData(const void* buffer, size_t frameCount)
+ EXCLUDES_ThreadBase_Mutex = 0;
// TODO(b/291317898) move to IAfThreadBase?
- virtual void invalidateTracks(std::set<audio_port_handle_t>& portIds) = 0;
+ virtual void invalidateTracks(std::set<audio_port_handle_t>& portIds)
+ EXCLUDES_ThreadBase_Mutex = 0;
// Sets the UID records silence - TODO(b/291317898) move to IAfMmapCaptureThread
- virtual void setRecordSilenced(audio_port_handle_t portId, bool silenced) = 0;
+ virtual void setRecordSilenced(audio_port_handle_t portId, bool silenced)
+ EXCLUDES_ThreadBase_Mutex = 0;
virtual sp<IAfMmapPlaybackThread> asIAfMmapPlaybackThread() { return nullptr; }
virtual sp<IAfMmapCaptureThread> asIAfMmapCaptureThread() { return nullptr; }
@@ -588,7 +667,7 @@
const sp<IAfThreadCallback>& afThreadCallback, audio_io_handle_t id,
AudioHwDevice* hwDev, AudioStreamOut* output, bool systemReady);
- virtual AudioStreamOut* clearOutput() = 0;
+ virtual AudioStreamOut* clearOutput() EXCLUDES_ThreadBase_Mutex = 0;
};
class IAfMmapCaptureThread : public virtual IAfMmapThread {
@@ -597,7 +676,7 @@
const sp<IAfThreadCallback>& afThreadCallback, audio_io_handle_t id,
AudioHwDevice* hwDev, AudioStreamIn* input, bool systemReady);
- virtual AudioStreamIn* clearInput() = 0;
+ virtual AudioStreamIn* clearInput() EXCLUDES_ThreadBase_Mutex = 0;
};
} // namespace android
diff --git a/services/audioflinger/MelReporter.cpp b/services/audioflinger/MelReporter.cpp
index 5dc2e8a..a9c868e 100644
--- a/services/audioflinger/MelReporter.cpp
+++ b/services/audioflinger/MelReporter.cpp
@@ -62,7 +62,7 @@
void MelReporter::activateInternalSoundDoseComputation() {
{
- std::lock_guard _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (!mUseHalSoundDoseInterface) {
// no need to start internal MEL on active patches
return;
@@ -87,8 +87,8 @@
return;
}
- std::lock_guard _laf(mAfMelReporterCallback->mutex());
- std::lock_guard _l(mLock);
+ audio_utils::lock_guard _laf(mAfMelReporterCallback->mutex()); // AudioFlinger_Mutex
+ audio_utils::lock_guard _l(mutex());
auto activeMelPatchId = activePatchStreamHandle_l(streamHandle);
if (!activeMelPatchId) {
ALOGV("%s stream handle %d does not have an active patch", __func__, streamHandle);
@@ -154,8 +154,8 @@
}
if (!newPatch.deviceStates.empty() && newPatch.csdActive) {
- std::lock_guard _afl(mAfMelReporterCallback->mutex());
- std::lock_guard _l(mLock);
+ audio_utils::lock_guard _afl(mAfMelReporterCallback->mutex()); // AudioFlinger_Mutex
+ audio_utils::lock_guard _l(mutex());
ALOGV("%s add patch handle %d to active devices", __func__, handle);
startMelComputationForActivePatch_l(newPatch);
mActiveMelPatches[handle] = newPatch;
@@ -192,8 +192,8 @@
void MelReporter::startMelComputationForDeviceId(audio_port_handle_t deviceId) {
ALOGV("%s(%d)", __func__, deviceId);
- std::lock_guard _laf(mAfMelReporterCallback->mutex());
- std::lock_guard _l(mLock);
+ audio_utils::lock_guard _laf(mAfMelReporterCallback->mutex());
+ audio_utils::lock_guard _l(mutex());
for (auto& activeMelPatch : mActiveMelPatches) {
bool csdActive = false;
@@ -218,7 +218,7 @@
ActiveMelPatch melPatch;
{
- std::lock_guard _l(mLock);
+ audio_utils::lock_guard _l(mutex());
auto patchIt = mActiveMelPatches.find(handle);
if (patchIt == mActiveMelPatches.end()) {
@@ -231,8 +231,8 @@
mActiveMelPatches.erase(patchIt);
}
- std::lock_guard _afl(mAfMelReporterCallback->mutex());
- std::lock_guard _l(mLock);
+ audio_utils::lock_guard _afl(mAfMelReporterCallback->mutex()); // AudioFlinger_Mutex
+ audio_utils::lock_guard _l(mutex());
if (melPatch.csdActive) {
// only need to stop if patch was active
melPatch.csdActive = false;
@@ -254,7 +254,7 @@
void MelReporter::stopInternalMelComputation() {
ALOGV("%s", __func__);
- std::lock_guard _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (mUseHalSoundDoseInterface) {
return;
}
@@ -287,8 +287,8 @@
void MelReporter::stopMelComputationForDeviceId(audio_port_handle_t deviceId) {
ALOGV("%s(%d)", __func__, deviceId);
- std::lock_guard _laf(mAfMelReporterCallback->mutex());
- std::lock_guard _l(mLock);
+ audio_utils::lock_guard _laf(mAfMelReporterCallback->mutex());
+ audio_utils::lock_guard _l(mutex());
for (auto& activeMelPatch : mActiveMelPatches) {
bool csdActive = false;
@@ -322,7 +322,7 @@
}
std::string MelReporter::dump() {
- std::lock_guard _l(mLock);
+ audio_utils::lock_guard _l(mutex());
std::string output("\nSound Dose:\n");
output.append(mSoundDoseManager->dump());
return output;
diff --git a/services/audioflinger/MelReporter.h b/services/audioflinger/MelReporter.h
index e26397c..bf4f390 100644
--- a/services/audioflinger/MelReporter.h
+++ b/services/audioflinger/MelReporter.h
@@ -20,9 +20,9 @@
#include "IAfPatchPanel.h"
#include "PatchCommandThread.h"
+#include <audio_utils/mutex.h>
#include <sounddose/SoundDoseManager.h>
-#include <mutex>
#include <unordered_map>
namespace android {
@@ -31,9 +31,11 @@
class IAfMelReporterCallback : public virtual RefBase {
public:
- virtual Mutex& mutex() const = 0;
+ virtual audio_utils::mutex& mutex() const
+ RETURN_CAPABILITY(audio_utils::AudioFlinger_Mutex) = 0;
virtual const sp<PatchCommandThread>& getPatchCommandThread() = 0;
- virtual sp<IAfThreadBase> checkOutputThread_l(audio_io_handle_t ioHandle) const = 0;
+ virtual sp<IAfThreadBase> checkOutputThread_l(audio_io_handle_t ioHandle) const
+ REQUIRES(mutex()) = 0;
};
/**
@@ -62,7 +64,7 @@
* implementation, false otherwise.
*/
bool activateHalSoundDoseComputation(const std::string& module,
- const sp<DeviceHalInterface>& device);
+ const sp<DeviceHalInterface>& device) EXCLUDES_MelReporter_Mutex;
/**
* Activates the MEL reporting from internal framework values. These are used
@@ -70,23 +72,26 @@
* Note: the internal CSD computation does not guarantee a certification with
* IEC62368-1 3rd edition or EN50332-3
*/
- void activateInternalSoundDoseComputation();
+ void activateInternalSoundDoseComputation() EXCLUDES_MelReporter_Mutex;
sp<media::ISoundDose> getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback);
std::string dump();
// IMelReporterCallback methods
- void stopMelComputationForDeviceId(audio_port_handle_t deviceId) override;
- void startMelComputationForDeviceId(audio_port_handle_t deviceId) override;
+ void stopMelComputationForDeviceId(audio_port_handle_t deviceId) final
+ EXCLUDES_MelReporter_Mutex;
+ void startMelComputationForDeviceId(audio_port_handle_t deviceId) final
+ EXCLUDES_MelReporter_Mutex;
// PatchCommandListener methods
void onCreateAudioPatch(audio_patch_handle_t handle,
- const IAfPatchPanel::Patch& patch) final;
- void onReleaseAudioPatch(audio_patch_handle_t handle) final;
+ const IAfPatchPanel::Patch& patch) final
+ EXCLUDES_AudioFlinger_Mutex;
+ void onReleaseAudioPatch(audio_patch_handle_t handle) final EXCLUDES_AudioFlinger_Mutex;
void onUpdateAudioPatch(audio_patch_handle_t oldHandle,
audio_patch_handle_t newHandle,
- const IAfPatchPanel::Patch& patch) final;
+ const IAfPatchPanel::Patch& patch) final EXCLUDES_AudioFlinger_Mutex;
/**
* The new metadata can determine whether we should compute MEL for the given thread.
@@ -94,7 +99,9 @@
* Otherwise, this method will disable CSD.
**/
void updateMetadataForCsd(audio_io_handle_t streamHandle,
- const std::vector<playback_track_metadata_v7_t>& metadataVec);
+ const std::vector<playback_track_metadata_v7_t>& metadataVec)
+ EXCLUDES_AudioFlinger_Mutex;
+
private:
struct ActiveMelPatch {
audio_io_handle_t streamHandle{AUDIO_IO_HANDLE_NONE};
@@ -108,30 +115,34 @@
};
void stopInternalMelComputation();
+ audio_utils::mutex& mutex() const RETURN_CAPABILITY(audio_utils::MelReporter_Mutex) {
+ return mMutex;
+ }
- /** Should be called with the following order of locks: mAudioFlinger.mLock -> mLock. */
- void stopMelComputationForPatch_l(const ActiveMelPatch& patch) REQUIRES(mLock);
+ /** Should be called with the following order of locks: mAudioFlinger.mutex() -> mutex(). */
+ void stopMelComputationForPatch_l(const ActiveMelPatch& patch) REQUIRES(mutex());
- /** Should be called with the following order of locks: mAudioFlinger.mLock -> mLock. */
- void startMelComputationForActivePatch_l(const ActiveMelPatch& patch) REQUIRES(mLock);
+ /** Should be called with the following order of locks: mAudioFlinger.mutex() -> mutex(). */
+ void startMelComputationForActivePatch_l(const ActiveMelPatch& patch) REQUIRES(mutex());
std::optional<audio_patch_handle_t>
- activePatchStreamHandle_l(audio_io_handle_t streamHandle) REQUIRES(mLock);
+ activePatchStreamHandle_l(audio_io_handle_t streamHandle) REQUIRES(mutex());
- bool useHalSoundDoseInterface_l() REQUIRES(mLock);
+ bool useHalSoundDoseInterface_l() REQUIRES(mutex());
const sp<IAfMelReporterCallback> mAfMelReporterCallback;
- sp<SoundDoseManager> mSoundDoseManager;
+ /* const */ sp<SoundDoseManager> mSoundDoseManager; // set onFirstRef
/**
* Lock for protecting the active mel patches. Do not mix with the AudioFlinger lock.
- * Locking order AudioFlinger::mLock -> PatchCommandThread::mLock -> MelReporter::mLock.
+ * Locking order AudioFlinger::mutex() -> PatchCommandThread::mutex() -> MelReporter::mutex().
*/
- std::mutex mLock;
- std::unordered_map<audio_patch_handle_t, ActiveMelPatch> mActiveMelPatches GUARDED_BY(mLock);
- std::unordered_map<audio_port_handle_t, int> mActiveDevices GUARDED_BY(mLock);
- bool mUseHalSoundDoseInterface GUARDED_BY(mLock) = false;
+ mutable audio_utils::mutex mMutex;
+ std::unordered_map<audio_patch_handle_t, ActiveMelPatch> mActiveMelPatches
+ GUARDED_BY(mutex());
+ std::unordered_map<audio_port_handle_t, int> mActiveDevices GUARDED_BY(mutex());
+ bool mUseHalSoundDoseInterface GUARDED_BY(mutex()) = false;
};
} // namespace android
diff --git a/services/audioflinger/PatchCommandThread.cpp b/services/audioflinger/PatchCommandThread.cpp
index 8d5eb9f..2cfefa0 100644
--- a/services/audioflinger/PatchCommandThread.cpp
+++ b/services/audioflinger/PatchCommandThread.cpp
@@ -29,7 +29,7 @@
PatchCommandThread::~PatchCommandThread() {
exit();
- std::lock_guard _l(mLock);
+ audio_utils::lock_guard _l(mutex());
mCommands.clear();
}
@@ -39,7 +39,7 @@
void PatchCommandThread::addListener(const sp<PatchCommandListener>& listener) {
ALOGV("%s add listener %p", __func__, static_cast<void*>(listener.get()));
- std::lock_guard _l(mListenerLock);
+ audio_utils::lock_guard _l(listenerMutex());
mListeners.emplace_back(listener);
}
@@ -69,9 +69,8 @@
}
bool PatchCommandThread::threadLoop()
-NO_THREAD_SAFETY_ANALYSIS // bug in clang compiler.
{
- std::unique_lock _l(mLock);
+ audio_utils::unique_lock _l(mutex());
while (!exitPending()) {
while (!mCommands.empty() && !exitPending()) {
@@ -81,7 +80,7 @@
std::vector<wp<PatchCommandListener>> listenersCopy;
{
- std::lock_guard _ll(mListenerLock);
+ audio_utils::lock_guard _ll(listenerMutex());
listenersCopy = mListeners;
}
@@ -147,7 +146,7 @@
}
void PatchCommandThread::sendCommand(const sp<Command>& command) {
- std::lock_guard _l(mLock);
+ audio_utils::lock_guard _l(mutex());
mCommands.emplace_back(command);
mWaitWorkCV.notify_one();
}
@@ -183,7 +182,7 @@
void PatchCommandThread::exit() {
ALOGV("%s", __func__);
{
- std::lock_guard _l(mLock);
+ audio_utils::lock_guard _l(mutex());
requestExit();
mWaitWorkCV.notify_one();
}
diff --git a/services/audioflinger/PatchCommandThread.h b/services/audioflinger/PatchCommandThread.h
index 66018d7..f491e8a 100644
--- a/services/audioflinger/PatchCommandThread.h
+++ b/services/audioflinger/PatchCommandThread.h
@@ -54,13 +54,14 @@
PatchCommandThread() : Thread(false /* canCallJava */) {}
~PatchCommandThread() override;
- void addListener(const sp<PatchCommandListener>& listener);
+ void addListener(const sp<PatchCommandListener>& listener)
+ EXCLUDES_PatchCommandThread_ListenerMutex;
- void createAudioPatch(audio_patch_handle_t handle, const IAfPatchPanel::Patch& patch);
- void releaseAudioPatch(audio_patch_handle_t handle);
- void updateAudioPatch(audio_patch_handle_t oldHandle,
- audio_patch_handle_t newHandle,
- const IAfPatchPanel::Patch& patch);
+ void createAudioPatch(audio_patch_handle_t handle, const IAfPatchPanel::Patch& patch)
+ EXCLUDES_PatchCommandThread_Mutex;
+ void releaseAudioPatch(audio_patch_handle_t handle) EXCLUDES_PatchCommandThread_Mutex;
+ void updateAudioPatch(audio_patch_handle_t oldHandle, audio_patch_handle_t newHandle,
+ const IAfPatchPanel::Patch& patch) EXCLUDES_PatchCommandThread_Mutex;
// Thread virtuals
void onFirstRef() override;
@@ -69,11 +70,11 @@
void exit();
void createAudioPatchCommand(audio_patch_handle_t handle,
- const IAfPatchPanel::Patch& patch);
- void releaseAudioPatchCommand(audio_patch_handle_t handle);
- void updateAudioPatchCommand(audio_patch_handle_t oldHandle,
- audio_patch_handle_t newHandle,
- const IAfPatchPanel::Patch& patch);
+ const IAfPatchPanel::Patch& patch) EXCLUDES_PatchCommandThread_Mutex;
+ void releaseAudioPatchCommand(audio_patch_handle_t handle) EXCLUDES_PatchCommandThread_Mutex;
+ void updateAudioPatchCommand(audio_patch_handle_t oldHandle, audio_patch_handle_t newHandle,
+ const IAfPatchPanel::Patch& patch) EXCLUDES_PatchCommandThread_Mutex;
+
private:
class CommandData;
@@ -119,15 +120,22 @@
const IAfPatchPanel::Patch mPatch;
};
- void sendCommand(const sp<Command>& command);
+ void sendCommand(const sp<Command>& command) EXCLUDES_PatchCommandThread_Mutex;
- std::string mThreadName;
- std::mutex mLock;
- std::condition_variable mWaitWorkCV;
- std::deque<sp<Command>> mCommands GUARDED_BY(mLock); // list of pending commands
+ audio_utils::mutex& mutex() const RETURN_CAPABILITY(audio_utils::PatchCommandThread_Mutex) {
+ return mMutex;
+ }
+ audio_utils::mutex& listenerMutex() const
+ RETURN_CAPABILITY(audio_utils::PatchCommandThread_ListenerMutex) {
+ return mListenerMutex;
+ }
- std::mutex mListenerLock;
- std::vector<wp<PatchCommandListener>> mListeners GUARDED_BY(mListenerLock);
+ mutable audio_utils::mutex mMutex;
+ audio_utils::condition_variable mWaitWorkCV;
+ std::deque<sp<Command>> mCommands GUARDED_BY(mutex()); // list of pending commands
+
+ mutable audio_utils::mutex mListenerMutex;
+ std::vector<wp<PatchCommandListener>> mListeners GUARDED_BY(listenerMutex());
};
} // namespace android
diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp
index 554272a..5f238fb 100644
--- a/services/audioflinger/PatchPanel.cpp
+++ b/services/audioflinger/PatchPanel.cpp
@@ -83,7 +83,7 @@
}
/* List connected audio ports and their attributes */
-status_t PatchPanel::listAudioPorts(unsigned int* /* num_ports */,
+status_t PatchPanel::listAudioPorts_l(unsigned int* /* num_ports */,
struct audio_port *ports __unused)
{
ALOGV(__func__);
@@ -91,14 +91,14 @@
}
/* Get supported attributes for a given audio port */
-status_t PatchPanel::getAudioPort(struct audio_port_v7* port)
+status_t PatchPanel::getAudioPort_l(struct audio_port_v7* port)
{
if (port->type != AUDIO_PORT_TYPE_DEVICE) {
// Only query the HAL when the port is a device.
// TODO: implement getAudioPort for mix.
return INVALID_OPERATION;
}
- AudioHwDevice* hwDevice = findAudioHwDeviceByModule(port->ext.device.hw_module);
+ AudioHwDevice* hwDevice = findAudioHwDeviceByModule_l(port->ext.device.hw_module);
if (hwDevice == nullptr) {
ALOGW("%s cannot find hw module %d", __func__, port->ext.device.hw_module);
return BAD_VALUE;
@@ -110,7 +110,7 @@
}
/* Connect a patch between several source and sink ports */
-status_t PatchPanel::createAudioPatch(const struct audio_patch* patch,
+status_t PatchPanel::createAudioPatch_l(const struct audio_patch* patch,
audio_patch_handle_t *handle,
bool endpointPatch)
//unlocks AudioFlinger::mLock when calling IAfThreadBase::sendCreateAudioPatchConfigEvent
@@ -145,7 +145,7 @@
// 1) if a software patch is present, release the playback and capture threads and
// tracks created. This will also release the corresponding audio HAL patches
if (removedPatch.isSoftware()) {
- removedPatch.clearConnections(this);
+ removedPatch.clearConnections_l(this);
}
// 2) if the new patch and old patch source or sink are devices from different
// hw modules, clear the audio HAL patches now because they will not be updated
@@ -171,7 +171,7 @@
// removedPatch.mHalHandle would be AUDIO_PATCH_HANDLE_NONE in this case.
hwModule = oldPatch.sinks[0].ext.device.hw_module;
}
- sp<DeviceHalInterface> hwDevice = findHwDeviceByModule(hwModule);
+ sp<DeviceHalInterface> hwDevice = findHwDeviceByModule_l(hwModule);
if (hwDevice != 0) {
hwDevice->releaseAudioPatch(removedPatch.mHalHandle);
}
@@ -191,7 +191,7 @@
switch (patch->sources[0].type) {
case AUDIO_PORT_TYPE_DEVICE: {
audio_module_handle_t srcModule = patch->sources[0].ext.device.hw_module;
- AudioHwDevice *audioHwDevice = findAudioHwDeviceByModule(srcModule);
+ AudioHwDevice *audioHwDevice = findAudioHwDeviceByModule_l(srcModule);
if (!audioHwDevice) {
status = BAD_VALUE;
goto exit;
@@ -323,7 +323,7 @@
goto exit;
}
newPatch.mRecord.setThread(thread->asIAfRecordThread().get());
- status = newPatch.createConnections(this);
+ status = newPatch.createConnections_l(this);
if (status != NO_ERROR) {
goto exit;
}
@@ -344,9 +344,9 @@
goto exit;
}
}
- mAfPatchPanelCallback->unlock();
+ mAfPatchPanelCallback->mutex().unlock();
status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle);
- mAfPatchPanelCallback->lock();
+ mAfPatchPanelCallback->mutex().lock();
if (status == NO_ERROR) {
newPatch.setThread(thread);
}
@@ -412,9 +412,25 @@
mAfPatchPanelCallback->updateOutDevicesForRecordThreads_l(devices);
}
- mAfPatchPanelCallback->unlock();
+ // For endpoint patches, we do not need to re-evaluate the device effect state
+ // if the same HAL patch is reused (see calls to mAfPatchPanelCallback below)
+ if (endpointPatch) {
+ for (auto& p : mPatches) {
+ // end point patches are skipped so we do not compare against this patch
+ if (!p.second.mIsEndpointPatch && patchesHaveSameRoute(
+ newPatch.mAudioPatch, p.second.mAudioPatch)) {
+ ALOGV("%s() Sw Bridge endpoint reusing halHandle=%d", __func__,
+ p.second.mHalHandle);
+ halHandle = p.second.mHalHandle;
+ reuseExistingHalPatch = true;
+ break;
+ }
+ }
+ }
+ mAfPatchPanelCallback->mutex().unlock();
+
status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle);
- mAfPatchPanelCallback->lock();
+ mAfPatchPanelCallback->mutex().lock();
if (status == NO_ERROR) {
newPatch.setThread(thread);
}
@@ -442,18 +458,25 @@
*handle = static_cast<audio_patch_handle_t>(
mAfPatchPanelCallback->nextUniqueId(AUDIO_UNIQUE_ID_USE_PATCH));
newPatch.mHalHandle = halHandle;
- if (reuseExistingHalPatch) {
- mAfPatchPanelCallback->getPatchCommandThread()->updateAudioPatch(
- oldhandle, *handle, newPatch);
- } else {
- mAfPatchPanelCallback->getPatchCommandThread()->createAudioPatch(*handle, newPatch);
+ // Skip device effect:
+ // -for sw bridge as effect are likely held by endpoint patches
+ // -for endpoint reusing a HalPatch handle
+ if (!(newPatch.isSoftware()
+ || (endpointPatch && reuseExistingHalPatch))) {
+ if (reuseExistingHalPatch) {
+ mAfPatchPanelCallback->getPatchCommandThread()->updateAudioPatch(
+ oldhandle, *handle, newPatch);
+ } else {
+ mAfPatchPanelCallback->getPatchCommandThread()->createAudioPatch(
+ *handle, newPatch);
+ }
}
if (insertedModule != AUDIO_MODULE_HANDLE_NONE) {
- addSoftwarePatchToInsertedModules(insertedModule, *handle, &newPatch.mAudioPatch);
+ addSoftwarePatchToInsertedModules_l(insertedModule, *handle, &newPatch.mAudioPatch);
}
mPatches.insert(std::make_pair(*handle, std::move(newPatch)));
} else {
- newPatch.clearConnections(this);
+ newPatch.clearConnections_l(this);
}
return status;
}
@@ -464,10 +487,10 @@
mRecord.handle(), mPlayback.handle());
}
-status_t PatchPanel::Patch::createConnections(const sp<IAfPatchPanel>& panel)
+status_t PatchPanel::Patch::createConnections_l(const sp<IAfPatchPanel>& panel)
{
// create patch from source device to record thread input
- status_t status = panel->createAudioPatch(
+ status_t status = panel->createAudioPatch_l(
PatchBuilder().addSource(mAudioPatch.sources[0]).
addSink(mRecord.thread(), { .source = AUDIO_SOURCE_MIC }).patch(),
mRecord.handlePtr(),
@@ -479,7 +502,7 @@
// create patch from playback thread output to sink device
if (mAudioPatch.num_sinks != 0) {
- status = panel->createAudioPatch(
+ status = panel->createAudioPatch_l(
PatchBuilder().addSource(mPlayback.thread()).addSink(mAudioPatch.sinks[0]).patch(),
mPlayback.handlePtr(),
true /*endpointPatch*/);
@@ -628,15 +651,15 @@
return status;
}
-void PatchPanel::Patch::clearConnections(const sp<IAfPatchPanel>& panel)
+void PatchPanel::Patch::clearConnections_l(const sp<IAfPatchPanel>& panel)
{
ALOGV("%s() mRecord.handle %d mPlayback.handle %d",
__func__, mRecord.handle(), mPlayback.handle());
mRecord.stopTrack();
mPlayback.stopTrack();
mRecord.clearTrackPeer(); // mRecord stop is synchronous. Break PeerProxy sp<> cycle.
- mRecord.closeConnections(panel);
- mPlayback.closeConnections(panel);
+ mRecord.closeConnections_l(panel);
+ mPlayback.closeConnections_l(panel);
}
status_t PatchPanel::Patch::getLatencyMs(double* latencyMs) const
@@ -726,7 +749,7 @@
}
/* Disconnect a patch */
-status_t PatchPanel::releaseAudioPatch(audio_patch_handle_t handle)
+status_t PatchPanel::releaseAudioPatch_l(audio_patch_handle_t handle)
//unlocks AudioFlinger::mLock when calling IAfThreadBase::sendReleaseAudioPatchConfigEvent
//to avoid deadlocks if the thread loop needs to acquire AudioFlinger::mLock
//before processing the release patch request.
@@ -734,18 +757,20 @@
{
ALOGV("%s handle %d", __func__, handle);
status_t status = NO_ERROR;
+ bool doReleasePatch = true;
auto iter = mPatches.find(handle);
if (iter == mPatches.end()) {
return BAD_VALUE;
}
Patch &removedPatch = iter->second;
+ const bool isSwBridge = removedPatch.isSoftware();
const struct audio_patch &patch = removedPatch.mAudioPatch;
const struct audio_port_config &src = patch.sources[0];
switch (src.type) {
case AUDIO_PORT_TYPE_DEVICE: {
- sp<DeviceHalInterface> hwDevice = findHwDeviceByModule(src.ext.device.hw_module);
+ sp<DeviceHalInterface> hwDevice = findHwDeviceByModule_l(src.ext.device.hw_module);
if (hwDevice == 0) {
ALOGW("%s() bad src hw module %d", __func__, src.ext.device.hw_module);
status = BAD_VALUE;
@@ -753,7 +778,7 @@
}
if (removedPatch.isSoftware()) {
- removedPatch.clearConnections(this);
+ removedPatch.clearConnections_l(this);
break;
}
@@ -768,15 +793,15 @@
break;
}
}
- mAfPatchPanelCallback->unlock();
+ mAfPatchPanelCallback->mutex().unlock();
status = thread->sendReleaseAudioPatchConfigEvent(removedPatch.mHalHandle);
- mAfPatchPanelCallback->lock();
+ mAfPatchPanelCallback->mutex().lock();
} else {
status = hwDevice->releaseAudioPatch(removedPatch.mHalHandle);
}
} break;
case AUDIO_PORT_TYPE_MIX: {
- if (findHwDeviceByModule(src.ext.mix.hw_module) == 0) {
+ if (findHwDeviceByModule_l(src.ext.mix.hw_module) == 0) {
ALOGW("%s() bad src hw module %d", __func__, src.ext.mix.hw_module);
status = BAD_VALUE;
break;
@@ -791,15 +816,31 @@
break;
}
}
- mAfPatchPanelCallback->unlock();
- status = thread->sendReleaseAudioPatchConfigEvent(removedPatch.mHalHandle);
- mAfPatchPanelCallback->lock();
+ // Check whether the removed patch Hal Handle is used in another non-Endpoint patch.
+ // Since this is a non-Endpoint patch, the removed patch is not considered (it is
+ // removed later from mPatches).
+ if (removedPatch.mIsEndpointPatch) {
+ for (auto& p: mPatches) {
+ if (!p.second.mIsEndpointPatch
+ && p.second.mHalHandle == removedPatch.mHalHandle) {
+ ALOGV("%s() Sw Bridge endpoint used existing halHandle=%d, do not release",
+ __func__, p.second.mHalHandle);
+ doReleasePatch = false;
+ break;
+ }
+ }
+ }
+ if (doReleasePatch) {
+ mAfPatchPanelCallback->mutex().unlock();
+ status = thread->sendReleaseAudioPatchConfigEvent(removedPatch.mHalHandle);
+ mAfPatchPanelCallback->mutex().lock();
+ }
} break;
default:
status = BAD_VALUE;
}
- erasePatch(handle);
+ erasePatch(handle, /* reuseExistingHalPatch= */ !doReleasePatch || isSwBridge);
return status;
}
@@ -812,7 +853,7 @@
}
/* List connected audio ports and they attributes */
-status_t PatchPanel::listAudioPatches(unsigned int* /* num_patches */,
+status_t PatchPanel::listAudioPatches_l(unsigned int* /* num_patches */,
struct audio_patch *patches __unused)
{
ALOGV(__func__);
@@ -869,7 +910,7 @@
}
}
-AudioHwDevice* PatchPanel::findAudioHwDeviceByModule(audio_module_handle_t module)
+AudioHwDevice* PatchPanel::findAudioHwDeviceByModule_l(audio_module_handle_t module)
{
if (module == AUDIO_MODULE_HANDLE_NONE) return nullptr;
ssize_t index = mAfPatchPanelCallback->getAudioHwDevs_l().indexOfKey(module);
@@ -880,13 +921,13 @@
return mAfPatchPanelCallback->getAudioHwDevs_l().valueAt(index);
}
-sp<DeviceHalInterface> PatchPanel::findHwDeviceByModule(audio_module_handle_t module)
+sp<DeviceHalInterface> PatchPanel::findHwDeviceByModule_l(audio_module_handle_t module)
{
- AudioHwDevice *audioHwDevice = findAudioHwDeviceByModule(module);
+ AudioHwDevice *audioHwDevice = findAudioHwDeviceByModule_l(module);
return audioHwDevice ? audioHwDevice->hwDevice() : nullptr;
}
-void PatchPanel::addSoftwarePatchToInsertedModules(
+void PatchPanel::addSoftwarePatchToInsertedModules_l(
audio_module_handle_t module, audio_patch_handle_t handle,
const struct audio_patch *patch)
{
diff --git a/services/audioflinger/PatchPanel.h b/services/audioflinger/PatchPanel.h
index a95c601..cec554c 100644
--- a/services/audioflinger/PatchPanel.h
+++ b/services/audioflinger/PatchPanel.h
@@ -30,25 +30,29 @@
: mAfPatchPanelCallback(afPatchPanelCallback) {}
/* List connected audio ports and their attributes */
- status_t listAudioPorts(unsigned int *num_ports,
- struct audio_port* ports) final;
+ status_t listAudioPorts_l(unsigned int *num_ports,
+ struct audio_port* ports) final REQUIRES(audio_utils::AudioFlinger_Mutex);
/* Get supported attributes for a given audio port */
- status_t getAudioPort(struct audio_port_v7* port) final;
+ status_t getAudioPort_l(struct audio_port_v7* port) final
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
/* Create a patch between several source and sink ports */
- status_t createAudioPatch(const struct audio_patch *patch,
+ status_t createAudioPatch_l(const struct audio_patch *patch,
audio_patch_handle_t *handle,
- bool endpointPatch = false) final;
+ bool endpointPatch = false) final
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
/* Release a patch */
- status_t releaseAudioPatch(audio_patch_handle_t handle) final;
+ status_t releaseAudioPatch_l(audio_patch_handle_t handle) final
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
/* List connected audio devices and they attributes */
- status_t listAudioPatches(unsigned int *num_patches,
- struct audio_patch* patches) final;
+ status_t listAudioPatches_l(unsigned int *num_patches,
+ struct audio_patch* patches) final
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
- // Retrieves all currently estrablished software patches for a stream
+ // Retrieves all currently established software patches for a stream
// opened on an intermediate module.
status_t getDownstreamSoftwarePatches(audio_io_handle_t stream,
std::vector<SoftwarePatch>* patches) const final;
@@ -60,20 +64,24 @@
void dump(int fd) const final;
- // Call with AudioFlinger mLock held
- const std::map<audio_patch_handle_t, Patch>& patches_l() const final { return mPatches; }
+ const std::map<audio_patch_handle_t, Patch>& patches_l() const final
+ REQUIRES(audio_utils::AudioFlinger_Mutex) { return mPatches; }
- // Must be called under AudioFlinger::mLock
- status_t getLatencyMs_l(audio_patch_handle_t patchHandle, double* latencyMs) const final;
+ status_t getLatencyMs_l(audio_patch_handle_t patchHandle, double* latencyMs) const final
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
- void closeThreadInternal_l(const sp<IAfThreadBase>& thread) const final;
+ void closeThreadInternal_l(const sp<IAfThreadBase>& thread) const final
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
private:
- AudioHwDevice* findAudioHwDeviceByModule(audio_module_handle_t module);
- sp<DeviceHalInterface> findHwDeviceByModule(audio_module_handle_t module);
- void addSoftwarePatchToInsertedModules(
+ AudioHwDevice* findAudioHwDeviceByModule_l(audio_module_handle_t module)
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
+ sp<DeviceHalInterface> findHwDeviceByModule_l(audio_module_handle_t module)
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
+ void addSoftwarePatchToInsertedModules_l(
audio_module_handle_t module, audio_patch_handle_t handle,
- const struct audio_patch *patch);
+ const struct audio_patch *patch)
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
void removeSoftwarePatchFromInsertedModules(audio_patch_handle_t handle);
/**
* erase the patch referred by its handle.
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index 3e5501f..078ae12 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -20,6 +20,7 @@
#include "TrackBase.h"
#include <android/os/BnExternalVibrationController.h>
+#include <audio_utils/mutex.h>
#include <audio_utils/LinearMap.h>
#include <binder/AppOpsManager.h>
@@ -468,7 +469,8 @@
*/
SourceMetadatas mTrackMetadatas;
/** Protects mTrackMetadatas against concurrent access. */
- mutable std::mutex mTrackMetadatasMutex;
+ audio_utils::mutex& trackMetadataMutex() const { return mTrackMetadataMutex; }
+ mutable audio_utils::mutex mTrackMetadataMutex;
}; // end of OutputTrack
// playback track, used by PatchPanel
diff --git a/services/audioflinger/RecordTracks.h b/services/audioflinger/RecordTracks.h
index 021add4..8d3de38 100644
--- a/services/audioflinger/RecordTracks.h
+++ b/services/audioflinger/RecordTracks.h
@@ -20,6 +20,7 @@
#include "TrackBase.h"
#include <android/content/AttributionSourceState.h>
+#include <audio_utils/mutex.h>
#include <datapath/AudioStreamIn.h> // struct Source
namespace android {
@@ -214,15 +215,16 @@
};
sp<StreamInHalInterface> obtainStream(sp<IAfThreadBase>* thread);
+ audio_utils::mutex& readMutex() const { return mReadMutex; }
PatchRecordAudioBufferProvider mPatchRecordAudioBufferProvider;
std::unique_ptr<void, decltype(free)*> mSinkBuffer; // frame size aligned continuous buffer
std::unique_ptr<void, decltype(free)*> mStubBuffer; // buffer used for AudioBufferProvider
size_t mUnconsumedFrames = 0;
- std::mutex mReadLock;
- std::condition_variable mReadCV;
- size_t mReadBytes = 0; // GUARDED_BY(mReadLock)
- status_t mReadError = NO_ERROR; // GUARDED_BY(mReadLock)
+ mutable audio_utils::mutex mReadMutex;
+ audio_utils::condition_variable mReadCV;
+ size_t mReadBytes = 0; // GUARDED_BY(readMutex())
+ status_t mReadError = NO_ERROR; // GUARDED_BY(readMutex())
int64_t mLastReadFrames = 0; // accessed on RecordThread only
};
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 157764f..e506ca6 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -685,9 +685,9 @@
// mWaitWorkCV.wait(...);
// // now thread is hung
// }
- AutoMutex lock(mLock);
+ audio_utils::lock_guard lock(mutex());
requestExit();
- mWaitWorkCV.broadcast();
+ mWaitWorkCV.notify_all();
}
// When Thread::requestExitAndWait is made virtual and this method is renamed to
// "virtual status_t requestExitAndWait()", replace by "return Thread::requestExitAndWait();"
@@ -697,7 +697,7 @@
status_t ThreadBase::setParameters(const String8& keyValuePairs)
{
ALOGV("ThreadBase::setParameters() %s", keyValuePairs.c_str());
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
return sendSetParameterConfigEvent_l(keyValuePairs);
}
@@ -716,30 +716,31 @@
}
mConfigEvents.add(event);
ALOGV("sendConfigEvent_l() num events %zu event %d", mConfigEvents.size(), event->mType);
- mWaitWorkCV.signal();
- mLock.unlock();
+ mWaitWorkCV.notify_one();
+ mutex().unlock();
{
- Mutex::Autolock _l(event->mLock);
+ audio_utils::unique_lock _l(event->mutex());
while (event->mWaitStatus) {
- if (event->mCond.waitRelative(event->mLock, kConfigEventTimeoutNs) != NO_ERROR) {
+ if (event->mCondition.wait_for(_l, std::chrono::nanoseconds(kConfigEventTimeoutNs))
+ == std::cv_status::timeout) {
event->mStatus = TIMED_OUT;
event->mWaitStatus = false;
}
}
status = event->mStatus;
}
- mLock.lock();
+ mutex().lock();
return status;
}
void ThreadBase::sendIoConfigEvent(audio_io_config_event_t event, pid_t pid,
audio_port_handle_t portId)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
sendIoConfigEvent_l(event, pid, portId);
}
-// sendIoConfigEvent_l() must be called with ThreadBase::mLock held
+// sendIoConfigEvent_l() must be called with ThreadBase::mutex() held
void ThreadBase::sendIoConfigEvent_l(audio_io_config_event_t event, pid_t pid,
audio_port_handle_t portId)
{
@@ -759,11 +760,11 @@
void ThreadBase::sendPrioConfigEvent(pid_t pid, pid_t tid, int32_t prio, bool forApp)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
sendPrioConfigEvent_l(pid, tid, prio, forApp);
}
-// sendPrioConfigEvent_l() must be called with ThreadBase::mLock held
+// sendPrioConfigEvent_l() must be called with ThreadBase::mutex() held
void ThreadBase::sendPrioConfigEvent_l(
pid_t pid, pid_t tid, int32_t prio, bool forApp)
{
@@ -771,7 +772,7 @@
sendConfigEvent_l(configEvent);
}
-// sendSetParameterConfigEvent_l() must be called with ThreadBase::mLock held
+// sendSetParameterConfigEvent_l() must be called with ThreadBase::mutex() held
status_t ThreadBase::sendSetParameterConfigEvent_l(const String8& keyValuePair)
{
sp<ConfigEvent> configEvent;
@@ -794,7 +795,7 @@
const struct audio_patch *patch,
audio_patch_handle_t *handle)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
sp<ConfigEvent> configEvent = (ConfigEvent *)new CreateAudioPatchConfigEvent(*patch, *handle);
status_t status = sendConfigEvent_l(configEvent);
if (status == NO_ERROR) {
@@ -808,7 +809,7 @@
status_t ThreadBase::sendReleaseAudioPatchConfigEvent(
const audio_patch_handle_t handle)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
sp<ConfigEvent> configEvent = (ConfigEvent *)new ReleaseAudioPatchConfigEvent(handle);
return sendConfigEvent_l(configEvent);
}
@@ -820,7 +821,7 @@
// The update out device operation is only for record thread.
return INVALID_OPERATION;
}
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
sp<ConfigEvent> configEvent = (ConfigEvent *)new UpdateOutDevicesConfigEvent(outDevices);
return sendConfigEvent_l(configEvent);
}
@@ -835,7 +836,7 @@
void ThreadBase::sendCheckOutputStageEffectsEvent()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
sendCheckOutputStageEffectsEvent_l();
}
@@ -874,7 +875,7 @@
} break;
case CFG_EVENT_IO: {
IoConfigEventData *data = (IoConfigEventData *)event->mData.get();
- ioConfigChanged(data->mEvent, data->mPid, data->mPortId);
+ ioConfigChanged_l(data->mEvent, data->mPid, data->mPortId);
} break;
case CFG_EVENT_SET_PARAMETER: {
SetParameterConfigEventData *data = (SetParameterConfigEventData *)event->mData.get();
@@ -885,22 +886,22 @@
}
} break;
case CFG_EVENT_CREATE_AUDIO_PATCH: {
- const DeviceTypeSet oldDevices = getDeviceTypes();
+ const DeviceTypeSet oldDevices = getDeviceTypes_l();
CreateAudioPatchConfigEventData *data =
(CreateAudioPatchConfigEventData *)event->mData.get();
event->mStatus = createAudioPatch_l(&data->mPatch, &data->mHandle);
- const DeviceTypeSet newDevices = getDeviceTypes();
+ const DeviceTypeSet newDevices = getDeviceTypes_l();
configChanged = oldDevices != newDevices;
mLocalLog.log("CFG_EVENT_CREATE_AUDIO_PATCH: old device %s (%s) new device %s (%s)",
dumpDeviceTypes(oldDevices).c_str(), toString(oldDevices).c_str(),
dumpDeviceTypes(newDevices).c_str(), toString(newDevices).c_str());
} break;
case CFG_EVENT_RELEASE_AUDIO_PATCH: {
- const DeviceTypeSet oldDevices = getDeviceTypes();
+ const DeviceTypeSet oldDevices = getDeviceTypes_l();
ReleaseAudioPatchConfigEventData *data =
(ReleaseAudioPatchConfigEventData *)event->mData.get();
event->mStatus = releaseAudioPatch_l(data->mHandle);
- const DeviceTypeSet newDevices = getDeviceTypes();
+ const DeviceTypeSet newDevices = getDeviceTypes_l();
configChanged = oldDevices != newDevices;
mLocalLog.log("CFG_EVENT_RELEASE_AUDIO_PATCH: old device %s (%s) new device %s (%s)",
dumpDeviceTypes(oldDevices).c_str(), toString(oldDevices).c_str(),
@@ -930,10 +931,10 @@
break;
}
{
- Mutex::Autolock _l(event->mLock);
+ audio_utils::lock_guard _l(event->mutex());
if (event->mWaitStatus) {
event->mWaitStatus = false;
- event->mCond.signal();
+ event->mCondition.notify_one();
}
}
ALOGV_IF(mConfigEvents.isEmpty(), "processConfigEvents_l() DONE thread %p", this);
@@ -1026,7 +1027,7 @@
dprintf(fd, "\n%s thread %p, name %s, tid %d, type %d (%s):\n", isOutput() ? "Output" : "Input",
this, mThreadName, getTid(), type(), threadTypeToString(type()));
- const bool locked = afutils::dumpTryLock(mLock);
+ const bool locked = afutils::dumpTryLock(mutex());
if (!locked) {
dprintf(fd, " Thread may be deadlocked\n");
}
@@ -1037,7 +1038,7 @@
dumpEffectChains_l(fd, args);
if (locked) {
- mLock.unlock();
+ mutex().unlock();
}
dprintf(fd, " Local log:\n");
@@ -1088,9 +1089,9 @@
}
// Note: output device may be used by capture threads for effects such as AEC.
dprintf(fd, " Output devices: %s (%s)\n",
- dumpDeviceTypes(outDeviceTypes()).c_str(), toString(outDeviceTypes()).c_str());
+ dumpDeviceTypes(outDeviceTypes_l()).c_str(), toString(outDeviceTypes_l()).c_str());
dprintf(fd, " Input device: %#x (%s)\n",
- inDeviceType(), toString(inDeviceType()).c_str());
+ inDeviceType_l(), toString(inDeviceType_l()).c_str());
dprintf(fd, " Audio source: %d (%s)\n", mAudioSource, toString(mAudioSource).c_str());
// Dump timestamp statistics for the Thread types that support it.
@@ -1101,7 +1102,8 @@
|| mType == OFFLOAD
|| mType == SPATIALIZER) {
dprintf(fd, " Timestamp stats: %s\n", mTimestampVerifier.toString().c_str());
- dprintf(fd, " Timestamp corrected: %s\n", isTimestampCorrectionEnabled() ? "yes" : "no");
+ dprintf(fd, " Timestamp corrected: %s\n",
+ isTimestampCorrectionEnabled_l() ? "yes" : "no");
}
if (mLastIoBeginNs > 0) { // MMAP may not set this
@@ -1152,7 +1154,7 @@
void ThreadBase::acquireWakeLock()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
acquireWakeLock_l();
}
@@ -1206,7 +1208,7 @@
void ThreadBase::releaseWakeLock()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
releaseWakeLock_l();
}
@@ -1265,7 +1267,7 @@
void ThreadBase::clearPowerManager()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
releaseWakeLock_l();
mPowerManager.clear();
}
@@ -1396,7 +1398,7 @@
NO_THREAD_SAFETY_ANALYSIS // manual locking
{
if (!threadLocked) {
- mLock.lock();
+ mutex().lock();
}
if (mType != RECORD) {
@@ -1411,11 +1413,11 @@
}
if (!threadLocked) {
- mLock.unlock();
+ mutex().unlock();
}
}
-// checkEffectCompatibility_l() must be called with ThreadBase::mLock held
+// checkEffectCompatibility_l() must be called with ThreadBase::mutex() held
status_t RecordThread::checkEffectCompatibility_l(
const effect_descriptor_t *desc, audio_session_t sessionId)
{
@@ -1459,7 +1461,7 @@
return NO_ERROR;
}
-// checkEffectCompatibility_l() must be called with ThreadBase::mLock held
+// checkEffectCompatibility_l() must be called with ThreadBase::mutex() held
status_t PlaybackThread::checkEffectCompatibility_l(
const effect_descriptor_t *desc, audio_session_t sessionId)
{
@@ -1614,7 +1616,7 @@
return NO_ERROR;
}
-// ThreadBase::createEffect_l() must be called with AudioFlinger::mLock held
+// ThreadBase::createEffect_l() must be called with AudioFlinger::mutex() held
sp<IAfEffectHandle> ThreadBase::createEffect_l(
const sp<Client>& client,
const sp<IEffectClient>& effectClient,
@@ -1643,8 +1645,8 @@
ALOGV("createEffect_l() thread %p effect %s on session %d", this, desc->name, sessionId);
- { // scope for mLock
- Mutex::Autolock _l(mLock);
+ { // scope for mutex()
+ audio_utils::lock_guard _l(mutex());
lStatus = checkEffectCompatibility_l(desc, sessionId);
if (probe || lStatus != NO_ERROR) {
@@ -1706,7 +1708,7 @@
Exit:
if (!probe && lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (effectCreated) {
chain->removeEffect_l(effect);
}
@@ -1726,7 +1728,7 @@
bool remove = false;
sp<IAfEffectModule> effect;
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
sp<IAfEffectBase> effectBase = handle->effect().promote();
if (effectBase == nullptr) {
return;
@@ -1752,7 +1754,7 @@
void ThreadBase::onEffectEnable(const sp<IAfEffectModule>& effect) {
if (isOffloadOrMmap()) {
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
broadcast_l();
}
if (!effect->isOffloadable()) {
@@ -1768,7 +1770,7 @@
void ThreadBase::onEffectDisable() {
if (isOffloadOrMmap()) {
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
broadcast_l();
}
}
@@ -1776,7 +1778,7 @@
sp<IAfEffectModule> ThreadBase::getEffect(audio_session_t sessionId,
int effectId) const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
return getEffect_l(sessionId, effectId);
}
@@ -1793,9 +1795,9 @@
return chain != nullptr ? chain->getEffectIds() : std::vector<int>{};
}
-// PlaybackThread::addEffect_l() must be called with AudioFlinger::mLock and
-// PlaybackThread::mLock held
-status_t ThreadBase::addEffect_l(const sp<IAfEffectModule>& effect)
+// PlaybackThread::addEffect_ll() must be called with AudioFlinger::mutex() and
+// ThreadBase::mutex() held
+status_t ThreadBase::addEffect_ll(const sp<IAfEffectModule>& effect)
{
// check for existing effect chain with the requested audio session
audio_session_t sessionId = effect->sessionId();
@@ -1803,22 +1805,22 @@
bool chainCreated = false;
ALOGD_IF((mType == OFFLOAD) && !effect->isOffloadable(),
- "addEffect_l() on offloaded thread %p: effect %s does not support offload flags %#x",
- this, effect->desc().name, effect->desc().flags);
+ "%s: on offloaded thread %p: effect %s does not support offload flags %#x",
+ __func__, this, effect->desc().name, effect->desc().flags);
if (chain == 0) {
// create a new chain for this session
- ALOGV("addEffect_l() new effect chain for session %d", sessionId);
+ ALOGV("%s: new effect chain for session %d", __func__, sessionId);
chain = IAfEffectChain::create(this, sessionId);
addEffectChain_l(chain);
chain->setStrategy(getStrategyForSession_l(sessionId));
chainCreated = true;
}
- ALOGV("addEffect_l() %p chain %p effect %p", this, chain.get(), effect.get());
+ ALOGV("%s: %p chain %p effect %p", __func__, this, chain.get(), effect.get());
if (chain->getEffectFromId_l(effect->id()) != 0) {
- ALOGW("addEffect_l() %p effect %s already present in chain %p",
- this, effect->desc().name, chain.get());
+ ALOGW("%s: %p effect %s already present in chain %p",
+ __func__, this, effect->desc().name, chain.get());
return BAD_VALUE;
}
@@ -1865,7 +1867,7 @@
{
effectChains = mEffectChains;
for (size_t i = 0; i < mEffectChains.size(); i++) {
- mEffectChains[i]->lock();
+ mEffectChains[i]->mutex().lock();
}
}
@@ -1874,13 +1876,13 @@
NO_THREAD_SAFETY_ANALYSIS // calls EffectChain::unlock()
{
for (size_t i = 0; i < effectChains.size(); i++) {
- effectChains[i]->unlock();
+ effectChains[i]->mutex().unlock();
}
}
sp<IAfEffectChain> ThreadBase::getEffectChain(audio_session_t sessionId) const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
return getEffectChain_l(sessionId);
}
@@ -1898,7 +1900,7 @@
void ThreadBase::setMode(audio_mode_t mode)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
size_t size = mEffectChains.size();
for (size_t i = 0; i < size; i++) {
mEffectChains[i]->setMode_l(mode);
@@ -1910,7 +1912,7 @@
config->type = AUDIO_PORT_TYPE_MIX;
config->ext.mix.handle = mId;
config->sample_rate = mSampleRate;
- config->format = mFormat;
+ config->format = mHALFormat;
config->channel_mask = mChannelMask;
config->config_mask = AUDIO_PORT_CONFIG_SAMPLE_RATE|AUDIO_PORT_CONFIG_CHANNEL_MASK|
AUDIO_PORT_CONFIG_FORMAT;
@@ -1918,7 +1920,7 @@
void ThreadBase::systemReady()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (mSystemReady) {
return;
}
@@ -1977,7 +1979,7 @@
}
template <typename T>
-void ThreadBase::ActiveTracks<T>::updatePowerState(
+void ThreadBase::ActiveTracks<T>::updatePowerState_l(
const sp<ThreadBase>& thread, bool force) {
// Updates ActiveTracks client uids to the thread wakelock.
if (mActiveTracksGeneration != mLastActiveTracksGeneration || force) {
@@ -2016,12 +2018,13 @@
// If threadLoop is currently unlocked a signal of mWaitWorkCV will
// be lost so we also flag to prevent it blocking on mWaitWorkCV
mSignalPending = true;
- mWaitWorkCV.broadcast();
+ mWaitWorkCV.notify_all();
}
// Call only from threadLoop() or when it is idle.
// Do not call from high performance code as this may do binder rpc to the MediaMetrics service.
void ThreadBase::sendStatistics(bool force)
+NO_THREAD_SAFETY_ANALYSIS
{
// Do not log if we have no stats.
// We choose the timestamp verifier because it is the most likely item to be present.
@@ -2053,8 +2056,8 @@
item->setInt64(MM_PREFIX "channelMask", (int64_t)mChannelMask);
item->setCString(MM_PREFIX "encoding", toString(mFormat).c_str());
item->setInt32(MM_PREFIX "frameCount", (int32_t)mFrameCount);
- item->setCString(MM_PREFIX "outDevice", toString(outDeviceTypes()).c_str());
- item->setCString(MM_PREFIX "inDevice", toString(inDeviceType()).c_str());
+ item->setCString(MM_PREFIX "outDevice", toString(outDeviceTypes_l()).c_str());
+ item->setCString(MM_PREFIX "inDevice", toString(inDeviceType_l()).c_str());
// thread statistics
if (mIoJitterMs.getN() > 0) {
@@ -2092,7 +2095,7 @@
return AudioSystem::getStrategyForStream(stream);
}
-// startMelComputation_l() must be called with AudioFlinger::mLock held
+// startMelComputation_l() must be called with AudioFlinger::mutex() held
void ThreadBase::startMelComputation_l(
const sp<audio_utils::MelProcessor>& /*processor*/)
{
@@ -2100,7 +2103,7 @@
ALOGW("%s: ThreadBase does not support CSD", __func__);
}
-// stopMelComputation_l() must be called with AudioFlinger::mLock held
+// stopMelComputation_l() must be called with AudioFlinger::mutex() held
void ThreadBase::stopMelComputation_l()
{
// Do nothing
@@ -2156,7 +2159,7 @@
snprintf(mThreadName, kThreadNameLength, "AudioOut_%X", id);
mNBLogWriter = afThreadCallback->newWriter_l(kLogSize, mThreadName);
- // Assumes constructor is called by AudioFlinger with it's mLock held, but
+ // Assumes constructor is called by AudioFlinger with its mutex() held, but
// it would be safer to explicitly pass initial masterVolume/masterMute as
// parameter.
//
@@ -2335,10 +2338,7 @@
dprintf(fd, " Total writes: %d\n", mNumWrites);
dprintf(fd, " Delayed writes: %d\n", mNumDelayedWrites);
dprintf(fd, " Blocked in write: %s\n", mInWrite ? "yes" : "no");
- dprintf(fd, " Suspend count: %d\n", mSuspended);
- dprintf(fd, " Sink buffer : %p\n", mSinkBuffer);
- dprintf(fd, " Mixer buffer: %p\n", mMixerBuffer);
- dprintf(fd, " Effect buffer: %p\n", mEffectBuffer);
+ dprintf(fd, " Suspend count: %d\n", (int32_t)mSuspended);
dprintf(fd, " Fast track availMask=%#x\n", mFastTrackAvailMask);
dprintf(fd, " Standby delay ns=%lld\n", (long long)mStandbyDelayNs);
AudioStreamOut *output = mOutput;
@@ -2356,7 +2356,7 @@
}
}
-// PlaybackThread::createTrack_l() must be called with AudioFlinger::mLock held
+// PlaybackThread::createTrack_l() must be called with AudioFlinger::mutex() held
sp<IAfTrack> PlaybackThread::createTrack_l(
const sp<Client>& client,
audio_stream_type_t streamType,
@@ -2412,6 +2412,7 @@
}
if (isBitPerfect) {
+ audio_utils::lock_guard _l(mutex());
sp<IAfEffectChain> chain = getEffectChain_l(sessionId);
if (chain.get() != nullptr) {
// Bit-perfect is required according to the configuration and preferred mixer
@@ -2461,8 +2462,8 @@
}
// check compatibility with audio effects.
- { // scope for mLock
- Mutex::Autolock _l(mLock);
+ { // scope for mutex()
+ audio_utils::lock_guard _l(mutex());
for (audio_session_t session : {
AUDIO_SESSION_DEVICE,
AUDIO_SESSION_OUTPUT_STAGE,
@@ -2668,8 +2669,8 @@
goto Exit;
}
- { // scope for mLock
- Mutex::Autolock _l(mLock);
+ { // scope for mutex()
+ audio_utils::lock_guard _l(mutex());
// all tracks in same audio session must share the same routing strategy otherwise
// conflicts will happen when tracks are moved from one output to another by audio policy
@@ -2714,7 +2715,7 @@
}
mTracks.add(track);
{
- Mutex::Autolock _atCbL(mAudioTrackCbLock);
+ audio_utils::lock_guard _atCbL(audioTrackCbMutex());
if (callback.get() != nullptr) {
mAudioTrackCallbacks.emplace(track, callback);
}
@@ -2766,10 +2767,12 @@
uint32_t PlaybackThread::latency() const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
return latency_l();
}
uint32_t PlaybackThread::latency_l() const
+NO_THREAD_SAFETY_ANALYSIS
+// Fix later.
{
uint32_t latency;
if (initCheck() == NO_ERROR && mOutput->stream->getLatency(&latency) == OK) {
@@ -2780,7 +2783,7 @@
void PlaybackThread::setMasterVolume(float value)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
// Don't apply master volume in SW if our HAL can do it for us.
if (mOutput && mOutput->audioHwDev &&
mOutput->audioHwDev->canSetMasterVolume()) {
@@ -2800,7 +2803,7 @@
if (isDuplicating()) {
return;
}
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
// Don't apply master mute in SW if our HAL can do it for us.
if (mOutput && mOutput->audioHwDev &&
mOutput->audioHwDev->canSetMasterMute()) {
@@ -2812,21 +2815,21 @@
void PlaybackThread::setStreamVolume(audio_stream_type_t stream, float value)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
mStreamTypes[stream].volume = value;
broadcast_l();
}
void PlaybackThread::setStreamMute(audio_stream_type_t stream, bool muted)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
mStreamTypes[stream].mute = muted;
broadcast_l();
}
float PlaybackThread::streamVolume(audio_stream_type_t stream) const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
return mStreamTypes[stream].volume;
}
@@ -2835,9 +2838,8 @@
mOutput->stream->setVolume(left, right);
}
-// addTrack_l() must be called with ThreadBase::mLock held
+// addTrack_l() must be called with ThreadBase::mutex() held
status_t PlaybackThread::addTrack_l(const sp<IAfTrack>& track)
-NO_THREAD_SAFETY_ANALYSIS // release and re-acquire mLock
{
status_t status = ALREADY_EXISTS;
@@ -2847,15 +2849,15 @@
// effectively get the latency it requested.
if (track->isExternalTrack()) {
IAfTrackBase::track_state state = track->state();
- mLock.unlock();
+ mutex().unlock();
status = AudioSystem::startOutput(track->portId());
- mLock.lock();
+ mutex().lock();
// abort track was stopped/paused while we released the lock
if (state != track->state()) {
if (status == NO_ERROR) {
- mLock.unlock();
+ mutex().unlock();
AudioSystem::stopOutput(track->portId());
- mLock.lock();
+ mutex().lock();
}
return INVALID_OPERATION;
}
@@ -2894,17 +2896,17 @@
|| (chain != nullptr && chain->containsHapticGeneratingEffect_l()))) {
// Unlock due to VibratorService will lock for this call and will
// call Tracks.mute/unmute which also require thread's lock.
- mLock.unlock();
+ mutex().unlock();
const os::HapticScale intensity = afutils::onExternalVibrationStart(
track->getExternalVibration());
std::optional<media::AudioVibratorInfo> vibratorInfo;
{
// TODO(b/184194780): Use the vibrator information from the vibrator that will be
// used to play this track.
- Mutex::Autolock _l(mAfThreadCallback->mutex());
+ audio_utils::lock_guard _l(mAfThreadCallback->mutex());
vibratorInfo = std::move(mAfThreadCallback->getDefaultVibratorInfo_l());
}
- mLock.lock();
+ mutex().lock();
track->setHapticIntensity(intensity);
if (vibratorInfo) {
track->setHapticMaxAmplitude(vibratorInfo->maxAmplitude);
@@ -2970,7 +2972,7 @@
mTracks.remove(track);
{
- Mutex::Autolock _atCbL(mAudioTrackCbLock);
+ audio_utils::lock_guard _atCbL(audioTrackCbMutex());
mAudioTrackCallbacks.erase(track);
}
if (track->isFastTrack()) {
@@ -2989,7 +2991,7 @@
String8 PlaybackThread::getParameters(const String8& keys)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
String8 out_s8;
if (initCheck() == NO_ERROR && mOutput->stream->getParameters(keys, &out_s8) == OK) {
return out_s8;
@@ -2998,14 +3000,14 @@
}
status_t DirectOutputThread::selectPresentation(int presentationId, int programId) {
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (!isStreamInitialized()) {
return NO_INIT;
}
return mOutput->stream->selectPresentation(presentationId, programId);
}
-void PlaybackThread::ioConfigChanged(audio_io_config_event_t event, pid_t pid,
+void PlaybackThread::ioConfigChanged_l(audio_io_config_event_t event, pid_t pid,
audio_port_handle_t portId) {
ALOGV("PlaybackThread::ioConfigChanged, thread %p, event %d", this, event);
sp<AudioIoDescriptor> desc;
@@ -3027,7 +3029,7 @@
desc = sp<AudioIoDescriptor>::make(mId);
break;
}
- mAfThreadCallback->ioConfigChanged(event, desc, pid);
+ mAfThreadCallback->ioConfigChanged_l(event, desc, pid);
}
void PlaybackThread::onWriteReady()
@@ -3068,7 +3070,7 @@
audio_utils::metadata::ByteString metaDataStr =
audio_utils::metadata::byteStringFromData(metadata);
std::vector metadataVec(metaDataStr.begin(), metaDataStr.end());
- Mutex::Autolock _l(mAudioTrackCbLock);
+ audio_utils::lock_guard _l(audioTrackCbMutex());
for (const auto& callbackPair : mAudioTrackCallbacks) {
callbackPair.second->onCodecFormatChanged(metadataVec);
}
@@ -3077,17 +3079,17 @@
void PlaybackThread::resetWriteBlocked(uint32_t sequence)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
// reject out of sequence requests
if ((mWriteAckSequence & 1) && (sequence == mWriteAckSequence)) {
mWriteAckSequence &= ~1;
- mWaitWorkCV.signal();
+ mWaitWorkCV.notify_one();
}
}
void PlaybackThread::resetDraining(uint32_t sequence)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
// reject out of sequence requests
if ((mDrainSequence & 1) && (sequence == mDrainSequence)) {
// Register discontinuity when HW drain is completed because that can cause
@@ -3096,11 +3098,13 @@
// elsewhere, e.g. in flush).
mTimestampVerifier.discontinuity(mTimestampVerifier.DISCONTINUITY_MODE_ZERO);
mDrainSequence &= ~1;
- mWaitWorkCV.signal();
+ mWaitWorkCV.notify_one();
}
}
void PlaybackThread::readOutputParameters_l()
+NO_THREAD_SAFETY_ANALYSIS
+// 'moveEffectChain_ll' requires holding mutex 'AudioFlinger_Mutex' exclusively
{
// unfortunately we have no way of recovering from errors here, hence the LOG_ALWAYS_FATAL
const audio_config_base_t audioConfig = mOutput->getAudioProperties();
@@ -3211,8 +3215,8 @@
if (hasMixer()) {
mNormalFrameCount = (mNormalFrameCount + 15) & ~15;
}
- ALOGI("HAL output buffer size %zu frames, normal sink buffer size %zu frames", mFrameCount,
- mNormalFrameCount);
+ ALOGI("HAL output buffer size %zu frames, normal sink buffer size %zu frames",
+ (size_t)mFrameCount, mNormalFrameCount);
// Check if we want to throttle the processing to no more than 2x normal rate
mThreadThrottle = property_get_bool("af.thread.throttle", true /* default_value */);
@@ -3265,13 +3269,14 @@
// force reconfiguration of effect chains and engines to take new buffer size and audio
// parameters into account
- // Note that mLock is not held when readOutputParameters_l() is called from the constructor
+ // Note that mutex() is not held when readOutputParameters_l() is called from the constructor
// but in this case nothing is done below as no audio sessions have effect yet so it doesn't
// matter.
- // create a copy of mEffectChains as calling moveEffectChain_l() can reorder some effect chains
+ // create a copy of mEffectChains as calling moveEffectChain_ll()
+ // can reorder some effect chains
Vector<sp<IAfEffectChain>> effectChains = mEffectChains;
for (size_t i = 0; i < effectChains.size(); i ++) {
- mAfThreadCallback->moveEffectChain_l(effectChains[i]->sessionId(),
+ mAfThreadCallback->moveEffectChain_ll(effectChains[i]->sessionId(),
this/* srcThread */, this/* dstThread */);
}
@@ -3329,7 +3334,7 @@
if (halFrames == NULL || dspFrames == NULL) {
return BAD_VALUE;
}
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (initCheck() != NO_ERROR) {
return INVALID_OPERATION;
}
@@ -3370,13 +3375,13 @@
AudioStreamOut* PlaybackThread::getOutput() const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
return mOutput;
}
AudioStreamOut* PlaybackThread::clearOutput()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
AudioStreamOut *output = mOutput;
mOutput = NULL;
// FIXME FastMixer might also have a raw ptr to mOutputSink;
@@ -3387,7 +3392,7 @@
return output;
}
-// this method must always be called either with ThreadBase mLock held or inside the thread loop
+// this method must always be called either with ThreadBase mutex() held or inside the thread loop
sp<StreamHalInterface> PlaybackThread::stream() const
{
if (mOutput == NULL) {
@@ -3407,7 +3412,7 @@
return BAD_VALUE;
}
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
for (size_t i = 0; i < mTracks.size(); ++i) {
sp<IAfTrack> track = mTracks[i];
@@ -3448,7 +3453,7 @@
ALOGD("ro.audio.silent is ignored since no output device is set");
return;
}
- if (isSingleDeviceType(outDeviceTypes(), AUDIO_DEVICE_OUT_REMOTE_SUBMIX)) {
+ if (isSingleDeviceType(outDeviceTypes_l(), AUDIO_DEVICE_OUT_REMOTE_SUBMIX)) {
ALOGD("ro.audio.silent will be ignored for threads on AUDIO_DEVICE_OUT_REMOTE_SUBMIX");
return;
}
@@ -3537,7 +3542,7 @@
return bytesWritten;
}
-// startMelComputation_l() must be called with AudioFlinger::mLock held
+// startMelComputation_l() must be called with AudioFlinger::mutex() held
void PlaybackThread::startMelComputation_l(
const sp<audio_utils::MelProcessor>& processor)
{
@@ -3547,7 +3552,7 @@
}
}
-// stopMelComputation_l() must be called with AudioFlinger::mLock held
+// stopMelComputation_l() must be called with AudioFlinger::mutex() held
void PlaybackThread::stopMelComputation_l()
{
auto outputSink = static_cast<AudioStreamOutSink*>(mOutputSink.get());
@@ -3575,7 +3580,7 @@
void PlaybackThread::threadLoop_exit()
{
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
for (size_t i = 0; i < mTracks.size(); i++) {
sp<IAfTrack> track = mTracks[i];
track->invalidate();
@@ -3618,7 +3623,7 @@
// make sure standby delay is not too short when connected to an A2DP sink to avoid
// truncating audio when going to standby.
- if (!Intersection(outDeviceTypes(), getAudioDeviceOutAllA2dpSet()).empty()) {
+ if (!Intersection(outDeviceTypes_l(), getAudioDeviceOutAllA2dpSet()).empty()) {
if (mStandbyDelayNs < kDefaultStandbyTimeInNsecs) {
mStandbyDelayNs = kDefaultStandbyTimeInNsecs;
}
@@ -3643,12 +3648,12 @@
void PlaybackThread::invalidateTracks(audio_stream_type_t streamType)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
invalidateTracks_l(streamType);
}
void PlaybackThread::invalidateTracks(std::set<audio_port_handle_t>& portIds) {
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
invalidateTracks_l(portIds);
}
@@ -3852,7 +3857,7 @@
status_t PlaybackThread::attachAuxEffect(
const sp<IAfTrack>& track, int EffectId)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
return attachAuxEffect_l(track, EffectId);
}
@@ -3953,11 +3958,11 @@
// If the device is AUDIO_DEVICE_OUT_BUS, check for downstream latency.
//
- // Note: we access outDeviceTypes() outside of mLock.
- if (isMsdDevice() && outDeviceTypes().count(AUDIO_DEVICE_OUT_BUS) != 0) {
+ // Note: we access outDeviceTypes() outside of mutex().
+ if (isMsdDevice() && outDeviceTypes_l().count(AUDIO_DEVICE_OUT_BUS) != 0) {
// Here, we try for the AF lock, but do not block on it as the latency
// is more informational.
- if (mAfThreadCallback->mutex().tryLock() == NO_ERROR) {
+ if (mAfThreadCallback->mutex().try_lock()) {
std::vector<SoftwarePatch> swPatches;
double latencyMs = 0.; // not required; initialized for clang-tidy
status_t status = INVALID_OPERATION;
@@ -3999,16 +4004,16 @@
}
MetadataUpdate metadataUpdate;
- { // scope for mLock
+ { // scope for mutex()
- Mutex::Autolock _l(mLock);
+ audio_utils::unique_lock _l(mutex());
processConfigEvents_l();
if (mCheckOutputStageEffects.load()) {
continue;
}
- // See comment at declaration of logString for why this is done under mLock
+ // See comment at declaration of logString for why this is done under mutex()
if (logString != NULL) {
mNBLogWriter->logTimestamp();
mNBLogWriter->log(logString);
@@ -4033,8 +4038,9 @@
const int64_t waitNs = computeWaitTimeNs_l();
ALOGV("wait async completion (wait time: %lld)", (long long)waitNs);
- status_t status = mWaitWorkCV.waitRelative(mLock, waitNs);
- if (status == TIMED_OUT) {
+ std::cv_status cvstatus =
+ mWaitWorkCV.wait_for(_l, std::chrono::nanoseconds(waitNs));
+ if (cvstatus == std::cv_status::timeout) {
mSignalPending = true; // if timeout recheck everything
}
ALOGV("async completion/wake");
@@ -4076,7 +4082,7 @@
releaseWakeLock_l();
// wait until we have something to do...
ALOGV("%s going to sleep", myName.c_str());
- mWaitWorkCV.wait(mLock);
+ mWaitWorkCV.wait(_l);
ALOGV("%s waking up", myName.c_str());
acquireWakeLock_l();
@@ -4098,7 +4104,7 @@
// mMixerStatusIgnoringFastTracks is also updated internally
mMixerStatus = prepareTracks_l(&tracksToRemove);
- mActiveTracks.updatePowerState(this);
+ mActiveTracks.updatePowerState_l(this);
metadataUpdate = updateMetadata_l();
@@ -4149,9 +4155,9 @@
&& (mKernelPositionOnStandby
!= mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL])))) {
mHalStarted = true;
- mWaitHalStartCV.broadcast();
+ mWaitHalStartCV.notify_all();
}
- } // mLock scope ends
+ } // mutex() scope ends
if (mBytesRemaining == 0) {
mCurrentWriteLength = 0;
@@ -4382,7 +4388,7 @@
const double processMs =
(lastIoBeginNs - mLastIoEndNs) * 1e-6;
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
mIoJitterMs.add(jitterMs);
mProcessTimeMs.add(processMs);
@@ -4471,9 +4477,10 @@
// notify of throttle end on debug log
// but prevent spamming for bluetooth
ALOGD_IF(!isSingleDeviceType(
- outDeviceTypes(), audio_is_a2dp_out_device) &&
+ outDeviceTypes_l(), audio_is_a2dp_out_device) &&
!isSingleDeviceType(
- outDeviceTypes(), audio_is_hearing_aid_out_device),
+ outDeviceTypes_l(),
+ audio_is_hearing_aid_out_device),
"mixer(%p) throttle end: throttle time(%u)", this, diff);
mThreadThrottleEndMs = mThreadThrottleTimeMs;
}
@@ -4483,7 +4490,7 @@
} else {
ATRACE_BEGIN("sleep");
- Mutex::Autolock _l(mLock);
+ audio_utils::unique_lock _l(mutex());
// suspended requires accurate metering of sleep time.
if (isSuspended()) {
// advance by expected sleepTime
@@ -4508,7 +4515,7 @@
mSleepTimeUs = deltaNs / 1000;
}
if (!mSignalPending && mConfigEvents.isEmpty() && !exitPending()) {
- mWaitWorkCV.waitRelative(mLock, microseconds((nsecs_t)mSleepTimeUs));
+ mWaitWorkCV.wait_for(_l, std::chrono::microseconds(mSleepTimeUs));
}
ATRACE_END();
}
@@ -4569,7 +4576,7 @@
timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL],
mSampleRate);
- if (isTimestampCorrectionEnabled()) {
+ if (isTimestampCorrectionEnabled_l()) {
ALOGVV("TS_BEFORE: %d %lld %lld", id(),
(long long)timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL],
(long long)timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL]);
@@ -4648,7 +4655,7 @@
// and we use systemTime().
mTimestamp.mPosition[ExtendedTimestamp::LOCATION_SERVER] = mFramesWritten;
mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_SERVER] = mLastIoBeginNs == -1
- ? systemTime() : mLastIoBeginNs;
+ ? systemTime() : (int64_t)mLastIoBeginNs;
}
for (const sp<IAfTrack>& t : mActiveTracks) {
@@ -4681,9 +4688,9 @@
#endif
}
-// removeTracks_l() must be called with ThreadBase::mLock held
+// removeTracks_l() must be called with ThreadBase::mutex() held
void PlaybackThread::removeTracks_l(const Vector<sp<IAfTrack>>& tracksToRemove)
-NO_THREAD_SAFETY_ANALYSIS // release and re-acquire mLock
+NO_THREAD_SAFETY_ANALYSIS // release and re-acquire mutex()
{
for (const auto& track : tracksToRemove) {
mActiveTracks.remove(track);
@@ -4709,11 +4716,11 @@
if (mHapticChannelCount > 0 &&
((track->channelMask() & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE
|| (chain != nullptr && chain->containsHapticGeneratingEffect_l()))) {
- mLock.unlock();
+ mutex().unlock();
// Unlock due to VibratorService will lock for this call and will
// call Tracks.mute/unmute which also require thread's lock.
afutils::onExternalVibrationStop(track->getExternalVibration());
- mLock.lock();
+ mutex().lock();
// When the track is stop, set the haptic intensity as MUTE
// for the HapticGenerator effect.
@@ -4911,13 +4918,13 @@
void PlaybackThread::addPatchTrack(const sp<IAfPatchTrack>& track)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
mTracks.add(track);
}
void PlaybackThread::deletePatchTrack(const sp<IAfPatchTrack>& track)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
destroyTrack_l(track);
}
@@ -5167,7 +5174,7 @@
void MixerThread::onFirstRef() {
PlaybackThread::onFirstRef();
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (mOutput != nullptr && mOutput->stream != nullptr) {
status_t status = mOutput->stream->setLatencyModeCallback(this);
if (status != INVALID_OPERATION) {
@@ -5282,14 +5289,15 @@
bool PlaybackThread::waitingAsyncCallback()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
return waitingAsyncCallback_l();
}
// shared by MIXER and DIRECT, overridden by DUPLICATING
void PlaybackThread::threadLoop_standby()
{
- ALOGV("Audio hardware entering standby, mixer %p, suspend count %d", this, mSuspended);
+ ALOGV("%s: audio hardware entering standby, mixer %p, suspend count %d",
+ __func__, this, (int32_t)mSuspended);
mOutput->standby();
if (mUseAsyncWrite != 0) {
// discard any pending drain or write ack by incrementing sequence
@@ -5387,7 +5395,7 @@
// TODO add standby time extension fct of effect tail
}
-// prepareTracks_l() must be called with ThreadBase::mLock held
+// prepareTracks_l() must be called with ThreadBase::mutex() held
PlaybackThread::mixer_state MixerThread::prepareTracks_l(
Vector<sp<IAfTrack>>* tracksToRemove)
{
@@ -6183,7 +6191,7 @@
return mixerStatus;
}
-// trackCountForUid_l() must be called with ThreadBase::mLock held
+// trackCountForUid_l() must be called with ThreadBase::mutex() held
uint32_t PlaybackThread::trackCountForUid_l(uid_t uid) const
{
uint32_t trackCount = 0;
@@ -6226,7 +6234,7 @@
mPreviousNs = 0;
}
-// isTrackAllowed_l() must be called with ThreadBase::mLock held
+// isTrackAllowed_l() must be called with ThreadBase::mutex() held
bool MixerThread::isTrackAllowed_l(
audio_channel_mask_t channelMask, audio_format_t format,
audio_session_t sessionId, uid_t uid) const
@@ -6246,7 +6254,7 @@
return true;
}
-// checkForNewParameter_l() must be called with ThreadBase::mLock held
+// checkForNewParameter_l() must be called with ThreadBase::mutex() held
bool MixerThread::checkForNewParameter_l(const String8& keyValuePair,
status_t& status)
{
@@ -6330,7 +6338,7 @@
void MixerThread::dumpInternals_l(int fd, const Vector<String16>& args)
{
PlaybackThread::dumpInternals_l(fd, args);
- dprintf(fd, " Thread throttle time (msecs): %u\n", mThreadThrottleTimeMs);
+ dprintf(fd, " Thread throttle time (msecs): %u\n", (uint32_t)mThreadThrottleTimeMs);
dprintf(fd, " AudioMixer tracks: %s\n", mAudioMixer->trackNames().c_str());
dprintf(fd, " Master mono: %s\n", mMasterMono ? "on" : "off");
dprintf(fd, " Master balance: %f (%s)\n", mMasterBalance.load(),
@@ -6464,14 +6472,14 @@
if (modes == nullptr) {
return BAD_VALUE;
}
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
*modes = mSupportedLatencyModes;
return NO_ERROR;
}
void MixerThread::onRecommendedLatencyModeChanged(
std::vector<audio_latency_mode_t> modes) {
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (modes != mSupportedLatencyModes) {
ALOGD("%s: thread(%d) supported latency modes: %s",
__func__, mId, toString(modes).c_str());
@@ -6522,7 +6530,7 @@
void DirectOutputThread::setMasterBalance(float balance)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (mMasterBalance != balance) {
mMasterBalance.store(balance);
mBalance.computeStereoBalance(balance, &mMasterBalanceLeft, &mMasterBalanceRight);
@@ -6537,12 +6545,11 @@
// Ensure volumeshaper state always advances even when muted.
const sp<AudioTrackServerProxy> proxy = track->audioTrackServerProxy();
- const size_t framesReleased = proxy->framesReleased();
const int64_t frames = mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL];
const int64_t time = mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL];
- ALOGV("%s: Direct/Offload bufferConsumed:%zu timestamp frames:%lld time:%lld",
- __func__, framesReleased, (long long)frames, (long long)time);
+ ALOGVV("%s: Direct/Offload bufferConsumed:%zu timestamp frames:%lld time:%lld",
+ __func__, proxy->framesReleased(), (long long)frames, (long long)time);
const int64_t volumeShaperFrames =
mMonotonicFrameCounter.updateAndGetMonotonicFrameCount(frames, time);
@@ -6903,7 +6910,7 @@
void DirectOutputThread::threadLoop_exit()
{
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
for (size_t i = 0; i < mTracks.size(); i++) {
if (mTracks[i]->isFlushPending()) {
mTracks[i]->flushAck();
@@ -6934,7 +6941,7 @@
return !mStandby && !(trackPaused || (mHwPaused && !trackStopped));
}
-// checkForNewParameter_l() must be called with ThreadBase::mLock held
+// checkForNewParameter_l() must be called with ThreadBase::mutex() held
bool DirectOutputThread::checkForNewParameter_l(const String8& keyValuePair,
status_t& status)
{
@@ -7069,12 +7076,12 @@
bool asyncError;
{
- Mutex::Autolock _l(mLock);
+ audio_utils::unique_lock _l(mutex());
while (!((mWriteAckSequence & 1) ||
(mDrainSequence & 1) ||
mAsyncError ||
exitPending())) {
- mWaitWorkCV.wait(mLock);
+ mWaitWorkCV.wait(_l);
}
if (exitPending()) {
@@ -7110,50 +7117,50 @@
void AsyncCallbackThread::exit()
{
ALOGV("AsyncCallbackThread::exit");
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
requestExit();
- mWaitWorkCV.broadcast();
+ mWaitWorkCV.notify_all();
}
void AsyncCallbackThread::setWriteBlocked(uint32_t sequence)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
// bit 0 is cleared
mWriteAckSequence = sequence << 1;
}
void AsyncCallbackThread::resetWriteBlocked()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
// ignore unexpected callbacks
if (mWriteAckSequence & 2) {
mWriteAckSequence |= 1;
- mWaitWorkCV.signal();
+ mWaitWorkCV.notify_one();
}
}
void AsyncCallbackThread::setDraining(uint32_t sequence)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
// bit 0 is cleared
mDrainSequence = sequence << 1;
}
void AsyncCallbackThread::resetDraining()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
// ignore unexpected callbacks
if (mDrainSequence & 2) {
mDrainSequence |= 1;
- mWaitWorkCV.signal();
+ mWaitWorkCV.notify_one();
}
}
void AsyncCallbackThread::setAsyncError()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
mAsyncError = true;
- mWaitWorkCV.signal();
+ mWaitWorkCV.notify_one();
}
@@ -7182,6 +7189,7 @@
{
if (mFlushPending || mHwPaused) {
// If a flush is pending or track was paused, just discard buffered data
+ audio_utils::lock_guard l(mutex());
flushHw_l();
} else {
mMixerStatus = MIXER_DRAIN_ALL;
@@ -7449,7 +7457,7 @@
bool OffloadThread::waitingAsyncCallback()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
return waitingAsyncCallback_l();
}
@@ -7476,14 +7484,14 @@
void OffloadThread::invalidateTracks(audio_stream_type_t streamType)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (PlaybackThread::invalidateTracks_l(streamType)) {
mFlushPending = true;
}
}
void OffloadThread::invalidateTracks(std::set<audio_port_handle_t>& portIds) {
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (PlaybackThread::invalidateTracks_l(portIds)) {
mFlushPending = true;
}
@@ -7625,7 +7633,7 @@
void DuplicatingThread::addOutputTrack(IAfPlaybackThread* thread)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
// The downstream MixerThread consumes thread->frameCount() amount of frames per mix pass.
// Adjust for thread->sampleRate() to determine minimum buffer frame count.
// Then triple buffer because Threads do not run synchronously and may not be clock locked.
@@ -7662,14 +7670,19 @@
void DuplicatingThread::removeOutputTrack(IAfPlaybackThread* thread)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
for (size_t i = 0; i < mOutputTracks.size(); i++) {
if (mOutputTracks[i]->thread() == thread) {
mOutputTracks[i]->destroy();
mOutputTracks.removeAt(i);
updateWaitTime_l();
- if (thread->getOutput() == mOutput) {
- mOutput = NULL;
+ // NO_THREAD_SAFETY_ANALYSIS
+ // Lambda workaround: as thread != this
+ // we can safely call the remote thread getOutput.
+ const bool equalOutput =
+ [&](){ return thread->getOutput() == mOutput; }();
+ if (equalOutput) {
+ mOutput = nullptr;
}
return;
}
@@ -7677,7 +7690,7 @@
ALOGV("removeOutputTrack(): unknown thread: %p", thread);
}
-// caller must hold mLock
+// caller must hold mutex()
void DuplicatingThread::updateWaitTime_l()
{
mWaitTimeMs = UINT_MAX;
@@ -7811,18 +7824,20 @@
if (mode != AUDIO_LATENCY_MODE_LOW && mode != AUDIO_LATENCY_MODE_FREE) {
return BAD_VALUE;
}
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
mRequestedLatencyMode = mode;
return NO_ERROR;
}
void SpatializerThread::checkOutputStageEffects()
+NO_THREAD_SAFETY_ANALYSIS
+// 'createEffect_l' requires holding mutex 'AudioFlinger_Mutex' exclusively
{
bool hasVirtualizer = false;
bool hasDownMixer = false;
sp<IAfEffectHandle> finalDownMixer;
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
sp<IAfEffectChain> chain = getEffectChain_l(AUDIO_SESSION_OUTPUT_STAGE);
if (chain != 0) {
hasVirtualizer = chain->getEffectFromType_l(FX_IID_SPATIALIZER) != nullptr;
@@ -7863,7 +7878,7 @@
}
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
mFinalDownMixer = finalDownMixer;
}
}
@@ -8069,13 +8084,13 @@
void RecordThread::preExit()
{
ALOGV(" preExit()");
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
for (size_t i = 0; i < mTracks.size(); i++) {
sp<IAfRecordTrack> track = mTracks[i];
track->invalidate();
}
mActiveTracks.clear();
- mStartStopCond.broadcast();
+ mStartStopCV.notify_all();
}
bool RecordThread::threadLoop()
@@ -8087,7 +8102,7 @@
reacquire_wakelock:
sp<IAfRecordTrack> activeTrack;
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
acquireWakeLock_l();
}
@@ -8111,13 +8126,13 @@
bool silenceFastCapture = false;
- { // scope for mLock
- Mutex::Autolock _l(mLock);
+ { // scope for mutex()
+ audio_utils::unique_lock _l(mutex());
processConfigEvents_l();
// check exitPending here because checkForNewParameters_l() and
- // checkForNewParameters_l() can temporarily release mLock
+ // checkForNewParameters_l() can temporarily release mutex()
if (exitPending()) {
break;
}
@@ -8125,7 +8140,7 @@
// sleep with mutex unlocked
if (sleepUs > 0) {
ATRACE_BEGIN("sleepC");
- mWaitWorkCV.waitRelative(mLock, microseconds((nsecs_t)sleepUs));
+ (void)mWaitWorkCV.wait_for(_l, std::chrono::microseconds(sleepUs));
ATRACE_END();
sleepUs = 0;
continue;
@@ -8139,7 +8154,7 @@
releaseWakeLock_l();
ALOGV("RecordThread: loop stopping");
// go to sleep
- mWaitWorkCV.wait(mLock);
+ mWaitWorkCV.wait(_l);
ALOGV("RecordThread: loop starting");
goto reacquire_wakelock;
}
@@ -8238,7 +8253,7 @@
}
- mActiveTracks.updatePowerState(this);
+ mActiveTracks.updatePowerState_l(this);
updateMetadata_l();
@@ -8246,7 +8261,7 @@
standbyIfNotAlreadyInStandby();
}
if (doBroadcast) {
- mStartStopCond.broadcast();
+ mStartStopCV.notify_all();
}
// sleep if there are no active tracks to process
@@ -8416,7 +8431,12 @@
mTimestampVerifier.add(position, time, mSampleRate);
// Correct timestamps
- if (isTimestampCorrectionEnabled()) {
+ bool timestampCorrectionEnabled = false;
+ {
+ audio_utils::lock_guard l(mutex());
+ timestampCorrectionEnabled = isTimestampCorrectionEnabled_l();
+ }
+ if (timestampCorrectionEnabled) {
ALOGVV("TS_BEFORE: %d %lld %lld",
id(), (long long)time, (long long)position);
auto correctedTimestamp = mTimestampVerifier.getLastCorrectedTimestamp();
@@ -8615,7 +8635,7 @@
{0, 0} /* lastTimestamp */, mSampleRate);
const double processMs = (lastIoBeginNs - mLastIoEndNs) * 1e-6;
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
mIoJitterMs.add(jitterMs);
mProcessTimeMs.add(processMs);
}
@@ -8628,13 +8648,13 @@
standbyIfNotAlreadyInStandby();
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
for (size_t i = 0; i < mTracks.size(); i++) {
sp<IAfRecordTrack> track = mTracks[i];
track->invalidate();
}
mActiveTracks.clear();
- mStartStopCond.broadcast();
+ mStartStopCV.notify_all();
}
releaseWakeLock();
@@ -8693,7 +8713,7 @@
}
}
-// RecordThread::createRecordTrack_l() must be called with AudioFlinger::mLock held
+// RecordThread::createRecordTrack_l() must be called with AudioFlinger::mutex() held
sp<IAfRecordTrack> RecordThread::createRecordTrack_l(
const sp<Client>& client,
const audio_attributes_t& attr,
@@ -8785,7 +8805,7 @@
mFastTrackAvail
) {
// check compatibility with audio effects.
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
// Do not accept FAST flag if the session has software effects
sp<IAfEffectChain> chain = getEffectChain_l(sessionId);
if (chain != 0) {
@@ -8849,8 +8869,8 @@
*pFrameCount = frameCount;
*pNotificationFrameCount = notificationFrameCount;
- { // scope for mLock
- Mutex::Autolock _l(mLock);
+ { // scope for mutex()
+ audio_utils::lock_guard _l(mutex());
int32_t startFrames = -1;
if (!mSharedAudioPackageName.empty()
&& mSharedAudioPackageName == attributionSource.packageName
@@ -8911,7 +8931,7 @@
{
// This section is a rendezvous between binder thread executing start() and RecordThread
- AutoMutex lock(mLock);
+ audio_utils::lock_guard lock(mutex());
if (recordTrack->isInvalid()) {
recordTrack->clearSyncStartEvent();
ALOGW("%s track %d: invalidated before startInput", __func__, recordTrack->portId());
@@ -8935,9 +8955,9 @@
recordTrack->setState(IAfTrackBase::STARTING_1);
mActiveTracks.add(recordTrack);
if (recordTrack->isExternalTrack()) {
- mLock.unlock();
+ mutex().unlock();
status = AudioSystem::startInput(recordTrack->portId());
- mLock.lock();
+ mutex().lock();
if (recordTrack->isInvalid()) {
recordTrack->clearSyncStartEvent();
if (status == NO_ERROR && recordTrack->state() == IAfTrackBase::STARTING_1) {
@@ -8983,7 +9003,7 @@
}
recordTrack->setState(IAfTrackBase::STARTING_2);
// signal thread to start
- mWaitWorkCV.broadcast();
+ mWaitWorkCV.notify_all();
return status;
}
}
@@ -9004,7 +9024,7 @@
bool RecordThread::stop(IAfRecordTrack* recordTrack) {
ALOGV("RecordThread::stop");
- AutoMutex _l(mLock);
+ audio_utils::unique_lock _l(mutex());
// if we're invalid, we can't be on the ActiveTracks.
if (mActiveTracks.indexOf(recordTrack) < 0 || recordTrack->state() == IAfTrackBase::PAUSING) {
return false;
@@ -9015,8 +9035,8 @@
// NOTE: Waiting here is important to keep stop synchronous.
// This is needed for proper patchRecord peer release.
while (recordTrack->state() == IAfTrackBase::PAUSING && !recordTrack->isInvalid()) {
- mWaitWorkCV.broadcast(); // signal thread to stop
- mStartStopCond.wait(mLock);
+ mWaitWorkCV.notify_all(); // signal thread to stop
+ mStartStopCV.wait(_l);
}
if (recordTrack->state() == IAfTrackBase::PAUSED) { // successful stop
@@ -9045,7 +9065,7 @@
audio_session_t eventSession = event->triggerSession();
status_t ret = NAME_NOT_FOUND;
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
for (size_t i = 0; i < mTracks.size(); i++) {
sp<IAfRecordTrack> track = mTracks[i];
@@ -9064,7 +9084,7 @@
std::vector<media::MicrophoneInfoFw>* activeMicrophones) const
{
ALOGV("RecordThread::getActiveMicrophones");
- AutoMutex _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (!isStreamInitialized()) {
return NO_INIT;
}
@@ -9076,7 +9096,7 @@
audio_microphone_direction_t direction)
{
ALOGV("setPreferredMicrophoneDirection(%d)", direction);
- AutoMutex _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (!isStreamInitialized()) {
return NO_INIT;
}
@@ -9086,7 +9106,7 @@
status_t RecordThread::setPreferredMicrophoneFieldDimension(float zoom)
{
ALOGV("setPreferredMicrophoneFieldDimension(%f)", zoom);
- AutoMutex _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (!isStreamInitialized()) {
return NO_INIT;
}
@@ -9096,7 +9116,7 @@
status_t RecordThread::shareAudioHistory(
const std::string& sharedAudioPackageName, audio_session_t sharedSessionId,
int64_t sharedAudioStartMs) {
- AutoMutex _l(mLock);
+ audio_utils::lock_guard _l(mutex());
return shareAudioHistory_l(sharedAudioPackageName, sharedSessionId, sharedAudioStartMs);
}
@@ -9162,7 +9182,7 @@
return change;
}
-// destroyTrack_l() must be called with ThreadBase::mLock held
+// destroyTrack_l() must be called with ThreadBase::mutex() held
void RecordThread::destroyTrack_l(const sp<IAfRecordTrack>& track)
{
track->terminate();
@@ -9262,7 +9282,7 @@
void RecordThread::setRecordSilenced(audio_port_handle_t portId, bool silenced)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
for (size_t i = 0; i < mTracks.size() ; i++) {
sp<IAfRecordTrack> track = mTracks[i];
if (track != 0 && track->portId() == portId) {
@@ -9387,7 +9407,7 @@
void RecordThread::checkBtNrec()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
checkBtNrec_l();
}
@@ -9395,7 +9415,7 @@
{
// disable AEC and NS if the device is a BT SCO headset supporting those
// pre processings
- bool suspend = audio_is_bluetooth_sco_device(inDeviceType()) &&
+ bool suspend = audio_is_bluetooth_sco_device(inDeviceType_l()) &&
mAfThreadCallback->btNrecIsOff();
if (mBtNrecSuspended.exchange(suspend) != suspend) {
for (size_t i = 0; i < mEffectChains.size(); i++) {
@@ -9496,7 +9516,7 @@
String8 RecordThread::getParameters(const String8& keys)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (initCheck() == NO_ERROR) {
String8 out_s8;
if (mInput->stream->getParameters(keys, &out_s8) == OK) {
@@ -9506,7 +9526,7 @@
return {};
}
-void RecordThread::ioConfigChanged(audio_io_config_event_t event, pid_t pid,
+void RecordThread::ioConfigChanged_l(audio_io_config_event_t event, pid_t pid,
audio_port_handle_t portId) {
sp<AudioIoDescriptor> desc;
switch (event) {
@@ -9524,7 +9544,7 @@
desc = sp<AudioIoDescriptor>::make(mId);
break;
}
- mAfThreadCallback->ioConfigChanged(event, desc, pid);
+ mAfThreadCallback->ioConfigChanged_l(event, desc, pid);
}
void RecordThread::readInputParameters_l()
@@ -9572,7 +9592,7 @@
uint32_t RecordThread::getInputFramesLost() const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
uint32_t result;
if (initCheck() == NO_ERROR && mInput->stream->getInputFramesLost(&result) == OK) {
return result;
@@ -9583,7 +9603,7 @@
KeyedVector<audio_session_t, bool> RecordThread::sessionIds() const
{
KeyedVector<audio_session_t, bool> ids;
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
for (size_t j = 0; j < mTracks.size(); ++j) {
sp<IAfRecordTrack> track = mTracks[j];
audio_session_t sessionId = track->sessionId();
@@ -9596,13 +9616,14 @@
AudioStreamIn* RecordThread::clearInput()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
AudioStreamIn *input = mInput;
mInput = NULL;
+ mInputSource.clear();
return input;
}
-// this method must always be called either with ThreadBase mLock held or inside the thread loop
+// this method must always be called either with ThreadBase mutex() held or inside the thread loop
sp<StreamHalInterface> RecordThread::stream() const
{
if (mInput == NULL) {
@@ -9720,7 +9741,7 @@
void RecordThread::updateOutDevices(const DeviceDescriptorBaseVector& outDevices)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
mOutDevices = outDevices;
mOutDeviceTypeAddrs = deviceTypeAddrsFromDescriptors(mOutDevices);
for (size_t i = 0; i < mEffectChains.size(); i++) {
@@ -9857,7 +9878,7 @@
void RecordThread::addPatchTrack(const sp<IAfPatchRecord>& record)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
mTracks.add(record);
if (record->getSource()) {
mSource = record->getSource();
@@ -9866,7 +9887,7 @@
void RecordThread::deletePatchTrack(const sp<IAfPatchRecord>& record)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (mSource == record->getSource()) {
mSource = mInput;
}
@@ -9990,25 +10011,27 @@
void MmapThread::disconnect()
{
ActiveTracks<IAfMmapTrack> activeTracks;
+ audio_port_handle_t localPortId;
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
for (const sp<IAfMmapTrack>& t : mActiveTracks) {
activeTracks.add(t);
}
+ localPortId = mPortId;
}
for (const sp<IAfMmapTrack>& t : activeTracks) {
stop(t->portId());
}
// This will decrement references and may cause the destruction of this thread.
if (isOutput()) {
- AudioSystem::releaseOutput(mPortId);
+ AudioSystem::releaseOutput(localPortId);
} else {
- AudioSystem::releaseInput(mPortId);
+ AudioSystem::releaseInput(localPortId);
}
}
-void MmapThread::configure(const audio_attributes_t* attr,
+void MmapThread::configure_l(const audio_attributes_t* attr,
audio_stream_type_t streamType __unused,
audio_session_t sessionId,
const sp<MmapStreamCallback>& callback,
@@ -10025,6 +10048,7 @@
status_t MmapThread::createMmapBuffer(int32_t minSizeFrames,
struct audio_mmap_buffer_info *info)
{
+ audio_utils::lock_guard l(mutex());
if (mHalStream == 0) {
return NO_INIT;
}
@@ -10034,6 +10058,7 @@
status_t MmapThread::getMmapPosition(struct audio_mmap_position* position) const
{
+ audio_utils::lock_guard l(mutex());
if (mHalStream == 0) {
return NO_INIT;
}
@@ -10061,6 +10086,7 @@
const audio_attributes_t *attr,
audio_port_handle_t *handle)
{
+ audio_utils::lock_guard l(mutex());
ALOGV("%s clientUid %d mStandby %d mPortId %d *handle %d", __FUNCTION__,
client.attributionSource.uid, mStandby, mPortId, *handle);
if (mHalStream == 0) {
@@ -10071,7 +10097,7 @@
// For the first track, reuse portId and session allocated when the stream was opened.
if (*handle == mPortId) {
- acquireWakeLock();
+ acquireWakeLock_l();
return NO_ERROR;
}
@@ -10081,20 +10107,23 @@
const AttributionSourceState adjAttributionSource = afutils::checkAttributionSourcePackage(
client.attributionSource);
+ const auto localSessionId = mSessionId;
+ auto localAttr = mAttr;
if (isOutput()) {
audio_config_t config = AUDIO_CONFIG_INITIALIZER;
config.sample_rate = mSampleRate;
config.channel_mask = mChannelMask;
config.format = mFormat;
- audio_stream_type_t stream = streamType();
+ audio_stream_type_t stream = streamType_l();
audio_output_flags_t flags =
(audio_output_flags_t)(AUDIO_OUTPUT_FLAG_MMAP_NOIRQ | AUDIO_OUTPUT_FLAG_DIRECT);
audio_port_handle_t deviceId = mDeviceId;
std::vector<audio_io_handle_t> secondaryOutputs;
bool isSpatialized;
bool isBitPerfect;
- ret = AudioSystem::getOutputForAttr(&mAttr, &io,
- mSessionId,
+ mutex().unlock();
+ ret = AudioSystem::getOutputForAttr(&localAttr, &io,
+ localSessionId,
&stream,
adjAttributionSource,
&config,
@@ -10104,6 +10133,8 @@
&secondaryOutputs,
&isSpatialized,
&isBitPerfect);
+ mutex().lock();
+ mAttr = localAttr;
ALOGD_IF(!secondaryOutputs.empty(),
"MmapThread::start does not support secondary outputs, ignoring them");
} else {
@@ -10112,14 +10143,17 @@
config.channel_mask = mChannelMask;
config.format = mFormat;
audio_port_handle_t deviceId = mDeviceId;
- ret = AudioSystem::getInputForAttr(&mAttr, &io,
+ mutex().unlock();
+ ret = AudioSystem::getInputForAttr(&localAttr, &io,
RECORD_RIID_INVALID,
- mSessionId,
+ localSessionId,
adjAttributionSource,
&config,
AUDIO_INPUT_FLAG_MMAP_NOIRQ,
&deviceId,
&portId);
+ mutex().lock();
+ // localAttr is const for getInputForAttr.
}
// APM should not chose a different input or output stream for the same set of attributes
// and audo configuration
@@ -10130,29 +10164,31 @@
}
if (isOutput()) {
+ mutex().unlock();
ret = AudioSystem::startOutput(portId);
+ mutex().lock();
} else {
{
// Add the track record before starting input so that the silent status for the
// client can be cached.
- Mutex::Autolock _l(mLock);
setClientSilencedState_l(portId, false /*silenced*/);
}
+ mutex().unlock();
ret = AudioSystem::startInput(portId);
+ mutex().lock();
}
- Mutex::Autolock _l(mLock);
// abort if start is rejected by audio policy manager
if (ret != NO_ERROR) {
ALOGE("%s: error start rejected by AudioPolicyManager = %d", __FUNCTION__, ret);
if (!mActiveTracks.isEmpty()) {
- mLock.unlock();
+ mutex().unlock();
if (isOutput()) {
AudioSystem::releaseOutput(portId);
} else {
AudioSystem::releaseInput(portId);
}
- mLock.lock();
+ mutex().lock();
} else {
mHalStream->stop();
}
@@ -10185,7 +10221,7 @@
mActiveTracks.add(track);
sp<IAfEffectChain> chain = getEffectChain_l(mSessionId);
if (chain != 0) {
- chain->setStrategy(getStrategyForStream(streamType()));
+ chain->setStrategy(getStrategyForStream(streamType_l()));
chain->incTrackCnt();
chain->incActiveTrackCnt();
}
@@ -10207,18 +10243,17 @@
status_t MmapThread::stop(audio_port_handle_t handle)
{
ALOGV("%s handle %d", __FUNCTION__, handle);
+ audio_utils::lock_guard l(mutex());
if (mHalStream == 0) {
return NO_INIT;
}
if (handle == mPortId) {
- releaseWakeLock();
+ releaseWakeLock_l();
return NO_ERROR;
}
- Mutex::Autolock _l(mLock);
-
sp<IAfMmapTrack> track;
for (const sp<IAfMmapTrack>& t : mActiveTracks) {
if (handle == t->portId()) {
@@ -10233,7 +10268,7 @@
mActiveTracks.remove(track);
eraseClientSilencedState_l(track->portId());
- mLock.unlock();
+ mutex().unlock();
if (isOutput()) {
AudioSystem::stopOutput(track->portId());
AudioSystem::releaseOutput(track->portId());
@@ -10241,7 +10276,7 @@
AudioSystem::stopInput(track->portId());
AudioSystem::releaseInput(track->portId());
}
- mLock.lock();
+ mutex().lock();
sp<IAfEffectChain> chain = getEffectChain_l(track->sessionId());
if (chain != 0) {
@@ -10259,8 +10294,10 @@
}
status_t MmapThread::standby()
+NO_THREAD_SAFETY_ANALYSIS // clang bug
{
ALOGV("%s", __FUNCTION__);
+ audio_utils::lock_guard(mutex());
if (mHalStream == 0) {
return NO_INIT;
@@ -10274,7 +10311,7 @@
mThreadSnapshot.onEnd();
mStandby = true;
}
- releaseWakeLock();
+ releaseWakeLock_l();
return NO_ERROR;
}
@@ -10321,7 +10358,10 @@
bool MmapThread::threadLoop()
{
- checkSilentMode_l();
+ {
+ audio_utils::unique_lock _l(mutex());
+ checkSilentMode_l();
+ }
const String8 myName(String8::format("thread %p type %d TID %d", this, mType, gettid()));
@@ -10330,7 +10370,7 @@
Vector<sp<IAfEffectChain>> effectChains;
{ // under Thread lock
- Mutex::Autolock _l(mLock);
+ audio_utils::unique_lock _l(mutex());
if (mSignalPending) {
// A signal was raised while we were unlocked
@@ -10346,7 +10386,7 @@
// wait until we have something to do...
ALOGV("%s going to sleep", myName.c_str());
- mWaitWorkCV.wait(mLock);
+ mWaitWorkCV.wait(_l);
ALOGV("%s waking up", myName.c_str());
checkSilentMode_l();
@@ -10361,7 +10401,7 @@
checkInvalidTracks_l();
- mActiveTracks.updatePowerState(this);
+ mActiveTracks.updatePowerState_l(this);
updateMetadata_l();
@@ -10389,7 +10429,7 @@
return false;
}
-// checkForNewParameter_l() must be called with ThreadBase::mLock held
+// checkForNewParameter_l() must be called with ThreadBase::mutex() held
bool MmapThread::checkForNewParameter_l(const String8& keyValuePair,
status_t& status)
{
@@ -10410,7 +10450,7 @@
String8 MmapThread::getParameters(const String8& keys)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
String8 out_s8;
if (initCheck() == NO_ERROR && mHalStream->getParameters(keys, &out_s8) == OK) {
return out_s8;
@@ -10418,7 +10458,7 @@
return {};
}
-void MmapThread::ioConfigChanged(audio_io_config_event_t event, pid_t pid,
+void MmapThread::ioConfigChanged_l(audio_io_config_event_t event, pid_t pid,
audio_port_handle_t portId __unused) {
sp<AudioIoDescriptor> desc;
bool isInput = false;
@@ -10440,12 +10480,12 @@
desc = sp<AudioIoDescriptor>::make(mId);
break;
}
- mAfThreadCallback->ioConfigChanged(event, desc, pid);
+ mAfThreadCallback->ioConfigChanged_l(event, desc, pid);
}
status_t MmapThread::createAudioPatch_l(const struct audio_patch* patch,
audio_patch_handle_t *handle)
-NO_THREAD_SAFETY_ANALYSIS // elease and re-acquire mLock
+NO_THREAD_SAFETY_ANALYSIS // elease and re-acquire mutex()
{
status_t status = NO_ERROR;
@@ -10521,9 +10561,9 @@
}
sp<MmapStreamCallback> callback = mCallback.promote();
if (mDeviceId != deviceId && callback != 0) {
- mLock.unlock();
+ mutex().unlock();
callback->onRoutingChanged(deviceId);
- mLock.lock();
+ mutex().lock();
}
mPatch = *patch;
mDeviceId = deviceId;
@@ -10557,6 +10597,7 @@
}
void MmapThread::toAudioPortConfig(struct audio_port_config* config)
+NO_THREAD_SAFETY_ANALYSIS // mAudioHwDev handle access
{
ThreadBase::toAudioPortConfig(config);
if (isOutput()) {
@@ -10674,7 +10715,6 @@
}
void MmapThread::checkInvalidTracks_l()
-NO_THREAD_SAFETY_ANALYSIS // release and re-acquire mLock
{
sp<MmapStreamCallback> callback;
for (const sp<IAfMmapTrack>& track : mActiveTracks) {
@@ -10688,9 +10728,9 @@
}
}
if (callback != 0) {
- mLock.unlock();
+ mutex().unlock();
callback->onRoutingChanged(AUDIO_PORT_HANDLE_NONE);
- mLock.lock();
+ mutex().lock();
}
}
@@ -10772,13 +10812,14 @@
audio_port_handle_t deviceId,
audio_port_handle_t portId)
{
- MmapThread::configure(attr, streamType, sessionId, callback, deviceId, portId);
+ audio_utils::lock_guard l(mutex());
+ MmapThread::configure_l(attr, streamType, sessionId, callback, deviceId, portId);
mStreamType = streamType;
}
AudioStreamOut* MmapPlaybackThread::clearOutput()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
AudioStreamOut *output = mOutput;
mOutput = NULL;
return output;
@@ -10786,7 +10827,7 @@
void MmapPlaybackThread::setMasterVolume(float value)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
// Don't apply master volume in SW if our HAL can do it for us.
if (mAudioHwDev &&
mAudioHwDev->canSetMasterVolume()) {
@@ -10798,7 +10839,7 @@
void MmapPlaybackThread::setMasterMute(bool muted)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
// Don't apply master mute in SW if our HAL can do it for us.
if (mAudioHwDev && mAudioHwDev->canSetMasterMute()) {
mMasterMute = false;
@@ -10809,7 +10850,7 @@
void MmapPlaybackThread::setStreamVolume(audio_stream_type_t stream, float value)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
mStreamTypes[stream].volume = value;
if (stream == mStreamType) {
broadcast_l();
@@ -10818,13 +10859,13 @@
float MmapPlaybackThread::streamVolume(audio_stream_type_t stream) const
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
return mStreamTypes[stream].volume;
}
void MmapPlaybackThread::setStreamMute(audio_stream_type_t stream, bool muted)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
mStreamTypes[stream].mute = muted;
if (stream == mStreamType) {
broadcast_l();
@@ -10833,7 +10874,7 @@
void MmapPlaybackThread::invalidateTracks(audio_stream_type_t streamType)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
if (streamType == mStreamType) {
for (const sp<IAfMmapTrack>& track : mActiveTracks) {
track->invalidate();
@@ -10844,7 +10885,7 @@
void MmapPlaybackThread::invalidateTracks(std::set<audio_port_handle_t>& portIds)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
bool trackMatch = false;
for (const sp<IAfMmapTrack>& track : mActiveTracks) {
if (portIds.find(track->portId()) != portIds.end()) {
@@ -10892,9 +10933,9 @@
if (callback != 0) {
mHalVolFloat = volume; // SW volume control worked, so update value.
mNoCallbackWarningCount = 0;
- mLock.unlock();
+ mutex().unlock();
callback->onVolumeChanged(volume);
- mLock.lock();
+ mutex().lock();
} else {
if (mNoCallbackWarningCount < kMaxNoCallbackWarnings) {
ALOGW("Could not set MMAP stream volume: no volume callback!");
@@ -10991,7 +11032,7 @@
return NO_ERROR;
}
-// startMelComputation_l() must be called with AudioFlinger::mLock held
+// startMelComputation_l() must be called with AudioFlinger::mutex() held
void MmapPlaybackThread::startMelComputation_l(
const sp<audio_utils::MelProcessor>& processor)
{
@@ -11005,7 +11046,7 @@
// assigned constant for each thread
}
-// stopMelComputation_l() must be called with AudioFlinger::mLock held
+// stopMelComputation_l() must be called with AudioFlinger::mutex() held
void MmapPlaybackThread::stopMelComputation_l()
{
ALOGV("%s: pausing mel processor for thread %d", __func__, id());
@@ -11054,7 +11095,7 @@
AudioStreamIn* MmapCaptureThread::clearInput()
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
AudioStreamIn *input = mInput;
mInput = NULL;
return input;
@@ -11112,7 +11153,7 @@
void MmapCaptureThread::setRecordSilenced(audio_port_handle_t portId, bool silenced)
{
- Mutex::Autolock _l(mLock);
+ audio_utils::lock_guard _l(mutex());
for (size_t i = 0; i < mActiveTracks.size() ; i++) {
if (mActiveTracks[i]->portId() == portId) {
mActiveTracks[i]->setSilenced_l(silenced);
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 18b6840..724a46d 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -44,6 +44,13 @@
public:
static const char *threadTypeToString(type_t type);
+ // ThreadBase_ThreadLoop is a virtual mutex (always nullptr) that
+ // guards methods and variables that ONLY run and are accessed
+ // on the single threaded threadLoop().
+ //
+ // As access is by a single thread, the variables are thread safe.
+ static audio_utils::mutex* ThreadBase_ThreadLoop;
+
IAfThreadCallback* afThreadCallback() const final { return mAfThreadCallback.get(); }
ThreadBase(const sp<IAfThreadCallback>& afThreadCallback, audio_io_handle_t id,
@@ -51,7 +58,7 @@
~ThreadBase() override;
status_t readyToRun() final;
- void clearPowerManager() final;
+ void clearPowerManager() final EXCLUDES_ThreadBase_Mutex;
// base for record and playback
enum {
@@ -68,29 +75,27 @@
class ConfigEventData: public RefBase {
public:
- virtual ~ConfigEventData() {}
-
virtual void dump(char *buffer, size_t size) = 0;
protected:
- ConfigEventData() {}
+ ConfigEventData() = default;
};
// Config event sequence by client if status needed (e.g binder thread calling setParameters()):
// 1. create SetParameterConfigEvent. This sets mWaitStatus in config event
- // 2. Lock mLock
+ // 2. Lock mutex()
// 3. Call sendConfigEvent_l(): Append to mConfigEvents and mWaitWorkCV.signal
// 4. sendConfigEvent_l() reads status from event->mStatus;
// 5. sendConfigEvent_l() returns status
// 6. Unlock
//
// Parameter sequence by server: threadLoop calling processConfigEvents_l():
- // 1. Lock mLock
+ // 1. Lock mutex()
// 2. If there is an entry in mConfigEvents proceed ...
// 3. Read first entry in mConfigEvents
// 4. Remove first entry from mConfigEvents
// 5. Process
// 6. Set event->mStatus
- // 7. event->mCond.signal
+ // 7. event->mCondition.notify_one()
// 8. Unlock
class ConfigEvent: public RefBase {
@@ -103,13 +108,22 @@
}
}
+ audio_utils::mutex& mutex() const RETURN_CAPABILITY(audio_utils::ConfigEvent_Mutex) {
+ return mMutex;
+ }
const int mType; // event type e.g. CFG_EVENT_IO
- Mutex mLock; // mutex associated with mCond
- Condition mCond; // condition for status return
+ mutable audio_utils::mutex mMutex; // mutex associated with mCondition
+ audio_utils::condition_variable mCondition; // condition for status return
+
+ // NO_THREAD_SAFETY_ANALYSIS Can we add GUARDED_BY?
status_t mStatus; // status communicated to sender
- bool mWaitStatus; // true if sender is waiting for status
- bool mRequiresSystemReady; // true if must wait for system ready to enter event queue
- sp<ConfigEventData> mData; // event specific parameter data
+
+ bool mWaitStatus GUARDED_BY(mutex()); // true if sender is waiting for status
+ // true if must wait for system ready to enter event queue
+ bool mRequiresSystemReady GUARDED_BY(mutex());
+
+ // NO_THREAD_SAFETY_ANALYSIS Can we add GUARDED_BY?
+ sp<ConfigEventData> mData; // event specific parameter data
protected:
explicit ConfigEvent(int type, bool requiresSystemReady = false) :
@@ -196,7 +210,7 @@
}
const struct audio_patch mPatch;
- audio_patch_handle_t mHandle;
+ audio_patch_handle_t mHandle; // cannot be const
};
class CreateAudioPatchConfigEvent : public ConfigEvent {
@@ -218,7 +232,7 @@
snprintf(buffer, size, "- Patch handle: %u\n", mHandle);
}
- audio_patch_handle_t mHandle;
+ const audio_patch_handle_t mHandle;
};
class ReleaseAudioPatchConfigEvent : public ConfigEvent {
@@ -239,7 +253,7 @@
snprintf(buffer, size, "- Devices: %s", android::toString(mOutDevices).c_str());
}
- DeviceDescriptorBaseVector mOutDevices;
+ const DeviceDescriptorBaseVector mOutDevices;
};
class UpdateOutDevicesConfigEvent : public ConfigEvent {
@@ -259,7 +273,7 @@
snprintf(buffer, size, "- mMaxSharedAudioHistoryMs: %d", mMaxSharedAudioHistoryMs);
}
- int32_t mMaxSharedAudioHistoryMs;
+ const int32_t mMaxSharedAudioHistoryMs;
};
class ResizeBufferConfigEvent : public ConfigEvent {
@@ -288,15 +302,14 @@
class PMDeathRecipient : public IBinder::DeathRecipient {
public:
explicit PMDeathRecipient(const wp<ThreadBase>& thread) : mThread(thread) {}
- virtual ~PMDeathRecipient() {}
// IBinder::DeathRecipient
- virtual void binderDied(const wp<IBinder>& who);
+ void binderDied(const wp<IBinder>& who) final;
private:
DISALLOW_COPY_AND_ASSIGN(PMDeathRecipient);
- wp<ThreadBase> mThread;
+ const wp<ThreadBase> mThread;
};
type_t type() const final { return mType; }
@@ -310,8 +323,9 @@
uint32_t channelCount() const final { return mChannelCount; }
audio_channel_mask_t hapticChannelMask() const override { return AUDIO_CHANNEL_NONE; }
uint32_t hapticChannelCount() const override { return 0; }
- uint32_t latency_l() const override { return 0; }
- void setVolumeForOutput_l(float /* left */, float /* right */) const override {}
+ uint32_t latency_l() const override { return 0; } // NO_THREAD_SAFETY_ANALYSIS
+ void setVolumeForOutput_l(float /* left */, float /* right */) const override
+ REQUIRES(mutex()) {}
// Return's the HAL's frame count i.e. fast mixer buffer size.
size_t frameCountHAL() const final { return mFrameCount; }
@@ -319,44 +333,49 @@
// Should be "virtual status_t requestExitAndWait()" and override same
// method in Thread, but Thread::requestExitAndWait() is not yet virtual.
- void exit() final;
- status_t setParameters(const String8& keyValuePairs) final;
+ void exit() final EXCLUDES_ThreadBase_Mutex;
+ status_t setParameters(const String8& keyValuePairs) final EXCLUDES_ThreadBase_Mutex;
- // sendConfigEvent_l() must be called with ThreadBase::mLock held
+ // sendConfigEvent_l() must be called with ThreadBase::mutex() held
// Can temporarily release the lock if waiting for a reply from
// processConfigEvents_l().
- status_t sendConfigEvent_l(sp<ConfigEvent>& event);
+ status_t sendConfigEvent_l(sp<ConfigEvent>& event) REQUIRES(mutex());
void sendIoConfigEvent(audio_io_config_event_t event, pid_t pid = 0,
- audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE) final;
+ audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE) final EXCLUDES_ThreadBase_Mutex;
void sendIoConfigEvent_l(audio_io_config_event_t event, pid_t pid = 0,
- audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE) final;
- void sendPrioConfigEvent(pid_t pid, pid_t tid, int32_t prio, bool forApp) final;
- void sendPrioConfigEvent_l(pid_t pid, pid_t tid, int32_t prio, bool forApp) final;
- status_t sendSetParameterConfigEvent_l(const String8& keyValuePair) final;
+ audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE) final REQUIRES(mutex());
+ void sendPrioConfigEvent(pid_t pid, pid_t tid, int32_t prio, bool forApp) final
+ EXCLUDES_ThreadBase_Mutex;
+ void sendPrioConfigEvent_l(pid_t pid, pid_t tid, int32_t prio, bool forApp) final
+ REQUIRES(mutex());
+ status_t sendSetParameterConfigEvent_l(const String8& keyValuePair) final REQUIRES(mutex());
status_t sendCreateAudioPatchConfigEvent(const struct audio_patch* patch,
- audio_patch_handle_t* handle) final;
- status_t sendReleaseAudioPatchConfigEvent(audio_patch_handle_t handle) final;
+ audio_patch_handle_t* handle) final EXCLUDES_ThreadBase_Mutex;
+ status_t sendReleaseAudioPatchConfigEvent(audio_patch_handle_t handle) final
+ EXCLUDES_ThreadBase_Mutex;
status_t sendUpdateOutDeviceConfigEvent(
- const DeviceDescriptorBaseVector& outDevices) final;
- void sendResizeBufferConfigEvent_l(int32_t maxSharedAudioHistoryMs) final;
- void sendCheckOutputStageEffectsEvent() final;
- void sendCheckOutputStageEffectsEvent_l() final;
- void sendHalLatencyModesChangedEvent_l() final;
+ const DeviceDescriptorBaseVector& outDevices) final EXCLUDES_ThreadBase_Mutex;
+ void sendResizeBufferConfigEvent_l(int32_t maxSharedAudioHistoryMs) final REQUIRES(mutex());
+ void sendCheckOutputStageEffectsEvent() final EXCLUDES_ThreadBase_Mutex;
+ void sendCheckOutputStageEffectsEvent_l() final REQUIRES(mutex());
+ void sendHalLatencyModesChangedEvent_l() final REQUIRES(mutex());
- void processConfigEvents_l() final;
+ void processConfigEvents_l() final REQUIRES(mutex());
void setCheckOutputStageEffects() override {}
void updateOutDevices(const DeviceDescriptorBaseVector& outDevices) override;
void toAudioPortConfig(struct audio_port_config* config) override;
- void resizeInputBuffer_l(int32_t maxSharedAudioHistoryMs) override;
+ void resizeInputBuffer_l(int32_t maxSharedAudioHistoryMs) override REQUIRES(mutex());
// see note at declaration of mStandby, mOutDevice and mInDevice
bool inStandby() const override { return mStandby; }
- const DeviceTypeSet outDeviceTypes() const final {
+ const DeviceTypeSet outDeviceTypes_l() const final REQUIRES(mutex()) {
return getAudioDeviceTypes(mOutDeviceTypeAddrs);
}
- audio_devices_t inDeviceType() const final { return mInDeviceTypeAddr.mType; }
- DeviceTypeSet getDeviceTypes() const final {
- return isOutput() ? outDeviceTypes() : DeviceTypeSet({inDeviceType()});
+ audio_devices_t inDeviceType_l() const final REQUIRES(mutex()) {
+ return mInDeviceTypeAddr.mType;
+ }
+ DeviceTypeSet getDeviceTypes_l() const final REQUIRES(mutex()) {
+ return isOutput() ? outDeviceTypes_l() : DeviceTypeSet({inDeviceType_l()});
}
const AudioDeviceTypeAddrVector& outDeviceTypeAddrs() const final {
@@ -389,7 +408,8 @@
status_t *status /*non-NULL*/,
bool pinned,
bool probe,
- bool notifyFramesProcessed) final;
+ bool notifyFramesProcessed) final
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
// return values for hasAudioSession (bit field)
enum effect_state {
@@ -408,43 +428,49 @@
// get effect chain corresponding to session Id.
sp<IAfEffectChain> getEffectChain(audio_session_t sessionId) const final;
// same as getEffectChain() but must be called with ThreadBase mutex locked
- sp<IAfEffectChain> getEffectChain_l(audio_session_t sessionId) const final;
- std::vector<int> getEffectIds_l(audio_session_t sessionId) const final;
+ sp<IAfEffectChain> getEffectChain_l(audio_session_t sessionId) const final REQUIRES(mutex());
+ std::vector<int> getEffectIds_l(audio_session_t sessionId) const final REQUIRES(mutex());
// lock all effect chains Mutexes. Must be called before releasing the
// ThreadBase mutex before processing the mixer and effects. This guarantees the
// integrity of the chains during the process.
// Also sets the parameter 'effectChains' to current value of mEffectChains.
- void lockEffectChains_l(Vector<sp<IAfEffectChain>>& effectChains) final;
+ void lockEffectChains_l(Vector<sp<IAfEffectChain>>& effectChains) final REQUIRES(mutex());
// unlock effect chains after process
void unlockEffectChains(const Vector<sp<IAfEffectChain>>& effectChains) final;
// get a copy of mEffectChains vector
- Vector<sp<IAfEffectChain>> getEffectChains_l() const final { return mEffectChains; };
+ Vector<sp<IAfEffectChain>> getEffectChains_l() const final REQUIRES(mutex()) {
+ return mEffectChains;
+ }
// set audio mode to all effect chains
void setMode(audio_mode_t mode) final;
// get effect module with corresponding ID on specified audio session
sp<IAfEffectModule> getEffect(audio_session_t sessionId, int effectId) const final;
- sp<IAfEffectModule> getEffect_l(audio_session_t sessionId, int effectId) const final;
+ sp<IAfEffectModule> getEffect_l(audio_session_t sessionId, int effectId) const final
+ REQUIRES(mutex());
// add and effect module. Also creates the effect chain is none exists for
// the effects audio session. Only called in a context of moving an effect
// from one thread to another
- status_t addEffect_l(const sp<IAfEffectModule>& effect) final;
+ status_t addEffect_ll(const sp<IAfEffectModule>& effect) final
+ REQUIRES(audio_utils::AudioFlinger_Mutex, mutex());
// remove and effect module. Also removes the effect chain is this was the last
// effect
- void removeEffect_l(const sp<IAfEffectModule>& effect, bool release = false) final;
+ void removeEffect_l(const sp<IAfEffectModule>& effect, bool release = false) final
+ REQUIRES(mutex());
// disconnect an effect handle from module and destroy module if last handle
void disconnectEffectHandle(IAfEffectHandle* handle, bool unpinIfLast) final;
// detach all tracks connected to an auxiliary effect
- void detachAuxEffect_l(int /* effectId */) override {}
+ void detachAuxEffect_l(int /* effectId */) override REQUIRES(mutex()) {}
// TODO(b/291317898) - remove hasAudioSession_l below.
- uint32_t hasAudioSession_l(audio_session_t sessionId) const override = 0;
- uint32_t hasAudioSession(audio_session_t sessionId) const final {
- Mutex::Autolock _l(mLock);
- return hasAudioSession_l(sessionId);
- }
+ uint32_t hasAudioSession_l(audio_session_t sessionId) const override REQUIRES(mutex()) = 0;
+ uint32_t hasAudioSession(audio_session_t sessionId) const final EXCLUDES_ThreadBase_Mutex {
+ audio_utils::lock_guard _l(mutex());
+ return hasAudioSession_l(sessionId);
+ }
template <typename T>
- uint32_t hasAudioSession_l(audio_session_t sessionId, const T& tracks) const {
+ uint32_t hasAudioSession_l(audio_session_t sessionId, const T& tracks) const
+ REQUIRES(mutex()) {
uint32_t result = 0;
if (getEffectChain_l(sessionId) != 0) {
result = EFFECT_SESSION;
@@ -473,9 +499,9 @@
// the value returned by default implementation is not important as the
// strategy is only meaningful for PlaybackThread which implements this method
product_strategy_t getStrategyForSession_l(
- audio_session_t /* sessionId */) const override {
- return static_cast<product_strategy_t>(0);
- }
+ audio_session_t /* sessionId */) const override REQUIRES(mutex()){
+ return static_cast<product_strategy_t>(0);
+ }
// check if some effects must be suspended/restored when an effect is enabled
// or disabled
@@ -494,38 +520,41 @@
sp<IMemory> pipeMemory() const override { return nullptr; }
- void systemReady() final;
+ void systemReady() final EXCLUDES_ThreadBase_Mutex;
- void broadcast_l() final;
+ void broadcast_l() final REQUIRES(mutex());
- bool isTimestampCorrectionEnabled() const override { return false; }
+ bool isTimestampCorrectionEnabled_l() const override REQUIRES(mutex()) { return false; }
bool isMsdDevice() const final { return mIsMsdDevice; }
void dump(int fd, const Vector<String16>& args) override;
// deliver stats to mediametrics.
- void sendStatistics(bool force) final;
+ void sendStatistics(bool force) final
+ REQUIRES(ThreadBase_ThreadLoop) EXCLUDES_ThreadBase_Mutex;
- Mutex& mutex() const final {
- return mLock;
+ audio_utils::mutex& mutex() const final RETURN_CAPABILITY(audio_utils::ThreadBase_Mutex) {
+ return mMutex;
}
- mutable Mutex mLock;
+ mutable audio_utils::mutex mMutex;
- void onEffectEnable(const sp<IAfEffectModule>& effect) final;
- void onEffectDisable() final;
+ void onEffectEnable(const sp<IAfEffectModule>& effect) final EXCLUDES_ThreadBase_Mutex;
+ void onEffectDisable() final EXCLUDES_ThreadBase_Mutex;
- // invalidateTracksForAudioSession_l must be called with holding mLock.
- void invalidateTracksForAudioSession_l(audio_session_t /* sessionId */) const override {}
+ // invalidateTracksForAudioSession_l must be called with holding mutex().
+ void invalidateTracksForAudioSession_l(audio_session_t /* sessionId */) const override
+ REQUIRES(mutex()) {}
// Invalidate all the tracks with the given audio session.
- void invalidateTracksForAudioSession(audio_session_t sessionId) const final {
- Mutex::Autolock _l(mLock);
+ void invalidateTracksForAudioSession(audio_session_t sessionId) const final
+ EXCLUDES_ThreadBase_Mutex {
+ audio_utils::lock_guard _l(mutex());
invalidateTracksForAudioSession_l(sessionId);
}
template <typename T>
- void invalidateTracksForAudioSession_l(audio_session_t sessionId,
- const T& tracks) const {
+ void invalidateTracksForAudioSession_l(audio_session_t sessionId,
+ const T& tracks) const REQUIRES(mutex()) {
for (size_t i = 0; i < tracks.size(); ++i) {
const sp<IAfTrackBase>& track = tracks[i];
if (sessionId == track->sessionId()) {
@@ -534,8 +563,10 @@
}
}
- void startMelComputation_l(const sp<audio_utils::MelProcessor>& processor) override;
- void stopMelComputation_l() override;
+ void startMelComputation_l(const sp<audio_utils::MelProcessor>& processor) override
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
+ void stopMelComputation_l() override
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
protected:
@@ -548,41 +579,44 @@
effect_uuid_t mType; // effect type UUID
};
- void acquireWakeLock();
- virtual void acquireWakeLock_l();
- void releaseWakeLock();
- void releaseWakeLock_l();
- void updateWakeLockUids_l(const SortedVector<uid_t> &uids);
- void getPowerManager_l();
+ void acquireWakeLock() EXCLUDES_ThreadBase_Mutex;
+ virtual void acquireWakeLock_l() REQUIRES(mutex());
+ void releaseWakeLock() EXCLUDES_ThreadBase_Mutex;
+ void releaseWakeLock_l() REQUIRES(mutex());
+ void updateWakeLockUids_l(const SortedVector<uid_t> &uids) REQUIRES(mutex());
+ void getPowerManager_l() REQUIRES(mutex());
// suspend or restore effects of the specified type (or all if type is NULL)
// on a given session. The number of suspend requests is counted and restore
// occurs when all suspend requests are cancelled.
- void setEffectSuspended_l(const effect_uuid_t *type,
+ void setEffectSuspended_l(const effect_uuid_t *type,
bool suspend,
- audio_session_t sessionId) final;
+ audio_session_t sessionId) final REQUIRES(mutex());
// updated mSuspendedSessions when an effect is suspended or restored
- void updateSuspendedSessions_l(const effect_uuid_t *type,
+ void updateSuspendedSessions_l(const effect_uuid_t *type,
bool suspend,
- audio_session_t sessionId);
+ audio_session_t sessionId) REQUIRES(mutex());
// check if some effects must be suspended when an effect chain is added
- void checkSuspendOnAddEffectChain_l(const sp<IAfEffectChain>& chain);
+ void checkSuspendOnAddEffectChain_l(const sp<IAfEffectChain>& chain) REQUIRES(mutex());
// sends the metadata of the active tracks to the HAL
struct MetadataUpdate {
std::vector<playback_track_metadata_v7_t> playbackMetadataUpdate;
std::vector<record_track_metadata_v7_t> recordMetadataUpdate;
};
- virtual MetadataUpdate updateMetadata_l() = 0;
+ // NO_THREAD_SAFETY_ANALYSIS, updateMetadata_l() should include ThreadBase_ThreadLoop
+ // but MmapThread::start() -> exitStandby_l() -> updateMetadata_l() prevents this.
+ virtual MetadataUpdate updateMetadata_l() REQUIRES(mutex()) = 0;
String16 getWakeLockTag();
- virtual void preExit() { }
- virtual void setMasterMono_l(bool mono __unused) { }
+ virtual void preExit() EXCLUDES_ThreadBase_Mutex {}
+ virtual void setMasterMono_l(bool mono __unused) REQUIRES(mutex()) {}
virtual bool requireMonoBlend() { return false; }
// called within the threadLoop to obtain timestamp from the HAL.
- virtual status_t threadloop_getHalTimestamp_l(
- ExtendedTimestamp *timestamp __unused) const {
+ virtual status_t threadloop_getHalTimestamp_l(
+ ExtendedTimestamp *timestamp __unused) const
+ REQUIRES(mutex(), ThreadBase_ThreadLoop) {
return INVALID_OPERATION;
}
public:
@@ -590,16 +624,17 @@
product_strategy_t getStrategyForStream(audio_stream_type_t stream) const;
protected:
- virtual void onHalLatencyModesChanged_l() {}
+ virtual void onHalLatencyModesChanged_l() REQUIRES(mutex()) {}
- virtual void dumpInternals_l(int fd __unused, const Vector<String16>& args __unused)
- { }
- virtual void dumpTracks_l(int fd __unused, const Vector<String16>& args __unused) { }
+ virtual void dumpInternals_l(int fd __unused, const Vector<String16>& args __unused)
+ REQUIRES(mutex()) {}
+ virtual void dumpTracks_l(int fd __unused, const Vector<String16>& args __unused)
+ REQUIRES(mutex()) {}
const type_t mType;
// Used by parameters, config events, addTrack_l, exit
- Condition mWaitWorkCV;
+ audio_utils::condition_variable mWaitWorkCV;
const sp<IAfThreadCallback> mAfThreadCallback;
ThreadMetrics mThreadMetrics;
@@ -619,10 +654,14 @@
// HAL format if Fastmixer is used.
audio_format_t mHALFormat;
size_t mBufferSize; // HAL buffer size for read() or write()
- AudioDeviceTypeAddrVector mOutDeviceTypeAddrs; // output device types and addresses
- AudioDeviceTypeAddr mInDeviceTypeAddr; // input device type and address
- Vector< sp<ConfigEvent> > mConfigEvents;
- Vector< sp<ConfigEvent> > mPendingConfigEvents; // events awaiting system ready
+
+ // output device types and addresses
+ AudioDeviceTypeAddrVector mOutDeviceTypeAddrs GUARDED_BY(mutex());
+ AudioDeviceTypeAddr mInDeviceTypeAddr GUARDED_BY(mutex()); // input device type and address
+ Vector<sp<ConfigEvent>> mConfigEvents GUARDED_BY(mutex());
+
+ // events awaiting system ready
+ Vector<sp<ConfigEvent>> mPendingConfigEvents GUARDED_BY(mutex());
// These fields are written and read by thread itself without lock or barrier,
// and read by other threads without lock or barrier via standby(), outDeviceTypes()
@@ -632,17 +671,17 @@
// with possibility that it might be inconsistent with other information.
bool mStandby; // Whether thread is currently in standby.
+ // NO_THREAD_SAFETY_ANALYSIS - mPatch and mAudioSource should be guarded by mutex().
struct audio_patch mPatch;
-
audio_source_t mAudioSource;
const audio_io_handle_t mId;
- Vector<sp<IAfEffectChain>> mEffectChains;
+ Vector<sp<IAfEffectChain>> mEffectChains GUARDED_BY(mutex());
static const int kThreadNameLength = 16; // prctl(PR_SET_NAME) limit
char mThreadName[kThreadNameLength]; // guaranteed NUL-terminated
- sp<os::IPowerManager> mPowerManager;
- sp<IBinder> mWakeLockToken;
+ sp<os::IPowerManager> mPowerManager GUARDED_BY(mutex());
+ sp<IBinder> mWakeLockToken GUARDED_BY(mutex());
const sp<PMDeathRecipient> mDeathRecipient;
// list of suspended effects per session and per type. The first (outer) vector is
// keyed by session ID, the second (inner) by type UUID timeLow field
@@ -653,27 +692,31 @@
static const size_t kLogSize = 4 * 1024;
sp<NBLog::Writer> mNBLogWriter;
bool mSystemReady;
- ExtendedTimestamp mTimestamp;
- TimestampVerifier< // For timestamp statistics.
- int64_t /* frame count */, int64_t /* time ns */> mTimestampVerifier;
+
+ // NO_THREAD_SAFETY_ANALYSIS - mTimestamp and mTimestampVerifier should be
+ // accessed under mutex for the RecordThread.
+ ExtendedTimestamp mTimestamp;
+ TimestampVerifier<int64_t /* frame count */, int64_t /* time ns */> mTimestampVerifier;
// DIRECT and OFFLOAD threads should reset frame count to zero on stop/flush
// TODO: add confirmation checks:
// 1) DIRECT threads and linear PCM format really resets to 0?
// 2) Is frame count really valid if not linear pcm?
// 3) Are all 64 bits of position returned, not just lowest 32 bits?
// Timestamp corrected device should be a single device.
- audio_devices_t mTimestampCorrectedDevice = AUDIO_DEVICE_NONE;
+
+ audio_devices_t mTimestampCorrectedDevice = AUDIO_DEVICE_NONE; // CONST set in ctor
// ThreadLoop statistics per iteration.
- int64_t mLastIoBeginNs = -1;
- int64_t mLastIoEndNs = -1;
+ std::atomic<int64_t> mLastIoBeginNs = -1; // set in threadLoop, read by dump()
+ int64_t mLastIoEndNs GUARDED_BY(ThreadBase_ThreadLoop) = -1;
// ThreadSnapshot is thread-safe (internally locked)
mediautils::ThreadSnapshot mThreadSnapshot;
- // This should be read under ThreadBase lock (if not on the threadLoop thread).
- audio_utils::Statistics<double> mIoJitterMs{0.995 /* alpha */};
- audio_utils::Statistics<double> mProcessTimeMs{0.995 /* alpha */};
+ audio_utils::Statistics<double> mIoJitterMs GUARDED_BY(mutex()) {0.995 /* alpha */};
+ audio_utils::Statistics<double> mProcessTimeMs GUARDED_BY(mutex()) {0.995 /* alpha */};
+
+ // NO_THREAD_SAFETY_ANALYSIS GUARDED_BY(mutex())
audio_utils::Statistics<double> mLatencyMs{0.995 /* alpha */};
audio_utils::Statistics<double> mMonopipePipeDepthStats{0.999 /* alpha */};
@@ -759,7 +802,8 @@
// ThreadBase thread.
void clear();
// periodically called in the threadLoop() to update power state uids.
- void updatePowerState(const sp<ThreadBase>& thread, bool force = false);
+ void updatePowerState_l(const sp<ThreadBase>& thread, bool force = false)
+ REQUIRES(audio_utils::ThreadBase_Mutex);
/** @return true if one or move active tracks was added or removed since the
* last time this function was called or the vector was created.
@@ -792,11 +836,11 @@
bool mHasChanged = false;
};
- SimpleLog mLocalLog;
+ SimpleLog mLocalLog; // locked internally
private:
- void dumpBase_l(int fd, const Vector<String16>& args);
- void dumpEffectChains_l(int fd, const Vector<String16>& args);
+ void dumpBase_l(int fd, const Vector<String16>& args) REQUIRES(mutex());
+ void dumpEffectChains_l(int fd, const Vector<String16>& args) REQUIRES(mutex());
};
// --- PlaybackThread ---
@@ -829,35 +873,38 @@
~PlaybackThread() override;
// Thread virtuals
- bool threadLoop() final;
+ bool threadLoop() final REQUIRES(ThreadBase_ThreadLoop) EXCLUDES_ThreadBase_Mutex;
// RefBase
void onFirstRef() override;
status_t checkEffectCompatibility_l(
- const effect_descriptor_t* desc, audio_session_t sessionId) final;
+ const effect_descriptor_t* desc, audio_session_t sessionId) final REQUIRES(mutex());
- void addOutputTrack_l(const sp<IAfTrack>& track) final {
+ void addOutputTrack_l(const sp<IAfTrack>& track) final REQUIRES(mutex()) {
mTracks.add(track);
}
protected:
// Code snippets that were lifted up out of threadLoop()
- virtual void threadLoop_mix() = 0;
- virtual void threadLoop_sleepTime() = 0;
- virtual ssize_t threadLoop_write();
- virtual void threadLoop_drain();
- virtual void threadLoop_standby();
- virtual void threadLoop_exit();
- virtual void threadLoop_removeTracks(const Vector<sp<IAfTrack>>& tracksToRemove);
+ virtual void threadLoop_mix() REQUIRES(ThreadBase_ThreadLoop) = 0;
+ virtual void threadLoop_sleepTime() REQUIRES(ThreadBase_ThreadLoop) = 0;
+ virtual ssize_t threadLoop_write() REQUIRES(ThreadBase_ThreadLoop);
+ virtual void threadLoop_drain() REQUIRES(ThreadBase_ThreadLoop);
+ virtual void threadLoop_standby() REQUIRES(ThreadBase_ThreadLoop);
+ virtual void threadLoop_exit() REQUIRES(ThreadBase_ThreadLoop);
+ virtual void threadLoop_removeTracks(const Vector<sp<IAfTrack>>& tracksToRemove)
+ REQUIRES(ThreadBase_ThreadLoop);
// prepareTracks_l reads and writes mActiveTracks, and returns
// the pending set of tracks to remove via Vector 'tracksToRemove'. The caller
// is responsible for clearing or destroying this Vector later on, when it
// is safe to do so. That will drop the final ref count and destroy the tracks.
- virtual mixer_state prepareTracks_l(Vector<sp<IAfTrack>>* tracksToRemove) = 0;
- void removeTracks_l(const Vector<sp<IAfTrack>>& tracksToRemove);
- status_t handleVoipVolume_l(float *volume);
+ virtual mixer_state prepareTracks_l(Vector<sp<IAfTrack>>* tracksToRemove)
+ REQUIRES(mutex(), ThreadBase_ThreadLoop) = 0;
+
+ void removeTracks_l(const Vector<sp<IAfTrack>>& tracksToRemove) REQUIRES(mutex());
+ status_t handleVoipVolume_l(float *volume) REQUIRES(mutex());
// StreamOutHalInterfaceCallback implementation
virtual void onWriteReady();
@@ -870,9 +917,9 @@
protected:
virtual bool waitingAsyncCallback();
- virtual bool waitingAsyncCallback_l();
- virtual bool shouldStandby_l();
- virtual void onAddNewTrack_l();
+ virtual bool waitingAsyncCallback_l() REQUIRES(mutex());
+ virtual bool shouldStandby_l() REQUIRES(mutex(), ThreadBase_ThreadLoop);
+ virtual void onAddNewTrack_l() REQUIRES(mutex());
public: // AsyncCallbackThread
void onAsyncError(); // error reported by AsyncCallbackThread
protected:
@@ -881,20 +928,21 @@
const std::basic_string<uint8_t>& metadataBs) final;
// ThreadBase virtuals
- virtual void preExit();
+ void preExit() final EXCLUDES_ThreadBase_Mutex;
virtual bool keepWakeLock() const { return true; }
- virtual void acquireWakeLock_l() {
+ virtual void acquireWakeLock_l() REQUIRES(mutex()) {
ThreadBase::acquireWakeLock_l();
- mActiveTracks.updatePowerState(this, true /* force */);
+ mActiveTracks.updatePowerState_l(this, true /* force */);
}
- virtual void checkOutputStageEffects() {}
+ virtual void checkOutputStageEffects()
+ REQUIRES(ThreadBase_ThreadLoop) EXCLUDES_ThreadBase_Mutex {}
virtual void setHalLatencyMode_l() {}
- void dumpInternals_l(int fd, const Vector<String16>& args) override;
- void dumpTracks_l(int fd, const Vector<String16>& args) final;
+ void dumpInternals_l(int fd, const Vector<String16>& args) override REQUIRES(mutex());
+ void dumpTracks_l(int fd, const Vector<String16>& args) final REQUIRES(mutex());
public:
@@ -903,15 +951,15 @@
// return estimated latency in milliseconds, as reported by HAL
uint32_t latency() const final;
// same, but lock must already be held
- uint32_t latency_l() const final;
+ uint32_t latency_l() const final /* REQUIRES(mutex()) */; // NO_THREAD_SAFETY_ANALYSIS
// VolumeInterface
void setMasterVolume(float value) final;
- void setMasterBalance(float balance) override;
+ void setMasterBalance(float balance) override EXCLUDES_ThreadBase_Mutex;
void setMasterMute(bool muted) final;
- void setStreamVolume(audio_stream_type_t stream, float value) final;
- void setStreamMute(audio_stream_type_t stream, bool muted) final;
- float streamVolume(audio_stream_type_t stream) const final;
+ void setStreamVolume(audio_stream_type_t stream, float value) final EXCLUDES_ThreadBase_Mutex;
+ void setStreamMute(audio_stream_type_t stream, bool muted) final EXCLUDES_ThreadBase_Mutex;
+ float streamVolume(audio_stream_type_t stream) const final EXCLUDES_ThreadBase_Mutex;
void setVolumeForOutput_l(float left, float right) const final;
sp<IAfTrack> createTrack_l(
@@ -936,62 +984,79 @@
const sp<media::IAudioTrackCallback>& callback,
bool isSpatialized,
bool isBitPerfect,
- audio_output_flags_t* afTrackFlags) final;
+ audio_output_flags_t* afTrackFlags) final
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
bool isTrackActive(const sp<IAfTrack>& track) const final {
return mActiveTracks.indexOf(track) >= 0;
}
- AudioStreamOut* getOutput_l() const final { return mOutput; }
- AudioStreamOut* getOutput() const final;
- AudioStreamOut* clearOutput() final;
+ AudioStreamOut* getOutput_l() const final REQUIRES(mutex()) { return mOutput; }
+ AudioStreamOut* getOutput() const final EXCLUDES_ThreadBase_Mutex;
+ AudioStreamOut* clearOutput() final EXCLUDES_ThreadBase_Mutex;
+
+ // NO_THREAD_SAFETY_ANALYSIS -- probably needs a lock.
sp<StreamHalInterface> stream() const final;
- // a very large number of suspend() will eventually wraparound, but unlikely
- void suspend() final { (void) android_atomic_inc(&mSuspended); }
- void restore() final
- {
- // if restore() is done without suspend(), get back into
- // range so that the next suspend() will operate correctly
- if (android_atomic_dec(&mSuspended) <= 0) {
- android_atomic_release_store(0, &mSuspended);
- }
- }
- bool isSuspended() const final
- { return android_atomic_acquire_load(&mSuspended) > 0; }
+ // suspend(), restore(), and isSuspended() are implemented atomically.
+ void suspend() final { ++mSuspended; }
+ void restore() final {
+ // if restore() is done without suspend(), get back into
+ // range so that the next suspend() will operate correctly
+ while (true) {
+ int32_t suspended = mSuspended;
+ if (suspended <= 0) {
+ ALOGW("%s: invalid mSuspended %d <= 0", __func__, suspended);
+ return;
+ }
+ const int32_t desired = suspended - 1;
+ if (mSuspended.compare_exchange_weak(suspended, desired)) return;
+ }
+ }
+ bool isSuspended() const final { return mSuspended > 0; }
- String8 getParameters(const String8& keys);
- void ioConfigChanged(audio_io_config_event_t event, pid_t pid = 0,
+ String8 getParameters(const String8& keys) EXCLUDES_ThreadBase_Mutex;
+
+ // Hold either the AudioFlinger::mutex or the ThreadBase::mutex
+ void ioConfigChanged_l(audio_io_config_event_t event, pid_t pid = 0,
audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE) final;
- status_t getRenderPosition(uint32_t* halFrames, uint32_t* dspFrames) const final;
+ status_t getRenderPosition(uint32_t* halFrames, uint32_t* dspFrames) const final
+ EXCLUDES_ThreadBase_Mutex;
// Consider also removing and passing an explicit mMainBuffer initialization
// parameter to AF::IAfTrack::Track().
float* sinkBuffer() const final {
return reinterpret_cast<float *>(mSinkBuffer); };
- void detachAuxEffect_l(int effectId) final;
+ void detachAuxEffect_l(int effectId) final REQUIRES(mutex());
- status_t attachAuxEffect(const sp<IAfTrack>& track, int EffectId) final;
- status_t attachAuxEffect_l(const sp<IAfTrack>& track, int EffectId) final;
+ status_t attachAuxEffect(const sp<IAfTrack>& track, int EffectId) final
+ EXCLUDES_ThreadBase_Mutex;
+ status_t attachAuxEffect_l(const sp<IAfTrack>& track, int EffectId) final REQUIRES(mutex());
- status_t addEffectChain_l(const sp<IAfEffectChain>& chain) final;
- size_t removeEffectChain_l(const sp<IAfEffectChain>& chain) final;
- uint32_t hasAudioSession_l(audio_session_t sessionId) const final {
+ status_t addEffectChain_l(const sp<IAfEffectChain>& chain) final REQUIRES(mutex());
+ size_t removeEffectChain_l(const sp<IAfEffectChain>& chain) final REQUIRES(mutex());
+ uint32_t hasAudioSession_l(audio_session_t sessionId) const final REQUIRES(mutex()) {
return ThreadBase::hasAudioSession_l(sessionId, mTracks);
}
- product_strategy_t getStrategyForSession_l(audio_session_t sessionId) const final;
+ product_strategy_t getStrategyForSession_l(audio_session_t sessionId) const final
+ REQUIRES(mutex());
- status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event) final;
+ status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event) final
+ EXCLUDES_ThreadBase_Mutex;
+ // could be static.
bool isValidSyncEvent(const sp<audioflinger::SyncEvent>& event) const final;
- // called with AudioFlinger lock held
- bool invalidateTracks_l(audio_stream_type_t streamType) final;
- bool invalidateTracks_l(std::set<audio_port_handle_t>& portIds) final;
+ // Does this require the AudioFlinger mutex as well?
+ bool invalidateTracks_l(audio_stream_type_t streamType) final
+ REQUIRES(mutex());
+ bool invalidateTracks_l(std::set<audio_port_handle_t>& portIds) final
+ REQUIRES(mutex());
void invalidateTracks(audio_stream_type_t streamType) override;
// Invalidate tracks by a set of port ids. The port id will be removed from
// the given set if the corresponding track is found and invalidated.
- void invalidateTracks(std::set<audio_port_handle_t>& portIds) override;
+ void invalidateTracks(std::set<audio_port_handle_t>& portIds) override
+ EXCLUDES_ThreadBase_Mutex;
size_t frameCount() const final { return mNormalFrameCount; }
@@ -999,30 +1064,33 @@
return mMixerChannelMask;
}
- status_t getTimestamp_l(AudioTimestamp& timestamp) final;
+ status_t getTimestamp_l(AudioTimestamp& timestamp) final
+ REQUIRES(mutex(), ThreadBase_ThreadLoop);
- void addPatchTrack(const sp<IAfPatchTrack>& track) final;
- void deletePatchTrack(const sp<IAfPatchTrack>& track) final;
+ void addPatchTrack(const sp<IAfPatchTrack>& track) final EXCLUDES_ThreadBase_Mutex;
+ void deletePatchTrack(const sp<IAfPatchTrack>& track) final EXCLUDES_ThreadBase_Mutex;
+ // NO_THREAD_SAFETY_ANALYSIS - fix this to use atomics.
void toAudioPortConfig(struct audio_port_config* config) final;
// Return the asynchronous signal wait time.
- int64_t computeWaitTimeNs_l() const override { return INT64_MAX; }
+ int64_t computeWaitTimeNs_l() const override REQUIRES(mutex()) { return INT64_MAX; }
// returns true if the track is allowed to be added to the thread.
bool isTrackAllowed_l(
audio_channel_mask_t channelMask __unused,
audio_format_t format __unused,
audio_session_t sessionId __unused,
- uid_t uid) const override {
+ uid_t uid) const override REQUIRES(mutex()) {
return trackCountForUid_l(uid) < PlaybackThread::kMaxTracksPerUid
&& mTracks.size() < PlaybackThread::kMaxTracks;
}
- bool isTimestampCorrectionEnabled() const final {
- return audio_is_output_devices(mTimestampCorrectedDevice)
- && outDeviceTypes().count(mTimestampCorrectedDevice) != 0;
+ bool isTimestampCorrectionEnabled_l() const final REQUIRES(mutex()) {
+ return audio_is_output_devices(mTimestampCorrectedDevice)
+ && outDeviceTypes_l().count(mTimestampCorrectedDevice) != 0;
}
+ // NO_THREAD_SAFETY_ANALYSIS - fix this to be atomic.
bool isStreamInitialized() const final {
return !(mOutput == nullptr || mOutput->stream == nullptr);
}
@@ -1039,12 +1107,12 @@
return (mHapticChannelMask & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE;
}
- void setDownStreamPatch(const struct audio_patch* patch) final {
- Mutex::Autolock _l(mLock);
+ void setDownStreamPatch(const struct audio_patch* patch) final EXCLUDES_ThreadBase_Mutex {
+ audio_utils::lock_guard _l(mutex());
mDownStreamPatch = *patch;
}
- IAfTrack* getTrackById_l(audio_port_handle_t trackId) final;
+ IAfTrack* getTrackById_l(audio_port_handle_t trackId) final REQUIRES(mutex());
bool hasMixer() const final {
return mType == MIXER || mType == DUPLICATING || mType == SPATIALIZER;
@@ -1062,23 +1130,25 @@
return INVALID_OPERATION;
}
- void startMelComputation_l(const sp<audio_utils::MelProcessor>& processor) override;
- void stopMelComputation_l() override;
+ void startMelComputation_l(const sp<audio_utils::MelProcessor>& processor) override
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
+ void stopMelComputation_l() override
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
- void setStandby() final {
- Mutex::Autolock _l(mLock);
+ void setStandby() final EXCLUDES_ThreadBase_Mutex {
+ audio_utils::lock_guard _l(mutex());
setStandby_l();
}
- void setStandby_l() final {
+ void setStandby_l() final REQUIRES(mutex()) {
mStandby = true;
mHalStarted = false;
mKernelPositionOnStandby =
mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL];
}
- bool waitForHalStart() final {
- Mutex::Autolock _l(mLock);
+ bool waitForHalStart() final EXCLUDES_ThreadBase_Mutex {
+ audio_utils::unique_lock _l(mutex());
static const nsecs_t kWaitHalTimeoutNs = seconds(2);
nsecs_t endWaitTimetNs = systemTime() + kWaitHalTimeoutNs;
while (!mHalStarted) {
@@ -1087,7 +1157,7 @@
break;
}
nsecs_t waitTimeLeftNs = endWaitTimetNs - timeNs;
- mWaitHalStartCV.waitRelative(mLock, waitTimeLeftNs);
+ mWaitHalStartCV.wait_for(_l, std::chrono::nanoseconds(waitTimeLeftNs));
}
return mHalStarted;
}
@@ -1095,10 +1165,17 @@
// updated by readOutputParameters_l()
size_t mNormalFrameCount; // normal mixer and effects
- bool mThreadThrottle; // throttle the thread processing
- uint32_t mThreadThrottleTimeMs; // throttle time for MIXER threads
- uint32_t mThreadThrottleEndMs; // notify once per throttling
- uint32_t mHalfBufferMs; // half the buffer size in milliseconds
+ // throttle the thread processing
+ bool mThreadThrottle GUARDED_BY(ThreadBase_ThreadLoop);
+
+ // throttle time for MIXER threads - atomic as read by dump()
+ std::atomic<uint32_t> mThreadThrottleTimeMs;
+
+ // notify once per throttling
+ uint32_t mThreadThrottleEndMs GUARDED_BY(ThreadBase_ThreadLoop);
+
+ // half the buffer size in milliseconds
+ uint32_t mHalfBufferMs GUARDED_BY(ThreadBase_ThreadLoop);
void* mSinkBuffer; // frame size aligned sink buffer
@@ -1118,21 +1195,21 @@
// buffer before downmixing or data conversion to the sink buffer.
// Set to "true" to enable the Mixer Buffer otherwise mixer output goes to sink buffer.
- bool mMixerBufferEnabled;
+ bool mMixerBufferEnabled GUARDED_BY(ThreadBase_ThreadLoop);
// Storage, 32 byte aligned (may make this alignment a requirement later).
// Due to constraints on mNormalFrameCount, the buffer size is a multiple of 16 frames.
- void* mMixerBuffer;
+ void* mMixerBuffer GUARDED_BY(ThreadBase_ThreadLoop);
// Size of mMixerBuffer in bytes: mNormalFrameCount * #channels * sampsize.
- size_t mMixerBufferSize;
+ size_t mMixerBufferSize GUARDED_BY(ThreadBase_ThreadLoop);
// The audio format of mMixerBuffer. Set to AUDIO_FORMAT_PCM_(FLOAT|16_BIT) only.
- audio_format_t mMixerBufferFormat;
+ audio_format_t mMixerBufferFormat GUARDED_BY(ThreadBase_ThreadLoop);
// An internal flag set to true by MixerThread::prepareTracks_l()
// when mMixerBuffer contains valid data after mixing.
- bool mMixerBufferValid;
+ bool mMixerBufferValid GUARDED_BY(ThreadBase_ThreadLoop);
// Effects Buffer (mEffectsBuffer*)
//
@@ -1141,46 +1218,49 @@
// to the sink buffer.
// Set to "true" to enable the Effects Buffer otherwise effects output goes to sink buffer.
- bool mEffectBufferEnabled;
+ bool mEffectBufferEnabled;
+ // NO_THREAD_SAFETY_ANALYSIS: Spatializer access this in addEffectChain_l()
// Storage, 32 byte aligned (may make this alignment a requirement later).
// Due to constraints on mNormalFrameCount, the buffer size is a multiple of 16 frames.
- void* mEffectBuffer;
+ void* mEffectBuffer;
+ // NO_THREAD_SAFETY_ANALYSIS: Spatializer access this in addEffectChain_l()
// Size of mEffectsBuffer in bytes: mNormalFrameCount * #channels * sampsize.
- size_t mEffectBufferSize;
+ size_t mEffectBufferSize;
+ // NO_THREAD_SAFETY_ANALYSIS: Spatializer access this in addEffectChain_l()
// The audio format of mEffectsBuffer. Set to AUDIO_FORMAT_PCM_16_BIT only.
- audio_format_t mEffectBufferFormat;
+ // NO_THREAD_SAFETY_ANALYSIS: Spatializer access this in addEffectChain_l()
+ audio_format_t mEffectBufferFormat;
// An internal flag set to true by MixerThread::prepareTracks_l()
// when mEffectsBuffer contains valid data after mixing.
//
// When this is set, all mixer data is routed into the effects buffer
// for any processing (including output processing).
- bool mEffectBufferValid;
+ bool mEffectBufferValid GUARDED_BY(ThreadBase_ThreadLoop);
// Set to "true" to enable when data has already copied to sink
- bool mHasDataCopiedToSinkBuffer = false;
+ bool mHasDataCopiedToSinkBuffer GUARDED_BY(ThreadBase_ThreadLoop) = false;
// Frame size aligned buffer used as input and output to all post processing effects
// except the Spatializer in a SPATIALIZER thread. Non spatialized tracks are mixed into
// this buffer so that post processing effects can be applied.
- void* mPostSpatializerBuffer = nullptr;
+ void* mPostSpatializerBuffer GUARDED_BY(mutex()) = nullptr;
// Size of mPostSpatializerBuffer in bytes
- size_t mPostSpatializerBufferSize;
-
+ size_t mPostSpatializerBufferSize GUARDED_BY(mutex());
// suspend count, > 0 means suspended. While suspended, the thread continues to pull from
// tracks and mix, but doesn't write to HAL. A2DP and SCO HAL implementations can't handle
// concurrent use of both of them, so Audio Policy Service suspends one of the threads to
// workaround that restriction.
// 'volatile' means accessed via atomic operations and no lock.
- volatile int32_t mSuspended;
+ std::atomic<int32_t> mSuspended;
int64_t mBytesWritten;
- std::atomic<int64_t> mFramesWritten; // not reset on standby
+ std::atomic<int64_t> mFramesWritten; // not reset on standby
int64_t mLastFramesWritten = -1; // track changes in timestamp
// server frames written.
int64_t mSuspendedFrames; // not reset on standby
@@ -1195,8 +1275,8 @@
// mMasterMute is in both PlaybackThread and in AudioFlinger. When a
// PlaybackThread needs to find out if master-muted, it checks it's local
// copy rather than the one in AudioFlinger. This optimization saves a lock.
- bool mMasterMute;
- void setMasterMute_l(bool muted) { mMasterMute = muted; }
+ bool mMasterMute GUARDED_BY(mutex());
+ void setMasterMute_l(bool muted) REQUIRES(mutex()) { mMasterMute = muted; }
auto discontinuityForStandbyOrFlush() const { // call on threadLoop or with lock.
return ((mType == DIRECT && !audio_is_linear_pcm(mFormat))
@@ -1215,24 +1295,28 @@
// No sleep in standby mode; waits on a condition
// Code snippets that are temporarily lifted up out of threadLoop() until the merge
- virtual void checkSilentMode_l() final; // consider unification with MMapThread
+
+ // consider unification with MMapThread
+ virtual void checkSilentMode_l() final REQUIRES(mutex());
// Non-trivial for DUPLICATING only
- virtual void saveOutputTracks() { }
- virtual void clearOutputTracks() { }
+ virtual void saveOutputTracks() REQUIRES(ThreadBase_ThreadLoop) {}
+ virtual void clearOutputTracks() REQUIRES(ThreadBase_ThreadLoop) {}
// Cache various calculated values, at threadLoop() entry and after a parameter change
- virtual void cacheParameters_l();
+ virtual void cacheParameters_l() REQUIRES(mutex(), ThreadBase_ThreadLoop);
void setCheckOutputStageEffects() override {
mCheckOutputStageEffects.store(true);
}
- virtual uint32_t correctLatency_l(uint32_t latency) const;
+ virtual uint32_t correctLatency_l(uint32_t latency) const REQUIRES(mutex());
virtual status_t createAudioPatch_l(const struct audio_patch *patch,
- audio_patch_handle_t *handle);
- virtual status_t releaseAudioPatch_l(const audio_patch_handle_t handle);
+ audio_patch_handle_t *handle) REQUIRES(mutex());
+ virtual status_t releaseAudioPatch_l(const audio_patch_handle_t handle)
+ REQUIRES(mutex());
+ // NO_THREAD_SAFETY_ANALYSIS - fix this to use atomics
bool usesHwAvSync() const final { return mType == DIRECT && mOutput != nullptr
&& mHwSupportsPause
&& (mOutput->flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC); }
@@ -1240,22 +1324,23 @@
uint32_t trackCountForUid_l(uid_t uid) const;
void invalidateTracksForAudioSession_l(
- audio_session_t sessionId) const override {
+ audio_session_t sessionId) const override REQUIRES(mutex()) {
ThreadBase::invalidateTracksForAudioSession_l(sessionId, mTracks);
}
DISALLOW_COPY_AND_ASSIGN(PlaybackThread);
- status_t addTrack_l(const sp<IAfTrack>& track) final;
- bool destroyTrack_l(const sp<IAfTrack>& track) final;
+ status_t addTrack_l(const sp<IAfTrack>& track) final REQUIRES(mutex());
+ bool destroyTrack_l(const sp<IAfTrack>& track) final REQUIRES(mutex());
- void removeTrack_l(const sp<IAfTrack>& track);
+ void removeTrack_l(const sp<IAfTrack>& track) REQUIRES(mutex());
- void readOutputParameters_l();
- MetadataUpdate updateMetadata_l() final;
- virtual void sendMetadataToBackend_l(const StreamOutHalInterface::SourceMetadata& metadata);
+ void readOutputParameters_l() REQUIRES(mutex());
+ MetadataUpdate updateMetadata_l() final REQUIRES(mutex());
+ virtual void sendMetadataToBackend_l(const StreamOutHalInterface::SourceMetadata& metadata)
+ REQUIRES(mutex()) ;
- void collectTimestamps_l();
+ void collectTimestamps_l() REQUIRES(mutex(), ThreadBase_ThreadLoop);
// The Tracks class manages tracks added and removed from the Thread.
template <typename T>
@@ -1331,17 +1416,17 @@
uint32_t mSleepTimeUs;
// mixer status returned by prepareTracks_l()
- mixer_state mMixerStatus; // current cycle
+ mixer_state mMixerStatus GUARDED_BY(ThreadBase_ThreadLoop); // current cycle
// previous cycle when in prepareTracks_l()
- mixer_state mMixerStatusIgnoringFastTracks;
+ mixer_state mMixerStatusIgnoringFastTracks GUARDED_BY(ThreadBase_ThreadLoop);
// FIXME or a separate ready state per track
// FIXME move these declarations into the specific sub-class that needs them
// MIXER only
- uint32_t sleepTimeShift;
+ uint32_t sleepTimeShift GUARDED_BY(ThreadBase_ThreadLoop);
// same as AudioFlinger::mStandbyTimeInNsecs except for DIRECT which uses a shorter value
- nsecs_t mStandbyDelayNs;
+ nsecs_t mStandbyDelayNs; // GUARDED_BY(mutex());
// MIXER only
nsecs_t maxPeriod;
@@ -1349,8 +1434,8 @@
// DUPLICATING only
uint32_t writeFrames;
- size_t mBytesRemaining;
- size_t mCurrentWriteLength;
+ size_t mBytesRemaining GUARDED_BY(ThreadBase_ThreadLoop);
+ size_t mCurrentWriteLength GUARDED_BY(ThreadBase_ThreadLoop);
bool mUseAsyncWrite;
// mWriteAckSequence contains current write sequence on bits 31-1. The write sequence is
// incremented each time a write(), a flush() or a standby() occurs.
@@ -1368,7 +1453,8 @@
sp<AsyncCallbackThread> mCallbackThread;
- Mutex mAudioTrackCbLock;
+ audio_utils::mutex& audioTrackCbMutex() const { return mAudioTrackCbMutex; }
+ mutable audio_utils::mutex mAudioTrackCbMutex;
// Record of IAudioTrackCallback
std::map<sp<IAfTrack>, sp<media::IAudioTrackCallback>> mAudioTrackCallbacks;
@@ -1389,7 +1475,7 @@
// output stream start detection based on render position returned by the kernel
// condition signalled when the output stream has started
- Condition mWaitHalStartCV;
+ audio_utils::condition_variable mWaitHalStartCV;
// true when the output stream render position has moved, reset to false in standby
bool mHalStarted = false;
// last kernel render position saved when entering standby
@@ -1402,7 +1488,7 @@
protected:
// accessed by both binder threads and within threadLoop(), lock on mutex needed
- uint32_t& fastTrackAvailMask_l() final { return mFastTrackAvailMask; }
+ uint32_t& fastTrackAvailMask_l() final REQUIRES(mutex()) { return mFastTrackAvailMask; }
uint32_t mFastTrackAvailMask; // bit i set if fast track [i] is available
bool mHwSupportsPause;
bool mHwPaused;
@@ -1471,18 +1557,20 @@
// Thread virtuals
- bool checkForNewParameter_l(const String8& keyValuePair, status_t& status) final;
+ bool checkForNewParameter_l(const String8& keyValuePair, status_t& status) final
+ REQUIRES(mutex());
bool isTrackAllowed_l(
audio_channel_mask_t channelMask, audio_format_t format,
- audio_session_t sessionId, uid_t uid) const final;
+ audio_session_t sessionId, uid_t uid) const final REQUIRES(mutex());
protected:
- mixer_state prepareTracks_l(Vector<sp<IAfTrack>>* tracksToRemove) override;
+ mixer_state prepareTracks_l(Vector<sp<IAfTrack>>* tracksToRemove) override
+ REQUIRES(mutex(), ThreadBase_ThreadLoop);
uint32_t idleSleepTimeUs() const final;
uint32_t suspendSleepTimeUs() const final;
- void cacheParameters_l() override;
+ void cacheParameters_l() override REQUIRES(mutex(), ThreadBase_ThreadLoop);
- void acquireWakeLock_l() final {
+ void acquireWakeLock_l() final REQUIRES(mutex()) {
PlaybackThread::acquireWakeLock_l();
if (hasFastMixer()) {
mFastMixer->setBoottimeOffset(
@@ -1490,18 +1578,19 @@
}
}
- void dumpInternals_l(int fd, const Vector<String16>& args) override;
+ void dumpInternals_l(int fd, const Vector<String16>& args) override REQUIRES(mutex());
// threadLoop snippets
- ssize_t threadLoop_write() override;
- void threadLoop_standby() override;
- void threadLoop_mix() override;
- void threadLoop_sleepTime() override;
- uint32_t correctLatency_l(uint32_t latency) const final;
+ ssize_t threadLoop_write() override REQUIRES(ThreadBase_ThreadLoop);
+ void threadLoop_standby() override REQUIRES(ThreadBase_ThreadLoop);
+ void threadLoop_mix() override REQUIRES(ThreadBase_ThreadLoop);
+ void threadLoop_sleepTime() override REQUIRES(ThreadBase_ThreadLoop);
+ uint32_t correctLatency_l(uint32_t latency) const final REQUIRES(mutex());
status_t createAudioPatch_l(
- const struct audio_patch* patch, audio_patch_handle_t* handle) final;
- status_t releaseAudioPatch_l(const audio_patch_handle_t handle) final;
+ const struct audio_patch* patch, audio_patch_handle_t* handle)
+ final REQUIRES(mutex());
+ status_t releaseAudioPatch_l(const audio_patch_handle_t handle) final REQUIRES(mutex());
AudioMixer* mAudioMixer; // normal mixer
@@ -1530,7 +1619,7 @@
// accessible only within the threadLoop(), no locks required
// mFastMixer->sq() // for mutating and pushing state
- int32_t mFastMixerFutex; // for cold idle
+ int32_t mFastMixerFutex GUARDED_BY(ThreadBase_ThreadLoop); // for cold idle
std::atomic_bool mMasterMono;
public:
@@ -1540,8 +1629,9 @@
return mFastMixerDumpState.mTracks[fastIndex].mUnderruns;
}
- status_t threadloop_getHalTimestamp_l(
- ExtendedTimestamp *timestamp) const override {
+ status_t threadloop_getHalTimestamp_l(
+ ExtendedTimestamp *timestamp) const override
+ REQUIRES(mutex(), ThreadBase_ThreadLoop) {
if (mNormalSink.get() != nullptr) {
return mNormalSink->getTimestamp(*timestamp);
}
@@ -1565,16 +1655,16 @@
// and blending without limiter is idempotent but inefficient to do twice.
virtual bool requireMonoBlend() { return mMasterMono.load() && !hasFastMixer(); }
- void setMasterBalance(float balance) override {
+ void setMasterBalance(float balance) override EXCLUDES_ThreadBase_Mutex {
mMasterBalance.store(balance);
if (hasFastMixer()) {
mFastMixer->setMasterBalance(balance);
}
}
- void updateHalSupportedLatencyModes_l();
- void onHalLatencyModesChanged_l() override;
- void setHalLatencyMode_l() override;
+ void updateHalSupportedLatencyModes_l() REQUIRES(mutex());
+ void onHalLatencyModesChanged_l() override REQUIRES(mutex());
+ void setHalLatencyMode_l() override REQUIRES(mutex());
};
class DirectOutputThread : public PlaybackThread, public virtual IAfDirectOutputThread {
@@ -1589,35 +1679,36 @@
const audio_offload_info_t& offloadInfo)
: DirectOutputThread(afThreadCallback, output, id, DIRECT, systemReady, offloadInfo) { }
- virtual ~DirectOutputThread();
+ ~DirectOutputThread() override;
status_t selectPresentation(int presentationId, int programId) final;
// Thread virtuals
virtual bool checkForNewParameter_l(const String8& keyValuePair,
- status_t& status);
+ status_t& status) REQUIRES(mutex());
- void flushHw_l() override;
+ void flushHw_l() override REQUIRES(mutex(), ThreadBase_ThreadLoop);
- void setMasterBalance(float balance) override;
+ void setMasterBalance(float balance) override EXCLUDES_ThreadBase_Mutex;
protected:
virtual uint32_t activeSleepTimeUs() const;
virtual uint32_t idleSleepTimeUs() const;
virtual uint32_t suspendSleepTimeUs() const;
- virtual void cacheParameters_l();
+ virtual void cacheParameters_l() REQUIRES(mutex(), ThreadBase_ThreadLoop);
- void dumpInternals_l(int fd, const Vector<String16>& args) override;
+ void dumpInternals_l(int fd, const Vector<String16>& args) override REQUIRES(mutex());
// threadLoop snippets
- virtual mixer_state prepareTracks_l(Vector<sp<IAfTrack>>* tracksToRemove);
- virtual void threadLoop_mix();
- virtual void threadLoop_sleepTime();
- virtual void threadLoop_exit();
- virtual bool shouldStandby_l();
+ virtual mixer_state prepareTracks_l(Vector<sp<IAfTrack>>* tracksToRemove)
+ REQUIRES(mutex(), ThreadBase_ThreadLoop);
+ virtual void threadLoop_mix() REQUIRES(ThreadBase_ThreadLoop);
+ virtual void threadLoop_sleepTime() REQUIRES(ThreadBase_ThreadLoop);
+ virtual void threadLoop_exit() REQUIRES(ThreadBase_ThreadLoop);
+ virtual bool shouldStandby_l() REQUIRES(mutex());
- virtual void onAddNewTrack_l();
+ virtual void onAddNewTrack_l() REQUIRES(mutex());
const audio_offload_info_t mOffloadInfo;
@@ -1627,7 +1718,7 @@
DirectOutputThread(const sp<IAfThreadCallback>& afThreadCallback, AudioStreamOut* output,
audio_io_handle_t id, ThreadBase::type_t type, bool systemReady,
const audio_offload_info_t& offloadInfo);
- void processVolume_l(IAfTrack *track, bool lastTrack);
+ void processVolume_l(IAfTrack *track, bool lastTrack) REQUIRES(mutex());
bool isTunerStream() const { return (mOffloadInfo.content_id > 0); }
// prepareTracks_l() tells threadLoop_mix() the name of the single active track
@@ -1642,7 +1733,7 @@
public:
virtual bool hasFastMixer() const { return false; }
- virtual int64_t computeWaitTimeNs_l() const override;
+ virtual int64_t computeWaitTimeNs_l() const override REQUIRES(mutex());
status_t threadloop_getHalTimestamp_l(ExtendedTimestamp *timestamp) const override {
// For DIRECT and OFFLOAD threads, query the output sink directly.
@@ -1669,19 +1760,20 @@
audio_io_handle_t id, bool systemReady,
const audio_offload_info_t& offloadInfo);
virtual ~OffloadThread() {};
- void flushHw_l() override;
+ void flushHw_l() final REQUIRES(mutex(), ThreadBase_ThreadLoop);
protected:
// threadLoop snippets
- virtual mixer_state prepareTracks_l(Vector<sp<IAfTrack>>* tracksToRemove);
- virtual void threadLoop_exit();
+ mixer_state prepareTracks_l(Vector<sp<IAfTrack>>* tracksToRemove) final
+ REQUIRES(mutex(), ThreadBase_ThreadLoop);
+ void threadLoop_exit() final REQUIRES(ThreadBase_ThreadLoop);
- virtual bool waitingAsyncCallback();
- virtual bool waitingAsyncCallback_l();
- virtual void invalidateTracks(audio_stream_type_t streamType);
- void invalidateTracks(std::set<audio_port_handle_t>& portIds) override;
+ bool waitingAsyncCallback() final;
+ bool waitingAsyncCallback_l() final REQUIRES(mutex());
+ void invalidateTracks(audio_stream_type_t streamType) final EXCLUDES_ThreadBase_Mutex;
+ void invalidateTracks(std::set<audio_port_handle_t>& portIds) final EXCLUDES_ThreadBase_Mutex;
- virtual bool keepWakeLock() const { return (mKeepWakeLock || (mDrainSequence & 1)); }
+ bool keepWakeLock() const final { return (mKeepWakeLock || (mDrainSequence & 1)); }
private:
size_t mPausedWriteLength; // length in bytes of write interrupted by pause
@@ -1694,10 +1786,10 @@
explicit AsyncCallbackThread(const wp<PlaybackThread>& playbackThread);
// Thread virtuals
- virtual bool threadLoop();
+ bool threadLoop() final;
// RefBase
- virtual void onFirstRef();
+ void onFirstRef() final;
void exit();
void setWriteBlocked(uint32_t sequence);
@@ -1716,9 +1808,13 @@
// setDraining(). The sequence is shifted one bit to the left and the lsb is used
// to indicate that the callback has been received via resetDraining()
uint32_t mDrainSequence;
- Condition mWaitWorkCV;
- Mutex mLock;
+ audio_utils::condition_variable mWaitWorkCV;
+ mutable audio_utils::mutex mMutex;
bool mAsyncError;
+
+ audio_utils::mutex& mutex() const RETURN_CAPABILITY(audio_utils::AsyncCallbackThread_Mutex) {
+ return mMutex;
+ }
};
class DuplicatingThread : public MixerThread, public IAfDuplicatingThread {
@@ -1733,41 +1829,42 @@
}
// Thread virtuals
- void addOutputTrack(IAfPlaybackThread* thread) final;
- void removeOutputTrack(IAfPlaybackThread* thread) final;
+ void addOutputTrack(IAfPlaybackThread* thread) final EXCLUDES_ThreadBase_Mutex;
+ void removeOutputTrack(IAfPlaybackThread* thread) final EXCLUDES_ThreadBase_Mutex;
uint32_t waitTimeMs() const final { return mWaitTimeMs; }
void sendMetadataToBackend_l(
- const StreamOutHalInterface::SourceMetadata& metadata) override;
+ const StreamOutHalInterface::SourceMetadata& metadata) final REQUIRES(mutex());
protected:
virtual uint32_t activeSleepTimeUs() const;
- void dumpInternals_l(int fd, const Vector<String16>& args) override;
+ void dumpInternals_l(int fd, const Vector<String16>& args) final REQUIRES(mutex());
private:
- bool outputsReady();
+ bool outputsReady() REQUIRES(ThreadBase_ThreadLoop);
protected:
// threadLoop snippets
- virtual void threadLoop_mix();
- virtual void threadLoop_sleepTime();
- virtual ssize_t threadLoop_write();
- virtual void threadLoop_standby();
- virtual void cacheParameters_l();
+ void threadLoop_mix() final REQUIRES(ThreadBase_ThreadLoop);
+ void threadLoop_sleepTime() final REQUIRES(ThreadBase_ThreadLoop);
+ ssize_t threadLoop_write() final REQUIRES(ThreadBase_ThreadLoop);
+ void threadLoop_standby() final REQUIRES(ThreadBase_ThreadLoop);
+ void cacheParameters_l() final REQUIRES(mutex(), ThreadBase_ThreadLoop);
private:
// called from threadLoop, addOutputTrack, removeOutputTrack
- virtual void updateWaitTime_l();
+ void updateWaitTime_l() REQUIRES(mutex());
protected:
- virtual void saveOutputTracks();
- virtual void clearOutputTracks();
+ void saveOutputTracks() final REQUIRES(mutex(), ThreadBase_ThreadLoop);
+ void clearOutputTracks() final REQUIRES(mutex(), ThreadBase_ThreadLoop);
private:
uint32_t mWaitTimeMs;
- SortedVector <sp<IAfOutputTrack>> outputTracks;
- SortedVector <sp<IAfOutputTrack>> mOutputTracks;
+ // NO_THREAD_SAFETY_ANALYSIS GUARDED_BY(ThreadBase_ThreadLoop)
+ SortedVector <sp<IAfOutputTrack>> outputTracks;
+ SortedVector <sp<IAfOutputTrack>> mOutputTracks GUARDED_BY(mutex());
public:
virtual bool hasFastMixer() const { return false; }
status_t threadloop_getHalTimestamp_l(
- ExtendedTimestamp *timestamp) const override {
+ ExtendedTimestamp *timestamp) const override REQUIRES(mutex()) {
if (mOutputTracks.size() > 0) {
// forward the first OutputTrack's kernel information for timestamp.
const ExtendedTimestamp trackTimestamp =
@@ -1797,11 +1894,12 @@
// RefBase
void onFirstRef() final;
- status_t setRequestedLatencyMode(audio_latency_mode_t mode) final;
+ status_t setRequestedLatencyMode(audio_latency_mode_t mode) final EXCLUDES_ThreadBase_Mutex;
protected:
- void checkOutputStageEffects() final;
- void setHalLatencyMode_l() final;
+ void checkOutputStageEffects() final
+ REQUIRES(ThreadBase_ThreadLoop) EXCLUDES_ThreadBase_Mutex;
+ void setHalLatencyMode_l() final REQUIRES(mutex());
private:
// Do not request a specific mode by default
@@ -1827,15 +1925,15 @@
~RecordThread() override;
// no addTrack_l ?
- void destroyTrack_l(const sp<IAfRecordTrack>& track) final;
- void removeTrack_l(const sp<IAfRecordTrack>& track) final;
+ void destroyTrack_l(const sp<IAfRecordTrack>& track) final REQUIRES(mutex());
+ void removeTrack_l(const sp<IAfRecordTrack>& track) final REQUIRES(mutex());
// Thread virtuals
- bool threadLoop() final;
- void preExit() final;
+ bool threadLoop() final REQUIRES(ThreadBase_ThreadLoop) EXCLUDES_ThreadBase_Mutex;
+ void preExit() final EXCLUDES_ThreadBase_Mutex;
// RefBase
- void onFirstRef() final;
+ void onFirstRef() final EXCLUDES_ThreadBase_Mutex;
status_t initCheck() const final { return mInput == nullptr ? NO_INIT : NO_ERROR; }
@@ -1858,15 +1956,16 @@
pid_t tid,
status_t *status /*non-NULL*/,
audio_port_handle_t portId,
- int32_t maxSharedAudioHistoryMs) final;
+ int32_t maxSharedAudioHistoryMs) final
+ REQUIRES(audio_utils::AudioFlinger_Mutex) EXCLUDES_ThreadBase_Mutex;
status_t start(IAfRecordTrack* recordTrack,
AudioSystem::sync_event_t event,
- audio_session_t triggerSession) final;
+ audio_session_t triggerSession) final EXCLUDES_ThreadBase_Mutex;
// ask the thread to stop the specified track, and
// return true if the caller should then do it's part of the stopping process
- bool stop(IAfRecordTrack* recordTrack) final;
+ bool stop(IAfRecordTrack* recordTrack) final EXCLUDES_ThreadBase_Mutex;
AudioStreamIn* getInput() const final { return mInput; }
AudioStreamIn* clearInput() final;
@@ -1874,27 +1973,30 @@
virtual sp<StreamHalInterface> stream() const;
- virtual bool checkForNewParameter_l(const String8& keyValuePair,
- status_t& status);
- virtual void cacheParameters_l() {}
- virtual String8 getParameters(const String8& keys);
- void ioConfigChanged(audio_io_config_event_t event, pid_t pid = 0,
+ virtual bool checkForNewParameter_l(const String8& keyValuePair,
+ status_t& status) REQUIRES(mutex());
+ virtual void cacheParameters_l() REQUIRES(mutex(), ThreadBase_ThreadLoop) {}
+ virtual String8 getParameters(const String8& keys) EXCLUDES_ThreadBase_Mutex;
+
+ // Hold either the AudioFlinger::mutex or the ThreadBase::mutex
+ void ioConfigChanged_l(audio_io_config_event_t event, pid_t pid = 0,
audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE) final;
virtual status_t createAudioPatch_l(const struct audio_patch *patch,
- audio_patch_handle_t *handle);
- virtual status_t releaseAudioPatch_l(const audio_patch_handle_t handle);
- void updateOutDevices(const DeviceDescriptorBaseVector& outDevices) override;
- void resizeInputBuffer_l(int32_t maxSharedAudioHistoryMs) override;
+ audio_patch_handle_t *handle) REQUIRES(mutex());
+ virtual status_t releaseAudioPatch_l(const audio_patch_handle_t handle) REQUIRES(mutex());
+ void updateOutDevices(const DeviceDescriptorBaseVector& outDevices) override
+ EXCLUDES_ThreadBase_Mutex;
+ void resizeInputBuffer_l(int32_t maxSharedAudioHistoryMs) override REQUIRES(mutex());
- void addPatchTrack(const sp<IAfPatchRecord>& record) final;
- void deletePatchTrack(const sp<IAfPatchRecord>& record) final;
+ void addPatchTrack(const sp<IAfPatchRecord>& record) final EXCLUDES_ThreadBase_Mutex;
+ void deletePatchTrack(const sp<IAfPatchRecord>& record) final EXCLUDES_ThreadBase_Mutex;
- void readInputParameters_l();
- uint32_t getInputFramesLost() const final;
+ void readInputParameters_l() REQUIRES(mutex());
+ uint32_t getInputFramesLost() const final EXCLUDES_ThreadBase_Mutex;
- virtual status_t addEffectChain_l(const sp<IAfEffectChain>& chain);
- virtual size_t removeEffectChain_l(const sp<IAfEffectChain>& chain);
- uint32_t hasAudioSession_l(audio_session_t sessionId) const override {
+ virtual status_t addEffectChain_l(const sp<IAfEffectChain>& chain) REQUIRES(mutex());
+ virtual size_t removeEffectChain_l(const sp<IAfEffectChain>& chain) REQUIRES(mutex());
+ uint32_t hasAudioSession_l(audio_session_t sessionId) const override REQUIRES(mutex()) {
return ThreadBase::hasAudioSession_l(sessionId, mTracks);
}
@@ -1903,7 +2005,8 @@
// FIXME replace by Set [and implement Bag/Multiset for other uses].
KeyedVector<audio_session_t, bool> sessionIds() const;
- status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event) override;
+ status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event) override
+ EXCLUDES_ThreadBase_Mutex;
bool isValidSyncEvent(const sp<audioflinger::SyncEvent>& event) const override;
static void syncStartEventCallback(const wp<audioflinger::SyncEvent>& event);
@@ -1912,52 +2015,55 @@
bool hasFastCapture() const final { return mFastCapture != 0; }
virtual void toAudioPortConfig(struct audio_port_config *config);
- virtual status_t checkEffectCompatibility_l(const effect_descriptor_t *desc,
- audio_session_t sessionId);
+ virtual status_t checkEffectCompatibility_l(const effect_descriptor_t *desc,
+ audio_session_t sessionId) REQUIRES(mutex());
- virtual void acquireWakeLock_l() {
+ virtual void acquireWakeLock_l() REQUIRES(mutex()) {
ThreadBase::acquireWakeLock_l();
- mActiveTracks.updatePowerState(this, true /* force */);
+ mActiveTracks.updatePowerState_l(this, true /* force */);
}
- void checkBtNrec() final;
+ void checkBtNrec() final EXCLUDES_ThreadBase_Mutex;
// Sets the UID records silence
- void setRecordSilenced(audio_port_handle_t portId, bool silenced) final;
+ void setRecordSilenced(audio_port_handle_t portId, bool silenced) final
+ EXCLUDES_ThreadBase_Mutex;
status_t getActiveMicrophones(
- std::vector<media::MicrophoneInfoFw>* activeMicrophones) const final;
- status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction) final;
- status_t setPreferredMicrophoneFieldDimension(float zoom) final;
+ std::vector<media::MicrophoneInfoFw>* activeMicrophones) const final
+ EXCLUDES_ThreadBase_Mutex;
+ status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction) final
+ EXCLUDES_ThreadBase_Mutex;
+ status_t setPreferredMicrophoneFieldDimension(float zoom) final EXCLUDES_ThreadBase_Mutex;
- MetadataUpdate updateMetadata_l() override;
+ MetadataUpdate updateMetadata_l() override REQUIRES(mutex());
bool fastTrackAvailable() const final { return mFastTrackAvail; }
void setFastTrackAvailable(bool available) final { mFastTrackAvail = available; }
- bool isTimestampCorrectionEnabled() const override {
+ bool isTimestampCorrectionEnabled_l() const override REQUIRES(mutex()) {
// checks popcount for exactly one device.
// Is currently disabled. Before enabling,
// verify compressed record timestamps.
return audio_is_input_device(mTimestampCorrectedDevice)
- && inDeviceType() == mTimestampCorrectedDevice;
+ && inDeviceType_l() == mTimestampCorrectedDevice;
}
status_t shareAudioHistory(const std::string& sharedAudioPackageName,
audio_session_t sharedSessionId = AUDIO_SESSION_NONE,
- int64_t sharedAudioStartMs = -1) final;
+ int64_t sharedAudioStartMs = -1) final EXCLUDES_ThreadBase_Mutex;
status_t shareAudioHistory_l(const std::string& sharedAudioPackageName,
audio_session_t sharedSessionId = AUDIO_SESSION_NONE,
- int64_t sharedAudioStartMs = -1);
- void resetAudioHistory_l() final;
+ int64_t sharedAudioStartMs = -1) REQUIRES(mutex());
+ void resetAudioHistory_l() final REQUIRES(mutex());
bool isStreamInitialized() const final {
return !(mInput == nullptr || mInput->stream == nullptr);
}
protected:
- void dumpInternals_l(int fd, const Vector<String16>& args) override;
- void dumpTracks_l(int fd, const Vector<String16>& args) override;
+ void dumpInternals_l(int fd, const Vector<String16>& args) override REQUIRES(mutex());
+ void dumpTracks_l(int fd, const Vector<String16>& args) override REQUIRES(mutex());
private:
// Enter standby if not already in standby, and set mStandby flag
@@ -1966,19 +2072,19 @@
// Call the HAL standby method unconditionally, and don't change mStandby flag
void inputStandBy();
- void checkBtNrec_l();
+ void checkBtNrec_l() REQUIRES(mutex());
- int32_t getOldestFront_l();
- void updateFronts_l(int32_t offset);
+ int32_t getOldestFront_l() REQUIRES(mutex());
+ void updateFronts_l(int32_t offset) REQUIRES(mutex());
AudioStreamIn *mInput;
Source *mSource;
SortedVector <sp<IAfRecordTrack>> mTracks;
// mActiveTracks has dual roles: it indicates the current active track(s), and
- // is used together with mStartStopCond to indicate start()/stop() progress
+ // is used together with mStartStopCV to indicate start()/stop() progress
ActiveTracks<IAfRecordTrack> mActiveTracks;
- Condition mStartStopCond;
+ audio_utils::condition_variable mStartStopCV;
// resampler converts input at HAL Hz to output at AudioRecord client Hz
void *mRsmpInBuffer; // size = mRsmpInFramesOA
@@ -2055,88 +2161,112 @@
audio_session_t sessionId,
const sp<MmapStreamCallback>& callback,
audio_port_handle_t deviceId,
- audio_port_handle_t portId) override;
+ audio_port_handle_t portId) override EXCLUDES_ThreadBase_Mutex {
+ audio_utils::lock_guard l(mutex());
+ configure_l(attr, streamType, sessionId, callback, deviceId, portId);
+ }
- void disconnect() final;
+ void configure_l(const audio_attributes_t* attr,
+ audio_stream_type_t streamType,
+ audio_session_t sessionId,
+ const sp<MmapStreamCallback>& callback,
+ audio_port_handle_t deviceId,
+ audio_port_handle_t portId) REQUIRES(mutex());
+
+ void disconnect() final EXCLUDES_ThreadBase_Mutex;
// MmapStreamInterface for adapter.
- status_t createMmapBuffer(int32_t minSizeFrames, struct audio_mmap_buffer_info* info) final;
- status_t getMmapPosition(struct audio_mmap_position* position) const override;
+ status_t createMmapBuffer(int32_t minSizeFrames, struct audio_mmap_buffer_info* info) final
+ EXCLUDES_ThreadBase_Mutex;
+ status_t getMmapPosition(struct audio_mmap_position* position) const override
+ EXCLUDES_ThreadBase_Mutex;
status_t start(const AudioClient& client,
const audio_attributes_t *attr,
- audio_port_handle_t* handle) final;
- status_t stop(audio_port_handle_t handle) final;
- status_t standby() final;
- status_t getExternalPosition(uint64_t* position, int64_t* timeNanos) const = 0;
- status_t reportData(const void* buffer, size_t frameCount) override;
+ audio_port_handle_t* handle) final EXCLUDES_ThreadBase_Mutex;
+ status_t stop(audio_port_handle_t handle) final EXCLUDES_ThreadBase_Mutex;
+ status_t standby() final EXCLUDES_ThreadBase_Mutex;
+ status_t getExternalPosition(uint64_t* position, int64_t* timeNanos) const
+ EXCLUDES_ThreadBase_Mutex = 0;
+ status_t reportData(const void* buffer, size_t frameCount) override EXCLUDES_ThreadBase_Mutex;
// RefBase
void onFirstRef() final;
// Thread virtuals
- bool threadLoop() final;
+ bool threadLoop() final REQUIRES(ThreadBase_ThreadLoop) EXCLUDES_ThreadBase_Mutex;
// Not in ThreadBase
- virtual void threadLoop_exit() final;
- virtual void threadLoop_standby() final;
- virtual bool shouldStandby_l() final { return false; }
- virtual status_t exitStandby_l() REQUIRES(mLock);
+ virtual void threadLoop_exit() final REQUIRES(ThreadBase_ThreadLoop);
+ virtual void threadLoop_standby() final REQUIRES(ThreadBase_ThreadLoop);
+ virtual bool shouldStandby_l() final REQUIRES(mutex()){ return false; }
+ virtual status_t exitStandby_l() REQUIRES(mutex());
status_t initCheck() const final { return mHalStream == nullptr ? NO_INIT : NO_ERROR; }
size_t frameCount() const final { return mFrameCount; }
- bool checkForNewParameter_l(const String8& keyValuePair, status_t& status) final;
- String8 getParameters(const String8& keys) final;
- void ioConfigChanged(audio_io_config_event_t event, pid_t pid = 0,
- audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE) final;
- void readHalParameters_l();
- void cacheParameters_l() final {}
+ bool checkForNewParameter_l(const String8& keyValuePair, status_t& status)
+ final REQUIRES(mutex());
+ String8 getParameters(const String8& keys) final EXCLUDES_ThreadBase_Mutex;
+ void ioConfigChanged_l(audio_io_config_event_t event, pid_t pid = 0,
+ audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE) final
+ /* holds either AF::mutex or TB::mutex */;
+ void readHalParameters_l() REQUIRES(mutex());
+ void cacheParameters_l() final REQUIRES(mutex(), ThreadBase_ThreadLoop) {}
status_t createAudioPatch_l(
- const struct audio_patch* patch, audio_patch_handle_t* handle) final;
- status_t releaseAudioPatch_l(const audio_patch_handle_t handle) final;
+ const struct audio_patch* patch, audio_patch_handle_t* handle) final
+ REQUIRES(mutex());
+ status_t releaseAudioPatch_l(const audio_patch_handle_t handle) final
+ REQUIRES(mutex());
+ // NO_THREAD_SAFETY_ANALYSIS
void toAudioPortConfig(struct audio_port_config* config) override;
sp<StreamHalInterface> stream() const final { return mHalStream; }
- status_t addEffectChain_l(const sp<IAfEffectChain>& chain) final;
- size_t removeEffectChain_l(const sp<IAfEffectChain>& chain) final;
+ status_t addEffectChain_l(const sp<IAfEffectChain>& chain) final REQUIRES(mutex());
+ size_t removeEffectChain_l(const sp<IAfEffectChain>& chain) final REQUIRES(mutex());
status_t checkEffectCompatibility_l(
- const effect_descriptor_t *desc, audio_session_t sessionId) final;
+ const effect_descriptor_t *desc, audio_session_t sessionId) final REQUIRES(mutex());
- uint32_t hasAudioSession_l(audio_session_t sessionId) const override {
+ uint32_t hasAudioSession_l(audio_session_t sessionId) const override REQUIRES(mutex()) {
// Note: using mActiveTracks as no mTracks here.
return ThreadBase::hasAudioSession_l(sessionId, mActiveTracks);
}
status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event) final;
bool isValidSyncEvent(const sp<audioflinger::SyncEvent>& event) const final;
- virtual void checkSilentMode_l() {} // cannot be const (RecordThread)
- virtual void processVolume_l() {}
- void checkInvalidTracks_l();
+ virtual void checkSilentMode_l() REQUIRES(mutex()) {} // cannot be const (RecordThread)
+ virtual void processVolume_l() REQUIRES(mutex()) {}
+ void checkInvalidTracks_l() REQUIRES(mutex());
// Not in ThreadBase
- virtual audio_stream_type_t streamType() const { return AUDIO_STREAM_DEFAULT; }
- virtual void invalidateTracks(audio_stream_type_t /* streamType */) {}
- void invalidateTracks(std::set<audio_port_handle_t>& /* portIds */) override {}
+ virtual audio_stream_type_t streamType_l() const REQUIRES(mutex()) {
+ return AUDIO_STREAM_DEFAULT;
+ }
+ virtual void invalidateTracks(audio_stream_type_t /* streamType */)
+ EXCLUDES_ThreadBase_Mutex {}
+ void invalidateTracks(std::set<audio_port_handle_t>& /* portIds */) override
+ EXCLUDES_ThreadBase_Mutex {}
// Sets the UID records silence
void setRecordSilenced(
- audio_port_handle_t /* portId */, bool /* silenced */) override {}
+ audio_port_handle_t /* portId */, bool /* silenced */) override
+ EXCLUDES_ThreadBase_Mutex {}
bool isStreamInitialized() const override { return false; }
- void setClientSilencedState_l(audio_port_handle_t portId, bool silenced) {
+ void setClientSilencedState_l(audio_port_handle_t portId, bool silenced) REQUIRES(mutex()) {
mClientSilencedStates[portId] = silenced;
}
- size_t eraseClientSilencedState_l(audio_port_handle_t portId) {
+ size_t eraseClientSilencedState_l(audio_port_handle_t portId) REQUIRES(mutex()) {
return mClientSilencedStates.erase(portId);
}
- bool isClientSilenced_l(audio_port_handle_t portId) const {
+ bool isClientSilenced_l(audio_port_handle_t portId) const REQUIRES(mutex()) {
const auto it = mClientSilencedStates.find(portId);
return it != mClientSilencedStates.end() ? it->second : false;
}
- void setClientSilencedIfExists_l(audio_port_handle_t portId, bool silenced) {
+ void setClientSilencedIfExists_l(audio_port_handle_t portId, bool silenced)
+ REQUIRES(mutex()) {
const auto it = mClientSilencedStates.find(portId);
if (it != mClientSilencedStates.end()) {
it->second = silenced;
@@ -2144,28 +2274,28 @@
}
protected:
- void dumpInternals_l(int fd, const Vector<String16>& args) override;
- void dumpTracks_l(int fd, const Vector<String16>& args) final;
+ void dumpInternals_l(int fd, const Vector<String16>& args) override REQUIRES(mutex());
+ void dumpTracks_l(int fd, const Vector<String16>& args) final REQUIRES(mutex());
/**
* @brief mDeviceId current device port unique identifier
*/
- audio_port_handle_t mDeviceId = AUDIO_PORT_HANDLE_NONE;
+ audio_port_handle_t mDeviceId GUARDED_BY(mutex()) = AUDIO_PORT_HANDLE_NONE;
- audio_attributes_t mAttr;
- audio_session_t mSessionId;
- audio_port_handle_t mPortId;
+ audio_attributes_t mAttr GUARDED_BY(mutex());
+ audio_session_t mSessionId GUARDED_BY(mutex());
+ audio_port_handle_t mPortId GUARDED_BY(mutex());
- wp<MmapStreamCallback> mCallback;
- sp<StreamHalInterface> mHalStream;
- sp<DeviceHalInterface> mHalDevice;
- AudioHwDevice* const mAudioHwDev;
- ActiveTracks<IAfMmapTrack> mActiveTracks;
- float mHalVolFloat;
- std::map<audio_port_handle_t, bool> mClientSilencedStates;
+ wp<MmapStreamCallback> mCallback GUARDED_BY(mutex());
+ sp<StreamHalInterface> mHalStream; // NO_THREAD_SAFETY_ANALYSIS
+ sp<DeviceHalInterface> mHalDevice GUARDED_BY(mutex());
+ AudioHwDevice* const mAudioHwDev GUARDED_BY(mutex());
+ ActiveTracks<IAfMmapTrack> mActiveTracks GUARDED_BY(mutex());
+ float mHalVolFloat GUARDED_BY(mutex());
+ std::map<audio_port_handle_t, bool> mClientSilencedStates GUARDED_BY(mutex());
- int32_t mNoCallbackWarningCount;
- static constexpr int32_t kMaxNoCallbackWarnings = 5;
+ int32_t mNoCallbackWarningCount GUARDED_BY(mutex());
+ static constexpr int32_t kMaxNoCallbackWarnings = 5;
};
class MmapPlaybackThread : public MmapThread, public IAfMmapPlaybackThread,
@@ -2183,28 +2313,31 @@
audio_session_t sessionId,
const sp<MmapStreamCallback>& callback,
audio_port_handle_t deviceId,
- audio_port_handle_t portId) final;
+ audio_port_handle_t portId) final EXCLUDES_ThreadBase_Mutex;
- AudioStreamOut* clearOutput() final;
+ AudioStreamOut* clearOutput() final EXCLUDES_ThreadBase_Mutex;
// VolumeInterface
void setMasterVolume(float value) final;
- void setMasterBalance(float /* value */) final {} // Needs implementation?
- void setMasterMute(bool muted) final;
- void setStreamVolume(audio_stream_type_t stream, float value) final;
- void setStreamMute(audio_stream_type_t stream, bool muted) final;
- float streamVolume(audio_stream_type_t stream) const final;
+ // Needs implementation?
+ void setMasterBalance(float /* value */) final EXCLUDES_ThreadBase_Mutex {}
+ void setMasterMute(bool muted) final EXCLUDES_ThreadBase_Mutex;
+ void setStreamVolume(audio_stream_type_t stream, float value) final EXCLUDES_ThreadBase_Mutex;
+ void setStreamMute(audio_stream_type_t stream, bool muted) final EXCLUDES_ThreadBase_Mutex;
+ float streamVolume(audio_stream_type_t stream) const final EXCLUDES_ThreadBase_Mutex;
- void setMasterMute_l(bool muted) { mMasterMute = muted; }
+ void setMasterMute_l(bool muted) REQUIRES(mutex()) { mMasterMute = muted; }
- void invalidateTracks(audio_stream_type_t streamType) final;
- void invalidateTracks(std::set<audio_port_handle_t>& portIds) final;
+ void invalidateTracks(audio_stream_type_t streamType) final EXCLUDES_ThreadBase_Mutex;
+ void invalidateTracks(std::set<audio_port_handle_t>& portIds) final EXCLUDES_ThreadBase_Mutex;
- audio_stream_type_t streamType() const final { return mStreamType; }
- void checkSilentMode_l() final;
- void processVolume_l() final;
+ audio_stream_type_t streamType_l() const final REQUIRES(mutex()) {
+ return mStreamType;
+ }
+ void checkSilentMode_l() final REQUIRES(mutex());
+ void processVolume_l() final REQUIRES(mutex());
- MetadataUpdate updateMetadata_l() final;
+ MetadataUpdate updateMetadata_l() final REQUIRES(mutex());
void toAudioPortConfig(struct audio_port_config* config) final;
@@ -2216,25 +2349,27 @@
status_t reportData(const void* buffer, size_t frameCount) final;
- void startMelComputation_l(const sp<audio_utils::MelProcessor>& processor) final;
- void stopMelComputation_l() final;
+ void startMelComputation_l(const sp<audio_utils::MelProcessor>& processor) final
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
+ void stopMelComputation_l() final
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
protected:
- void dumpInternals_l(int fd, const Vector<String16>& args) final;
- float streamVolume_l() const {
+ void dumpInternals_l(int fd, const Vector<String16>& args) final REQUIRES(mutex());
+ float streamVolume_l() const REQUIRES(mutex()) {
return mStreamTypes[mStreamType].volume;
}
- bool streamMuted_l() const {
+ bool streamMuted_l() const REQUIRES(mutex()) {
return mStreamTypes[mStreamType].mute;
}
- stream_type_t mStreamTypes[AUDIO_STREAM_CNT];
- audio_stream_type_t mStreamType;
- float mMasterVolume;
- bool mMasterMute;
- AudioStreamOut* mOutput;
+ stream_type_t mStreamTypes[AUDIO_STREAM_CNT] GUARDED_BY(mutex());
+ audio_stream_type_t mStreamType GUARDED_BY(mutex());
+ float mMasterVolume GUARDED_BY(mutex());
+ bool mMasterMute GUARDED_BY(mutex());
+ AudioStreamOut* mOutput; // NO_THREAD_SAFETY_ANALYSIS
- mediautils::atomic_sp<audio_utils::MelProcessor> mMelProcessor;
+ mediautils::atomic_sp<audio_utils::MelProcessor> mMelProcessor; // locked internally
};
class MmapCaptureThread : public MmapThread, public IAfMmapCaptureThread
@@ -2247,13 +2382,14 @@
return sp<IAfMmapCaptureThread>::fromExisting(this);
}
- AudioStreamIn* clearInput() final;
+ AudioStreamIn* clearInput() final EXCLUDES_ThreadBase_Mutex;
- status_t exitStandby_l() REQUIRES(mLock) final;
+ status_t exitStandby_l() REQUIRES(mutex()) final;
- MetadataUpdate updateMetadata_l() final;
- void processVolume_l() final;
- void setRecordSilenced(audio_port_handle_t portId, bool silenced) final;
+ MetadataUpdate updateMetadata_l() final REQUIRES(mutex());
+ void processVolume_l() final REQUIRES(mutex());
+ void setRecordSilenced(audio_port_handle_t portId, bool silenced) final
+ EXCLUDES_ThreadBase_Mutex;
void toAudioPortConfig(struct audio_port_config* config) final;
@@ -2265,7 +2401,7 @@
protected:
- AudioStreamIn* mInput;
+ AudioStreamIn* mInput; // NO_THREAD_SAFETY_ANALYSIS
};
class BitPerfectThread : public MixerThread {
@@ -2274,13 +2410,15 @@
audio_io_handle_t id, bool systemReady);
protected:
- mixer_state prepareTracks_l(Vector<sp<IAfTrack>>* tracksToRemove) final;
- void threadLoop_mix() final;
+ mixer_state prepareTracks_l(Vector<sp<IAfTrack>>* tracksToRemove) final
+ REQUIRES(mutex(), ThreadBase_ThreadLoop);
+ void threadLoop_mix() final REQUIRES(ThreadBase_ThreadLoop);
private:
- bool mIsBitPerfect;
- float mVolumeLeft = 0.f;
- float mVolumeRight = 0.f;
+ // These variables are only accessed on the threadLoop; hence need no mutex.
+ bool mIsBitPerfect GUARDED_BY(ThreadBase_ThreadLoop) = false;
+ float mVolumeLeft GUARDED_BY(ThreadBase_ThreadLoop) = 0.f;
+ float mVolumeRight GUARDED_BY(ThreadBase_ThreadLoop) = 0.f;
};
} // namespace android
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index e93046e..0dbb502 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -277,7 +277,7 @@
mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to
if (mClient != 0) {
// Client destructor must run with AudioFlinger client mutex locked
- Mutex::Autolock _l(mClient->afClientCallback()->clientMutex());
+ audio_utils::lock_guard _l(mClient->afClientCallback()->clientMutex());
// If the client's reference count drops to zero, the associated destructor
// must run with AudioFlinger lock held. Thus the explicit clear() rather than
// relying on the automatic clear() at end of scope.
@@ -635,12 +635,12 @@
bool shouldChange = !hasAppOps; // check if we need to update.
if (mHasOpPlayAudio.compare_exchange_strong(shouldChange, hasAppOps)) {
ALOGI("OpPlayAudio: track:%d package:%s usage:%d %smuted", mId,
- String8(mPackageName).string(), mUsage, hasAppOps ? "not " : "");
+ String8(mPackageName).c_str(), mUsage, hasAppOps ? "not " : "");
if (doBroadcast) {
auto thread = mThread.promote();
if (thread != nullptr && thread->type() == IAfThreadBase::OFFLOAD) {
// Wake up Thread if offloaded, otherwise it may be several seconds for update.
- Mutex::Autolock _l(thread->mutex());
+ audio_utils::lock_guard _l(thread->mutex());
thread->broadcast_l();
}
}
@@ -657,7 +657,7 @@
return;
}
- ALOGI("%s OP_PLAY_AUDIO callback received for %s", __func__, String8(packageName).string());
+ ALOGI("%s OP_PLAY_AUDIO callback received for %s", __func__, String8(packageName).c_str());
sp<OpPlayAudioMonitor> monitor = mMonitor.promote();
if (monitor != NULL) {
monitor->checkPlayAudioForUsage(/*doBroadcast=*/true);
@@ -887,7 +887,7 @@
bool wasActive = false;
const sp<IAfThreadBase> thread = mThread.promote();
if (thread != 0) {
- Mutex::Autolock _l(thread->mutex());
+ audio_utils::lock_guard _l(thread->mutex());
auto* const playbackThread = thread->asIAfPlaybackThread().get();
wasActive = playbackThread->destroyTrack_l(this);
forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->destroy(); });
@@ -1167,16 +1167,18 @@
const sp<IAfThreadBase> thread = mThread.promote();
if (thread != 0) {
if (isOffloaded()) {
- Mutex::Autolock _laf(thread->afThreadCallback()->mutex());
- Mutex::Autolock _lth(thread->mutex());
+ audio_utils::lock_guard _laf(thread->afThreadCallback()->mutex());
+ const bool nonOffloadableGlobalEffectEnabled =
+ thread->afThreadCallback()->isNonOffloadableGlobalEffectEnabled_l();
+ audio_utils::lock_guard _lth(thread->mutex());
sp<IAfEffectChain> ec = thread->getEffectChain_l(mSessionId);
- if (thread->afThreadCallback()->isNonOffloadableGlobalEffectEnabled_l() ||
+ if (nonOffloadableGlobalEffectEnabled ||
(ec != 0 && ec->isNonOffloadableEnabled())) {
invalidate();
return PERMISSION_DENIED;
}
}
- Mutex::Autolock _lth(thread->mutex());
+ audio_utils::lock_guard _lth(thread->mutex());
track_state state = mState;
// here the track could be either new, or restarted
// in both cases "unstop" the track
@@ -1301,7 +1303,7 @@
ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
const sp<IAfThreadBase> thread = mThread.promote();
if (thread != 0) {
- Mutex::Autolock _l(thread->mutex());
+ audio_utils::lock_guard _l(thread->mutex());
track_state state = mState;
if (state == RESUMING || state == ACTIVE || state == PAUSING || state == PAUSED) {
// If the track is not active (PAUSED and buffers full), flush buffers
@@ -1334,7 +1336,7 @@
ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
const sp<IAfThreadBase> thread = mThread.promote();
if (thread != 0) {
- Mutex::Autolock _l(thread->mutex());
+ audio_utils::lock_guard _l(thread->mutex());
auto* const playbackThread = thread->asIAfPlaybackThread().get();
switch (mState) {
case STOPPING_1:
@@ -1371,7 +1373,7 @@
ALOGV("%s(%d)", __func__, mId);
const sp<IAfThreadBase> thread = mThread.promote();
if (thread != 0) {
- Mutex::Autolock _l(thread->mutex());
+ audio_utils::lock_guard _l(thread->mutex());
auto* const playbackThread = thread->asIAfPlaybackThread().get();
// Flush the ring buffer now if the track is not active in the PlaybackThread.
@@ -1503,7 +1505,7 @@
// Signal thread to fetch new volume.
const sp<IAfThreadBase> thread = mThread.promote();
if (thread != 0) {
- Mutex::Autolock _l(thread->mutex());
+ audio_utils::lock_guard _l(thread->mutex());
thread->broadcast_l();
}
}
@@ -1663,7 +1665,7 @@
return INVALID_OPERATION;
}
- Mutex::Autolock _l(thread->mutex());
+ audio_utils::lock_guard _l(thread->mutex());
auto* const playbackThread = thread->asIAfPlaybackThread().get();
return playbackThread->getTimestamp_l(timestamp);
}
@@ -1866,7 +1868,7 @@
const sp<IAfThreadBase> thread = mThread.promote();
if (thread != 0) {
auto* const t = thread->asIAfPlaybackThread().get();
- Mutex::Autolock _l(t->mutex());
+ audio_utils::lock_guard _l(t->mutex());
t->broadcast_l();
}
}
@@ -1878,7 +1880,7 @@
const sp<IAfThreadBase> thread = mThread.promote();
if (thread != nullptr) {
auto* const t = thread->asIAfPlaybackThread().get();
- Mutex::Autolock _l(t->mutex());
+ audio_utils::lock_guard _l(t->mutex());
status = t->getOutput_l()->stream->getDualMonoMode(mode);
ALOGD_IF((status == NO_ERROR) && (mDualMonoMode != *mode),
"%s: mode %d inconsistent", __func__, mDualMonoMode);
@@ -1894,7 +1896,7 @@
const sp<IAfThreadBase> thread = mThread.promote();
if (thread != nullptr) {
auto* const t = thread->asIAfPlaybackThread().get();
- Mutex::Autolock lock(t->mutex());
+ audio_utils::lock_guard lock(t->mutex());
status = t->getOutput_l()->stream->setDualMonoMode(mode);
if (status == NO_ERROR) {
mDualMonoMode = mode;
@@ -1911,7 +1913,7 @@
sp<IAfThreadBase> thread = mThread.promote();
if (thread != nullptr) {
auto* const t = thread->asIAfPlaybackThread().get();
- Mutex::Autolock lock(t->mutex());
+ audio_utils::lock_guard lock(t->mutex());
status = t->getOutput_l()->stream->getAudioDescriptionMixLevel(leveldB);
ALOGD_IF((status == NO_ERROR) && (mAudioDescriptionMixLevel != *leveldB),
"%s: level %.3f inconsistent", __func__, mAudioDescriptionMixLevel);
@@ -1927,7 +1929,7 @@
const sp<IAfThreadBase> thread = mThread.promote();
if (thread != nullptr) {
auto* const t = thread->asIAfPlaybackThread().get();
- Mutex::Autolock lock(t->mutex());
+ audio_utils::lock_guard lock(t->mutex());
status = t->getOutput_l()->stream->setAudioDescriptionMixLevel(leveldB);
if (status == NO_ERROR) {
mAudioDescriptionMixLevel = leveldB;
@@ -1945,7 +1947,7 @@
const sp<IAfThreadBase> thread = mThread.promote();
if (thread != nullptr) {
auto* const t = thread->asIAfPlaybackThread().get();
- Mutex::Autolock lock(t->mutex());
+ audio_utils::lock_guard lock(t->mutex());
status = t->getOutput_l()->stream->getPlaybackRateParameters(playbackRate);
ALOGD_IF((status == NO_ERROR) &&
!isAudioPlaybackRateEqual(mPlaybackRateParameters, *playbackRate),
@@ -1963,7 +1965,7 @@
const sp<IAfThreadBase> thread = mThread.promote();
if (thread != nullptr) {
auto* const t = thread->asIAfPlaybackThread().get();
- Mutex::Autolock lock(t->mutex());
+ audio_utils::lock_guard lock(t->mutex());
status = t->getOutput_l()->stream->setPlaybackRateParameters(playbackRate);
if (status == NO_ERROR) {
mPlaybackRateParameters = playbackRate;
@@ -2086,7 +2088,7 @@
const sp<IAfThreadBase> thread = mTrack->mThread.promote();
if (thread != 0) {
// Lock for updating mHapticPlaybackEnabled.
- Mutex::Autolock _l(thread->mutex());
+ audio_utils::lock_guard _l(thread->mutex());
auto* const playbackThread = thread->asIAfPlaybackThread().get();
if ((mTrack->channelMask() & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE
&& playbackThread->hapticChannelCount() > 0) {
@@ -2349,13 +2351,13 @@
void OutputTrack::copyMetadataTo(MetadataInserter& backInserter) const
{
- std::lock_guard<std::mutex> lock(mTrackMetadatasMutex);
+ audio_utils::lock_guard lock(trackMetadataMutex());
backInserter = std::copy(mTrackMetadatas.begin(), mTrackMetadatas.end(), backInserter);
}
void OutputTrack::setMetadatas(const SourceMetadatas& metadatas) {
{
- std::lock_guard<std::mutex> lock(mTrackMetadatasMutex);
+ audio_utils::lock_guard lock(trackMetadataMutex());
mTrackMetadatas = metadatas;
}
// No need to adjust metadata track volumes as OutputTrack volumes are always 0dBFS.
@@ -2842,7 +2844,7 @@
track_state priorState = mState;
const sp<IAfThreadBase> thread = mThread.promote();
if (thread != 0) {
- Mutex::Autolock _l(thread->mutex());
+ audio_utils::lock_guard _l(thread->mutex());
auto* const recordThread = thread->asIAfRecordThread().get();
priorState = mState;
if (!mSharedAudioPackageName.empty()) {
@@ -3266,7 +3268,7 @@
*thread = mThread.promote();
if (!*thread) return nullptr;
auto* const recordThread = (*thread)->asIAfRecordThread().get();
- Mutex::Autolock _l(recordThread->mutex());
+ audio_utils::lock_guard _l(recordThread->mutex());
return recordThread->getInput() ? recordThread->getInput()->stream : nullptr;
}
@@ -3303,7 +3305,7 @@
}
{
- std::lock_guard<std::mutex> lock(mReadLock);
+ audio_utils::lock_guard lock(readMutex());
mReadBytes += bytesRead;
mReadError = NO_ERROR;
}
@@ -3330,7 +3332,7 @@
stream_error:
stream->standby();
{
- std::lock_guard<std::mutex> lock(mReadLock);
+ audio_utils::lock_guard lock(readMutex());
mReadError = result;
}
mReadCV.notify_one();
@@ -3359,7 +3361,7 @@
{
bytes = std::min(bytes, mFrameCount * mFrameSize);
{
- std::unique_lock<std::mutex> lock(mReadLock);
+ audio_utils::unique_lock lock(readMutex());
mReadCV.wait(lock, [&]{ return mReadError != NO_ERROR || mReadBytes != 0; });
if (mReadError != NO_ERROR) {
mLastReadFrames = 0;
diff --git a/services/audioflinger/afutils/DumpTryLock.h b/services/audioflinger/afutils/DumpTryLock.h
index c185a68..e4ad112 100644
--- a/services/audioflinger/afutils/DumpTryLock.h
+++ b/services/audioflinger/afutils/DumpTryLock.h
@@ -17,7 +17,9 @@
#pragma once
+#include <audio_utils/mutex.h>
#include <utils/Mutex.h>
+#include <utils/Timers.h>
namespace android::afutils {
@@ -28,4 +30,19 @@
return err == NO_ERROR;
}
-} // android::afutils
\ No newline at end of file
+// Note: the std::timed_mutex try_lock_for and try_lock_until methods are inefficient.
+// It is better to use std::mutex and call this method.
+//
+inline bool dumpTryLock(audio_utils::mutex& mutex) TRY_ACQUIRE(true, mutex)
+{
+ static constexpr int64_t kDumpLockTimeoutNs = 1'000'000'000;
+
+ const int64_t timeoutNs = kDumpLockTimeoutNs + systemTime(SYSTEM_TIME_REALTIME);
+ const struct timespec ts = {
+ .tv_sec = static_cast<time_t>(timeoutNs / 1000000000),
+ .tv_nsec = static_cast<long>(timeoutNs % 1000000000),
+ };
+ return pthread_mutex_timedlock(mutex.native_handle(), &ts) == 0;
+}
+
+} // android::afutils
diff --git a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
index c489eed..a2cacd2 100644
--- a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
+++ b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
@@ -63,13 +63,7 @@
if (getRole() == AUDIO_PORT_ROLE_SINK && (flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0) {
maxActiveCount = 0;
}
- if (getRole() == AUDIO_PORT_ROLE_SOURCE) {
- mMixerBehaviors.clear();
- mMixerBehaviors.insert(AUDIO_MIXER_BEHAVIOR_DEFAULT);
- if (mFlags.output & AUDIO_OUTPUT_FLAG_BIT_PERFECT) {
- mMixerBehaviors.insert(AUDIO_MIXER_BEHAVIOR_BIT_PERFECT);
- }
- }
+ refreshMixerBehaviors();
}
const MixerBehaviorSet& getMixerBehaviors() const {
@@ -222,6 +216,8 @@
void toSupportedMixerAttributes(std::vector<audio_mixer_attributes_t>* mixerAttributes) const;
+ status_t readFromParcelable(const media::AudioPortFw& parcelable);
+
// Number of streams currently opened for this profile.
uint32_t curOpenCount;
// Number of streams currently active for this profile. This is not the number of active clients
@@ -229,6 +225,8 @@
uint32_t curActiveCount;
private:
+ void refreshMixerBehaviors();
+
DeviceVector mSupportedDevices; // supported devices: this input/output can be routed from/to
MixerBehaviorSet mMixerBehaviors;
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
index a83e0af..7ee75c7 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -241,13 +241,13 @@
mix.mRouteFlags == registeredMix->mRouteFlags) {
registeredMix->mCriteria = updatedCriteria;
ALOGV("updateMix(): updated mix for dev=0x%x addr=%s", mix.mDeviceType,
- mix.mDeviceAddress.string());
+ mix.mDeviceAddress.c_str());
return NO_ERROR;
}
}
ALOGE("updateMix(): mix not registered for dev=0x%x addr=%s", mix.mDeviceType,
- mix.mDeviceAddress.string());
+ mix.mDeviceAddress.c_str());
return BAD_VALUE;
}
@@ -295,6 +295,7 @@
ALOGV("getOutputForAttr() querying %zu mixes:", size());
primaryMix.clear();
bool mixesDisallowsRequestedDevice = false;
+ const bool isMmapRequested = (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ);
for (size_t i = 0; i < size(); i++) {
sp<AudioPolicyMix> policyMix = itemAt(i);
const bool primaryOutputMix = !is_mix_loopback_render(policyMix->mRouteFlags);
@@ -305,6 +306,17 @@
mixesDisallowsRequestedDevice = true;
}
+ if (!primaryOutputMix && isMmapRequested) {
+ // AAudio does not support MMAP_NO_IRQ loopback render, and there is no way with
+ // the current MmapStreamInterface::start to reject a specific client added to a shared
+ // mmap stream.
+ // As a result all MMAP_NOIRQ requests have to be rejected when an loopback render
+ // policy is present. That ensures no shared mmap stream is used when an loopback
+ // render policy is registered.
+ ALOGD("%s: Rejecting MMAP_NOIRQ request due to LOOPBACK|RENDER mix present.", __func__);
+ return INVALID_OPERATION;
+ }
+
if (primaryOutputMix && primaryMix != nullptr) {
ALOGV("%s: Skiping %zu: Primary output already found", __func__, i);
continue; // Primary output already found
@@ -315,7 +327,7 @@
continue; // skip the mix
}
- if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
+ if (isMmapRequested) {
if (is_mix_loopback(policyMix->mRouteFlags)) {
// AAudio MMAP_NOIRQ streams cannot be routed to loopback/loopback+render
// using dynamic audio policy.
@@ -323,10 +335,11 @@
"audio policy mix.", __func__);
return INVALID_OPERATION;
}
- if (mixDevice != nullptr && !mixDevice->isMmap()) {
+ if (mixDevice != nullptr) {
+ // TODO(b/301619865): Only disallow the device that doesn't support MMAP.
ALOGD("%s: Rejecting MMAP_NOIRQ request matched to dynamic audio policy "
- "mix pointing to device %s which doesn't support mmap", __func__,
- mixDevice->toString(false).c_str());
+ "mix pointing to device %s which the mmap support is unknown at this moment",
+ __func__, mixDevice->toString(false).c_str());
return INVALID_OPERATION;
}
}
diff --git a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
index 03ab3f8..25b1c5c 100644
--- a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
@@ -171,6 +171,24 @@
}
}
+void IOProfile::refreshMixerBehaviors() {
+ if (getRole() == AUDIO_PORT_ROLE_SOURCE) {
+ mMixerBehaviors.clear();
+ mMixerBehaviors.insert(AUDIO_MIXER_BEHAVIOR_DEFAULT);
+ if (mFlags.output & AUDIO_OUTPUT_FLAG_BIT_PERFECT) {
+ mMixerBehaviors.insert(AUDIO_MIXER_BEHAVIOR_BIT_PERFECT);
+ }
+ }
+}
+
+status_t IOProfile::readFromParcelable(const media::AudioPortFw &parcelable) {
+ status_t status = AudioPort::readFromParcelable(parcelable);
+ if (status == OK) {
+ refreshMixerBehaviors();
+ }
+ return status;
+}
+
void IOProfile::dump(String8 *dst, int spaces) const
{
String8 extraInfo;
@@ -195,6 +213,10 @@
spaces - 2, "", maxActiveCount, curActiveCount);
dst->appendFormat("%*s- recommendedMuteDurationMs: %u ms\n",
spaces - 2, "", recommendedMuteDurationMs);
+ if (hasDynamicAudioProfile() && !mMixerBehaviors.empty()) {
+ dst->appendFormat("%*s- mixerBehaviors: %s\n",
+ spaces - 2, "", dumpMixerBehaviors(mMixerBehaviors).c_str());
+ }
}
void IOProfile::log()
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index a72598e..99042af 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -658,7 +658,7 @@
status_t AudioPolicyManager::updateCallRouting(bool fromCache, uint32_t delayMs, uint32_t *waitMs)
{
- if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL && hasPrimaryOutput()) {
+ if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL) {
DeviceVector rxDevices = selectBestRxSinkDevicesForCall(fromCache);
return updateCallRoutingInternal(rxDevices, delayMs, waitMs);
}
@@ -671,14 +671,21 @@
bool createTxPatch = false;
bool createRxPatch = false;
uint32_t muteWaitMs = 0;
- if(!hasPrimaryOutput() ||
+ if (hasPrimaryOutput() &&
mPrimaryOutput->devices().onlyContainsDevicesWithType(AUDIO_DEVICE_OUT_STUB)) {
return INVALID_OPERATION;
}
- ALOG_ASSERT(!rxDevices.isEmpty(), "%s() no selected output device", __func__);
audio_attributes_t attr = { .source = AUDIO_SOURCE_VOICE_COMMUNICATION };
auto txSourceDevice = mEngine->getInputDeviceForAttributes(attr);
+
+ disconnectTelephonyAudioSource(mCallRxSourceClient);
+ disconnectTelephonyAudioSource(mCallTxSourceClient);
+
+ if (rxDevices.isEmpty()) {
+ ALOGW("%s() no selected output device", __func__);
+ return INVALID_OPERATION;
+ }
if (txSourceDevice == nullptr) {
ALOGE("%s() selected input device not available", __func__);
return INVALID_OPERATION;
@@ -687,9 +694,6 @@
ALOGV("%s device rxDevice %s txDevice %s", __func__,
rxDevices.itemAt(0)->toString().c_str(), txSourceDevice->toString().c_str());
- disconnectTelephonyAudioSource(mCallRxSourceClient);
- disconnectTelephonyAudioSource(mCallTxSourceClient);
-
auto telephonyRxModule =
mHwModules.getModuleForDeviceType(AUDIO_DEVICE_IN_TELEPHONY_RX, AUDIO_FORMAT_DEFAULT);
auto telephonyTxModule =
@@ -729,6 +733,10 @@
// Use legacy routing method for voice calls via setOutputDevice() on primary output.
// Otherwise, create two audio patches for TX and RX path.
if (!createRxPatch) {
+ if (!hasPrimaryOutput()) {
+ ALOGW("%s() no primary output available", __func__);
+ return INVALID_OPERATION;
+ }
muteWaitMs = setOutputDevices(__func__, mPrimaryOutput, rxDevices, true, delayMs);
} else { // create RX path audio patch
connectTelephonyRxAudioSource();
@@ -875,20 +883,20 @@
}
}
- if (hasPrimaryOutput()) {
- if (state == AUDIO_MODE_IN_CALL) {
- (void)updateCallRouting(false /*fromCache*/, delayMs);
- } else {
+ if (state == AUDIO_MODE_IN_CALL) {
+ (void)updateCallRouting(false /*fromCache*/, delayMs);
+ } else {
+ if (oldState == AUDIO_MODE_IN_CALL) {
+ disconnectTelephonyAudioSource(mCallRxSourceClient);
+ disconnectTelephonyAudioSource(mCallTxSourceClient);
+ }
+ if (hasPrimaryOutput()) {
DeviceVector rxDevices = getNewOutputDevices(mPrimaryOutput, false /*fromCache*/);
// force routing command to audio hardware when ending call
// even if no device change is needed
if (isStateInCall(oldState) && rxDevices.isEmpty()) {
rxDevices = mPrimaryOutput->devices();
}
- if (oldState == AUDIO_MODE_IN_CALL) {
- disconnectTelephonyAudioSource(mCallRxSourceClient);
- disconnectTelephonyAudioSource(mCallTxSourceClient);
- }
setOutputDevices(__func__, mPrimaryOutput, rxDevices, force, 0);
}
}
@@ -5250,14 +5258,9 @@
return NO_ERROR;
}
patchHandle = outputDesc->getPatchHandle();
- // When a Sw bridge is released, the mixer used by this bridge will release its
- // patch at AudioFlinger side. Hence, the mixer audio patch must be recreated
- // Reuse patch handle to force audio flinger removing initial mixer patch removal
- // updating hal patch handle (prevent leaks).
// While using a HwBridge, force reconsidering device only if not reusing an existing
// output and no more activity on output (will force to close).
- bool force = sourceDesc->useSwBridge() ||
- (sourceDesc->canCloseOutput() && !outputDesc->isActive());
+ const bool force = sourceDesc->canCloseOutput() && !outputDesc->isActive();
// APM pattern is to have always outputs opened / patch realized for reachable devices.
// Update device may result to NONE (empty), coupled with force, it releases the patch.
// Reconsider device only for cases:
@@ -6280,6 +6283,7 @@
if (mPrimaryOutput == nullptr &&
outProfile->getFlags() & AUDIO_OUTPUT_FLAG_PRIMARY) {
mPrimaryOutput = outputDesc;
+ mPrimaryModuleHandle = mPrimaryOutput->getModuleHandle();
}
if ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_DIRECT) != 0) {
outputDesc->close();
@@ -7114,7 +7118,9 @@
DeviceVector AudioPolicyManager::getNewOutputDevices(const sp<SwAudioOutputDescriptor>& outputDesc,
bool fromCache)
{
- DeviceVector devices;
+ if (outputDesc == nullptr) {
+ return DeviceVector{};
+ }
ssize_t index = mAudioPatches.indexOfKey(outputDesc->getPatchHandle());
if (index >= 0) {
@@ -7148,6 +7154,7 @@
return DeviceVector(device);
}
+ DeviceVector devices;
for (const auto &productStrategy : mEngine->getOrderedProductStrategies()) {
StreamTypeVector streams = mEngine->getStreamTypesForProductStrategy(productStrategy);
auto attr = mEngine->getAllAttributesForProductStrategy(productStrategy).front();
@@ -8442,6 +8449,7 @@
if (mPrimaryOutput == nullptr && profile->getFlags() & AUDIO_OUTPUT_FLAG_PRIMARY) {
ALOGV("%s(): re-assigning mPrimaryOutput", __func__);
mPrimaryOutput = desc;
+ mPrimaryModuleHandle = mPrimaryOutput->getModuleHandle();
}
return desc;
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 91fe1cc..6365962 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -820,10 +820,10 @@
bool isPrimaryModule(const sp<HwModule> &module) const
{
- if (module == 0 || !hasPrimaryOutput()) {
+ if (module == nullptr || mPrimaryModuleHandle == AUDIO_MODULE_HANDLE_NONE) {
return false;
}
- return module->getHandle() == mPrimaryOutput->getModuleHandle();
+ return module->getHandle() == mPrimaryModuleHandle;
}
DeviceVector availablePrimaryOutputDevices() const
{
@@ -935,6 +935,8 @@
EngineInstance mEngine; // Audio Policy Engine instance
AudioPolicyClientInterface *mpClientInterface; // audio policy client interface
sp<SwAudioOutputDescriptor> mPrimaryOutput; // primary output descriptor
+ // mPrimaryModuleHandle is cached mPrimaryOutput->getModuleHandle();
+ audio_module_handle_t mPrimaryModuleHandle = AUDIO_MODULE_HANDLE_NONE;
// list of descriptors for outputs currently opened
sp<SwAudioOutputDescriptor> mSpatializerOutput;
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index 110e6bf..6eb59ad 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -2001,7 +2001,9 @@
/*deviceAddress=*/"remote_submix_media"),
DPMmapTestParam(MIX_ROUTE_FLAG_LOOP_BACK_AND_RENDER,
AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
- /*deviceAddress=*/"remote_submix_media")));
+ /*deviceAddress=*/"remote_submix_media"),
+ DPMmapTestParam(MIX_ROUTE_FLAG_RENDER, AUDIO_DEVICE_OUT_SPEAKER,
+ /*deviceAddress=*/"")));
class AudioPolicyManagerTestDPMixRecordInjection : public AudioPolicyManagerTestDynamicPolicy,
public testing::WithParamInterface<DPTestParam> {
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index ea467e7..abc3ecf 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -84,8 +84,8 @@
"android.hardware.common-V2-ndk",
"android.hardware.common.fmq-V1-ndk",
"android.hardware.graphics.common-V4-ndk",
+ "camera_platform_flags_c_lib",
"media_permission-aidl-cpp",
- "server_configurable_flags",
],
static_libs: [
@@ -106,7 +106,6 @@
"android.hardware.camera.provider@2.6",
"android.hardware.camera.provider@2.7",
"android.hardware.camera.provider-V2-ndk",
- "camera_platform_flags_c_lib",
"libaidlcommonsupport",
"libbinderthreadstateutils",
"libcameraservice_device_independent",
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index e56ca64..61b667b 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -124,6 +124,8 @@
static const std::string sManageCameraPermission("android.permission.MANAGE_CAMERA");
static const std::string sCameraPermission("android.permission.CAMERA");
static const std::string sSystemCameraPermission("android.permission.SYSTEM_CAMERA");
+static const std::string sCameraHeadlessSystemUserPermission(
+ "android.permission.CAMERA_HEADLESS_SYSTEM_USER");
static const std::string
sCameraSendSystemEventsPermission("android.permission.CAMERA_SEND_SYSTEM_EVENTS");
static const std::string sCameraOpenCloseListenerPermission(
@@ -703,6 +705,14 @@
return strncmp(value, "automotive", PROPERTY_VALUE_MAX) == 0;
}
+static bool isHeadlessSystemUserMode() {
+ // Checks if the device is running in headless system user mode
+ // by checking the property ro.fw.mu.headless_system_user.
+ char value[PROPERTY_VALUE_MAX] = {0};
+ property_get("ro.fw.mu.headless_system_user", value, "");
+ return strncmp(value, "true", PROPERTY_VALUE_MAX) == 0;
+}
+
static bool isAutomotivePrivilegedClient(int32_t uid) {
// Returns false if this is not an automotive device type.
if (!isAutomotiveDevice())
@@ -792,6 +802,15 @@
return checkPermissionForSystemCamera && checkPermissionForCamera;
}
+bool CameraService::hasPermissionsForCameraHeadlessSystemUser(const std::string& cameraId,
+ int callingPid, int callingUid) const{
+ AttributionSourceState attributionSource{};
+ attributionSource.pid = callingPid;
+ attributionSource.uid = callingUid;
+ return checkPermission(cameraId, sCameraHeadlessSystemUserPermission, attributionSource,
+ std::string(), AppOpsManager::OP_NONE);
+}
+
Status CameraService::getNumberOfCameras(int32_t type, int32_t* numCameras) {
ATRACE_CALL();
Mutex::Autolock l(mServiceLock);
@@ -1661,6 +1680,18 @@
clientUserId, cameraId.c_str());
}
+ // If the System User tries to access the camera when the device is running in
+ // headless system user mode, ensure that client has the required permission
+ // CAMERA_HEADLESS_SYSTEM_USER.
+ if (isHeadlessSystemUserMode() && (clientUserId == USER_SYSTEM) &&
+ !hasPermissionsForCameraHeadlessSystemUser(cameraId, callingPid, callingUid)) {
+ ALOGE("Permission Denial: can't use the camera pid=%d, uid=%d", clientPid, clientUid);
+ return STATUS_ERROR_FMT(ERROR_PERMISSION_DENIED,
+ "Caller \"%s\" (PID %d, UID %d) cannot open camera \"%s\" as Headless System User\
+ without camera headless system user permission",
+ clientName.c_str(), clientUid, clientPid, cameraId.c_str());
+ }
+
return Status::ok();
}
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index f631480..6819136 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -104,6 +104,9 @@
// Event log ID
static const int SN_EVENT_LOG_ID = 0x534e4554;
+ // Keep this in sync with frameworks/base/core/java/android/os/UserHandle.java
+ static const userid_t USER_SYSTEM = 0;
+
// Register camera service
static void instantiate();
@@ -364,7 +367,7 @@
static bool isValidAudioRestriction(int32_t mode);
// Override rotate-and-crop AUTO behavior
- virtual status_t setRotateAndCropOverride(uint8_t rotateAndCrop) = 0;
+ virtual status_t setRotateAndCropOverride(uint8_t rotateAndCrop, bool fromHal = false) = 0;
// Override autoframing AUTO behaviour
virtual status_t setAutoframingOverride(uint8_t autoframingValue) = 0;
@@ -656,6 +659,9 @@
bool hasPermissionsForSystemCamera(const std::string& cameraId, int callingPid, int callingUid)
const;
+ bool hasPermissionsForCameraHeadlessSystemUser(const std::string& cameraId, int callingPid,
+ int callingUid) const;
+
/**
* Typesafe version of device status, containing both the HAL-layer and the service interface-
* layer values.
diff --git a/services/camera/libcameraservice/aidl/VndkVersionMetadataTags.h b/services/camera/libcameraservice/aidl/VndkVersionMetadataTags.h
index 48c804d..3cc843d 100644
--- a/services/camera/libcameraservice/aidl/VndkVersionMetadataTags.h
+++ b/services/camera/libcameraservice/aidl/VndkVersionMetadataTags.h
@@ -77,6 +77,10 @@
{34, {
ANDROID_CONTROL_AUTOFRAMING_AVAILABLE,
ANDROID_CONTROL_AVAILABLE_SETTINGS_OVERRIDES,
+ ANDROID_FLASH_SINGLE_STRENGTH_DEFAULT_LEVEL,
+ ANDROID_FLASH_SINGLE_STRENGTH_MAX_LEVEL,
+ ANDROID_FLASH_TORCH_STRENGTH_DEFAULT_LEVEL,
+ ANDROID_FLASH_TORCH_STRENGTH_MAX_LEVEL,
ANDROID_JPEGR_AVAILABLE_JPEG_R_MIN_FRAME_DURATIONS,
ANDROID_JPEGR_AVAILABLE_JPEG_R_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION,
ANDROID_JPEGR_AVAILABLE_JPEG_R_STALL_DURATIONS,
@@ -108,6 +112,7 @@
ANDROID_CONTROL_SETTINGS_OVERRIDING_FRAME_NUMBER,
ANDROID_EXTENSION_CURRENT_TYPE,
ANDROID_EXTENSION_STRENGTH,
+ ANDROID_FLASH_STRENGTH_LEVEL,
ANDROID_SCALER_RAW_CROP_REGION,
} },
};
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index b217476..caa6424 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -2342,7 +2342,7 @@
return mDevice->setCameraServiceWatchdog(enabled);
}
-status_t Camera2Client::setRotateAndCropOverride(uint8_t rotateAndCrop) {
+status_t Camera2Client::setRotateAndCropOverride(uint8_t rotateAndCrop, bool fromHal) {
if (rotateAndCrop > ANDROID_SCALER_ROTATE_AND_CROP_AUTO) return BAD_VALUE;
{
@@ -2356,7 +2356,7 @@
}
return mDevice->setRotateAndCropAutoBehavior(
- static_cast<camera_metadata_enum_android_scaler_rotate_and_crop_t>(rotateAndCrop));
+ static_cast<camera_metadata_enum_android_scaler_rotate_and_crop_t>(rotateAndCrop), fromHal);
}
status_t Camera2Client::setAutoframingOverride(uint8_t autoframingValue) {
diff --git a/services/camera/libcameraservice/api1/Camera2Client.h b/services/camera/libcameraservice/api1/Camera2Client.h
index 9ec1eb5..2cb7af0 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.h
+++ b/services/camera/libcameraservice/api1/Camera2Client.h
@@ -81,7 +81,7 @@
virtual status_t setVideoTarget(const sp<IGraphicBufferProducer>& bufferProducer);
virtual status_t setAudioRestriction(int mode);
virtual int32_t getGlobalAudioRestriction();
- virtual status_t setRotateAndCropOverride(uint8_t rotateAndCrop);
+ virtual status_t setRotateAndCropOverride(uint8_t rotateAndCrop, bool fromHal = false);
virtual status_t setAutoframingOverride(uint8_t autoframingMode);
virtual bool supportsCameraMute();
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 939f969..2e6eb06 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -18,6 +18,7 @@
#define ATRACE_TAG ATRACE_TAG_CAMERA
//#define LOG_NDEBUG 0
+#include <com_android_internal_camera_flags.h>
#include <cutils/properties.h>
#include <utils/CameraThreadState.h>
#include <utils/Log.h>
@@ -55,6 +56,8 @@
using namespace camera3;
using camera3::camera_stream_rotation_t::CAMERA_STREAM_ROTATION_0;
+namespace flags = com::android::internal::camera::flags;
+
CameraDeviceClientBase::CameraDeviceClientBase(
const sp<CameraService>& cameraService,
const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
@@ -539,6 +542,13 @@
if (entry.count == 1) {
mVideoStabilizationMode = entry.data.u8[0];
}
+ if (flags::log_ultrawide_usage()) {
+ entry = physicalSettingsList.begin()->metadata.find(
+ ANDROID_CONTROL_ZOOM_RATIO);
+ if (entry.count == 1 && entry.data.f[0] < 1.0f ) {
+ mUsedUltraWide = true;
+ }
+ }
}
mRequestIdCounter++;
@@ -1762,11 +1772,11 @@
return mDevice->setCameraServiceWatchdog(enabled);
}
-status_t CameraDeviceClient::setRotateAndCropOverride(uint8_t rotateAndCrop) {
+status_t CameraDeviceClient::setRotateAndCropOverride(uint8_t rotateAndCrop, bool fromHal) {
if (rotateAndCrop > ANDROID_SCALER_ROTATE_AND_CROP_AUTO) return BAD_VALUE;
return mDevice->setRotateAndCropAutoBehavior(
- static_cast<camera_metadata_enum_android_scaler_rotate_and_crop_t>(rotateAndCrop));
+ static_cast<camera_metadata_enum_android_scaler_rotate_and_crop_t>(rotateAndCrop), fromHal);
}
status_t CameraDeviceClient::setAutoframingOverride(uint8_t autoframingValue) {
@@ -2051,7 +2061,7 @@
}
}
Camera2ClientBase::notifyIdleWithUserTag(requestCount, resultErrorCount, deviceError,
- fullStreamStats, mUserTag, mVideoStabilizationMode);
+ fullStreamStats, mUserTag, mVideoStabilizationMode, mUsedUltraWide);
}
void CameraDeviceClient::notifyShutter(const CaptureResultExtras& resultExtras,
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 86a94e2..c2870aa 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -198,7 +198,8 @@
virtual status_t initialize(sp<CameraProviderManager> manager,
const std::string& monitorTags) override;
- virtual status_t setRotateAndCropOverride(uint8_t rotateAndCrop) override;
+ virtual status_t setRotateAndCropOverride(uint8_t rotateAndCrop,
+ bool fromHal = false) override;
virtual status_t setAutoframingOverride(uint8_t autoframingValue) override;
@@ -369,6 +370,8 @@
std::string mUserTag;
// The last set video stabilization mode
int mVideoStabilizationMode = -1;
+ // Whether a zoom_ratio < 1.0 has been used during this session
+ bool mUsedUltraWide = false;
// This only exists in case of camera ID Remapping.
const std::string mOriginalCameraId;
diff --git a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
index 99bdb0e..4ed352d 100644
--- a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
@@ -80,7 +80,8 @@
return OK;
}
-status_t CameraOfflineSessionClient::setRotateAndCropOverride(uint8_t /*rotateAndCrop*/) {
+status_t CameraOfflineSessionClient::setRotateAndCropOverride(uint8_t /*rotateAndCrop*/,
+ bool /*fromHal*/) {
// Since we're not submitting more capture requests, changes to rotateAndCrop override
// make no difference.
return OK;
diff --git a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
index 70bad03..8aad4e9 100644
--- a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
+++ b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
@@ -80,7 +80,7 @@
status_t initialize(sp<CameraProviderManager> /*manager*/,
const std::string& /*monitorTags*/) override;
- status_t setRotateAndCropOverride(uint8_t rotateAndCrop) override;
+ status_t setRotateAndCropOverride(uint8_t rotateAndCrop, bool fromHal = false) override;
status_t setAutoframingOverride(uint8_t autoframingValue) override;
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
index a611cc6..5c88cfa 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
@@ -370,7 +370,8 @@
rotateAndCropMode = ANDROID_SCALER_ROTATE_AND_CROP_90;
}
- static_cast<TClientBase *>(this)->setRotateAndCropOverride(rotateAndCropMode);
+ static_cast<TClientBase *>(this)->setRotateAndCropOverride(rotateAndCropMode,
+ /*fromHal*/ true);
}
}
@@ -395,7 +396,7 @@
void Camera2ClientBase<TClientBase>::notifyIdleWithUserTag(
int64_t requestCount, int64_t resultErrorCount, bool deviceError,
const std::vector<hardware::CameraStreamStats>& streamStats,
- const std::string& userTag, int videoStabilizationMode) {
+ const std::string& userTag, int videoStabilizationMode, bool usedUltraWide) {
if (mDeviceActive) {
status_t res = TClientBase::finishCameraStreamingOps();
if (res != OK) {
@@ -404,7 +405,7 @@
}
mCameraServiceProxyWrapper->logIdle(TClientBase::mCameraIdStr,
requestCount, resultErrorCount, deviceError, userTag, videoStabilizationMode,
- streamStats);
+ usedUltraWide, streamStats);
}
mDeviceActive = false;
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.h b/services/camera/libcameraservice/common/Camera2ClientBase.h
index 88d65dc..226881a 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.h
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.h
@@ -97,7 +97,8 @@
void notifyIdleWithUserTag(int64_t requestCount, int64_t resultErrorCount,
bool deviceError,
const std::vector<hardware::CameraStreamStats>& streamStats,
- const std::string& userTag, int videoStabilizationMode);
+ const std::string& userTag, int videoStabilizationMode,
+ bool usedUltraWide);
int getCameraId() const;
const sp<CameraDeviceBase>&
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index 017da0f..01199af 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -444,7 +444,8 @@
* and defaults to NONE.
*/
virtual status_t setRotateAndCropAutoBehavior(
- camera_metadata_enum_android_scaler_rotate_and_crop_t rotateAndCropValue) = 0;
+ camera_metadata_enum_android_scaler_rotate_and_crop_t rotateAndCropValue,
+ bool fromHal = false) = 0;
/**
* Set the current behavior for the AUTOFRAMING control when in AUTO.
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index a2ec576..28be652 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -86,6 +86,7 @@
};
#define CAMERA_DEVICE_API_VERSION_1_0 HARDWARE_DEVICE_API_VERSION(1, 0)
+#define CAMERA_DEVICE_API_VERSION_1_2 HARDWARE_DEVICE_API_VERSION(1, 2)
#define CAMERA_DEVICE_API_VERSION_3_0 HARDWARE_DEVICE_API_VERSION(3, 0)
#define CAMERA_DEVICE_API_VERSION_3_1 HARDWARE_DEVICE_API_VERSION(3, 1)
#define CAMERA_DEVICE_API_VERSION_3_2 HARDWARE_DEVICE_API_VERSION(3, 2)
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 456d1be..6765c1d 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -51,6 +51,7 @@
#include <cutils/properties.h>
#include <camera/StringUtils.h>
+#include <android-base/properties.h>
#include <android/hardware/camera/device/3.7/ICameraInjectionSession.h>
#include <android/hardware/camera2/ICameraDeviceUser.h>
@@ -69,6 +70,7 @@
#include "utils/TraceHFR.h"
#include <algorithm>
+#include <optional>
#include <tuple>
using namespace android::camera3;
@@ -295,13 +297,6 @@
}
}
}
- // Signal to request thread that we're not expecting any
- // more requests. This will be true since once we're in
- // disconnect and we've cleared off the request queue, the
- // request thread can't receive any new requests through
- // binder calls - since disconnect holds
- // mBinderSerialization lock.
- mRequestThread->setRequestClearing();
}
if (mStatus == STATUS_ERROR) {
@@ -770,8 +765,7 @@
auto firstRequest = requestList->begin();
for (auto& outputStream : (*firstRequest)->mOutputStreams) {
if (outputStream->isVideoStream()) {
- (*firstRequest)->mBatchSize = requestList->size();
- outputStream->setBatchSize(requestList->size());
+ applyMaxBatchSizeLocked(requestList, outputStream);
break;
}
}
@@ -2339,6 +2333,9 @@
// deadlocks (http://b/143513518)
nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
+ // Make sure status tracker is flushed
+ mStatusTracker->flushPendingStates();
+
Mutex::Autolock l(mLock);
if (checkAbandonedStreamsLocked()) {
ALOGW("%s: Abandoned stream detected, session parameters can't be applied correctly!",
@@ -3299,8 +3296,12 @@
}
void Camera3Device::RequestThread::requestExit() {
- // Call parent to set up shutdown
- Thread::requestExit();
+ {
+ Mutex::Autolock l(mRequestLock);
+ mRequestClearing = true;
+ // Call parent to set up shutdown
+ Thread::requestExit();
+ }
// The exit from any possible waits
mDoPauseSignal.signal();
mRequestSignal.signal();
@@ -4432,11 +4433,6 @@
return;
}
-void Camera3Device::RequestThread::setRequestClearing() {
- Mutex::Autolock l(mRequestLock);
- mRequestClearing = true;
-}
-
sp<Camera3Device::CaptureRequest>
Camera3Device::RequestThread::waitForNextRequestLocked() {
status_t res;
@@ -5399,9 +5395,13 @@
}
status_t Camera3Device::setRotateAndCropAutoBehavior(
- camera_metadata_enum_android_scaler_rotate_and_crop_t rotateAndCropValue) {
+ camera_metadata_enum_android_scaler_rotate_and_crop_t rotateAndCropValue, bool fromHal) {
ATRACE_CALL();
- Mutex::Autolock il(mInterfaceLock);
+ // We shouldn't hold mInterfaceLock when called as an effect of a HAL
+ // callback since this can lead to a deadlock : b/299348355.
+ // mLock still protects state.
+ std::optional<Mutex::Autolock> maybeMutex =
+ fromHal ? std::nullopt : std::optional<Mutex::Autolock>(mInterfaceLock);
Mutex::Autolock l(mLock);
if (mRequestThread == nullptr) {
return INVALID_OPERATION;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 0229446..d812c01 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -275,7 +275,7 @@
* and defaults to NONE.
*/
status_t setRotateAndCropAutoBehavior(
- camera_metadata_enum_android_scaler_rotate_and_crop_t rotateAndCropValue);
+ camera_metadata_enum_android_scaler_rotate_and_crop_t rotateAndCropValue, bool fromHal);
/**
* Set the current behavior for the AUTOFRAMING control when in AUTO.
@@ -703,6 +703,15 @@
status_t initializeCommonLocked();
/**
+ * Update capture request list so that each batch size honors the batch_size_max report from
+ * the HAL. Set the batch size to output stream for buffer operations.
+ *
+ * Must be called with mLock held.
+ */
+ virtual void applyMaxBatchSizeLocked(
+ RequestList* requestList, const sp<camera3::Camera3OutputStreamInterface>& stream) = 0;
+
+ /**
* Get the last request submitted to the hal by the request thread.
*
* Must be called with mLock held.
@@ -932,9 +941,6 @@
*/
void setPaused(bool paused);
- // set mRequestClearing - no new requests are expected to be queued to RequestThread
- void setRequestClearing();
-
/**
* Wait until thread processes the capture request with settings'
* android.request.id == requestId.
diff --git a/services/camera/libcameraservice/device3/StatusTracker.cpp b/services/camera/libcameraservice/device3/StatusTracker.cpp
index bd78e0a..f13109a 100644
--- a/services/camera/libcameraservice/device3/StatusTracker.cpp
+++ b/services/camera/libcameraservice/device3/StatusTracker.cpp
@@ -34,7 +34,8 @@
mParent(parent),
mNextComponentId(0),
mIdleFence(new Fence()),
- mDeviceState(IDLE) {
+ mDeviceState(IDLE),
+ mFlushed(true) {
}
StatusTracker::~StatusTracker() {
@@ -111,16 +112,33 @@
const sp<Fence>& componentFence) {
ALOGV("%s: Component %d is now %s", __FUNCTION__, id,
state == IDLE ? "idle" : "active");
- Mutex::Autolock l(mPendingLock);
- StateChange newState = {
- id,
- state,
- componentFence
- };
+ // If any component state changes, the status tracker is considered
+ // not flushed.
+ {
+ Mutex::Autolock l(mFlushLock);
+ mFlushed = false;
+ }
- mPendingChangeQueue.add(newState);
- mPendingChangeSignal.signal();
+ {
+ Mutex::Autolock l(mPendingLock);
+
+ StateChange newState = {
+ id,
+ state,
+ componentFence
+ };
+
+ mPendingChangeQueue.add(newState);
+ mPendingChangeSignal.signal();
+ }
+}
+
+void StatusTracker::flushPendingStates() {
+ Mutex::Autolock l(mFlushLock);
+ while (!mFlushed && isRunning()) {
+ mFlushCondition.waitRelative(mFlushLock, kWaitDuration);
+ }
}
void StatusTracker::requestExit() {
@@ -128,6 +146,7 @@
Thread::requestExit();
// Then exit any waits
mPendingChangeSignal.signal();
+ mFlushCondition.signal();
}
StatusTracker::ComponentState StatusTracker::getDeviceStateLocked() {
@@ -231,6 +250,17 @@
}
mStateTransitions.clear();
+ // After all pending changes are cleared and notified, mark the tracker
+ // as flushed.
+ {
+ Mutex::Autolock fl(mFlushLock);
+ Mutex::Autolock pl(mPendingLock);
+ if (mPendingChangeQueue.size() == 0) {
+ mFlushed = true;
+ mFlushCondition.signal();
+ }
+ }
+
if (waitForIdleFence) {
auto ret = mIdleFence->wait(kWaitDuration);
if (ret == NO_ERROR) {
diff --git a/services/camera/libcameraservice/device3/StatusTracker.h b/services/camera/libcameraservice/device3/StatusTracker.h
index 069bff6..fc65502 100644
--- a/services/camera/libcameraservice/device3/StatusTracker.h
+++ b/services/camera/libcameraservice/device3/StatusTracker.h
@@ -70,6 +70,10 @@
void dumpActiveComponents();
+ // Flush all pending states inflight in the tracker, and return upon
+ // completion.
+ void flushPendingStates();
+
virtual void requestExit();
protected:
@@ -113,6 +117,11 @@
// Current overall device state
ComponentState mDeviceState;
+ // For flushing all pending states transitions
+ bool mFlushed;
+ Mutex mFlushLock;
+ Condition mFlushCondition;
+
// Private to threadLoop
// Determine current overall device state
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp
index af48dd6..272c390 100644
--- a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp
@@ -51,6 +51,7 @@
#include <aidl/android/hardware/camera/device/ICameraInjectionSession.h>
#include <aidlcommonsupport/NativeHandle.h>
+#include <android-base/properties.h>
#include <android/binder_ibinder_platform.h>
#include <android/hardware/camera2/ICameraDeviceUser.h>
#include <camera/StringUtils.h>
@@ -313,6 +314,20 @@
}
}
+ // batch size limit is applied to the device with camera device version larger than 3.2 which is
+ // AIDL v2
+ hardware::hidl_version maxVersion{0, 0};
+ IPCTransport transport = IPCTransport::AIDL;
+ res = manager->getHighestSupportedVersion(mId, &maxVersion, &transport);
+ if (res != OK) {
+ ALOGE("%s: Error in getting camera device version id: %s (%d)", __FUNCTION__,
+ strerror(-res), res);
+ return res;
+ }
+ int deviceVersion = HARDWARE_DEVICE_API_VERSION(maxVersion.get_major(), maxVersion.get_minor());
+
+ mBatchSizeLimitEnabled = (deviceVersion >= CAMERA_DEVICE_API_VERSION_1_2);
+
return initializeCommonLocked();
}
@@ -1580,6 +1595,66 @@
return OK;
}
+void AidlCamera3Device::applyMaxBatchSizeLocked(
+ RequestList* requestList, const sp<camera3::Camera3OutputStreamInterface>& stream) {
+ int batchSize = requestList->size();
+
+ if (!mBatchSizeLimitEnabled) {
+ (*requestList->begin())->mBatchSize = batchSize;
+ stream->setBatchSize(batchSize);
+ return;
+ }
+
+ const auto& metadata = (*requestList->begin())->mSettingsList.begin()->metadata;
+
+ uint32_t tag = ANDROID_CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS;
+ auto sensorPixelModeEntry = metadata.find(ANDROID_SENSOR_PIXEL_MODE);
+ if (sensorPixelModeEntry.count != 0) {
+ if (ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION == sensorPixelModeEntry.data.u8[0]) {
+ tag = ANDROID_CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS_MAXIMUM_RESOLUTION;
+ }
+ }
+
+ const auto fpsRange = metadata.find(ANDROID_CONTROL_AE_TARGET_FPS_RANGE);
+ if (fpsRange.count > 1) {
+ auto configEntry = mDeviceInfo.find(tag);
+ for (size_t index = 4; index < configEntry.count; index += 5) {
+ if (stream->getWidth() == static_cast<uint32_t>(configEntry.data.i32[index - 4]) &&
+ stream->getHeight() == static_cast<uint32_t>(configEntry.data.i32[index - 3]) &&
+ fpsRange.data.i32[0] == configEntry.data.i32[index - 2] &&
+ fpsRange.data.i32[1] == configEntry.data.i32[index - 1]) {
+ const int maxBatchSize = configEntry.data.i32[index - 1] / 30;
+ const int reportedSize = configEntry.data.i32[index];
+
+ if (maxBatchSize % reportedSize == 0 && requestList->size() % reportedSize == 0) {
+ batchSize = reportedSize;
+ ALOGVV("Matching high speed configuration found. Limit batch size to %d",
+ batchSize);
+ } else if (maxBatchSize % reportedSize == 0 &&
+ reportedSize % requestList->size() == 0) {
+ ALOGVV("Matching high speed configuration found, but requested batch size is "
+ "divisor of batch_size_max. No need to limit batch size.");
+ } else {
+ ALOGW("Matching high speed configuration found, but batch_size_max is not a "
+ "divisor of corresponding fps_max/30 or requested batch size is not a "
+ "divisor of batch_size_max, (fps_max %d, batch_size_max %d, requested "
+ "batch size %zu)",
+ configEntry.data.i32[index - 1], reportedSize, requestList->size());
+ }
+ break;
+ }
+ }
+ }
+
+ for (auto request = requestList->begin(); request != requestList->end(); request++) {
+ if (requestList->distance(requestList->begin(), request) % batchSize == 0) {
+ (*request)->mBatchSize = batchSize;
+ }
+ }
+
+ stream->setBatchSize(batchSize);
+}
+
status_t AidlCamera3Device::injectionCameraInitialize(const std::string &injectedCamId,
sp<CameraProviderManager> manager) {
return (static_cast<AidlCamera3DeviceInjectionMethods *>
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h
index e0be367..21813d4 100644
--- a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h
@@ -257,6 +257,10 @@
};
private:
+ virtual void applyMaxBatchSizeLocked(
+ RequestList* requestList,
+ const sp<camera3::Camera3OutputStreamInterface>& stream) override;
+
virtual status_t injectionCameraInitialize(const std::string &injectCamId,
sp<CameraProviderManager> manager) override;
@@ -277,6 +281,9 @@
std::shared_ptr<AidlCameraDeviceCallbacks> mCallbacks = nullptr;
+ // Whether the batch_size_max field in the high speed configuration actually applied to
+ // capture requests.
+ bool mBatchSizeLimitEnabled = false;
}; // class AidlCamera3Device
diff --git a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp
index 06af5ff..4488067 100644
--- a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp
+++ b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp
@@ -699,6 +699,14 @@
// Java side to make sure the CameraCaptureSession is properly closed
}
+void HidlCamera3Device::applyMaxBatchSizeLocked(
+ RequestList* requestList, const sp<camera3::Camera3OutputStreamInterface>& stream) {
+ int batchSize = requestList->size();
+
+ (*requestList->begin())->mBatchSize = batchSize;
+ stream->setBatchSize(batchSize);
+}
+
sp<Camera3Device::RequestThread> HidlCamera3Device::createNewRequestThread(
wp<Camera3Device> parent, sp<camera3::StatusTracker> statusTracker,
sp<Camera3Device::HalInterface> interface,
diff --git a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h
index 2cfdf9d..350b072 100644
--- a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h
+++ b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h
@@ -218,6 +218,10 @@
hardware::Return<void> notifyHelper(
const hardware::hidl_vec<NotifyMsgType>& msgs);
+ virtual void applyMaxBatchSizeLocked(
+ RequestList* requestList,
+ const sp<camera3::Camera3OutputStreamInterface>& stream) override;
+
virtual status_t injectionCameraInitialize(const std::string &injectCamId,
sp<CameraProviderManager> manager) override;
diff --git a/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.cpp b/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.cpp
index d07bf6d..d227606 100644
--- a/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.cpp
+++ b/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.cpp
@@ -94,7 +94,7 @@
void CameraServiceProxyWrapper::CameraSessionStatsWrapper::onIdle(
sp<hardware::ICameraServiceProxy>& proxyBinder,
int64_t requestCount, int64_t resultErrorCount, bool deviceError,
- const std::string& userTag, int32_t videoStabilizationMode,
+ const std::string& userTag, int32_t videoStabilizationMode, bool usedUltraWide,
const std::vector<hardware::CameraStreamStats>& streamStats) {
Mutex::Autolock l(mLock);
@@ -104,6 +104,7 @@
mSessionStats.mDeviceError = deviceError;
mSessionStats.mUserTag = userTag;
mSessionStats.mVideoStabilizationMode = videoStabilizationMode;
+ mSessionStats.mUsedUltraWide = usedUltraWide;
mSessionStats.mStreamStats = streamStats;
updateProxyDeviceState(proxyBinder);
@@ -278,7 +279,7 @@
void CameraServiceProxyWrapper::logIdle(const std::string& id,
int64_t requestCount, int64_t resultErrorCount, bool deviceError,
- const std::string& userTag, int32_t videoStabilizationMode,
+ const std::string& userTag, int32_t videoStabilizationMode, bool usedUltraWide,
const std::vector<hardware::CameraStreamStats>& streamStats) {
std::shared_ptr<CameraSessionStatsWrapper> sessionStats;
{
@@ -304,7 +305,7 @@
sp<hardware::ICameraServiceProxy> proxyBinder = getCameraServiceProxy();
sessionStats->onIdle(proxyBinder, requestCount, resultErrorCount, deviceError, userTag,
- videoStabilizationMode, streamStats);
+ videoStabilizationMode, usedUltraWide, streamStats);
}
void CameraServiceProxyWrapper::logOpen(const std::string& id, int facing,
diff --git a/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.h b/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.h
index 1afe5b3..4e21e58 100644
--- a/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.h
+++ b/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.h
@@ -61,7 +61,7 @@
void onActive(sp<hardware::ICameraServiceProxy>& proxyBinder, float maxPreviewFps);
void onIdle(sp<hardware::ICameraServiceProxy>& proxyBinder,
int64_t requestCount, int64_t resultErrorCount, bool deviceError,
- const std::string& userTag, int32_t videoStabilizationMode,
+ const std::string& userTag, int32_t videoStabilizationMode, bool usedUltraWide,
const std::vector<hardware::CameraStreamStats>& streamStats);
std::string updateExtensionSessionStats(
@@ -110,7 +110,7 @@
// Session state becomes idle
void logIdle(const std::string& id,
int64_t requestCount, int64_t resultErrorCount, bool deviceError,
- const std::string& userTag, int32_t videoStabilizationMode,
+ const std::string& userTag, int32_t videoStabilizationMode, bool usedUltraWide,
const std::vector<hardware::CameraStreamStats>& streamStats);
// Ping camera service proxy for user update
diff --git a/services/mediametrics/statsd_codec.cpp b/services/mediametrics/statsd_codec.cpp
index 5e3e654..844f204 100644
--- a/services/mediametrics/statsd_codec.cpp
+++ b/services/mediametrics/statsd_codec.cpp
@@ -660,6 +660,12 @@
metrics_proto.set_caller_uid(app_uid);
AStatsEvent_writeInt32(event, app_uid);
+ int64_t pixelFormat = -1;
+ if (item->getInt64("android.media.mediacodec.pixel-format", &pixelFormat)) {
+ metrics_proto.set_pixel_format(pixelFormat);
+ }
+ AStatsEvent_writeInt64(event, pixelFormat);
+
int64_t firstRenderTimeUs = -1;
item->getInt64("android.media.mediacodec.first-render-time-us", &firstRenderTimeUs);
int64_t framesReleased = -1;
diff --git a/services/mediaresourcemanager/ResourceManagerService.cpp b/services/mediaresourcemanager/ResourceManagerService.cpp
index 5d1ba2b..8e7a624 100644
--- a/services/mediaresourcemanager/ResourceManagerService.cpp
+++ b/services/mediaresourcemanager/ResourceManagerService.cpp
@@ -53,23 +53,20 @@
std::weak_ptr<DeathNotifier> mDeathNotifier;
};
public:
+ static std::shared_ptr<DeathNotifier> Create(
+ const std::shared_ptr<IResourceManagerClient>& client,
+ const std::shared_ptr<ResourceManagerService>& service,
+ const ClientInfoParcel& clientInfo,
+ bool overrideProcessInfo = false);
+
DeathNotifier(const std::shared_ptr<IResourceManagerClient>& client,
const std::shared_ptr<ResourceManagerService>& service,
- const ClientInfoParcel& clientInfo,
- AIBinder_DeathRecipient* recipient);
+ const ClientInfoParcel& clientInfo);
virtual ~DeathNotifier() {
unlink();
}
- void unlink() {
- if (mClient != nullptr) {
- // Register for the callbacks by linking to death notification.
- AIBinder_unlinkToDeath(mClient->asBinder().get(), mRecipient, mCookie);
- mClient = nullptr;
- }
- }
-
// Implement death recipient
static void BinderDiedCallback(void* cookie);
static void BinderUnlinkedCallback(void* cookie);
@@ -81,24 +78,34 @@
// The context gets deleted at BinderUnlinkedCallback.
mCookie = new BinderDiedContext{.mDeathNotifier = weak_from_this()};
// Register for the callbacks by linking to death notification.
- AIBinder_linkToDeath(mClient->asBinder().get(), mRecipient, mCookie);
+ AIBinder_linkToDeath(mClient->asBinder().get(), mDeathRecipient.get(), mCookie);
+ }
+
+ void unlink() {
+ if (mClient != nullptr) {
+ // Unlink from the death notification.
+ AIBinder_unlinkToDeath(mClient->asBinder().get(), mDeathRecipient.get(), mCookie);
+ mClient = nullptr;
+ }
}
protected:
std::shared_ptr<IResourceManagerClient> mClient;
std::weak_ptr<ResourceManagerService> mService;
const ClientInfoParcel mClientInfo;
- AIBinder_DeathRecipient* mRecipient;
BinderDiedContext* mCookie;
+ ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
};
DeathNotifier::DeathNotifier(const std::shared_ptr<IResourceManagerClient>& client,
const std::shared_ptr<ResourceManagerService>& service,
- const ClientInfoParcel& clientInfo,
- AIBinder_DeathRecipient* recipient)
+ const ClientInfoParcel& clientInfo)
: mClient(client), mService(service), mClientInfo(clientInfo),
- mRecipient(recipient), mCookie(nullptr) {
- link();
+ mCookie(nullptr),
+ mDeathRecipient(::ndk::ScopedAIBinder_DeathRecipient(
+ AIBinder_DeathRecipient_new(BinderDiedCallback))) {
+ // Setting callback notification when DeathRecipient gets deleted.
+ AIBinder_DeathRecipient_setOnUnlinked(mDeathRecipient.get(), BinderUnlinkedCallback);
}
//static
@@ -140,9 +147,8 @@
public:
OverrideProcessInfoDeathNotifier(const std::shared_ptr<IResourceManagerClient>& client,
const std::shared_ptr<ResourceManagerService>& service,
- const ClientInfoParcel& clientInfo,
- AIBinder_DeathRecipient* recipient)
- : DeathNotifier(client, service, clientInfo, recipient) {}
+ const ClientInfoParcel& clientInfo)
+ : DeathNotifier(client, service, clientInfo) {}
virtual ~OverrideProcessInfoDeathNotifier() {}
@@ -160,6 +166,26 @@
service->removeProcessInfoOverride(mClientInfo.pid);
}
+std::shared_ptr<DeathNotifier> DeathNotifier::Create(
+ const std::shared_ptr<IResourceManagerClient>& client,
+ const std::shared_ptr<ResourceManagerService>& service,
+ const ClientInfoParcel& clientInfo,
+ bool overrideProcessInfo) {
+ std::shared_ptr<DeathNotifier> deathNotifier = nullptr;
+ if (overrideProcessInfo) {
+ deathNotifier = std::make_shared<OverrideProcessInfoDeathNotifier>(
+ client, service, clientInfo);
+ } else {
+ deathNotifier = std::make_shared<DeathNotifier>(client, service, clientInfo);
+ }
+
+ if (deathNotifier) {
+ deathNotifier->link();
+ }
+
+ return deathNotifier;
+}
+
template <typename T>
static String8 getString(const std::vector<T>& items) {
String8 itemsStr;
@@ -377,9 +403,7 @@
mServiceLog(new ServiceLog()),
mSupportsMultipleSecureCodecs(true),
mSupportsSecureWithNonSecureCodec(true),
- mCpuBoostCount(0),
- mDeathRecipient(::ndk::ScopedAIBinder_DeathRecipient(
- AIBinder_DeathRecipient_new(DeathNotifier::BinderDiedCallback))) {
+ mCpuBoostCount(0) {
mSystemCB->noteResetVideo();
// Create ResourceManagerMetrics that handles all the metrics.
mResourceManagerMetrics = std::make_unique<ResourceManagerMetrics>(mProcessInfo);
@@ -535,8 +559,8 @@
}
}
if (info.deathNotifier == nullptr && client != nullptr) {
- info.deathNotifier = std::make_shared<DeathNotifier>(
- client, ref<ResourceManagerService>(), clientInfo, mDeathRecipient.get());
+ info.deathNotifier = DeathNotifier::Create(
+ client, ref<ResourceManagerService>(), clientInfo);
}
if (mObserverService != nullptr && !resourceAdded.empty()) {
mObserverService->onResourceAdded(uid, pid, resourceAdded);
@@ -905,8 +929,8 @@
.uid = 0,
.id = 0,
.name = "<unknown client>"};
- auto deathNotifier = std::make_shared<OverrideProcessInfoDeathNotifier>(
- client, ref<ResourceManagerService>(), clientInfo, mDeathRecipient.get());
+ auto deathNotifier = DeathNotifier::Create(
+ client, ref<ResourceManagerService>(), clientInfo, true);
mProcessInfoOverrideMap.emplace(pid, ProcessInfoOverride{deathNotifier, client});
diff --git a/services/mediaresourcemanager/ResourceManagerService.h b/services/mediaresourcemanager/ResourceManagerService.h
index aa88ac6..637525d 100644
--- a/services/mediaresourcemanager/ResourceManagerService.h
+++ b/services/mediaresourcemanager/ResourceManagerService.h
@@ -204,7 +204,6 @@
bool mSupportsMultipleSecureCodecs;
bool mSupportsSecureWithNonSecureCodec;
int32_t mCpuBoostCount;
- ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
struct ProcessInfoOverride {
std::shared_ptr<DeathNotifier> deathNotifier = nullptr;
std::shared_ptr<IResourceManagerClient> client;
diff --git a/services/tuner/hidl/TunerHidlFilter.cpp b/services/tuner/hidl/TunerHidlFilter.cpp
index 617622d..be482c4 100644
--- a/services/tuner/hidl/TunerHidlFilter.cpp
+++ b/services/tuner/hidl/TunerHidlFilter.cpp
@@ -355,6 +355,11 @@
return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
}
+ // Call to HAL to make sure the transport FD was able to be closed by binder.
+ // This is a tricky workaround for a problem in Binder.
+ // TODO:[b/192048842] When that problem is fixed we may be able to remove or change this code.
+ mFilter_1_1->getId([&](HidlResult /* r */, uint32_t /* filterId*/){});
+
return ::ndk::ScopedAStatus::ok();
}
diff --git a/services/tuner/main_tunerservice.cpp b/services/tuner/main_tunerservice.cpp
index acfaf8a..6dee324 100644
--- a/services/tuner/main_tunerservice.cpp
+++ b/services/tuner/main_tunerservice.cpp
@@ -32,7 +32,8 @@
int main() {
ALOGD("Tuner service starting");
- if (!property_get_bool("tuner.server.enable", false)) {
+ if (!property_get_bool("tuner.server.enable", false)
+ && !property_get_bool("ro.tuner.lazyhal", false)) {
ALOGD("tuner is not enabled, terminating");
return 0;
}