Merge "MPEG4Writer: Better logging in DumpTimeStamps()"
diff --git a/apex/ld.config.txt b/apex/ld.config.txt
index a3e96c4..d50b353 100644
--- a/apex/ld.config.txt
+++ b/apex/ld.config.txt
@@ -49,6 +49,8 @@
# namespace.default.link.platform.shared_libs = %LLNDK_LIBRARIES%
# namespace.default.link.platform.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
namespace.default.link.platform.shared_libs = libEGL.so:libGLESv1_CM.so:libGLESv2.so:libGLESv3.so:libRS.so:libandroid_net.so:libc.so:libclang_rt.asan-aarch64-android.so:libclang_rt.asan-arm-android.so:libclang_rt.hwasan-aarch64-android.so:libclang_rt.asan-i686-android.so:libclang_rt.asan-x86_64-android.so:libdl.so:libft2.so:liblog.so:libm.so:libmediandk.so:libnativewindow.so:libneuralnetworks.so:libsync.so:libvndksupport.so:libvulkan.so
+# FIXME: b/129552044
+namespace.default.link.platform.shared_libs += libz.so
###############################################################################
# "platform" namespace
@@ -61,14 +63,14 @@
namespace.platform.search.paths = /system/${LIB}
namespace.platform.asan.search.paths = /data/asan/system/${LIB}
-# /system/lib/libc.so, etc are symlinks to /bionic/lib/libc.so, etc.
-# Add /bionic/lib to the permitted paths because linker uses realpath(3)
+# /system/lib/libc.so, etc are symlinks to /apex/com.android.lib/lib/bionic/libc.so, etc.
+# Add /apex/... pat to the permitted paths because linker uses realpath(3)
# to check the accessibility of the lib. We could add this to search.paths
# instead but that makes the resolution of bionic libs be dependent on
-# the order of /system/lib and /bionic/lib in search.paths. If /bionic/lib
-# is after /system/lib, then /bionic/lib is never tried because libc.so
+# the order of /system/lib and /apex/... in search.paths. If /apex/...
+# is after /system/lib, then /apex/... is never tried because libc.so
# is always found in /system/lib but fails to pass the accessibility test
# because of its realpath. It's better to not depend on the ordering if
# possible.
-namespace.platform.permitted.paths = /bionic/${LIB}
-namespace.platform.asan.permitted.paths = /bionic/${LIB}
+namespace.platform.permitted.paths = /apex/com.android.runtime/${LIB}/bionic
+namespace.platform.asan.permitted.paths = /apex/com.android.runtime/${LIB}/bionic
diff --git a/camera/ndk/NdkCameraDevice.cpp b/camera/ndk/NdkCameraDevice.cpp
index 09b85d5..691996b 100644
--- a/camera/ndk/NdkCameraDevice.cpp
+++ b/camera/ndk/NdkCameraDevice.cpp
@@ -287,3 +287,16 @@
}
return device->createCaptureSession(outputs, sessionParameters, callbacks, session);
}
+
+EXPORT
+camera_status_t ACameraDevice_isSessionConfigurationSupported(
+ const ACameraDevice* device,
+ const ACaptureSessionOutputContainer* sessionOutputContainer) {
+ ATRACE_CALL();
+ if (device == nullptr || sessionOutputContainer == nullptr) {
+ ALOGE("%s: Error: invalid input: device %p, sessionOutputContainer %p",
+ __FUNCTION__, device, sessionOutputContainer);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ return device->isSessionConfigurationSupported(sessionOutputContainer);
+}
diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp
index 5e4fcd0..c9db01e 100644
--- a/camera/ndk/impl/ACameraDevice.cpp
+++ b/camera/ndk/impl/ACameraDevice.cpp
@@ -227,6 +227,55 @@
return ACAMERA_OK;
}
+camera_status_t CameraDevice::isSessionConfigurationSupported(
+ const ACaptureSessionOutputContainer* sessionOutputContainer) const {
+ Mutex::Autolock _l(mDeviceLock);
+ camera_status_t ret = checkCameraClosedOrErrorLocked();
+ if (ret != ACAMERA_OK) {
+ return ret;
+ }
+
+ SessionConfiguration sessionConfiguration(0 /*inputWidth*/, 0 /*inputHeight*/,
+ -1 /*inputFormat*/, CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE);
+ for (const auto& output : sessionOutputContainer->mOutputs) {
+ sp<IGraphicBufferProducer> iGBP(nullptr);
+ ret = getIGBPfromAnw(output.mWindow, iGBP);
+ if (ret != ACAMERA_OK) {
+ ALOGE("Camera device %s failed to extract graphic producer from native window",
+ getId());
+ return ret;
+ }
+
+ String16 physicalId16(output.mPhysicalCameraId.c_str());
+ OutputConfiguration outConfig(iGBP, output.mRotation, physicalId16,
+ OutputConfiguration::INVALID_SET_ID, true);
+
+ for (auto& anw : output.mSharedWindows) {
+ ret = getIGBPfromAnw(anw, iGBP);
+ if (ret != ACAMERA_OK) {
+ ALOGE("Camera device %s failed to extract graphic producer from native window",
+ getId());
+ return ret;
+ }
+ outConfig.addGraphicProducer(iGBP);
+ }
+
+ sessionConfiguration.addOutputConfiguration(outConfig);
+ }
+
+ bool supported = false;
+ binder::Status remoteRet = mRemote->isSessionConfigurationSupported(
+ sessionConfiguration, &supported);
+ if (remoteRet.serviceSpecificErrorCode() ==
+ hardware::ICameraService::ERROR_INVALID_OPERATION) {
+ return ACAMERA_ERROR_UNSUPPORTED_OPERATION;
+ } else if (!remoteRet.isOk()) {
+ return ACAMERA_ERROR_UNKNOWN;
+ } else {
+ return supported ? ACAMERA_OK : ACAMERA_ERROR_STREAM_CONFIGURE_FAIL;
+ }
+}
+
camera_status_t CameraDevice::updateOutputConfigurationLocked(ACaptureSessionOutput *output) {
camera_status_t ret = checkCameraClosedOrErrorLocked();
if (ret != ACAMERA_OK) {
diff --git a/camera/ndk/impl/ACameraDevice.h b/camera/ndk/impl/ACameraDevice.h
index 103efd5..56741ce 100644
--- a/camera/ndk/impl/ACameraDevice.h
+++ b/camera/ndk/impl/ACameraDevice.h
@@ -35,6 +35,7 @@
#include <media/stagefright/foundation/AMessage.h>
#include <camera/CaptureResult.h>
#include <camera/camera2/OutputConfiguration.h>
+#include <camera/camera2/SessionConfiguration.h>
#include <camera/camera2/CaptureRequest.h>
#include <camera/NdkCameraManager.h>
@@ -77,6 +78,9 @@
const ACameraCaptureSession_stateCallbacks* callbacks,
/*out*/ACameraCaptureSession** session);
+ camera_status_t isSessionConfigurationSupported(
+ const ACaptureSessionOutputContainer* sessionOutputContainer) const;
+
// Callbacks from camera service
class ServiceCallback : public hardware::camera2::BnCameraDeviceCallbacks {
public:
@@ -369,6 +373,11 @@
return mDevice->createCaptureSession(outputs, sessionParameters, callbacks, session);
}
+ camera_status_t isSessionConfigurationSupported(
+ const ACaptureSessionOutputContainer* sessionOutputContainer) const {
+ return mDevice->isSessionConfigurationSupported(sessionOutputContainer);
+ }
+
/***********************
* Device interal APIs *
***********************/
diff --git a/camera/ndk/include/camera/NdkCameraDevice.h b/camera/ndk/include/camera/NdkCameraDevice.h
index cedf83a..bc544e3 100644
--- a/camera/ndk/include/camera/NdkCameraDevice.h
+++ b/camera/ndk/include/camera/NdkCameraDevice.h
@@ -845,6 +845,43 @@
const ACameraIdList* physicalIdList,
/*out*/ACaptureRequest** request) __INTRODUCED_IN(29);
+/**
+ * Check whether a particular {@ACaptureSessionOutputContainer} is supported by
+ * the camera device.
+ *
+ * <p>This method performs a runtime check of a given {@link
+ * ACaptureSessionOutputContainer}. The result confirms whether or not the
+ * passed CaptureSession outputs can be successfully used to create a camera
+ * capture session using {@link ACameraDevice_createCaptureSession}.</p>
+ *
+ * <p>This method can be called at any point before, during and after active
+ * capture session. It must not impact normal camera behavior in any way and
+ * must complete significantly faster than creating a capture session.</p>
+ *
+ * <p>Although this method is faster than creating a new capture session, it is not intended
+ * to be used for exploring the entire space of supported stream combinations.</p>
+ *
+ * @param device the camera device of interest
+ * @param sessionOutputContainer the {@link ACaptureSessionOutputContainer} of
+ * interest.
+ *
+ * @return <ul>
+ * <li>{@link ACAMERA_OK} if the given {@link ACaptureSessionOutputContainer}
+ * is supported by the camera device.</li>
+ * <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if device, or sessionOutputContainer
+ * is NULL.</li>
+ * <li>{@link ACAMERA_ERROR_STREAM_CONFIGURE_FAIL} if the given
+ * {@link ACaptureSessionOutputContainer}
+ * is not supported by
+ * the camera
+ * device.</li>
+ * <li>{@link ACAMERA_ERROR_UNSUPPORTED_OPERATION} if the query operation is not
+ * supported by the camera device.</li>
+ */
+camera_status_t ACameraDevice_isSessionConfigurationSupported(
+ const ACameraDevice* device,
+ const ACaptureSessionOutputContainer* sessionOutputContainer) __INTRODUCED_IN(29);
+
#endif /* __ANDROID_API__ >= 29 */
__END_DECLS
diff --git a/camera/ndk/include/camera/NdkCameraError.h b/camera/ndk/include/camera/NdkCameraError.h
index 6b58155..fc618ee 100644
--- a/camera/ndk/include/camera/NdkCameraError.h
+++ b/camera/ndk/include/camera/NdkCameraError.h
@@ -106,7 +106,8 @@
/**
* Camera device does not support the stream configuration provided by application in
- * {@link ACameraDevice_createCaptureSession}.
+ * {@link ACameraDevice_createCaptureSession} or {@link
+ * ACameraDevice_isSessionConfigurationSupported}.
*/
ACAMERA_ERROR_STREAM_CONFIGURE_FAIL = ACAMERA_ERROR_BASE - 9,
@@ -130,6 +131,11 @@
* The application does not have permission to open camera.
*/
ACAMERA_ERROR_PERMISSION_DENIED = ACAMERA_ERROR_BASE - 13,
+
+ /**
+ * The operation is not supported by the camera device.
+ */
+ ACAMERA_ERROR_UNSUPPORTED_OPERATION = ACAMERA_ERROR_BASE - 14,
} camera_status_t;
#endif /* __ANDROID_API__ >= 24 */
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index c26ca69..acf6999 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -7762,7 +7762,9 @@
typedef enum acamera_metadata_enum_acamera_scaler_available_recommended_stream_configurations {
/**
* <p>Preview must only include non-stalling processed stream configurations with
- * output formats like YUV_420_888, IMPLEMENTATION_DEFINED, etc.</p>
+ * output formats like
+ * {@link AIMAGE_FORMAT_YUV_420_888 },
+ * {@link AIMAGE_FORMAT_PRIVATE }, etc.</p>
*/
ACAMERA_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_PREVIEW
= 0x0,
@@ -7777,19 +7779,20 @@
/**
* <p>Video snapshot must include stream configurations at least as big as
- * the maximum RECORD resolutions and only with format BLOB + DATASPACE_JFIF
- * format/dataspace combination (JPEG). Additionally the configurations shouldn't cause
- * preview glitches and also be able to run at 30 fps.</p>
+ * the maximum RECORD resolutions and only with
+ * {@link AIMAGE_FORMAT_JPEG JPEG output format}.
+ * Additionally the configurations shouldn't cause preview glitches and also be able to
+ * run at 30 fps.</p>
*/
ACAMERA_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_VIDEO_SNAPSHOT
= 0x2,
/**
* <p>Recommended snapshot stream configurations must include at least one with
- * size close to ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE with BLOB + DATASPACE_JFIF
- * format/dataspace combination (JPEG). Taking into account restrictions on aspect
- * ratio, alignment etc. the area of the maximum suggested size shouldn’t be less than
- * 97% of the sensor array size area.</p>
+ * size close to ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE and
+ * {@link AIMAGE_FORMAT_JPEG JPEG output format}.
+ * Taking into account restrictions on aspect ratio, alignment etc. the area of the
+ * maximum suggested size shouldn’t be less than 97% of the sensor array size area.</p>
*
* @see ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE
*/
@@ -7808,9 +7811,20 @@
*/
ACAMERA_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_RAW = 0x5,
- ACAMERA_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_PUBLIC_END
+ /**
+ * <p>If supported, the recommended low latency stream configurations must have
+ * end-to-end latency that does not exceed 200 ms. under standard operating conditions
+ * (reasonable light levels, not loaded system) and using template
+ * TEMPLATE_STILL_CAPTURE. This is primarily for listing configurations for the
+ * {@link AIMAGE_FORMAT_JPEG JPEG output format}
+ * however other supported output formats can be added as well.</p>
+ */
+ ACAMERA_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_LOW_LATENCY_SNAPSHOT
= 0x6,
+ ACAMERA_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_PUBLIC_END
+ = 0x7,
+
/**
* <p>Vendor defined use cases. These depend on the vendor implementation.</p>
*/
diff --git a/camera/ndk/libcamera2ndk.map.txt b/camera/ndk/libcamera2ndk.map.txt
index 946a98e..b6f1553 100644
--- a/camera/ndk/libcamera2ndk.map.txt
+++ b/camera/ndk/libcamera2ndk.map.txt
@@ -14,6 +14,7 @@
ACameraDevice_createCaptureRequest_withPhysicalIds; # introduced=29
ACameraDevice_createCaptureSession;
ACameraDevice_createCaptureSessionWithSessionParameters; # introduced=28
+ ACameraDevice_isSessionConfigurationSupported; # introduced=29
ACameraDevice_getId;
ACameraManager_create;
ACameraManager_delete;
diff --git a/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp b/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
index a38a31e..d7d774b 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
+++ b/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
@@ -38,6 +38,7 @@
using HCameraMetadata = frameworks::cameraservice::device::V2_0::CameraMetadata;
using OutputConfiguration = frameworks::cameraservice::device::V2_0::OutputConfiguration;
+using SessionConfiguration = frameworks::cameraservice::device::V2_0::SessionConfiguration;
using hardware::Void;
// Static member definitions
@@ -216,6 +217,47 @@
return ACAMERA_OK;
}
+camera_status_t CameraDevice::isSessionConfigurationSupported(
+ const ACaptureSessionOutputContainer* sessionOutputContainer) const {
+ Mutex::Autolock _l(mDeviceLock);
+ camera_status_t ret = checkCameraClosedOrErrorLocked();
+ if (ret != ACAMERA_OK) {
+ return ret;
+ }
+
+ SessionConfiguration sessionConfig;
+ sessionConfig.inputWidth = 0;
+ sessionConfig.inputHeight = 0;
+ sessionConfig.inputFormat = -1;
+ sessionConfig.operationMode = StreamConfigurationMode::NORMAL_MODE;
+ sessionConfig.outputStreams.resize(sessionOutputContainer->mOutputs.size());
+ size_t index = 0;
+ for (const auto& output : sessionOutputContainer->mOutputs) {
+ sessionConfig.outputStreams[index].rotation = utils::convertToHidl(output.mRotation);
+ sessionConfig.outputStreams[index].windowGroupId = -1;
+ sessionConfig.outputStreams[index].windowHandles.resize(output.mSharedWindows.size() + 1);
+ sessionConfig.outputStreams[index].windowHandles[0] = output.mWindow;
+ sessionConfig.outputStreams[index].physicalCameraId = output.mPhysicalCameraId;
+ index++;
+ }
+
+ bool configSupported = false;
+ Status status = Status::NO_ERROR;
+ auto remoteRet = mRemote->isSessionConfigurationSupported(sessionConfig,
+ [&status, &configSupported](auto s, auto supported) {
+ status = s;
+ configSupported = supported;
+ });
+
+ if (status == Status::INVALID_OPERATION) {
+ return ACAMERA_ERROR_UNSUPPORTED_OPERATION;
+ } else if (!remoteRet.isOk()) {
+ return ACAMERA_ERROR_UNKNOWN;
+ } else {
+ return configSupported ? ACAMERA_OK : ACAMERA_ERROR_STREAM_CONFIGURE_FAIL;
+ }
+}
+
void CameraDevice::addRequestSettingsMetadata(ACaptureRequest *aCaptureRequest,
sp<CaptureRequest> &req) {
CameraMetadata metadataCopy = aCaptureRequest->settings->getInternalData();
diff --git a/camera/ndk/ndk_vendor/impl/ACameraDevice.h b/camera/ndk/ndk_vendor/impl/ACameraDevice.h
index 28092fd..47e6f56 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraDevice.h
+++ b/camera/ndk/ndk_vendor/impl/ACameraDevice.h
@@ -101,6 +101,9 @@
const ACameraCaptureSession_stateCallbacks* callbacks,
/*out*/ACameraCaptureSession** session);
+ camera_status_t isSessionConfigurationSupported(
+ const ACaptureSessionOutputContainer* sessionOutputContainer) const;
+
// Callbacks from camera service
class ServiceCallback : public ICameraDeviceCallback {
public:
@@ -397,6 +400,11 @@
return mDevice->createCaptureSession(outputs, sessionParameters, callbacks, session);
}
+ camera_status_t isSessionConfigurationSupported(
+ const ACaptureSessionOutputContainer* sessionOutputContainer) const {
+ return mDevice->isSessionConfigurationSupported(sessionOutputContainer);
+ }
+
/***********************
* Device interal APIs *
***********************/
diff --git a/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp b/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
index 2398922..c51f93b 100644
--- a/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
+++ b/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
@@ -121,6 +121,12 @@
cameraIdList.numCameras = idPointerList.size();
cameraIdList.cameraIds = idPointerList.data();
+ ret = ACameraDevice_isSessionConfigurationSupported(mDevice, mOutputs);
+ if (ret != ACAMERA_OK && ret != ACAMERA_ERROR_UNSUPPORTED_OPERATION) {
+ ALOGE("ACameraDevice_isSessionConfigurationSupported failed, ret=%d", ret);
+ return ret;
+ }
+
ret = ACameraDevice_createCaptureSession(mDevice, mOutputs, &mSessionCb, &mSession);
if (ret != AMEDIA_OK) {
ALOGE("ACameraDevice_createCaptureSession failed, ret=%d", ret);
diff --git a/media/codec2/components/base/Android.bp b/media/codec2/components/base/Android.bp
index 78a444b..f10835f 100644
--- a/media/codec2/components/base/Android.bp
+++ b/media/codec2/components/base/Android.bp
@@ -36,13 +36,18 @@
ldflags: ["-Wl,-Bsymbolic"],
}
+filegroup {
+ name: "codec2_soft_exports",
+ srcs: [ "exports.lds" ],
+}
+
// public dependency for software codec implementation
// to be used by code under media/codecs/* only as its stability is not guaranteed
cc_defaults {
name: "libcodec2_soft-defaults",
defaults: ["libcodec2-impl-defaults"],
vendor_available: true,
-
+ version_script: ":codec2_soft_exports",
export_shared_lib_headers: [
"libsfplugin_ccodec_utils",
],
diff --git a/media/codec2/components/base/exports.lds b/media/codec2/components/base/exports.lds
new file mode 100644
index 0000000..641bae8
--- /dev/null
+++ b/media/codec2/components/base/exports.lds
@@ -0,0 +1,7 @@
+{
+ global:
+ CreateCodec2Factory;
+ DestroyCodec2Factory;
+ local: *;
+};
+
diff --git a/media/codec2/components/hevc/C2SoftHevcEnc.cpp b/media/codec2/components/hevc/C2SoftHevcEnc.cpp
index 7045b6a..402d9aa 100644
--- a/media/codec2/components/hevc/C2SoftHevcEnc.cpp
+++ b/media/codec2/components/hevc/C2SoftHevcEnc.cpp
@@ -94,6 +94,20 @@
// matches limits in codec library
addParameter(
+ DefineParam(mBitrateMode, C2_PARAMKEY_BITRATE_MODE)
+ .withDefault(new C2StreamBitrateModeTuning::output(
+ 0u, C2Config::BITRATE_VARIABLE))
+ .withFields({
+ C2F(mBitrateMode, value).oneOf({
+ C2Config::BITRATE_CONST,
+ C2Config::BITRATE_VARIABLE,
+ C2Config::BITRATE_IGNORE})
+ })
+ .withSetter(
+ Setter<decltype(*mBitrateMode)>::StrictValueWithNoDeps)
+ .build());
+
+ addParameter(
DefineParam(mBitrate, C2_PARAMKEY_BITRATE)
.withDefault(new C2StreamBitrateInfo::output(0u, 64000))
.withFields({C2F(mBitrate, value).inRange(4096, 12000000)})
@@ -102,6 +116,20 @@
// matches levels allowed within codec library
addParameter(
+ DefineParam(mComplexity, C2_PARAMKEY_COMPLEXITY)
+ .withDefault(new C2StreamComplexityTuning::output(0u, 0))
+ .withFields({C2F(mComplexity, value).inRange(0, 10)})
+ .withSetter(Setter<decltype(*mComplexity)>::NonStrictValueWithNoDeps)
+ .build());
+
+ addParameter(
+ DefineParam(mQuality, C2_PARAMKEY_QUALITY)
+ .withDefault(new C2StreamQualityTuning::output(0u, 80))
+ .withFields({C2F(mQuality, value).inRange(0, 100)})
+ .withSetter(Setter<decltype(*mQuality)>::NonStrictValueWithNoDeps)
+ .build());
+
+ addParameter(
DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
.withDefault(new C2StreamProfileLevelInfo::output(
0u, PROFILE_HEVC_MAIN, LEVEL_HEVC_MAIN_1))
@@ -287,12 +315,21 @@
std::shared_ptr<C2StreamFrameRateInfo::output> getFrameRate_l() const {
return mFrameRate;
}
+ std::shared_ptr<C2StreamBitrateModeTuning::output> getBitrateMode_l() const {
+ return mBitrateMode;
+ }
std::shared_ptr<C2StreamBitrateInfo::output> getBitrate_l() const {
return mBitrate;
}
std::shared_ptr<C2StreamRequestSyncFrameTuning::output> getRequestSync_l() const {
return mRequestSync;
}
+ std::shared_ptr<C2StreamComplexityTuning::output> getComplexity_l() const {
+ return mComplexity;
+ }
+ std::shared_ptr<C2StreamQualityTuning::output> getQuality_l() const {
+ return mQuality;
+ }
private:
std::shared_ptr<C2StreamBufferTypeSetting::input> mInputFormat;
@@ -304,6 +341,9 @@
std::shared_ptr<C2StreamFrameRateInfo::output> mFrameRate;
std::shared_ptr<C2StreamRequestSyncFrameTuning::output> mRequestSync;
std::shared_ptr<C2StreamBitrateInfo::output> mBitrate;
+ std::shared_ptr<C2StreamBitrateModeTuning::output> mBitrateMode;
+ std::shared_ptr<C2StreamComplexityTuning::output> mComplexity;
+ std::shared_ptr<C2StreamQualityTuning::output> mQuality;
std::shared_ptr<C2StreamProfileLevelInfo::output> mProfileLevel;
std::shared_ptr<C2StreamSyncFrameIntervalTuning::output> mSyncFramePeriod;
};
@@ -387,6 +427,19 @@
work->workletsProcessed = 1u;
}
+static int getQpFromQuality(int quality) {
+ int qp;
+#define MIN_QP 4
+#define MAX_QP 50
+ /* Quality: 100 -> Qp : MIN_QP
+ * Quality: 0 -> Qp : MAX_QP
+ * Qp = ((MIN_QP - MAX_QP) * quality / 100) + MAX_QP;
+ */
+ qp = ((MIN_QP - MAX_QP) * quality / 100) + MAX_QP;
+ qp = std::min(qp, MAX_QP);
+ qp = std::max(qp, MIN_QP);
+ return qp;
+}
c2_status_t C2SoftHevcEnc::initEncParams() {
mCodecCtx = nullptr;
mNumCores = std::min(GetCPUCoreCount(), (size_t) CODEC_MAX_CORES);
@@ -416,9 +469,37 @@
mIvVideoColorFormat = IV_YUV_420P;
mEncParams.s_multi_thrd_prms.i4_max_num_cores = mNumCores;
mEncParams.s_out_strm_prms.i4_codec_profile = mHevcEncProfile;
- mEncParams.s_config_prms.i4_rate_control_mode = 2;
mEncParams.s_lap_prms.i4_rc_look_ahead_pics = 0;
+ switch (mBitrateMode->value) {
+ case C2Config::BITRATE_IGNORE:
+ mEncParams.s_config_prms.i4_rate_control_mode = 3;
+ mEncParams.s_tgt_lyr_prms.as_tgt_params[0].ai4_frame_qp[0] =
+ getQpFromQuality(mQuality->value);
+ break;
+ case C2Config::BITRATE_CONST:
+ mEncParams.s_config_prms.i4_rate_control_mode = 5;
+ break;
+ case C2Config::BITRATE_VARIABLE:
+ [[fallthrough]];
+ default:
+ mEncParams.s_config_prms.i4_rate_control_mode = 2;
+ break;
+ break;
+ }
+
+ if (mComplexity->value == 10) {
+ mEncParams.s_tgt_lyr_prms.as_tgt_params[0].i4_quality_preset = IHEVCE_QUALITY_P0;
+ } else if (mComplexity->value >= 8) {
+ mEncParams.s_tgt_lyr_prms.as_tgt_params[0].i4_quality_preset = IHEVCE_QUALITY_P2;
+ } else if (mComplexity->value >= 7) {
+ mEncParams.s_tgt_lyr_prms.as_tgt_params[0].i4_quality_preset = IHEVCE_QUALITY_P3;
+ } else if (mComplexity->value >= 5) {
+ mEncParams.s_tgt_lyr_prms.as_tgt_params[0].i4_quality_preset = IHEVCE_QUALITY_P4;
+ } else {
+ mEncParams.s_tgt_lyr_prms.as_tgt_params[0].i4_quality_preset = IHEVCE_QUALITY_P5;
+ }
+
return C2_OK;
}
@@ -447,11 +528,14 @@
{
IntfImpl::Lock lock = mIntf->lock();
mSize = mIntf->getSize_l();
+ mBitrateMode = mIntf->getBitrateMode_l();
mBitrate = mIntf->getBitrate_l();
mFrameRate = mIntf->getFrameRate_l();
mHevcEncProfile = mIntf->getProfile_l();
mHevcEncLevel = mIntf->getLevel_l();
mIDRInterval = mIntf->getSyncFramePeriod_l();
+ mComplexity = mIntf->getComplexity_l();
+ mQuality = mIntf->getQuality_l();
}
c2_status_t status = initEncParams();
diff --git a/media/codec2/components/hevc/C2SoftHevcEnc.h b/media/codec2/components/hevc/C2SoftHevcEnc.h
index 9d90b95..8569a3e 100644
--- a/media/codec2/components/hevc/C2SoftHevcEnc.h
+++ b/media/codec2/components/hevc/C2SoftHevcEnc.h
@@ -77,6 +77,9 @@
std::shared_ptr<C2StreamPictureSizeInfo::input> mSize;
std::shared_ptr<C2StreamFrameRateInfo::output> mFrameRate;
std::shared_ptr<C2StreamBitrateInfo::output> mBitrate;
+ std::shared_ptr<C2StreamBitrateModeTuning::output> mBitrateMode;
+ std::shared_ptr<C2StreamComplexityTuning::output> mComplexity;
+ std::shared_ptr<C2StreamQualityTuning::output> mQuality;
#ifdef FILE_DUMP_ENABLE
char mInFile[200];
diff --git a/media/codec2/hidl/1.0/utils/Android.bp b/media/codec2/hidl/1.0/utils/Android.bp
index f5aa65b..97dde71 100644
--- a/media/codec2/hidl/1.0/utils/Android.bp
+++ b/media/codec2/hidl/1.0/utils/Android.bp
@@ -27,15 +27,18 @@
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",
+ "android.hidl.safe_union@1.0",
"libbase",
"libcodec2",
"libcodec2_vndk",
"libcutils",
+ "libgui",
"libhidlbase",
"libhidltransport",
"libhwbinder",
diff --git a/media/codec2/hidl/1.0/utils/Component.cpp b/media/codec2/hidl/1.0/utils/Component.cpp
index f3bf6f7..5897dce 100644
--- a/media/codec2/hidl/1.0/utils/Component.cpp
+++ b/media/codec2/hidl/1.0/utils/Component.cpp
@@ -272,7 +272,7 @@
Return<Status> Component::setOutputSurface(
uint64_t blockPoolId,
- const sp<HGraphicBufferProducer>& surface) {
+ const sp<HGraphicBufferProducer2>& surface) {
std::shared_ptr<C2BlockPool> pool;
GetCodec2BlockPool(blockPoolId, mComponent, &pool);
if (pool && pool->getAllocatorId() == C2PlatformAllocatorStore::BUFFERQUEUE) {
@@ -312,7 +312,7 @@
}
Return<void> Component::connectToOmxInputSurface(
- const sp<HGraphicBufferProducer>& producer,
+ const sp<HGraphicBufferProducer1>& producer,
const sp<::android::hardware::media::omx::V1_0::
IGraphicBufferSource>& source,
connectToOmxInputSurface_cb _hidl_cb) {
diff --git a/media/codec2/hidl/1.0/utils/ComponentStore.cpp b/media/codec2/hidl/1.0/utils/ComponentStore.cpp
index bb5faa5..53bb6d2 100644
--- a/media/codec2/hidl/1.0/utils/ComponentStore.cpp
+++ b/media/codec2/hidl/1.0/utils/ComponentStore.cpp
@@ -23,7 +23,7 @@
#include <codec2/hidl/1.0/types.h>
#include <android-base/file.h>
-#include <media/stagefright/bqhelper/WGraphicBufferProducer.h>
+#include <gui/bufferqueue/2.0/B2HGraphicBufferProducer.h>
#include <media/stagefright/bqhelper/GraphicBufferSource.h>
#include <utils/Errors.h>
@@ -219,13 +219,11 @@
_hidl_cb(Status::CORRUPTED, nullptr);
return Void();
}
- typedef ::android::hardware::graphics::bufferqueue::V1_0::
- IGraphicBufferProducer HGbp;
- typedef ::android::TWGraphicBufferProducer<HGbp> B2HGbp;
sp<InputSurface> inputSurface = new InputSurface(
this,
std::make_shared<C2ReflectorHelper>(),
- new B2HGbp(source->getIGraphicBufferProducer()),
+ new ::android::hardware::graphics::bufferqueue::V2_0::utils::
+ B2HGraphicBufferProducer(source->getIGraphicBufferProducer()),
source);
_hidl_cb(inputSurface ? Status::OK : Status::NO_MEMORY,
inputSurface);
diff --git a/media/codec2/hidl/1.0/utils/InputSurface.cpp b/media/codec2/hidl/1.0/utils/InputSurface.cpp
index 85c44c3..2b4ca85 100644
--- a/media/codec2/hidl/1.0/utils/InputSurface.cpp
+++ b/media/codec2/hidl/1.0/utils/InputSurface.cpp
@@ -151,8 +151,6 @@
return Void();
}
-// Derived methods from IGraphicBufferProducer
-
// Constructor is exclusive to ComponentStore.
InputSurface::InputSurface(
const sp<ComponentStore>& store,
diff --git a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/Component.h b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/Component.h
index e444013..86dccd0 100644
--- a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/Component.h
+++ b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/Component.h
@@ -68,7 +68,9 @@
c2_status_t status() const;
typedef ::android::hardware::graphics::bufferqueue::V1_0::
- IGraphicBufferProducer HGraphicBufferProducer;
+ IGraphicBufferProducer HGraphicBufferProducer1;
+ typedef ::android::hardware::graphics::bufferqueue::V2_0::
+ IGraphicBufferProducer HGraphicBufferProducer2;
// Methods from IComponent follow.
virtual Return<Status> queue(const WorkBundle& workBundle) override;
@@ -76,12 +78,12 @@
virtual Return<Status> drain(bool withEos) override;
virtual Return<Status> setOutputSurface(
uint64_t blockPoolId,
- const sp<HGraphicBufferProducer>& surface) override;
+ const sp<HGraphicBufferProducer2>& surface) override;
virtual Return<void> connectToInputSurface(
const sp<IInputSurface>& inputSurface,
connectToInputSurface_cb _hidl_cb) override;
virtual Return<void> connectToOmxInputSurface(
- const sp<HGraphicBufferProducer>& producer,
+ const sp<HGraphicBufferProducer1>& producer,
const sp<::android::hardware::media::omx::V1_0::
IGraphicBufferSource>& source,
connectToOmxInputSurface_cb _hidl_cb) override;
diff --git a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputSurface.h b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputSurface.h
index 2682c13..34ea959 100644
--- a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputSurface.h
+++ b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputSurface.h
@@ -19,7 +19,7 @@
#include <codec2/hidl/1.0/ComponentStore.h>
-#include <android/hardware/graphics/bufferqueue/1.0/IGraphicBufferProducer.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 <gui/IGraphicBufferProducer.h>
@@ -44,7 +44,7 @@
struct InputSurface : public IInputSurface {
- typedef ::android::hardware::graphics::bufferqueue::V1_0::
+ typedef ::android::hardware::graphics::bufferqueue::V2_0::
IGraphicBufferProducer HGraphicBufferProducer;
typedef ::android::
diff --git a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/types.h b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/types.h
index b9f3aa8..817d148 100644
--- a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/types.h
+++ b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/types.h
@@ -22,6 +22,7 @@
#include <android/hardware/media/bufferpool/2.0/types.h>
#include <android/hardware/media/c2/1.0/IComponentStore.h>
#include <android/hardware/media/c2/1.0/types.h>
+#include <android/hidl/safe_union/1.0/types.h>
#include <gui/IGraphicBufferProducer.h>
#include <C2Component.h>
diff --git a/media/codec2/hidl/1.0/utils/types.cpp b/media/codec2/hidl/1.0/utils/types.cpp
index 343bcb5..74320e7 100644
--- a/media/codec2/hidl/1.0/utils/types.cpp
+++ b/media/codec2/hidl/1.0/utils/types.cpp
@@ -18,9 +18,9 @@
#define LOG_TAG "Codec2-types"
#include <android-base/logging.h>
+#include <android/hardware/graphics/bufferqueue/2.0/IGraphicBufferProducer.h>
#include <codec2/hidl/1.0/types.h>
-
-#include <media/stagefright/bqhelper/WGraphicBufferProducer.h>
+#include <gui/bufferqueue/2.0/B2HGraphicBufferProducer.h>
#include <media/stagefright/foundation/AUtils.h>
#include <C2AllocatorIon.h>
@@ -46,7 +46,6 @@
namespace V1_0 {
namespace utils {
-using namespace ::android;
using ::android::hardware::Return;
using ::android::hardware::media::bufferpool::BufferPoolData;
using ::android::hardware::media::bufferpool::V2_0::BufferStatusMessage;
@@ -55,7 +54,10 @@
ClientManager;
using ::android::hardware::media::bufferpool::V2_0::implementation::
TransactionId;
-using ::android::TWGraphicBufferProducer;
+using HGraphicBufferProducer = ::android::hardware::graphics::bufferqueue::
+ V2_0::IGraphicBufferProducer;
+using B2HGraphicBufferProducer = ::android::hardware::graphics::bufferqueue::
+ V2_0::utils::B2HGraphicBufferProducer;
const char* asString(Status status, const char* def) {
return asString(static_cast<c2_status_t>(status), def);
@@ -118,9 +120,9 @@
return true;
}
-// C2FieldSupportedValues::range's type -> FieldSupportedValues::Range
+// C2FieldSupportedValues::range's type -> ValueRange
bool objcpy(
- FieldSupportedValues::Range* d,
+ ValueRange* d,
const decltype(C2FieldSupportedValues::range)& s) {
d->min = static_cast<PrimitiveValue>(s.min.u64);
d->max = static_cast<PrimitiveValue>(s.max.u64);
@@ -133,45 +135,45 @@
// C2FieldSupportedValues -> FieldSupportedValues
bool objcpy(FieldSupportedValues *d, const C2FieldSupportedValues &s) {
switch (s.type) {
- case C2FieldSupportedValues::EMPTY:
- d->type = FieldSupportedValues::Type::EMPTY;
- d->values.resize(0);
- break;
- case C2FieldSupportedValues::RANGE:
- d->type = FieldSupportedValues::Type::RANGE;
- if (!objcpy(&d->range, s.range)) {
- LOG(ERROR) << "Invalid C2FieldSupportedValues::range.";
- return false;
+ case C2FieldSupportedValues::EMPTY: {
+ d->empty(::android::hidl::safe_union::V1_0::Monostate{});
+ break;
}
- d->values.resize(0);
- break;
- default:
- switch (s.type) {
- case C2FieldSupportedValues::VALUES:
- d->type = FieldSupportedValues::Type::VALUES;
- break;
- case C2FieldSupportedValues::FLAGS:
- d->type = FieldSupportedValues::Type::FLAGS;
- break;
- default:
- LOG(DEBUG) << "Unrecognized C2FieldSupportedValues::type_t "
- << "with underlying value " << underlying_value(s.type)
- << ".";
- d->type = static_cast<FieldSupportedValues::Type>(s.type);
- if (!objcpy(&d->range, s.range)) {
+ case C2FieldSupportedValues::RANGE: {
+ ValueRange range{};
+ if (!objcpy(&range, s.range)) {
LOG(ERROR) << "Invalid C2FieldSupportedValues::range.";
+ d->range(range);
return false;
}
+ d->range(range);
+ break;
}
- copyVector<uint64_t>(&d->values, s.values);
+ case C2FieldSupportedValues::VALUES: {
+ hidl_vec<PrimitiveValue> values;
+ copyVector<uint64_t>(&values, s.values);
+ d->values(values);
+ break;
+ }
+ case C2FieldSupportedValues::FLAGS: {
+ hidl_vec<PrimitiveValue> flags;
+ copyVector<uint64_t>(&flags, s.values);
+ d->flags(flags);
+ break;
+ }
+ default:
+ LOG(DEBUG) << "Unrecognized C2FieldSupportedValues::type_t "
+ << "with underlying value " << underlying_value(s.type)
+ << ".";
+ return false;
}
return true;
}
-// FieldSupportedValues::Range -> C2FieldSupportedValues::range's type
+// ValueRange -> C2FieldSupportedValues::range's type
bool objcpy(
decltype(C2FieldSupportedValues::range)* d,
- const FieldSupportedValues::Range& s) {
+ const ValueRange& s) {
d->min.u64 = static_cast<uint64_t>(s.min);
d->max.u64 = static_cast<uint64_t>(s.max);
d->step.u64 = static_cast<uint64_t>(s.step);
@@ -182,37 +184,33 @@
// FieldSupportedValues -> C2FieldSupportedValues
bool objcpy(C2FieldSupportedValues *d, const FieldSupportedValues &s) {
- switch (s.type) {
- case FieldSupportedValues::Type::EMPTY:
- d->type = C2FieldSupportedValues::EMPTY;
- break;
- case FieldSupportedValues::Type::RANGE:
- d->type = C2FieldSupportedValues::RANGE;
- if (!objcpy(&d->range, s.range)) {
- LOG(ERROR) << "Invalid FieldSupportedValues::range.";
- return false;
+ switch (s.getDiscriminator()) {
+ case FieldSupportedValues::hidl_discriminator::empty: {
+ d->type = C2FieldSupportedValues::EMPTY;
+ break;
}
- d->values.resize(0);
- break;
- default:
- switch (s.type) {
- case FieldSupportedValues::Type::VALUES:
- d->type = C2FieldSupportedValues::VALUES;
- break;
- case FieldSupportedValues::Type::FLAGS:
- d->type = C2FieldSupportedValues::FLAGS;
- break;
- default:
- LOG(DEBUG) << "Unrecognized FieldSupportedValues::Type "
- << "with underlying value " << underlying_value(s.type)
- << ".";
- d->type = static_cast<C2FieldSupportedValues::type_t>(s.type);
- if (!objcpy(&d->range, s.range)) {
+ case FieldSupportedValues::hidl_discriminator::range: {
+ d->type = C2FieldSupportedValues::RANGE;
+ if (!objcpy(&d->range, s.range())) {
LOG(ERROR) << "Invalid FieldSupportedValues::range.";
return false;
}
+ d->values.resize(0);
+ break;
}
- copyVector<uint64_t>(&d->values, s.values);
+ case FieldSupportedValues::hidl_discriminator::values: {
+ d->type = C2FieldSupportedValues::VALUES;
+ copyVector<uint64_t>(&d->values, s.values());
+ break;
+ }
+ case FieldSupportedValues::hidl_discriminator::flags: {
+ d->type = C2FieldSupportedValues::FLAGS;
+ copyVector<uint64_t>(&d->values, s.flags());
+ break;
+ }
+ default:
+ LOG(WARNING) << "Unrecognized FieldSupportedValues::getDiscriminator()";
+ return false;
}
return true;
}
@@ -1806,7 +1804,7 @@
sp<HGraphicBufferProducer> hgbp =
igbp->getHalInterface<HGraphicBufferProducer>();
return hgbp ? hgbp :
- new TWGraphicBufferProducer<HGraphicBufferProducer>(igbp);
+ new B2HGraphicBufferProducer(igbp);
}
} // unnamed namespace
diff --git a/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.cpp b/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.cpp
index 1f36270..d73b731 100644
--- a/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.cpp
@@ -127,4 +127,12 @@
queueCondition.notify_all();
}
}
-}
\ No newline at end of file
+}
+
+// Return current time in micro seconds
+int64_t getNowUs() {
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+
+ return (int64_t)tv.tv_usec + tv.tv_sec * 1000000ll;
+}
diff --git a/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h b/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h
index fca2902..c577dac 100644
--- a/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h
+++ b/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h
@@ -201,4 +201,6 @@
std::list<std::unique_ptr<C2Work>>& workQueue, bool& eos, bool& csd,
uint32_t& framesReceived);
+int64_t getNowUs();
+
#endif // MEDIA_C2_HIDL_TEST_COMMON_H
diff --git a/media/codec2/hidl/1.0/vts/functional/component/VtsHidlC2V1_0TargetComponentTest.cpp b/media/codec2/hidl/1.0/vts/functional/component/VtsHidlC2V1_0TargetComponentTest.cpp
index ec803d7..74548b5 100644
--- a/media/codec2/hidl/1.0/vts/functional/component/VtsHidlC2V1_0TargetComponentTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/component/VtsHidlC2V1_0TargetComponentTest.cpp
@@ -26,6 +26,32 @@
#include <VtsHalHidlTargetTestBase.h>
#include "media_c2_hidl_test_common.h"
+/* Time_Out for start(), stop(), reset(), release(), flush(), queue() are
+ * defined in hardware/interfaces/media/c2/1.0/IComponent.hal. Adding 50ms
+ * extra in case of timeout is 500ms, 1ms extra in case timeout is 1ms/5ms. All
+ * timeout is calculated in us.
+ */
+#define START_TIME_OUT 550000
+#define STOP_TIME_OUT 550000
+#define RESET_TIME_OUT 550000
+#define RELEASE_TIME_OUT 550000
+#define FLUSH_TIME_OUT 6000
+#define QUEUE_TIME_OUT 2000
+
+// Time_Out for config(), query(), querySupportedParams() are defined in
+// hardware/interfaces/media/c2/1.0/IConfigurable.hal.
+#define CONFIG_TIME_OUT 6000
+#define QUERY_TIME_OUT 6000
+#define QUERYSUPPORTEDPARAMS_TIME_OUT 2000
+
+#define CHECK_TIMEOUT(timeConsumed, TIME_OUT, FuncName) \
+ if (timeConsumed > TIME_OUT) { \
+ ALOGW( \
+ "TIMED_OUT %s timeConsumed=%" PRId64 " us is " \
+ "greater than threshold %d us", \
+ FuncName, timeConsumed, TIME_OUT); \
+ }
+
static ComponentTestEnvironment* gEnv = nullptr;
namespace {
@@ -244,6 +270,93 @@
std::make_pair(C2FrameData::FLAG_CODEC_CONFIG, false),
std::make_pair(C2FrameData::FLAG_END_OF_STREAM, false)));
+// Test API's Timeout
+TEST_F(Codec2ComponentHidlTest, Timeout) {
+ ALOGV("Timeout Test");
+ c2_status_t err = C2_OK;
+
+ int64_t startTime = getNowUs();
+ err = mComponent->start();
+ int64_t timeConsumed = getNowUs() - startTime;
+ CHECK_TIMEOUT(timeConsumed, START_TIME_OUT, "start()");
+ ALOGV("mComponent->start() timeConsumed=%" PRId64 " us", timeConsumed);
+ ASSERT_EQ(err, C2_OK);
+
+ startTime = getNowUs();
+ err = mComponent->reset();
+ timeConsumed = getNowUs() - startTime;
+ CHECK_TIMEOUT(timeConsumed, RESET_TIME_OUT, "reset()");
+ ALOGV("mComponent->reset() timeConsumed=%" PRId64 " us", timeConsumed);
+ ASSERT_EQ(err, C2_OK);
+
+ err = mComponent->start();
+ ASSERT_EQ(err, C2_OK);
+
+ // Query supported params by the component
+ std::vector<std::shared_ptr<C2ParamDescriptor>> params;
+ startTime = getNowUs();
+ err = mComponent->querySupportedParams(¶ms);
+ timeConsumed = getNowUs() - startTime;
+ CHECK_TIMEOUT(timeConsumed, QUERYSUPPORTEDPARAMS_TIME_OUT,
+ "querySupportedParams()");
+ ALOGV("mComponent->querySupportedParams() timeConsumed=%" PRId64 " us",
+ timeConsumed);
+ ASSERT_EQ(err, C2_OK);
+
+ std::vector<std::unique_ptr<C2Param>> queried;
+ std::vector<std::unique_ptr<C2SettingResult>> failures;
+ // Query and config all the supported params
+ for (std::shared_ptr<C2ParamDescriptor> p : params) {
+ startTime = getNowUs();
+ err = mComponent->query({}, {p->index()}, C2_DONT_BLOCK, &queried);
+ timeConsumed = getNowUs() - startTime;
+ CHECK_TIMEOUT(timeConsumed, QUERY_TIME_OUT, "query()");
+ EXPECT_NE(queried.size(), 0u);
+ EXPECT_EQ(err, C2_OK);
+ ALOGV("mComponent->query() for %s timeConsumed=%" PRId64 " us",
+ p->name().c_str(), timeConsumed);
+
+ startTime = getNowUs();
+ err = mComponent->config({queried[0].get()}, C2_DONT_BLOCK, &failures);
+ timeConsumed = getNowUs() - startTime;
+ CHECK_TIMEOUT(timeConsumed, CONFIG_TIME_OUT, "config()");
+ ASSERT_EQ(err, C2_OK);
+ ASSERT_EQ(failures.size(), 0u);
+ ALOGV("mComponent->config() for %s timeConsumed=%" PRId64 " us",
+ p->name().c_str(), timeConsumed);
+ }
+
+ std::list<std::unique_ptr<C2Work>> workList;
+ startTime = getNowUs();
+ err = mComponent->queue(&workList);
+ timeConsumed = getNowUs() - startTime;
+ ALOGV("mComponent->queue() timeConsumed=%" PRId64 " us", timeConsumed);
+ CHECK_TIMEOUT(timeConsumed, QUEUE_TIME_OUT, "queue()");
+ ASSERT_EQ(err, C2_OK);
+
+ startTime = getNowUs();
+ err = mComponent->flush(C2Component::FLUSH_COMPONENT, &workList);
+ timeConsumed = getNowUs() - startTime;
+ ALOGV("mComponent->flush() timeConsumed=%" PRId64 " us", timeConsumed);
+ CHECK_TIMEOUT(timeConsumed, FLUSH_TIME_OUT, "flush()");
+ ASSERT_EQ(err, C2_OK);
+
+ startTime = getNowUs();
+ err = mComponent->stop();
+ timeConsumed = getNowUs() - startTime;
+ ALOGV("mComponent->stop() timeConsumed=%" PRId64 " us", timeConsumed);
+ CHECK_TIMEOUT(timeConsumed, STOP_TIME_OUT, "stop()");
+ ASSERT_EQ(err, C2_OK);
+
+ startTime = getNowUs();
+ err = mComponent->release();
+ timeConsumed = getNowUs() - startTime;
+ ALOGV("mComponent->release() timeConsumed=%" PRId64 " us", timeConsumed);
+ CHECK_TIMEOUT(timeConsumed, RELEASE_TIME_OUT, "release()");
+ ASSERT_EQ(err, C2_OK);
+
+}
+
} // anonymous namespace
// TODO: Add test for Invalid work,
diff --git a/media/codec2/hidl/client/client.cpp b/media/codec2/hidl/client/client.cpp
index 7a2e549..0fe8376 100644
--- a/media/codec2/hidl/client/client.cpp
+++ b/media/codec2/hidl/client/client.cpp
@@ -29,9 +29,9 @@
#include <android-base/properties.h>
#include <bufferpool/ClientManager.h>
#include <cutils/native_handle.h>
-#include <gui/bufferqueue/1.0/H2BGraphicBufferProducer.h>
+#include <gui/bufferqueue/2.0/B2HGraphicBufferProducer.h>
+#include <gui/bufferqueue/2.0/H2BGraphicBufferProducer.h>
#include <hidl/HidlSupport.h>
-#include <media/stagefright/bqhelper/WGraphicBufferProducer.h>
#include <android/hardware/media/bufferpool/2.0/IClientManager.h>
#include <android/hardware/media/c2/1.0/IComponent.h>
@@ -50,13 +50,21 @@
using ::android::hardware::hidl_string;
using ::android::hardware::Return;
using ::android::hardware::Void;
-using ::android::TWGraphicBufferProducer;
using namespace ::android::hardware::media::c2::V1_0;
using namespace ::android::hardware::media::c2::V1_0::utils;
using namespace ::android::hardware::media::bufferpool::V2_0;
using namespace ::android::hardware::media::bufferpool::V2_0::implementation;
+using HGraphicBufferProducer1 = ::android::hardware::graphics::bufferqueue::
+ V1_0::IGraphicBufferProducer;
+using HGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
+ V2_0::IGraphicBufferProducer;
+using B2HGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
+ V2_0::utils::B2HGraphicBufferProducer;
+using H2BGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
+ V2_0::utils::H2BGraphicBufferProducer;
+
namespace /* unnamed */ {
// c2_status_t value that corresponds to hwbinder transaction failure.
@@ -1064,11 +1072,11 @@
C2BlockPool::local_id_t blockPoolId,
const sp<IGraphicBufferProducer>& surface,
uint32_t generation) {
- sp<HGraphicBufferProducer> igbp =
- surface->getHalInterface<HGraphicBufferProducer>();
+ sp<HGraphicBufferProducer2> igbp =
+ surface->getHalInterface<HGraphicBufferProducer2>();
if (!igbp) {
- igbp = new TWGraphicBufferProducer<HGraphicBufferProducer>(surface);
+ igbp = new B2HGraphicBufferProducer2(surface);
}
Return<Status> transStatus = mBase->setOutputSurface(
@@ -1195,7 +1203,7 @@
}
c2_status_t Codec2Client::Component::connectToOmxInputSurface(
- const sp<HGraphicBufferProducer>& producer,
+ const sp<HGraphicBufferProducer1>& producer,
const sp<HGraphicBufferSource>& source,
std::shared_ptr<InputSurfaceConnection>* connection) {
c2_status_t status;
@@ -1284,12 +1292,11 @@
},
mBase{base},
mGraphicBufferProducer{new
- ::android::hardware::graphics::bufferqueue::V1_0::utils::
- H2BGraphicBufferProducer([base]() -> sp<HGraphicBufferProducer> {
- Return<sp<HGraphicBufferProducer>> transResult =
+ H2BGraphicBufferProducer2([base]() -> sp<HGraphicBufferProducer2> {
+ Return<sp<HGraphicBufferProducer2>> transResult =
base->getGraphicBufferProducer();
return transResult.isOk() ?
- static_cast<sp<HGraphicBufferProducer>>(transResult) :
+ static_cast<sp<HGraphicBufferProducer2>>(transResult) :
nullptr;
}())} {
}
diff --git a/media/codec2/hidl/client/include/codec2/hidl/client.h b/media/codec2/hidl/client/include/codec2/hidl/client.h
index 478ce6e..cd42205 100644
--- a/media/codec2/hidl/client/include/codec2/hidl/client.h
+++ b/media/codec2/hidl/client/include/codec2/hidl/client.h
@@ -63,55 +63,29 @@
* Codec2Client are all subclasses of Configurable.
*/
-// Forward declaration of Codec2.0 HIDL interfaces
-namespace android {
-namespace hardware {
-namespace media {
-namespace c2 {
-namespace V1_0 {
+// Forward declaration of relevant HIDL interfaces
+
+namespace android::hardware::media::c2::V1_0 {
struct IConfigurable;
struct IComponent;
struct IComponentInterface;
struct IComponentStore;
+struct IInputSink;
struct IInputSurface;
struct IInputSurfaceConnection;
-} // namespace V1_0
-} // namespace c2
-} // namespace media
-} // namespace hardware
-} // namespace android
+} // namespace android::hardware::media::c2::V1_0
-namespace android {
-namespace hardware {
-namespace media {
-namespace bufferpool {
-namespace V2_0 {
+namespace android::hardware::media::bufferpool::V2_0 {
struct IClientManager;
-} // namespace V2_0
-} // namespace bufferpool
-} // namespace media
-} // namespace hardware
-} // namespace android
+} // namespace android::hardware::media::bufferpool::V2_0
-// Forward declarations of other classes
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace bufferqueue {
-namespace V1_0 {
+namespace android::hardware::graphics::bufferqueue::V1_0 {
struct IGraphicBufferProducer;
-} // namespace V1_0
-} // namespace bufferqueue
-} // namespace graphics
-namespace media {
-namespace omx {
-namespace V1_0 {
+} // android::hardware::graphics::bufferqueue::V1_0
+
+namespace android::hardware::media::omx::V1_0 {
struct IGraphicBufferSource;
-} // namespace V1_0
-} // namespace omx
-} // namespace media
-} // namespace hardware
-} // namespace android
+} // namespace android::hardware::media::omx::V1_0
namespace android {
@@ -324,7 +298,9 @@
QueueBufferOutput QueueBufferOutput;
typedef ::android::hardware::graphics::bufferqueue::V1_0::
- IGraphicBufferProducer HGraphicBufferProducer;
+ IGraphicBufferProducer HGraphicBufferProducer1;
+ typedef ::android::hardware::graphics::bufferqueue::V2_0::
+ IGraphicBufferProducer HGraphicBufferProducer2;
typedef ::android::hardware::media::omx::V1_0::
IGraphicBufferSource HGraphicBufferSource;
@@ -362,7 +338,7 @@
std::shared_ptr<InputSurfaceConnection>* connection);
c2_status_t connectToOmxInputSurface(
- const sp<HGraphicBufferProducer>& producer,
+ const sp<HGraphicBufferProducer1>& producer,
const sp<HGraphicBufferSource>& source,
std::shared_ptr<InputSurfaceConnection>* connection);
diff --git a/media/codec2/sfplugin/C2OMXNode.cpp b/media/codec2/sfplugin/C2OMXNode.cpp
index 03d859a..962df0f 100644
--- a/media/codec2/sfplugin/C2OMXNode.cpp
+++ b/media/codec2/sfplugin/C2OMXNode.cpp
@@ -272,19 +272,14 @@
work->input.buffers.clear();
if (block) {
std::shared_ptr<C2Buffer> c2Buffer(
- // TODO: fence
new Buffer2D(block->share(
- C2Rect(block->width(), block->height()), ::C2Fence())),
- [buffer, source = getSource()](C2Buffer *ptr) {
- delete ptr;
- // TODO: fence
- (void)source->onInputBufferEmptied(buffer, -1);
- });
+ C2Rect(block->width(), block->height()), ::C2Fence())));
work->input.buffers.push_back(c2Buffer);
}
work->worklets.clear();
work->worklets.emplace_back(new C2Worklet);
std::list<std::unique_ptr<C2Work>> items;
+ uint64_t index = work->input.ordinal.frameIndex.peeku();
items.push_back(std::move(work));
c2_status_t err = comp->queue(&items);
@@ -292,6 +287,7 @@
return UNKNOWN_ERROR;
}
+ (void)mBufferIdsInUse.emplace(index, buffer);
return OK;
}
@@ -326,4 +322,18 @@
mHeight = height;
}
+void C2OMXNode::onInputBufferDone(c2_cntr64_t index) {
+ if (!mBufferSource) {
+ ALOGD("Buffer source not set (index=%llu)", index.peekull());
+ return;
+ }
+ auto it = mBufferIdsInUse.find(index.peeku());
+ if (it == mBufferIdsInUse.end()) {
+ ALOGV("Untracked input index %llu (maybe already removed)", index.peekull());
+ return;
+ }
+ (void)mBufferSource->onInputBufferEmptied(it->second, -1);
+ (void)mBufferIdsInUse.erase(it);
+}
+
} // namespace android
diff --git a/media/codec2/sfplugin/C2OMXNode.h b/media/codec2/sfplugin/C2OMXNode.h
index b5a815e..b7bd696 100644
--- a/media/codec2/sfplugin/C2OMXNode.h
+++ b/media/codec2/sfplugin/C2OMXNode.h
@@ -75,9 +75,23 @@
OMX_INDEXTYPE *index) override;
status_t dispatchMessage(const omx_message &msg) override;
+ /**
+ * Returns underlying IOMXBufferSource object.
+ */
sp<IOMXBufferSource> getSource();
+
+ /**
+ * Configure the frame size.
+ */
void setFrameSize(uint32_t width, uint32_t height);
+ /**
+ * Clean up work item reference.
+ *
+ * \param index input work index
+ */
+ void onInputBufferDone(c2_cntr64_t index);
+
private:
std::weak_ptr<Codec2Client::Component> mComp;
sp<IOMXBufferSource> mBufferSource;
@@ -96,6 +110,8 @@
bool mFirstInputFrame; // true for first input
c2_cntr64_t mPrevInputTimestamp; // input timestamp for previous frame
c2_cntr64_t mPrevCodecTimestamp; // adjusted (codec) timestamp for previous frame
+
+ std::map<uint64_t, buffer_id> mBufferIdsInUse;
};
} // namespace android
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index 2d10c67..8474ce8 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -271,9 +271,12 @@
if (mNode != nullptr) {
OMX_PARAM_U32TYPE ptrGapParam = {};
ptrGapParam.nSize = sizeof(OMX_PARAM_U32TYPE);
- ptrGapParam.nU32 = (config.mMinAdjustedFps > 0)
+ float gap = (config.mMinAdjustedFps > 0)
? c2_min(INT32_MAX + 0., 1e6 / config.mMinAdjustedFps + 0.5)
: c2_max(0. - INT32_MAX, -1e6 / config.mFixedAdjustedFps - 0.5);
+ // float -> uint32_t is undefined if the value is negative.
+ // First convert to int32_t to ensure the expected behavior.
+ ptrGapParam.nU32 = int32_t(gap);
(void)mNode->setParameter(
(OMX_INDEXTYPE)OMX_IndexParamMaxFrameDurationForBitrateControl,
&ptrGapParam, sizeof(ptrGapParam));
@@ -282,7 +285,7 @@
// max fps
// TRICKY: we do not unset max fps to 0 unless using fixed fps
- if ((config.mMaxFps > 0 || (config.mFixedAdjustedFps > 0 && config.mMaxFps == 0))
+ if ((config.mMaxFps > 0 || (config.mFixedAdjustedFps > 0 && config.mMaxFps == -1))
&& config.mMaxFps != mConfig.mMaxFps) {
status_t res = GetStatus(mSource->setMaxFps(config.mMaxFps));
status << " maxFps=" << config.mMaxFps;
@@ -367,6 +370,10 @@
return err;
}
+ void onInputBufferDone(c2_cntr64_t index) override {
+ mNode->onInputBufferDone(index);
+ }
+
private:
sp<BGraphicBufferSource> mSource;
sp<C2OMXNode> mNode;
@@ -739,10 +746,21 @@
return BAD_VALUE;
}
if ((config->mDomain & Config::IS_ENCODER) && (config->mDomain & Config::IS_VIDEO)) {
- if (!msg->findInt32(KEY_BIT_RATE, &i32)
- && !msg->findFloat(KEY_BIT_RATE, &flt)) {
- ALOGD("bitrate is missing, which is required for video encoders.");
- return BAD_VALUE;
+ C2Config::bitrate_mode_t mode = C2Config::BITRATE_VARIABLE;
+ if (msg->findInt32(KEY_BITRATE_MODE, &i32)) {
+ mode = (C2Config::bitrate_mode_t) i32;
+ }
+ if (mode == BITRATE_MODE_CQ) {
+ if (!msg->findInt32(KEY_QUALITY, &i32)) {
+ ALOGD("quality is missing, which is required for video encoders in CQ.");
+ return BAD_VALUE;
+ }
+ } else {
+ if (!msg->findInt32(KEY_BIT_RATE, &i32)
+ && !msg->findFloat(KEY_BIT_RATE, &flt)) {
+ ALOGD("bitrate is missing, which is required for video encoders.");
+ return BAD_VALUE;
+ }
}
if (!msg->findInt32(KEY_I_FRAME_INTERVAL, &i32)
&& !msg->findFloat(KEY_I_FRAME_INTERVAL, &flt)) {
@@ -764,13 +782,16 @@
if (msg->findInt64(KEY_REPEAT_PREVIOUS_FRAME_AFTER, &value) && value > 0) {
config->mISConfig->mMinFps = 1e6 / value;
}
- (void)msg->findFloat(
- KEY_MAX_FPS_TO_ENCODER, &config->mISConfig->mMaxFps);
+ if (!msg->findFloat(
+ KEY_MAX_FPS_TO_ENCODER, &config->mISConfig->mMaxFps)) {
+ config->mISConfig->mMaxFps = -1;
+ }
config->mISConfig->mMinAdjustedFps = 0;
config->mISConfig->mFixedAdjustedFps = 0;
if (msg->findInt64(KEY_MAX_PTS_GAP_TO_ENCODER, &value)) {
if (value < 0 && value >= INT32_MIN) {
config->mISConfig->mFixedAdjustedFps = -1e6 / value;
+ config->mISConfig->mMaxFps = -1;
} else if (value > 0 && value <= INT32_MAX) {
config->mISConfig->mMinAdjustedFps = 1e6 / value;
}
@@ -1566,6 +1587,13 @@
void CCodec::onInputBufferDone(uint64_t frameIndex, size_t arrayIndex) {
mChannel->onInputBufferDone(frameIndex, arrayIndex);
+ if (arrayIndex == 0) {
+ // We always put no more than one buffer per work, if we use an input surface.
+ Mutexed<Config>::Locked config(mConfig);
+ if (config->mInputSurface) {
+ config->mInputSurface->onInputBufferDone(frameIndex);
+ }
+ }
}
void CCodec::onMessageReceived(const sp<AMessage> &msg) {
@@ -1698,6 +1726,9 @@
++stream;
}
}
+ if (config->mInputSurface) {
+ config->mInputSurface->onInputBufferDone(work->input.ordinal.frameIndex);
+ }
mChannel->onWorkDone(
std::move(work), changed ? config->mOutputFormat : nullptr,
initData.hasChanged() ? initData.update().get() : nullptr);
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index fb6af93..d1fa920 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -1525,6 +1525,7 @@
mPending.splice(mPending.end(), mStash);
mDepth = depth;
}
+
void CCodecBufferChannel::ReorderStash::setKey(C2Config::ordinal_key_t key) {
mPending.splice(mPending.end(), mStash);
mKey = key;
@@ -1547,13 +1548,25 @@
int64_t timestamp,
int32_t flags,
const C2WorkOrdinalStruct &ordinal) {
- auto it = mStash.begin();
- for (; it != mStash.end(); ++it) {
- if (less(ordinal, it->ordinal)) {
- break;
+ bool eos = flags & MediaCodec::BUFFER_FLAG_EOS;
+ if (!buffer && eos) {
+ // TRICKY: we may be violating ordering of the stash here. Because we
+ // don't expect any more emplace() calls after this, the ordering should
+ // not matter.
+ mStash.emplace_back(buffer, timestamp, flags, ordinal);
+ } else {
+ flags = flags & ~MediaCodec::BUFFER_FLAG_EOS;
+ auto it = mStash.begin();
+ for (; it != mStash.end(); ++it) {
+ if (less(ordinal, it->ordinal)) {
+ break;
+ }
+ }
+ mStash.emplace(it, buffer, timestamp, flags, ordinal);
+ if (eos) {
+ mStash.back().flags = mStash.back().flags | MediaCodec::BUFFER_FLAG_EOS;
}
}
- mStash.emplace(it, buffer, timestamp, flags, ordinal);
while (!mStash.empty() && mStash.size() > mDepth) {
mPending.push_back(mStash.front());
mStash.pop_front();
@@ -2483,6 +2496,7 @@
bool post = true;
if (!configs->empty()) {
sp<ABuffer> config = configs->front();
+ configs->pop_front();
if (buffer->capacity() >= config->size()) {
memcpy(buffer->base(), config->data(), config->size());
buffer->setRange(0, config->size());
@@ -2593,9 +2607,9 @@
return false;
}
- if (work->worklets.size() != 1u
+ if (mInputSurface == nullptr && (work->worklets.size() != 1u
|| !work->worklets.front()
- || !(work->worklets.front()->output.flags & C2FrameData::FLAG_INCOMPLETE)) {
+ || !(work->worklets.front()->output.flags & C2FrameData::FLAG_INCOMPLETE))) {
mPipelineWatcher.lock()->onWorkDone(work->input.ordinal.frameIndex.peeku());
}
@@ -2709,6 +2723,10 @@
c2_cntr64_t timestamp =
worklet->output.ordinal.timestamp + work->input.ordinal.customOrdinal
- work->input.ordinal.timestamp;
+ if (mInputSurface != nullptr) {
+ // When using input surface we need to restore the original input timestamp.
+ timestamp = work->input.ordinal.customOrdinal;
+ }
ALOGV("[%s] onWorkDone: input %lld, codec %lld => output %lld => %lld",
mName,
work->input.ordinal.customOrdinal.peekll(),
@@ -2810,8 +2828,9 @@
outBuffer->meta()->setInt64("timeUs", entry.timestamp);
outBuffer->meta()->setInt32("flags", entry.flags);
- ALOGV("[%s] sendOutputBuffers: out buffer index = %zu [%p] => %p + %zu",
- mName, index, outBuffer.get(), outBuffer->data(), outBuffer->size());
+ ALOGV("[%s] sendOutputBuffers: out buffer index = %zu [%p] => %p + %zu (%lld)",
+ mName, index, outBuffer.get(), outBuffer->data(), outBuffer->size(),
+ (long long)entry.timestamp);
mCallback->onOutputBufferAvailable(index, outBuffer);
}
}
diff --git a/media/codec2/sfplugin/InputSurfaceWrapper.h b/media/codec2/sfplugin/InputSurfaceWrapper.h
index d9c4eec..8341fd5 100644
--- a/media/codec2/sfplugin/InputSurfaceWrapper.h
+++ b/media/codec2/sfplugin/InputSurfaceWrapper.h
@@ -98,6 +98,13 @@
mDataSpace = dataSpace;
}
+ /**
+ * Clean up C2Work related references if necessary. No-op by default.
+ *
+ * \param index index of input work.
+ */
+ virtual void onInputBufferDone(c2_cntr64_t /* index */) {}
+
protected:
android_dataspace mDataSpace;
};
diff --git a/media/codec2/sfplugin/utils/Codec2Mapper.cpp b/media/codec2/sfplugin/utils/Codec2Mapper.cpp
index 6da131f..d62944a 100644
--- a/media/codec2/sfplugin/utils/Codec2Mapper.cpp
+++ b/media/codec2/sfplugin/utils/Codec2Mapper.cpp
@@ -589,6 +589,21 @@
bool mIsHdr10Plus;
};
+struct Av1ProfileLevelMapper : ProfileLevelMapperHelper {
+ virtual bool simpleMap(C2Config::level_t from, int32_t *to) {
+ return sAv1Levels.map(from, to);
+ }
+ virtual bool simpleMap(int32_t from, C2Config::level_t *to) {
+ return sAv1Levels.map(from, to);
+ }
+ virtual bool simpleMap(C2Config::profile_t from, int32_t *to) {
+ return sAv1Profiles.map(from, to);
+ }
+ virtual bool simpleMap(int32_t from, C2Config::profile_t *to) {
+ return sAv1Profiles.map(from, to);
+ }
+};
+
} // namespace
// static
@@ -613,6 +628,8 @@
return std::make_shared<Vp8ProfileLevelMapper>();
} else if (mediaType == MIMETYPE_VIDEO_VP9) {
return std::make_shared<Vp9ProfileLevelMapper>();
+ } else if (mediaType == MIMETYPE_VIDEO_AV1) {
+ return std::make_shared<Av1ProfileLevelMapper>();
}
return nullptr;
}
diff --git a/media/codec2/vndk/Android.bp b/media/codec2/vndk/Android.bp
index ab6a105..c6ca670 100644
--- a/media/codec2/vndk/Android.bp
+++ b/media/codec2/vndk/Android.bp
@@ -38,6 +38,7 @@
export_shared_lib_headers: [
"libbase",
+ "libgui",
"android.hardware.media.bufferpool@2.0",
],
@@ -52,13 +53,14 @@
shared_libs: [
"android.hardware.graphics.allocator@2.0",
- "android.hardware.graphics.bufferqueue@1.0",
+ "android.hardware.graphics.bufferqueue@2.0",
"android.hardware.graphics.mapper@2.0",
"android.hardware.media.bufferpool@2.0",
"libbase",
"libbinder",
"libcutils",
"libdl",
+ "libgui",
"libhardware",
"libhidlbase",
"libion",
diff --git a/media/codec2/vndk/include/C2BqBufferPriv.h b/media/codec2/vndk/include/C2BqBufferPriv.h
index 9271a71..e1a8138 100644
--- a/media/codec2/vndk/include/C2BqBufferPriv.h
+++ b/media/codec2/vndk/include/C2BqBufferPriv.h
@@ -17,10 +17,11 @@
#ifndef STAGEFRIGHT_CODEC2_BQ_BUFFER_PRIV_H_
#define STAGEFRIGHT_CODEC2_BQ_BUFFER_PRIV_H_
-#include <functional>
+#include <android/hardware/graphics/bufferqueue/2.0/IGraphicBufferProducer.h>
#include <C2Buffer.h>
-#include <media/stagefright/bqhelper/WGraphicBufferProducer.h>
+
+#include <functional>
class C2BufferQueueBlockPool : public C2BlockPool {
public:
@@ -52,6 +53,8 @@
*/
virtual void setRenderCallback(const OnRenderCallback &renderCallback = OnRenderCallback());
+ typedef ::android::hardware::graphics::bufferqueue::V2_0::
+ IGraphicBufferProducer HGraphicBufferProducer;
/**
* Configures an IGBP in order to create blocks. A newly created block is
* dequeued from the configured IGBP. Unique Id of IGBP and the slot number of
@@ -62,7 +65,7 @@
*
* \param producer the IGBP, which will be used to fetch blocks
*/
- virtual void configureProducer(const android::sp<android::HGraphicBufferProducer> &producer);
+ virtual void configureProducer(const android::sp<HGraphicBufferProducer> &producer);
private:
const std::shared_ptr<C2Allocator> mAllocator;
diff --git a/media/codec2/vndk/internal/C2BlockInternal.h b/media/codec2/vndk/internal/C2BlockInternal.h
index 2abf3ac..84ce70a 100644
--- a/media/codec2/vndk/internal/C2BlockInternal.h
+++ b/media/codec2/vndk/internal/C2BlockInternal.h
@@ -17,7 +17,7 @@
#ifndef ANDROID_STAGEFRIGHT_C2BLOCK_INTERNAL_H_
#define ANDROID_STAGEFRIGHT_C2BLOCK_INTERNAL_H_
-#include <android/hardware/graphics/bufferqueue/1.0/IGraphicBufferProducer.h>
+#include <android/hardware/graphics/bufferqueue/2.0/IGraphicBufferProducer.h>
#include <C2Buffer.h>
@@ -291,7 +291,7 @@
bool AssignBlockToBufferQueue(
const std::shared_ptr<_C2BlockPoolData>& poolData,
const ::android::sp<::android::hardware::graphics::bufferqueue::
- V1_0::IGraphicBufferProducer>& igbp,
+ V2_0::IGraphicBufferProducer>& igbp,
uint32_t generation,
uint64_t bqId,
int32_t bqSlot,
@@ -314,7 +314,7 @@
bool HoldBlockFromBufferQueue(
const std::shared_ptr<_C2BlockPoolData>& poolData,
const ::android::sp<::android::hardware::graphics::bufferqueue::
- V1_0::IGraphicBufferProducer>& igbp = nullptr);
+ V2_0::IGraphicBufferProducer>& igbp = nullptr);
/**
* Yield a block to the designated bufferqueue. This causes the destruction
diff --git a/media/codec2/vndk/platform/C2BqBuffer.cpp b/media/codec2/vndk/platform/C2BqBuffer.cpp
index 41a5b3f..9cc5677 100644
--- a/media/codec2/vndk/platform/C2BqBuffer.cpp
+++ b/media/codec2/vndk/platform/C2BqBuffer.cpp
@@ -19,29 +19,37 @@
#include <utils/Log.h>
#include <gui/BufferQueueDefs.h>
-#include <list>
-#include <map>
-#include <mutex>
+#include <gui/bufferqueue/2.0/B2HGraphicBufferProducer.h>
+#include <hidl/HidlSupport.h>
#include <C2AllocatorGralloc.h>
#include <C2BqBufferPriv.h>
#include <C2BlockInternal.h>
-using ::android::AnwBuffer;
+#include <list>
+#include <map>
+#include <mutex>
+
using ::android::BufferQueueDefs::NUM_BUFFER_SLOTS;
using ::android::C2AllocatorGralloc;
using ::android::C2AndroidMemoryUsage;
using ::android::Fence;
using ::android::GraphicBuffer;
-using ::android::HGraphicBufferProducer;
using ::android::IGraphicBufferProducer;
-using ::android::hidl_handle;
using ::android::sp;
using ::android::status_t;
using ::android::wp;
-
+using ::android::hardware::hidl_handle;
using ::android::hardware::Return;
-using ::android::hardware::graphics::common::V1_0::PixelFormat;
+
+using HBuffer = ::android::hardware::graphics::common::V1_2::HardwareBuffer;
+using HStatus = ::android::hardware::graphics::bufferqueue::V2_0::Status;
+using ::android::hardware::graphics::bufferqueue::V2_0::utils::b2h;
+using ::android::hardware::graphics::bufferqueue::V2_0::utils::h2b;
+using ::android::hardware::graphics::bufferqueue::V2_0::utils::HFenceWrapper;
+
+using HGraphicBufferProducer = ::android::hardware::graphics::bufferqueue::V2_0
+ ::IGraphicBufferProducer;
struct C2BufferQueueBlockPoolData : public _C2BlockPoolData {
@@ -185,57 +193,67 @@
C2MemoryUsage usage,
std::shared_ptr<C2GraphicBlock> *block /* nonnull */) {
// We have an IGBP now.
- sp<Fence> fence = new Fence();
C2AndroidMemoryUsage androidUsage = usage;
- status_t status;
- PixelFormat pixelFormat = static_cast<PixelFormat>(format);
- int slot;
+ status_t status{};
+ int slot{};
+ bool bufferNeedsReallocation{};
+ sp<Fence> fence = new Fence();
ALOGV("tries to dequeue buffer");
- Return<void> transStatus = mProducer->dequeueBuffer(
- width, height, pixelFormat, androidUsage.asGrallocUsage(), false,
- [&status, &slot, &fence](
- int32_t tStatus, int32_t tSlot, hidl_handle const& tFence,
- HGraphicBufferProducer::FrameEventHistoryDelta const& tTs) {
- status = tStatus;
- slot = tSlot;
- if (!android::conversion::convertTo(fence.get(), tFence) &&
- status == android::NO_ERROR) {
- status = android::BAD_VALUE;
+
+ { // Call dequeueBuffer().
+ using Input = HGraphicBufferProducer::DequeueBufferInput;
+ using Output = HGraphicBufferProducer::DequeueBufferOutput;
+ Return<void> transResult = mProducer->dequeueBuffer(
+ Input{
+ width,
+ height,
+ format,
+ androidUsage.asGrallocUsage()},
+ [&status, &slot, &bufferNeedsReallocation,
+ &fence](HStatus hStatus,
+ int32_t hSlot,
+ Output const& hOutput) {
+ slot = static_cast<int>(hSlot);
+ if (!h2b(hStatus, &status) ||
+ !h2b(hOutput.fence, &fence)) {
+ status = ::android::BAD_VALUE;
+ } else {
+ bufferNeedsReallocation =
+ hOutput.bufferNeedsReallocation;
+ }
+ });
+ if (!transResult.isOk() || status != android::OK) {
+ ALOGD("cannot dequeue buffer %d", status);
+ if (transResult.isOk()) {
+ if (status == android::INVALID_OPERATION ||
+ status == android::TIMED_OUT ||
+ status == android::WOULD_BLOCK) {
+ // Dequeue buffer is blocked temporarily. Retrying is
+ // required.
+ return C2_BLOCKING;
}
- (void) tTs;
- });
- // dequeueBuffer returns flag.
- if (!transStatus.isOk() || status < android::OK) {
- ALOGD("cannot dequeue buffer %d", status);
- if (transStatus.isOk()) {
- if (status == android::INVALID_OPERATION ||
- status == android::TIMED_OUT ||
- status == android::WOULD_BLOCK) {
- // Dequeue buffer is blocked temporarily. Retrying is
- // required.
- return C2_BLOCKING;
}
+ return C2_BAD_VALUE;
}
+ }
+ HFenceWrapper hFenceWrapper{};
+ if (!b2h(fence, &hFenceWrapper)) {
+ ALOGE("Invalid fence received from dequeueBuffer.");
return C2_BAD_VALUE;
}
ALOGV("dequeued a buffer successfully");
- native_handle_t* nh = nullptr;
- hidl_handle fenceHandle;
- if (fence) {
- android::conversion::wrapAs(&fenceHandle, &nh, *fence);
- }
if (fence) {
static constexpr int kFenceWaitTimeMs = 10;
status_t status = fence->wait(kFenceWaitTimeMs);
if (status == -ETIME) {
// fence is not signalled yet.
- (void)mProducer->cancelBuffer(slot, fenceHandle).isOk();
+ (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
return C2_BLOCKING;
}
if (status != android::NO_ERROR) {
ALOGD("buffer fence wait error %d", status);
- (void)mProducer->cancelBuffer(slot, fenceHandle).isOk();
+ (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
return C2_BAD_VALUE;
} else if (mRenderCallback) {
nsecs_t signalTime = fence->getSignalTime();
@@ -248,27 +266,31 @@
}
sp<GraphicBuffer> &slotBuffer = mBuffers[slot];
- if (status & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION || !slotBuffer) {
+ if (bufferNeedsReallocation || !slotBuffer) {
if (!slotBuffer) {
slotBuffer = new GraphicBuffer();
}
// N.B. This assumes requestBuffer# returns an existing allocation
// instead of a new allocation.
- Return<void> transStatus = mProducer->requestBuffer(
+ Return<void> transResult = mProducer->requestBuffer(
slot,
- [&status, &slotBuffer](int32_t tStatus, AnwBuffer const& tBuffer){
- status = tStatus;
- if (!android::conversion::convertTo(slotBuffer.get(), tBuffer) &&
- status == android::NO_ERROR) {
+ [&status, &slotBuffer](
+ HStatus hStatus,
+ HBuffer const& hBuffer,
+ uint32_t generationNumber){
+ if (h2b(hStatus, &status) &&
+ h2b(hBuffer, &slotBuffer) &&
+ slotBuffer) {
+ slotBuffer->setGenerationNumber(generationNumber);
+ } else {
status = android::BAD_VALUE;
}
});
-
- if (!transStatus.isOk()) {
+ if (!transResult.isOk()) {
return C2_BAD_VALUE;
} else if (status != android::NO_ERROR) {
slotBuffer.clear();
- (void)mProducer->cancelBuffer(slot, fenceHandle).isOk();
+ (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
return C2_BAD_VALUE;
}
}
@@ -292,13 +314,14 @@
std::shared_ptr<C2BufferQueueBlockPoolData> poolData =
std::make_shared<C2BufferQueueBlockPoolData>(
slotBuffer->getGenerationNumber(),
- mProducerId, slot, shared_from_this());
+ mProducerId, slot,
+ shared_from_this());
*block = _C2BlockFactory::CreateGraphicBlock(alloc, poolData);
return C2_OK;
}
// Block was not created. call requestBuffer# again next time.
slotBuffer.clear();
- (void)mProducer->cancelBuffer(slot, fenceHandle).isOk();
+ (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
}
return C2_BAD_VALUE;
}
@@ -312,10 +335,10 @@
bool noInit = false;
for (int i = 0; i < NUM_BUFFER_SLOTS; ++i) {
if (!noInit && mProducer) {
- Return<int32_t> transResult =
+ Return<HStatus> transResult =
mProducer->detachBuffer(static_cast<int32_t>(i));
noInit = !transResult.isOk() ||
- static_cast<int32_t>(transResult) == android::NO_INIT;
+ static_cast<HStatus>(transResult) == HStatus::NO_INIT;
}
mBuffers[i].clear();
}
@@ -373,32 +396,28 @@
}
void configureProducer(const sp<HGraphicBufferProducer> &producer) {
- int32_t status = android::OK;
uint64_t producerId = 0;
if (producer) {
- Return<void> transStatus = producer->getUniqueId(
- [&status, &producerId](int32_t tStatus, int64_t tProducerId) {
- status = tStatus;
- producerId = tProducerId;
- });
- if (!transStatus.isOk()) {
+ Return<uint64_t> transResult = producer->getUniqueId();
+ if (!transResult.isOk()) {
ALOGD("configureProducer -- failed to connect to the producer");
return;
}
+ producerId = static_cast<uint64_t>(transResult);
}
{
std::lock_guard<std::mutex> lock(mMutex);
bool noInit = false;
for (int i = 0; i < NUM_BUFFER_SLOTS; ++i) {
if (!noInit && mProducer) {
- Return<int32_t> transResult =
+ Return<HStatus> transResult =
mProducer->detachBuffer(static_cast<int32_t>(i));
noInit = !transResult.isOk() ||
- static_cast<int32_t>(transResult) == android::NO_INIT;
+ static_cast<HStatus>(transResult) == HStatus::NO_INIT;
}
mBuffers[i].clear();
}
- if (producer && status == android::OK) {
+ if (producer) {
mProducer = producer;
mProducerId = producerId;
} else {
@@ -414,7 +433,7 @@
void cancel(uint64_t igbp_id, int32_t igbp_slot) {
std::lock_guard<std::mutex> lock(mMutex);
if (igbp_id == mProducerId && mProducer) {
- (void)mProducer->cancelBuffer(igbp_slot, nullptr).isOk();
+ (void)mProducer->cancelBuffer(igbp_slot, hidl_handle{}).isOk();
}
}
@@ -455,7 +474,7 @@
if (local && localPool) {
localPool->cancel(bqId, bqSlot);
} else if (igbp) {
- igbp->cancelBuffer(bqSlot, nullptr);
+ igbp->cancelBuffer(bqSlot, hidl_handle{}).isOk();
}
}
diff --git a/media/extractors/mkv/MatroskaExtractor.cpp b/media/extractors/mkv/MatroskaExtractor.cpp
index f8aa784..d6d24c1 100644
--- a/media/extractors/mkv/MatroskaExtractor.cpp
+++ b/media/extractors/mkv/MatroskaExtractor.cpp
@@ -32,6 +32,7 @@
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MetaDataUtils.h>
+#include <media/stagefright/foundation/avc_utils.h>
#include <utils/String8.h>
#include <arpa/inet.h>
@@ -147,6 +148,7 @@
AVC,
AAC,
HEVC,
+ MP3,
OTHER
};
@@ -159,6 +161,15 @@
List<MediaBufferHelper *> mPendingFrames;
+ int64_t mCurrentTS; // add for mp3
+ uint32_t mMP3Header;
+
+ media_status_t findMP3Header(uint32_t * header,
+ const uint8_t *dataSource, int length, int *outStartPos);
+ media_status_t mp3FrameRead(
+ MediaBufferHelper **out, const ReadOptions *options,
+ int64_t targetSampleTimeUs);
+
status_t advance();
status_t setWebmBlockCryptoInfo(MediaBufferHelper *mbuf);
@@ -225,7 +236,9 @@
mBlockIter(mExtractor,
mExtractor->mTracks.itemAt(index).mTrackNum,
index),
- mNALSizeLen(-1) {
+ mNALSizeLen(-1),
+ mCurrentTS(0),
+ mMP3Header(0) {
MatroskaExtractor::TrackInfo &trackInfo = mExtractor->mTracks.editItemAt(index);
AMediaFormat *meta = trackInfo.mMeta;
@@ -254,6 +267,8 @@
}
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
mType = AAC;
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
+ mType = MP3;
}
}
@@ -270,6 +285,16 @@
mBufferGroup->init(1 /* number of buffers */, 1024 /* buffer size */, 64 /* growth limit */);
mBlockIter.reset();
+ if (mType == MP3 && mMP3Header == 0) {
+ int start = -1;
+ media_status_t err = findMP3Header(&mMP3Header, NULL, 0, &start);
+ if (err != OK) {
+ ALOGE("No mp3 header found");
+ clearPendingFrames();
+ return err;
+ }
+ }
+
return AMEDIA_OK;
}
@@ -796,6 +821,188 @@
return AMEDIA_OK;
}
+//the value of kMP3HeaderMask is from MP3Extractor
+static const uint32_t kMP3HeaderMask = 0xfffe0c00;
+
+media_status_t MatroskaSource::findMP3Header(uint32_t * header,
+ const uint8_t *dataSource, int length, int *outStartPos) {
+ if (NULL == header) {
+ ALOGE("header is null!");
+ return AMEDIA_ERROR_END_OF_STREAM;
+ }
+
+ //to find header start position
+ if (0 != *header) {
+ if (NULL == dataSource) {
+ *outStartPos = -1;
+ return AMEDIA_OK;
+ }
+ uint32_t tmpCode = 0;
+ for (int i = 0; i < length; i++) {
+ tmpCode = (tmpCode << 8) + dataSource[i];
+ if ((tmpCode & kMP3HeaderMask) == (*header & kMP3HeaderMask)) {
+ *outStartPos = i - 3;
+ return AMEDIA_OK;
+ }
+ }
+ *outStartPos = -1;
+ return AMEDIA_OK;
+ }
+
+ //to find mp3 header
+ uint32_t code = 0;
+ while (0 == *header) {
+ while (mPendingFrames.empty()) {
+ media_status_t err = readBlock();
+ if (err != OK) {
+ clearPendingFrames();
+ return err;
+ }
+ }
+ MediaBufferHelper *frame = *mPendingFrames.begin();
+ size_t size = frame->range_length();
+ size_t offset = frame->range_offset();
+ size_t i;
+ size_t frame_size;
+ for (i = 0; i < size; i++) {
+ ALOGV("data[%zu]=%x", i, *((uint8_t*)frame->data() + offset + i));
+ code = (code << 8) + *((uint8_t*)frame->data() + offset + i);
+ if (GetMPEGAudioFrameSize(code, &frame_size, NULL, NULL, NULL)) {
+ *header = code;
+ mBlockIter.reset();
+ clearPendingFrames();
+ return AMEDIA_OK;
+ }
+ }
+ }
+
+ return AMEDIA_ERROR_END_OF_STREAM;
+}
+
+media_status_t MatroskaSource::mp3FrameRead(
+ MediaBufferHelper **out, const ReadOptions *options,
+ int64_t targetSampleTimeUs) {
+ MediaBufferHelper *frame = *mPendingFrames.begin();
+ int64_t seekTimeUs;
+ ReadOptions::SeekMode mode;
+ if (options && options->getSeekTo(&seekTimeUs, &mode)) {
+ CHECK(AMediaFormat_getInt64(frame->meta_data(),
+ AMEDIAFORMAT_KEY_TIME_US, &mCurrentTS));
+ if (mCurrentTS < 0) {
+ mCurrentTS = 0;
+ AMediaFormat_setInt64(frame->meta_data(),
+ AMEDIAFORMAT_KEY_TIME_US, mCurrentTS);
+ }
+ }
+
+ int32_t start = -1;
+ while (start < 0) {
+ //find header start position
+ findMP3Header(&mMP3Header,
+ (const uint8_t*)frame->data() + frame->range_offset(),
+ frame->range_length(), &start);
+ ALOGV("start=%d, frame->range_length() = %zu, frame->range_offset() =%zu",
+ start, frame->range_length(), frame->range_offset());
+ if (start >= 0)
+ break;
+ frame->release();
+ mPendingFrames.erase(mPendingFrames.begin());
+ while (mPendingFrames.empty()) {
+ media_status_t err = readBlock();
+ if (err != OK) {
+ clearPendingFrames();
+ return err;
+ }
+ }
+ frame = *mPendingFrames.begin();
+ }
+
+ frame->set_range(frame->range_offset() + start, frame->range_length() - start);
+
+ uint32_t header = *(uint32_t*)((uint8_t*)frame->data() + frame->range_offset());
+ header = ((header >> 24) & 0xff) | ((header >> 8) & 0xff00) |
+ ((header << 8) & 0xff0000) | ((header << 24) & 0xff000000);
+ size_t frame_size;
+ int out_sampling_rate;
+ int out_channels;
+ int out_bitrate;
+ if (!GetMPEGAudioFrameSize(header, &frame_size,
+ &out_sampling_rate, &out_channels, &out_bitrate)) {
+ ALOGE("MP3 Header read fail!!");
+ return AMEDIA_ERROR_UNSUPPORTED;
+ }
+
+ MediaBufferHelper *buffer;
+ mBufferGroup->acquire_buffer(&buffer, false /* nonblocking */, frame_size /* requested size */);
+ buffer->set_range(0, frame_size);
+
+ uint8_t *data = static_cast<uint8_t *>(buffer->data());
+ ALOGV("MP3 frame %zu frame->range_length() %zu", frame_size, frame->range_length());
+
+ if (frame_size > frame->range_length()) {
+ memcpy(data, (uint8_t*)(frame->data()) + frame->range_offset(), frame->range_length());
+ size_t sumSize = 0;
+ sumSize += frame->range_length();
+ size_t needSize = frame_size - frame->range_length();
+ frame->release();
+ mPendingFrames.erase(mPendingFrames.begin());
+ while (mPendingFrames.empty()) {
+ media_status_t err = readBlock();
+ if (err != OK) {
+ clearPendingFrames();
+ return err;
+ }
+ }
+ frame = *mPendingFrames.begin();
+ size_t offset = frame->range_offset();
+ size_t size = frame->range_length();
+
+ // the next buffer frame is not enough to fullfill mp3 frame,
+ // we have to read until mp3 frame is completed.
+ while (size < needSize) {
+ memcpy(data + sumSize, (uint8_t*)(frame->data()) + offset, size);
+ needSize -= size;
+ sumSize += size;
+ frame->release();
+ mPendingFrames.erase(mPendingFrames.begin());
+ while (mPendingFrames.empty()) {
+ media_status_t err = readBlock();
+ if (err != OK) {
+ clearPendingFrames();
+ return err;
+ }
+ }
+ frame = *mPendingFrames.begin();
+ offset = frame->range_offset();
+ size = frame->range_length();
+ }
+ memcpy(data + sumSize, (uint8_t*)(frame->data()) + offset, needSize);
+ frame->set_range(offset + needSize, size - needSize);
+ } else {
+ size_t offset = frame->range_offset();
+ size_t size = frame->range_length();
+ memcpy(data, (uint8_t*)(frame->data()) + offset, frame_size);
+ frame->set_range(offset + frame_size, size - frame_size);
+ }
+ if (frame->range_length() < 4) {
+ frame->release();
+ frame = NULL;
+ mPendingFrames.erase(mPendingFrames.begin());
+ }
+ ALOGV("MatroskaSource::read MP3 frame kKeyTime=%lld,kKeyTargetTime=%lld",
+ (long long)mCurrentTS, (long long)targetSampleTimeUs);
+ AMediaFormat_setInt64(buffer->meta_data(),
+ AMEDIAFORMAT_KEY_TIME_US, mCurrentTS);
+ mCurrentTS += (int64_t)frame_size * 8000ll / out_bitrate;
+
+ if (targetSampleTimeUs >= 0ll)
+ AMediaFormat_setInt64(buffer->meta_data(),
+ AMEDIAFORMAT_KEY_TARGET_TIME, targetSampleTimeUs);
+ *out = buffer;
+ ALOGV("MatroskaSource::read MP3, keyTime=%lld for next frame", (long long)mCurrentTS);
+ return AMEDIA_OK;
+}
+
media_status_t MatroskaSource::read(
MediaBufferHelper **out, const ReadOptions *options) {
*out = NULL;
@@ -833,6 +1040,10 @@
}
}
+ if (mType == MP3) {
+ return mp3FrameRead(out, options, targetSampleTimeUs);
+ }
+
MediaBufferHelper *frame = *mPendingFrames.begin();
mPendingFrames.erase(mPendingFrames.begin());
@@ -1125,6 +1336,13 @@
mReader = NULL;
delete mDataSource;
+
+ for (size_t i = 0; i < mTracks.size(); ++i) {
+ TrackInfo *info = &mTracks.editItemAt(i);
+ if (info->mMeta) {
+ AMediaFormat_delete(info->mMeta);
+ }
+ }
}
size_t MatroskaExtractor::countTracks() {
@@ -1597,6 +1815,8 @@
void MatroskaExtractor::addTracks() {
const mkvparser::Tracks *tracks = mSegment->GetTracks();
+ AMediaFormat *meta = nullptr;
+
for (size_t index = 0; index < tracks->GetTracksCount(); ++index) {
const mkvparser::Track *track = tracks->GetTrackByIndex(index);
@@ -1621,7 +1841,11 @@
enum { VIDEO_TRACK = 1, AUDIO_TRACK = 2 };
- AMediaFormat *meta = AMediaFormat_new();
+ if (meta) {
+ AMediaFormat_clear(meta);
+ } else {
+ meta = AMediaFormat_new();
+ }
status_t err = OK;
int32_t nalSize = -1;
@@ -1856,21 +2080,26 @@
long long durationNs = mSegment->GetDuration();
AMediaFormat_setInt64(meta, AMEDIAFORMAT_KEY_DURATION, (durationNs + 500) / 1000);
+ const char *mimetype = "";
+ if (!AMediaFormat_getString(meta, AMEDIAFORMAT_KEY_MIME, &mimetype)) {
+ // do not add this track to the track list
+ ALOGW("ignoring track with unknown mime");
+ continue;
+ }
+
mTracks.push();
size_t n = mTracks.size() - 1;
TrackInfo *trackInfo = &mTracks.editItemAt(n);
initTrackInfo(track, meta, trackInfo);
trackInfo->mNalLengthSize = nalSize;
- const char *mimetype = "";
- AMediaFormat_getString(meta, AMEDIAFORMAT_KEY_MIME, &mimetype);
-
if ((!strcmp("V_MPEG4/ISO/AVC", codecID) && codecPrivateSize == 0) ||
(!strcmp(mimetype, MEDIA_MIMETYPE_VIDEO_AVC) && isSetCsdFrom1stFrame)) {
// Attempt to recover from AVC track without codec private data
err = synthesizeAVCC(trackInfo, n);
if (err != OK) {
mTracks.pop();
+ continue;
}
} else if ((!strcmp("V_MPEG2", codecID) && codecPrivateSize == 0) ||
(!strcmp(mimetype, MEDIA_MIMETYPE_VIDEO_MPEG2) && isSetCsdFrom1stFrame)) {
@@ -1878,6 +2107,7 @@
err = synthesizeMPEG2(trackInfo, n);
if (err != OK) {
mTracks.pop();
+ continue;
}
} else if ((!strcmp("V_MPEG4/ISO/ASP", codecID) && codecPrivateSize == 0) ||
(!strcmp(mimetype, MEDIA_MIMETYPE_VIDEO_MPEG4) && isSetCsdFrom1stFrame) ||
@@ -1888,9 +2118,14 @@
err = synthesizeMPEG4(trackInfo, n);
if (err != OK) {
mTracks.pop();
+ continue;
}
}
-
+ // the TrackInfo owns the metadata now
+ meta = nullptr;
+ }
+ if (meta) {
+ AMediaFormat_delete(meta);
}
}
diff --git a/media/extractors/mkv/MatroskaExtractor.h b/media/extractors/mkv/MatroskaExtractor.h
index d53d9e3..99fad17 100644
--- a/media/extractors/mkv/MatroskaExtractor.h
+++ b/media/extractors/mkv/MatroskaExtractor.h
@@ -61,10 +61,8 @@
TrackInfo() {
mMeta = NULL;
}
+
~TrackInfo() {
- if (mMeta) {
- AMediaFormat_delete(mMeta);
- }
}
unsigned long mTrackNum;
bool mEncrypted;
diff --git a/media/extractors/mp4/ItemTable.cpp b/media/extractors/mp4/ItemTable.cpp
index a72e589..d56abaa 100644
--- a/media/extractors/mp4/ItemTable.cpp
+++ b/media/extractors/mp4/ItemTable.cpp
@@ -1540,7 +1540,8 @@
AMediaFormat_setInt32(meta,
AMEDIAFORMAT_KEY_THUMBNAIL_HEIGHT, thumbnail.height);
AMediaFormat_setBuffer(meta,
- AMEDIAFORMAT_KEY_CSD_HEVC, thumbnail.hvcc->data(), thumbnail.hvcc->size());
+ AMEDIAFORMAT_KEY_THUMBNAIL_CSD_HEVC,
+ thumbnail.hvcc->data(), thumbnail.hvcc->size());
ALOGV("image[%u]: thumbnail: size %dx%d, item index %zd",
imageIndex, thumbnail.width, thumbnail.height, thumbItemIndex);
} else {
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index 93f34a8..5ff1c59 100755
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -3675,8 +3675,10 @@
void *tmpData;
size_t tmpDataSize;
+ const char *s;
if (size >= 8 && metadataKey &&
- !AMediaFormat_getBuffer(mFileMetaData, metadataKey, &tmpData, &tmpDataSize)) {
+ !AMediaFormat_getBuffer(mFileMetaData, metadataKey, &tmpData, &tmpDataSize) &&
+ !AMediaFormat_getString(mFileMetaData, metadataKey, &s)) {
if (!strcmp(metadataKey, "albumart")) {
AMediaFormat_setBuffer(mFileMetaData, metadataKey,
buffer + 8, size - 8);
@@ -3918,10 +3920,9 @@
};
static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]);
- void *tmpData;
- size_t tmpDataSize;
for (size_t i = 0; i < kNumMapEntries; ++i) {
- if (!AMediaFormat_getBuffer(mFileMetaData, kMap[i].key, &tmpData, &tmpDataSize)) {
+ const char *ss;
+ if (!AMediaFormat_getString(mFileMetaData, kMap[i].key, &ss)) {
ID3::Iterator *it = new ID3::Iterator(id3, kMap[i].tag1);
if (it->done()) {
delete it;
@@ -5318,7 +5319,9 @@
}
int32_t MPEG4Source::parseHEVCLayerId(const uint8_t *data, size_t size) {
- CHECK(data != nullptr && size >= (mNALLengthSize + 2));
+ if (data == nullptr || size < mNALLengthSize + 2) {
+ return -1;
+ }
// HEVC NAL-header (16-bit)
// 1 6 6 3
@@ -6124,6 +6127,7 @@
FOURCC("mp41"),
FOURCC("mp42"),
FOURCC("dash"),
+ FOURCC("nvr1"),
// Won't promise that the following file types can be played.
// Just give these file types a chance.
diff --git a/media/extractors/ogg/OggExtractor.cpp b/media/extractors/ogg/OggExtractor.cpp
index d99493d..b63ae6b 100644
--- a/media/extractors/ogg/OggExtractor.cpp
+++ b/media/extractors/ogg/OggExtractor.cpp
@@ -1280,7 +1280,7 @@
//ALOGI("comment #%d: '%s'", i + 1, mVc.user_comments[i]);
}
- AMediaFormat_getInt32(mFileMeta, "haptic", &mHapticChannelCount);
+ AMediaFormat_getInt32(mFileMeta, AMEDIAFORMAT_KEY_HAPTIC_CHANNEL_COUNT, &mHapticChannelCount);
}
void MyOggExtractor::setChannelMask(int channelCount) {
@@ -1297,6 +1297,8 @@
const audio_channel_mask_t channelMask = audio_channel_out_mask_from_count(
audioChannelCount) | hapticChannelMask;
AMediaFormat_setInt32(mMeta, AMEDIAFORMAT_KEY_CHANNEL_MASK, channelMask);
+ AMediaFormat_setInt32(
+ mMeta, AMEDIAFORMAT_KEY_HAPTIC_CHANNEL_COUNT, mHapticChannelCount);
}
} else {
AMediaFormat_setInt32(mMeta, AMEDIAFORMAT_KEY_CHANNEL_MASK,
diff --git a/media/extractors/wav/WAVExtractor.cpp b/media/extractors/wav/WAVExtractor.cpp
index 5679de8..020951b 100644
--- a/media/extractors/wav/WAVExtractor.cpp
+++ b/media/extractors/wav/WAVExtractor.cpp
@@ -81,7 +81,7 @@
virtual media_status_t read(
MediaBufferHelper **buffer, const ReadOptions *options = NULL);
- bool supportsNonBlockingRead() override { return true; }
+ bool supportsNonBlockingRead() override { return false; }
protected:
virtual ~WAVSource();
diff --git a/media/libaaudio/examples/loopback/src/loopback.cpp b/media/libaaudio/examples/loopback/src/loopback.cpp
index c7c42eb..49d921f 100644
--- a/media/libaaudio/examples/loopback/src/loopback.cpp
+++ b/media/libaaudio/examples/loopback/src/loopback.cpp
@@ -40,7 +40,8 @@
// V0.4.01 = add -h hang option
// fix -n option to set output buffer for -tm
// plot first glitch
-#define APP_VERSION "0.4.01"
+// V0.4.02 = allow -n0 for minimal buffer size
+#define APP_VERSION "0.4.02"
// Tag for machine readable results as property = value pairs
#define RESULT_TAG "RESULT: "
@@ -535,7 +536,7 @@
printf("INPUT stream ----------------------------------------\n");
// Use different parameters for the input.
argParser.setDeviceId(requestedInputDeviceId);
- argParser.setNumberOfBursts(AAUDIO_UNSPECIFIED);
+ argParser.setNumberOfBursts(AAudioParameters::kDefaultNumberOfBursts);
argParser.setFormat(requestedInputFormat);
argParser.setPerformanceMode(inputPerformanceLevel);
argParser.setChannelCount(requestedInputChannelCount);
diff --git a/media/libaaudio/examples/utils/AAudioArgsParser.h b/media/libaaudio/examples/utils/AAudioArgsParser.h
index f5ed7aa..9115778 100644
--- a/media/libaaudio/examples/utils/AAudioArgsParser.h
+++ b/media/libaaudio/examples/utils/AAudioArgsParser.h
@@ -36,11 +36,14 @@
aaudio_content_type_t contentType) = nullptr;
static void (*s_setInputPreset)(AAudioStreamBuilder* builder,
aaudio_input_preset_t inputPreset) = nullptr;
+static void (*s_setAllowedCapturePolicy)(AAudioStreamBuilder* builder,
+ aaudio_allowed_capture_policy_t usage) = nullptr;
static bool s_loadAttempted = false;
static aaudio_usage_t (*s_getUsage)(AAudioStream *stream) = nullptr;
static aaudio_content_type_t (*s_getContentType)(AAudioStream *stream) = nullptr;
static aaudio_input_preset_t (*s_getInputPreset)(AAudioStream *stream) = nullptr;
+static aaudio_allowed_capture_policy_t (*s_getAllowedCapturePolicy)(AAudioStream *stream) = nullptr;
// Link to test functions in shared library.
static void loadFutureFunctions() {
@@ -61,6 +64,10 @@
dlsym(handle, "AAudioStreamBuilder_setInputPreset");
if (s_setInputPreset == nullptr) goto error;
+ s_setAllowedCapturePolicy = (void (*)(AAudioStreamBuilder *, aaudio_input_preset_t))
+ dlsym(handle, "AAudioStreamBuilder_setAllowedCapturePolicy");
+ if (s_setAllowedCapturePolicy == nullptr) goto error;
+
s_getUsage = (aaudio_usage_t (*)(AAudioStream *))
dlsym(handle, "AAudioStream_getUsage");
if (s_getUsage == nullptr) goto error;
@@ -72,6 +79,10 @@
s_getInputPreset = (aaudio_input_preset_t (*)(AAudioStream *))
dlsym(handle, "AAudioStream_getInputPreset");
if (s_getInputPreset == nullptr) goto error;
+
+ s_getAllowedCapturePolicy = (aaudio_input_preset_t (*)(AAudioStream *))
+ dlsym(handle, "AAudioStream_getAllowedCapturePolicy");
+ if (s_getAllowedCapturePolicy == nullptr) goto error;
}
return;
@@ -169,6 +180,14 @@
mInputPreset = inputPreset;
}
+ aaudio_allowed_capture_policy_t getAllowedCapturePolicy() const {
+ return mAllowedCapturePolicy;
+ }
+
+ void setAllowedCapturePolicy(aaudio_allowed_capture_policy_t policy) {
+ mAllowedCapturePolicy = policy;
+ }
+
int32_t getDeviceId() const {
return mDeviceId;
}
@@ -223,8 +242,17 @@
} else if (mUsage != AAUDIO_UNSPECIFIED){
printf("WARNING: setInputPreset not supported");
}
+
+ // Call Q functions if supported.
+ if (s_setAllowedCapturePolicy != nullptr) {
+ s_setAllowedCapturePolicy(builder, mAllowedCapturePolicy);
+ } else if (mAllowedCapturePolicy != AAUDIO_UNSPECIFIED){
+ printf("WARNING: setAllowedCapturePolicy not supported");
+ }
}
+ static constexpr int32_t kDefaultNumberOfBursts = 2;
+
private:
int32_t mChannelCount = AAUDIO_UNSPECIFIED;
aaudio_format_t mFormat = AAUDIO_FORMAT_UNSPECIFIED;
@@ -238,8 +266,9 @@
aaudio_usage_t mUsage = AAUDIO_UNSPECIFIED;
aaudio_content_type_t mContentType = AAUDIO_UNSPECIFIED;
aaudio_input_preset_t mInputPreset = AAUDIO_UNSPECIFIED;
+ aaudio_allowed_capture_policy_t mAllowedCapturePolicy = AAUDIO_UNSPECIFIED;
- int32_t mNumberOfBursts = AAUDIO_UNSPECIFIED;
+ int32_t mNumberOfBursts = kDefaultNumberOfBursts;
int32_t mFramesPerCallback = AAUDIO_UNSPECIFIED;
};
@@ -267,6 +296,9 @@
case 'c':
setChannelCount(atoi(&arg[2]));
break;
+ case 'C':
+ setAllowedCapturePolicy(parseAllowedCapturePolicy(arg[2]));
+ break;
case 'd':
setDeviceId(atoi(&arg[2]));
break;
@@ -341,6 +373,10 @@
printf(" Default values are UNSPECIFIED unless otherwise stated.\n");
printf(" -b{bufferCapacity} frames\n");
printf(" -c{channels} for example 2 for stereo\n");
+ printf(" -C{a|s|n} set playback capture policy\n");
+ printf(" a = _ALL (default)\n");
+ printf(" s = _SYSTEM\n");
+ printf(" n = _NONE\n");
printf(" -d{deviceId} default is %d\n", AAUDIO_UNSPECIFIED);
printf(" -f{0|1|2} set format\n");
printf(" 0 = UNSPECIFIED\n");
@@ -352,7 +388,7 @@
printf(" 1 = _NEVER, never use MMAP\n");
printf(" 2 = _AUTO, use MMAP if available, default for -m with no number\n");
printf(" 3 = _ALWAYS, use MMAP or fail\n");
- printf(" -n{numberOfBursts} for setBufferSize\n");
+ printf(" -n{numberOfBursts} for setBufferSize, default %d\n", kDefaultNumberOfBursts);
printf(" -p{performanceMode} set output AAUDIO_PERFORMANCE_MODE*, default NONE\n");
printf(" n for _NONE\n");
printf(" l for _LATENCY\n");
@@ -365,6 +401,25 @@
printf(" -z{callbackSize} or block size, in frames, default = 0\n");
}
+ static aaudio_performance_mode_t parseAllowedCapturePolicy(char c) {
+ aaudio_allowed_capture_policy_t policy = AAUDIO_ALLOW_CAPTURE_BY_ALL;
+ switch (c) {
+ case 'a':
+ policy = AAUDIO_ALLOW_CAPTURE_BY_ALL;
+ break;
+ case 's':
+ policy = AAUDIO_ALLOW_CAPTURE_BY_SYSTEM;
+ break;
+ case 'n':
+ policy = AAUDIO_ALLOW_CAPTURE_BY_NONE;
+ break;
+ default:
+ printf("ERROR: invalid playback capture policy %c\n", c);
+ break;
+ }
+ return policy;
+ }
+
static aaudio_performance_mode_t parsePerformanceMode(char c) {
aaudio_performance_mode_t mode = AAUDIO_PERFORMANCE_MODE_NONE;
switch (c) {
@@ -407,17 +462,28 @@
getFormat(), AAudioStream_getFormat(stream));
int32_t framesPerBurst = AAudioStream_getFramesPerBurst(stream);
- int32_t sizeFrames = AAudioStream_getBufferSizeInFrames(stream);
printf(" Buffer: burst = %d\n", framesPerBurst);
+
+ int32_t sizeFrames = AAudioStream_getBufferSizeInFrames(stream);
if (framesPerBurst > 0) {
- printf(" Buffer: size = %d = (%d * %d) + %d\n",
+ int32_t requestedSize = getNumberOfBursts() * framesPerBurst;
+ printf(" BufferSize: requested = %4d, actual = %4d = (%d * %d) + %d\n",
+ requestedSize,
sizeFrames,
(sizeFrames / framesPerBurst),
framesPerBurst,
(sizeFrames % framesPerBurst));
+ } else {
+ printf(" BufferSize: %d\n", sizeFrames);
}
- printf(" Capacity: requested = %d, actual = %d\n", getBufferCapacity(),
- AAudioStream_getBufferCapacityInFrames(stream));
+
+ int32_t capacityFrames = AAudioStream_getBufferCapacityInFrames(stream);
+ printf(" Capacity: requested = %4d, actual = %4d = (%d * %d) + %d\n",
+ getBufferCapacity(),
+ capacityFrames,
+ (capacityFrames / framesPerBurst),
+ framesPerBurst,
+ (capacityFrames % framesPerBurst));
printf(" CallbackSize: requested = %d, actual = %d\n", getFramesPerCallback(),
AAudioStream_getFramesPerDataCallback(stream));
@@ -449,6 +515,11 @@
printf(" Is MMAP used? %s\n", AAudioStream_isMMapUsed(stream)
? "yes" : "no");
+ if (s_getAllowedCapturePolicy != nullptr) {
+ printf(" ContentType: requested = %d, actual = %d\n",
+ getAllowedCapturePolicy(), s_getAllowedCapturePolicy(stream));
+ }
+
}
int32_t getDurationSeconds() const {
diff --git a/media/libaaudio/examples/utils/AAudioSimplePlayer.h b/media/libaaudio/examples/utils/AAudioSimplePlayer.h
index 4373fa9..fd1fc45 100644
--- a/media/libaaudio/examples/utils/AAudioSimplePlayer.h
+++ b/media/libaaudio/examples/utils/AAudioSimplePlayer.h
@@ -120,10 +120,9 @@
if (result == AAUDIO_OK) {
int32_t sizeInBursts = parameters.getNumberOfBursts();
- if (sizeInBursts > 0) {
- int32_t framesPerBurst = AAudioStream_getFramesPerBurst(mStream);
- AAudioStream_setBufferSizeInFrames(mStream, sizeInBursts * framesPerBurst);
- }
+ int32_t framesPerBurst = AAudioStream_getFramesPerBurst(mStream);
+ int32_t bufferSizeFrames = sizeInBursts * framesPerBurst;
+ AAudioStream_setBufferSizeInFrames(mStream, bufferSizeFrames);
}
AAudioStreamBuilder_delete(builder);
diff --git a/media/libaaudio/examples/write_sine/src/write_sine_callback.cpp b/media/libaaudio/examples/write_sine/src/write_sine_callback.cpp
index 2b05f10..ca60233 100644
--- a/media/libaaudio/examples/write_sine/src/write_sine_callback.cpp
+++ b/media/libaaudio/examples/write_sine/src/write_sine_callback.cpp
@@ -31,7 +31,7 @@
#include "AAudioSimplePlayer.h"
#include "AAudioArgsParser.h"
-#define APP_VERSION "0.1.6"
+#define APP_VERSION "0.1.7"
constexpr int32_t kDefaultHangTimeMSec = 10;
diff --git a/media/libaaudio/include/aaudio/AAudio.h b/media/libaaudio/include/aaudio/AAudio.h
index 8e36c77..1c1df6c 100644
--- a/media/libaaudio/include/aaudio/AAudio.h
+++ b/media/libaaudio/include/aaudio/AAudio.h
@@ -37,7 +37,7 @@
/**
* This is used to represent a value that has not been specified.
- * For example, an application could use AAUDIO_UNSPECIFIED to indicate
+ * For example, an application could use {@link #AAUDIO_UNSPECIFIED} to indicate
* that is did not not care what the specific value of a parameter was
* and would accept whatever it was given.
*/
@@ -232,7 +232,8 @@
* This information is used by certain platforms or routing policies
* to make more refined volume or routing decisions.
*
- * Note that these match the equivalent values in AudioAttributes in the Android Java API.
+ * Note that these match the equivalent values in {@link android.media.AudioAttributes}
+ * in the Android Java API.
*
* Added in API level 28.
*/
@@ -303,12 +304,13 @@
/**
* The CONTENT_TYPE attribute describes "what" you are playing.
* It expresses the general category of the content. This information is optional.
- * But in case it is known (for instance {@link #AAUDIO_CONTENT_TYPE_MOVIE} for a
- * movie streaming service or {@link #AAUDIO_CONTENT_TYPE_SPEECH} for
+ * But in case it is known (for instance AAUDIO_CONTENT_TYPE_MOVIE for a
+ * movie streaming service or AAUDIO_CONTENT_TYPE_SPEECH for
* an audio book application) this information might be used by the audio framework to
* enforce audio focus.
*
- * Note that these match the equivalent values in AudioAttributes in the Android Java API.
+ * Note that these match the equivalent values in {@link android.media.AudioAttributes}
+ * in the Android Java API.
*
* Added in API level 28.
*/
@@ -384,6 +386,48 @@
typedef int32_t aaudio_input_preset_t;
/**
+ * Specifying if audio may or may not be captured by other apps or the system.
+ *
+ * Note that these match the equivalent values in {@link android.media.AudioAttributes}
+ * in the Android Java API.
+ *
+ * Added in API level 29.
+ */
+enum {
+ /**
+ * Indicates that the audio may be captured by any app.
+ *
+ * For privacy, the following usages can not be recorded: AAUDIO_VOICE_COMMUNICATION*,
+ * AAUDIO_USAGE_NOTIFICATION*, AAUDIO_USAGE_ASSISTANCE* and {@link #AAUDIO_USAGE_ASSISTANT}.
+ *
+ * On {@link android.os.Build.VERSION_CODES#Q}, this means only {@link #AAUDIO_USAGE_MEDIA}
+ * and {@link #AAUDIO_USAGE_GAME} may be captured.
+ *
+ * See {@link android.media.AudioAttributes#ALLOW_CAPTURE_BY_ALL}.
+ */
+ AAUDIO_ALLOW_CAPTURE_BY_ALL = 1,
+ /**
+ * Indicates that the audio may only be captured by system apps.
+ *
+ * System apps can capture for many purposes like accessibility, user guidance...
+ * but have strong restriction. See
+ * {@link android.media.AudioAttributes#ALLOW_CAPTURE_BY_SYSTEM} for what the system apps
+ * can do with the capture audio.
+ */
+ AAUDIO_ALLOW_CAPTURE_BY_SYSTEM = 2,
+ /**
+ * Indicates that the audio may not be recorded by any app, even if it is a system app.
+ *
+ * It is encouraged to use {@link #AAUDIO_ALLOW_CAPTURE_BY_SYSTEM} instead of this value as system apps
+ * provide significant and useful features for the user (eg. accessibility).
+ * See {@link android.media.AudioAttributes#ALLOW_CAPTURE_BY_NONE}.
+ */
+ AAUDIO_ALLOW_CAPTURE_BY_NONE = 3,
+};
+
+typedef int32_t aaudio_allowed_capture_policy_t;
+
+/**
* These may be used with AAudioStreamBuilder_setSessionId().
*
* Added in API level 28.
@@ -452,8 +496,8 @@
*
* The deviceId is initially unspecified, meaning that the current default device will be used.
*
- * The default direction is AAUDIO_DIRECTION_OUTPUT.
- * The default sharing mode is AAUDIO_SHARING_MODE_SHARED.
+ * The default direction is {@link #AAUDIO_DIRECTION_OUTPUT}.
+ * The default sharing mode is {@link #AAUDIO_SHARING_MODE_SHARED}.
* The data format, samplesPerFrames and sampleRate are unspecified and will be
* chosen by the device when it is opened.
*
@@ -478,7 +522,7 @@
/**
* Request a sample rate in Hertz.
*
- * The default, if you do not call this function, is AAUDIO_UNSPECIFIED.
+ * The default, if you do not call this function, is {@link #AAUDIO_UNSPECIFIED}.
* An optimal value will then be chosen when the stream is opened.
* After opening a stream with an unspecified value, the application must
* query for the actual value, which may vary by device.
@@ -495,7 +539,7 @@
/**
* Request a number of channels for the stream.
*
- * The default, if you do not call this function, is AAUDIO_UNSPECIFIED.
+ * The default, if you do not call this function, is {@link #AAUDIO_UNSPECIFIED}.
* An optimal value will then be chosen when the stream is opened.
* After opening a stream with an unspecified value, the application must
* query for the actual value, which may vary by device.
@@ -519,9 +563,9 @@
int32_t samplesPerFrame) __INTRODUCED_IN(26);
/**
- * Request a sample data format, for example AAUDIO_FORMAT_PCM_I16.
+ * Request a sample data format, for example {@link #AAUDIO_FORMAT_PCM_I16}.
*
- * The default, if you do not call this function, is AAUDIO_UNSPECIFIED.
+ * The default, if you do not call this function, is {@link #AAUDIO_UNSPECIFIED}.
* An optimal value will then be chosen when the stream is opened.
* After opening a stream with an unspecified value, the application must
* query for the actual value, which may vary by device.
@@ -530,7 +574,8 @@
* If a stream cannot be opened with the specified value then the open will fail.
*
* @param builder reference provided by AAudio_createStreamBuilder()
- * @param format common formats are AAUDIO_FORMAT_PCM_FLOAT and AAUDIO_FORMAT_PCM_I16.
+ * @param format common formats are {@link #AAUDIO_FORMAT_PCM_FLOAT} and
+ * {@link #AAUDIO_FORMAT_PCM_I16}.
*/
AAUDIO_API void AAudioStreamBuilder_setFormat(AAudioStreamBuilder* builder,
aaudio_format_t format) __INTRODUCED_IN(26);
@@ -538,13 +583,13 @@
/**
* Request a mode for sharing the device.
*
- * The default, if you do not call this function, is AAUDIO_SHARING_MODE_SHARED.
+ * The default, if you do not call this function, is {@link #AAUDIO_SHARING_MODE_SHARED}.
*
* The requested sharing mode may not be available.
* The application can query for the actual mode after the stream is opened.
*
* @param builder reference provided by AAudio_createStreamBuilder()
- * @param sharingMode AAUDIO_SHARING_MODE_SHARED or AAUDIO_SHARING_MODE_EXCLUSIVE
+ * @param sharingMode {@link #AAUDIO_SHARING_MODE_SHARED} or {@link #AAUDIO_SHARING_MODE_EXCLUSIVE}
*/
AAUDIO_API void AAudioStreamBuilder_setSharingMode(AAudioStreamBuilder* builder,
aaudio_sharing_mode_t sharingMode) __INTRODUCED_IN(26);
@@ -552,10 +597,10 @@
/**
* Request the direction for a stream.
*
- * The default, if you do not call this function, is AAUDIO_DIRECTION_OUTPUT.
+ * The default, if you do not call this function, is {@link #AAUDIO_DIRECTION_OUTPUT}.
*
* @param builder reference provided by AAudio_createStreamBuilder()
- * @param direction AAUDIO_DIRECTION_OUTPUT or AAUDIO_DIRECTION_INPUT
+ * @param direction {@link #AAUDIO_DIRECTION_OUTPUT} or {@link #AAUDIO_DIRECTION_INPUT}
*/
AAUDIO_API void AAudioStreamBuilder_setDirection(AAudioStreamBuilder* builder,
aaudio_direction_t direction) __INTRODUCED_IN(26);
@@ -564,10 +609,10 @@
* Set the requested buffer capacity in frames.
* The final AAudioStream capacity may differ, but will probably be at least this big.
*
- * The default, if you do not call this function, is AAUDIO_UNSPECIFIED.
+ * The default, if you do not call this function, is {@link #AAUDIO_UNSPECIFIED}.
*
* @param builder reference provided by AAudio_createStreamBuilder()
- * @param numFrames the desired buffer capacity in frames or AAUDIO_UNSPECIFIED
+ * @param numFrames the desired buffer capacity in frames or {@link #AAUDIO_UNSPECIFIED}
*/
AAUDIO_API void AAudioStreamBuilder_setBufferCapacityInFrames(AAudioStreamBuilder* builder,
int32_t numFrames) __INTRODUCED_IN(26);
@@ -575,16 +620,17 @@
/**
* Set the requested performance mode.
*
- * Supported modes are AAUDIO_PERFORMANCE_MODE_NONE, AAUDIO_PERFORMANCE_MODE_POWER_SAVING
- * and AAUDIO_PERFORMANCE_MODE_LOW_LATENCY.
+ * Supported modes are {@link #AAUDIO_PERFORMANCE_MODE_NONE},
+ * {@link #AAUDIO_PERFORMANCE_MODE_POWER_SAVING} * and {@link #AAUDIO_PERFORMANCE_MODE_LOW_LATENCY}.
*
- * The default, if you do not call this function, is AAUDIO_PERFORMANCE_MODE_NONE.
+ * The default, if you do not call this function, is {@link #AAUDIO_PERFORMANCE_MODE_NONE}.
*
* You may not get the mode you requested.
- * You can call AAudioStream_getPerformanceMode() to find out the final mode for the stream.
+ * You can call AAudioStream_getPerformanceMode()
+ * to find out the final mode for the stream.
*
* @param builder reference provided by AAudio_createStreamBuilder()
- * @param mode the desired performance mode, eg. AAUDIO_PERFORMANCE_MODE_LOW_LATENCY
+ * @param mode the desired performance mode, eg. {@link #AAUDIO_PERFORMANCE_MODE_LOW_LATENCY}
*/
AAUDIO_API void AAudioStreamBuilder_setPerformanceMode(AAudioStreamBuilder* builder,
aaudio_performance_mode_t mode) __INTRODUCED_IN(26);
@@ -596,12 +642,12 @@
* behavior of the stream.
* This could, for example, affect how volume and focus is handled for the stream.
*
- * The default, if you do not call this function, is AAUDIO_USAGE_MEDIA.
+ * The default, if you do not call this function, is {@link #AAUDIO_USAGE_MEDIA}.
*
* Added in API level 28.
*
* @param builder reference provided by AAudio_createStreamBuilder()
- * @param usage the desired usage, eg. AAUDIO_USAGE_GAME
+ * @param usage the desired usage, eg. {@link #AAUDIO_USAGE_GAME}
*/
AAUDIO_API void AAudioStreamBuilder_setUsage(AAudioStreamBuilder* builder,
aaudio_usage_t usage) __INTRODUCED_IN(28);
@@ -613,12 +659,12 @@
* behavior of the stream.
* This could, for example, affect whether a stream is paused when a notification occurs.
*
- * The default, if you do not call this function, is AAUDIO_CONTENT_TYPE_MUSIC.
+ * The default, if you do not call this function, is {@link #AAUDIO_CONTENT_TYPE_MUSIC}.
*
* Added in API level 28.
*
* @param builder reference provided by AAudio_createStreamBuilder()
- * @param contentType the type of audio data, eg. AAUDIO_CONTENT_TYPE_SPEECH
+ * @param contentType the type of audio data, eg. {@link #AAUDIO_CONTENT_TYPE_SPEECH}
*/
AAUDIO_API void AAudioStreamBuilder_setContentType(AAudioStreamBuilder* builder,
aaudio_content_type_t contentType) __INTRODUCED_IN(28);
@@ -631,7 +677,7 @@
* This could, for example, affect which microphones are used and how the
* recorded data is processed.
*
- * The default, if you do not call this function, is AAUDIO_INPUT_PRESET_VOICE_RECOGNITION.
+ * The default, if you do not call this function, is {@link #AAUDIO_INPUT_PRESET_VOICE_RECOGNITION}.
* That is because VOICE_RECOGNITION is the preset with the lowest latency
* on many platforms.
*
@@ -643,14 +689,30 @@
AAUDIO_API void AAudioStreamBuilder_setInputPreset(AAudioStreamBuilder* builder,
aaudio_input_preset_t inputPreset) __INTRODUCED_IN(28);
+/**
+ * Specify whether this stream audio may or may not be captured by other apps or the system.
+ *
+ * The default is {@link #AAUDIO_ALLOW_CAPTURE_BY_ALL}.
+ *
+ * Note that an application can also set its global policy, in which case the most restrictive
+ * policy is always applied. See {@link android.media.AudioAttributes#setAllowedCapturePolicy(int)}
+ *
+ * Added in API level 29.
+ *
+ * @param builder reference provided by AAudio_createStreamBuilder()
+ * @param inputPreset the desired level of opt-out from being captured.
+ */
+AAUDIO_API void AAudioStreamBuilder_setAllowedCapturePolicy(AAudioStreamBuilder* builder,
+ aaudio_allowed_capture_policy_t capturePolicy) __INTRODUCED_IN(29);
+
/** Set the requested session ID.
*
* The session ID can be used to associate a stream with effects processors.
* The effects are controlled using the Android AudioEffect Java API.
*
- * The default, if you do not call this function, is AAUDIO_SESSION_ID_NONE.
+ * The default, if you do not call this function, is {@link #AAUDIO_SESSION_ID_NONE}.
*
- * If set to AAUDIO_SESSION_ID_ALLOCATE then a session ID will be allocated
+ * If set to {@link #AAUDIO_SESSION_ID_ALLOCATE} then a session ID will be allocated
* when the stream is opened.
*
* The allocated session ID can be obtained by calling AAudioStream_getSessionId()
@@ -668,7 +730,7 @@
* Added in API level 28.
*
* @param builder reference provided by AAudio_createStreamBuilder()
- * @param sessionId an allocated sessionID or AAUDIO_SESSION_ID_ALLOCATE
+ * @param sessionId an allocated sessionID or {@link #AAUDIO_SESSION_ID_ALLOCATE}
*/
AAUDIO_API void AAudioStreamBuilder_setSessionId(AAudioStreamBuilder* builder,
aaudio_session_id_t sessionId) __INTRODUCED_IN(28);
@@ -751,15 +813,16 @@
*
* Note that when using this callback, the audio data will be passed in or out
* of the function as an argument.
- * So you cannot call AAudioStream_write() or AAudioStream_read() on the same stream
- * that has an active data callback.
+ * So you cannot call AAudioStream_write() or AAudioStream_read()
+ * on the same stream that has an active data callback.
*
- * The callback function will start being called after AAudioStream_requestStart() is called.
+ * The callback function will start being called after AAudioStream_requestStart()
+ * is called.
* It will stop being called after AAudioStream_requestPause() or
* AAudioStream_requestStop() is called.
*
* This callback function will be called on a real-time thread owned by AAudio. See
- * {@link AAudioStream_dataCallback} for more information.
+ * {@link #AAudioStream_dataCallback} for more information.
*
* Note that the AAudio callbacks will never be called simultaneously from multiple threads.
*
@@ -773,9 +836,9 @@
/**
* Set the requested data callback buffer size in frames.
- * See {@link AAudioStream_dataCallback}.
+ * See {@link #AAudioStream_dataCallback}.
*
- * The default, if you do not call this function, is AAUDIO_UNSPECIFIED.
+ * The default, if you do not call this function, is {@link #AAUDIO_UNSPECIFIED}.
*
* For the lowest possible latency, do not call this function. AAudio will then
* call the dataProc callback function with whatever size is optimal.
@@ -792,7 +855,7 @@
* half the buffer capacity, to allow double buffering.
*
* @param builder reference provided by AAudio_createStreamBuilder()
- * @param numFrames the desired buffer size in frames or AAUDIO_UNSPECIFIED
+ * @param numFrames the desired buffer size in frames or {@link #AAUDIO_UNSPECIFIED}
*/
AAUDIO_API void AAudioStreamBuilder_setFramesPerDataCallback(AAudioStreamBuilder* builder,
int32_t numFrames) __INTRODUCED_IN(26);
@@ -853,12 +916,12 @@
/**
* Open a stream based on the options in the StreamBuilder.
*
- * AAudioStream_close must be called when finished with the stream to recover
+ * AAudioStream_close() must be called when finished with the stream to recover
* the memory and to free the associated resources.
*
* @param builder reference provided by AAudio_createStreamBuilder()
* @param stream pointer to a variable to receive the new stream reference
- * @return AAUDIO_OK or a negative error.
+ * @return {@link #AAUDIO_OK} or a negative error.
*/
AAUDIO_API aaudio_result_t AAudioStreamBuilder_openStream(AAudioStreamBuilder* builder,
AAudioStream** stream) __INTRODUCED_IN(26);
@@ -867,7 +930,7 @@
* Delete the resources associated with the StreamBuilder.
*
* @param builder reference provided by AAudio_createStreamBuilder()
- * @return AAUDIO_OK or a negative error.
+ * @return {@link #AAUDIO_OK} or a negative error.
*/
AAUDIO_API aaudio_result_t AAudioStreamBuilder_delete(AAudioStreamBuilder* builder)
__INTRODUCED_IN(26);
@@ -880,7 +943,7 @@
* Free the resources associated with a stream created by AAudioStreamBuilder_openStream()
*
* @param stream reference provided by AAudioStreamBuilder_openStream()
- * @return AAUDIO_OK or a negative error.
+ * @return {@link #AAUDIO_OK} or a negative error.
*/
AAUDIO_API aaudio_result_t AAudioStream_close(AAudioStream* stream) __INTRODUCED_IN(26);
@@ -888,24 +951,26 @@
* Asynchronously request to start playing the stream. For output streams, one should
* write to the stream to fill the buffer before starting.
* Otherwise it will underflow.
- * After this call the state will be in AAUDIO_STREAM_STATE_STARTING or AAUDIO_STREAM_STATE_STARTED.
+ * After this call the state will be in {@link #AAUDIO_STREAM_STATE_STARTING} or
+ * {@link #AAUDIO_STREAM_STATE_STARTED}.
*
* @param stream reference provided by AAudioStreamBuilder_openStream()
- * @return AAUDIO_OK or a negative error.
+ * @return {@link #AAUDIO_OK} or a negative error.
*/
AAUDIO_API aaudio_result_t AAudioStream_requestStart(AAudioStream* stream) __INTRODUCED_IN(26);
/**
* Asynchronous request for the stream to pause.
* Pausing a stream will freeze the data flow but not flush any buffers.
- * Use AAudioStream_Start() to resume playback after a pause.
- * After this call the state will be in AAUDIO_STREAM_STATE_PAUSING or AAUDIO_STREAM_STATE_PAUSED.
+ * Use AAudioStream_requestStart() to resume playback after a pause.
+ * After this call the state will be in {@link #AAUDIO_STREAM_STATE_PAUSING} or
+ * {@link #AAUDIO_STREAM_STATE_PAUSED}.
*
- * This will return AAUDIO_ERROR_UNIMPLEMENTED for input streams.
+ * This will return {@link #AAUDIO_ERROR_UNIMPLEMENTED} for input streams.
* For input streams use AAudioStream_requestStop().
*
* @param stream reference provided by AAudioStreamBuilder_openStream()
- * @return AAUDIO_OK or a negative error.
+ * @return {@link #AAUDIO_OK} or a negative error.
*/
AAUDIO_API aaudio_result_t AAudioStream_requestPause(AAudioStream* stream) __INTRODUCED_IN(26);
@@ -914,32 +979,34 @@
* Flushing will discard any pending data.
* This call only works if the stream is pausing or paused. TODO review
* Frame counters are not reset by a flush. They may be advanced.
- * After this call the state will be in AAUDIO_STREAM_STATE_FLUSHING or AAUDIO_STREAM_STATE_FLUSHED.
+ * After this call the state will be in {@link #AAUDIO_STREAM_STATE_FLUSHING} or
+ * {@link #AAUDIO_STREAM_STATE_FLUSHED}.
*
- * This will return AAUDIO_ERROR_UNIMPLEMENTED for input streams.
+ * This will return {@link #AAUDIO_ERROR_UNIMPLEMENTED} for input streams.
*
* @param stream reference provided by AAudioStreamBuilder_openStream()
- * @return AAUDIO_OK or a negative error.
+ * @return {@link #AAUDIO_OK} or a negative error.
*/
AAUDIO_API aaudio_result_t AAudioStream_requestFlush(AAudioStream* stream) __INTRODUCED_IN(26);
/**
* Asynchronous request for the stream to stop.
* The stream will stop after all of the data currently buffered has been played.
- * After this call the state will be in AAUDIO_STREAM_STATE_STOPPING or AAUDIO_STREAM_STATE_STOPPED.
+ * After this call the state will be in {@link #AAUDIO_STREAM_STATE_STOPPING} or
+ * {@link #AAUDIO_STREAM_STATE_STOPPED}.
*
* @param stream reference provided by AAudioStreamBuilder_openStream()
- * @return AAUDIO_OK or a negative error.
+ * @return {@link #AAUDIO_OK} or a negative error.
*/
AAUDIO_API aaudio_result_t AAudioStream_requestStop(AAudioStream* stream) __INTRODUCED_IN(26);
/**
- * Query the current state of the client, eg. AAUDIO_STREAM_STATE_PAUSING
+ * Query the current state of the client, eg. {@link #AAUDIO_STREAM_STATE_PAUSING}
*
* This function will immediately return the state without updating the state.
* If you want to update the client state based on the server state then
* call AAudioStream_waitForStateChange() with currentState
- * set to AAUDIO_STREAM_STATE_UNKNOWN and a zero timeout.
+ * set to {@link #AAUDIO_STREAM_STATE_UNKNOWN} and a zero timeout.
*
* @param stream reference provided by AAudioStreamBuilder_openStream()
*/
@@ -965,7 +1032,7 @@
* @param inputState The state we want to avoid.
* @param nextState Pointer to a variable that will be set to the new state.
* @param timeoutNanoseconds Maximum number of nanoseconds to wait for completion.
- * @return AAUDIO_OK or a negative error.
+ * @return {@link #AAUDIO_OK} or a negative error.
*/
AAUDIO_API aaudio_result_t AAudioStream_waitForStateChange(AAudioStream* stream,
aaudio_stream_state_t inputState, aaudio_stream_state_t *nextState,
@@ -1082,17 +1149,17 @@
* This call can be used if the application needs to know the value of numFrames before
* the stream is started. This is not normally necessary.
*
- * If a specific size was requested by calling AAudioStreamBuilder_setFramesPerDataCallback()
- * then this will be the same size.
+ * If a specific size was requested by calling
+ * AAudioStreamBuilder_setFramesPerDataCallback() then this will be the same size.
*
* If AAudioStreamBuilder_setFramesPerDataCallback() was not called then this will
- * return the size chosen by AAudio, or AAUDIO_UNSPECIFIED.
+ * return the size chosen by AAudio, or {@link #AAUDIO_UNSPECIFIED}.
*
- * AAUDIO_UNSPECIFIED indicates that the callback buffer size for this stream
+ * {@link #AAUDIO_UNSPECIFIED} indicates that the callback buffer size for this stream
* may vary from one dataProc callback to the next.
*
* @param stream reference provided by AAudioStreamBuilder_openStream()
- * @return callback buffer size in frames or AAUDIO_UNSPECIFIED
+ * @return callback buffer size in frames or {@link #AAUDIO_UNSPECIFIED}
*/
AAUDIO_API int32_t AAudioStream_getFramesPerDataCallback(AAudioStream* stream) __INTRODUCED_IN(26);
@@ -1202,21 +1269,22 @@
* The session ID can be used to associate a stream with effects processors.
* The effects are controlled using the Android AudioEffect Java API.
*
- * If AAudioStreamBuilder_setSessionId() was called with AAUDIO_SESSION_ID_ALLOCATE
+ * If AAudioStreamBuilder_setSessionId() was
+ * called with {@link #AAUDIO_SESSION_ID_ALLOCATE}
* then a new session ID should be allocated once when the stream is opened.
*
* If AAudioStreamBuilder_setSessionId() was called with a previously allocated
* session ID then that value should be returned.
*
* If AAudioStreamBuilder_setSessionId() was not called then this function should
- * return AAUDIO_SESSION_ID_NONE.
+ * return {@link #AAUDIO_SESSION_ID_NONE}.
*
* The sessionID for a stream should not change once the stream has been opened.
*
* Added in API level 28.
*
* @param stream reference provided by AAudioStreamBuilder_openStream()
- * @return session ID or AAUDIO_SESSION_ID_NONE
+ * @return session ID or {@link #AAUDIO_SESSION_ID_NONE}
*/
AAUDIO_API aaudio_session_id_t AAudioStream_getSessionId(AAudioStream* stream) __INTRODUCED_IN(28);
@@ -1225,11 +1293,11 @@
* This can be used to synchronize audio with video or MIDI.
* It can also be used to align a recorded stream with a playback stream.
*
- * Timestamps are only valid when the stream is in AAUDIO_STREAM_STATE_STARTED.
- * AAUDIO_ERROR_INVALID_STATE will be returned if the stream is not started.
+ * Timestamps are only valid when the stream is in {@link #AAUDIO_STREAM_STATE_STARTED}.
+ * {@link #AAUDIO_ERROR_INVALID_STATE} will be returned if the stream is not started.
* Note that because requestStart() is asynchronous, timestamps will not be valid until
* a short time after calling requestStart().
- * So AAUDIO_ERROR_INVALID_STATE should not be considered a fatal error.
+ * So {@link #AAUDIO_ERROR_INVALID_STATE} should not be considered a fatal error.
* Just try calling again later.
*
* If an error occurs, then the position and time will not be modified.
@@ -1240,7 +1308,7 @@
* @param clockid CLOCK_MONOTONIC or CLOCK_BOOTTIME
* @param framePosition pointer to a variable to receive the position
* @param timeNanoseconds pointer to a variable to receive the time
- * @return AAUDIO_OK or a negative error
+ * @return {@link #AAUDIO_OK} or a negative error
*/
AAUDIO_API aaudio_result_t AAudioStream_getTimestamp(AAudioStream* stream,
clockid_t clockid, int64_t *framePosition, int64_t *timeNanoseconds) __INTRODUCED_IN(26);
@@ -1261,7 +1329,7 @@
* Added in API level 28.
*
* @param stream reference provided by AAudioStreamBuilder_openStream()
- * @return content type, for example AAUDIO_CONTENT_TYPE_MUSIC
+ * @return content type, for example {@link #AAUDIO_CONTENT_TYPE_MUSIC}
*/
AAUDIO_API aaudio_content_type_t AAudioStream_getContentType(AAudioStream* stream)
__INTRODUCED_IN(28);
@@ -1272,11 +1340,23 @@
* Added in API level 28.
*
* @param stream reference provided by AAudioStreamBuilder_openStream()
- * @return input preset, for example AAUDIO_INPUT_PRESET_CAMCORDER
+ * @return input preset, for example {@link #AAUDIO_INPUT_PRESET_CAMCORDER}
*/
AAUDIO_API aaudio_input_preset_t AAudioStream_getInputPreset(AAudioStream* stream)
__INTRODUCED_IN(28);
+/**
+ * Return the policy that determines whether the audio may or may not be captured
+ * by other apps or the system.
+ *
+ * Added in API level 29.
+ *
+ * @param stream reference provided by AAudioStreamBuilder_openStream()
+ * @return the allowed capture policy, for example {@link #AAUDIO_ALLOW_CAPTURE_BY_ALL}
+ */
+AAUDIO_API aaudio_allowed_capture_policy_t AAudioStream_getAllowedCapturePolicy(
+ AAudioStream* stream) __INTRODUCED_IN(29);
+
#ifdef __cplusplus
}
#endif
diff --git a/media/libaaudio/src/binding/AAudioStreamConfiguration.cpp b/media/libaaudio/src/binding/AAudioStreamConfiguration.cpp
index 3d1bc9b..a987fab 100644
--- a/media/libaaudio/src/binding/AAudioStreamConfiguration.cpp
+++ b/media/libaaudio/src/binding/AAudioStreamConfiguration.cpp
@@ -62,6 +62,8 @@
if (status != NO_ERROR) goto error;
status = parcel->writeInt32((int32_t) getInputPreset());
if (status != NO_ERROR) goto error;
+ status = parcel->writeInt32((int32_t) getAllowedCapturePolicy());
+ if (status != NO_ERROR) goto error;
status = parcel->writeInt32(getSessionId());
if (status != NO_ERROR) goto error;
return NO_ERROR;
@@ -105,6 +107,9 @@
setInputPreset((aaudio_input_preset_t) value);
status = parcel->readInt32(&value);
if (status != NO_ERROR) goto error;
+ setAllowedCapturePolicy((aaudio_allowed_capture_policy_t) value);
+ status = parcel->readInt32(&value);
+ if (status != NO_ERROR) goto error;
setSessionId(value);
return NO_ERROR;
diff --git a/media/libaaudio/src/core/AAudioAudio.cpp b/media/libaaudio/src/core/AAudioAudio.cpp
index 0d71efc..8ae2644 100644
--- a/media/libaaudio/src/core/AAudioAudio.cpp
+++ b/media/libaaudio/src/core/AAudioAudio.cpp
@@ -204,6 +204,12 @@
streamBuilder->setBufferCapacity(frames);
}
+AAUDIO_API void AAudioStreamBuilder_setAllowedCapturePolicy(
+ AAudioStreamBuilder* builder, aaudio_allowed_capture_policy_t policy) {
+ AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
+ streamBuilder->setAllowedCapturePolicy(policy);
+}
+
AAUDIO_API void AAudioStreamBuilder_setSessionId(AAudioStreamBuilder* builder,
aaudio_session_id_t sessionId)
{
@@ -494,6 +500,13 @@
return audioStream->getInputPreset();
}
+AAUDIO_API aaudio_allowed_capture_policy_t AAudioStream_getAllowedCapturePolicy(
+ AAudioStream* stream)
+{
+ AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
+ return audioStream->getAllowedCapturePolicy();
+}
+
AAUDIO_API int32_t AAudioStream_getSessionId(AAudioStream* stream)
{
AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
diff --git a/media/libaaudio/src/core/AAudioStreamParameters.cpp b/media/libaaudio/src/core/AAudioStreamParameters.cpp
index 88da53a..e5bda30 100644
--- a/media/libaaudio/src/core/AAudioStreamParameters.cpp
+++ b/media/libaaudio/src/core/AAudioStreamParameters.cpp
@@ -35,17 +35,18 @@
AAudioStreamParameters::~AAudioStreamParameters() {}
void AAudioStreamParameters::copyFrom(const AAudioStreamParameters &other) {
- mSamplesPerFrame = other.mSamplesPerFrame;
- mSampleRate = other.mSampleRate;
- mDeviceId = other.mDeviceId;
- mSessionId = other.mSessionId;
- mSharingMode = other.mSharingMode;
- mAudioFormat = other.mAudioFormat;
- mDirection = other.mDirection;
- mBufferCapacity = other.mBufferCapacity;
- mUsage = other.mUsage;
- mContentType = other.mContentType;
- mInputPreset = other.mInputPreset;
+ mSamplesPerFrame = other.mSamplesPerFrame;
+ mSampleRate = other.mSampleRate;
+ mDeviceId = other.mDeviceId;
+ mSessionId = other.mSessionId;
+ mSharingMode = other.mSharingMode;
+ mAudioFormat = other.mAudioFormat;
+ mDirection = other.mDirection;
+ mBufferCapacity = other.mBufferCapacity;
+ mUsage = other.mUsage;
+ mContentType = other.mContentType;
+ mInputPreset = other.mInputPreset;
+ mAllowedCapturePolicy = other.mAllowedCapturePolicy;
}
static aaudio_result_t isFormatValid(audio_format_t format) {
@@ -166,19 +167,32 @@
// break;
}
+ switch (mAllowedCapturePolicy) {
+ case AAUDIO_UNSPECIFIED:
+ case AAUDIO_ALLOW_CAPTURE_BY_ALL:
+ case AAUDIO_ALLOW_CAPTURE_BY_SYSTEM:
+ case AAUDIO_ALLOW_CAPTURE_BY_NONE:
+ break; // valid
+ default:
+ ALOGE("allowed capture policy not valid = %d", mAllowedCapturePolicy);
+ return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
+ // break;
+ }
+
return AAUDIO_OK;
}
void AAudioStreamParameters::dump() const {
- ALOGD("mDeviceId = %6d", mDeviceId);
- ALOGD("mSessionId = %6d", mSessionId);
- ALOGD("mSampleRate = %6d", mSampleRate);
- ALOGD("mSamplesPerFrame = %6d", mSamplesPerFrame);
- ALOGD("mSharingMode = %6d", (int)mSharingMode);
- ALOGD("mAudioFormat = %6d", (int)mAudioFormat);
- ALOGD("mDirection = %6d", mDirection);
- ALOGD("mBufferCapacity = %6d", mBufferCapacity);
- ALOGD("mUsage = %6d", mUsage);
- ALOGD("mContentType = %6d", mContentType);
- ALOGD("mInputPreset = %6d", mInputPreset);
+ ALOGD("mDeviceId = %6d", mDeviceId);
+ ALOGD("mSessionId = %6d", mSessionId);
+ ALOGD("mSampleRate = %6d", mSampleRate);
+ ALOGD("mSamplesPerFrame = %6d", mSamplesPerFrame);
+ ALOGD("mSharingMode = %6d", (int)mSharingMode);
+ ALOGD("mAudioFormat = %6d", (int)mAudioFormat);
+ ALOGD("mDirection = %6d", mDirection);
+ ALOGD("mBufferCapacity = %6d", mBufferCapacity);
+ ALOGD("mUsage = %6d", mUsage);
+ ALOGD("mContentType = %6d", mContentType);
+ ALOGD("mInputPreset = %6d", mInputPreset);
+ ALOGD("mAllowedCapturePolicy = %6d", mAllowedCapturePolicy);
}
diff --git a/media/libaaudio/src/core/AAudioStreamParameters.h b/media/libaaudio/src/core/AAudioStreamParameters.h
index 6beb4b2..2e21a8d 100644
--- a/media/libaaudio/src/core/AAudioStreamParameters.h
+++ b/media/libaaudio/src/core/AAudioStreamParameters.h
@@ -112,6 +112,14 @@
mInputPreset = inputPreset;
}
+ aaudio_allowed_capture_policy_t getAllowedCapturePolicy() const {
+ return mAllowedCapturePolicy;
+ }
+
+ void setAllowedCapturePolicy(aaudio_allowed_capture_policy_t policy) {
+ mAllowedCapturePolicy = policy;
+ }
+
aaudio_session_id_t getSessionId() const {
return mSessionId;
}
@@ -138,17 +146,18 @@
void dump() const;
private:
- int32_t mSamplesPerFrame = AAUDIO_UNSPECIFIED;
- int32_t mSampleRate = AAUDIO_UNSPECIFIED;
- int32_t mDeviceId = AAUDIO_UNSPECIFIED;
- aaudio_sharing_mode_t mSharingMode = AAUDIO_SHARING_MODE_SHARED;
- audio_format_t mAudioFormat = AUDIO_FORMAT_DEFAULT;
- aaudio_direction_t mDirection = AAUDIO_DIRECTION_OUTPUT;
- aaudio_usage_t mUsage = AAUDIO_UNSPECIFIED;
- aaudio_content_type_t mContentType = AAUDIO_UNSPECIFIED;
- aaudio_input_preset_t mInputPreset = AAUDIO_UNSPECIFIED;
- int32_t mBufferCapacity = AAUDIO_UNSPECIFIED;
- aaudio_session_id_t mSessionId = AAUDIO_SESSION_ID_NONE;
+ int32_t mSamplesPerFrame = AAUDIO_UNSPECIFIED;
+ int32_t mSampleRate = AAUDIO_UNSPECIFIED;
+ int32_t mDeviceId = AAUDIO_UNSPECIFIED;
+ aaudio_sharing_mode_t mSharingMode = AAUDIO_SHARING_MODE_SHARED;
+ audio_format_t mAudioFormat = AUDIO_FORMAT_DEFAULT;
+ aaudio_direction_t mDirection = AAUDIO_DIRECTION_OUTPUT;
+ aaudio_usage_t mUsage = AAUDIO_UNSPECIFIED;
+ aaudio_content_type_t mContentType = AAUDIO_UNSPECIFIED;
+ aaudio_input_preset_t mInputPreset = AAUDIO_UNSPECIFIED;
+ int32_t mBufferCapacity = AAUDIO_UNSPECIFIED;
+ aaudio_allowed_capture_policy_t mAllowedCapturePolicy = AAUDIO_UNSPECIFIED;
+ aaudio_session_id_t mSessionId = AAUDIO_SESSION_ID_NONE;
};
} /* namespace aaudio */
diff --git a/media/libaaudio/src/core/AudioStream.cpp b/media/libaaudio/src/core/AudioStream.cpp
index e39a075..732d45c 100644
--- a/media/libaaudio/src/core/AudioStream.cpp
+++ b/media/libaaudio/src/core/AudioStream.cpp
@@ -94,6 +94,10 @@
if (mInputPreset == AAUDIO_UNSPECIFIED) {
mInputPreset = AAUDIO_INPUT_PRESET_VOICE_RECOGNITION;
}
+ mAllowedCapturePolicy = builder.getAllowedCapturePolicy();
+ if (mAllowedCapturePolicy == AAUDIO_UNSPECIFIED) {
+ mAllowedCapturePolicy = AAUDIO_ALLOW_CAPTURE_BY_ALL;
+ }
// callbacks
mFramesPerDataCallback = builder.getFramesPerDataCallback();
@@ -113,8 +117,8 @@
mPerformanceMode,
(isDataCallbackSet() ? "ON" : "OFF"),
mFramesPerDataCallback);
- ALOGI("open() usage = %d, contentType = %d, inputPreset = %d",
- mUsage, mContentType, mInputPreset);
+ ALOGI("open() usage = %d, contentType = %d, inputPreset = %d, allowedCapturePolicy = %d",
+ mUsage, mContentType, mInputPreset, mAllowedCapturePolicy);
return AAUDIO_OK;
}
diff --git a/media/libaaudio/src/core/AudioStream.h b/media/libaaudio/src/core/AudioStream.h
index 46951f5..32713b1 100644
--- a/media/libaaudio/src/core/AudioStream.h
+++ b/media/libaaudio/src/core/AudioStream.h
@@ -219,6 +219,10 @@
return mInputPreset;
}
+ aaudio_allowed_capture_policy_t getAllowedCapturePolicy() const {
+ return mAllowedCapturePolicy;
+ }
+
int32_t getSessionId() const {
return mSessionId;
}
@@ -525,6 +529,13 @@
mInputPreset = inputPreset;
}
+ /**
+ * This should not be called after the open() call.
+ */
+ void setAllowedCapturePolicy(aaudio_allowed_capture_policy_t policy) {
+ mAllowedCapturePolicy = policy;
+ }
+
private:
aaudio_result_t safeStop();
@@ -546,6 +557,7 @@
aaudio_usage_t mUsage = AAUDIO_UNSPECIFIED;
aaudio_content_type_t mContentType = AAUDIO_UNSPECIFIED;
aaudio_input_preset_t mInputPreset = AAUDIO_UNSPECIFIED;
+ aaudio_allowed_capture_policy_t mAllowedCapturePolicy = AAUDIO_ALLOW_CAPTURE_BY_ALL;
int32_t mSessionId = AAUDIO_UNSPECIFIED;
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.cpp b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
index ff95aed..d628bf7 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
@@ -134,12 +134,14 @@
AAudioConvert_contentTypeToInternal(builder.getContentType());
const audio_usage_t usage =
AAudioConvert_usageToInternal(builder.getUsage());
+ const audio_flags_mask_t attributesFlags =
+ AAudioConvert_allowCapturePolicyToAudioFlagsMask(builder.getAllowedCapturePolicy());
const audio_attributes_t attributes = {
.content_type = contentType,
.usage = usage,
.source = AUDIO_SOURCE_DEFAULT, // only used for recording
- .flags = AUDIO_FLAG_NONE, // Different than the AUDIO_OUTPUT_FLAGS
+ .flags = attributesFlags,
.tags = ""
};
@@ -420,6 +422,10 @@
aaudio_result_t AudioStreamTrack::setBufferSize(int32_t requestedFrames)
{
+ // Do not ask for less than one burst.
+ if (requestedFrames < getFramesPerBurst()) {
+ requestedFrames = getFramesPerBurst();
+ }
ssize_t result = mAudioTrack->setBufferSizeInFrames(requestedFrames);
if (result < 0) {
return AAudioConvert_androidToAAudioResult(result);
diff --git a/media/libaaudio/src/utility/AAudioUtilities.cpp b/media/libaaudio/src/utility/AAudioUtilities.cpp
index 723cbf1..96ed56a 100644
--- a/media/libaaudio/src/utility/AAudioUtilities.cpp
+++ b/media/libaaudio/src/utility/AAudioUtilities.cpp
@@ -217,6 +217,22 @@
return (audio_source_t) preset; // same value
}
+audio_flags_mask_t AAudioConvert_allowCapturePolicyToAudioFlagsMask(
+ aaudio_allowed_capture_policy_t policy) {
+ switch (policy) {
+ case AAUDIO_UNSPECIFIED:
+ case AAUDIO_ALLOW_CAPTURE_BY_ALL:
+ return AUDIO_FLAG_NONE;
+ case AAUDIO_ALLOW_CAPTURE_BY_SYSTEM:
+ return AUDIO_FLAG_NO_MEDIA_PROJECTION;
+ case AAUDIO_ALLOW_CAPTURE_BY_NONE:
+ return AUDIO_FLAG_NO_MEDIA_PROJECTION | AUDIO_FLAG_NO_SYSTEM_CAPTURE;
+ default:
+ ALOGE("%s() 0x%08X unrecognized", __func__, policy);
+ return AUDIO_FLAG_NONE; //
+ }
+}
+
int32_t AAudioConvert_framesToBytes(int32_t numFrames,
int32_t bytesPerFrame,
int32_t *sizeInBytes) {
diff --git a/media/libaaudio/src/utility/AAudioUtilities.h b/media/libaaudio/src/utility/AAudioUtilities.h
index dc2b198..76d0457 100644
--- a/media/libaaudio/src/utility/AAudioUtilities.h
+++ b/media/libaaudio/src/utility/AAudioUtilities.h
@@ -84,6 +84,14 @@
*/
audio_source_t AAudioConvert_inputPresetToAudioSource(aaudio_input_preset_t preset);
+/**
+ * Note that this function does not validate the passed in value.
+ * That is done somewhere else.
+ * @return internal audio flags mask
+ */
+audio_flags_mask_t AAudioConvert_allowCapturePolicyToAudioFlagsMask(
+ aaudio_allowed_capture_policy_t policy);
+
// Note that this code may be replaced by Settings or by some other system configuration tool.
#define AAUDIO_PROP_MMAP_POLICY "aaudio.mmap_policy"
diff --git a/media/libaaudio/tests/test_attributes.cpp b/media/libaaudio/tests/test_attributes.cpp
index dbf8712..32ee2a3 100644
--- a/media/libaaudio/tests/test_attributes.cpp
+++ b/media/libaaudio/tests/test_attributes.cpp
@@ -32,6 +32,7 @@
aaudio_usage_t usage,
aaudio_content_type_t contentType,
aaudio_input_preset_t preset = DONT_SET,
+ aaudio_allowed_capture_policy_t capturePolicy = DONT_SET,
aaudio_direction_t direction = AAUDIO_DIRECTION_OUTPUT) {
float *buffer = new float[kNumFrames * kChannelCount];
@@ -56,6 +57,9 @@
if (preset != DONT_SET) {
AAudioStreamBuilder_setInputPreset(aaudioBuilder, preset);
}
+ if (capturePolicy != DONT_SET) {
+ AAudioStreamBuilder_setAllowedCapturePolicy(aaudioBuilder, capturePolicy);
+ }
// Create an AAudioStream using the Builder.
ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
@@ -80,6 +84,12 @@
: preset;
EXPECT_EQ(expectedPreset, AAudioStream_getInputPreset(aaudioStream));
+ aaudio_allowed_capture_policy_t expectedCapturePolicy =
+ (capturePolicy == DONT_SET || capturePolicy == AAUDIO_UNSPECIFIED)
+ ? AAUDIO_ALLOW_CAPTURE_BY_ALL // default
+ : preset;
+ EXPECT_EQ(expectedCapturePolicy, AAudioStream_getAllowedCapturePolicy(aaudioStream));
+
EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStart(aaudioStream));
if (direction == AAUDIO_DIRECTION_INPUT) {
@@ -133,13 +143,21 @@
AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE,
};
+static const aaudio_input_preset_t sAllowCapturePolicies[] = {
+ DONT_SET,
+ AAUDIO_UNSPECIFIED,
+ AAUDIO_ALLOW_CAPTURE_BY_ALL,
+ AAUDIO_ALLOW_CAPTURE_BY_SYSTEM,
+ AAUDIO_ALLOW_CAPTURE_BY_NONE,
+};
+
static void checkAttributesUsage(aaudio_performance_mode_t perfMode) {
for (aaudio_usage_t usage : sUsages) {
checkAttributes(perfMode, usage, DONT_SET);
}
}
-static void checkAttributesContentType(aaudio_input_preset_t perfMode) {
+static void checkAttributesContentType(aaudio_performance_mode_t perfMode) {
for (aaudio_content_type_t contentType : sContentypes) {
checkAttributes(perfMode, DONT_SET, contentType);
}
@@ -151,6 +169,18 @@
DONT_SET,
DONT_SET,
inputPreset,
+ DONT_SET,
+ AAUDIO_DIRECTION_INPUT);
+ }
+}
+
+static void checkAttributesAllowedCapturePolicy(aaudio_performance_mode_t perfMode) {
+ for (aaudio_allowed_capture_policy_t policy : sAllowCapturePolicies) {
+ checkAttributes(perfMode,
+ DONT_SET,
+ DONT_SET,
+ DONT_SET,
+ policy,
AAUDIO_DIRECTION_INPUT);
}
}
@@ -167,6 +197,10 @@
checkAttributesInputPreset(AAUDIO_PERFORMANCE_MODE_NONE);
}
+TEST(test_attributes, aaudio_allowed_capture_policy_perfnone) {
+ checkAttributesAllowedCapturePolicy(AAUDIO_PERFORMANCE_MODE_NONE);
+}
+
TEST(test_attributes, aaudio_usage_lowlat) {
checkAttributesUsage(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
}
@@ -178,3 +212,7 @@
TEST(test_attributes, aaudio_input_preset_lowlat) {
checkAttributesInputPreset(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
}
+
+TEST(test_attributes, aaudio_allowed_capture_policy_lowlat) {
+ checkAttributesAllowedCapturePolicy(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
+}
diff --git a/media/libaudioclient/AudioPolicy.cpp b/media/libaudioclient/AudioPolicy.cpp
index 3ab38cd..65e797f 100644
--- a/media/libaudioclient/AudioPolicy.cpp
+++ b/media/libaudioclient/AudioPolicy.cpp
@@ -97,6 +97,7 @@
mDeviceType = (audio_devices_t) parcel->readInt32();
mDeviceAddress = parcel->readString8();
mCbFlags = (uint32_t)parcel->readInt32();
+ mAllowPrivilegedPlaybackCapture = parcel->readBool();
size_t size = (size_t)parcel->readInt32();
if (size > MAX_CRITERIA_PER_MIX) {
size = MAX_CRITERIA_PER_MIX;
@@ -120,6 +121,7 @@
parcel->writeInt32(mDeviceType);
parcel->writeString8(mDeviceAddress);
parcel->writeInt32(mCbFlags);
+ parcel->writeBool(mAllowPrivilegedPlaybackCapture);
size_t size = mCriteria.size();
if (size > MAX_CRITERIA_PER_MIX) {
size = MAX_CRITERIA_PER_MIX;
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index 5851533..f07be46 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -410,8 +410,8 @@
}
// Call these directly because we are already holding the lock.
- mAudioRecord->setMicrophoneDirection(mSelectedMicDirection);
- mAudioRecord->setMicrophoneFieldDimension(mSelectedMicFieldDimension);
+ mAudioRecord->setPreferredMicrophoneDirection(mSelectedMicDirection);
+ mAudioRecord->setPreferredMicrophoneFieldDimension(mSelectedMicFieldDimension);
if (status != NO_ERROR) {
mActive = false;
@@ -1381,7 +1381,7 @@
return mAudioRecord->getActiveMicrophones(activeMicrophones).transactionError();
}
-status_t AudioRecord::setMicrophoneDirection(audio_microphone_direction_t direction)
+status_t AudioRecord::setPreferredMicrophoneDirection(audio_microphone_direction_t direction)
{
AutoMutex lock(mLock);
if (mSelectedMicDirection == direction) {
@@ -1394,11 +1394,11 @@
// the internal AudioRecord hasn't be created yet, so just stash the attribute.
return OK;
} else {
- return mAudioRecord->setMicrophoneDirection(direction).transactionError();
+ return mAudioRecord->setPreferredMicrophoneDirection(direction).transactionError();
}
}
-status_t AudioRecord::setMicrophoneFieldDimension(float zoom) {
+status_t AudioRecord::setPreferredMicrophoneFieldDimension(float zoom) {
AutoMutex lock(mLock);
if (mSelectedMicFieldDimension == zoom) {
// NOP
@@ -1410,7 +1410,7 @@
// the internal AudioRecord hasn't be created yet, so just stash the attribute.
return OK;
} else {
- return mAudioRecord->setMicrophoneFieldDimension(zoom).transactionError();
+ return mAudioRecord->setPreferredMicrophoneFieldDimension(zoom).transactionError();
}
}
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 0ce2513..f324669 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -1133,6 +1133,12 @@
}
}
+status_t AudioSystem::setAllowedCapturePolicy(uid_t uid, audio_flags_mask_t flags) {
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == nullptr) return PERMISSION_DENIED;
+ return aps->setAllowedCapturePolicy(uid, flags);
+}
+
bool AudioSystem::isOffloadSupported(const audio_offload_info_t& info)
{
ALOGV("isOffloadSupported()");
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index 3bac44f..bf98c60 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -101,7 +101,8 @@
LIST_AUDIO_PRODUCT_STRATEGIES,
GET_STRATEGY_FOR_ATTRIBUTES,
LIST_AUDIO_VOLUME_GROUPS,
- GET_VOLUME_GROUP_FOR_ATTRIBUTES
+ GET_VOLUME_GROUP_FOR_ATTRIBUTES,
+ SET_ALLOWED_CAPTURE_POLICY,
};
#define MAX_ITEMS_PER_LIST 1024
@@ -603,6 +604,15 @@
return status;
}
+ status_t setAllowedCapturePolicy(uid_t uid, audio_flags_mask_t flags) override {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(uid);
+ data.writeInt32(flags);
+ remote()->transact(SET_ALLOWED_CAPTURE_POLICY, data, &reply);
+ return reply.readInt32();
+ }
+
virtual bool isOffloadSupported(const audio_offload_info_t& info)
{
Parcel data, reply;
@@ -2168,7 +2178,7 @@
CHECK_INTERFACE(IAudioPolicyService, data, reply);
bool isSupported = isHapticPlaybackSupported();
reply->writeBool(isSupported);
- return NO_ERROR;
+ return NO_ERROR;
}
case SET_UID_DEVICE_AFFINITY: {
@@ -2285,6 +2295,15 @@
return NO_ERROR;
}
+ case SET_ALLOWED_CAPTURE_POLICY: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ uid_t uid = data.readInt32();
+ audio_flags_mask_t flags = data.readInt32();
+ status_t status = setAllowedCapturePolicy(uid, flags);
+ reply->writeInt32(status);
+ return NO_ERROR;
+ }
+
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/media/libaudioclient/aidl/android/media/IAudioRecord.aidl b/media/libaudioclient/aidl/android/media/IAudioRecord.aidl
index cf9c7f4..ecf58b6 100644
--- a/media/libaudioclient/aidl/android/media/IAudioRecord.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioRecord.aidl
@@ -39,9 +39,9 @@
/* Set the microphone direction (for processing).
*/
- void setMicrophoneDirection(int /*audio_microphone_direction_t*/ direction);
+ void setPreferredMicrophoneDirection(int /*audio_microphone_direction_t*/ direction);
/* Set the microphone zoom (for processing).
*/
- void setMicrophoneFieldDimension(float zoom);
+ void setPreferredMicrophoneFieldDimension(float zoom);
}
diff --git a/media/libaudioclient/include/media/AudioPolicy.h b/media/libaudioclient/include/media/AudioPolicy.h
index bf8d627..4b94c12 100644
--- a/media/libaudioclient/include/media/AudioPolicy.h
+++ b/media/libaudioclient/include/media/AudioPolicy.h
@@ -114,6 +114,8 @@
audio_devices_t mDeviceType;
String8 mDeviceAddress;
uint32_t mCbFlags; // flags indicating which callbacks to use, see kCbFlag*
+ /** Ignore the AUDIO_FLAG_NO_MEDIA_PROJECTION */
+ bool mAllowPrivilegedPlaybackCapture = false;
};
diff --git a/media/libaudioclient/include/media/AudioRecord.h b/media/libaudioclient/include/media/AudioRecord.h
index b4ddb69..9c81bb7 100644
--- a/media/libaudioclient/include/media/AudioRecord.h
+++ b/media/libaudioclient/include/media/AudioRecord.h
@@ -542,11 +542,11 @@
/* Set the Microphone direction (for processing purposes).
*/
- status_t setMicrophoneDirection(audio_microphone_direction_t direction);
+ status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction);
/* Set the Microphone zoom factor (for processing purposes).
*/
- status_t setMicrophoneFieldDimension(float zoom);
+ status_t setPreferredMicrophoneFieldDimension(float zoom);
/* Get the unique port ID assigned to this AudioRecord instance by audio policy manager.
* The ID is unique across all audioserver clients and can change during the life cycle
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index e64f285..05a1d56 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -299,6 +299,8 @@
static status_t setLowRamDevice(bool isLowRamDevice, int64_t totalMemory);
+ static status_t setAllowedCapturePolicy(uid_t uid, audio_flags_mask_t flags);
+
// Check if hw offload is possible for given format, stream type, sample rate,
// bit rate, duration, video and streaming or offload property is enabled
static bool isOffloadSupported(const audio_offload_info_t& info);
diff --git a/media/libaudioclient/include/media/IAudioPolicyService.h b/media/libaudioclient/include/media/IAudioPolicyService.h
index 35540f0..95530ac 100644
--- a/media/libaudioclient/include/media/IAudioPolicyService.h
+++ b/media/libaudioclient/include/media/IAudioPolicyService.h
@@ -135,6 +135,7 @@
audio_unique_id_t* id) = 0;
virtual status_t removeSourceDefaultEffect(audio_unique_id_t id) = 0;
virtual status_t removeStreamDefaultEffect(audio_unique_id_t id) = 0;
+ virtual status_t setAllowedCapturePolicy(uid_t uid, audio_flags_mask_t flags) = 0;
// Check if offload is possible for given format, stream type, sample rate,
// bit rate, duration, video and streaming or offload property is enabled
virtual bool isOffloadSupported(const audio_offload_info_t& info) = 0;
diff --git a/media/libaudiohal/impl/StreamHalHidl.cpp b/media/libaudiohal/impl/StreamHalHidl.cpp
index e396cf3..6c8e6a4 100644
--- a/media/libaudiohal/impl/StreamHalHidl.cpp
+++ b/media/libaudiohal/impl/StreamHalHidl.cpp
@@ -855,25 +855,26 @@
#endif
#if MAJOR_VERSION < 5
-status_t StreamInHalHidl::setMicrophoneDirection(audio_microphone_direction_t direction __unused) {
+status_t StreamInHalHidl::setPreferredMicrophoneDirection(
+ audio_microphone_direction_t direction __unused) {
if (mStream == 0) return NO_INIT;
return INVALID_OPERATION;
}
-status_t StreamInHalHidl::setMicrophoneFieldDimension(float zoom __unused) {
+status_t StreamInHalHidl::setPreferredMicrophoneFieldDimension(float zoom __unused) {
if (mStream == 0) return NO_INIT;
return INVALID_OPERATION;
}
#else
-status_t StreamInHalHidl::setMicrophoneDirection(audio_microphone_direction_t direction) {
+status_t StreamInHalHidl::setPreferredMicrophoneDirection(audio_microphone_direction_t direction) {
if (!mStream) return NO_INIT;
- return processReturn("setMicrophoneDirection",
- mStream->setMicrophoneDirection(static_cast<MicrophoneDirection>(direction)));
+ return processReturn("setPreferredMicrophoneDirection",
+ mStream->setMicrophoneDirection(static_cast<MicrophoneDirection>(direction)));
}
-status_t StreamInHalHidl::setMicrophoneFieldDimension(float zoom) {
+status_t StreamInHalHidl::setPreferredMicrophoneFieldDimension(float zoom) {
if (!mStream) return NO_INIT;
- return processReturn("setMicrophoneFieldDimension",
+ return processReturn("setPreferredMicrophoneFieldDimension",
mStream->setMicrophoneFieldDimension(zoom));
}
#endif
diff --git a/media/libaudiohal/impl/StreamHalHidl.h b/media/libaudiohal/impl/StreamHalHidl.h
index 9ac1067..f587889 100644
--- a/media/libaudiohal/impl/StreamHalHidl.h
+++ b/media/libaudiohal/impl/StreamHalHidl.h
@@ -221,10 +221,11 @@
virtual status_t getActiveMicrophones(std::vector<media::MicrophoneInfo> *microphones);
// Set microphone direction (for processing)
- virtual status_t setMicrophoneDirection(audio_microphone_direction_t direction) override;
+ virtual status_t setPreferredMicrophoneDirection(
+ audio_microphone_direction_t direction) override;
// Set microphone zoom (for processing)
- virtual status_t setMicrophoneFieldDimension(float zoom) override;
+ virtual status_t setPreferredMicrophoneFieldDimension(float zoom) override;
// Called when the metadata of the stream's sink has been changed.
status_t updateSinkMetadata(const SinkMetadata& sinkMetadata) override;
diff --git a/media/libaudiohal/impl/StreamHalLocal.cpp b/media/libaudiohal/impl/StreamHalLocal.cpp
index fcb809b..7d5ce05 100644
--- a/media/libaudiohal/impl/StreamHalLocal.cpp
+++ b/media/libaudiohal/impl/StreamHalLocal.cpp
@@ -369,20 +369,21 @@
#endif
#if MAJOR_VERSION < 5
-status_t StreamInHalLocal::setMicrophoneDirection(audio_microphone_direction_t direction __unused) {
+status_t StreamInHalLocal::setPreferredMicrophoneDirection(
+ audio_microphone_direction_t direction __unused) {
return INVALID_OPERATION;
}
-status_t StreamInHalLocal::setMicrophoneFieldDimension(float zoom __unused) {
+status_t StreamInHalLocal::setPreferredMicrophoneFieldDimension(float zoom __unused) {
return INVALID_OPERATION;
}
#else
-status_t StreamInHalLocal::setMicrophoneDirection(audio_microphone_direction_t direction) {
+status_t StreamInHalLocal::setPreferredMicrophoneDirection(audio_microphone_direction_t direction) {
if (mStream->set_microphone_direction == NULL) return INVALID_OPERATION;
return mStream->set_microphone_direction(mStream, direction);
}
-status_t StreamInHalLocal::setMicrophoneFieldDimension(float zoom) {
+status_t StreamInHalLocal::setPreferredMicrophoneFieldDimension(float zoom) {
if (mStream->set_microphone_field_dimension == NULL) return INVALID_OPERATION;
return mStream->set_microphone_field_dimension(mStream, zoom);
@@ -391,3 +392,5 @@
} // namespace CPP_VERSION
} // namespace android
+
+
diff --git a/media/libaudiohal/impl/StreamHalLocal.h b/media/libaudiohal/impl/StreamHalLocal.h
index 3d6c50e..34f2bd8 100644
--- a/media/libaudiohal/impl/StreamHalLocal.h
+++ b/media/libaudiohal/impl/StreamHalLocal.h
@@ -205,10 +205,10 @@
virtual status_t getActiveMicrophones(std::vector<media::MicrophoneInfo> *microphones);
// Sets microphone direction (for processing)
- virtual status_t setMicrophoneDirection(audio_microphone_direction_t direction);
+ virtual status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction);
// Sets microphone zoom (for processing)
- virtual status_t setMicrophoneFieldDimension(float zoom);
+ virtual status_t setPreferredMicrophoneFieldDimension(float zoom);
// Called when the metadata of the stream's sink has been changed.
status_t updateSinkMetadata(const SinkMetadata& sinkMetadata) override;
diff --git a/media/libaudiohal/include/media/audiohal/StreamHalInterface.h b/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
index ed8282f..6c3b21c 100644
--- a/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
@@ -180,10 +180,10 @@
virtual status_t getActiveMicrophones(std::vector<media::MicrophoneInfo> *microphones) = 0;
// Set direction for capture processing
- virtual status_t setMicrophoneDirection(audio_microphone_direction_t) = 0;
+ virtual status_t setPreferredMicrophoneDirection(audio_microphone_direction_t) = 0;
// Set zoom factor for capture stream
- virtual status_t setMicrophoneFieldDimension(float zoom) = 0;
+ virtual status_t setPreferredMicrophoneFieldDimension(float zoom) = 0;
struct SinkMetadata {
std::vector<record_track_metadata_t> tracks;
diff --git a/media/libeffects/lvm/lib/Android.bp b/media/libeffects/lvm/lib/Android.bp
index 7a32d3f..d150f18 100644
--- a/media/libeffects/lvm/lib/Android.bp
+++ b/media/libeffects/lvm/lib/Android.bp
@@ -132,6 +132,9 @@
shared_libs: [
"liblog",
],
+ header_libs: [
+ "libhardware_headers"
+ ],
cflags: [
"-fvisibility=hidden",
"-DBUILD_FLOAT",
diff --git a/media/libeffects/lvm/lib/Bundle/lib/LVM.h b/media/libeffects/lvm/lib/Bundle/lib/LVM.h
index 83ecae1..5082a53 100644
--- a/media/libeffects/lvm/lib/Bundle/lib/LVM.h
+++ b/media/libeffects/lvm/lib/Bundle/lib/LVM.h
@@ -298,6 +298,7 @@
LVM_PSA_DecaySpeed_en PSA_PeakDecayRate; /* Peak value decay rate*/
#ifdef SUPPORT_MC
LVM_INT32 NrChannels;
+ LVM_INT32 ChMask;
#endif
} LVM_ControlParams_t;
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Control.c b/media/libeffects/lvm/lib/Bundle/src/LVM_Control.c
index 62b4c73..1d95342 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Control.c
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Control.c
@@ -93,6 +93,7 @@
#ifdef SUPPORT_MC
pInstance->Params.NrChannels = pParams->NrChannels;
+ pInstance->Params.ChMask = pParams->ChMask;
#endif
/*
* Cinema Sound parameters
@@ -584,6 +585,7 @@
#ifdef SUPPORT_MC
pInstance->NrChannels = LocalParams.NrChannels;
+ pInstance->ChMask = LocalParams.ChMask;
#endif
/* Clear all internal data if format change*/
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h b/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h
index 19d1532..cdd3134 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h
@@ -291,6 +291,7 @@
#ifdef SUPPORT_MC
LVM_INT16 NrChannels;
+ LVM_INT32 ChMask;
#endif
} LVM_Instance_t;
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Process.c b/media/libeffects/lvm/lib/Bundle/src/LVM_Process.c
index 94ba278..8d30a61 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Process.c
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Process.c
@@ -21,6 +21,7 @@
/* Includes */
/* */
/****************************************************************************************/
+#include <system/audio.h>
#include "LVM_Private.h"
#include "VectorArithmetic.h"
@@ -67,6 +68,7 @@
LVM_ReturnStatus_en Status;
#ifdef SUPPORT_MC
LVM_INT32 NrChannels = pInstance->NrChannels;
+ LVM_INT32 ChMask = pInstance->ChMask;
#define NrFrames SampleCount // alias for clarity
#endif
@@ -119,6 +121,7 @@
#ifdef SUPPORT_MC
/* Update the local variable NrChannels from pInstance->NrChannels value */
NrChannels = pInstance->NrChannels;
+ ChMask = pInstance->ChMask;
#endif
if(Status != LVM_SUCCESS)
@@ -140,6 +143,7 @@
pToProcess = pOutData;
#ifdef SUPPORT_MC
NrChannels = 2;
+ ChMask = AUDIO_CHANNEL_OUT_STEREO;
#endif
}
@@ -254,18 +258,24 @@
}
#ifdef SUPPORT_MC
- /* TODO - Multichannel support to be added */
- if (NrChannels == 2)
+ /*
+ * Volume balance
+ */
+ LVC_MixSoft_1St_MC_float_SAT(&pInstance->VC_BalanceMix,
+ pProcessed,
+ pProcessed,
+ NrFrames,
+ NrChannels,
+ ChMask);
+#else
+ /*
+ * Volume balance
+ */
+ LVC_MixSoft_1St_2i_D16C31_SAT(&pInstance->VC_BalanceMix,
+ pProcessed,
+ pProcessed,
+ SampleCount);
#endif
- {
- /*
- * Volume balance
- */
- LVC_MixSoft_1St_2i_D16C31_SAT(&pInstance->VC_BalanceMix,
- pProcessed,
- pProcessed,
- SampleCount);
- }
/*
* Perform Parametric Spectum Analysis
diff --git a/media/libeffects/lvm/lib/Common/lib/LVM_Types.h b/media/libeffects/lvm/lib/Common/lib/LVM_Types.h
index 59586e0..fbfdd4d 100644
--- a/media/libeffects/lvm/lib/Common/lib/LVM_Types.h
+++ b/media/libeffects/lvm/lib/Common/lib/LVM_Types.h
@@ -94,6 +94,7 @@
typedef int32_t LVM_INT32; /* Signed 32-bit word */
typedef uint32_t LVM_UINT32; /* Unsigned 32-bit word */
+typedef int64_t LVM_INT64; /* Signed 64-bit word */
#ifdef BUILD_FLOAT
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_1St_2i_D16C31_SAT.c b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_1St_2i_D16C31_SAT.c
index eb5755e..db76cd1 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_1St_2i_D16C31_SAT.c
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_1St_2i_D16C31_SAT.c
@@ -59,6 +59,31 @@
}
+#ifdef SUPPORT_MC
+void LVC_Core_MixHard_1St_MC_float_SAT (Mix_Private_FLOAT_st **ptrInstance,
+ const LVM_FLOAT *src,
+ LVM_FLOAT *dst,
+ LVM_INT16 NrFrames,
+ LVM_INT16 NrChannels)
+{
+ LVM_FLOAT Temp;
+ LVM_INT16 ii, jj;
+ for (ii = NrFrames; ii != 0; ii--)
+ {
+ for (jj = 0; jj < NrChannels; jj++)
+ {
+ Mix_Private_FLOAT_st *pInstance1 = (Mix_Private_FLOAT_st *)(ptrInstance[jj]);
+ Temp = ((LVM_FLOAT)*(src++) * (LVM_FLOAT)pInstance1->Current);
+ if (Temp > 1.0f)
+ *dst++ = 1.0f;
+ else if (Temp < -1.0f)
+ *dst++ = -1.0f;
+ else
+ *dst++ = (LVM_FLOAT)Temp;
+ }
+ }
+}
+#endif
#else
void LVC_Core_MixHard_1St_2i_D16C31_SAT( LVMixer3_st *ptrInstance1,
LVMixer3_st *ptrInstance2,
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_2i_D16C31_WRA.c b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_2i_D16C31_WRA.c
index 656a117..56b5dae 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_2i_D16C31_WRA.c
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_2i_D16C31_WRA.c
@@ -146,6 +146,51 @@
pInstanceR->Current = CurrentR;
}
+#ifdef SUPPORT_MC
+void LVC_Core_MixSoft_1St_MC_float_WRA (Mix_Private_FLOAT_st **ptrInstance,
+ const LVM_FLOAT *src,
+ LVM_FLOAT *dst,
+ LVM_INT16 NrFrames,
+ LVM_INT16 NrChannels)
+{
+ LVM_INT32 ii, ch;
+ LVM_FLOAT Temp =0.0f;
+ LVM_FLOAT tempCurrent[NrChannels];
+ for (ch = 0; ch < NrChannels; ch++)
+ {
+ tempCurrent[ch] = ptrInstance[ch]->Current;
+ }
+ for (ii = NrFrames; ii > 0; ii--)
+ {
+ for (ch = 0; ch < NrChannels; ch++)
+ {
+ Mix_Private_FLOAT_st *pInstance = ptrInstance[ch];
+ const LVM_FLOAT Delta = pInstance->Delta;
+ LVM_FLOAT Current = tempCurrent[ch];
+ const LVM_FLOAT Target = pInstance->Target;
+ if (Current < Target)
+ {
+ ADD2_SAT_FLOAT(Current, Delta, Temp);
+ Current = Temp;
+ if (Current > Target)
+ Current = Target;
+ }
+ else
+ {
+ Current -= Delta;
+ if (Current < Target)
+ Current = Target;
+ }
+ *dst++ = *src++ * Current;
+ tempCurrent[ch] = Current;
+ }
+ }
+ for (ch = 0; ch < NrChannels; ch++)
+ {
+ ptrInstance[ch]->Current = tempCurrent[ch];
+ }
+}
+#endif
#else
void LVC_Core_MixSoft_1St_2i_D16C31_WRA( LVMixer3_st *ptrInstance1,
LVMixer3_st *ptrInstance2,
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.c b/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.c
index bd5a925..a4682d3 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.c
+++ b/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.c
@@ -19,6 +19,8 @@
INCLUDE FILES
***********************************************************************************/
+#include <system/audio.h>
+
#include "LVC_Mixer_Private.h"
#include "VectorArithmetic.h"
#include "ScalarArithmetic.h"
@@ -30,10 +32,207 @@
#define TRUE 1
#define FALSE 0
+#define ARRAY_SIZE(a) ((sizeof(a)) / (sizeof(*(a))))
+
/**********************************************************************************
FUNCTION LVC_MixSoft_1St_2i_D16C31_SAT
***********************************************************************************/
#ifdef BUILD_FLOAT
+#ifdef SUPPORT_MC
+/* This threshold is used to decide on the processing to be applied on
+ * front center and back center channels
+ */
+#define LVM_VOL_BAL_THR (0.000016f)
+void LVC_MixSoft_1St_MC_float_SAT (LVMixer3_2St_FLOAT_st *ptrInstance,
+ const LVM_FLOAT *src,
+ LVM_FLOAT *dst,
+ LVM_INT16 NrFrames,
+ LVM_INT32 NrChannels,
+ LVM_INT32 ChMask)
+{
+ char HardMixing = TRUE;
+ LVM_FLOAT TargetGain;
+ Mix_Private_FLOAT_st Target_lfe = {LVM_MAXFLOAT, LVM_MAXFLOAT, LVM_MAXFLOAT};
+ Mix_Private_FLOAT_st Target_ctr = {LVM_MAXFLOAT, LVM_MAXFLOAT, LVM_MAXFLOAT};
+ Mix_Private_FLOAT_st *pInstance1 = \
+ (Mix_Private_FLOAT_st *)(ptrInstance->MixerStream[0].PrivateParams);
+ Mix_Private_FLOAT_st *pInstance2 = \
+ (Mix_Private_FLOAT_st *)(ptrInstance->MixerStream[1].PrivateParams);
+ Mix_Private_FLOAT_st *pMixPrivInst[4] = {pInstance1, pInstance2, &Target_ctr, &Target_lfe};
+ Mix_Private_FLOAT_st *pInstance[NrChannels];
+
+ if (audio_channel_mask_get_representation(ChMask)
+ == AUDIO_CHANNEL_REPRESENTATION_INDEX)
+ {
+ for (int i = 0; i < 2; i++)
+ {
+ pInstance[i] = pMixPrivInst[i];
+ }
+ for (int i = 2; i < NrChannels; i++)
+ {
+ pInstance[i] = pMixPrivInst[2];
+ }
+ }
+ else
+ {
+ // TODO: Combine with system/media/audio_utils/Balance.cpp
+ // Constants in system/media/audio/include/system/audio-base.h
+ // 'mixInstIdx' is used to map the appropriate mixer instance for each channel.
+ const int mixInstIdx[] = {
+ 0, // AUDIO_CHANNEL_OUT_FRONT_LEFT = 0x1u,
+ 1, // AUDIO_CHANNEL_OUT_FRONT_RIGHT = 0x2u,
+ 2, // AUDIO_CHANNEL_OUT_FRONT_CENTER = 0x4u,
+ 3, // AUDIO_CHANNEL_OUT_LOW_FREQUENCY = 0x8u,
+ 0, // AUDIO_CHANNEL_OUT_BACK_LEFT = 0x10u,
+ 1, // AUDIO_CHANNEL_OUT_BACK_RIGHT = 0x20u,
+ 0, // AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER = 0x40u,
+ 1, // AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER = 0x80u,
+ 2, // AUDIO_CHANNEL_OUT_BACK_CENTER = 0x100u,
+ 0, // AUDIO_CHANNEL_OUT_SIDE_LEFT = 0x200u,
+ 1, // AUDIO_CHANNEL_OUT_SIDE_RIGHT = 0x400u,
+ 2, // AUDIO_CHANNEL_OUT_TOP_CENTER = 0x800u,
+ 0, // AUDIO_CHANNEL_OUT_TOP_FRONT_LEFT = 0x1000u,
+ 2, // AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER = 0x2000u,
+ 1, // AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT = 0x4000u,
+ 0, // AUDIO_CHANNEL_OUT_TOP_BACK_LEFT = 0x8000u,
+ 2, // AUDIO_CHANNEL_OUT_TOP_BACK_CENTER = 0x10000u,
+ 1, // AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT = 0x20000u,
+ 0, // AUDIO_CHANNEL_OUT_TOP_SIDE_LEFT = 0x40000u,
+ 1, // AUDIO_CHANNEL_OUT_TOP_SIDE_RIGHT = 0x80000u
+ };
+ if (pInstance1->Target <= LVM_VOL_BAL_THR ||
+ pInstance2->Target <= LVM_VOL_BAL_THR)
+ {
+ Target_ctr.Target = 0.0f;
+ Target_ctr.Current = 0.0f;
+ Target_ctr.Delta = 0.0f;
+ }
+ const unsigned int idxArrSize = ARRAY_SIZE(mixInstIdx);
+ for (unsigned int i = 0, channel = ChMask; channel !=0 ; ++i)
+ {
+ const unsigned int idx = __builtin_ctz(channel);
+ if (idx < idxArrSize)
+ {
+ pInstance[i] = pMixPrivInst[mixInstIdx[idx]];
+ }
+ else
+ {
+ pInstance[i] = pMixPrivInst[2];
+ }
+ channel &= ~(1 << idx);
+ }
+ }
+
+ if (NrFrames <= 0) return;
+
+ /******************************************************************************
+ SOFT MIXING
+ *******************************************************************************/
+
+ if ((pInstance1->Current != pInstance1->Target) ||
+ (pInstance2->Current != pInstance2->Target))
+ {
+ // TODO: combine similar checks below.
+ if (pInstance1->Delta == LVM_MAXFLOAT
+ || Abs_Float(pInstance1->Current - pInstance1->Target) < pInstance1->Delta)
+ {
+ /* Difference is not significant anymore. Make them equal. */
+ pInstance1->Current = pInstance1->Target;
+ TargetGain = pInstance1->Target;
+ LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]), TargetGain);
+ }
+ else
+ {
+ /* Soft mixing has to be applied */
+ HardMixing = FALSE;
+ }
+
+ if (HardMixing == TRUE)
+ {
+ if (pInstance2->Delta == LVM_MAXFLOAT
+ || Abs_Float(pInstance2->Current - pInstance2->Target) < pInstance2->Delta)
+ {
+ /* Difference is not significant anymore. Make them equal. */
+ pInstance2->Current = pInstance2->Target;
+ TargetGain = pInstance2->Target;
+ LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[1]), TargetGain);
+ }
+ else
+ {
+ /* Soft mixing has to be applied */
+ HardMixing = FALSE;
+ }
+ }
+
+ if (HardMixing == FALSE)
+ {
+ LVC_Core_MixSoft_1St_MC_float_WRA (&pInstance[0],
+ src, dst, NrFrames, NrChannels);
+ }
+ }
+
+ /******************************************************************************
+ HARD MIXING
+ *******************************************************************************/
+
+ if (HardMixing == TRUE)
+ {
+ if ((pInstance1->Target == LVM_MAXFLOAT) && (pInstance2->Target == LVM_MAXFLOAT))
+ {
+ if (src != dst)
+ {
+ Copy_Float(src, dst, NrFrames*NrChannels);
+ }
+ }
+ else
+ {
+ LVC_Core_MixHard_1St_MC_float_SAT(&(pInstance[0]),
+ src, dst, NrFrames, NrChannels);
+ }
+ }
+
+ /******************************************************************************
+ CALL BACK
+ *******************************************************************************/
+
+ if (ptrInstance->MixerStream[0].CallbackSet)
+ {
+ if (Abs_Float(pInstance1->Current - pInstance1->Target) < pInstance1->Delta)
+ {
+ pInstance1->Current = pInstance1->Target; /* Difference is not significant anymore. \
+ Make them equal. */
+ TargetGain = pInstance1->Target;
+ LVC_Mixer_SetTarget(&ptrInstance->MixerStream[0], TargetGain);
+ ptrInstance->MixerStream[0].CallbackSet = FALSE;
+ if (ptrInstance->MixerStream[0].pCallBack != 0)
+ {
+ (*ptrInstance->MixerStream[0].pCallBack) (\
+ ptrInstance->MixerStream[0].pCallbackHandle,
+ ptrInstance->MixerStream[0].pGeneralPurpose,
+ ptrInstance->MixerStream[0].CallbackParam);
+ }
+ }
+ }
+ if (ptrInstance->MixerStream[1].CallbackSet)
+ {
+ if (Abs_Float(pInstance2->Current - pInstance2->Target) < pInstance2->Delta)
+ {
+ pInstance2->Current = pInstance2->Target; /* Difference is not significant anymore.
+ Make them equal. */
+ TargetGain = pInstance2->Target;
+ LVC_Mixer_SetTarget(&ptrInstance->MixerStream[1], TargetGain);
+ ptrInstance->MixerStream[1].CallbackSet = FALSE;
+ if (ptrInstance->MixerStream[1].pCallBack != 0)
+ {
+ (*ptrInstance->MixerStream[1].pCallBack) (\
+ ptrInstance->MixerStream[1].pCallbackHandle,
+ ptrInstance->MixerStream[1].pGeneralPurpose,
+ ptrInstance->MixerStream[1].CallbackParam);
+ }
+ }
+ }
+}
+#endif
void LVC_MixSoft_1St_2i_D16C31_SAT( LVMixer3_2St_FLOAT_st *ptrInstance,
const LVM_FLOAT *src,
LVM_FLOAT *dst,
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer.h b/media/libeffects/lvm/lib/Common/src/LVC_Mixer.h
index 7f18747..199d529 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Mixer.h
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer.h
@@ -224,6 +224,14 @@
/* Gain values should not be more that 1.0 */
/**********************************************************************************/
#ifdef BUILD_FLOAT
+#ifdef SUPPORT_MC
+void LVC_MixSoft_1St_MC_float_SAT(LVMixer3_2St_FLOAT_st *pInstance,
+ const LVM_FLOAT *src,
+ LVM_FLOAT *dst, /* dst can be equal to src */
+ LVM_INT16 NrFrames,
+ LVM_INT32 NrChannels,
+ LVM_INT32 ChMask);
+#endif
void LVC_MixSoft_1St_2i_D16C31_SAT(LVMixer3_2St_FLOAT_st *pInstance,
const LVM_FLOAT *src,
LVM_FLOAT *dst, /* dst can be equal to src */
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Private.h b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Private.h
index f10094b..453a6a5 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Private.h
@@ -116,6 +116,13 @@
/* Gain values should not be more that 1.0 */
/**********************************************************************************/
#ifdef BUILD_FLOAT
+#ifdef SUPPORT_MC
+void LVC_Core_MixSoft_1St_MC_float_WRA(Mix_Private_FLOAT_st **ptrInstance,
+ const LVM_FLOAT *src,
+ LVM_FLOAT *dst,
+ LVM_INT16 NrFrames,
+ LVM_INT16 NrChannels);
+#endif
void LVC_Core_MixSoft_1St_2i_D16C31_WRA( LVMixer3_FLOAT_st *ptrInstance1,
LVMixer3_FLOAT_st *ptrInstance2,
const LVM_FLOAT *src,
@@ -136,6 +143,13 @@
/* Gain values should not be more that 1.0 */
/**********************************************************************************/
#ifdef BUILD_FLOAT
+#ifdef SUPPORT_MC
+void LVC_Core_MixHard_1St_MC_float_SAT(Mix_Private_FLOAT_st **ptrInstance,
+ const LVM_FLOAT *src,
+ LVM_FLOAT *dst,
+ LVM_INT16 NrFrames,
+ LVM_INT16 NrChannels);
+#endif
void LVC_Core_MixHard_1St_2i_D16C31_SAT( LVMixer3_FLOAT_st *ptrInstance1,
LVMixer3_FLOAT_st *ptrInstance2,
const LVM_FLOAT *src,
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.c b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.c
index ea5f74a..61899fe 100644
--- a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.c
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.c
@@ -22,6 +22,17 @@
#define LVM_MININT_32 0x80000000
+static LVM_INT32 mult32x32in32_shiftr(LVM_INT32 a, LVM_INT32 b, LVM_INT32 c) {
+ LVM_INT64 result = ((LVM_INT64)a * b) >> c;
+
+ if (result >= INT32_MAX) {
+ return INT32_MAX;
+ } else if (result <= INT32_MIN) {
+ return INT32_MIN;
+ } else {
+ return (LVM_INT32)result;
+ }
+}
/************************************************************************************/
/* */
@@ -123,10 +134,10 @@
if(pLVPSA_Inst->pSpectralDataBufferWritePointer != pWrite_Save)
{
- MUL32x32INTO32((AudioTime + (LVM_INT32)((LVM_INT32)pLVPSA_Inst->LocalSamplesCount*1000)),
- (LVM_INT32)LVPSA_SampleRateInvTab[pLVPSA_Inst->CurrentParams.Fs],
- AudioTimeInc,
- LVPSA_FsInvertShift)
+ AudioTimeInc = mult32x32in32_shiftr(
+ (AudioTime + ((LVM_INT32)pLVPSA_Inst->LocalSamplesCount * 1000)),
+ (LVM_INT32)LVPSA_SampleRateInvTab[pLVPSA_Inst->CurrentParams.Fs],
+ LVPSA_FsInvertShift);
pLVPSA_Inst->SpectralDataBufferAudioTime = AudioTime + AudioTimeInc;
}
diff --git a/media/libeffects/lvm/tests/build_and_run_all_unit_tests.sh b/media/libeffects/lvm/tests/build_and_run_all_unit_tests.sh
index 1a874a3..5079634 100755
--- a/media/libeffects/lvm/tests/build_and_run_all_unit_tests.sh
+++ b/media/libeffects/lvm/tests/build_and_run_all_unit_tests.sh
@@ -36,6 +36,10 @@
"-csE -tE"
"-csE -eqE" "-tE -eqE"
"-csE -tE -bE -M -eqE"
+ "-tE -eqE -vcBal:96 -M"
+ "-tE -eqE -vcBal:-96 -M"
+ "-tE -eqE -vcBal:0 -M"
+ "-tE -eqE -bE -vcBal:30 -M"
)
fs_arr=(
@@ -56,26 +60,41 @@
# run multichannel effects at different configs, saving only the stereo channel
# pair.
+error_count=0
for flags in "${flags_arr[@]}"
do
for fs in ${fs_arr[*]}
do
- for ch in {1..8}
+ for chMask in {0..22}
do
adb shell $testdir/lvmtest -i:$testdir/sinesweepraw.raw \
- -o:$testdir/sinesweep_$((ch))_$((fs)).raw -ch:$ch -fs:$fs $flags
+ -o:$testdir/sinesweep_$((chMask))_$((fs)).raw -chMask:$chMask -fs:$fs $flags
+
+ shell_ret=$?
+ if [ $shell_ret -ne 0 ]; then
+ echo "error: $shell_ret"
+ ((++error_count))
+ fi
+
# two channel files should be identical to higher channel
# computation (first 2 channels).
# Do not compare cases where -bE is in flags (due to mono computation)
- if [[ $flags != *"-bE"* ]] && [ "$ch" -gt 2 ]
+ if [[ $flags != *"-bE"* ]] && [[ "$chMask" -gt 1 ]]
then
- adb shell cmp $testdir/sinesweep_2_$((fs)).raw \
- $testdir/sinesweep_$((ch))_$((fs)).raw
- elif [[ $flags == *"-bE"* ]] && [ "$ch" -gt 2 ]
+ adb shell cmp $testdir/sinesweep_1_$((fs)).raw \
+ $testdir/sinesweep_$((chMask))_$((fs)).raw
+ elif [[ $flags == *"-bE"* ]] && [[ "$chMask" -gt 1 ]]
then
- adb shell $testdir/snr $testdir/sinesweep_2_$((fs)).raw \
- $testdir/sinesweep_$((ch))_$((fs)).raw -thr:90.308998
+ adb shell $testdir/snr $testdir/sinesweep_1_$((fs)).raw \
+ $testdir/sinesweep_$((chMask))_$((fs)).raw -thr:90.308998
+ fi
+
+ # both cmp and snr return EXIT_FAILURE on mismatch.
+ shell_ret=$?
+ if [ $shell_ret -ne 0 ]; then
+ echo "error: $shell_ret"
+ ((++error_count))
fi
done
@@ -83,3 +102,5 @@
done
adb shell rm -r $testdir
+echo "$error_count errors"
+exit $error_count
diff --git a/media/libeffects/lvm/tests/lvmtest.cpp b/media/libeffects/lvm/tests/lvmtest.cpp
index 416bdaa..5b58dd1 100644
--- a/media/libeffects/lvm/tests/lvmtest.cpp
+++ b/media/libeffects/lvm/tests/lvmtest.cpp
@@ -24,6 +24,7 @@
#include <audio_utils/channels.h>
#include <audio_utils/primitives.h>
#include <log/log.h>
+#include <system/audio.h>
#include "EffectBundle.h"
#include "LVM_Private.h"
@@ -76,6 +77,8 @@
struct lvmConfigParams_t {
int samplingFreq = 44100;
int nrChannels = 2;
+ int chMask = AUDIO_CHANNEL_OUT_STEREO;
+ int vcBal = 0;
int fChannels = 2;
bool monoMode = false;
int bassEffectLevel = 0;
@@ -87,9 +90,36 @@
LVM_Mode_en csEnable = LVM_MODE_OFF;
};
+constexpr audio_channel_mask_t lvmConfigChMask[] = {
+ AUDIO_CHANNEL_OUT_MONO,
+ AUDIO_CHANNEL_OUT_STEREO,
+ AUDIO_CHANNEL_OUT_2POINT1,
+ AUDIO_CHANNEL_OUT_2POINT0POINT2,
+ AUDIO_CHANNEL_OUT_QUAD,
+ AUDIO_CHANNEL_OUT_QUAD_BACK,
+ AUDIO_CHANNEL_OUT_QUAD_SIDE,
+ AUDIO_CHANNEL_OUT_SURROUND,
+ (1 << 4) - 1,
+ AUDIO_CHANNEL_OUT_2POINT1POINT2,
+ AUDIO_CHANNEL_OUT_3POINT0POINT2,
+ AUDIO_CHANNEL_OUT_PENTA,
+ (1 << 5) - 1,
+ AUDIO_CHANNEL_OUT_3POINT1POINT2,
+ AUDIO_CHANNEL_OUT_5POINT1,
+ AUDIO_CHANNEL_OUT_5POINT1_BACK,
+ AUDIO_CHANNEL_OUT_5POINT1_SIDE,
+ (1 << 6) - 1,
+ AUDIO_CHANNEL_OUT_6POINT1,
+ (1 << 7) - 1,
+ AUDIO_CHANNEL_OUT_5POINT1POINT2,
+ AUDIO_CHANNEL_OUT_7POINT1,
+ (1 << 8) - 1,
+};
+
+
void printUsage() {
printf("\nUsage: ");
- printf("\n <exceutable> -i:<input_file> -o:<out_file> [options]\n");
+ printf("\n <executable> -i:<input_file> -o:<out_file> [options]\n");
printf("\nwhere, \n <inputfile> is the input file name");
printf("\n on which LVM effects are applied");
printf("\n <outputfile> processed output file");
@@ -98,7 +128,34 @@
printf("\n -help (or) -h");
printf("\n Prints this usage information");
printf("\n");
- printf("\n -ch:<process_channels> (1 through 8)\n\n");
+ printf("\n -chMask:<channel_mask>\n");
+ printf("\n 0 - AUDIO_CHANNEL_OUT_MONO");
+ printf("\n 1 - AUDIO_CHANNEL_OUT_STEREO");
+ printf("\n 2 - AUDIO_CHANNEL_OUT_2POINT1");
+ printf("\n 3 - AUDIO_CHANNEL_OUT_2POINT0POINT2");
+ printf("\n 4 - AUDIO_CHANNEL_OUT_QUAD");
+ printf("\n 5 - AUDIO_CHANNEL_OUT_QUAD_BACK");
+ printf("\n 6 - AUDIO_CHANNEL_OUT_QUAD_SIDE");
+ printf("\n 7 - AUDIO_CHANNEL_OUT_SURROUND");
+ printf("\n 8 - canonical channel index mask for 4 ch: (1 << 4) - 1");
+ printf("\n 9 - AUDIO_CHANNEL_OUT_2POINT1POINT2");
+ printf("\n 10 - AUDIO_CHANNEL_OUT_3POINT0POINT2");
+ printf("\n 11 - AUDIO_CHANNEL_OUT_PENTA");
+ printf("\n 12 - canonical channel index mask for 5 ch: (1 << 5) - 1");
+ printf("\n 13 - AUDIO_CHANNEL_OUT_3POINT1POINT2");
+ printf("\n 14 - AUDIO_CHANNEL_OUT_5POINT1");
+ printf("\n 15 - AUDIO_CHANNEL_OUT_5POINT1_BACK");
+ printf("\n 16 - AUDIO_CHANNEL_OUT_5POINT1_SIDE");
+ printf("\n 17 - canonical channel index mask for 6 ch: (1 << 6) - 1");
+ printf("\n 18 - AUDIO_CHANNEL_OUT_6POINT1");
+ printf("\n 19 - canonical channel index mask for 7 ch: (1 << 7) - 1");
+ printf("\n 20 - AUDIO_CHANNEL_OUT_5POINT1POINT2");
+ printf("\n 21 - AUDIO_CHANNEL_OUT_7POINT1");
+ printf("\n 22 - canonical channel index mask for 8 ch: (1 << 8) - 1");
+ printf("\n default 0");
+ printf("\n -vcBal:<Left Right Balance control in dB [-96 to 96 dB]>");
+ printf("\n -ve values reduce Right channel while +ve value reduces Left channel");
+ printf("\n default 0");
printf("\n -fch:<file_channels> (1 through 8)\n\n");
printf("\n -M");
printf("\n Mono mode (force all input audio channels to be identical)");
@@ -298,6 +355,7 @@
params->OperatingMode = LVM_MODE_ON;
params->SampleRate = LVM_FS_44100;
params->SourceFormat = LVM_STEREO;
+ params->ChMask = AUDIO_CHANNEL_OUT_STEREO;
params->SpeakerType = LVM_HEADPHONES;
pContext->pBundledContext->SampleRate = LVM_FS_44100;
@@ -452,13 +510,13 @@
params->OperatingMode = LVM_MODE_ON;
params->SpeakerType = LVM_HEADPHONES;
- const int nrChannels = plvmConfigParams->nrChannels;
- params->NrChannels = nrChannels;
- if (nrChannels == 1) {
+ params->ChMask = plvmConfigParams->chMask;
+ params->NrChannels = plvmConfigParams->nrChannels;
+ if (params->NrChannels == 1) {
params->SourceFormat = LVM_MONO;
- } else if (nrChannels == 2) {
+ } else if (params->NrChannels == 2) {
params->SourceFormat = LVM_STEREO;
- } else if (nrChannels > 2 && nrChannels <= 8) { // FCC_2 FCC_8
+ } else if (params->NrChannels > 2 && params->NrChannels <= 8) { // FCC_2 FCC_8
params->SourceFormat = LVM_MULTICHANNEL;
} else {
return -EINVAL;
@@ -531,7 +589,7 @@
/* Volume Control parameters */
params->VC_EffectLevel = 0;
- params->VC_Balance = 0;
+ params->VC_Balance = plvmConfigParams->vcBal;
/* Treble Enhancement parameters */
params->TE_OperatingMode = plvmConfigParams->trebleEnable;
@@ -667,13 +725,21 @@
return -1;
}
lvmConfigParams.samplingFreq = samplingFreq;
- } else if (!strncmp(argv[i], "-ch:", 4)) {
- const int nrChannels = atoi(argv[i] + 4);
- if (nrChannels > 8 || nrChannels < 1) {
- printf("Error: Unsupported number of channels : %d\n", nrChannels);
+ } else if (!strncmp(argv[i], "-chMask:", 8)) {
+ const int chMaskConfigIdx = atoi(argv[i] + 8);
+ if (chMaskConfigIdx < 0 || (size_t)chMaskConfigIdx >= std::size(lvmConfigChMask)) {
+ ALOGE("\nError: Unsupported Channel Mask : %d\n", chMaskConfigIdx);
return -1;
}
- lvmConfigParams.nrChannels = nrChannels;
+ const audio_channel_mask_t chMask = lvmConfigChMask[chMaskConfigIdx];
+ lvmConfigParams.chMask = chMask;
+ lvmConfigParams.nrChannels = audio_channel_count_from_out_mask(chMask);
+ } else if (!strncmp(argv[i], "-vcBal:", 7)) {
+ const int vcBalance = atoi(argv[i] + 7);
+ if (vcBalance > 96 || vcBalance < -96) {
+ ALOGE("\nError: Unsupported volume balance value: %d\n", vcBalance);
+ }
+ lvmConfigParams.vcBal = vcBalance;
} else if (!strncmp(argv[i], "-fch:", 5)) {
const int fChannels = atoi(argv[i] + 5);
if (fChannels > 8 || fChannels < 1) {
diff --git a/media/libeffects/lvm/tests/snr.cpp b/media/libeffects/lvm/tests/snr.cpp
index 88110c0..885994c 100644
--- a/media/libeffects/lvm/tests/snr.cpp
+++ b/media/libeffects/lvm/tests/snr.cpp
@@ -84,6 +84,7 @@
printf("\nError: missing input/reference files\n");
return -1;
}
+ int ret = EXIT_SUCCESS;
auto sn = pcm_format == 0
? getSignalNoise<short>(finp, fref)
: getSignalNoise<float>(finp, fref);
@@ -92,6 +93,7 @@
// compare the measured snr value with threshold
if (snr < thr) {
printf("%.6f less than threshold %.6f\n", snr, thr);
+ ret = EXIT_FAILURE;
} else {
printf("%.6f\n", snr);
}
@@ -99,5 +101,5 @@
fclose(finp);
fclose(fref);
- return 0;
+ return ret;
}
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index 0c6f8de..3a97905 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -1315,6 +1315,7 @@
#ifdef SUPPORT_MC
ActiveParams.NrChannels = NrChannels;
+ ActiveParams.ChMask = pConfig->inputCfg.channels;
#endif
LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index 9799cad..a529628 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -1,3 +1,10 @@
+cc_defaults {
+ name: "libmedia_defaults",
+ include_dirs: [
+ "bionic/libc/private",
+ ],
+}
+
cc_library_headers {
name: "libmedia_headers",
vendor_available: true,
@@ -86,6 +93,7 @@
export_shared_lib_headers: [
"android.hidl.token@1.0-utils",
"android.hardware.media.omx@1.0",
+ "libgui",
"libstagefright_foundation",
"libui",
],
@@ -148,6 +156,8 @@
cc_library {
name: "libmedia",
+ defaults: [ "libmedia_defaults" ],
+
srcs: [
"IDataSource.cpp",
"BufferingSettings.cpp",
@@ -258,6 +268,8 @@
cc_library_static {
name: "libmedia_player2_util",
+ defaults: [ "libmedia_defaults" ],
+
srcs: [
"AudioParameter.cpp",
"BufferingSettings.cpp",
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index f283569..a354ce1 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -66,8 +66,8 @@
ENABLE_AUDIO_DEVICE_CALLBACK,
GET_ACTIVE_MICROPHONES,
GET_PORT_ID,
- SET_MICROPHONE_DIRECTION,
- SET_MICROPHONE_FIELD_DIMENSION
+ SET_PREFERRED_MICROPHONE_DIRECTION,
+ SET_PREFERRED_MICROPHONE_FIELD_DIMENSION
};
class BpMediaRecorder: public BpInterface<IMediaRecorder>
@@ -409,21 +409,21 @@
return status;
}
- status_t setMicrophoneDirection(audio_microphone_direction_t direction) {
- ALOGV("setMicrophoneDirection(%d)", direction);
+ status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction) {
+ ALOGV("setPreferredMicrophoneDirection(%d)", direction);
Parcel data, reply;
data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
data.writeInt32(direction);
- status_t status = remote()->transact(SET_MICROPHONE_DIRECTION, data, &reply);
+ status_t status = remote()->transact(SET_PREFERRED_MICROPHONE_DIRECTION, data, &reply);
return status == NO_ERROR ? (status_t)reply.readInt32() : status;
}
- status_t setMicrophoneFieldDimension(float zoom) {
- ALOGV("setMicrophoneFieldDimension(%f)", zoom);
+ status_t setPreferredMicrophoneFieldDimension(float zoom) {
+ ALOGV("setPreferredMicrophoneFieldDimension(%f)", zoom);
Parcel data, reply;
data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
data.writeFloat(zoom);
- status_t status = remote()->transact(SET_MICROPHONE_FIELD_DIMENSION, data, &reply);
+ status_t status = remote()->transact(SET_PREFERRED_MICROPHONE_FIELD_DIMENSION, data, &reply);
return status == NO_ERROR ? (status_t)reply.readInt32() : status;
}
@@ -709,20 +709,20 @@
}
return NO_ERROR;
}
- case SET_MICROPHONE_DIRECTION: {
- ALOGV("SET_MICROPHONE_DIRECTION");
+ case SET_PREFERRED_MICROPHONE_DIRECTION: {
+ ALOGV("SET_PREFERRED_MICROPHONE_DIRECTION");
CHECK_INTERFACE(IMediaRecorder, data, reply);
int direction = data.readInt32();
- status_t status =
- setMicrophoneDirection(static_cast<audio_microphone_direction_t>(direction));
+ status_t status = setPreferredMicrophoneDirection(
+ static_cast<audio_microphone_direction_t>(direction));
reply->writeInt32(status);
return NO_ERROR;
}
- case SET_MICROPHONE_FIELD_DIMENSION: {
+ case SET_PREFERRED_MICROPHONE_FIELD_DIMENSION: {
ALOGV("SET_MICROPHONE_FIELD_DIMENSION");
CHECK_INTERFACE(IMediaRecorder, data, reply);
float zoom = data.readFloat();
- status_t status = setMicrophoneFieldDimension(zoom);
+ status_t status = setPreferredMicrophoneFieldDimension(zoom);
reply->writeInt32(status);
return NO_ERROR;
}
diff --git a/media/libmedia/MediaUtils.cpp b/media/libmedia/MediaUtils.cpp
index bcc7ebf..31972fa 100644
--- a/media/libmedia/MediaUtils.cpp
+++ b/media/libmedia/MediaUtils.cpp
@@ -22,23 +22,16 @@
#include <sys/resource.h>
#include <unistd.h>
+#include <bionic_malloc.h>
+
#include "MediaUtils.h"
-extern "C" size_t __cfi_shadow_size();
extern "C" void __scudo_set_rss_limit(size_t, int) __attribute__((weak));
namespace android {
-void limitProcessMemory(
- const char *property,
- size_t numberOfBytes,
- size_t percentageOfTotalMem) {
-
- if (running_with_asan()) {
- ALOGW("Running with (HW)ASan, skip enforcing memory limitations.");
- return;
- }
-
+void limitProcessMemory(const char *property, size_t numberOfBytes,
+ size_t percentageOfTotalMem) {
long pageSize = sysconf(_SC_PAGESIZE);
long numPages = sysconf(_SC_PHYS_PAGES);
size_t maxMem = SIZE_MAX;
@@ -66,38 +59,17 @@
maxMem = propVal;
}
- // If 64-bit Scudo is in use, enforce the hard RSS limit (in MB).
- if (maxMem != SIZE_MAX && sizeof(void *) == 8 &&
- &__scudo_set_rss_limit != 0) {
+ // If Scudo is in use, enforce the hard RSS limit (in MB).
+ if (maxMem != SIZE_MAX && &__scudo_set_rss_limit != 0) {
__scudo_set_rss_limit(maxMem >> 20, 1);
ALOGV("Scudo hard RSS limit set to %zu MB", maxMem >> 20);
return;
}
- // Increase by the size of the CFI shadow mapping. Most of the shadow is not
- // backed with physical pages, and it is possible for the result to be
- // higher than total physical memory. This is fine for RLIMIT_AS.
- size_t cfi_size = __cfi_shadow_size();
- if (cfi_size) {
- ALOGV("cfi shadow size: %zu", cfi_size);
- if (maxMem <= SIZE_MAX - cfi_size) {
- maxMem += cfi_size;
- } else {
- maxMem = SIZE_MAX;
- }
+ if (!android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &maxMem,
+ sizeof(maxMem))) {
+ ALOGW("couldn't set allocation limit");
}
- ALOGV("actual limit: %zu", maxMem);
-
- struct rlimit limit;
- getrlimit(RLIMIT_AS, &limit);
- ALOGV("original limits: %lld/%lld", (long long)limit.rlim_cur, (long long)limit.rlim_max);
- limit.rlim_cur = maxMem;
- setrlimit(RLIMIT_AS, &limit);
- limit.rlim_cur = -1;
- limit.rlim_max = -1;
- getrlimit(RLIMIT_AS, &limit);
- ALOGV("new limits: %lld/%lld", (long long)limit.rlim_cur, (long long)limit.rlim_max);
-
}
} // namespace android
diff --git a/media/libmedia/MediaUtils.h b/media/libmedia/MediaUtils.h
index 26075c4..f80dd30 100644
--- a/media/libmedia/MediaUtils.h
+++ b/media/libmedia/MediaUtils.h
@@ -19,13 +19,6 @@
namespace android {
-extern "C" void __asan_init(void) __attribute__((weak));
-extern "C" void __hwasan_init(void) __attribute__((weak));
-
-static inline int running_with_asan() {
- return &__asan_init != 0 || &__hwasan_init != 0;
-}
-
/**
Limit the amount of memory a process can allocate using setrlimit(RLIMIT_AS).
The value to use will be read from the specified system property, or if the
diff --git a/media/libmedia/NdkWrapper.cpp b/media/libmedia/NdkWrapper.cpp
index ea0547c..c150407 100644
--- a/media/libmedia/NdkWrapper.cpp
+++ b/media/libmedia/NdkWrapper.cpp
@@ -65,6 +65,7 @@
AMEDIAFORMAT_KEY_FLAC_COMPRESSION_LEVEL,
AMEDIAFORMAT_KEY_GRID_COLUMNS,
AMEDIAFORMAT_KEY_GRID_ROWS,
+ AMEDIAFORMAT_KEY_HAPTIC_CHANNEL_COUNT,
AMEDIAFORMAT_KEY_HEIGHT,
AMEDIAFORMAT_KEY_INTRA_REFRESH_PERIOD,
AMEDIAFORMAT_KEY_IS_ADTS,
diff --git a/media/libmedia/TypeConverter.cpp b/media/libmedia/TypeConverter.cpp
index 0301b21..5be78d1 100644
--- a/media/libmedia/TypeConverter.cpp
+++ b/media/libmedia/TypeConverter.cpp
@@ -217,6 +217,7 @@
MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_APTX_ADAPTIVE),
MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_LHDC),
MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_LHDC_LL),
+ MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_APTX_TWSP),
TERMINATOR
};
@@ -391,7 +392,8 @@
MAKE_STRING_FROM_ENUM(AUDIO_FLAG_BYPASS_MUTE),
MAKE_STRING_FROM_ENUM(AUDIO_FLAG_LOW_LATENCY),
MAKE_STRING_FROM_ENUM(AUDIO_FLAG_DEEP_BUFFER),
- MAKE_STRING_FROM_ENUM(AUDIO_FLAG_NO_CAPTURE),
+ MAKE_STRING_FROM_ENUM(AUDIO_FLAG_NO_MEDIA_PROJECTION),
+ MAKE_STRING_FROM_ENUM(AUDIO_FLAG_NO_SYSTEM_CAPTURE),
TERMINATOR
};
diff --git a/media/libmedia/include/media/IMediaRecorder.h b/media/libmedia/include/media/IMediaRecorder.h
index 0b09420..f9c557c 100644
--- a/media/libmedia/include/media/IMediaRecorder.h
+++ b/media/libmedia/include/media/IMediaRecorder.h
@@ -73,8 +73,8 @@
virtual status_t enableAudioDeviceCallback(bool enabled) = 0;
virtual status_t getActiveMicrophones(
std::vector<media::MicrophoneInfo>* activeMicrophones) = 0;
- virtual status_t setMicrophoneDirection(audio_microphone_direction_t direction) = 0;
- virtual status_t setMicrophoneFieldDimension(float zoom) = 0;
+ virtual status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction) = 0;
+ virtual status_t setPreferredMicrophoneFieldDimension(float zoom) = 0;
virtual status_t getPortId(audio_port_handle_t *portId) = 0;
};
diff --git a/media/libmedia/include/media/MediaRecorderBase.h b/media/libmedia/include/media/MediaRecorderBase.h
index 88282ac..a2dff31 100644
--- a/media/libmedia/include/media/MediaRecorderBase.h
+++ b/media/libmedia/include/media/MediaRecorderBase.h
@@ -72,8 +72,8 @@
virtual status_t enableAudioDeviceCallback(bool enabled) = 0;
virtual status_t getActiveMicrophones(
std::vector<media::MicrophoneInfo>* activeMicrophones) = 0;
- virtual status_t setMicrophoneDirection(audio_microphone_direction_t direction) = 0;
- virtual status_t setMicrophoneFieldDimension(float zoom) = 0;
+ virtual status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction) = 0;
+ virtual status_t setPreferredMicrophoneFieldDimension(float zoom) = 0;
virtual status_t getPortId(audio_port_handle_t *portId) const = 0;
diff --git a/media/libmedia/include/media/mediarecorder.h b/media/libmedia/include/media/mediarecorder.h
index 8580437..2dd4b7f 100644
--- a/media/libmedia/include/media/mediarecorder.h
+++ b/media/libmedia/include/media/mediarecorder.h
@@ -264,8 +264,8 @@
status_t getRoutedDeviceId(audio_port_handle_t *deviceId);
status_t enableAudioDeviceCallback(bool enabled);
status_t getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones);
- status_t setMicrophoneDirection(audio_microphone_direction_t direction);
- status_t setMicrophoneFieldDimension(float zoom);
+ status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction);
+ status_t setPreferredMicrophoneFieldDimension(float zoom);
status_t getPortId(audio_port_handle_t *portId) const;
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index 6c59a29..4570af9 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -842,14 +842,14 @@
return mMediaRecorder->getActiveMicrophones(activeMicrophones);
}
-status_t MediaRecorder::setMicrophoneDirection(audio_microphone_direction_t direction) {
- ALOGV("setMicrophoneDirection(%d)", direction);
- return mMediaRecorder->setMicrophoneDirection(direction);
+status_t MediaRecorder::setPreferredMicrophoneDirection(audio_microphone_direction_t direction) {
+ ALOGV("setPreferredMicrophoneDirection(%d)", direction);
+ return mMediaRecorder->setPreferredMicrophoneDirection(direction);
}
-status_t MediaRecorder::setMicrophoneFieldDimension(float zoom) {
- ALOGV("setMicrophoneFieldDimension(%f)", zoom);
- return mMediaRecorder->setMicrophoneFieldDimension(zoom);
+status_t MediaRecorder::setPreferredMicrophoneFieldDimension(float zoom) {
+ ALOGV("setPreferredMicrophoneFieldDimension(%f)", zoom);
+ return mMediaRecorder->setPreferredMicrophoneFieldDimension(zoom);
}
status_t MediaRecorder::getPortId(audio_port_handle_t *portId) const
diff --git a/media/libmedia/xsd/Android.bp b/media/libmedia/xsd/Android.bp
new file mode 100644
index 0000000..1635f70
--- /dev/null
+++ b/media/libmedia/xsd/Android.bp
@@ -0,0 +1,21 @@
+//
+// Copyright (C) 2019 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.
+//
+
+xsd_config {
+ name: "media_profiles",
+ srcs: ["media_profiles.xsd"],
+ package_name: "media.profiles",
+}
diff --git a/media/libmedia/xsd/api/current.txt b/media/libmedia/xsd/api/current.txt
new file mode 100644
index 0000000..05e8a49
--- /dev/null
+++ b/media/libmedia/xsd/api/current.txt
@@ -0,0 +1,147 @@
+// Signature format: 2.0
+package media.profiles {
+
+ public class Audio {
+ ctor public Audio();
+ method public int getBitRate();
+ method public int getChannels();
+ method public String getCodec();
+ method public int getSampleRate();
+ method public void setBitRate(int);
+ method public void setChannels(int);
+ method public void setCodec(String);
+ method public void setSampleRate(int);
+ }
+
+ public class AudioDecoderCap {
+ ctor public AudioDecoderCap();
+ method public boolean getEnabled();
+ method public String getName();
+ method public void setEnabled(boolean);
+ method public void setName(String);
+ }
+
+ public class AudioEncoderCap {
+ ctor public AudioEncoderCap();
+ method public boolean getEnabled();
+ method public int getMaxBitRate();
+ method public int getMaxChannels();
+ method public int getMaxSampleRate();
+ method public int getMinBitRate();
+ method public int getMinChannels();
+ method public int getMinSampleRate();
+ method public String getName();
+ method public void setEnabled(boolean);
+ method public void setMaxBitRate(int);
+ method public void setMaxChannels(int);
+ method public void setMaxSampleRate(int);
+ method public void setMinBitRate(int);
+ method public void setMinChannels(int);
+ method public void setMinSampleRate(int);
+ method public void setName(String);
+ }
+
+ public class CamcorderProfiles {
+ ctor public CamcorderProfiles();
+ method public int getCameraId();
+ method public java.util.List<media.profiles.EncoderProfile> getEncoderProfile();
+ method public java.util.List<media.profiles.CamcorderProfiles.ImageDecoding> getImageDecoding();
+ method public java.util.List<media.profiles.CamcorderProfiles.ImageEncoding> getImageEncoding();
+ method public void setCameraId(int);
+ }
+
+ public static class CamcorderProfiles.ImageDecoding {
+ ctor public CamcorderProfiles.ImageDecoding();
+ method public int getMemCap();
+ method public void setMemCap(int);
+ }
+
+ public static class CamcorderProfiles.ImageEncoding {
+ ctor public CamcorderProfiles.ImageEncoding();
+ method public int getQuality();
+ method public void setQuality(int);
+ }
+
+ public class EncoderProfile {
+ ctor public EncoderProfile();
+ method public java.util.List<media.profiles.Audio> getAudio();
+ method public int getDuration();
+ method public String getFileFormat();
+ method public String getQuality();
+ method public java.util.List<media.profiles.Video> getVideo();
+ method public void setDuration(int);
+ method public void setFileFormat(String);
+ method public void setQuality(String);
+ }
+
+ public class MediaSettings {
+ ctor public MediaSettings();
+ method public java.util.List<media.profiles.AudioDecoderCap> getAudioDecoderCap();
+ method public java.util.List<media.profiles.AudioEncoderCap> getAudioEncoderCap();
+ method public java.util.List<media.profiles.CamcorderProfiles> getCamcorderProfiles();
+ method public java.util.List<media.profiles.MediaSettings.EncoderOutputFileFormat> getEncoderOutputFileFormat();
+ method public java.util.List<media.profiles.VideoDecoderCap> getVideoDecoderCap();
+ method public java.util.List<media.profiles.VideoEncoderCap> getVideoEncoderCap();
+ }
+
+ public static class MediaSettings.EncoderOutputFileFormat {
+ ctor public MediaSettings.EncoderOutputFileFormat();
+ method public String getName();
+ method public void setName(String);
+ }
+
+ public class Video {
+ ctor public Video();
+ method public int getBitRate();
+ method public String getCodec();
+ method public int getFrameRate();
+ method public int getHeight();
+ method public int getWidth();
+ method public void setBitRate(int);
+ method public void setCodec(String);
+ method public void setFrameRate(int);
+ method public void setHeight(int);
+ method public void setWidth(int);
+ }
+
+ public class VideoDecoderCap {
+ ctor public VideoDecoderCap();
+ method public boolean getEnabled();
+ method public String getName();
+ method public void setEnabled(boolean);
+ method public void setName(String);
+ }
+
+ public class VideoEncoderCap {
+ ctor public VideoEncoderCap();
+ method public boolean getEnabled();
+ method public int getMaxBitRate();
+ method public int getMaxFrameHeight();
+ method public int getMaxFrameRate();
+ method public int getMaxFrameWidth();
+ method public int getMinBitRate();
+ method public int getMinFrameHeight();
+ method public int getMinFrameRate();
+ method public int getMinFrameWidth();
+ method public String getName();
+ method public void setEnabled(boolean);
+ method public void setMaxBitRate(int);
+ method public void setMaxFrameHeight(int);
+ method public void setMaxFrameRate(int);
+ method public void setMaxFrameWidth(int);
+ method public void setMinBitRate(int);
+ method public void setMinFrameHeight(int);
+ method public void setMinFrameRate(int);
+ method public void setMinFrameWidth(int);
+ method public void setName(String);
+ }
+
+ public class XmlParser {
+ ctor public XmlParser();
+ method public static media.profiles.MediaSettings read(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ method public static String readText(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ method public static void skip(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ }
+
+}
+
diff --git a/media/libmedia/xsd/api/last_current.txt b/media/libmedia/xsd/api/last_current.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/media/libmedia/xsd/api/last_current.txt
diff --git a/media/libmedia/xsd/api/last_removed.txt b/media/libmedia/xsd/api/last_removed.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/media/libmedia/xsd/api/last_removed.txt
diff --git a/media/libmedia/xsd/api/removed.txt b/media/libmedia/xsd/api/removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/media/libmedia/xsd/api/removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/media/libmedia/xsd/media_profiles.xsd b/media/libmedia/xsd/media_profiles.xsd
new file mode 100644
index 0000000..a02252a
--- /dev/null
+++ b/media/libmedia/xsd/media_profiles.xsd
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2019 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.
+-->
+<!-- TODO: define a targetNamespace. Note that it will break retrocompatibility -->
+<xs:schema version="2.0"
+ elementFormDefault="qualified"
+ attributeFormDefault="unqualified"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:element name="MediaSettings">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="CamcorderProfiles" type="CamcorderProfiles" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="EncoderOutputFileFormat" minOccurs="0" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:attribute name="name" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="VideoEncoderCap" type="VideoEncoderCap" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="AudioEncoderCap" type="AudioEncoderCap" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="VideoDecoderCap" type="VideoDecoderCap" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="AudioDecoderCap" type="AudioDecoderCap" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:complexType name="CamcorderProfiles">
+ <xs:sequence>
+ <xs:element name="EncoderProfile" type="EncoderProfile" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="ImageEncoding" minOccurs="0" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:attribute name="quality" type="xs:int"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="ImageDecoding" minOccurs="0" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:attribute name="memCap" type="xs:int"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="cameraId" type="xs:int"/>
+ </xs:complexType>
+ <xs:complexType name="EncoderProfile">
+ <xs:sequence>
+ <xs:element name="Video" type="Video" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="Audio" type="Audio" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="quality" type="xs:string"/>
+ <xs:attribute name="fileFormat" type="xs:string"/>
+ <xs:attribute name="duration" type="xs:int"/>
+ </xs:complexType>
+ <xs:complexType name="Video">
+ <xs:attribute name="codec" type="xs:string"/>
+ <xs:attribute name="bitRate" type="xs:int"/>
+ <xs:attribute name="width" type="xs:int"/>
+ <xs:attribute name="height" type="xs:int"/>
+ <xs:attribute name="frameRate" type="xs:int"/>
+ </xs:complexType>
+ <xs:complexType name="Audio">
+ <xs:attribute name="codec" type="xs:string"/>
+ <xs:attribute name="bitRate" type="xs:int"/>
+ <xs:attribute name="sampleRate" type="xs:int"/>
+ <xs:attribute name="channels" type="xs:int"/>
+ </xs:complexType>
+ <xs:complexType name="VideoEncoderCap">
+ <xs:attribute name="name" type="xs:string"/>
+ <xs:attribute name="enabled" type="xs:boolean"/>
+ <xs:attribute name="minBitRate" type="xs:int"/>
+ <xs:attribute name="maxBitRate" type="xs:int"/>
+ <xs:attribute name="minFrameWidth" type="xs:int"/>
+ <xs:attribute name="maxFrameWidth" type="xs:int"/>
+ <xs:attribute name="minFrameHeight" type="xs:int"/>
+ <xs:attribute name="maxFrameHeight" type="xs:int"/>
+ <xs:attribute name="minFrameRate" type="xs:int"/>
+ <xs:attribute name="maxFrameRate" type="xs:int"/>
+ </xs:complexType>
+ <xs:complexType name="AudioEncoderCap">
+ <xs:attribute name="name" type="xs:string"/>
+ <xs:attribute name="enabled" type="xs:boolean"/>
+ <xs:attribute name="minBitRate" type="xs:int"/>
+ <xs:attribute name="maxBitRate" type="xs:int"/>
+ <xs:attribute name="minSampleRate" type="xs:int"/>
+ <xs:attribute name="maxSampleRate" type="xs:int"/>
+ <xs:attribute name="minChannels" type="xs:int"/>
+ <xs:attribute name="maxChannels" type="xs:int"/>
+ </xs:complexType>
+ <xs:complexType name="VideoDecoderCap">
+ <xs:attribute name="name" type="xs:string"/>
+ <xs:attribute name="enabled" type="xs:boolean"/>
+ </xs:complexType>
+ <xs:complexType name="AudioDecoderCap">
+ <xs:attribute name="name" type="xs:string"/>
+ <xs:attribute name="enabled" type="xs:boolean"/>
+ </xs:complexType>
+</xs:schema>
diff --git a/media/libmediaplayer2/JAudioTrack.cpp b/media/libmediaplayer2/JAudioTrack.cpp
index 910edff..fab6c64 100644
--- a/media/libmediaplayer2/JAudioTrack.cpp
+++ b/media/libmediaplayer2/JAudioTrack.cpp
@@ -571,10 +571,9 @@
}
void JAudioTrack::registerRoutingDelegates(
- Vector<std::pair<jobject, jobject>>& routingDelegates) {
- for (Vector<std::pair<jobject, jobject>>::iterator it = routingDelegates.begin();
- it != routingDelegates.end(); it++) {
- addAudioDeviceCallback(it->second, getHandler(it->second));
+ Vector<std::pair<sp<JObjectHolder>, sp<JObjectHolder>>>& routingDelegates) {
+ for (auto it = routingDelegates.begin(); it != routingDelegates.end(); it++) {
+ addAudioDeviceCallback(it->second->getJObject(), getHandler(it->second->getJObject()));
}
}
@@ -597,20 +596,22 @@
return env->CallObjectMethod(routingDelegateObj, jGetHandler);
}
-jobject JAudioTrack::findByKey(Vector<std::pair<jobject, jobject>>& mp, const jobject key) {
+jobject JAudioTrack::findByKey(
+ Vector<std::pair<sp<JObjectHolder>, sp<JObjectHolder>>>& mp, const jobject key) {
JNIEnv *env = JavaVMHelper::getJNIEnv();
- for (Vector<std::pair<jobject, jobject>>::iterator it = mp.begin(); it != mp.end(); it++) {
- if (env->IsSameObject(it->first, key)) {
- return it->second;
+ for (auto it = mp.begin(); it != mp.end(); it++) {
+ if (env->IsSameObject(it->first->getJObject(), key)) {
+ return it->second->getJObject();
}
}
return nullptr;
}
-void JAudioTrack::eraseByKey(Vector<std::pair<jobject, jobject>>& mp, const jobject key) {
+void JAudioTrack::eraseByKey(
+ Vector<std::pair<sp<JObjectHolder>, sp<JObjectHolder>>>& mp, const jobject key) {
JNIEnv *env = JavaVMHelper::getJNIEnv();
- for (Vector<std::pair<jobject, jobject>>::iterator it = mp.begin(); it != mp.end(); it++) {
- if (env->IsSameObject(it->first, key)) {
+ for (auto it = mp.begin(); it != mp.end(); it++) {
+ if (env->IsSameObject(it->first->getJObject(), key)) {
mp.erase(it);
return;
}
diff --git a/media/libmediaplayer2/MediaPlayer2AudioOutput.cpp b/media/libmediaplayer2/MediaPlayer2AudioOutput.cpp
index 7c3063d..b4fa0c1 100644
--- a/media/libmediaplayer2/MediaPlayer2AudioOutput.cpp
+++ b/media/libmediaplayer2/MediaPlayer2AudioOutput.cpp
@@ -521,15 +521,18 @@
status_t MediaPlayer2AudioOutput::addAudioDeviceCallback(jobject jRoutingDelegate) {
ALOGV("addAudioDeviceCallback");
Mutex::Autolock lock(mLock);
- jobject listener = (new JObjectHolder(
- JAudioTrack::getListener(jRoutingDelegate)))->getJObject();
+ jobject listener = JAudioTrack::getListener(jRoutingDelegate);
if (JAudioTrack::findByKey(mRoutingDelegates, listener) == nullptr) {
- jobject handler = (new JObjectHolder(
- JAudioTrack::getHandler(jRoutingDelegate)))->getJObject();
- jobject routingDelegate = (new JObjectHolder(jRoutingDelegate))->getJObject();
- mRoutingDelegates.push_back(std::pair<jobject, jobject>(listener, routingDelegate));
+ sp<JObjectHolder> listenerHolder = new JObjectHolder(listener);
+ jobject handler = JAudioTrack::getHandler(jRoutingDelegate);
+ sp<JObjectHolder> routingDelegateHolder = new JObjectHolder(jRoutingDelegate);
+
+ mRoutingDelegates.push_back(std::pair<sp<JObjectHolder>, sp<JObjectHolder>>(
+ listenerHolder, routingDelegateHolder));
+
if (mJAudioTrack != nullptr) {
- return mJAudioTrack->addAudioDeviceCallback(routingDelegate, handler);
+ return mJAudioTrack->addAudioDeviceCallback(
+ routingDelegateHolder->getJObject(), handler);
}
}
return NO_ERROR;
diff --git a/media/libmediaplayer2/include/mediaplayer2/JAudioTrack.h b/media/libmediaplayer2/include/mediaplayer2/JAudioTrack.h
index 7381286..2ed4632 100644
--- a/media/libmediaplayer2/include/mediaplayer2/JAudioTrack.h
+++ b/media/libmediaplayer2/include/mediaplayer2/JAudioTrack.h
@@ -405,7 +405,8 @@
* routingDelegates: backed-up routing delegates
*
*/
- void registerRoutingDelegates(Vector<std::pair<jobject, jobject>>& routingDelegates);
+ void registerRoutingDelegates(
+ Vector<std::pair<sp<JObjectHolder>, sp<JObjectHolder>>>& routingDelegates);
/* get listener from RoutingDelegate object
*/
@@ -422,13 +423,15 @@
* Returns value if key is in the map
* nullptr if key is not in the map
*/
- static jobject findByKey(Vector<std::pair<jobject, jobject>>& mp, const jobject key);
+ static jobject findByKey(
+ Vector<std::pair<sp<JObjectHolder>, sp<JObjectHolder>>>& mp, const jobject key);
/*
* Parameters:
* map and key
*/
- static void eraseByKey(Vector<std::pair<jobject, jobject>>& mp, const jobject key);
+ static void eraseByKey(
+ Vector<std::pair<sp<JObjectHolder>, sp<JObjectHolder>>>& mp, const jobject key);
private:
audio_output_flags_t mFlags;
diff --git a/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2AudioOutput.h b/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2AudioOutput.h
index 1b3f2dc..f38b7cc 100644
--- a/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2AudioOutput.h
+++ b/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2AudioOutput.h
@@ -124,7 +124,9 @@
audio_output_flags_t mFlags;
sp<JObjectHolder> mPreferredDevice;
mutable Mutex mLock;
- Vector<std::pair<jobject, jobject>> mRoutingDelegates; // <listener, routingDelegate>
+
+ // <listener, routingDelegate>
+ Vector<std::pair<sp<JObjectHolder>, sp<JObjectHolder>>> mRoutingDelegates;
// static variables below not protected by mutex
static bool mIsOnEmulator;
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index d6628d9..9f4265b 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -538,18 +538,19 @@
return NO_INIT;
}
-status_t MediaRecorderClient::setMicrophoneDirection(audio_microphone_direction_t direction) {
- ALOGV("setMicrophoneDirection(%d)", direction);
+status_t MediaRecorderClient::setPreferredMicrophoneDirection(
+ audio_microphone_direction_t direction) {
+ ALOGV("setPreferredMicrophoneDirection(%d)", direction);
if (mRecorder != NULL) {
- return mRecorder->setMicrophoneDirection(direction);
+ return mRecorder->setPreferredMicrophoneDirection(direction);
}
return NO_INIT;
}
-status_t MediaRecorderClient::setMicrophoneFieldDimension(float zoom) {
- ALOGV("setMicrophoneFieldDimension(%f)", zoom);
+status_t MediaRecorderClient::setPreferredMicrophoneFieldDimension(float zoom) {
+ ALOGV("setPreferredMicrophoneFieldDimension(%f)", zoom);
if (mRecorder != NULL) {
- return mRecorder->setMicrophoneFieldDimension(zoom);
+ return mRecorder->setPreferredMicrophoneFieldDimension(zoom);
}
return NO_INIT;
}
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
index 8da718f..e698819 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.h
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -109,8 +109,8 @@
virtual status_t enableAudioDeviceCallback(bool enabled);
virtual status_t getActiveMicrophones(
std::vector<media::MicrophoneInfo>* activeMicrophones);
- virtual status_t setMicrophoneDirection(audio_microphone_direction_t direction);
- virtual status_t setMicrophoneFieldDimension(float zoom);
+ virtual status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction);
+ virtual status_t setPreferredMicrophoneFieldDimension(float zoom);
status_t getPortId(audio_port_handle_t *portId) override;
private:
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 624f596..63681fa 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -164,9 +164,12 @@
mAnalyticsItem->setInt32(kRecorderVideoIframeInterval, mIFramesIntervalSec);
// TBD mAudioSourceNode = 0;
// TBD mUse64BitFileOffset = false;
- mAnalyticsItem->setInt32(kRecorderMovieTimescale, mMovieTimeScale);
- mAnalyticsItem->setInt32(kRecorderAudioTimescale, mAudioTimeScale);
- mAnalyticsItem->setInt32(kRecorderVideoTimescale, mVideoTimeScale);
+ if (mMovieTimeScale != -1)
+ mAnalyticsItem->setInt32(kRecorderMovieTimescale, mMovieTimeScale);
+ if (mAudioTimeScale != -1)
+ mAnalyticsItem->setInt32(kRecorderAudioTimescale, mAudioTimeScale);
+ if (mVideoTimeScale != -1)
+ mAnalyticsItem->setInt32(kRecorderVideoTimescale, mVideoTimeScale);
// TBD mCameraId = 0;
// TBD mStartTimeOffsetMs = -1;
mAnalyticsItem->setInt32(kRecorderVideoProfile, mVideoEncoderProfile);
@@ -400,12 +403,14 @@
return -EBADF;
}
- // start with a clean, empty file
- ftruncate(fd, 0);
- if (mWriter == NULL) {
+ if (mWriter == nullptr) {
ALOGE("setNextOutputFile failed. Writer has been freed");
return INVALID_OPERATION;
}
+
+ // start with a clean, empty file
+ ftruncate(fd, 0);
+
return mWriter->setNextFd(fd);
}
@@ -2208,7 +2213,7 @@
}
status_t StagefrightRecorder::getMetrics(Parcel *reply) {
- ALOGD("StagefrightRecorder::getMetrics");
+ ALOGV("StagefrightRecorder::getMetrics");
if (reply == NULL) {
ALOGE("Null pointer argument");
@@ -2272,20 +2277,20 @@
return NO_INIT;
}
-status_t StagefrightRecorder::setMicrophoneDirection(audio_microphone_direction_t direction) {
- ALOGV("setMicrophoneDirection(%d)", direction);
+status_t StagefrightRecorder::setPreferredMicrophoneDirection(audio_microphone_direction_t direction) {
+ ALOGV("setPreferredMicrophoneDirection(%d)", direction);
mSelectedMicDirection = direction;
if (mAudioSourceNode != 0) {
- return mAudioSourceNode->setMicrophoneDirection(direction);
+ return mAudioSourceNode->setPreferredMicrophoneDirection(direction);
}
return NO_INIT;
}
-status_t StagefrightRecorder::setMicrophoneFieldDimension(float zoom) {
- ALOGV("setMicrophoneFieldDimension(%f)", zoom);
+status_t StagefrightRecorder::setPreferredMicrophoneFieldDimension(float zoom) {
+ ALOGV("setPreferredMicrophoneFieldDimension(%f)", zoom);
mSelectedMicFieldDimension = zoom;
if (mAudioSourceNode != 0) {
- return mAudioSourceNode->setMicrophoneFieldDimension(zoom);
+ return mAudioSourceNode->setPreferredMicrophoneFieldDimension(zoom);
}
return NO_INIT;
}
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index 236b19e..8bf083a 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -77,8 +77,8 @@
virtual void setAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback);
virtual status_t enableAudioDeviceCallback(bool enabled);
virtual status_t getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones);
- virtual status_t setMicrophoneDirection(audio_microphone_direction_t direction);
- virtual status_t setMicrophoneFieldDimension(float zoom);
+ virtual status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction);
+ virtual status_t setPreferredMicrophoneFieldDimension(float zoom);
status_t getPortId(audio_port_handle_t *portId) const override;
private:
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index f00c895..cf1a6f1 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -569,7 +569,6 @@
mFps(-1.0),
mCaptureFps(-1.0),
mCreateInputBuffersSuspended(false),
- mLatency(0),
mTunneled(false),
mDescribeColorAspectsIndex((OMX_INDEXTYPE)0),
mDescribeHDRStaticInfoIndex((OMX_INDEXTYPE)0),
@@ -4425,12 +4424,13 @@
h264type.eProfile == OMX_VIDEO_AVCProfileHigh) {
h264type.nSliceHeaderSpacing = 0;
h264type.bUseHadamard = OMX_TRUE;
- h264type.nRefFrames = 2;
- h264type.nBFrames = mLatency == 0 ? 1 : std::min(1U, mLatency - 1);
-
- // disable B-frames until we have explicit settings for enabling the feature.
- h264type.nRefFrames = 1;
- h264type.nBFrames = 0;
+ int32_t maxBframes = 0;
+ (void)msg->findInt32(KEY_MAX_B_FRAMES, &maxBframes);
+ h264type.nBFrames = uint32_t(maxBframes);
+ if (mLatency && h264type.nBFrames > *mLatency) {
+ h264type.nBFrames = *mLatency;
+ }
+ h264type.nRefFrames = h264type.nBFrames == 0 ? 1 : 2;
h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate, h264type.nBFrames);
h264type.nAllowedPictureTypes =
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index d8b825d..da35889 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -181,6 +181,7 @@
"libcamera_client",
"libcutils",
"libdl",
+ "libdl_android",
"libdrmframework",
"libgui",
"liblog",
@@ -225,6 +226,7 @@
],
export_shared_lib_headers: [
+ "libgui",
"libmedia",
"android.hidl.allocator@1.0",
],
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
index 5f86bd3..a713900 100644
--- a/media/libstagefright/AudioSource.cpp
+++ b/media/libstagefright/AudioSource.cpp
@@ -385,11 +385,11 @@
}
mLastFrameTimestampUs = timeUs;
- size_t numLostBytes = 0;
+ uint64_t numLostBytes = 0; // AudioRecord::getInputFramesLost() returns uint32_t
if (mNumFramesReceived > 0) { // Ignore earlier frame lost
// getInputFramesLost() returns the number of lost frames.
// Convert number of frames lost to number of bytes lost.
- numLostBytes = mRecord->getInputFramesLost() * mRecord->frameSize();
+ numLostBytes = (uint64_t)mRecord->getInputFramesLost() * mRecord->frameSize();
}
CHECK_EQ(numLostBytes & 1, 0u);
@@ -397,11 +397,11 @@
if (numLostBytes > 0) {
// Loss of audio frames should happen rarely; thus the LOGW should
// not cause a logging spam
- ALOGW("Lost audio record data: %zu bytes", numLostBytes);
+ ALOGW("Lost audio record data: %" PRIu64 " bytes", numLostBytes);
}
while (numLostBytes > 0) {
- size_t bufferSize = numLostBytes;
+ uint64_t bufferSize = numLostBytes;
if (numLostBytes > kMaxBufferSize) {
numLostBytes -= kMaxBufferSize;
bufferSize = kMaxBufferSize;
@@ -510,18 +510,18 @@
return NO_INIT;
}
-status_t AudioSource::setMicrophoneDirection(audio_microphone_direction_t direction) {
- ALOGV("setMicrophoneDirection(%d)", direction);
+status_t AudioSource::setPreferredMicrophoneDirection(audio_microphone_direction_t direction) {
+ ALOGV("setPreferredMicrophoneDirection(%d)", direction);
if (mRecord != 0) {
- return mRecord->setMicrophoneDirection(direction);
+ return mRecord->setPreferredMicrophoneDirection(direction);
}
return NO_INIT;
}
-status_t AudioSource::setMicrophoneFieldDimension(float zoom) {
- ALOGV("setMicrophoneFieldDimension(%f)", zoom);
+status_t AudioSource::setPreferredMicrophoneFieldDimension(float zoom) {
+ ALOGV("setPreferredMicrophoneFieldDimension(%f)", zoom);
if (mRecord != 0) {
- return mRecord->setMicrophoneFieldDimension(zoom);
+ return mRecord->setPreferredMicrophoneFieldDimension(zoom);
}
return NO_INIT;
}
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 6b5fd87..1ec419a 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -71,6 +71,7 @@
static const uint8_t kNalUnitTypePicParamSet = 0x08;
static const int64_t kInitialDelayTimeUs = 700000LL;
static const int64_t kMaxMetadataSize = 0x4000000LL; // 64MB max per-frame metadata size
+static const int64_t kMaxCttsOffsetTimeUs = 30 * 60 * 1000000LL; // 30 minutes
static const char kMetaKey_Version[] = "com.android.version";
static const char kMetaKey_Manufacturer[] = "com.android.manufacturer";
@@ -136,13 +137,6 @@
void resetInternal();
private:
- enum {
- // TODO: need to increase this considering the bug
- // about camera app not sending video frames continuously?
- kMaxCttsOffsetTimeUs = 1000000LL, // 1 second
- kSampleArraySize = 1000,
- };
-
// A helper class to handle faster write box with table entries
template<class TYPE, unsigned ENTRY_SIZE>
// ENTRY_SIZE: # of values in each entry
diff --git a/media/libstagefright/MetaDataUtils.cpp b/media/libstagefright/MetaDataUtils.cpp
index dbc287e..3f0bc7d 100644
--- a/media/libstagefright/MetaDataUtils.cpp
+++ b/media/libstagefright/MetaDataUtils.cpp
@@ -309,7 +309,6 @@
void parseVorbisComment(
AMediaFormat *fileMeta, const char *comment, size_t commentLength) {
// Haptic tag is only kept here as it will only be used in extractor to generate channel mask.
- const char* const haptic = "haptic";
struct {
const char *const mTag;
const char *mKey;
@@ -330,7 +329,7 @@
{ "LYRICIST", AMEDIAFORMAT_KEY_LYRICIST },
{ "METADATA_BLOCK_PICTURE", AMEDIAFORMAT_KEY_ALBUMART },
{ "ANDROID_LOOP", AMEDIAFORMAT_KEY_LOOP },
- { "ANDROID_HAPTIC", haptic },
+ { "ANDROID_HAPTIC", AMEDIAFORMAT_KEY_HAPTIC_CHANNEL_COUNT },
};
for (size_t j = 0; j < sizeof(kMap) / sizeof(kMap[0]); ++j) {
@@ -346,12 +345,12 @@
if (!strcasecmp(&comment[tagLen + 1], "true")) {
AMediaFormat_setInt32(fileMeta, AMEDIAFORMAT_KEY_LOOP, 1);
}
- } else if (kMap[j].mKey == haptic) {
+ } else if (kMap[j].mKey == AMEDIAFORMAT_KEY_HAPTIC_CHANNEL_COUNT) {
char *end;
errno = 0;
const int hapticChannelCount = strtol(&comment[tagLen + 1], &end, 10);
if (errno == 0) {
- AMediaFormat_setInt32(fileMeta, haptic, hapticChannelCount);
+ AMediaFormat_setInt32(fileMeta, kMap[j].mKey, hapticChannelCount);
} else {
ALOGE("Error(%d) when parsing haptic channel count", errno);
}
diff --git a/media/libstagefright/RemoteMediaExtractor.cpp b/media/libstagefright/RemoteMediaExtractor.cpp
index b0ce688..29c3a35 100644
--- a/media/libstagefright/RemoteMediaExtractor.cpp
+++ b/media/libstagefright/RemoteMediaExtractor.cpp
@@ -18,6 +18,7 @@
#define LOG_TAG "RemoteMediaExtractor"
#include <utils/Log.h>
+#include <binder/IPCThreadState.h>
#include <media/stagefright/InterfaceUtils.h>
#include <media/MediaAnalyticsItem.h>
#include <media/MediaSource.h>
@@ -51,6 +52,11 @@
if (MEDIA_LOG) {
mAnalyticsItem = MediaAnalyticsItem::create(kKeyExtractor);
+ // we're in the extractor service, we want to attribute to the app
+ // that invoked us.
+ int uid = IPCThreadState::self()->getCallingUid();
+ mAnalyticsItem->setUid(uid);
+
// track the container format (mpeg, aac, wvm, etc)
size_t ntracks = extractor->countTracks();
mAnalyticsItem->setCString(kExtractorFormat, extractor->name());
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index 16b3319..c7b2719 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -642,6 +642,15 @@
{ "icc-profile", kKeyIccProfile },
{ "sei", kKeySEI },
{ "text-format-data", kKeyTextFormatData },
+ { "thumbnail-csd-hevc", kKeyThumbnailHVCC },
+ }
+};
+
+static std::vector<std::pair<const char *, uint32_t>> CSDMappings {
+ {
+ { "csd-0", kKeyOpaqueCSD0 },
+ { "csd-1", kKeyOpaqueCSD1 },
+ { "csd-2", kKeyOpaqueCSD2 },
}
};
@@ -681,6 +690,14 @@
MetaDataBase::Type::TYPE_NONE, value->data(), value->size());
}
}
+
+ for (auto elem : CSDMappings) {
+ sp<ABuffer> value;
+ if (msg->findBuffer(elem.first, &value)) {
+ meta->setData(elem.second,
+ MetaDataBase::Type::TYPE_NONE, value->data(), value->size());
+ }
+ }
}
void convertMetaDataToMessageFromMappings(const MetaDataBase *meta, sp<AMessage> format) {
@@ -721,6 +738,18 @@
format->setBuffer(elem.first, buf);
}
}
+
+ for (auto elem : CSDMappings) {
+ uint32_t type;
+ const void* data;
+ size_t size;
+ if (meta->findData(elem.second, &type, &data, &size)) {
+ sp<ABuffer> buf = ABuffer::CreateAsCopy(data, size);
+ buf->meta()->setInt32("csd", true);
+ buf->meta()->setInt64("timeUs", 0);
+ format->setBuffer(elem.first, buf);
+ }
+ }
}
status_t convertMetaDataToMessage(
@@ -938,6 +967,11 @@
if (meta->findInt32(kKeyPcmEncoding, &pcmEncoding)) {
msg->setInt32("pcm-encoding", pcmEncoding);
}
+
+ int32_t hapticChannelCount;
+ if (meta->findInt32(kKeyHapticChannelCount, &hapticChannelCount)) {
+ msg->setInt32("haptic-channel-count", hapticChannelCount);
+ }
}
int32_t maxInputSize;
@@ -1248,30 +1282,6 @@
} else if (meta->findData(kKeyD263, &type, &data, &size)) {
const uint8_t *ptr = (const uint8_t *)data;
parseH263ProfileLevelFromD263(ptr, size, msg);
- } else if (meta->findData(kKeyVorbisInfo, &type, &data, &size)) {
- sp<ABuffer> buffer = new (std::nothrow) ABuffer(size);
- if (buffer.get() == NULL || buffer->base() == NULL) {
- return NO_MEMORY;
- }
- memcpy(buffer->data(), data, size);
-
- buffer->meta()->setInt32("csd", true);
- buffer->meta()->setInt64("timeUs", 0);
- msg->setBuffer("csd-0", buffer);
-
- if (!meta->findData(kKeyVorbisBooks, &type, &data, &size)) {
- return -EINVAL;
- }
-
- buffer = new (std::nothrow) ABuffer(size);
- if (buffer.get() == NULL || buffer->base() == NULL) {
- return NO_MEMORY;
- }
- memcpy(buffer->data(), data, size);
-
- buffer->meta()->setInt32("csd", true);
- buffer->meta()->setInt64("timeUs", 0);
- msg->setBuffer("csd-1", buffer);
} else if (meta->findData(kKeyOpusHeader, &type, &data, &size)) {
sp<ABuffer> buffer = new (std::nothrow) ABuffer(size);
if (buffer.get() == NULL || buffer->base() == NULL) {
@@ -1310,16 +1320,6 @@
buffer->meta()->setInt32("csd", true);
buffer->meta()->setInt64("timeUs", 0);
msg->setBuffer("csd-2", buffer);
- } else if (meta->findData(kKeyFlacMetadata, &type, &data, &size)) {
- sp<ABuffer> buffer = new (std::nothrow) ABuffer(size);
- if (buffer.get() == NULL || buffer->base() == NULL) {
- return NO_MEMORY;
- }
- memcpy(buffer->data(), data, size);
-
- buffer->meta()->setInt32("csd", true);
- buffer->meta()->setInt64("timeUs", 0);
- msg->setBuffer("csd-0", buffer);
} else if (meta->findData(kKeyVp9CodecPrivate, &type, &data, &size)) {
sp<ABuffer> buffer = new (std::nothrow) ABuffer(size);
if (buffer.get() == NULL || buffer->base() == NULL) {
@@ -1713,6 +1713,11 @@
if (msg->findInt32("pcm-encoding", &pcmEncoding)) {
meta->setInt32(kKeyPcmEncoding, pcmEncoding);
}
+
+ int32_t hapticChannelCount;
+ if (msg->findInt32("haptic-channel-count", &hapticChannelCount)) {
+ meta->setInt32(kKeyHapticChannelCount, hapticChannelCount);
+ }
}
int32_t maxInputSize;
@@ -1796,11 +1801,6 @@
if (seekPreRollBuf) {
meta->setData(kKeyOpusSeekPreRoll, 0, seekPreRollBuf, seekPreRollBufSize);
}
- } else if (mime == MEDIA_MIMETYPE_AUDIO_VORBIS) {
- meta->setData(kKeyVorbisInfo, 0, csd0->data(), csd0->size());
- if (msg->findBuffer("csd-1", &csd1)) {
- meta->setData(kKeyVorbisBooks, 0, csd1->data(), csd1->size());
- }
} else if (mime == MEDIA_MIMETYPE_AUDIO_ALAC) {
meta->setData(kKeyAlacMagicCookie, 0, csd0->data(), csd0->size());
}
diff --git a/media/libstagefright/codecs/aacdec/Android.bp b/media/libstagefright/codecs/aacdec/Android.bp
index 25628a2..e0bb5cd 100644
--- a/media/libstagefright/codecs/aacdec/Android.bp
+++ b/media/libstagefright/codecs/aacdec/Android.bp
@@ -29,12 +29,10 @@
static_libs: ["libFraunhoferAAC"],
+ defaults: ["omx_soft_libs"],
+
shared_libs: [
- "libstagefright_omx",
- "libstagefright_foundation",
- "libutils",
"libcutils",
- "liblog",
],
compile_multilib: "32",
}
diff --git a/media/libstagefright/codecs/aacenc/Android.bp b/media/libstagefright/codecs/aacenc/Android.bp
index ec1151b..0d677fe 100644
--- a/media/libstagefright/codecs/aacenc/Android.bp
+++ b/media/libstagefright/codecs/aacenc/Android.bp
@@ -26,11 +26,7 @@
static_libs: ["libFraunhoferAAC"],
- shared_libs: [
- "libstagefright_omx",
- "libstagefright_foundation",
- "libutils",
- "liblog",
- ],
+ defaults: ["omx_soft_libs"],
+
compile_multilib: "32",
}
diff --git a/media/libstagefright/codecs/amrnb/common/src/lsp.cpp b/media/libstagefright/codecs/amrnb/common/src/lsp.cpp
index 0e3f772..81d9cde 100644
--- a/media/libstagefright/codecs/amrnb/common/src/lsp.cpp
+++ b/media/libstagefright/codecs/amrnb/common/src/lsp.cpp
@@ -173,7 +173,7 @@
*st = NULL;
/* allocate memory */
- if ((s = (lspState *) malloc(sizeof(lspState))) == NULL)
+ if ((s = (lspState *) calloc(sizeof(lspState), 1)) == NULL)
{
/* fprintf(stderr, "lsp_init: can not malloc state structure\n"); */
return -1;
@@ -182,11 +182,13 @@
/* Initialize quantization state */
if (0 != Q_plsf_init(&s->qSt))
{
+ lsp_exit(&s);
return -1;
}
if (0 != lsp_reset(s))
{
+ lsp_exit(&s);
return -1;
}
diff --git a/media/libstagefright/codecs/amrnb/dec/Android.bp b/media/libstagefright/codecs/amrnb/dec/Android.bp
index 880f161..f3b272b 100644
--- a/media/libstagefright/codecs/amrnb/dec/Android.bp
+++ b/media/libstagefright/codecs/amrnb/dec/Android.bp
@@ -101,11 +101,9 @@
"libstagefright_amrwbdec",
],
+ defaults: ["omx_soft_libs"],
+
shared_libs: [
- "libstagefright_omx",
- "libstagefright_foundation",
- "libutils",
- "liblog",
"libstagefright_amrnb_common",
],
compile_multilib: "32",
diff --git a/media/libstagefright/codecs/amrnb/dec/src/sp_dec.cpp b/media/libstagefright/codecs/amrnb/dec/src/sp_dec.cpp
index 2989b74..49cafff 100644
--- a/media/libstagefright/codecs/amrnb/dec/src/sp_dec.cpp
+++ b/media/libstagefright/codecs/amrnb/dec/src/sp_dec.cpp
@@ -268,13 +268,7 @@
if (Decoder_amr_init(&s->decoder_amrState)
|| Post_Process_reset(&s->postHP_state))
{
- Speech_Decode_FrameState *tmp = s;
- /*
- * dereferencing type-punned pointer avoid
- * breaking strict-aliasing rules
- */
- void** tempVoid = (void**) tmp;
- GSMDecodeFrameExit(tempVoid);
+ free(s);
return (-1);
}
diff --git a/media/libstagefright/codecs/amrnb/enc/Android.bp b/media/libstagefright/codecs/amrnb/enc/Android.bp
index 19fd4a8..1c8b511 100644
--- a/media/libstagefright/codecs/amrnb/enc/Android.bp
+++ b/media/libstagefright/codecs/amrnb/enc/Android.bp
@@ -110,11 +110,9 @@
static_libs: ["libstagefright_amrnbenc"],
+ defaults: ["omx_soft_libs"],
+
shared_libs: [
- "libstagefright_omx",
- "libstagefright_foundation",
- "libutils",
- "liblog",
"libstagefright_amrnb_common",
],
compile_multilib: "32",
diff --git a/media/libstagefright/codecs/amrwbenc/Android.bp b/media/libstagefright/codecs/amrwbenc/Android.bp
index b9d45c1..8327500 100644
--- a/media/libstagefright/codecs/amrwbenc/Android.bp
+++ b/media/libstagefright/codecs/amrwbenc/Android.bp
@@ -167,11 +167,9 @@
static_libs: ["libstagefright_amrwbenc"],
+ defaults: ["omx_soft_libs"],
+
shared_libs: [
- "libstagefright_omx",
- "libstagefright_foundation",
- "libutils",
- "liblog",
"libstagefright_enc_common",
],
compile_multilib: "32",
diff --git a/media/libstagefright/codecs/avcdec/Android.bp b/media/libstagefright/codecs/avcdec/Android.bp
index 8a34845..567bcca 100644
--- a/media/libstagefright/codecs/avcdec/Android.bp
+++ b/media/libstagefright/codecs/avcdec/Android.bp
@@ -22,12 +22,7 @@
"frameworks/native/include/media/openmax",
],
- shared_libs: [
- "libstagefright_omx",
- "libstagefright_foundation",
- "libutils",
- "liblog",
- ],
+ defaults: ["omx_soft_libs"],
sanitize: {
misc_undefined: [
diff --git a/media/libstagefright/codecs/avcenc/Android.bp b/media/libstagefright/codecs/avcenc/Android.bp
index 6371828..0cd39e1 100644
--- a/media/libstagefright/codecs/avcenc/Android.bp
+++ b/media/libstagefright/codecs/avcenc/Android.bp
@@ -16,12 +16,7 @@
"frameworks/native/include/media/openmax",
],
- shared_libs: [
- "libstagefright_foundation",
- "libstagefright_omx",
- "libutils",
- "liblog",
- ],
+ defaults: ["omx_soft_libs"],
sanitize: {
misc_undefined: [
diff --git a/media/libstagefright/codecs/flac/dec/Android.bp b/media/libstagefright/codecs/flac/dec/Android.bp
index 3d4a44f..18a3f6b 100644
--- a/media/libstagefright/codecs/flac/dec/Android.bp
+++ b/media/libstagefright/codecs/flac/dec/Android.bp
@@ -28,12 +28,10 @@
cfi: true,
},
+ defaults: ["omx_soft_libs"],
+
shared_libs: [
- "liblog",
"libstagefright_flacdec",
- "libstagefright_omx",
- "libstagefright_foundation",
- "libutils",
],
compile_multilib: "32",
}
diff --git a/media/libstagefright/codecs/flac/enc/Android.bp b/media/libstagefright/codecs/flac/enc/Android.bp
index b32ab08..4149ccd 100644
--- a/media/libstagefright/codecs/flac/enc/Android.bp
+++ b/media/libstagefright/codecs/flac/enc/Android.bp
@@ -19,13 +19,7 @@
],
cfi: true,
},
-
- shared_libs: [
- "libstagefright_omx",
- "libstagefright_foundation",
- "libutils",
- "liblog",
- ],
+ defaults: ["omx_soft_libs"],
header_libs: ["libbase_headers"],
static_libs: [
diff --git a/media/libstagefright/codecs/g711/dec/Android.bp b/media/libstagefright/codecs/g711/dec/Android.bp
index 7097688..c273179 100644
--- a/media/libstagefright/codecs/g711/dec/Android.bp
+++ b/media/libstagefright/codecs/g711/dec/Android.bp
@@ -12,12 +12,7 @@
"frameworks/native/include/media/openmax",
],
- shared_libs: [
- "libstagefright_foundation",
- "libstagefright_omx",
- "libutils",
- "liblog",
- ],
+ defaults: ["omx_soft_libs"],
cflags: ["-Werror"],
diff --git a/media/libstagefright/codecs/gsm/dec/Android.bp b/media/libstagefright/codecs/gsm/dec/Android.bp
index a973f70..3c5ebfe 100644
--- a/media/libstagefright/codecs/gsm/dec/Android.bp
+++ b/media/libstagefright/codecs/gsm/dec/Android.bp
@@ -25,12 +25,7 @@
cfi: true,
},
- shared_libs: [
- "libstagefright_foundation",
- "libstagefright_omx",
- "libutils",
- "liblog",
- ],
+ defaults: ["omx_soft_libs"],
static_libs: ["libgsm"],
compile_multilib: "32",
diff --git a/media/libstagefright/codecs/hevcdec/Android.bp b/media/libstagefright/codecs/hevcdec/Android.bp
index 60fc446..cc91d53 100644
--- a/media/libstagefright/codecs/hevcdec/Android.bp
+++ b/media/libstagefright/codecs/hevcdec/Android.bp
@@ -30,12 +30,7 @@
cfi: true,
},
- shared_libs: [
- "libstagefright_omx",
- "libstagefright_foundation",
- "libutils",
- "liblog",
- ],
+ defaults: ["omx_soft_libs"],
// We need this because the current asm generates the following link error:
// requires unsupported dynamic reloc R_ARM_REL32; recompile with -fPIC
diff --git a/media/libstagefright/codecs/m4v_h263/dec/Android.bp b/media/libstagefright/codecs/m4v_h263/dec/Android.bp
index 41141b1..0523143 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/Android.bp
+++ b/media/libstagefright/codecs/m4v_h263/dec/Android.bp
@@ -91,12 +91,7 @@
static_libs: ["libstagefright_m4vh263dec"],
- shared_libs: [
- "libstagefright_omx",
- "libstagefright_foundation",
- "libutils",
- "liblog",
- ],
+ defaults: ["omx_soft_libs"],
sanitize: {
misc_undefined: [
diff --git a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
index a8fcdd1..60750d9 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
@@ -24,7 +24,6 @@
#include <media/stagefright/foundation/AUtils.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaErrors.h>
-#include <media/IOMX.h>
#include "mp4dec_api.h"
@@ -118,9 +117,14 @@
outHeader->nFlags = OMX_BUFFERFLAG_EOS;
List<BufferInfo *>::iterator it = outQueue.begin();
- while ((*it)->mHeader != outHeader) {
+ while (it != outQueue.end() && (*it)->mHeader != outHeader) {
++it;
}
+ if (it == outQueue.end()) {
+ ALOGE("couldn't find port buffer %d in outQueue: b/109891727", mNumSamplesOutput & 1);
+ android_errorWriteLog(0x534e4554, "109891727");
+ return;
+ }
BufferInfo *outInfo = *it;
outInfo->mOwnedByUs = false;
diff --git a/media/libstagefright/codecs/m4v_h263/enc/Android.bp b/media/libstagefright/codecs/m4v_h263/enc/Android.bp
index d4f7d50..d38f4b1 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/Android.bp
+++ b/media/libstagefright/codecs/m4v_h263/enc/Android.bp
@@ -77,12 +77,7 @@
static_libs: ["libstagefright_m4vh263enc"],
- shared_libs: [
- "libstagefright_foundation",
- "libstagefright_omx",
- "libutils",
- "liblog",
- ],
+ defaults: ["omx_soft_libs"],
sanitize: {
misc_undefined: [
diff --git a/media/libstagefright/codecs/mp3dec/Android.bp b/media/libstagefright/codecs/mp3dec/Android.bp
index 2154f84..9173ed6 100644
--- a/media/libstagefright/codecs/mp3dec/Android.bp
+++ b/media/libstagefright/codecs/mp3dec/Android.bp
@@ -105,12 +105,7 @@
cfi: true,
},
- shared_libs: [
- "libstagefright_omx",
- "libstagefright_foundation",
- "libutils",
- "liblog",
- ],
+ defaults: ["omx_soft_libs"],
static_libs: ["libstagefright_mp3dec"],
compile_multilib: "32",
diff --git a/media/libstagefright/codecs/mpeg2dec/Android.bp b/media/libstagefright/codecs/mpeg2dec/Android.bp
index c655544..26e786e 100644
--- a/media/libstagefright/codecs/mpeg2dec/Android.bp
+++ b/media/libstagefright/codecs/mpeg2dec/Android.bp
@@ -20,12 +20,7 @@
"frameworks/native/include/media/openmax",
],
- shared_libs: [
- "libstagefright_omx",
- "libstagefright_foundation",
- "libutils",
- "liblog",
- ],
+ defaults: ["omx_soft_libs"],
ldflags: ["-Wl,-Bsymbolic"],
diff --git a/media/libstagefright/codecs/on2/dec/Android.bp b/media/libstagefright/codecs/on2/dec/Android.bp
index 174f183..abd21d7 100644
--- a/media/libstagefright/codecs/on2/dec/Android.bp
+++ b/media/libstagefright/codecs/on2/dec/Android.bp
@@ -14,12 +14,7 @@
static_libs: ["libvpx"],
- shared_libs: [
- "libstagefright_omx",
- "libstagefright_foundation",
- "libutils",
- "liblog",
- ],
+ defaults: ["omx_soft_libs"],
cflags: ["-Werror"],
diff --git a/media/libstagefright/codecs/on2/enc/Android.bp b/media/libstagefright/codecs/on2/enc/Android.bp
index 891a771..ea46bad 100644
--- a/media/libstagefright/codecs/on2/enc/Android.bp
+++ b/media/libstagefright/codecs/on2/enc/Android.bp
@@ -30,11 +30,7 @@
static_libs: ["libvpx"],
- shared_libs: [
- "libstagefright_omx",
- "libstagefright_foundation",
- "libutils",
- "liblog",
- ],
+ defaults: ["omx_soft_libs"],
+
compile_multilib: "32",
}
diff --git a/media/libstagefright/codecs/on2/enc/SoftVP8Encoder.h b/media/libstagefright/codecs/on2/enc/SoftVP8Encoder.h
index b4904bf..c5c2abf 100644
--- a/media/libstagefright/codecs/on2/enc/SoftVP8Encoder.h
+++ b/media/libstagefright/codecs/on2/enc/SoftVP8Encoder.h
@@ -23,8 +23,6 @@
#include <OMX_VideoExt.h>
#include <OMX_IndexExt.h>
-#include <hardware/gralloc.h>
-
#include "vpx/vpx_encoder.h"
#include "vpx/vpx_codec.h"
#include "vpx/vp8cx.h"
diff --git a/media/libstagefright/codecs/on2/enc/SoftVP9Encoder.h b/media/libstagefright/codecs/on2/enc/SoftVP9Encoder.h
index 85df69a..308a9ac 100644
--- a/media/libstagefright/codecs/on2/enc/SoftVP9Encoder.h
+++ b/media/libstagefright/codecs/on2/enc/SoftVP9Encoder.h
@@ -23,8 +23,6 @@
#include <OMX_VideoExt.h>
#include <OMX_IndexExt.h>
-#include <hardware/gralloc.h>
-
#include "vpx/vpx_encoder.h"
#include "vpx/vpx_codec.h"
#include "vpx/vp8cx.h"
diff --git a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h
index 263d134..7208d69 100644
--- a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h
+++ b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h
@@ -23,8 +23,6 @@
#include <OMX_VideoExt.h>
#include <OMX_IndexExt.h>
-#include <hardware/gralloc.h>
-
#include "vpx/vpx_encoder.h"
#include "vpx/vpx_codec.h"
#include "vpx/vp8cx.h"
diff --git a/media/libstagefright/codecs/opus/dec/Android.bp b/media/libstagefright/codecs/opus/dec/Android.bp
index afe459d..bfcae07 100644
--- a/media/libstagefright/codecs/opus/dec/Android.bp
+++ b/media/libstagefright/codecs/opus/dec/Android.bp
@@ -12,12 +12,10 @@
"frameworks/native/include/media/openmax",
],
+ defaults: ["omx_soft_libs"],
+
shared_libs: [
"libopus",
- "libstagefright_omx",
- "libstagefright_foundation",
- "libutils",
- "liblog",
],
cflags: ["-Werror"],
diff --git a/media/libstagefright/codecs/raw/Android.bp b/media/libstagefright/codecs/raw/Android.bp
index f822445..1c23bad 100644
--- a/media/libstagefright/codecs/raw/Android.bp
+++ b/media/libstagefright/codecs/raw/Android.bp
@@ -24,11 +24,7 @@
cfi: true,
},
- shared_libs: [
- "libstagefright_omx",
- "libstagefright_foundation",
- "libutils",
- "liblog",
- ],
+ defaults: ["omx_soft_libs"],
+
compile_multilib: "32",
}
diff --git a/media/libstagefright/codecs/vorbis/dec/Android.bp b/media/libstagefright/codecs/vorbis/dec/Android.bp
index a9265cb..2d1a922 100644
--- a/media/libstagefright/codecs/vorbis/dec/Android.bp
+++ b/media/libstagefright/codecs/vorbis/dec/Android.bp
@@ -12,12 +12,10 @@
"frameworks/native/include/media/openmax",
],
+ defaults: ["omx_soft_libs"],
+
shared_libs: [
"libvorbisidec",
- "libstagefright_omx",
- "libstagefright_foundation",
- "libutils",
- "liblog",
],
cflags: ["-Werror"],
diff --git a/media/libstagefright/codecs/xaacdec/Android.bp b/media/libstagefright/codecs/xaacdec/Android.bp
index 7392f1e..e49eb8f 100644
--- a/media/libstagefright/codecs/xaacdec/Android.bp
+++ b/media/libstagefright/codecs/xaacdec/Android.bp
@@ -24,12 +24,10 @@
static_libs: ["libxaacdec"],
+ defaults: ["omx_soft_libs"],
+
shared_libs: [
- "libstagefright_omx",
- "libstagefright_foundation",
- "libutils",
"libcutils",
- "liblog",
],
compile_multilib: "32",
diff --git a/media/libstagefright/data/media_codecs_google_c2_video.xml b/media/libstagefright/data/media_codecs_google_c2_video.xml
index e20174f..f785bfa 100644
--- a/media/libstagefright/data/media_codecs_google_c2_video.xml
+++ b/media/libstagefright/data/media_codecs_google_c2_video.xml
@@ -115,6 +115,9 @@
<Limit name="block-count" range="1-4096" /> <!-- max 512x512 -->
<Limit name="blocks-per-second" range="1-122880" />
<Limit name="bitrate" range="1-10000000" />
+ <Limit name="complexity" range="0-10" default="0" />
+ <Limit name="quality" range="0-100" default="80" />
+ <Feature name="bitrate-modes" value="VBR,CBR,CQ" />
</MediaCodec>
<MediaCodec name="c2.android.mpeg4.encoder" type="video/mp4v-es">
<Alias name="OMX.google.mpeg4.encoder" />
diff --git a/media/libstagefright/httplive/M3UParser.cpp b/media/libstagefright/httplive/M3UParser.cpp
index b2361b8..cb97a3c 100644
--- a/media/libstagefright/httplive/M3UParser.cpp
+++ b/media/libstagefright/httplive/M3UParser.cpp
@@ -1397,6 +1397,18 @@
case 'ulaw':
case 'vdva':
case 'ac-4':
+ case 'Opus':
+ case 'a3ds':
+ case 'dts+':
+ case 'dts-':
+ case 'dtsx':
+ case 'dtsy':
+ case 'ec+3':
+ case 'mha1':
+ case 'mha2':
+ case 'mhm1':
+ case 'mhm2':
+ case 'sevs':
return !strcmp("audio", type);
case 'avc1':
@@ -1445,6 +1457,35 @@
case 'tga ':
case 'tiff':
case 'WRLE':
+ case 'a3d1':
+ case 'a3d2':
+ case 'a3d3':
+ case 'a3d4':
+ case 'avc3':
+ case 'avc4':
+ case 'dva1':
+ case 'dvav':
+ case 'dvh1':
+ case 'dvhe':
+ case 'hev1':
+ case 'hev2':
+ case 'hvc1':
+ case 'hvc2':
+ case 'hvt1':
+ case 'lhe1':
+ case 'lht1':
+ case 'lhv1':
+ case 'mjpg':
+ case 'mvc3':
+ case 'mvc4':
+ case 'mvd1':
+ case 'mvd2':
+ case 'mvd3':
+ case 'mvd4':
+ case 'rv60':
+ case 'svc2':
+ case 'vp08':
+ case 'vp09':
return !strcmp("video", type);
default:
diff --git a/media/libstagefright/httplive/PlaylistFetcher.cpp b/media/libstagefright/httplive/PlaylistFetcher.cpp
index d153598..c62c2cd 100644
--- a/media/libstagefright/httplive/PlaylistFetcher.cpp
+++ b/media/libstagefright/httplive/PlaylistFetcher.cpp
@@ -2125,7 +2125,10 @@
size_t offset = 0;
while (offset < buffer->size()) {
const uint8_t *adtsHeader = buffer->data() + offset;
- CHECK_LT(offset + 5, buffer->size());
+ if (buffer->size() <= offset+5) {
+ ALOGV("buffer does not contain a complete header");
+ return ERROR_MALFORMED;
+ }
// non-const pointer for decryption if needed
uint8_t *adtsFrame = buffer->data() + offset;
diff --git a/media/libstagefright/include/media/stagefright/ACodec.h b/media/libstagefright/include/media/stagefright/ACodec.h
index 9d46d2d..784fd36 100644
--- a/media/libstagefright/include/media/stagefright/ACodec.h
+++ b/media/libstagefright/include/media/stagefright/ACodec.h
@@ -286,7 +286,7 @@
double mFps;
double mCaptureFps;
bool mCreateInputBuffersSuspended;
- uint32_t mLatency;
+ std::optional<uint32_t> mLatency;
bool mTunneled;
diff --git a/media/libstagefright/include/media/stagefright/AudioSource.h b/media/libstagefright/include/media/stagefright/AudioSource.h
index 18e5f10..af04dad 100644
--- a/media/libstagefright/include/media/stagefright/AudioSource.h
+++ b/media/libstagefright/include/media/stagefright/AudioSource.h
@@ -70,8 +70,8 @@
status_t removeAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback);
status_t getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones);
- status_t setMicrophoneDirection(audio_microphone_direction_t direction);
- status_t setMicrophoneFieldDimension(float zoom);
+ status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction);
+ status_t setPreferredMicrophoneFieldDimension(float zoom);
status_t getPortId(audio_port_handle_t *portId) const;
diff --git a/media/libstagefright/include/media/stagefright/MPEG4Writer.h b/media/libstagefright/include/media/stagefright/MPEG4Writer.h
index 803155d..6f19023 100644
--- a/media/libstagefright/include/media/stagefright/MPEG4Writer.h
+++ b/media/libstagefright/include/media/stagefright/MPEG4Writer.h
@@ -82,10 +82,6 @@
kWhatSwitch = 'swch',
};
- enum {
- kMaxCttsOffsetTimeUs = 1000000LL, // 1 second
- };
-
int mFd;
int mNextFd;
sp<MetaData> mStartMeta;
diff --git a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
index 2dca5c3..8b6944b 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
@@ -772,6 +772,7 @@
constexpr char KEY_LANGUAGE[] = "language";
constexpr char KEY_LATENCY[] = "latency";
constexpr char KEY_LEVEL[] = "level";
+constexpr char KEY_MAX_B_FRAMES[] = "max-bframes";
constexpr char KEY_MAX_BIT_RATE[] = "max-bitrate";
constexpr char KEY_MAX_FPS_TO_ENCODER[] = "max-fps-to-encoder";
constexpr char KEY_MAX_HEIGHT[] = "max-height";
diff --git a/media/libstagefright/include/media/stagefright/MetaDataBase.h b/media/libstagefright/include/media/stagefright/MetaDataBase.h
index a0407af..8dc2dd5 100644
--- a/media/libstagefright/include/media/stagefright/MetaDataBase.h
+++ b/media/libstagefright/include/media/stagefright/MetaDataBase.h
@@ -62,12 +62,9 @@
kKeyAV1C = 'av1c', // raw data
kKeyThumbnailHVCC = 'thvc', // raw data
kKeyD263 = 'd263', // raw data
- kKeyVorbisInfo = 'vinf', // raw data
- kKeyVorbisBooks = 'vboo', // raw data
kKeyOpusHeader = 'ohdr', // raw data
kKeyOpusCodecDelay = 'ocod', // uint64_t (codec delay in ns)
kKeyOpusSeekPreRoll = 'ospr', // uint64_t (seek preroll in ns)
- kKeyFlacMetadata = 'flMd', // raw data
kKeyVp9CodecPrivate = 'vp9p', // raw data (vp9 csd information)
kKeyIsSyncFrame = 'sync', // int32_t (bool)
kKeyIsCodecConfig = 'conf', // int32_t (bool)
@@ -234,6 +231,13 @@
// AC-4 AudioPresentationInfo
kKeyAudioPresentationInfo = 'audP', // raw data
+
+ // opaque codec specific data being passed from extractor to codec
+ kKeyOpaqueCSD0 = 'csd0',
+ kKeyOpaqueCSD1 = 'csd1',
+ kKeyOpaqueCSD2 = 'csd2',
+
+ kKeyHapticChannelCount = 'hapC',
};
enum {
diff --git a/media/libstagefright/mpeg2ts/HlsSampleDecryptor.cpp b/media/libstagefright/mpeg2ts/HlsSampleDecryptor.cpp
index e32f676..7d446ab 100644
--- a/media/libstagefright/mpeg2ts/HlsSampleDecryptor.cpp
+++ b/media/libstagefright/mpeg2ts/HlsSampleDecryptor.cpp
@@ -149,6 +149,11 @@
}
// ADTS header is included in the size
+ if (size < adtsHdrSize) {
+ ALOGV("processAAC: size (%zu) < adtsHdrSize (%zu)", size, adtsHdrSize);
+ android_errorWriteLog(0x534e4554, "128433933");
+ return;
+ }
size_t offset = adtsHdrSize;
size_t remainingBytes = size - adtsHdrSize;
diff --git a/media/libstagefright/omx/Android.bp b/media/libstagefright/omx/Android.bp
index 4383004..b959f6c 100644
--- a/media/libstagefright/omx/Android.bp
+++ b/media/libstagefright/omx/Android.bp
@@ -11,11 +11,6 @@
"OMXNodeInstance.cpp",
"OMXUtils.cpp",
"OmxGraphicBufferSource.cpp",
- "SimpleSoftOMXComponent.cpp",
- "SoftOMXComponent.cpp",
- "SoftOMXPlugin.cpp",
- "SoftVideoDecoderOMXComponent.cpp",
- "SoftVideoEncoderOMXComponent.cpp",
"1.0/Omx.cpp",
"1.0/OmxStore.cpp",
"1.0/WGraphicBufferSource.cpp",
@@ -56,6 +51,7 @@
"libvndksupport",
"android.hardware.media.omx@1.0",
"android.hardware.graphics.bufferqueue@1.0",
+ "libstagefright_omx_soft",
],
export_shared_lib_headers: [
@@ -81,6 +77,64 @@
},
}
+cc_defaults {
+ name: "omx_soft_libs",
+ shared_libs: [
+ "libutils",
+ "liblog",
+ "libstagefright_foundation",
+ "libstagefright_omx_soft",
+ ],
+}
+
+cc_library_shared {
+ name: "libstagefright_omx_soft",
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
+
+ srcs: [
+ "SimpleSoftOMXComponent.cpp",
+ "SoftOMXComponent.cpp",
+ "SoftOMXPlugin.cpp",
+ "SoftVideoDecoderOMXComponent.cpp",
+ "SoftVideoEncoderOMXComponent.cpp",
+ ],
+
+ export_include_dirs: [
+ "include",
+ ],
+
+ shared_libs: [
+ "libutils",
+ "liblog",
+ "libui",
+ "libstagefright_foundation",
+ ],
+
+ export_shared_lib_headers: [
+ "libstagefright_foundation",
+ "libutils",
+ "liblog",
+ ],
+
+ cflags: [
+ "-Werror",
+ "-Wall",
+ "-Wno-unused-parameter",
+ "-Wno-documentation",
+ ],
+
+ sanitize: {
+ misc_undefined: [
+ "signed-integer-overflow",
+ "unsigned-integer-overflow",
+ ],
+ cfi: true,
+ },
+}
+
cc_library_shared {
name: "libstagefright_omx_utils",
vendor_available: true,
diff --git a/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp b/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
index 2fbbb44..d75acda 100644
--- a/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
+++ b/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
@@ -559,7 +559,7 @@
if (nativeMeta.nFenceFd >= 0) {
sp<Fence> fence = new Fence(nativeMeta.nFenceFd);
nativeMeta.nFenceFd = -1;
- status_t err = fence->wait(IOMX::kFenceTimeoutMs);
+ status_t err = fence->wait(kFenceTimeoutMs);
if (err != OK) {
ALOGE("Timed out waiting on input fence");
return NULL;
diff --git a/media/libstagefright/omx/include/media/stagefright/omx/SoftOMXComponent.h b/media/libstagefright/omx/include/media/stagefright/omx/SoftOMXComponent.h
index 3ab6f88..79f0c77 100644
--- a/media/libstagefright/omx/include/media/stagefright/omx/SoftOMXComponent.h
+++ b/media/libstagefright/omx/include/media/stagefright/omx/SoftOMXComponent.h
@@ -21,12 +21,15 @@
#include <media/stagefright/foundation/ABase.h>
#include <media/stagefright/foundation/AString.h>
#include <utils/RefBase.h>
-
+#include <utils/Log.h>
#include <OMX_Component.h>
namespace android {
struct SoftOMXComponent : public RefBase {
+ enum {
+ kFenceTimeoutMs = 1000
+ };
SoftOMXComponent(
const char *name,
const OMX_CALLBACKTYPE *callbacks,
diff --git a/media/libstagefright/omx/include/media/stagefright/omx/SoftVideoDecoderOMXComponent.h b/media/libstagefright/omx/include/media/stagefright/omx/SoftVideoDecoderOMXComponent.h
index 3b381ce..d7c1658 100644
--- a/media/libstagefright/omx/include/media/stagefright/omx/SoftVideoDecoderOMXComponent.h
+++ b/media/libstagefright/omx/include/media/stagefright/omx/SoftVideoDecoderOMXComponent.h
@@ -23,7 +23,10 @@
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/AHandlerReflector.h>
#include <media/stagefright/foundation/ColorUtils.h>
-#include <media/IOMX.h>
+#include <media/openmax/OMX_Core.h>
+#include <media/openmax/OMX_Video.h>
+#include <media/openmax/OMX_VideoExt.h>
+
#include <media/hardware/HardwareAPI.h>
#include <utils/RefBase.h>
diff --git a/media/libstagefright/omx/include/media/stagefright/omx/SoftVideoEncoderOMXComponent.h b/media/libstagefright/omx/include/media/stagefright/omx/SoftVideoEncoderOMXComponent.h
index 2d6f31b..9cb72dd 100644
--- a/media/libstagefright/omx/include/media/stagefright/omx/SoftVideoEncoderOMXComponent.h
+++ b/media/libstagefright/omx/include/media/stagefright/omx/SoftVideoEncoderOMXComponent.h
@@ -18,7 +18,9 @@
#define SOFT_VIDEO_ENCODER_OMX_COMPONENT_H_
-#include <media/IOMX.h>
+#include <media/openmax/OMX_Core.h>
+#include <media/openmax/OMX_Video.h>
+#include <media/openmax/OMX_VideoExt.h>
#include "SimpleSoftOMXComponent.h"
diff --git a/media/libstagefright/webm/WebmWriter.cpp b/media/libstagefright/webm/WebmWriter.cpp
index b0a303e..26e0884 100644
--- a/media/libstagefright/webm/WebmWriter.cpp
+++ b/media/libstagefright/webm/WebmWriter.cpp
@@ -177,8 +177,8 @@
const void *headerData3;
size_t headerSize1, headerSize2 = sizeof(headerData2), headerSize3;
- if (!md->findData(kKeyVorbisInfo, &type, &headerData1, &headerSize1)
- || !md->findData(kKeyVorbisBooks, &type, &headerData3, &headerSize3)) {
+ if (!md->findData(kKeyOpaqueCSD0, &type, &headerData1, &headerSize1)
+ || !md->findData(kKeyOpaqueCSD1, &type, &headerData3, &headerSize3)) {
ALOGE("Missing header format keys for vorbis track");
md->dumpToLog();
return NULL;
diff --git a/media/libstagefright/xmlparser/Android.bp b/media/libstagefright/xmlparser/Android.bp
index bebfb3b..202e964 100644
--- a/media/libstagefright/xmlparser/Android.bp
+++ b/media/libstagefright/xmlparser/Android.bp
@@ -46,3 +46,9 @@
}
+xsd_config {
+ name: "media_codecs",
+ srcs: ["media_codecs.xsd"],
+ package_name: "media.codecs",
+}
+
diff --git a/media/libstagefright/xmlparser/api/current.txt b/media/libstagefright/xmlparser/api/current.txt
new file mode 100644
index 0000000..5443f2c
--- /dev/null
+++ b/media/libstagefright/xmlparser/api/current.txt
@@ -0,0 +1,138 @@
+// Signature format: 2.0
+package media.codecs {
+
+ public class Alias {
+ ctor public Alias();
+ method public String getName();
+ method public void setName(String);
+ }
+
+ public class Decoders {
+ ctor public Decoders();
+ method public java.util.List<media.codecs.MediaCodec> getMediaCodec();
+ }
+
+ public class Encoders {
+ ctor public Encoders();
+ method public java.util.List<media.codecs.MediaCodec> getMediaCodec();
+ }
+
+ public class Feature {
+ ctor public Feature();
+ method public String getName();
+ method public String getOptional();
+ method public String getRequired();
+ method public String getValue();
+ method public void setName(String);
+ method public void setOptional(String);
+ method public void setRequired(String);
+ method public void setValue(String);
+ }
+
+ public class Include {
+ ctor public Include();
+ method public String getHref();
+ method public void setHref(String);
+ }
+
+ public class Included {
+ ctor public Included();
+ method public media.codecs.Decoders getDecoders_optional();
+ method public media.codecs.Encoders getEncoders_optional();
+ method public java.util.List<media.codecs.Include> getInclude_optional();
+ method public media.codecs.Settings getSettings_optional();
+ method public void setDecoders_optional(media.codecs.Decoders);
+ method public void setEncoders_optional(media.codecs.Encoders);
+ method public void setSettings_optional(media.codecs.Settings);
+ }
+
+ public class Limit {
+ ctor public Limit();
+ method public String getIn();
+ method public String getMax();
+ method public String getMin();
+ method public String getName();
+ method public String getRange();
+ method public String getRanges();
+ method public String getScale();
+ method public String getValue();
+ method public String get_default();
+ method public void setIn(String);
+ method public void setMax(String);
+ method public void setMin(String);
+ method public void setName(String);
+ method public void setRange(String);
+ method public void setRanges(String);
+ method public void setScale(String);
+ method public void setValue(String);
+ method public void set_default(String);
+ }
+
+ public class MediaCodec {
+ ctor public MediaCodec();
+ method public java.util.List<media.codecs.Alias> getAlias_optional();
+ method public java.util.List<media.codecs.Feature> getFeature_optional();
+ method public java.util.List<media.codecs.Limit> getLimit_optional();
+ method public String getName();
+ method public java.util.List<media.codecs.Quirk> getQuirk_optional();
+ method public String getType();
+ method public java.util.List<media.codecs.Type> getType_optional();
+ method public String getUpdate();
+ method public void setName(String);
+ method public void setType(String);
+ method public void setUpdate(String);
+ }
+
+ public class MediaCodecs {
+ ctor public MediaCodecs();
+ method public media.codecs.Decoders getDecoders_optional();
+ method public media.codecs.Encoders getEncoders_optional();
+ method public java.util.List<media.codecs.Include> getInclude_optional();
+ method public media.codecs.Settings getSettings_optional();
+ method public void setDecoders_optional(media.codecs.Decoders);
+ method public void setEncoders_optional(media.codecs.Encoders);
+ method public void setSettings_optional(media.codecs.Settings);
+ }
+
+ public class Quirk {
+ ctor public Quirk();
+ method public String getName();
+ method public void setName(String);
+ }
+
+ public class Setting {
+ ctor public Setting();
+ method public String getName();
+ method public String getUpdate();
+ method public String getValue();
+ method public void setName(String);
+ method public void setUpdate(String);
+ method public void setValue(String);
+ }
+
+ public class Settings {
+ ctor public Settings();
+ method public java.util.List<media.codecs.Setting> getSetting();
+ }
+
+ public class Type {
+ ctor public Type();
+ method public java.util.List<media.codecs.Alias> getAlias();
+ method public java.util.List<media.codecs.Feature> getFeature();
+ method public java.util.List<media.codecs.Limit> getLimit();
+ method public String getName();
+ method public String getUpdate();
+ method public void setName(String);
+ method public void setUpdate(String);
+ }
+
+ public class XmlParser {
+ ctor public XmlParser();
+ method public static media.codecs.Included readIncluded(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ method public static media.codecs.MediaCodecs readMediaCodecs(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ method public static String readText(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ method public static void skip(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ }
+
+}
+
diff --git a/media/libstagefright/xmlparser/api/last_current.txt b/media/libstagefright/xmlparser/api/last_current.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/media/libstagefright/xmlparser/api/last_current.txt
diff --git a/media/libstagefright/xmlparser/api/last_removed.txt b/media/libstagefright/xmlparser/api/last_removed.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/media/libstagefright/xmlparser/api/last_removed.txt
diff --git a/media/libstagefright/xmlparser/api/removed.txt b/media/libstagefright/xmlparser/api/removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/media/libstagefright/xmlparser/api/removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/media/libstagefright/xmlparser/media_codecs.xsd b/media/libstagefright/xmlparser/media_codecs.xsd
new file mode 100644
index 0000000..77193a2
--- /dev/null
+++ b/media/libstagefright/xmlparser/media_codecs.xsd
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2019 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.
+-->
+<!-- TODO: define a targetNamespace. Note that it will break retrocompatibility -->
+<xs:schema version="2.0"
+ elementFormDefault="qualified"
+ attributeFormDefault="unqualified"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:element name="MediaCodecs">
+ <xs:complexType>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="Include" type="Include" maxOccurs="unbounded"/>
+ <xs:element name="Settings" type="Settings"/>
+ <xs:element name="Decoders" type="Decoders"/>
+ <xs:element name="Encoders" type="Encoders"/>
+ </xs:choice>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Included">
+ <xs:complexType>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="Include" type="Include" maxOccurs="unbounded"/>
+ <xs:element name="Settings" type="Settings"/>
+ <xs:element name="Decoders" type="Decoders"/>
+ <xs:element name="Encoders" type="Encoders"/>
+ </xs:choice>
+ </xs:complexType>
+ </xs:element>
+ <xs:complexType name="Decoders">
+ <xs:sequence>
+ <xs:element name="MediaCodec" type="MediaCodec" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="Encoders">
+ <xs:sequence>
+ <xs:element name="MediaCodec" type="MediaCodec" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="Settings">
+ <xs:sequence>
+ <xs:element name="Setting" type="Setting" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="MediaCodec">
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="Quirk" type="Quirk" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="Type" type="Type" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="Alias" type="Alias" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="Limit" type="Limit" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="Feature" type="Feature" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:choice>
+ <xs:attribute name="name" type="xs:string"/>
+ <xs:attribute name="type" type="xs:string"/>
+ <xs:attribute name="update" type="xs:string"/>
+ </xs:complexType>
+ <xs:complexType name="Quirk">
+ <xs:attribute name="name" type="xs:string"/>
+ </xs:complexType>
+ <xs:complexType name="Type">
+ <xs:sequence>
+ <xs:element name="Alias" type="Alias" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="Limit" type="Limit" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="Feature" type="Feature" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:string"/>
+ <xs:attribute name="update" type="xs:string"/>
+ </xs:complexType>
+ <xs:complexType name="Alias">
+ <xs:attribute name="name" type="xs:string"/>
+ </xs:complexType>
+ <xs:complexType name="Limit">
+ <xs:attribute name="name" type="xs:string"/>
+ <xs:attribute name="default" type="xs:string"/>
+ <xs:attribute name="in" type="xs:string"/>
+ <xs:attribute name="max" type="xs:string"/>
+ <xs:attribute name="min" type="xs:string"/>
+ <xs:attribute name="range" type="xs:string"/>
+ <xs:attribute name="ranges" type="xs:string"/>
+ <xs:attribute name="scale" type="xs:string"/>
+ <xs:attribute name="value" type="xs:string"/>
+ </xs:complexType>
+ <xs:complexType name="Feature">
+ <xs:attribute name="name" type="xs:string"/>
+ <xs:attribute name="optional" type="xs:string"/>
+ <xs:attribute name="required" type="xs:string"/>
+ <xs:attribute name="value" type="xs:string"/>
+ </xs:complexType>
+ <xs:complexType name="Setting">
+ <xs:attribute name="name" type="xs:string"/>
+ <xs:attribute name="value" type="xs:string"/>
+ <xs:attribute name="update" type="xs:string"/>
+ </xs:complexType>
+ <xs:complexType name="Include">
+ <xs:attribute name="href" type="xs:string"/>
+ </xs:complexType>
+</xs:schema>
diff --git a/media/mediaserver/Android.bp b/media/mediaserver/Android.bp
index 8377723..6a1cc71 100644
--- a/media/mediaserver/Android.bp
+++ b/media/mediaserver/Android.bp
@@ -25,7 +25,6 @@
],
static_libs: [
- "libicuandroid_utils",
"libregistermsext",
],
diff --git a/media/mediaserver/main_mediaserver.cpp b/media/mediaserver/main_mediaserver.cpp
index ecddc48..7b22b05 100644
--- a/media/mediaserver/main_mediaserver.cpp
+++ b/media/mediaserver/main_mediaserver.cpp
@@ -18,6 +18,7 @@
#define LOG_TAG "mediaserver"
//#define LOG_NDEBUG 0
+#include <aicu/AIcu.h>
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
@@ -25,7 +26,6 @@
#include "RegisterExtensions.h"
// from LOCAL_C_INCLUDES
-#include "IcuUtils.h"
#include "MediaPlayerService.h"
#include "ResourceManagerService.h"
@@ -38,7 +38,7 @@
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm(defaultServiceManager());
ALOGI("ServiceManager: %p", sm.get());
- InitializeIcuOrDie();
+ AIcu_initializeIcuOrDie();
MediaPlayerService::instantiate();
ResourceManagerService::instantiate();
registerExtensions();
diff --git a/media/mediaserver/mediaserver.rc b/media/mediaserver/mediaserver.rc
index 8cfcd79..f6c325c 100644
--- a/media/mediaserver/mediaserver.rc
+++ b/media/mediaserver/mediaserver.rc
@@ -2,7 +2,5 @@
class main
user media
group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm
- # TODO(b/123275379): Remove updatable when http://aosp/878198 has landed
- updatable
ioprio rt 4
writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks
diff --git a/media/ndk/Android.bp b/media/ndk/Android.bp
index f9f1acc..a4f5730 100644
--- a/media/ndk/Android.bp
+++ b/media/ndk/Android.bp
@@ -73,6 +73,7 @@
shared_libs: [
"android.hardware.graphics.bufferqueue@1.0",
"android.hidl.token@1.0-utils",
+ "libandroid_runtime_lazy",
"libbinder",
"libmedia",
"libmedia_omx",
@@ -93,14 +94,12 @@
"libmediandk_utils",
],
- required: [
- // libmediandk may be used by Java and non-Java things. When lower-level things use it,
- // they shouldn't have to take on the cost of loading libandroid_runtime.
- "libandroid_runtime",
- ],
-
export_include_dirs: ["include"],
+ export_shared_lib_headers: [
+ "libgui",
+ ],
+
product_variables: {
pdk: {
enabled: false,
diff --git a/media/ndk/NdkImageReader.cpp b/media/ndk/NdkImageReader.cpp
index bcc7ff3..22e15d3 100644
--- a/media/ndk/NdkImageReader.cpp
+++ b/media/ndk/NdkImageReader.cpp
@@ -21,6 +21,7 @@
#include "NdkImagePriv.h"
#include "NdkImageReaderPriv.h"
+#include <private/media/NdkImage.h>
#include <cutils/atomic.h>
#include <utils/Log.h>
@@ -63,6 +64,7 @@
case AIMAGE_FORMAT_YUV_420_888:
case AIMAGE_FORMAT_JPEG:
case AIMAGE_FORMAT_RAW16:
+ case AIMAGE_FORMAT_RAW_DEPTH:
case AIMAGE_FORMAT_RAW_PRIVATE:
case AIMAGE_FORMAT_RAW10:
case AIMAGE_FORMAT_RAW12:
@@ -92,6 +94,7 @@
case AIMAGE_FORMAT_RGBA_FP16:
case AIMAGE_FORMAT_JPEG:
case AIMAGE_FORMAT_RAW16:
+ case AIMAGE_FORMAT_RAW_DEPTH:
case AIMAGE_FORMAT_RAW_PRIVATE:
case AIMAGE_FORMAT_RAW10:
case AIMAGE_FORMAT_RAW12:
diff --git a/media/ndk/NdkMediaDataSource.cpp b/media/ndk/NdkMediaDataSource.cpp
index 0891f2a..7979c2f 100644
--- a/media/ndk/NdkMediaDataSource.cpp
+++ b/media/ndk/NdkMediaDataSource.cpp
@@ -23,7 +23,8 @@
#include <jni.h>
#include <unistd.h>
-#include <binder/IBinder.h>
+#include <android_runtime/AndroidRuntime.h>
+#include <android_util_Binder.h>
#include <cutils/properties.h>
#include <utils/Log.h>
#include <utils/StrongPointer.h>
@@ -39,67 +40,9 @@
#include "../../libstagefright/include/NuCachedSource2.h"
#include "NdkMediaDataSourceCallbacksPriv.h"
-#include <mutex> // std::call_once,once_flag
-#include <dlfcn.h> // dlopen
using namespace android;
-// load libandroid_runtime.so lazily.
-// A vendor process may use libmediandk but should not depend on libandroid_runtime.
-// TODO(jooyung): remove duplicate (b/125550121)
-// frameworks/native/libs/binder/ndk/ibinder_jni.cpp
-namespace {
-
-typedef JNIEnv* (*getJNIEnv_t)();
-typedef sp<IBinder> (*ibinderForJavaObject_t)(JNIEnv* env, jobject obj);
-
-getJNIEnv_t getJNIEnv_;
-ibinderForJavaObject_t ibinderForJavaObject_;
-
-std::once_flag mLoadFlag;
-
-void load() {
- std::call_once(mLoadFlag, []() {
- void* handle = dlopen("libandroid_runtime.so", RTLD_LAZY);
- if (handle == nullptr) {
- ALOGE("Could not open libandroid_runtime.");
- return;
- }
-
- getJNIEnv_ = reinterpret_cast<getJNIEnv_t>(
- dlsym(handle, "_ZN7android14AndroidRuntime9getJNIEnvEv"));
- if (getJNIEnv_ == nullptr) {
- ALOGE("Could not find AndroidRuntime::getJNIEnv.");
- // no return
- }
-
- ibinderForJavaObject_ = reinterpret_cast<ibinderForJavaObject_t>(
- dlsym(handle, "_ZN7android20ibinderForJavaObjectEP7_JNIEnvP8_jobject"));
- if (ibinderForJavaObject_ == nullptr) {
- ALOGE("Could not find ibinderForJavaObject.");
- // no return
- }
- });
-}
-
-JNIEnv* getJNIEnv() {
- load();
- if (getJNIEnv_ == nullptr) {
- return nullptr;
- }
- return (getJNIEnv_)();
-}
-
-sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj) {
- load();
- if (ibinderForJavaObject_ == nullptr) {
- return nullptr;
- }
- return (ibinderForJavaObject_)(env, obj);
-}
-
-} // namespace
-
struct AMediaDataSource {
void *userdata;
AMediaDataSourceReadAt readAt;
@@ -181,14 +124,9 @@
if (obj == NULL) {
return NULL;
}
- sp<IBinder> binder;
switch (version) {
case 1:
- binder = ibinderForJavaObject(env, obj);
- if (binder == NULL) {
- return NULL;
- }
- return interface_cast<IMediaHTTPService>(binder);
+ return interface_cast<IMediaHTTPService>(ibinderForJavaObject(env, obj));
case 2:
return new JMedia2HTTPService(env, obj);
default:
@@ -241,7 +179,7 @@
switch (version) {
case 1:
- env = getJNIEnv();
+ env = AndroidRuntime::getJNIEnv();
clazz = "android/media/MediaHTTPService";
method = "createHttpServiceBinderIfNecessary";
signature = "(Ljava/lang/String;)Landroid/os/IBinder;";
diff --git a/media/ndk/NdkMediaFormat.cpp b/media/ndk/NdkMediaFormat.cpp
index 768a7a9..51138c8 100644
--- a/media/ndk/NdkMediaFormat.cpp
+++ b/media/ndk/NdkMediaFormat.cpp
@@ -324,6 +324,7 @@
EXPORT const char* AMEDIAFORMAT_KEY_GENRE = "genre";
EXPORT const char* AMEDIAFORMAT_KEY_GRID_COLUMNS = "grid-cols";
EXPORT const char* AMEDIAFORMAT_KEY_GRID_ROWS = "grid-rows";
+EXPORT const char* AMEDIAFORMAT_KEY_HAPTIC_CHANNEL_COUNT = "haptic-channel-count";
EXPORT const char* AMEDIAFORMAT_KEY_HDR_STATIC_INFO = "hdr-static-info";
EXPORT const char* AMEDIAFORMAT_KEY_HDR10_PLUS_INFO = "hdr10-plus-info";
EXPORT const char* AMEDIAFORMAT_KEY_HEIGHT = "height";
@@ -371,6 +372,7 @@
EXPORT const char* AMEDIAFORMAT_KEY_TEMPORAL_LAYER_ID = "temporal-layer-id";
EXPORT const char* AMEDIAFORMAT_KEY_TEMPORAL_LAYERING = "ts-schema";
EXPORT const char* AMEDIAFORMAT_KEY_TEXT_FORMAT_DATA = "text-format-data";
+EXPORT const char* AMEDIAFORMAT_KEY_THUMBNAIL_CSD_HEVC = "thumbnail-csd-hevc";
EXPORT const char* AMEDIAFORMAT_KEY_THUMBNAIL_HEIGHT = "thumbnail-height";
EXPORT const char* AMEDIAFORMAT_KEY_THUMBNAIL_TIME = "thumbnail-time";
EXPORT const char* AMEDIAFORMAT_KEY_THUMBNAIL_WIDTH = "thumbnail-width";
diff --git a/media/ndk/include/media/NdkMediaFormat.h b/media/ndk/include/media/NdkMediaFormat.h
index 56bcaab..fd43f36 100644
--- a/media/ndk/include/media/NdkMediaFormat.h
+++ b/media/ndk/include/media/NdkMediaFormat.h
@@ -209,6 +209,7 @@
extern const char* AMEDIAFORMAT_KEY_EXIF_SIZE __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_FRAME_COUNT __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_GENRE __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_HAPTIC_CHANNEL_COUNT __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_ICC_PROFILE __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_IS_SYNC_FRAME __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_LOCATION __INTRODUCED_IN(29);
@@ -226,6 +227,7 @@
extern const char* AMEDIAFORMAT_KEY_TARGET_TIME __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_TEMPORAL_LAYER_COUNT __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_TEXT_FORMAT_DATA __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_THUMBNAIL_CSD_HEVC __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_THUMBNAIL_HEIGHT __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_THUMBNAIL_TIME __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_THUMBNAIL_WIDTH __INTRODUCED_IN(29);
diff --git a/media/ndk/include/private/media/NdkImage.h b/media/ndk/include/private/media/NdkImage.h
new file mode 100644
index 0000000..4368a56
--- /dev/null
+++ b/media/ndk/include/private/media/NdkImage.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2019 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 _PRIVATE_MEDIA_NDKIMAGE_H_
+#define _PRIVATE_MEDIA_NDKIMAGE_H_
+// Formats not listed in the public API, but still available to AImageReader
+enum AIMAGE_PRIVATE_FORMATS {
+ /**
+ * Unprocessed implementation-dependent raw
+ * depth measurements, opaque with 16 bit
+ * samples.
+ *
+ */
+
+ AIMAGE_FORMAT_RAW_DEPTH = 0x1002,
+};
+#endif // _PRIVATE_MEDIA_NDKIMAGE
diff --git a/media/ndk/libmediandk.map.txt b/media/ndk/libmediandk.map.txt
index 9756926..f666ad0 100644
--- a/media/ndk/libmediandk.map.txt
+++ b/media/ndk/libmediandk.map.txt
@@ -89,6 +89,7 @@
AMEDIAFORMAT_KEY_GENRE; # var introduced=29
AMEDIAFORMAT_KEY_GRID_COLUMNS; # var introduced=28
AMEDIAFORMAT_KEY_GRID_ROWS; # var introduced=28
+ AMEDIAFORMAT_KEY_HAPTIC_CHANNEL_COUNT; # var introduced=29
AMEDIAFORMAT_KEY_HDR_STATIC_INFO; # var introduced=28
AMEDIAFORMAT_KEY_HEIGHT; # var introduced=21
AMEDIAFORMAT_KEY_ICC_PROFILE; # var introduced=29
@@ -135,6 +136,7 @@
AMEDIAFORMAT_KEY_TEMPORAL_LAYER_ID; # var introduced=28
AMEDIAFORMAT_KEY_TEMPORAL_LAYERING; # var introduced=28
AMEDIAFORMAT_KEY_TEXT_FORMAT_DATA; # var introduced=29
+ AMEDIAFORMAT_KEY_THUMBNAIL_CSD_HEVC; # var introduced=29
AMEDIAFORMAT_KEY_THUMBNAIL_HEIGHT; # var introduced=29
AMEDIAFORMAT_KEY_THUMBNAIL_TIME; # var introduced=29
AMEDIAFORMAT_KEY_THUMBNAIL_WIDTH; # var introduced=29
diff --git a/media/ndk/tests/AImageReaderWindowHandleTest.cpp b/media/ndk/tests/AImageReaderWindowHandleTest.cpp
index ef0ff67..5b65064 100644
--- a/media/ndk/tests/AImageReaderWindowHandleTest.cpp
+++ b/media/ndk/tests/AImageReaderWindowHandleTest.cpp
@@ -17,6 +17,7 @@
#include <gtest/gtest.h>
#include <media/NdkImageReader.h>
#include <media/NdkImage.h>
+#include <private/media/NdkImage.h>
#include <mediautils/AImageReaderUtils.h>
#include <gui/IGraphicBufferProducer.h>
#include <gui/bufferqueue/1.0/H2BGraphicBufferProducer.h>
@@ -26,6 +27,8 @@
namespace android {
+using HGraphicBufferProducer = hardware::graphics::bufferqueue::V1_0::
+ IGraphicBufferProducer;
using hardware::graphics::bufferqueue::V1_0::utils::H2BGraphicBufferProducer;
using aimg::AImageReader_getHGBPFromHandle;
@@ -182,4 +185,25 @@
EXPECT_TRUE(imageAvailable_) << "Timed out waiting for image data to be handled!\n";
}
+class AImageReaderPrivateFormatTest : public ::testing::Test {
+ public:
+ void SetUp() override {
+ auto status = AImageReader_new(kImageWidth, kImageHeight, AIMAGE_FORMAT_RAW_DEPTH,
+ kMaxImages, &imgReader);
+ EXPECT_TRUE(status == AMEDIA_OK);
+ }
+
+ void TearDown() override {
+ if (imgReader) {
+ AImageReader_delete(imgReader);
+ }
+ }
+ AImageReader *imgReader = nullptr;
+};
+
+TEST_F(AImageReaderPrivateFormatTest, CreateTest) {
+ EXPECT_TRUE(imgReader != nullptr);
+}
+
+
} // namespace android
diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp
index 2fb24f5..cb681e0 100644
--- a/media/utils/ServiceUtilities.cpp
+++ b/media/utils/ServiceUtilities.cpp
@@ -130,6 +130,14 @@
return ok;
}
+bool captureMediaOutputAllowed(pid_t pid, uid_t uid) {
+ if (isAudioServerOrRootUid(uid)) return true;
+ static const String16 sCaptureMediaOutput("android.permission.CAPTURE_MEDIA_OUTPUT");
+ bool ok = PermissionCache::checkPermission(sCaptureMediaOutput, pid, uid);
+ if (!ok) ALOGE("Request requires android.permission.CAPTURE_MEDIA_OUTPUT");
+ return ok;
+}
+
bool captureHotwordAllowed(pid_t pid, uid_t uid) {
// CAPTURE_AUDIO_HOTWORD permission implies RECORD_AUDIO permission
bool ok = recordingAllowed(String16(""), pid, uid);
diff --git a/media/utils/include/mediautils/ServiceUtilities.h b/media/utils/include/mediautils/ServiceUtilities.h
index 94370ee..9377ff3 100644
--- a/media/utils/include/mediautils/ServiceUtilities.h
+++ b/media/utils/include/mediautils/ServiceUtilities.h
@@ -74,6 +74,7 @@
bool startRecording(const String16& opPackageName, pid_t pid, uid_t uid);
void finishRecording(const String16& opPackageName, uid_t uid);
bool captureAudioOutputAllowed(pid_t pid, uid_t uid);
+bool captureMediaOutputAllowed(pid_t pid, uid_t uid);
bool captureHotwordAllowed(pid_t pid, uid_t uid);
bool settingsAllowed();
bool modifyAudioRoutingAllowed();
diff --git a/services/audioflinger/Android.bp b/services/audioflinger/Android.bp
new file mode 100644
index 0000000..96ad54b
--- /dev/null
+++ b/services/audioflinger/Android.bp
@@ -0,0 +1,73 @@
+
+
+cc_library_shared {
+ name: "libaudioflinger",
+
+ srcs: [
+ "AudioFlinger.cpp",
+ "AudioHwDevice.cpp",
+ "AudioStreamOut.cpp",
+ "AudioWatchdog.cpp",
+ "BufLog.cpp",
+ "Effects.cpp",
+ "FastCapture.cpp",
+ "FastCaptureDumpState.cpp",
+ "FastCaptureState.cpp",
+ "FastMixer.cpp",
+ "FastMixerDumpState.cpp",
+ "FastMixerState.cpp",
+ "FastThread.cpp",
+ "FastThreadDumpState.cpp",
+ "FastThreadState.cpp",
+ "NBAIO_Tee.cpp",
+ "PatchPanel.cpp",
+ "SpdifStreamOut.cpp",
+ "StateQueue.cpp",
+ "Threads.cpp",
+ "Tracks.cpp",
+ "TypedLogger.cpp",
+ ],
+
+ include_dirs: [
+ "frameworks/av/services/audiopolicy",
+ "frameworks/av/services/medialog",
+ ],
+
+ shared_libs: [
+ "libaudiohal",
+ "libaudioprocessing",
+ "libaudiospdif",
+ "libaudioutils",
+ "libcutils",
+ "libutils",
+ "liblog",
+ "libbinder",
+ "libaudioclient",
+ "libmedialogservice",
+ "libmediametrics",
+ "libmediautils",
+ "libnbaio",
+ "libnblog",
+ "libpowermanager",
+ "libmediautils",
+ "libmemunreachable",
+ "libmedia_helper",
+ "libvibrator",
+ ],
+
+ static_libs: [
+ "libcpustats",
+ "libsndfile",
+ ],
+
+ cflags: [
+ "-DSTATE_QUEUE_INSTANTIATIONS=\"StateQueueInstantiations.cpp\"",
+ "-fvisibility=hidden",
+ "-Werror",
+ "-Wall",
+ ],
+ sanitize: {
+ integer_overflow: true,
+ },
+
+}
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
deleted file mode 100644
index 40980a6..0000000
--- a/services/audioflinger/Android.mk
+++ /dev/null
@@ -1,74 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- AudioFlinger.cpp \
- Threads.cpp \
- Tracks.cpp \
- AudioHwDevice.cpp \
- AudioStreamOut.cpp \
- SpdifStreamOut.cpp \
- Effects.cpp \
- PatchPanel.cpp \
- StateQueue.cpp \
- BufLog.cpp \
- TypedLogger.cpp \
- NBAIO_Tee.cpp \
-
-LOCAL_C_INCLUDES := \
- frameworks/av/services/audiopolicy \
- frameworks/av/services/medialog \
- $(call include-path-for, audio-utils)
-
-LOCAL_SHARED_LIBRARIES := \
- libaudiohal \
- libaudioprocessing \
- libaudiospdif \
- libaudioutils \
- libcutils \
- libutils \
- liblog \
- libbinder \
- libaudioclient \
- libmedialogservice \
- libmediametrics \
- libmediautils \
- libnbaio \
- libnblog \
- libpowermanager \
- libmediautils \
- libmemunreachable \
- libmedia_helper \
- libvibrator
-
-LOCAL_STATIC_LIBRARIES := \
- libcpustats \
- libsndfile \
-
-LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
-
-LOCAL_MODULE:= libaudioflinger
-
-LOCAL_SRC_FILES += \
- AudioWatchdog.cpp \
- FastCapture.cpp \
- FastCaptureDumpState.cpp \
- FastCaptureState.cpp \
- FastMixer.cpp \
- FastMixerDumpState.cpp \
- FastMixerState.cpp \
- FastThread.cpp \
- FastThreadDumpState.cpp \
- FastThreadState.cpp
-
-LOCAL_CFLAGS += -DSTATE_QUEUE_INSTANTIATIONS='"StateQueueInstantiations.cpp"'
-
-LOCAL_CFLAGS += -fvisibility=hidden
-
-LOCAL_CFLAGS += -Werror -Wall
-LOCAL_SANITIZE := integer_overflow
-
-include $(BUILD_SHARED_LIBRARY)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 213c9c3..0825cb4 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -224,6 +224,14 @@
// closeOutput_nonvirtual() will remove specified entry from mPlaybackThreads
closeOutput_nonvirtual(mPlaybackThreads.keyAt(0));
}
+ while (!mMmapThreads.isEmpty()) {
+ const audio_io_handle_t io = mMmapThreads.keyAt(0);
+ if (mMmapThreads.valueAt(0)->isOutput()) {
+ closeOutput_nonvirtual(io); // removes entry from mMmapThreads
+ } else {
+ closeInput_nonvirtual(io); // removes entry from mMmapThreads
+ }
+ }
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
// no mHardwareLock needed, as there are no other references to this
@@ -458,15 +466,8 @@
bool AudioFlinger::dumpTryLock(Mutex& mutex)
{
- bool locked = false;
- for (int i = 0; i < kDumpLockRetries; ++i) {
- if (mutex.tryLock() == NO_ERROR) {
- locked = true;
- break;
- }
- usleep(kDumpLockSleepUs);
- }
- return locked;
+ status_t err = mutex.timedLock(kDumpLockTimeoutNs);
+ return err == NO_ERROR;
}
status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
@@ -3208,24 +3209,44 @@
goto Exit;
}
- // check audio settings permission for global effects
- if (sessionId == AUDIO_SESSION_OUTPUT_MIX && !settingsAllowed()) {
- lStatus = PERMISSION_DENIED;
- goto Exit;
- }
-
- // Session AUDIO_SESSION_OUTPUT_STAGE is reserved for output stage effects
- // that can only be created by audio policy manager
- if (sessionId == AUDIO_SESSION_OUTPUT_STAGE && !isAudioServerUid(callingUid)) {
- lStatus = PERMISSION_DENIED;
- goto Exit;
- }
-
if (mEffectsFactoryHal == 0) {
+ ALOGE("%s: no effects factory hal", __func__);
lStatus = NO_INIT;
goto Exit;
}
+ // check audio settings permission for global effects
+ if (sessionId == AUDIO_SESSION_OUTPUT_MIX) {
+ if (!settingsAllowed()) {
+ ALOGE("%s: no permission for AUDIO_SESSION_OUTPUT_MIX", __func__);
+ lStatus = PERMISSION_DENIED;
+ goto Exit;
+ }
+ } else if (sessionId == AUDIO_SESSION_OUTPUT_STAGE) {
+ if (!isAudioServerUid(callingUid)) {
+ ALOGE("%s: only APM can create using AUDIO_SESSION_OUTPUT_STAGE", __func__);
+ lStatus = PERMISSION_DENIED;
+ goto Exit;
+ }
+
+ if (io == AUDIO_IO_HANDLE_NONE) {
+ ALOGE("%s: APM must specify output when using AUDIO_SESSION_OUTPUT_STAGE", __func__);
+ lStatus = BAD_VALUE;
+ goto Exit;
+ }
+ } else {
+ // general sessionId.
+
+ if (audio_unique_id_get_use(sessionId) != AUDIO_UNIQUE_ID_USE_SESSION) {
+ ALOGE("%s: invalid sessionId %d", __func__, sessionId);
+ lStatus = BAD_VALUE;
+ goto Exit;
+ }
+
+ // TODO: should we check if the callingUid (limited to pid) is in mAudioSessionRefs
+ // to prevent creating an effect when one doesn't actually have track with that session?
+ }
+
{
// Get the full effect descriptor from the uuid/type.
// If the session is the output mix, prefer an auxiliary effect,
@@ -3269,41 +3290,36 @@
// output threads.
// If output is 0 here, sessionId is neither SESSION_OUTPUT_STAGE nor SESSION_OUTPUT_MIX
// because of code checking output when entering the function.
- // Note: io is never 0 when creating an effect on an input
+ // Note: io is never AUDIO_IO_HANDLE_NONE when creating an effect on an input by APM.
+ // An AudioEffect created from the Java API will have io as AUDIO_IO_HANDLE_NONE.
if (io == AUDIO_IO_HANDLE_NONE) {
- if (sessionId == AUDIO_SESSION_OUTPUT_STAGE) {
- // output must be specified by AudioPolicyManager when using session
- // AUDIO_SESSION_OUTPUT_STAGE
- lStatus = BAD_VALUE;
+ // look for the thread where the specified audio session is present
+ io = findIoHandleBySessionId_l(sessionId, mPlaybackThreads);
+ if (io == AUDIO_IO_HANDLE_NONE) {
+ io = findIoHandleBySessionId_l(sessionId, mRecordThreads);
+ }
+ if (io == AUDIO_IO_HANDLE_NONE) {
+ io = findIoHandleBySessionId_l(sessionId, mMmapThreads);
+ }
+
+ // If you wish to create a Record preprocessing AudioEffect in Java,
+ // you MUST create an AudioRecord first and keep it alive so it is picked up above.
+ // Otherwise it will fail when created on a Playback thread by legacy
+ // handling below. Ditto with Mmap, the associated Mmap track must be created
+ // before creating the AudioEffect or the io handle must be specified.
+ //
+ // Detect if the effect is created after an AudioRecord is destroyed.
+ if (getOrphanEffectChain_l(sessionId).get() != nullptr) {
+ ALOGE("%s: effect %s with no specified io handle is denied because the AudioRecord"
+ " for session %d no longer exists",
+ __func__, desc.name, sessionId);
+ lStatus = PERMISSION_DENIED;
goto Exit;
}
- // look for the thread where the specified audio session is present
- for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
- uint32_t sessionType = mPlaybackThreads.valueAt(i)->hasAudioSession(sessionId);
- if (sessionType != 0) {
- io = mPlaybackThreads.keyAt(i);
- // thread with same effect session is preferable
- if ((sessionType & ThreadBase::EFFECT_SESSION) != 0) {
- break;
- }
- }
- }
- if (io == AUDIO_IO_HANDLE_NONE) {
- for (size_t i = 0; i < mRecordThreads.size(); i++) {
- if (mRecordThreads.valueAt(i)->hasAudioSession(sessionId) != 0) {
- io = mRecordThreads.keyAt(i);
- break;
- }
- }
- }
- if (io == AUDIO_IO_HANDLE_NONE) {
- for (size_t i = 0; i < mMmapThreads.size(); i++) {
- if (mMmapThreads.valueAt(i)->hasAudioSession(sessionId) != 0) {
- io = mMmapThreads.keyAt(i);
- break;
- }
- }
- }
+
+ // Legacy handling of creating an effect on an expired or made-up
+ // session id. We think that it is a Playback effect.
+ //
// If no output thread contains the requested session ID, default to
// first output. The effect chain will be moved to the correct output
// thread when a track with the same session ID is created
@@ -3311,6 +3327,21 @@
io = mPlaybackThreads.keyAt(0);
}
ALOGV("createEffect() got io %d for effect %s", io, desc.name);
+ } else if (checkPlaybackThread_l(io) != nullptr) {
+ // allow only one effect chain per sessionId on mPlaybackThreads.
+ for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+ const audio_io_handle_t checkIo = mPlaybackThreads.keyAt(i);
+ if (io == checkIo) continue;
+ const uint32_t sessionType =
+ mPlaybackThreads.valueAt(i)->hasAudioSession(sessionId);
+ if ((sessionType & ThreadBase::EFFECT_SESSION) != 0) {
+ ALOGE("%s: effect %s io %d denied because session %d effect exists on io %d",
+ __func__, desc.name, (int)io, (int)sessionId, (int)checkIo);
+ android_errorWriteLog(0x534e4554, "123237974");
+ lStatus = BAD_VALUE;
+ goto Exit;
+ }
+ }
}
ThreadBase *thread = checkRecordThread_l(io);
if (thread == NULL) {
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 1441e15..5a65ea8 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -431,8 +431,7 @@
static uint32_t mScreenState;
// Internal dump utilities.
- static const int kDumpLockRetries = 50;
- static const int kDumpLockSleepUs = 20000;
+ static const int kDumpLockTimeoutNs = 1 * NANOS_PER_SECOND;
static bool dumpTryLock(Mutex& mutex);
void dumpPermissionDenial(int fd, const Vector<String16>& args);
void dumpClients(int fd, const Vector<String16>& args);
@@ -558,6 +557,26 @@
#include "PatchPanel.h"
+ // Find io handle by session id.
+ // Preference is given to an io handle with a matching effect chain to session id.
+ // 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_io_handle_t io = AUDIO_IO_HANDLE_NONE;
+
+ for (size_t i = 0; i < threads.size(); i++) {
+ const uint32_t sessionType = threads.valueAt(i)->hasAudioSession(sessionId);
+ if (sessionType != 0) {
+ io = threads.keyAt(i);
+ if ((sessionType & AudioFlinger::ThreadBase::EFFECT_SESSION) != 0) {
+ break; // effect chain here.
+ }
+ }
+ }
+ return io;
+ }
+
// server side of the client's IAudioTrack
class TrackHandle : public android::BnAudioTrack {
public:
@@ -595,9 +614,9 @@
virtual binder::Status stop();
virtual binder::Status getActiveMicrophones(
std::vector<media::MicrophoneInfo>* activeMicrophones);
- virtual binder::Status setMicrophoneDirection(
+ virtual binder::Status setPreferredMicrophoneDirection(
int /*audio_microphone_direction_t*/ direction);
- virtual binder::Status setMicrophoneFieldDimension(float zoom);
+ virtual binder::Status setPreferredMicrophoneFieldDimension(float zoom);
private:
const sp<RecordThread::RecordTrack> mRecordTrack;
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index ecaeb52..2b34267 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -2335,13 +2335,10 @@
void AudioFlinger::EffectChain::dump(int fd, const Vector<String16>& args)
{
- const size_t SIZE = 256;
- char buffer[SIZE];
String8 result;
- size_t numEffects = mEffects.size();
- snprintf(buffer, SIZE, " %zu effects for session %d\n", numEffects, mSessionId);
- result.append(buffer);
+ const size_t numEffects = mEffects.size();
+ result.appendFormat(" %zu effects for session %d\n", numEffects, mSessionId);
if (numEffects) {
bool locked = AudioFlinger::dumpTryLock(mLock);
@@ -2369,6 +2366,8 @@
if (locked) {
mLock.unlock();
}
+ } else {
+ write(fd, result.string(), result.size());
}
}
diff --git a/services/audioflinger/RecordTracks.h b/services/audioflinger/RecordTracks.h
index ab4af33..ec1f86c 100644
--- a/services/audioflinger/RecordTracks.h
+++ b/services/audioflinger/RecordTracks.h
@@ -71,8 +71,8 @@
status_t getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones);
- status_t setMicrophoneDirection(audio_microphone_direction_t direction);
- status_t setMicrophoneFieldDimension(float zoom);
+ status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction);
+ status_t setPreferredMicrophoneFieldDimension(float zoom);
static bool checkServerLatencySupported(
audio_format_t format, audio_input_flags_t flags) {
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 49f74a2..b51c570 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -786,12 +786,8 @@
}
}
-void AudioFlinger::ThreadBase::dumpBase(int fd, const Vector<String16>& args __unused)
+void AudioFlinger::ThreadBase::dump(int fd, const Vector<String16>& args)
{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
-
dprintf(fd, "\n%s thread %p, name %s, tid %d, type %d (%s):\n", isOutput() ? "Output" : "Input",
this, mThreadName, getTid(), type(), threadTypeToString(type()));
@@ -800,6 +796,21 @@
dprintf(fd, " Thread may be deadlocked\n");
}
+ dumpBase_l(fd, args);
+ dumpInternals_l(fd, args);
+ dumpTracks_l(fd, args);
+ dumpEffectChains_l(fd, args);
+
+ if (locked) {
+ mLock.unlock();
+ }
+
+ dprintf(fd, " Local log:\n");
+ mLocalLog.dump(fd, " " /* prefix */, 40 /* lines */);
+}
+
+void AudioFlinger::ThreadBase::dumpBase_l(int fd, const Vector<String16>& args __unused)
+{
dprintf(fd, " I/O handle: %d\n", mId);
dprintf(fd, " Standby: %s\n", mStandby ? "yes" : "no");
dprintf(fd, " Sample rate: %u Hz\n", mSampleRate);
@@ -814,6 +825,8 @@
dprintf(fd, " Pending config events:");
size_t numConfig = mConfigEvents.size();
if (numConfig) {
+ const size_t SIZE = 256;
+ char buffer[SIZE];
for (size_t i = 0; i < numConfig; i++) {
mConfigEvents[i]->dump(buffer, SIZE);
dprintf(fd, "\n %s", buffer);
@@ -858,17 +871,12 @@
isOutput() ? "write" : "read",
mLatencyMs.toString().c_str());
}
-
- if (locked) {
- mLock.unlock();
- }
}
-void AudioFlinger::ThreadBase::dumpEffectChains(int fd, const Vector<String16>& args)
+void AudioFlinger::ThreadBase::dumpEffectChains_l(int fd, const Vector<String16>& args)
{
const size_t SIZE = 256;
char buffer[SIZE];
- String8 result;
size_t numEffectChains = mEffectChains.size();
snprintf(buffer, SIZE, " %zu Effect Chains\n", numEffectChains);
@@ -1819,16 +1827,24 @@
free(mEffectBuffer);
}
-void AudioFlinger::PlaybackThread::dump(int fd, const Vector<String16>& args)
+// Thread virtuals
+
+void AudioFlinger::PlaybackThread::onFirstRef()
{
- dumpInternals(fd, args);
- dumpTracks(fd, args);
- dumpEffectChains(fd, args);
- dprintf(fd, " Local log:\n");
- mLocalLog.dump(fd, " " /* prefix */, 40 /* lines */);
+ run(mThreadName, ANDROID_PRIORITY_URGENT_AUDIO);
}
-void AudioFlinger::PlaybackThread::dumpTracks(int fd, const Vector<String16>& args __unused)
+// ThreadBase virtuals
+void AudioFlinger::PlaybackThread::preExit()
+{
+ ALOGV(" preExit()");
+ // FIXME this is using hard-coded strings but in the future, this functionality will be
+ // converted to use audio HAL extensions required to support tunneling
+ status_t result = mOutput->stream->setParameters(String8("exiting=1"));
+ ALOGE_IF(result != OK, "Error when setting parameters on exit: %d", result);
+}
+
+void AudioFlinger::PlaybackThread::dumpTracks_l(int fd, const Vector<String16>& args __unused)
{
String8 result;
@@ -1893,10 +1909,8 @@
write(fd, result.string(), result.size());
}
-void AudioFlinger::PlaybackThread::dumpInternals(int fd, const Vector<String16>& args)
+void AudioFlinger::PlaybackThread::dumpInternals_l(int fd, const Vector<String16>& args __unused)
{
- dumpBase(fd, args);
-
dprintf(fd, " Master mute: %s\n", mMasterMute ? "on" : "off");
if (mHapticChannelMask != AUDIO_CHANNEL_NONE) {
dprintf(fd, " Haptic channel mask: %#x (%s)\n", mHapticChannelMask,
@@ -1927,23 +1941,6 @@
}
}
-// Thread virtuals
-
-void AudioFlinger::PlaybackThread::onFirstRef()
-{
- run(mThreadName, ANDROID_PRIORITY_URGENT_AUDIO);
-}
-
-// ThreadBase virtuals
-void AudioFlinger::PlaybackThread::preExit()
-{
- ALOGV(" preExit()");
- // FIXME this is using hard-coded strings but in the future, this functionality will be
- // converted to use audio HAL extensions required to support tunneling
- status_t result = mOutput->stream->setParameters(String8("exiting=1"));
- ALOGE_IF(result != OK, "Error when setting parameters on exit: %d", result);
-}
-
// PlaybackThread::createTrack_l() must be called with AudioFlinger::mLock held
sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrack_l(
const sp<AudioFlinger::Client>& client,
@@ -2788,28 +2785,6 @@
}
}
-// hasAudioSession_l() must be called with ThreadBase::mLock held
-uint32_t AudioFlinger::PlaybackThread::hasAudioSession_l(audio_session_t sessionId) const
-{
- uint32_t result = 0;
- if (getEffectChain_l(sessionId) != 0) {
- result = EFFECT_SESSION;
- }
-
- for (size_t i = 0; i < mTracks.size(); ++i) {
- sp<Track> track = mTracks[i];
- if (sessionId == track->sessionId() && !track->isInvalid()) {
- result |= TRACK_SESSION;
- if (track->isFastTrack()) {
- result |= FAST_SESSION;
- }
- break;
- }
- }
-
- return result;
-}
-
uint32_t AudioFlinger::PlaybackThread::getStrategyForSession_l(audio_session_t sessionId)
{
// session AUDIO_SESSION_OUTPUT_MIX is placed in same strategy as MUSIC stream so that
@@ -5372,9 +5347,9 @@
}
-void AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16>& args)
+void AudioFlinger::MixerThread::dumpInternals_l(int fd, const Vector<String16>& args)
{
- PlaybackThread::dumpInternals(fd, args);
+ PlaybackThread::dumpInternals_l(fd, args);
dprintf(fd, " Thread throttle time (msecs): %u\n", mThreadThrottleTimeMs);
dprintf(fd, " AudioMixer tracks: %s\n", mAudioMixer->trackNames().c_str());
dprintf(fd, " Master mono: %s\n", mMasterMono ? "on" : "off");
@@ -5448,9 +5423,9 @@
{
}
-void AudioFlinger::DirectOutputThread::dumpInternals(int fd, const Vector<String16>& args)
+void AudioFlinger::DirectOutputThread::dumpInternals_l(int fd, const Vector<String16>& args)
{
- PlaybackThread::dumpInternals(fd, args);
+ PlaybackThread::dumpInternals_l(fd, args);
dprintf(fd, " Master balance: %f Left: %f Right: %f\n",
mMasterBalance.load(), mMasterBalanceLeft, mMasterBalanceRight);
}
@@ -6465,9 +6440,9 @@
}
}
-void AudioFlinger::DuplicatingThread::dumpInternals(int fd, const Vector<String16>& args __unused)
+void AudioFlinger::DuplicatingThread::dumpInternals_l(int fd, const Vector<String16>& args __unused)
{
- MixerThread::dumpInternals(fd, args);
+ MixerThread::dumpInternals_l(fd, args);
std::stringstream ss;
const size_t numTracks = mOutputTracks.size();
@@ -7267,7 +7242,7 @@
} else {
// FIXME could do a partial drop of framesOut
if (activeTrack->mFramesToDrop > 0) {
- activeTrack->mFramesToDrop -= framesOut;
+ activeTrack->mFramesToDrop -= (ssize_t)framesOut;
if (activeTrack->mFramesToDrop <= 0) {
activeTrack->clearSyncStartEvent();
}
@@ -7740,18 +7715,19 @@
return status;
}
-status_t AudioFlinger::RecordThread::setMicrophoneDirection(audio_microphone_direction_t direction)
+status_t AudioFlinger::RecordThread::setPreferredMicrophoneDirection(
+ audio_microphone_direction_t direction)
{
- ALOGV("setMicrophoneDirection(%d)", direction);
+ ALOGV("setPreferredMicrophoneDirection(%d)", direction);
AutoMutex _l(mLock);
- return mInput->stream->setMicrophoneDirection(direction);
+ return mInput->stream->setPreferredMicrophoneDirection(direction);
}
-status_t AudioFlinger::RecordThread::setMicrophoneFieldDimension(float zoom)
+status_t AudioFlinger::RecordThread::setPreferredMicrophoneFieldDimension(float zoom)
{
- ALOGV("setMicrophoneFieldDimension(%f)", zoom);
+ ALOGV("setPreferredMicrophoneFieldDimension(%f)", zoom);
AutoMutex _l(mLock);
- return mInput->stream->setMicrophoneFieldDimension(zoom);
+ return mInput->stream->setPreferredMicrophoneFieldDimension(zoom);
}
void AudioFlinger::RecordThread::updateMetadata_l()
@@ -7796,19 +7772,8 @@
}
}
-void AudioFlinger::RecordThread::dump(int fd, const Vector<String16>& args)
+void AudioFlinger::RecordThread::dumpInternals_l(int fd, const Vector<String16>& args __unused)
{
- dumpInternals(fd, args);
- dumpTracks(fd, args);
- dumpEffectChains(fd, args);
- dprintf(fd, " Local log:\n");
- mLocalLog.dump(fd, " " /* prefix */, 40 /* lines */);
-}
-
-void AudioFlinger::RecordThread::dumpInternals(int fd, const Vector<String16>& args)
-{
- dumpBase(fd, args);
-
AudioStreamIn *input = mInput;
audio_input_flags_t flags = input != NULL ? input->flags : AUDIO_INPUT_FLAG_NONE;
dprintf(fd, " AudioStreamIn: %p flags %#x (%s)\n",
@@ -7835,7 +7800,7 @@
copy->dump(fd);
}
-void AudioFlinger::RecordThread::dumpTracks(int fd, const Vector<String16>& args __unused)
+void AudioFlinger::RecordThread::dumpTracks_l(int fd, const Vector<String16>& args __unused)
{
String8 result;
size_t numtracks = mTracks.size();
@@ -8219,27 +8184,6 @@
return 0;
}
-// hasAudioSession_l() must be called with ThreadBase::mLock held
-uint32_t AudioFlinger::RecordThread::hasAudioSession_l(audio_session_t sessionId) const
-{
- uint32_t result = 0;
- if (getEffectChain_l(sessionId) != 0) {
- result = EFFECT_SESSION;
- }
-
- for (size_t i = 0; i < mTracks.size(); ++i) {
- if (sessionId == mTracks[i]->sessionId()) {
- result |= TRACK_SESSION;
- if (mTracks[i]->isFastTrack()) {
- result |= FAST_SESSION;
- }
- break;
- }
- }
-
- return result;
-}
-
KeyedVector<audio_session_t, bool> AudioFlinger::RecordThread::sessionIds() const
{
KeyedVector<audio_session_t, bool> ids;
@@ -8747,9 +8691,11 @@
while (!exitPending())
{
- Mutex::Autolock _l(mLock);
Vector< sp<EffectChain> > effectChains;
+ { // under Thread lock
+ Mutex::Autolock _l(mLock);
+
if (mSignalPending) {
// A signal was raised while we were unlocked
mSignalPending = false;
@@ -8784,10 +8730,13 @@
updateMetadata_l();
lockEffectChains_l(effectChains);
+ } // release Thread lock
+
for (size_t i = 0; i < effectChains.size(); i ++) {
- effectChains[i]->process_l();
+ effectChains[i]->process_l(); // Thread is not locked, but effect chain is locked
}
- // enable changes in effect chain
+
+ // enable changes in effect chain, including moving to another thread.
unlockEffectChains(effectChains);
// Effect chains will be actually deleted here if they were removed from
// mEffectChains list during mixing or effects processing
@@ -9048,28 +8997,6 @@
return mEffectChains.size();
}
-// hasAudioSession_l() must be called with ThreadBase::mLock held
-uint32_t AudioFlinger::MmapThread::hasAudioSession_l(audio_session_t sessionId) const
-{
- uint32_t result = 0;
- if (getEffectChain_l(sessionId) != 0) {
- result = EFFECT_SESSION;
- }
-
- for (size_t i = 0; i < mActiveTracks.size(); i++) {
- sp<MmapTrack> track = mActiveTracks[i];
- if (sessionId == track->sessionId()) {
- result |= TRACK_SESSION;
- if (track->isFastTrack()) {
- result |= FAST_SESSION;
- }
- break;
- }
- }
-
- return result;
-}
-
void AudioFlinger::MmapThread::threadLoop_standby()
{
mHalStream->standby();
@@ -9138,19 +9065,8 @@
}
}
-void AudioFlinger::MmapThread::dump(int fd, const Vector<String16>& args)
+void AudioFlinger::MmapThread::dumpInternals_l(int fd, const Vector<String16>& args __unused)
{
- dumpInternals(fd, args);
- dumpTracks(fd, args);
- dumpEffectChains(fd, args);
- dprintf(fd, " Local log:\n");
- mLocalLog.dump(fd, " " /* prefix */, 40 /* lines */);
-}
-
-void AudioFlinger::MmapThread::dumpInternals(int fd, const Vector<String16>& args)
-{
- dumpBase(fd, args);
-
dprintf(fd, " Attributes: content type %d usage %d source %d\n",
mAttr.content_type, mAttr.usage, mAttr.source);
dprintf(fd, " Session: %d port Id: %d\n", mSessionId, mPortId);
@@ -9159,7 +9075,7 @@
}
}
-void AudioFlinger::MmapThread::dumpTracks(int fd, const Vector<String16>& args __unused)
+void AudioFlinger::MmapThread::dumpTracks_l(int fd, const Vector<String16>& args __unused)
{
String8 result;
size_t numtracks = mActiveTracks.size();
@@ -9382,9 +9298,9 @@
}
}
-void AudioFlinger::MmapPlaybackThread::dumpInternals(int fd, const Vector<String16>& args)
+void AudioFlinger::MmapPlaybackThread::dumpInternals_l(int fd, const Vector<String16>& args)
{
- MmapThread::dumpInternals(fd, args);
+ MmapThread::dumpInternals_l(fd, args);
dprintf(fd, " Stream type: %d Stream volume: %f HAL volume: %f Stream mute %d\n",
mStreamType, mStreamVolume, mHalVolFloat, mStreamMute);
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 97aa9f0..18cb361 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -43,9 +43,6 @@
virtual status_t readyToRun();
- void dumpBase(int fd, const Vector<String16>& args);
- void dumpEffectChains(int fd, const Vector<String16>& args);
-
void clearPowerManager();
// base for record and playback
@@ -356,6 +353,27 @@
return hasAudioSession_l(sessionId);
}
+ template <typename T>
+ uint32_t hasAudioSession_l(audio_session_t sessionId, const T& tracks) const {
+ uint32_t result = 0;
+ if (getEffectChain_l(sessionId) != 0) {
+ result = EFFECT_SESSION;
+ }
+ for (size_t i = 0; i < tracks.size(); ++i) {
+ const sp<TrackBase>& track = tracks[i];
+ if (sessionId == track->sessionId()
+ && !track->isInvalid() // not yet removed from tracks.
+ && !track->isTerminated()) {
+ result |= TRACK_SESSION;
+ if (track->isFastTrack()) {
+ result |= FAST_SESSION; // caution, only represents first track.
+ }
+ break;
+ }
+ }
+ return result;
+ }
+
// the value returned by default implementation is not important as the
// strategy is only meaningful for PlaybackThread which implements this method
virtual uint32_t getStrategyForSession_l(audio_session_t sessionId __unused)
@@ -397,7 +415,7 @@
bool isMsdDevice() const { return mIsMsdDevice; }
- virtual void dump(int fd, const Vector<String16>& args) = 0;
+ void dump(int fd, const Vector<String16>& args);
// deliver stats to mediametrics.
void sendStatistics(bool force);
@@ -449,6 +467,11 @@
return INVALID_OPERATION;
}
+ virtual void dumpInternals_l(int fd __unused, const Vector<String16>& args __unused)
+ { }
+ virtual void dumpTracks_l(int fd __unused, const Vector<String16>& args __unused) { }
+
+
friend class AudioFlinger; // for mEffectChains
const type_t mType;
@@ -636,6 +659,10 @@
};
SimpleLog mLocalLog;
+
+private:
+ void dumpBase_l(int fd, const Vector<String16>& args);
+ void dumpEffectChains_l(int fd, const Vector<String16>& args);
};
class VolumeInterface {
@@ -688,8 +715,6 @@
audio_io_handle_t id, audio_devices_t device, type_t type, bool systemReady);
virtual ~PlaybackThread();
- void dump(int fd, const Vector<String16>& args) override;
-
// Thread virtuals
virtual bool threadLoop();
@@ -739,6 +764,9 @@
mActiveTracks.updatePowerState(this, true /* force */);
}
+ void dumpInternals_l(int fd, const Vector<String16>& args) override;
+ void dumpTracks_l(int fd, const Vector<String16>& args) override;
+
public:
virtual status_t initCheck() const { return (mOutput == NULL) ? NO_INIT : NO_ERROR; }
@@ -810,7 +838,9 @@
virtual status_t addEffectChain_l(const sp<EffectChain>& chain);
virtual size_t removeEffectChain_l(const sp<EffectChain>& chain);
- virtual uint32_t hasAudioSession_l(audio_session_t sessionId) const;
+ uint32_t hasAudioSession_l(audio_session_t sessionId) const override {
+ return ThreadBase::hasAudioSession_l(sessionId, mTracks);
+ }
virtual uint32_t getStrategyForSession_l(audio_session_t sessionId);
@@ -986,9 +1016,6 @@
void updateMetadata_l() final;
virtual void sendMetadataToBackend_l(const StreamOutHalInterface::SourceMetadata& metadata);
- virtual void dumpInternals(int fd, const Vector<String16>& args);
- void dumpTracks(int fd, const Vector<String16>& args);
-
// The Tracks class manages tracks added and removed from the Thread.
template <typename T>
class Tracks {
@@ -1143,7 +1170,6 @@
virtual bool checkForNewParameter_l(const String8& keyValuePair,
status_t& status);
- virtual void dumpInternals(int fd, const Vector<String16>& args);
virtual bool isTrackAllowed_l(
audio_channel_mask_t channelMask, audio_format_t format,
@@ -1162,6 +1188,8 @@
}
}
+ void dumpInternals_l(int fd, const Vector<String16>& args) override;
+
// threadLoop snippets
virtual ssize_t threadLoop_write();
virtual void threadLoop_standby();
@@ -1243,8 +1271,6 @@
virtual bool checkForNewParameter_l(const String8& keyValuePair,
status_t& status);
- void dumpInternals(int fd, const Vector<String16>& args) override;
-
virtual void flushHw_l();
void setMasterBalance(float balance) override;
@@ -1255,6 +1281,8 @@
virtual uint32_t suspendSleepTimeUs() const;
virtual void cacheParameters_l();
+ void dumpInternals_l(int fd, const Vector<String16>& args) override;
+
// threadLoop snippets
virtual mixer_state prepareTracks_l(Vector< sp<Track> > *tracksToRemove);
virtual void threadLoop_mix();
@@ -1374,8 +1402,6 @@
virtual ~DuplicatingThread();
// Thread virtuals
- virtual void dumpInternals(int fd, const Vector<String16>& args) override;
-
void addOutputTrack(MixerThread* thread);
void removeOutputTrack(MixerThread* thread);
uint32_t waitTimeMs() const { return mWaitTimeMs; }
@@ -1384,6 +1410,7 @@
const StreamOutHalInterface::SourceMetadata& metadata) override;
protected:
virtual uint32_t activeSleepTimeUs() const;
+ void dumpInternals_l(int fd, const Vector<String16>& args) override;
private:
bool outputsReady(const SortedVector< sp<OutputTrack> > &outputTracks);
@@ -1489,9 +1516,6 @@
void destroyTrack_l(const sp<RecordTrack>& track);
void removeTrack_l(const sp<RecordTrack>& track);
- void dumpInternals(int fd, const Vector<String16>& args);
- void dumpTracks(int fd, const Vector<String16>& args);
-
// Thread virtuals
virtual bool threadLoop();
virtual void preExit();
@@ -1528,7 +1552,6 @@
// return true if the caller should then do it's part of the stopping process
bool stop(RecordTrack* recordTrack);
- void dump(int fd, const Vector<String16>& args) override;
AudioStreamIn* clearInput();
virtual sp<StreamHalInterface> stream() const;
@@ -1550,7 +1573,9 @@
virtual status_t addEffectChain_l(const sp<EffectChain>& chain);
virtual size_t removeEffectChain_l(const sp<EffectChain>& chain);
- virtual uint32_t hasAudioSession_l(audio_session_t sessionId) const;
+ uint32_t hasAudioSession_l(audio_session_t sessionId) const override {
+ return ThreadBase::hasAudioSession_l(sessionId, mTracks);
+ }
// Return the set of unique session IDs across all tracks.
// The keys are the session IDs, and the associated values are meaningless.
@@ -1582,8 +1607,8 @@
status_t getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones);
- status_t setMicrophoneDirection(audio_microphone_direction_t direction);
- status_t setMicrophoneFieldDimension(float zoom);
+ status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction);
+ status_t setPreferredMicrophoneFieldDimension(float zoom);
void updateMetadata_l() override;
@@ -1594,6 +1619,11 @@
return audio_is_input_device(
mInDevice & mTimestampCorrectedDevices);
}
+
+protected:
+ void dumpInternals_l(int fd, const Vector<String16>& args) override;
+ void dumpTracks_l(int fd, const Vector<String16>& args) override;
+
private:
// Enter standby if not already in standby, and set mStandby flag
void standbyIfNotAlreadyInStandby();
@@ -1725,7 +1755,10 @@
virtual status_t checkEffectCompatibility_l(const effect_descriptor_t *desc,
audio_session_t sessionId);
- virtual uint32_t hasAudioSession_l(audio_session_t sessionId) const;
+ uint32_t hasAudioSession_l(audio_session_t sessionId) const override {
+ // Note: using mActiveTracks as no mTracks here.
+ return ThreadBase::hasAudioSession_l(sessionId, mActiveTracks);
+ }
virtual status_t setSyncEvent(const sp<SyncEvent>& event);
virtual bool isValidSyncEvent(const sp<SyncEvent>& event) const;
@@ -1740,11 +1773,9 @@
// Sets the UID records silence
virtual void setRecordSilenced(uid_t uid __unused, bool silenced __unused) {}
- void dump(int fd, const Vector<String16>& args) override;
- virtual void dumpInternals(int fd, const Vector<String16>& args);
- void dumpTracks(int fd, const Vector<String16>& args);
-
protected:
+ void dumpInternals_l(int fd, const Vector<String16>& args) override;
+ void dumpTracks_l(int fd, const Vector<String16>& args) override;
audio_attributes_t mAttr;
audio_session_t mSessionId;
@@ -1794,8 +1825,6 @@
virtual void checkSilentMode_l();
void processVolume_l() override;
- virtual void dumpInternals(int fd, const Vector<String16>& args);
-
virtual bool isOutput() const override { return true; }
void updateMetadata_l() override;
@@ -1803,6 +1832,7 @@
virtual void toAudioPortConfig(struct audio_port_config *config);
protected:
+ void dumpInternals_l(int fd, const Vector<String16>& args) override;
audio_stream_type_t mStreamType;
float mMasterVolume;
diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h
index e23173f..4402d99 100644
--- a/services/audioflinger/TrackBase.h
+++ b/services/audioflinger/TrackBase.h
@@ -94,6 +94,9 @@
virtual void invalidate() { mIsInvalid = true; }
bool isInvalid() const { return mIsInvalid; }
+ void terminate() { mTerminated = true; }
+ bool isTerminated() const { return mTerminated; }
+
audio_attributes_t attributes() const { return mAttr; }
#ifdef TEE_SINK
@@ -228,14 +231,6 @@
return mState == STOPPING_2;
}
- bool isTerminated() const {
- return mTerminated;
- }
-
- void terminate() {
- mTerminated = true;
- }
-
// Upper case characters are final states.
// Lower case characters are transitory.
const char *getTrackStateString() const {
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 5a43696..fbf8fef 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -1838,16 +1838,16 @@
mRecordTrack->getActiveMicrophones(activeMicrophones));
}
-binder::Status AudioFlinger::RecordHandle::setMicrophoneDirection(
+binder::Status AudioFlinger::RecordHandle::setPreferredMicrophoneDirection(
int /*audio_microphone_direction_t*/ direction) {
ALOGV("%s()", __func__);
- return binder::Status::fromStatusT(mRecordTrack->setMicrophoneDirection(
+ return binder::Status::fromStatusT(mRecordTrack->setPreferredMicrophoneDirection(
static_cast<audio_microphone_direction_t>(direction)));
}
-binder::Status AudioFlinger::RecordHandle::setMicrophoneFieldDimension(float zoom) {
+binder::Status AudioFlinger::RecordHandle::setPreferredMicrophoneFieldDimension(float zoom) {
ALOGV("%s()", __func__);
- return binder::Status::fromStatusT(mRecordTrack->setMicrophoneFieldDimension(zoom));
+ return binder::Status::fromStatusT(mRecordTrack->setPreferredMicrophoneFieldDimension(zoom));
}
// ----------------------------------------------------------------------------
@@ -2144,22 +2144,22 @@
}
}
-status_t AudioFlinger::RecordThread::RecordTrack::setMicrophoneDirection(
+status_t AudioFlinger::RecordThread::RecordTrack::setPreferredMicrophoneDirection(
audio_microphone_direction_t direction) {
sp<ThreadBase> thread = mThread.promote();
if (thread != 0) {
RecordThread *recordThread = (RecordThread *)thread.get();
- return recordThread->setMicrophoneDirection(direction);
+ return recordThread->setPreferredMicrophoneDirection(direction);
} else {
return BAD_VALUE;
}
}
-status_t AudioFlinger::RecordThread::RecordTrack::setMicrophoneFieldDimension(float zoom) {
+status_t AudioFlinger::RecordThread::RecordTrack::setPreferredMicrophoneFieldDimension(float zoom) {
sp<ThreadBase> thread = mThread.promote();
if (thread != 0) {
RecordThread *recordThread = (RecordThread *)thread.get();
- return recordThread->setMicrophoneFieldDimension(zoom);
+ return recordThread->setPreferredMicrophoneFieldDimension(zoom);
} else {
return BAD_VALUE;
}
diff --git a/services/audiopolicy/Android.mk b/services/audiopolicy/Android.mk
index 9e4eebc..3badda1 100644
--- a/services/audiopolicy/Android.mk
+++ b/services/audiopolicy/Android.mk
@@ -62,10 +62,6 @@
$(error Configurable policy does not support legacy conf file)
endif #ifneq ($(USE_XML_AUDIO_POLICY_CONF), 1)
-LOCAL_REQUIRED_MODULES := \
- parameter-framework.policy \
- audio_policy_criteria.conf \
-
LOCAL_C_INCLUDES += frameworks/av/services/audiopolicy/engineconfigurable/include
LOCAL_C_INCLUDES += frameworks/av/include
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index acbfc9e..a2cf7aa 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -198,6 +198,7 @@
//dump state
virtual status_t dump(int fd) = 0;
+ virtual status_t setAllowedCapturePolicy(uid_t uid, audio_flags_mask_t flags) = 0;
virtual bool isOffloadSupported(const audio_offload_info_t& offloadInfo) = 0;
virtual bool isDirectOutputSupported(const audio_config_base_t& config,
const audio_attributes_t& attributes) = 0;
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
index 635de6f..5b4e2eb 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
@@ -334,6 +334,13 @@
void AudioInputDescriptor::updateClientRecordingConfiguration(
int event, const sp<RecordClientDescriptor>& client)
{
+ // do not send callback if starting and no device is selected yet to avoid
+ // double callbacks from startInput() before and after the device is selected
+ if (event == RECORD_CONFIG_EVENT_START
+ && mPatchHandle == AUDIO_PATCH_HANDLE_NONE) {
+ return;
+ }
+
const audio_config_base_t sessionConfig = client->config();
const record_client_info_t recordClientInfo{client->uid(), client->session(),
client->source(), client->portId(),
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
index f7289ca..8f15016 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -47,32 +47,29 @@
int indexCriterion = 0;
for (const auto &criterion : mCriteria) {
- dst->appendFormat("%*s- Criterion %d:\n", spaces + 2, "", indexCriterion++);
+ dst->appendFormat("%*s- Criterion %d: ", spaces + 2, "", indexCriterion++);
- std::string usageLiteral;
- if (!UsageTypeConverter::toString(criterion.mValue.mUsage, usageLiteral)) {
- ALOGE("%s: failed to convert usage %d", __FUNCTION__, criterion.mValue.mUsage);
- return;
+ std::string ruleType, ruleValue;
+ bool unknownRule = !RuleTypeConverter::toString(criterion.mRule, ruleType);
+ switch (criterion.mRule & ~RULE_EXCLUSION_MASK) { // no need to match RULE_EXCLUDE_...
+ case RULE_MATCH_ATTRIBUTE_USAGE:
+ UsageTypeConverter::toString(criterion.mValue.mUsage, ruleValue);
+ break;
+ case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET:
+ SourceTypeConverter::toString(criterion.mValue.mSource, ruleValue);
+ break;
+ case RULE_MATCH_UID:
+ ruleValue = std::to_string(criterion.mValue.mUid);
+ break;
+ default:
+ unknownRule = true;
}
- dst->appendFormat("%*s- Usage:%s\n", spaces + 4, "", usageLiteral.c_str());
- if (mMixType == MIX_TYPE_RECORDERS) {
- std::string sourceLiteral;
- if (!SourceTypeConverter::toString(criterion.mValue.mSource, sourceLiteral)) {
- ALOGE("%s: failed to convert source %d", __FUNCTION__, criterion.mValue.mSource);
- return;
- }
- dst->appendFormat("%*s- Source:%s\n", spaces + 4, "", sourceLiteral.c_str());
-
+ if (!unknownRule) {
+ dst->appendFormat("%s %s\n", ruleType.c_str(), ruleValue.c_str());
+ } else {
+ dst->appendFormat("Unknown rule type value 0x%x\n", criterion.mRule);
}
- dst->appendFormat("%*s- Uid:%d\n", spaces + 4, "", criterion.mValue.mUid);
-
- std::string ruleLiteral;
- if (!RuleTypeConverter::toString(criterion.mRule, ruleLiteral)) {
- ALOGE("%s: failed to convert source %d", __FUNCTION__,criterion.mRule);
- return;
- }
- dst->appendFormat("%*s- Rule:%s\n", spaces + 4, "", ruleLiteral.c_str());
}
}
@@ -180,7 +177,12 @@
// Loopback render mixes are created from a public API and thus restricted
// to non sensible audio that have not opted out.
if (is_mix_loopback_render(mix->mRouteFlags)) {
- if ((attributes.flags & AUDIO_FLAG_NO_CAPTURE) == AUDIO_FLAG_NO_CAPTURE) {
+ auto hasFlag = [](auto flags, auto flag) { return (flags & flag) == flag; };
+ if (hasFlag(attributes.flags, AUDIO_FLAG_NO_SYSTEM_CAPTURE)) {
+ return MixMatchStatus::NO_MATCH;
+ }
+ if (!mix->mAllowPrivilegedPlaybackCapture &&
+ hasFlag(attributes.flags, AUDIO_FLAG_NO_MEDIA_PROJECTION)) {
return MixMatchStatus::NO_MATCH;
}
if (!(attributes.usage == AUDIO_USAGE_UNKNOWN ||
diff --git a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
index 91961d0..1a74f48 100644
--- a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
@@ -40,7 +40,7 @@
mTagName(tagName), mDeviceType(type), mEncodedFormats(encodedFormats)
{
mCurrentEncodedFormat = AUDIO_FORMAT_DEFAULT;
- if (type == AUDIO_DEVICE_IN_REMOTE_SUBMIX || type == AUDIO_DEVICE_OUT_REMOTE_SUBMIX ) {
+ if (audio_is_remote_submix_device(type)) {
mAddress = String8("0");
}
/* If framework runs against a pre 5.0 Audio HAL, encoded formats are absent from the config.
diff --git a/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp b/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp
index 7c76d8a..2b5455e 100644
--- a/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp
@@ -52,7 +52,6 @@
template <>
const RuleTypeConverter::Table RuleTypeConverter::mTable[] = {
- MAKE_STRING_FROM_ENUM(RULE_EXCLUSION_MASK),
MAKE_STRING_FROM_ENUM(RULE_MATCH_ATTRIBUTE_USAGE),
MAKE_STRING_FROM_ENUM(RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET),
MAKE_STRING_FROM_ENUM(RULE_MATCH_UID),
diff --git a/services/audiopolicy/engineconfigurable/config/example/Android.mk b/services/audiopolicy/engineconfigurable/config/example/Android.mk
index 45419f0..37271b5 100644
--- a/services/audiopolicy/engineconfigurable/config/example/Android.mk
+++ b/services/audiopolicy/engineconfigurable/config/example/Android.mk
@@ -10,16 +10,15 @@
ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), phone_configurable)
include $(CLEAR_VARS)
-LOCAL_MODULE := audio_policy_engine_configuration_phone.xml
-LOCAL_MODULE_STEM := audio_policy_engine_configuration.xml
+LOCAL_MODULE := audio_policy_engine_configuration.xml
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := ETC
LOCAL_VENDOR_MODULE := true
-LOCAL_SRC_FILES := phone/$(LOCAL_MODULE_STEM)
+LOCAL_SRC_FILES := phone/$(LOCAL_MODULE)
LOCAL_REQUIRED_MODULES := \
- audio_policy_engine_product_strategies_phone.xml \
+ audio_policy_engine_product_strategies.xml \
audio_policy_engine_stream_volumes.xml \
audio_policy_engine_default_stream_volumes.xml \
audio_policy_engine_criteria.xml \
@@ -28,12 +27,11 @@
include $(BUILD_PREBUILT)
include $(CLEAR_VARS)
-LOCAL_MODULE := audio_policy_engine_product_strategies_phone.xml
-LOCAL_MODULE_STEM := audio_policy_engine_product_strategies.xml
+LOCAL_MODULE := audio_policy_engine_product_strategies.xml
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := ETC
LOCAL_VENDOR_MODULE := true
-LOCAL_SRC_FILES := phone/$(LOCAL_MODULE_STEM)
+LOCAL_SRC_FILES := phone/$(LOCAL_MODULE)
include $(BUILD_PREBUILT)
include $(CLEAR_VARS)
@@ -55,39 +53,40 @@
endif # ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), phone_configurable)
-ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), automotive_configurable)
+ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),$(filter $(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),automotive_configurable caremu_configurable))
##################################################################
# AUTOMOTIVE CONFIGURATION TOP FILE
##################################################################
include $(CLEAR_VARS)
-LOCAL_MODULE := audio_policy_engine_configuration_automotive.xml
-LOCAL_MODULE_STEM := audio_policy_engine_configuration.xml
-
+LOCAL_MODULE := audio_policy_engine_configuration.xml
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := ETC
LOCAL_VENDOR_MODULE := true
-LOCAL_SRC_FILES := automotive/$(LOCAL_MODULE_STEM)
+LOCAL_SRC_FILES := automotive/$(LOCAL_MODULE)
LOCAL_REQUIRED_MODULES := \
- audio_policy_engine_product_strategies_automotive.xml \
+ audio_policy_engine_product_strategies.xml \
audio_policy_engine_criteria.xml \
audio_policy_engine_criterion_types.xml \
audio_policy_engine_volumes.xml
include $(BUILD_PREBUILT)
+endif #ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),$(filter $(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),automotive_configurable caremu_configurable))
+
+ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), automotive_configurable)
+
##################################################################
# CONFIGURATION FILES
##################################################################
include $(CLEAR_VARS)
-LOCAL_MODULE := audio_policy_engine_product_strategies_automotive.xml
-LOCAL_MODULE_STEM := audio_policy_engine_product_strategies.xml
+LOCAL_MODULE := audio_policy_engine_product_strategies.xml
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := ETC
LOCAL_VENDOR_MODULE := true
-LOCAL_SRC_FILES := automotive/$(LOCAL_MODULE_STEM)
+LOCAL_SRC_FILES := automotive/$(LOCAL_MODULE)
include $(BUILD_PREBUILT)
include $(CLEAR_VARS)
@@ -100,7 +99,31 @@
endif #ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), automotive_configurable)
-ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),$(filter $(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),phone_configurable automotive_configurable))
+ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), caremu_configurable)
+
+##################################################################
+# CONFIGURATION FILES
+##################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := audio_policy_engine_product_strategies.xml
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := ETC
+LOCAL_VENDOR_MODULE := true
+LOCAL_SRC_FILES := caremu/$(LOCAL_MODULE)
+include $(BUILD_PREBUILT)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := audio_policy_engine_volumes.xml
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := ETC
+LOCAL_VENDOR_MODULE := true
+LOCAL_SRC_FILES := caremu/$(LOCAL_MODULE)
+include $(BUILD_PREBUILT)
+
+endif #ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), caremu_configurable)
+
+ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),$(filter $(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),phone_configurable automotive_configurable caremu_configurable))
include $(CLEAR_VARS)
LOCAL_MODULE := audio_policy_engine_criteria.xml
@@ -123,4 +146,4 @@
include $(PROVISION_CRITERION_TYPES)
-endif #ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),$(filter $(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),phone_configurable automotive_configurable))
+endif #ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),$(filter $(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),phone_configurable automotive_configurable caremu_configurable))
diff --git a/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_volumes.xml b/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_volumes.xml
index b326b50..9ec3d77 100644
--- a/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_volumes.xml
+++ b/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_volumes.xml
@@ -159,7 +159,7 @@
<name>phone</name>
<indexMin>1</indexMin>
<indexMax>40</indexMax>
- <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+ <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
<point>0,-4200</point>
<point>33,-2800</point>
<point>66,-1400</point>
diff --git a/services/audiopolicy/engineconfigurable/config/example/caremu/audio_policy_engine_product_strategies.xml b/services/audiopolicy/engineconfigurable/config/example/caremu/audio_policy_engine_product_strategies.xml
new file mode 100644
index 0000000..c487da9
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/config/example/caremu/audio_policy_engine_product_strategies.xml
@@ -0,0 +1,170 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Copyright (C) 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.
+-->
+
+<ProductStrategies>
+ <!-- OEM Usages -->
+ <!-- product_strategy will be defined according this order
+ product_strategy is oem_traffic_anouncement if all the conditions are satisfied for
+ AudioAttributes aa
+
+ int type = 0;
+ if (bundle != null) {
+ type = bundle.getInt(KEY_OEM_TYPE, 0);
+ }
+ if(
+ ( aa.mContentType == AudioAttributes.AUDIO_CONTENT_TYPE_SPEECH ) &&
+ ( aa.mUsage == AudioAttributes.AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE ) &&
+ ( type == 1 ) )
+ -->
+
+ <ProductStrategy name="oem_traffic_anouncement">
+ <AttributesGroup volumeGroup="oem_traffic_anouncement">
+ <ContentType value="AUDIO_CONTENT_TYPE_SPEECH"/>
+ <Usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"/>
+ <!-- traffic_annoucement = 1 -->
+ <Bundle key="oem" value="1"/>
+ </AttributesGroup>
+ </ProductStrategy>
+ <ProductStrategy name="oem_strategy_1">
+ <AttributesGroup volumeGroup="oem_adas_2">
+ <ContentType value="AUDIO_CONTENT_TYPE_SPEECH"/>
+ <Usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"/>
+ <Bundle key="oem" value="2"/>
+ </AttributesGroup>
+ </ProductStrategy>
+ <ProductStrategy name="oem_strategy_2">
+ <AttributesGroup volumeGroup="oem_adas_3">
+ <ContentType value="AUDIO_CONTENT_TYPE_SPEECH"/>
+ <Usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"/>
+ <Bundle key="oem" value="3"/>
+ </AttributesGroup>
+ </ProductStrategy>
+
+ <!-- Car Usages -->
+ <!-- Keep those lines only for car -->
+ <!-- Check car conditions if any OEM conditions matched -->
+ <!-- As defined by CarAudioAttributesUtil.java -->
+ <!-- product_strategy will be defined according this order
+ product_strategy is radio if all the conditions are satisfied for AudioAttributes aa
+
+ int type = CAR_AUDIO_TYPE_DEFAULT;
+ if (bundle != null) {
+ type = bundle.getInt(KEY_CAR_AUDIO_TYPE, CAR_AUDIO_TYPE_DEFAULT);
+ }
+ if(
+ ( aa.mContentType == AudioAttributes.AUDIO_CONTENT_TYPE_SPEECH ) &&
+ ( aa.mUsage == AudioAttributes.AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE ) &&
+ ( type == CAR_AUDIO_TYPE_RADIO ) )
+ -->
+ <ProductStrategy name="radio">
+ <AttributesGroup volumeGroup="media_car_audio_type_3">
+ <ContentType value="AUDIO_CONTENT_TYPE_MUSIC"/>
+ <Usage value="AUDIO_USAGE_MEDIA"/>
+ <Bundle key="car_audio_type" value="3"/>
+ </AttributesGroup>
+ </ProductStrategy>
+ <ProductStrategy name="ext_audio_source">
+ <AttributesGroup volumeGroup="media_car_audio_type_7">
+ <ContentType value="AUDIO_CONTENT_TYPE_MUSIC"/>
+ <Usage value="AUDIO_USAGE_MEDIA"/>
+ <Bundle key="car_audio_type" value="7"/>
+ </AttributesGroup>
+ </ProductStrategy>
+ <ProductStrategy name="voice_command">
+ <AttributesGroup volumeGroup="speech">
+ <Attributes>
+ <ContentType value="AUDIO_CONTENT_TYPE_SPEECH"/>
+ <Usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"/>
+ <!-- CAR_AUDIO_TYPE_VOICE_COMMAND = 1 -->
+ <Bundle key="car_audio_type" value="1"/>
+ </Attributes>
+ <Attributes> <Usage value="AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY"/> </Attributes>
+ <Attributes> <Usage value="AUDIO_USAGE_ASSISTANT"/> </Attributes>
+ </AttributesGroup>
+ </ProductStrategy>
+ <ProductStrategy name="safety_alert">
+ <AttributesGroup volumeGroup="system">
+ <ContentType value="AUDIO_CONTENT_TYPE_SONIFICATION"/>
+ <Usage value="AUDIO_USAGE_NOTIFICATION"/>
+ <!-- CAR_AUDIO_TYPE_SAFETY_ALERT = 2 -->
+ <Bundle key="car_audio_type" value="2"/>
+ </AttributesGroup>
+ </ProductStrategy>
+
+ <!-- To be checked
+ CAR_AUDIO_TYPE_CARSERVICE_BOTTOM
+ CAR_AUDIO_TYPE_CARSERVICE_CAR_PROXY
+ CAR_AUDIO_TYPE_CARSERVICE_MEDIA_MUTE
+ -->
+
+ <!-- Generic Usages -->
+ <ProductStrategy name="music">
+ <AttributesGroup streamType="AUDIO_STREAM_MUSIC" volumeGroup="media">
+ <Attributes> <Usage value="AUDIO_USAGE_MEDIA"/> </Attributes>
+ <Attributes> <Usage value="AUDIO_USAGE_GAME"/> </Attributes>
+ <!-- Default product strategy has empty attributes -->
+ <Attributes></Attributes>
+ </AttributesGroup>
+ </ProductStrategy>
+
+ <ProductStrategy name="nav_guidance">
+ <AttributesGroup volumeGroup="speech">
+ <Usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"/>
+ </AttributesGroup>
+ </ProductStrategy>
+ <ProductStrategy name="voice_call">
+ <AttributesGroup streamType="AUDIO_STREAM_VOICE_CALL" volumeGroup="phone">
+ <Attributes> <Usage value="AUDIO_USAGE_VOICE_COMMUNICATION"/> </Attributes>
+ <Attributes> <Usage value="AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING"/> </Attributes>
+ </AttributesGroup>
+ <AttributesGroup streamType="AUDIO_STREAM_BLUETOOTH_SCO" volumeGroup="phone">
+ <Attributes> <Flags value="AUDIO_FLAG_SCO"/> </Attributes>
+ </AttributesGroup>
+ </ProductStrategy>
+ <ProductStrategy name="alarm">
+ <AttributesGroup streamType="AUDIO_STREAM_ALARM" volumeGroup="ring">
+ <Usage value="AUDIO_USAGE_ALARM"/>
+ </AttributesGroup>
+ </ProductStrategy>
+ <ProductStrategy name="ring">
+ <AttributesGroup streamType="AUDIO_STREAM_RING" volumeGroup="ring">
+ <Usage value="AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE"/>
+ </AttributesGroup>
+ </ProductStrategy>
+ <ProductStrategy name="notification">
+ <AttributesGroup streamType="AUDIO_STREAM_NOTIFICATION" volumeGroup="ring">
+ <Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION"/> </Attributes>
+ <Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT"/> </Attributes>
+ <Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED"/> </Attributes>
+ <Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST"/> </Attributes>
+ <Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_EVENT"/> </Attributes>
+ </AttributesGroup>
+ </ProductStrategy>
+ <ProductStrategy name="system">
+ <AttributesGroup streamType="AUDIO_STREAM_SYSTEM" volumeGroup="system">
+ <Usage value="AUDIO_USAGE_ASSISTANCE_SONIFICATION"/>
+ </AttributesGroup>
+ </ProductStrategy>
+ <ProductStrategy name="tts">
+ <!-- TTS stream MUST BE MANAGED OUTSIDE default product strategy if NO DEDICATED OUTPUT
+ for TTS, otherwise when beacon happens, default strategy is ... muted.
+ If it is media, it is annoying... -->
+ <AttributesGroup streamType="AUDIO_STREAM_TTS" volumeGroup="tts">
+ <Attributes> <Flags value="AUDIO_FLAG_BEACON"/> </Attributes>
+ </AttributesGroup>
+ </ProductStrategy>
+</ProductStrategies>
+
diff --git a/services/audiopolicy/engineconfigurable/config/example/caremu/audio_policy_engine_volumes.xml b/services/audiopolicy/engineconfigurable/config/example/caremu/audio_policy_engine_volumes.xml
new file mode 100644
index 0000000..9ec3d77
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/config/example/caremu/audio_policy_engine_volumes.xml
@@ -0,0 +1,192 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Copyright (C) 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.
+ -->
+
+<!-- Volume Groups Tables included by Audio Policy Configuration file -->
+<!-- Note:
+ It is VALID to have a group without attributes if a product strategy is following
+ this group for all attributes.
+ Otherwise, attributes must be specified
+-->
+
+<volumeGroups>
+ <volumeGroup>
+ <name>oem_traffic_anouncement</name>
+ <indexMin>0</indexMin>
+ <indexMax>40</indexMax>
+ <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+ <point>0,-4200</point>
+ <point>33,-2800</point>
+ <point>66,-1400</point>
+ <point>100,0</point>
+ </volume>
+ <volume deviceCategory="DEVICE_CATEGORY_HEADSET">
+ <point>0,-4200</point>
+ <point>33,-2800</point>
+ <point>66,-1400</point>
+ <point>100,0</point>
+ </volume>
+ <volume deviceCategory="DEVICE_CATEGORY_EARPIECE">
+ <point>0,-4200</point>
+ <point>33,-2800</point>
+ <point>66,-1400</point>
+ <point>100,0</point>
+ </volume>
+ <volume deviceCategory="DEVICE_CATEGORY_EXT_MEDIA">
+ <point>0,-4200</point>
+ <point>33,-2800</point>
+ <point>66,-1400</point>
+ <point>100,0</point>
+ </volume>
+ </volumeGroup>
+
+<!-- OEM ADAS is a volume group that has a single port gain (this is the reason why it is a group
+ but may host different streams.
+ A priority must be given among them (either they are multualy excluisve, so the volume
+ will be the one of the currently acitve stream, otherwise a priority must be given by
+ any mean. -->
+ <volumeGroup>
+ <name>oem_adas_2</name>
+ <indexMin>0</indexMin>
+ <indexMax>40</indexMax>
+ <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+ <point>0,-4200</point>
+ <point>33,-2800</point>
+ <point>66,-1400</point>
+ <point>100,0</point>
+ </volume>
+ <volume deviceCategory="DEVICE_CATEGORY_HEADSET">
+ <point>0,-4200</point>
+ <point>33,-2800</point>
+ <point>66,-1400</point>
+ <point>100,0</point>
+ </volume>
+ </volumeGroup>
+ <volumeGroup>
+ <name>oem_adas_3</name>
+ <indexMin>0</indexMin>
+ <indexMax>40</indexMax>
+ <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+ <point>0,-2400</point>
+ <point>33,-1600</point>
+ <point>66,-800</point>
+ <point>100,0</point>
+ </volume>
+ <volume deviceCategory="DEVICE_CATEGORY_EARPIECE">
+ <point>0,-2400</point>
+ <point>33,-1600</point>
+ <point>66,-800</point>
+ <point>100,0</point>
+ </volume>
+ </volumeGroup>
+
+<!-- MEDIA is a volume group that has a single port gain (this is the reason why it is a group
+ but may host different streams.
+ A priority must be given among them (either they are multualy exclusive, so the volume
+ will be the one of the active stream with highest priority (ORDER MATTERS) unless the curves
+ followed will the the curves for the requested attributes.-->
+ <volumeGroup>
+ <name>media_car_audio_type_3</name>
+ <indexMin>0</indexMin>
+ <indexMax>40</indexMax>
+ <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+ <point>0,-4200</point>
+ <point>33,-2800</point>
+ <point>66,-1400</point>
+ <point>100,0</point>
+ </volume>
+ </volumeGroup>
+ <volumeGroup>
+ <name>media_car_audio_type_7</name>
+ <indexMin>0</indexMin>
+ <indexMax>40</indexMax>
+ <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+ <point>0,-2400</point>
+ <point>33,-1600</point>
+ <point>66,-800</point>
+ <point>100,0</point>
+ </volume>
+ </volumeGroup>
+ <volumeGroup>
+ <name>media</name>
+ <indexMin>0</indexMin>
+ <indexMax>40</indexMax>
+ <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+ <point>0,-2400</point>
+ <point>33,-1600</point>
+ <point>66,-800</point>
+ <point>100,0</point>
+ </volume>
+ </volumeGroup>
+
+ <volumeGroup>
+ <name>speech</name>
+ <indexMin>1</indexMin>
+ <indexMax>40</indexMax>
+ <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+ <point>0,-4200</point>
+ <point>33,-2800</point>
+ <point>66,-1400</point>
+ <point>100,0</point>
+ </volume>
+ </volumeGroup>
+
+ <volumeGroup>
+ <name>system</name>
+ <indexMin>0</indexMin>
+ <indexMax>40</indexMax>
+ <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+ <point>0,-4200</point>
+ <point>33,-2800</point>
+ <point>66,-1400</point>
+ <point>100,0</point>
+ </volume>
+ </volumeGroup>
+
+ <volumeGroup>
+ <name>phone</name>
+ <indexMin>1</indexMin>
+ <indexMax>40</indexMax>
+ <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+ <point>0,-4200</point>
+ <point>33,-2800</point>
+ <point>66,-1400</point>
+ <point>100,0</point>
+ </volume>
+ </volumeGroup>
+
+ <volumeGroup>
+ <name>ring</name>
+ <indexMin>0</indexMin>
+ <indexMax>40</indexMax>
+ <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+ <point>0,-4200</point>
+ <point>33,-2800</point>
+ <point>66,-1400</point>
+ <point>100,0</point>
+ </volume>
+ </volumeGroup>
+
+ <volumeGroup>
+ <name>tts</name>
+ <indexMin>0</indexMin>
+ <indexMax>15</indexMax>
+ <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+ <point>0,-0</point>
+ <point>100,0</point>
+ </volume>
+ </volumeGroup>
+</volumeGroups>
+
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Android.mk b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Android.mk
index 060830b..782fe83 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Android.mk
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Android.mk
@@ -9,7 +9,7 @@
LOCAL_PATH := $(call my-dir)
-ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),$(filter $(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),phone_configurable automotive_configurable no-output_configurable no-input_configurable))
+ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),$(filter $(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),phone_configurable automotive_configurable caremu_configurable no-output_configurable no-input_configurable))
PFW_CORE := external/parameter-framework
#@TODO: upstream new domain generator
@@ -20,6 +20,8 @@
TOOLS := frameworks/av/services/audiopolicy/engineconfigurable/tools
BUILD_PFW_SETTINGS := $(TOOLS)/build_audio_pfw_settings.mk
+PROVISION_STRATEGIES_STRUCTURE := $(TOOLS)/provision_strategies_structure.mk
+
endif
##################################################################
@@ -27,7 +29,7 @@
##################################################################
######### Policy PFW top level file #########
-ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),$(filter $(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),phone_configurable automotive_configurable))
+ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),$(filter $(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),phone_configurable automotive_configurable caremu_configurable))
include $(CLEAR_VARS)
LOCAL_MODULE := ParameterFrameworkConfigurationPolicy.xml
@@ -52,12 +54,27 @@
########## Policy PFW Common Structures #########
include $(CLEAR_VARS)
+LOCAL_MODULE := PolicySubsystem.xml
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := ETC
+LOCAL_VENDOR_MODULE := true
+LOCAL_REQUIRED_MODULES := \
+ PolicySubsystem-CommonTypes.xml \
+ ProductStrategies.xml \
+ PolicySubsystem-Volume.xml \
+ libpolicy-subsystem \
+
+LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Structure/Policy
+LOCAL_SRC_FILES := common/Structure/$(LOCAL_MODULE)
+include $(BUILD_PREBUILT)
+
+include $(CLEAR_VARS)
LOCAL_MODULE := PolicySubsystem-CommonTypes.xml
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := ETC
LOCAL_VENDOR_MODULE := true
LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Structure/Policy
-LOCAL_SRC_FILES := Structure/$(LOCAL_MODULE)
+LOCAL_SRC_FILES := common/Structure/$(LOCAL_MODULE)
include $(BUILD_PREBUILT)
include $(CLEAR_VARS)
@@ -66,16 +83,29 @@
LOCAL_MODULE_CLASS := ETC
LOCAL_VENDOR_MODULE := true
LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Structure/Policy
-LOCAL_SRC_FILES := Structure/$(LOCAL_MODULE)
+LOCAL_SRC_FILES := common/Structure/$(LOCAL_MODULE)
include $(BUILD_PREBUILT)
-endif #ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),$(filter $(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),phone_configurable automotive_configurable))
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := ProductStrategies.xml
+LOCAL_MODULE_CLASS := ETC
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Structure/Policy
+LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_VENDOR_ETC)/audio_policy_engine_configuration.xml
+AUDIO_POLICY_ENGINE_CONFIGURATION_FILE := \
+ $(TARGET_OUT_VENDOR_ETC)/audio_policy_engine_configuration.xml
+STRATEGIES_STRUCTURE_FILE := $(LOCAL_PATH)/common/Structure/$(LOCAL_MODULE).in
+
+include $(PROVISION_STRATEGIES_STRUCTURE)
+
+endif #ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),$(filter $(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),phone_configurable automotive_configurable caremu_configurable))
########## Policy PFW Example Structures #########
ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),$(filter $(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),no-output_configurable no-input_configurable))
include $(CLEAR_VARS)
-LOCAL_MODULE := PolicySubsystem.xml.common
+LOCAL_MODULE := PolicySubsystem-no-strategy.xml
LOCAL_MODULE_STEM := PolicySubsystem.xml
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := ETC
@@ -86,7 +116,7 @@
libpolicy-subsystem \
LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Structure/Policy
-LOCAL_SRC_FILES := Structure/$(LOCAL_MODULE_STEM)
+LOCAL_SRC_FILES := common/Structure/$(LOCAL_MODULE_STEM)
include $(BUILD_PREBUILT)
endif # ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),$(filter $(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),no-output_configurable no-input_configurable))
@@ -95,7 +125,7 @@
ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),no-output_configurable)
include $(CLEAR_VARS)
-LOCAL_MODULE := parameter-framework.policy.no-output
+LOCAL_MODULE := parameter-framework.policy
LOCAL_MODULE_STEM := PolicyConfigurableDomains-NoOutputDevice.xml
LOCAL_MODULE_CLASS := ETC
LOCAL_VENDOR_MODULE := true
@@ -103,7 +133,7 @@
LOCAL_REQUIRED_MODULES := \
audio_policy_engine_criteria.xml \
audio_policy_engine_criterion_types.xml \
- PolicySubsystem.xml.common \
+ PolicySubsystem-no-strategy.xml \
PolicyClass.xml \
ParameterFrameworkConfigurationPolicy.xml
@@ -121,7 +151,7 @@
ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),no-input_configurable)
include $(CLEAR_VARS)
-LOCAL_MODULE := parameter-framework.policy.no-input
+LOCAL_MODULE := parameter-framework.policy
LOCAL_MODULE_STEM := PolicyConfigurableDomains-NoInputDevice.xml
LOCAL_MODULE_CLASS := ETC
LOCAL_VENDOR_MODULE := true
@@ -129,7 +159,7 @@
LOCAL_REQUIRED_MODULES := \
audio_policy_engine_criteria.xml \
audio_policy_engine_criterion_types.xml \
- PolicySubsystem.xml.common \
+ PolicySubsystem-no-strategy.xml \
PolicyClass.xml \
ParameterFrameworkConfigurationPolicy.xml
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Car/Android.mk b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Car/Android.mk
index ea4a58f..20ca8e2 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Car/Android.mk
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Car/Android.mk
@@ -23,37 +23,9 @@
##################################################################
########## Policy PFW Structures #########
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := PolicySubsystem.xml.car
-LOCAL_MODULE_STEM := PolicySubsystem.xml
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_REQUIRED_MODULES := \
- ProductStrategies.xml.car \
- PolicySubsystem-Volume.xml \
- PolicySubsystem-CommonTypes.xml \
- libpolicy-subsystem
-
-LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Structure/Policy
-LOCAL_SRC_FILES := Structure/$(LOCAL_MODULE_STEM)
-include $(BUILD_PREBUILT)
-
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := ProductStrategies.xml.car
-LOCAL_MODULE_STEM := ProductStrategies.xml
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Structure/Policy
-LOCAL_SRC_FILES := Structure/$(LOCAL_MODULE_STEM)
-include $(BUILD_PREBUILT)
-
######### Policy PFW Settings #########
include $(CLEAR_VARS)
-LOCAL_MODULE := parameter-framework.policy.car
+LOCAL_MODULE := parameter-framework.policy
LOCAL_MODULE_STEM := PolicyConfigurableDomains.xml
LOCAL_MODULE_CLASS := ETC
LOCAL_VENDOR_MODULE := true
@@ -68,7 +40,7 @@
$(PFW_EDD_FILES)
LOCAL_REQUIRED_MODULES := \
- PolicySubsystem.xml.car \
+ PolicySubsystem.xml \
PolicyClass.xml \
audio_policy_engine_criteria.xml \
audio_policy_engine_criterion_types.xml \
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Car/Settings/device_for_product_strategies.pfw b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Car/Settings/device_for_product_strategies.pfw
index 196d82c..57ad592 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Car/Settings/device_for_product_strategies.pfw
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Car/Settings/device_for_product_strategies.pfw
@@ -714,4 +714,47 @@
speaker = 0
bus = 0
+ supDomain: Tts
+ domain: UnreachableDevices
+ conf: calibration
+ component: /Policy/policy/product_strategies/tts/selected_output_devices/mask
+ earpiece = 0
+ speaker = 0
+ wired_headset = 0
+ wired_headphone = 0
+ bluetooth_sco = 0
+ bluetooth_sco_headset = 0
+ bluetooth_sco_carkit = 0
+ bluetooth_a2dp = 0
+ bluetooth_a2dp_headphones = 0
+ bluetooth_a2dp_speaker = 0
+ hdmi = 0
+ angl_dock_headset = 0
+ dgtl_dock_headset = 0
+ usb_accessory = 0
+ usb_device = 0
+ remote_submix = 0
+ telephony_tx = 0
+ line = 0
+ hdmi_arc = 0
+ spdif = 0
+ fm = 0
+ aux_line = 0
+ speaker_safe = 0
+ ip = 0
+ proxy = 0
+ usb_headset = 0
+ stub = 0
+ /Policy/policy/product_strategies/tts/device_address = BUS00_MEDIA
+ domain: SelectedDevice
+ conf: Bus
+ AvailableOutputDevices Includes Bus
+ AvailableOutputDevicesAddresses Includes BUS00_MEDIA
+
+ component: /Policy/policy/product_strategies/tts/selected_output_devices/mask
+ bus = 1
+
+ conf: Default
+ component: /Policy/policy/product_strategies/tts/selected_output_devices/mask
+ bus = 0
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Car/Structure/ProductStrategies.xml b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Car/Structure/ProductStrategies.xml
deleted file mode 100644
index 53bba03..0000000
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Car/Structure/ProductStrategies.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 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.
--->
-<ComponentTypeSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:xi="http://www.w3.org/2001/XInclude"
- xsi:noNamespaceSchemaLocation="Schemas/ComponentTypeSet.xsd">
-
- <ComponentType Name="ProductStrategies" Description="">
- <Component Name="oem_traffic_anouncement" Type="ProductStrategy"/>
- <Component Name="oem_strategy_1" Type="ProductStrategy"/>
- <Component Name="oem_strategy_2" Type="ProductStrategy"/>
-
- <Component Name="radio" Type="ProductStrategy"/>
- <Component Name="ext_audio_source" Type="ProductStrategy"/>
- <Component Name="voice_command" Type="ProductStrategy"/>
- <Component Name="safety_alert" Type="ProductStrategy"/>
-
- <Component Name="music" Type="ProductStrategy"/>
- <Component Name="nav_guidance" Type="ProductStrategy"/>
- <Component Name="voice_call" Type="ProductStrategy"/>
- <Component Name="alarm" Type="ProductStrategy"/>
- <Component Name="ring" Type="ProductStrategy"/>
- <Component Name="notification" Type="ProductStrategy"/>
- <Component Name="system" Type="ProductStrategy"/>
- </ComponentType>
-
-</ComponentTypeSet>
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/CarEmu/Android.mk b/services/audiopolicy/engineconfigurable/parameter-framework/examples/CarEmu/Android.mk
new file mode 100644
index 0000000..8fa8f0a
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/CarEmu/Android.mk
@@ -0,0 +1,58 @@
+################################################################################################
+#
+# @NOTE:
+# Audio Policy Engine configurable example for generic device build
+#
+# Any vendor shall have its own configuration within the corresponding device folder
+#
+################################################################################################
+
+ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), caremu_configurable)
+LOCAL_PATH := $(call my-dir)
+
+PFW_CORE := external/parameter-framework
+PFW_DEFAULT_SCHEMAS_DIR := $(PFW_CORE)/upstream/schemas
+PFW_SCHEMAS_DIR := $(PFW_DEFAULT_SCHEMAS_DIR)
+
+TOOLS := frameworks/av/services/audiopolicy/engineconfigurable/tools
+BUILD_PFW_SETTINGS := $(TOOLS)/build_audio_pfw_settings.mk
+
+
+##################################################################
+# CONFIGURATION FILES
+##################################################################
+
+########## Policy PFW Structures #########
+######### Policy PFW Settings #########
+include $(CLEAR_VARS)
+LOCAL_MODULE := parameter-framework.policy
+LOCAL_MODULE_STEM := PolicyConfigurableDomains.xml
+LOCAL_MODULE_CLASS := ETC
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Settings/Policy
+
+PFW_EDD_FILES := \
+ $(LOCAL_PATH)/Settings/device_for_product_strategies.pfw \
+ $(LOCAL_PATH)/../Settings/device_for_input_source.pfw \
+ $(LOCAL_PATH)/../Settings/volumes.pfw
+
+LOCAL_ADDITIONAL_DEPENDENCIES := \
+ $(PFW_EDD_FILES)
+
+LOCAL_REQUIRED_MODULES := \
+ PolicySubsystem.xml \
+ PolicyClass.xml \
+ audio_policy_engine_criteria.xml \
+ audio_policy_engine_criterion_types.xml \
+ ParameterFrameworkConfigurationPolicy.xml
+
+PFW_CRITERION_TYPES_FILE := $(TARGET_OUT_VENDOR_ETC)/audio_policy_engine_criterion_types.xml
+PFW_CRITERIA_FILE := $(TARGET_OUT_VENDOR_ETC)/audio_policy_engine_criteria.xml
+
+PFW_TOPLEVEL_FILE := $(TARGET_OUT_VENDOR_ETC)/parameter-framework/ParameterFrameworkConfigurationPolicy.xml
+
+PFW_SCHEMAS_DIR := $(PFW_DEFAULT_SCHEMAS_DIR)
+
+include $(BUILD_PFW_SETTINGS)
+
+endif #ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), caremu_configurable)
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/CarEmu/Settings/device_for_product_strategies.pfw b/services/audiopolicy/engineconfigurable/parameter-framework/examples/CarEmu/Settings/device_for_product_strategies.pfw
new file mode 100644
index 0000000..ca3464f
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/CarEmu/Settings/device_for_product_strategies.pfw
@@ -0,0 +1,690 @@
+supDomain: DeviceForProductStrategies
+ supDomain: OemTrafficAnouncement
+ domain: UnreachableDevices
+ conf: calibration
+ component: /Policy/policy/product_strategies/oem_traffic_anouncement/selected_output_devices/mask
+ earpiece = 0
+ speaker = 0
+ wired_headset = 0
+ wired_headphone = 0
+ bluetooth_sco = 0
+ bluetooth_sco_headset = 0
+ bluetooth_sco_carkit = 0
+ bluetooth_a2dp = 0
+ bluetooth_a2dp_headphones = 0
+ bluetooth_a2dp_speaker = 0
+ hdmi = 0
+ angl_dock_headset = 0
+ dgtl_dock_headset = 0
+ usb_accessory = 0
+ usb_device = 0
+ remote_submix = 0
+ telephony_tx = 0
+ line = 0
+ hdmi_arc = 0
+ spdif = 0
+ fm = 0
+ aux_line = 0
+ speaker_safe = 0
+ ip = 0
+ proxy = 0
+ usb_headset = 0
+ stub = 0
+ /Policy/policy/product_strategies/oem_traffic_anouncement/device_address = BUS00_MEDIA
+
+ domain: SelectedDevice
+ conf: Bus
+ AvailableOutputDevices Includes Bus
+ AvailableOutputDevicesAddresses Includes BUS00_MEDIA
+
+ component: /Policy/policy/product_strategies/oem_traffic_anouncement/selected_output_devices/mask
+ bus = 1
+
+ conf: Default
+ component: /Policy/policy/product_strategies/oem_traffic_anouncement/selected_output_devices/mask
+ bus = 0
+
+ supDomain: OemStrategy1
+ domain: UnreachableDevices
+ conf: calibration
+ component: /Policy/policy/product_strategies/oem_strategy_1/selected_output_devices/mask
+ earpiece = 0
+ speaker = 0
+ wired_headset = 0
+ wired_headphone = 0
+ bluetooth_sco = 0
+ bluetooth_sco_headset = 0
+ bluetooth_sco_carkit = 0
+ bluetooth_a2dp = 0
+ bluetooth_a2dp_headphones = 0
+ bluetooth_a2dp_speaker = 0
+ hdmi = 0
+ angl_dock_headset = 0
+ dgtl_dock_headset = 0
+ usb_accessory = 0
+ usb_device = 0
+ remote_submix = 0
+ telephony_tx = 0
+ line = 0
+ hdmi_arc = 0
+ spdif = 0
+ fm = 0
+ aux_line = 0
+ speaker_safe = 0
+ ip = 0
+ proxy = 0
+ usb_headset = 0
+ stub = 0
+ /Policy/policy/product_strategies/oem_strategy_1/device_address = BUS02_OEM1
+
+ domain: SelectedDevice
+ conf: Bus
+ AvailableOutputDevices Includes Bus
+ AvailableOutputDevicesAddresses Includes BUS02_OEM1
+
+ component: /Policy/policy/product_strategies/oem_strategy_1/selected_output_devices/mask
+ bus = 1
+
+ conf: Default
+ component: /Policy/policy/product_strategies/oem_strategy_1/selected_output_devices/mask
+ bus = 0
+
+
+
+ supDomain: OemStrategy2
+ domain: UnreachableDevices
+ conf: calibration
+ component: /Policy/policy/product_strategies/oem_strategy_2/selected_output_devices/mask
+ earpiece = 0
+ speaker = 0
+ wired_headset = 0
+ wired_headphone = 0
+ bluetooth_sco = 0
+ bluetooth_sco_headset = 0
+ bluetooth_sco_carkit = 0
+ bluetooth_a2dp = 0
+ bluetooth_a2dp_headphones = 0
+ bluetooth_a2dp_speaker = 0
+ hdmi = 0
+ angl_dock_headset = 0
+ dgtl_dock_headset = 0
+ usb_accessory = 0
+ usb_device = 0
+ remote_submix = 0
+ telephony_tx = 0
+ line = 0
+ hdmi_arc = 0
+ spdif = 0
+ fm = 0
+ aux_line = 0
+ speaker_safe = 0
+ ip = 0
+ proxy = 0
+ usb_headset = 0
+ stub = 0
+ /Policy/policy/product_strategies/oem_strategy_2/device_address = BUS01_NAV_GUIDANCE
+
+ domain: SelectedDevice
+ conf: Bus
+ AvailableOutputDevices Includes Bus
+ AvailableOutputDevicesAddresses Includes BUS01_NAV_GUIDANCE
+
+ component: /Policy/policy/product_strategies/oem_strategy_2/selected_output_devices/mask
+ bus = 1
+
+ conf: Default
+ component: /Policy/policy/product_strategies/oem_strategy_2/selected_output_devices/mask
+ bus = 0
+
+
+
+ supDomain: Radio
+ domain: UnreachableDevices
+ conf: calibration
+ component: /Policy/policy/product_strategies/radio/selected_output_devices/mask
+ earpiece = 0
+ speaker = 0
+ wired_headset = 0
+ wired_headphone = 0
+ bluetooth_sco = 0
+ bluetooth_sco_headset = 0
+ bluetooth_sco_carkit = 0
+ bluetooth_a2dp = 0
+ bluetooth_a2dp_headphones = 0
+ bluetooth_a2dp_speaker = 0
+ hdmi = 0
+ angl_dock_headset = 0
+ dgtl_dock_headset = 0
+ usb_accessory = 0
+ usb_device = 0
+ remote_submix = 0
+ telephony_tx = 0
+ line = 0
+ hdmi_arc = 0
+ spdif = 0
+ fm = 0
+ aux_line = 0
+ speaker_safe = 0
+ ip = 0
+ proxy = 0
+ usb_headset = 0
+ stub = 0
+ /Policy/policy/product_strategies/radio/device_address = BUS00_MEDIA
+
+ domain: SelectedDevice
+ conf: Bus
+ AvailableOutputDevices Includes Bus
+ AvailableOutputDevicesAddresses Includes BUS00_MEDIA
+
+ component: /Policy/policy/product_strategies/radio/selected_output_devices/mask
+ bus = 1
+
+ conf: Default
+ component: /Policy/policy/product_strategies/radio/selected_output_devices/mask
+ bus = 0
+
+ supDomain: ExtAudioSource
+ domain: UnreachableDevices
+ conf: calibration
+ component: /Policy/policy/product_strategies/ext_audio_source/selected_output_devices/mask
+ earpiece = 0
+ speaker = 0
+ wired_headset = 0
+ wired_headphone = 0
+ bluetooth_sco = 0
+ bluetooth_sco_headset = 0
+ bluetooth_sco_carkit = 0
+ bluetooth_a2dp = 0
+ bluetooth_a2dp_headphones = 0
+ bluetooth_a2dp_speaker = 0
+ hdmi = 0
+ angl_dock_headset = 0
+ dgtl_dock_headset = 0
+ usb_accessory = 0
+ usb_device = 0
+ remote_submix = 0
+ telephony_tx = 0
+ line = 0
+ hdmi_arc = 0
+ spdif = 0
+ fm = 0
+ aux_line = 0
+ speaker_safe = 0
+ ip = 0
+ proxy = 0
+ usb_headset = 0
+ stub = 0
+ /Policy/policy/product_strategies/ext_audio_source/device_address = BUS00_MEDIA
+
+ domain: SelectedDevice
+ conf: Bus
+ AvailableOutputDevices Includes Bus
+ AvailableOutputDevicesAddresses Includes BUS00_MEDIA
+
+ component: /Policy/policy/product_strategies/ext_audio_source/selected_output_devices/mask
+ bus = 1
+
+ conf: Default
+ component: /Policy/policy/product_strategies/ext_audio_source/selected_output_devices/mask
+ bus = 0
+
+
+
+ supDomain: VoiceCommand
+ domain: UnreachableDevices
+ conf: calibration
+ component: /Policy/policy/product_strategies/voice_command/selected_output_devices/mask
+ earpiece = 0
+ speaker = 0
+ wired_headset = 0
+ wired_headphone = 0
+ bluetooth_sco = 0
+ bluetooth_sco_headset = 0
+ bluetooth_sco_carkit = 0
+ bluetooth_a2dp = 0
+ bluetooth_a2dp_headphones = 0
+ bluetooth_a2dp_speaker = 0
+ hdmi = 0
+ angl_dock_headset = 0
+ dgtl_dock_headset = 0
+ usb_accessory = 0
+ usb_device = 0
+ remote_submix = 0
+ telephony_tx = 0
+ line = 0
+ hdmi_arc = 0
+ spdif = 0
+ fm = 0
+ aux_line = 0
+ speaker_safe = 0
+ ip = 0
+ proxy = 0
+ usb_headset = 0
+ stub = 0
+ /Policy/policy/product_strategies/voice_command/device_address = BUS04_VOICE
+
+ domain: SelectedDevice
+ conf: Bus
+ AvailableOutputDevices Includes Bus
+ AvailableOutputDevicesAddresses Includes BUS04_VOICE
+
+ component: /Policy/policy/product_strategies/voice_command/selected_output_devices/mask
+ bus = 1
+
+ conf: Default
+ component: /Policy/policy/product_strategies/voice_command/selected_output_devices/mask
+ bus = 0
+
+
+ supDomain: SafetyAlert
+ domain: UnreachableDevices
+ conf: calibration
+ component: /Policy/policy/product_strategies/safety_alert/selected_output_devices/mask
+ earpiece = 0
+ speaker = 0
+ wired_headset = 0
+ wired_headphone = 0
+ bluetooth_sco = 0
+ bluetooth_sco_headset = 0
+ bluetooth_sco_carkit = 0
+ bluetooth_a2dp = 0
+ bluetooth_a2dp_headphones = 0
+ bluetooth_a2dp_speaker = 0
+ hdmi = 0
+ angl_dock_headset = 0
+ dgtl_dock_headset = 0
+ usb_accessory = 0
+ usb_device = 0
+ remote_submix = 0
+ telephony_tx = 0
+ line = 0
+ hdmi_arc = 0
+ spdif = 0
+ fm = 0
+ aux_line = 0
+ speaker_safe = 0
+ ip = 0
+ proxy = 0
+ usb_headset = 0
+ stub = 0
+ /Policy/policy/product_strategies/safety_alert/device_address = BUS00_MEDIA
+
+ domain: SelectedDevice
+ conf: Bus
+ AvailableOutputDevices Includes Bus
+ AvailableOutputDevicesAddresses Includes BUS00_MEDIA
+
+ component: /Policy/policy/product_strategies/safety_alert/selected_output_devices/mask
+ bus = 1
+
+ conf: Default
+ component: /Policy/policy/product_strategies/safety_alert/selected_output_devices/mask
+ bus = 0
+
+
+ supDomain: Music
+ domain: UnreachableDevices
+ conf: calibration
+ component: /Policy/policy/product_strategies/music/selected_output_devices/mask
+ earpiece = 0
+ speaker = 0
+ wired_headset = 0
+ wired_headphone = 0
+ bluetooth_sco = 0
+ bluetooth_sco_headset = 0
+ bluetooth_sco_carkit = 0
+ bluetooth_a2dp = 0
+ bluetooth_a2dp_headphones = 0
+ bluetooth_a2dp_speaker = 0
+ hdmi = 0
+ angl_dock_headset = 0
+ dgtl_dock_headset = 0
+ usb_accessory = 0
+ usb_device = 0
+ remote_submix = 0
+ telephony_tx = 0
+ line = 0
+ hdmi_arc = 0
+ spdif = 0
+ fm = 0
+ aux_line = 0
+ speaker_safe = 0
+ ip = 0
+ proxy = 0
+ usb_headset = 0
+ stub = 0
+ /Policy/policy/product_strategies/music/device_address = BUS00_MEDIA
+
+ domain: SelectedDevice
+ conf: Bus
+ AvailableOutputDevices Includes Bus
+ AvailableOutputDevicesAddresses Includes BUS00_MEDIA
+
+ component: /Policy/policy/product_strategies/music/selected_output_devices/mask
+ bus = 1
+
+ conf: Default
+ component: /Policy/policy/product_strategies/music/selected_output_devices/mask
+ bus = 0
+
+
+
+ supDomain: NavGuidance
+ domain: UnreachableDevices
+ conf: calibration
+ component: /Policy/policy/product_strategies/nav_guidance/selected_output_devices/mask
+ earpiece = 0
+ speaker = 0
+ wired_headset = 0
+ wired_headphone = 0
+ bluetooth_sco = 0
+ bluetooth_sco_headset = 0
+ bluetooth_sco_carkit = 0
+ bluetooth_a2dp = 0
+ bluetooth_a2dp_headphones = 0
+ bluetooth_a2dp_speaker = 0
+ hdmi = 0
+ angl_dock_headset = 0
+ dgtl_dock_headset = 0
+ usb_accessory = 0
+ usb_device = 0
+ remote_submix = 0
+ telephony_tx = 0
+ line = 0
+ hdmi_arc = 0
+ spdif = 0
+ fm = 0
+ aux_line = 0
+ speaker_safe = 0
+ ip = 0
+ proxy = 0
+ usb_headset = 0
+ stub = 0
+ /Policy/policy/product_strategies/nav_guidance/device_address = BUS01_NAV_GUIDANCE
+
+ domain: SelectedDevice
+ conf: Bus
+ AvailableOutputDevices Includes Bus
+ AvailableOutputDevicesAddresses Includes BUS01_NAV_GUIDANCE
+
+ component: /Policy/policy/product_strategies/nav_guidance/selected_output_devices/mask
+ bus = 1
+
+ conf: Default
+ component: /Policy/policy/product_strategies/nav_guidance/selected_output_devices/mask
+ bus = 0
+
+
+ supDomain: VoiceCall
+ domain: UnreachableDevices
+ conf: calibration
+ component: /Policy/policy/product_strategies/voice_call/selected_output_devices/mask
+ earpiece = 0
+ speaker = 0
+ wired_headset = 0
+ wired_headphone = 0
+ bluetooth_sco = 0
+ bluetooth_sco_headset = 0
+ bluetooth_sco_carkit = 0
+ bluetooth_a2dp = 0
+ bluetooth_a2dp_headphones = 0
+ bluetooth_a2dp_speaker = 0
+ hdmi = 0
+ angl_dock_headset = 0
+ dgtl_dock_headset = 0
+ usb_accessory = 0
+ usb_device = 0
+ remote_submix = 0
+ telephony_tx = 0
+ line = 0
+ hdmi_arc = 0
+ spdif = 0
+ fm = 0
+ aux_line = 0
+ speaker_safe = 0
+ ip = 0
+ proxy = 0
+ usb_headset = 0
+ stub = 0
+ /Policy/policy/product_strategies/voice_call/device_address = BUS04_VOICE
+
+ domain: SelectedDevice
+ conf: Bus
+ AvailableOutputDevices Includes Bus
+ AvailableOutputDevicesAddresses Includes BUS04_VOICE
+
+ component: /Policy/policy/product_strategies/voice_call/selected_output_devices/mask
+ bus = 1
+
+ conf: Default
+ component: /Policy/policy/product_strategies/voice_call/selected_output_devices/mask
+ bus = 0
+
+
+ supDomain: Alarm
+ domain: UnreachableDevices
+ conf: calibration
+ component: /Policy/policy/product_strategies/alarm/selected_output_devices/mask
+ earpiece = 0
+ speaker = 0
+ wired_headset = 0
+ wired_headphone = 0
+ bluetooth_sco = 0
+ bluetooth_sco_headset = 0
+ bluetooth_sco_carkit = 0
+ bluetooth_a2dp = 0
+ bluetooth_a2dp_headphones = 0
+ bluetooth_a2dp_speaker = 0
+ hdmi = 0
+ angl_dock_headset = 0
+ dgtl_dock_headset = 0
+ usb_accessory = 0
+ usb_device = 0
+ remote_submix = 0
+ telephony_tx = 0
+ line = 0
+ hdmi_arc = 0
+ spdif = 0
+ fm = 0
+ aux_line = 0
+ speaker_safe = 0
+ ip = 0
+ proxy = 0
+ usb_headset = 0
+ stub = 0
+ /Policy/policy/product_strategies/alarm/device_address = BUS00_MEDIA
+
+ domain: SelectedDevice
+ conf: Bus
+ AvailableOutputDevices Includes Bus
+ AvailableOutputDevicesAddresses Includes BUS00_MEDIA
+
+ component: /Policy/policy/product_strategies/alarm/selected_output_devices/mask
+ bus = 1
+
+ conf: Default
+ component: /Policy/policy/product_strategies/alarm/selected_output_devices/mask
+ bus = 0
+
+
+ supDomain: Ring
+ domain: UnreachableDevices
+ conf: calibration
+ component: /Policy/policy/product_strategies/ring/selected_output_devices/mask
+ earpiece = 0
+ speaker = 0
+ wired_headset = 0
+ wired_headphone = 0
+ bluetooth_sco = 0
+ bluetooth_sco_headset = 0
+ bluetooth_sco_carkit = 0
+ bluetooth_a2dp = 0
+ bluetooth_a2dp_headphones = 0
+ bluetooth_a2dp_speaker = 0
+ hdmi = 0
+ angl_dock_headset = 0
+ dgtl_dock_headset = 0
+ usb_accessory = 0
+ usb_device = 0
+ remote_submix = 0
+ telephony_tx = 0
+ line = 0
+ hdmi_arc = 0
+ spdif = 0
+ fm = 0
+ aux_line = 0
+ speaker_safe = 0
+ ip = 0
+ proxy = 0
+ usb_headset = 0
+ stub = 0
+ /Policy/policy/product_strategies/ring/device_address = BUS04_VOICE
+
+ domain: SelectedDevice
+ conf: Bus
+ AvailableOutputDevices Includes Bus
+ AvailableOutputDevicesAddresses Includes BUS04_VOICE
+
+ component: /Policy/policy/product_strategies/ring/selected_output_devices/mask
+ bus = 1
+
+ conf: Default
+ component: /Policy/policy/product_strategies/ring/selected_output_devices/mask
+ bus = 0
+
+
+ supDomain: Notification
+ domain: UnreachableDevices
+ conf: calibration
+ component: /Policy/policy/product_strategies/notification/selected_output_devices/mask
+ earpiece = 0
+ speaker = 0
+ wired_headset = 0
+ wired_headphone = 0
+ bluetooth_sco = 0
+ bluetooth_sco_headset = 0
+ bluetooth_sco_carkit = 0
+ bluetooth_a2dp = 0
+ bluetooth_a2dp_headphones = 0
+ bluetooth_a2dp_speaker = 0
+ hdmi = 0
+ angl_dock_headset = 0
+ dgtl_dock_headset = 0
+ usb_accessory = 0
+ usb_device = 0
+ remote_submix = 0
+ telephony_tx = 0
+ line = 0
+ hdmi_arc = 0
+ spdif = 0
+ fm = 0
+ aux_line = 0
+ speaker_safe = 0
+ ip = 0
+ proxy = 0
+ usb_headset = 0
+ stub = 0
+ /Policy/policy/product_strategies/notification/device_address = BUS00_MEDIA
+
+ domain: SelectedDevice
+ conf: Bus
+ AvailableOutputDevices Includes Bus
+ AvailableOutputDevicesAddresses Includes BUS00_MEDIA
+
+ component: /Policy/policy/product_strategies/notification/selected_output_devices/mask
+ bus = 1
+
+ conf: Default
+ component: /Policy/policy/product_strategies/notification/selected_output_devices/mask
+ bus = 0
+
+
+ supDomain: System
+ domain: UnreachableDevices
+ conf: calibration
+ component: /Policy/policy/product_strategies/system/selected_output_devices/mask
+ earpiece = 0
+ speaker = 0
+ wired_headset = 0
+ wired_headphone = 0
+ bluetooth_sco = 0
+ bluetooth_sco_headset = 0
+ bluetooth_sco_carkit = 0
+ bluetooth_a2dp = 0
+ bluetooth_a2dp_headphones = 0
+ bluetooth_a2dp_speaker = 0
+ hdmi = 0
+ angl_dock_headset = 0
+ dgtl_dock_headset = 0
+ usb_accessory = 0
+ usb_device = 0
+ remote_submix = 0
+ telephony_tx = 0
+ line = 0
+ hdmi_arc = 0
+ spdif = 0
+ fm = 0
+ aux_line = 0
+ speaker_safe = 0
+ ip = 0
+ proxy = 0
+ usb_headset = 0
+ stub = 0
+ /Policy/policy/product_strategies/system/device_address = BUS03_SYSTEM_SOUND
+
+ domain: SelectedDevice
+ conf: Bus
+ AvailableOutputDevices Includes Bus
+ AvailableOutputDevicesAddresses Includes BUS03_SYSTEM_SOUND
+
+ component: /Policy/policy/product_strategies/system/selected_output_devices/mask
+ bus = 1
+
+ conf: Default
+ component: /Policy/policy/product_strategies/system/selected_output_devices/mask
+ bus = 0
+
+ supDomain: Tts
+ domain: UnreachableDevices
+ conf: calibration
+ component: /Policy/policy/product_strategies/tts/selected_output_devices/mask
+ earpiece = 0
+ speaker = 0
+ wired_headset = 0
+ wired_headphone = 0
+ bluetooth_sco = 0
+ bluetooth_sco_headset = 0
+ bluetooth_sco_carkit = 0
+ bluetooth_a2dp = 0
+ bluetooth_a2dp_headphones = 0
+ bluetooth_a2dp_speaker = 0
+ hdmi = 0
+ angl_dock_headset = 0
+ dgtl_dock_headset = 0
+ usb_accessory = 0
+ usb_device = 0
+ remote_submix = 0
+ telephony_tx = 0
+ line = 0
+ hdmi_arc = 0
+ spdif = 0
+ fm = 0
+ aux_line = 0
+ speaker_safe = 0
+ ip = 0
+ proxy = 0
+ usb_headset = 0
+ stub = 0
+ /Policy/policy/product_strategies/tts/device_address = BUS00_MEDIA
+
+ domain: SelectedDevice
+ conf: Bus
+ AvailableOutputDevices Includes Bus
+ AvailableOutputDevicesAddresses Includes BUS00_MEDIA
+
+ component: /Policy/policy/product_strategies/tts/selected_output_devices/mask
+ bus = 1
+
+ conf: Default
+ component: /Policy/policy/product_strategies/tts/selected_output_devices/mask
+ bus = 0
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Android.mk b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Android.mk
index e9d67e9..d1845b8 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Android.mk
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Android.mk
@@ -22,37 +22,9 @@
# CONFIGURATION FILES
##################################################################
########## Policy PFW Structures #########
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := PolicySubsystem.xml.phone
-LOCAL_MODULE_STEM := PolicySubsystem.xml
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_REQUIRED_MODULES := \
- PolicySubsystem-CommonTypes.xml \
- ProductStrategies.xml.phone \
- PolicySubsystem-Volume.xml \
- libpolicy-subsystem \
-
-LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Structure/Policy
-LOCAL_SRC_FILES := Structure/$(LOCAL_MODULE_STEM)
-include $(BUILD_PREBUILT)
-
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := ProductStrategies.xml.phone
-LOCAL_MODULE_STEM := ProductStrategies.xml
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Structure/Policy
-LOCAL_SRC_FILES := Structure/$(LOCAL_MODULE_STEM)
-include $(BUILD_PREBUILT)
-
######### Policy PFW Settings #########
include $(CLEAR_VARS)
-LOCAL_MODULE := parameter-framework.policy.phone
+LOCAL_MODULE := parameter-framework.policy
LOCAL_MODULE_STEM := PolicyConfigurableDomains.xml
LOCAL_MODULE_CLASS := ETC
LOCAL_VENDOR_MODULE := true
@@ -68,15 +40,15 @@
$(LOCAL_PATH)/Settings/device_for_product_strategy_phone.pfw \
$(LOCAL_PATH)/Settings/device_for_product_strategy_sonification.pfw \
$(LOCAL_PATH)/Settings/device_for_product_strategy_sonification_respectful.pfw \
- $(LOCAL_PATH)/Settings/device_for_product_strategy_rerouting.pfw \
$(LOCAL_PATH)/Settings/device_for_product_strategy_transmitted_through_speaker.pfw \
- $(LOCAL_PATH)/Settings/device_for_product_strategy_unknown.pfw
+ $(LOCAL_PATH)/Settings/device_for_product_strategy_rerouting.pfw \
+ $(LOCAL_PATH)/Settings/device_for_product_strategy_patch.pfw
LOCAL_ADDITIONAL_DEPENDENCIES := \
$(PFW_EDD_FILES)
LOCAL_REQUIRED_MODULES := \
- PolicySubsystem.xml.phone \
+ PolicySubsystem.xml \
PolicyClass.xml \
audio_policy_engine_criteria.xml \
audio_policy_engine_criterion_types.xml \
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_unknown.pfw b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_patch.pfw
similarity index 79%
rename from services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_unknown.pfw
rename to services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_patch.pfw
index c46cf56..d2cc090 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_unknown.pfw
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_patch.pfw
@@ -1,8 +1,8 @@
supDomain: DeviceForProductStrategy
- supDomain: Unknown
+ supDomain: Patch
domain: UnreachableDevices
conf: calibration
- component: /Policy/policy/product_strategies/unknown/selected_output_devices/mask
+ component: /Policy/policy/product_strategies/patch/selected_output_devices/mask
earpiece = 0
speaker = 0
wired_headset = 0
@@ -31,6 +31,6 @@
usb_headset = 0
bus = 0
stub = 0
- /Policy/policy/product_strategies/unknown/device_address =
+ /Policy/policy/product_strategies/patch/device_address =
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_rerouting.pfw b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_rerouting.pfw
index c064c18..10f8814 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_rerouting.pfw
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_rerouting.pfw
@@ -29,15 +29,8 @@
ip = 0
proxy = 0
usb_headset = 0
+ bus = 0
stub = 0
/Policy/policy/product_strategies/rerouting/device_address =
- domain: SelectedDevice
- conf: Bus
- component: /Policy/policy/product_strategies/rerouting/selected_output_devices/mask
- bus = 1
-
- conf: Default
- component: /Policy/policy/product_strategies/rerouting/selected_output_devices/mask
- bus = 0
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Structure/PolicySubsystem.xml b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Structure/PolicySubsystem.xml
deleted file mode 100644
index b55ce2c..0000000
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Structure/PolicySubsystem.xml
+++ /dev/null
@@ -1,88 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 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.
--->
-<Subsystem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:xi="http://www.w3.org/2001/XInclude"
- xsi:noNamespaceSchemaLocation="Schemas/Subsystem.xsd"
- Name="policy" Type="Policy">
-
- <ComponentLibrary>
- <!--#################### GLOBAL COMPONENTS BEGIN ####################-->
- <!-- Common Types defintion -->
- <xi:include href="PolicySubsystem-CommonTypes.xml"/>
- <xi:include href="ProductStrategies.xml"/>
-
-
- <!--#################### GLOBAL COMPONENTS END ####################-->
-
- <!--#################### STREAM BEGIN ####################-->
-
- <ComponentType Name="Streams" Description="associated to audio_stream_type_t definition">
- <Component Name="voice_call" Type="Stream" Mapping="Name:AUDIO_STREAM_VOICE_CALL"/>
- <Component Name="system" Type="Stream" Mapping="Name:AUDIO_STREAM_SYSTEM"/>
- <Component Name="ring" Type="Stream" Mapping="Name:AUDIO_STREAM_RING"/>
- <Component Name="music" Type="Stream" Mapping="Name:AUDIO_STREAM_MUSIC"/>
- <Component Name="alarm" Type="Stream" Mapping="Name:AUDIO_STREAM_ALARM"/>
- <Component Name="notification" Type="Stream" Mapping="Name:AUDIO_STREAM_NOTIFICATION"/>
- <Component Name="bluetooth_sco" Type="Stream" Mapping="Name:AUDIO_STREAM_BLUETOOTH_SCO"/>
- <Component Name="enforced_audible" Type="Stream" Mapping="Name:AUDIO_STREAM_ENFORCED_AUDIBLE"
- Description="Sounds that cannot be muted by user and must be routed to speaker"/>
- <Component Name="dtmf" Type="Stream" Mapping="Name:AUDIO_STREAM_DTMF"/>
- <Component Name="tts" Type="Stream" Mapping="Name:AUDIO_STREAM_TTS"
- Description="Transmitted Through Speaker. Plays over speaker only, silent on other devices"/>
- <Component Name="accessibility" Type="Stream" Mapping="Name:AUDIO_STREAM_ACCESSIBILITY"
- Description="For accessibility talk back prompts"/>
- <Component Name="rerouting" Type="Stream" Mapping="Name:AUDIO_STREAM_REROUTING"
- Description="For dynamic policy output mixes"/>
- <Component Name="patch" Type="Stream" Mapping="Name:AUDIO_STREAM_PATCH"
- Description="For internal audio flinger tracks. Fixed volume"/>
- </ComponentType>
-
- <!--#################### STREAM END ####################-->
-
- <!--#################### INPUT SOURCE BEGIN ####################-->
-
- <ComponentType Name="InputSources" Description="associated to audio_source_t definition,
- identifier mapping must match the value of the enum">
- <Component Name="default" Type="InputSource" Mapping="Name:AUDIO_SOURCE_DEFAULT"/>
- <Component Name="mic" Type="InputSource" Mapping="Name:AUDIO_SOURCE_MIC"/>
- <Component Name="voice_uplink" Type="InputSource"
- Mapping="Name:AUDIO_SOURCE_VOICE_UPLINK"/>
- <Component Name="voice_downlink" Type="InputSource"
- Mapping="Name:AUDIO_SOURCE_VOICE_DOWNLINK"/>
- <Component Name="voice_call" Type="InputSource"
- Mapping="Name:AUDIO_SOURCE_VOICE_CALL"/>
- <Component Name="camcorder" Type="InputSource" Mapping="Name:AUDIO_SOURCE_CAMCORDER"/>
- <Component Name="voice_recognition" Type="InputSource"
- Mapping="Name:AUDIO_SOURCE_VOICE_RECOGNITION"/>
- <Component Name="voice_communication" Type="InputSource"
- Mapping="Name:AUDIO_SOURCE_VOICE_COMMUNICATION"/>
- <Component Name="remote_submix" Type="InputSource"
- Mapping="Name:AUDIO_SOURCE_REMOTE_SUBMIX"/>
- <Component Name="unprocessed" Type="InputSource"
- Mapping="Name:AUDIO_SOURCE_UNPROCESSED"/>
- <Component Name="fm_tuner" Type="InputSource" Mapping="Name:AUDIO_SOURCE_FM_TUNER"/>
- <Component Name="hotword" Type="InputSource" Mapping="Name:AUDIO_SOURCE_HOTWORD"/>
- </ComponentType>
-
- <!--#################### INPUT SOURCE END ####################-->
- </ComponentLibrary>
-
- <InstanceDefinition>
- <Component Name="streams" Type="Streams"/>
- <Component Name="input_sources" Type="InputSources"/>
- <Component Name="product_strategies" Type="ProductStrategies"/>
- </InstanceDefinition>
-</Subsystem>
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Structure/ProductStrategies.xml b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Structure/ProductStrategies.xml
deleted file mode 100644
index 4cbb3da..0000000
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Structure/ProductStrategies.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 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.
--->
-<ComponentTypeSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:xi="http://www.w3.org/2001/XInclude"
- xsi:noNamespaceSchemaLocation="Schemas/ComponentTypeSet.xsd">
-
- <ComponentType Name="ProductStrategies" Description="">
- <Component Name="accessibility" Type="ProductStrategy"/>
- <Component Name="enforced_audible" Type="ProductStrategy"/>
- <Component Name="transmitted_through_speaker" Type="ProductStrategy"/>
-
- <Component Name="media" Type="ProductStrategy"/>
- <Component Name="phone" Type="ProductStrategy"/>
- <Component Name="dtmf" Type="ProductStrategy"/>
-
- <Component Name="sonification" Type="ProductStrategy"/>
- <Component Name="sonification_respectful" Type="ProductStrategy"/>
- <Component Name="rerouting" Type="ProductStrategy"/>
- <Component Name="unknown" Type="ProductStrategy"/>
- </ComponentType>
-
-</ComponentTypeSet>
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Structure/PolicyClass.xml b/services/audiopolicy/engineconfigurable/parameter-framework/examples/common/Structure/PolicyClass.xml
similarity index 100%
rename from services/audiopolicy/engineconfigurable/parameter-framework/examples/Structure/PolicyClass.xml
rename to services/audiopolicy/engineconfigurable/parameter-framework/examples/common/Structure/PolicyClass.xml
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Structure/PolicySubsystem-CommonTypes.xml b/services/audiopolicy/engineconfigurable/parameter-framework/examples/common/Structure/PolicySubsystem-CommonTypes.xml
similarity index 100%
rename from services/audiopolicy/engineconfigurable/parameter-framework/examples/Structure/PolicySubsystem-CommonTypes.xml
rename to services/audiopolicy/engineconfigurable/parameter-framework/examples/common/Structure/PolicySubsystem-CommonTypes.xml
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Structure/PolicySubsystem.xml b/services/audiopolicy/engineconfigurable/parameter-framework/examples/common/Structure/PolicySubsystem-no-strategy.xml
similarity index 100%
rename from services/audiopolicy/engineconfigurable/parameter-framework/examples/Structure/PolicySubsystem.xml
rename to services/audiopolicy/engineconfigurable/parameter-framework/examples/common/Structure/PolicySubsystem-no-strategy.xml
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Car/Structure/PolicySubsystem.xml b/services/audiopolicy/engineconfigurable/parameter-framework/examples/common/Structure/PolicySubsystem.xml
similarity index 100%
rename from services/audiopolicy/engineconfigurable/parameter-framework/examples/Car/Structure/PolicySubsystem.xml
rename to services/audiopolicy/engineconfigurable/parameter-framework/examples/common/Structure/PolicySubsystem.xml
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/common/Structure/ProductStrategies.xml.in b/services/audiopolicy/engineconfigurable/parameter-framework/examples/common/Structure/ProductStrategies.xml.in
new file mode 100644
index 0000000..2760b25
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/common/Structure/ProductStrategies.xml.in
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2019 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.
+-->
+<ComponentTypeSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:xi="http://www.w3.org/2001/XInclude"
+ xsi:noNamespaceSchemaLocation="Schemas/ComponentTypeSet.xsd">
+
+ <!-- automatically populate the strategy structure plugin file from Engine Configuration XML file
+ Component Name="xxx" Type="ProductStrategy"/-->
+ <ComponentType Name="ProductStrategies" Description="">
+ </ComponentType>
+
+</ComponentTypeSet>
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/PolicySubsystem.cpp b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/PolicySubsystem.cpp
index bfc1bca..8bd7f66 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/PolicySubsystem.cpp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/PolicySubsystem.cpp
@@ -72,7 +72,7 @@
);
addSubsystemObjectFactory(
new TSubsystemObjectFactory<ProductStrategy>(
- mProductStrategyComponentName, 0)
+ mProductStrategyComponentName, (1 << MappingKeyName))
);
}
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/ProductStrategy.cpp b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/ProductStrategy.cpp
index bb29ef1..ebd9456 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/ProductStrategy.cpp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/ProductStrategy.cpp
@@ -32,6 +32,8 @@
(MappingKeyAmendEnd - MappingKeyAmend1 + 1),
context)
{
+ std::string name(context.getItem(MappingKeyName));
+
ALOG_ASSERT(instanceConfigurableElement != nullptr, "Invalid Configurable Element");
mPolicySubsystem = static_cast<const PolicySubsystem *>(
instanceConfigurableElement->getBelongingSubsystem());
@@ -40,7 +42,6 @@
mPolicyPluginInterface = mPolicySubsystem->getPolicyPluginInterface();
ALOG_ASSERT(mPolicyPluginInterface != nullptr, "Invalid Policy Plugin Interface");
- std::string name(instanceConfigurableElement->getName());
mId = mPolicyPluginInterface->getProductStrategyByName(name);
ALOG_ASSERT(mId != PRODUCT_STRATEGY_INVALID, "Product Strategy %s not found", name.c_str());
diff --git a/services/audiopolicy/engineconfigurable/tools/Android.bp b/services/audiopolicy/engineconfigurable/tools/Android.bp
index d8f29dc..8c16972 100644
--- a/services/audiopolicy/engineconfigurable/tools/Android.bp
+++ b/services/audiopolicy/engineconfigurable/tools/Android.bp
@@ -12,13 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-python_binary_host {
- name: "buildPolicyCriterionTypes.py",
- owner: "renault",
- main: "buildPolicyCriterionTypes.py",
- srcs: [
- "buildPolicyCriterionTypes.py",
- ],
+python_defaults {
+ name: "tools_default",
version: {
py2: {
enabled: true,
@@ -29,3 +24,37 @@
},
}
+python_binary_host {
+ name: "buildPolicyCriterionTypes.py",
+ main: "buildPolicyCriterionTypes.py",
+ srcs: [
+ "buildPolicyCriterionTypes.py",
+ ],
+ defaults: ["tools_default"],
+}
+
+python_binary_host {
+ name: "domainGeneratorPolicy.py",
+ main: "domainGeneratorPolicy.py",
+ srcs: [
+ "domainGeneratorPolicy.py",
+ ],
+ defaults: ["tools_default"],
+ libs: [
+ "EddParser.py",
+ "hostConfig.py",
+ "PFWScriptGenerator.py",
+ ],
+ required: [
+ "domainGeneratorConnector",
+ ],
+}
+
+python_binary_host {
+ name: "buildStrategiesStructureFile.py",
+ main: "buildStrategiesStructureFile.py",
+ srcs: [
+ "buildStrategiesStructureFile.py",
+ ],
+ defaults: ["tools_default"],
+}
diff --git a/services/audiopolicy/engineconfigurable/tools/buildStrategiesStructureFile.py b/services/audiopolicy/engineconfigurable/tools/buildStrategiesStructureFile.py
new file mode 100755
index 0000000..ee70b26
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/tools/buildStrategiesStructureFile.py
@@ -0,0 +1,139 @@
+#!/usr/bin/python
+
+#
+# Copyright 2019, 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.
+#
+
+import argparse
+import re
+import sys
+import tempfile
+import os
+import logging
+import subprocess
+import xml.etree.ElementTree as ET
+import xml.etree.ElementInclude as EI
+import xml.dom.minidom as MINIDOM
+from collections import OrderedDict
+
+#
+# Helper script that helps to feed at build time the XML Product Strategies Structure file file used
+# by the engineconfigurable to start the parameter-framework.
+# It prevents to fill them manually and avoid divergences with android.
+#
+# The Product Strategies Structure file is fed from the audio policy engine configuration file
+# in order to discover all the strategies available for the current platform.
+# --audiopolicyengineconfigurationfile <path/to/audio_policy_engine_configuration.xml>
+#
+# The reference file of ProductStrategies structure must also be set as an input of the script:
+# --productstrategiesstructurefile <path/to/structure/file/ProductStrategies.xml.in>
+#
+# At last, the output of the script shall be set also:
+# --outputfile <path/to/out/<system|vendor|odm>/etc/ProductStrategies.xml>
+#
+
+def parseArgs():
+ argparser = argparse.ArgumentParser(description="Parameter-Framework XML \
+ product strategies structure file generator.\n\
+ Exit with the number of (recoverable or not) error that occured.")
+ argparser.add_argument('--audiopolicyengineconfigurationfile',
+ help="Android Audio Policy Engine Configuration file, Mandatory.",
+ metavar="(AUDIO_POLICY_ENGINE_CONFIGURATION_FILE)",
+ type=argparse.FileType('r'),
+ required=True)
+ argparser.add_argument('--productstrategiesstructurefile',
+ help="Product Strategies Structure XML base file, Mandatory.",
+ metavar="STRATEGIES_STRUCTURE_FILE",
+ type=argparse.FileType('r'),
+ required=True)
+ argparser.add_argument('--outputfile',
+ help="Product Strategies Structure output file, Mandatory.",
+ metavar="STRATEGIES_STRUCTURE_OUTPUT_FILE",
+ type=argparse.FileType('w'),
+ required=True)
+ argparser.add_argument('--verbose',
+ action='store_true')
+
+ return argparser.parse_args()
+
+
+def generateXmlStructureFile(strategies, strategyStructureInFile, outputFile):
+
+ logging.info("Importing strategyStructureInFile {}".format(strategyStructureInFile))
+ strategies_in_tree = ET.parse(strategyStructureInFile)
+
+ strategies_root = strategies_in_tree.getroot()
+ strategy_components = strategies_root.find('ComponentType')
+
+ for strategy_name in strategies:
+ context_mapping = "".join(map(str, ["Name:", strategy_name]))
+ strategy_pfw_name = strategy_name.replace('STRATEGY_', '').lower()
+ strategy_component_node = ET.SubElement(strategy_components, "Component", Name=strategy_pfw_name, Type="ProductStrategy", Mapping=context_mapping)
+
+ xmlstr = ET.tostring(strategies_root, encoding='utf8', method='xml')
+ reparsed = MINIDOM.parseString(xmlstr)
+ prettyXmlStr = reparsed.toprettyxml(newl='\r\n')
+ prettyXmlStr = os.linesep.join([s for s in prettyXmlStr.splitlines() if s.strip()])
+ outputFile.write(prettyXmlStr.encode('utf-8'))
+
+def capitalizeLine(line):
+ return ' '.join((w.capitalize() for w in line.split(' ')))
+
+
+#
+# Parse the audio policy configuration file and output a dictionary of device criteria addresses
+#
+def parseAndroidAudioPolicyEngineConfigurationFile(audiopolicyengineconfigurationfile):
+
+ logging.info("Checking Audio Policy Engine Configuration file {}".format(audiopolicyengineconfigurationfile))
+ #
+ # extract all product strategies name from audio policy engine configuration file
+ #
+ strategy_names = []
+
+ oldWorkingDir = os.getcwd()
+ print "Current working directory %s" % oldWorkingDir
+
+ newDir = os.path.join(oldWorkingDir , audiopolicyengineconfigurationfile.name)
+
+ policy_engine_in_tree = ET.parse(audiopolicyengineconfigurationfile)
+ os.chdir(os.path.dirname(os.path.normpath(newDir)))
+
+ print "new working directory %s" % os.getcwd()
+
+ policy_engine_root = policy_engine_in_tree.getroot()
+ EI.include(policy_engine_root)
+
+ os.chdir(oldWorkingDir)
+
+ for strategy in policy_engine_root.iter('ProductStrategy'):
+ strategy_names.append(strategy.get('name'))
+
+ return strategy_names
+
+
+def main():
+ logging.root.setLevel(logging.INFO)
+ args = parseArgs()
+
+ strategies = parseAndroidAudioPolicyEngineConfigurationFile(args.audiopolicyengineconfigurationfile)
+
+ product_strategies_structure = args.productstrategiesstructurefile
+
+ generateXmlStructureFile(strategies, product_strategies_structure, args.outputfile)
+
+# If this file is directly executed
+if __name__ == "__main__":
+ exit(main())
diff --git a/services/audiopolicy/engineconfigurable/tools/provision_strategies_structure.mk b/services/audiopolicy/engineconfigurable/tools/provision_strategies_structure.mk
new file mode 100644
index 0000000..72c938c
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/tools/provision_strategies_structure.mk
@@ -0,0 +1,21 @@
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): MY_STRATEGIES_STRUCTURE_FILE := $(STRATEGIES_STRUCTURE_FILE)
+$(LOCAL_BUILT_MODULE): MY_AUDIO_POLICY_ENGINE_CONFIGURATION_FILE := $(AUDIO_POLICY_ENGINE_CONFIGURATION_FILE)
+$(LOCAL_BUILT_MODULE): MY_PROVISION_TOOL := $(HOST_OUT)/bin/buildStrategiesStructureFile.py
+$(LOCAL_BUILT_MODULE): $(LOCAL_REQUIRED_MODULES) $(LOCAL_ADDITIONAL_DEPENDENCIES) \
+ buildStrategiesStructureFile.py \
+ $(STRATEGIES_STRUCTURE_FILE) \
+ $(AUDIO_POLICY_ENGINE_CONFIGURATION_FILE)
+
+ "$(MY_PROVISION_TOOL)" \
+ --audiopolicyengineconfigurationfile "$(MY_AUDIO_POLICY_ENGINE_CONFIGURATION_FILE)" \
+ --productstrategiesstructurefile "$(MY_STRATEGIES_STRUCTURE_FILE)" \
+ --outputfile "$(@)"
+
+# Clear variables for further use
+STRATEGIES_STRUCTURE_FILE :=
+AUDIO_POLICY_ENGINE_CONFIGURATION_FILE :=
diff --git a/services/audiopolicy/enginedefault/config/example/Android.mk b/services/audiopolicy/enginedefault/config/example/Android.mk
index f06ee4c..0badac8 100644
--- a/services/audiopolicy/enginedefault/config/example/Android.mk
+++ b/services/audiopolicy/enginedefault/config/example/Android.mk
@@ -7,28 +7,26 @@
ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), phone_default)
include $(CLEAR_VARS)
-LOCAL_MODULE := audio_policy_engine_configuration_phone.xml
-LOCAL_MODULE_STEM := audio_policy_engine_configuration.xml
+LOCAL_MODULE := audio_policy_engine_configuration.xml
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := ETC
LOCAL_VENDOR_MODULE := true
-LOCAL_SRC_FILES := phone/$(LOCAL_MODULE_STEM)
+LOCAL_SRC_FILES := phone/$(LOCAL_MODULE)
LOCAL_REQUIRED_MODULES := \
- audio_policy_engine_product_strategies_phone.xml \
+ audio_policy_engine_product_strategies.xml \
audio_policy_engine_stream_volumes.xml \
audio_policy_engine_default_stream_volumes.xml
include $(BUILD_PREBUILT)
include $(CLEAR_VARS)
-LOCAL_MODULE := audio_policy_engine_product_strategies_phone.xml
-LOCAL_MODULE_STEM := audio_policy_engine_product_strategies.xml
+LOCAL_MODULE := audio_policy_engine_product_strategies.xml
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := ETC
LOCAL_VENDOR_MODULE := true
-LOCAL_SRC_FILES := phone/$(LOCAL_MODULE_STEM)
+LOCAL_SRC_FILES := phone/$(LOCAL_MODULE)
include $(BUILD_PREBUILT)
include $(CLEAR_VARS)
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 4a0e764..a12bdaa 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -169,8 +169,6 @@
broadcastDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE);
return INVALID_OPERATION;
}
- // Propagate device availability to Engine
- mEngine->setDeviceConnectionState(device, state);
// outputs should never be empty here
ALOG_ASSERT(outputs.size() != 0, "setDeviceConnectionState():"
@@ -200,8 +198,6 @@
// Reset active device codec
device->setEncodedFormat(AUDIO_FORMAT_DEFAULT);
- // Propagate device availability to Engine
- mEngine->setDeviceConnectionState(device, state);
} break;
default:
@@ -209,6 +205,9 @@
return BAD_VALUE;
}
+ // Propagate device availability to Engine
+ setEngineDeviceConnectionState(device, state);
+
// No need to evaluate playback routing when connecting a remote submix
// output device used by a dynamic policy of type recorder as no
// playback use case is affected.
@@ -318,9 +317,6 @@
if (mAvailableInputDevices.add(device) < 0) {
return NO_MEMORY;
}
-
- // Propagate device availability to Engine
- mEngine->setDeviceConnectionState(device, state);
} break;
// handle input device disconnection
@@ -337,9 +333,6 @@
checkInputsForDevice(device, state, inputs);
mAvailableInputDevices.remove(device);
-
- // Propagate device availability to Engine
- mEngine->setDeviceConnectionState(device, state);
} break;
default:
@@ -347,6 +340,9 @@
return BAD_VALUE;
}
+ // Propagate device availability to Engine
+ setEngineDeviceConnectionState(device, state);
+
closeAllInputs();
// As the input device list can impact the output device selection, update
// getDeviceForStrategy() cache
@@ -369,6 +365,17 @@
return BAD_VALUE;
}
+void AudioPolicyManager::setEngineDeviceConnectionState(const sp<DeviceDescriptor> device,
+ audio_policy_dev_state_t state) {
+
+ // the Engine does not have to know about remote submix devices used by dynamic audio policies
+ if (audio_is_remote_submix_device(device->type()) && device->address() != "0") {
+ return;
+ }
+ mEngine->setDeviceConnectionState(device, state);
+}
+
+
audio_policy_dev_state_t AudioPolicyManager::getDeviceConnectionState(audio_devices_t device,
const char *device_address)
{
@@ -945,6 +952,9 @@
if (status != NO_ERROR) {
return status;
}
+ if (auto it = mAllowedCapturePolicies.find(uid); it != end(mAllowedCapturePolicies)) {
+ resultAttr->flags |= it->second;
+ }
*stream = mEngine->getStreamTypeForAttributes(*resultAttr);
ALOGV("%s() attributes=%s stream=%s session %d selectedDeviceId %d", __func__,
@@ -2025,7 +2035,7 @@
mSoundTriggerSessions.indexOfKey(session) > 0;
*portId = AudioPort::getNextUniqueId();
- clientDesc = new RecordClientDescriptor(*portId, uid, session, *attr, *config,
+ clientDesc = new RecordClientDescriptor(*portId, uid, session, attributes, *config,
requestedDeviceId, attributes.source, flags,
isSoundTrigger);
inputDesc = mInputs.valueFor(*input);
@@ -2389,14 +2399,9 @@
audio_devices_t device)
{
auto attributes = mEngine->getAttributesForStreamType(stream);
- auto volumeGroup = mEngine->getVolumeGroupForStreamType(stream);
- if (volumeGroup == VOLUME_GROUP_NONE) {
- ALOGE("%s: no group matching with stream %s", __FUNCTION__, toString(stream).c_str());
- return BAD_VALUE;
- }
ALOGV("%s: stream %s attributes=%s", __func__,
toString(stream).c_str(), toString(attributes).c_str());
- return setVolumeGroupIndex(getVolumeCurves(stream), volumeGroup, index, device, attributes);
+ return setVolumeIndexForAttributes(attributes, index, device);
}
status_t AudioPolicyManager::getStreamVolumeIndex(audio_stream_type_t stream,
@@ -2411,27 +2416,19 @@
return getVolumeIndex(getVolumeCurves(stream), *index, device);
}
-status_t AudioPolicyManager::setVolumeIndexForAttributes(const audio_attributes_t &attr,
+status_t AudioPolicyManager::setVolumeIndexForAttributes(const audio_attributes_t &attributes,
int index,
audio_devices_t device)
{
// Get Volume group matching the Audio Attributes
- auto volumeGroup = mEngine->getVolumeGroupForAttributes(attr);
- if (volumeGroup == VOLUME_GROUP_NONE) {
- ALOGD("%s: could not find group matching with %s", __FUNCTION__, toString(attr).c_str());
+ auto group = mEngine->getVolumeGroupForAttributes(attributes);
+ if (group == VOLUME_GROUP_NONE) {
+ ALOGD("%s: no group matching with %s", __FUNCTION__, toString(attributes).c_str());
return BAD_VALUE;
}
- ALOGV("%s: group %d matching with %s", __FUNCTION__, volumeGroup, toString(attr).c_str());
- return setVolumeGroupIndex(getVolumeCurves(attr), volumeGroup, index, device, attr);
-}
-
-status_t AudioPolicyManager::setVolumeGroupIndex(IVolumeCurves &curves, volume_group_t group,
- int index,
- audio_devices_t device,
- const audio_attributes_t attributes)
-{
- ALOGVV("%s: group=%d", __func__, group);
+ ALOGV("%s: group %d matching with %s", __FUNCTION__, group, toString(attributes).c_str());
status_t status = NO_ERROR;
+ IVolumeCurves &curves = getVolumeCurves(attributes);
VolumeSource vs = toVolumeSource(group);
product_strategy_t strategy = mEngine->getProductStrategyForAttributes(attributes);
@@ -2440,6 +2437,21 @@
ALOGE("%s failed to set curve index for group %d device 0x%X", __func__, group, device);
return status;
}
+
+ audio_devices_t curSrcDevice;
+ auto curCurvAttrs = curves.getAttributes();
+ if (!curCurvAttrs.empty() && curCurvAttrs.front() != defaultAttr) {
+ auto attr = curCurvAttrs.front();
+ curSrcDevice = mEngine->getOutputDevicesForAttributes(attr, nullptr, false).types();
+ } else if (!curves.getStreamTypes().empty()) {
+ auto stream = curves.getStreamTypes().front();
+ curSrcDevice = mEngine->getOutputDevicesForStream(stream, false).types();
+ } else {
+ ALOGE("%s: Invalid src %d: no valid attributes nor stream",__func__, vs);
+ return BAD_VALUE;
+ }
+ curSrcDevice = Volume::getDeviceForVolume(curSrcDevice);
+
// update volume on all outputs and streams matching the following:
// - The requested stream (or a stream matching for volume control) is active on the output
// - The device (or devices) selected by the engine for this stream includes
@@ -2450,7 +2462,7 @@
// no specific device volume value exists for currently selected device.
for (size_t i = 0; i < mOutputs.size(); i++) {
sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
- audio_devices_t curDevice = Volume::getDeviceForVolume(desc->devices().types());
+ audio_devices_t curDevice = desc->devices().types();
// Inter / intra volume group priority management: Loop on strategies arranged by priority
// If a higher priority strategy is active, and the output is routed to a device with a
@@ -2501,48 +2513,28 @@
}
continue;
}
- for (auto curVolGroup : getVolumeGroups()) {
- VolumeSource curVolSrc = toVolumeSource(curVolGroup);
- if (!(curVolSrc == vs || isInCall())) {
- continue;
- }
- if (!(desc->isActive(vs) || isInCall())) {
- continue;
- }
- audio_devices_t curSrcDevice;
- auto &curCurves = getVolumeCurves(curVolSrc);
- auto curCurvAttrs = curCurves.getAttributes();
- if (!curCurvAttrs.empty() && curCurvAttrs.front() != defaultAttr) {
- auto attr = curCurvAttrs.front();
- curSrcDevice = mEngine->getOutputDevicesForAttributes(attr, nullptr, false).types();
- } else if (!curCurves.getStreamTypes().empty()) {
- auto stream = curCurves.getStreamTypes().front();
- curSrcDevice = mEngine->getOutputDevicesForStream(stream, false).types();
- } else {
- ALOGE("%s: Invalid src %d: no valid attributes nor stream",__func__, curVolSrc);
- continue;
- }
- curSrcDevice = Volume::getDeviceForVolume(curSrcDevice);
- if ((device != AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME) && ((curDevice & device) == 0)) {
- continue;
- }
- if (device != AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME) {
- curSrcDevice |= device;
- applyVolume = (curDevice & curSrcDevice) != 0;
- } else {
- applyVolume = !curves.hasVolumeIndexForDevice(curSrcDevice);
- }
- if (applyVolume) {
- //FIXME: workaround for truncated touch sounds
- // delayed volume change for system stream to be removed when the problem is
- // handled by system UI
- status_t volStatus = checkAndSetVolume(
- curCurves, curVolSrc, index, desc, curDevice,
- ((vs == toVolumeSource(AUDIO_STREAM_SYSTEM))?
- TOUCH_SOUND_FIXED_DELAY_MS : 0));
- if (volStatus != NO_ERROR) {
- status = volStatus;
- }
+ if (!(desc->isActive(vs) || isInCall())) {
+ continue;
+ }
+ if ((device != AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME) && ((curDevice & device) == 0)) {
+ continue;
+ }
+ if (device != AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME) {
+ curSrcDevice |= device;
+ applyVolume = (Volume::getDeviceForVolume(curDevice) & curSrcDevice) != 0;
+ } else {
+ applyVolume = !curves.hasVolumeIndexForDevice(curSrcDevice);
+ }
+ if (applyVolume) {
+ //FIXME: workaround for truncated touch sounds
+ // delayed volume change for system stream to be removed when the problem is
+ // handled by system UI
+ status_t volStatus = checkAndSetVolume(
+ curves, vs, index, desc, curDevice,
+ ((vs == toVolumeSource(AUDIO_STREAM_SYSTEM))?
+ TOUCH_SOUND_FIXED_DELAY_MS : 0));
+ if (volStatus != NO_ERROR) {
+ status = volStatus;
}
}
}
@@ -3040,6 +3032,11 @@
mPolicyMixes.dump(dst);
mAudioSources.dump(dst);
+ dst->appendFormat(" AllowedCapturePolicies:\n");
+ for (auto& policy : mAllowedCapturePolicies) {
+ dst->appendFormat(" - uid=%d flag_mask=%#x\n", policy.first, policy.second);
+ }
+
dst->appendFormat("\nPolicy Engine dump:\n");
mEngine->dump(dst);
}
@@ -3052,6 +3049,12 @@
return NO_ERROR;
}
+status_t AudioPolicyManager::setAllowedCapturePolicy(uid_t uid, audio_flags_mask_t capturePolicy)
+{
+ mAllowedCapturePolicies[uid] = capturePolicy;
+ return NO_ERROR;
+}
+
// This function checks for the parameters which can be offloaded.
// This can be enhanced depending on the capability of the DSP and policy
// of the system.
@@ -4403,7 +4406,7 @@
continue;
}
// Device is now validated and can be appended to the available devices of the engine
- mEngine->setDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
+ setEngineDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
i++;
}
};
@@ -4417,7 +4420,7 @@
status = NO_INIT;
}
// If microphones address is empty, set it according to device type
- for (size_t i = 0; i < mAvailableInputDevices.size(); i++) {
+ for (size_t i = 0; i < mAvailableInputDevices.size(); i++) {
if (mAvailableInputDevices[i]->address().isEmpty()) {
if (mAvailableInputDevices[i]->type() == AUDIO_DEVICE_IN_BUILTIN_MIC) {
mAvailableInputDevices[i]->setAddress(String8(AUDIO_BOTTOM_MICROPHONE_ADDRESS));
@@ -4846,6 +4849,7 @@
ALOGW("closeOutput() unknown output %d", output);
return;
}
+ const bool closingOutputWasActive = closingOutput->isActive();
mPolicyMixes.closeOutput(closingOutput);
// look for duplicated outputs connected to the output being removed.
@@ -4885,6 +4889,9 @@
mpClientInterface->onAudioPatchListUpdate();
}
+ if (closingOutputWasActive) {
+ closingOutput->stop();
+ }
closingOutput->close();
removeOutput(output);
@@ -5730,14 +5737,14 @@
}
int AudioPolicyManager::rescaleVolumeIndex(int srcIndex,
- audio_stream_type_t srcStream,
- audio_stream_type_t dstStream)
+ VolumeSource fromVolumeSource,
+ VolumeSource toVolumeSource)
{
- if (srcStream == dstStream) {
+ if (fromVolumeSource == toVolumeSource) {
return srcIndex;
}
- auto &srcCurves = getVolumeCurves(srcStream);
- auto &dstCurves = getVolumeCurves(dstStream);
+ auto &srcCurves = getVolumeCurves(fromVolumeSource);
+ auto &dstCurves = getVolumeCurves(toVolumeSource);
float minSrc = (float)srcCurves.getVolumeIndexMin();
float maxSrc = (float)srcCurves.getVolumeIndexMax();
float minDst = (float)dstCurves.getVolumeIndexMin();
@@ -5851,12 +5858,8 @@
bool on,
const sp<AudioOutputDescriptor>& outputDesc,
int delayMs,
- audio_devices_t device,
- bool activeOnly)
+ audio_devices_t device)
{
- if (activeOnly && !outputDesc->isActive(volumeSource)) {
- return;
- }
if (device == AUDIO_DEVICE_NONE) {
device = outputDesc->devices().types();
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 1fc61e5..26208c8 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -171,9 +171,6 @@
virtual status_t getMinVolumeIndexForAttributes(const audio_attributes_t &attr, int &index);
- status_t setVolumeGroupIndex(IVolumeCurves &volumeCurves, volume_group_t group, int index,
- audio_devices_t device, const audio_attributes_t attributes);
-
status_t setVolumeCurveIndex(int index,
audio_devices_t device,
IVolumeCurves &volumeCurves);
@@ -221,6 +218,7 @@
status_t dump(int fd) override;
+ status_t setAllowedCapturePolicy(uid_t uid, audio_flags_mask_t capturePolicy) override;
virtual bool isOffloadSupported(const audio_offload_info_t& offloadInfo);
virtual bool isDirectOutputSupported(const audio_config_base_t& config,
@@ -425,8 +423,8 @@
// rescale volume index from srcStream within range of dstStream
int rescaleVolumeIndex(int srcIndex,
- audio_stream_type_t srcStream,
- audio_stream_type_t dstStream);
+ VolumeSource fromVolumeSource,
+ VolumeSource toVolumeSource);
// check that volume change is permitted, compute and send new volume to audio hardware
virtual status_t checkAndSetVolume(IVolumeCurves &curves,
VolumeSource volumeSource, int index,
@@ -461,14 +459,12 @@
* @param outputDesc on which the client following the volume group shall be muted/umuted
* @param delayMs
* @param device
- * @param activeOnly if true, mute only if the volume group is active on the output.
*/
void setVolumeSourceMute(VolumeSource volumeSource,
bool on,
const sp<AudioOutputDescriptor>& outputDesc,
int delayMs = 0,
- audio_devices_t device = AUDIO_DEVICE_NONE,
- bool activeOnly = false);
+ audio_devices_t device = AUDIO_DEVICE_NONE);
audio_mode_t getPhoneState();
@@ -759,6 +755,8 @@
// Surround formats that are enabled manually. Taken into account when
// "encoded surround" is forced into "manual" mode.
std::unordered_set<audio_format_t> mManualSurroundFormats;
+
+ std::unordered_map<uid_t, audio_flags_mask_t> mAllowedCapturePolicies;
private:
// Add or remove AC3 DTS encodings based on user preferences.
void modifySurroundFormats(const sp<DeviceDescriptor>& devDesc, FormatVector *formatsPtr);
@@ -849,6 +847,10 @@
const char *device_address,
const char *device_name,
audio_format_t encodedFormat);
+
+ void setEngineDeviceConnectionState(const sp<DeviceDescriptor> device,
+ audio_policy_dev_state_t state);
+
void updateMono(audio_io_handle_t output) {
AudioParameter param;
param.addInt(String8(AudioParameter::keyMonoOutput), (int)mMasterMono);
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index a672521..b2a2344 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -192,7 +192,7 @@
}
audio_attributes_t attr = *originalAttr;
if (!mPackageManager.allowPlaybackCapture(uid)) {
- attr.flags |= AUDIO_FLAG_NO_CAPTURE;
+ attr.flags |= AUDIO_FLAG_NO_MEDIA_PROJECTION;
}
audio_output_flags_t originalFlags = flags;
AutoCallerClear acc;
@@ -322,7 +322,7 @@
return;
}
sp<AudioPlaybackClient> client = mAudioPlaybackClients.valueAt(index);
- mAudioRecordClients.removeItem(portId);
+ mAudioPlaybackClients.removeItem(portId);
// called from internal thread: no need to clear caller identity
mAudioPolicyManager->releaseOutput(portId);
@@ -376,15 +376,17 @@
return PERMISSION_DENIED;
}
+ bool canCaptureOutput = captureAudioOutputAllowed(pid, uid);
if ((attr->source == AUDIO_SOURCE_VOICE_UPLINK ||
attr->source == AUDIO_SOURCE_VOICE_DOWNLINK ||
attr->source == AUDIO_SOURCE_VOICE_CALL ||
attr->source == AUDIO_SOURCE_ECHO_REFERENCE) &&
- !captureAudioOutputAllowed(pid, uid)) {
+ !canCaptureOutput) {
return PERMISSION_DENIED;
}
- if ((attr->source == AUDIO_SOURCE_HOTWORD) && !captureHotwordAllowed(pid, uid)) {
+ bool canCaptureHotword = captureHotwordAllowed(pid, uid);
+ if ((attr->source == AUDIO_SOURCE_HOTWORD) && !canCaptureHotword) {
return BAD_VALUE;
}
@@ -415,7 +417,7 @@
case AudioPolicyInterface::API_INPUT_TELEPHONY_RX:
// FIXME: use the same permission as for remote submix for now.
case AudioPolicyInterface::API_INPUT_MIX_CAPTURE:
- if (!captureAudioOutputAllowed(pid, uid)) {
+ if (!canCaptureOutput) {
ALOGE("getInputForAttr() permission denied: capture not allowed");
status = PERMISSION_DENIED;
}
@@ -442,7 +444,8 @@
}
sp<AudioRecordClient> client = new AudioRecordClient(*attr, *input, uid, pid, session,
- *selectedDeviceId, opPackageName);
+ *selectedDeviceId, opPackageName,
+ canCaptureOutput, canCaptureHotword);
mAudioRecordClients.add(*portId, client);
}
@@ -945,6 +948,20 @@
return audioPolicyEffects->removeStreamDefaultEffect(id);
}
+status_t AudioPolicyService::setAllowedCapturePolicy(uid_t uid, audio_flags_mask_t capturePolicy) {
+ Mutex::Autolock _l(mLock);
+ if (mAudioPolicyManager == NULL) {
+ ALOGV("%s() mAudioPolicyManager == NULL", __func__);
+ return NO_INIT;
+ }
+ uint_t callingUid = IPCThreadState::self()->getCallingUid();
+ if (uid != callingUid) {
+ ALOGD("%s() uid invalid %d != %d", __func__, uid, callingUid);
+ return PERMISSION_DENIED;
+ }
+ return mAudioPolicyManager->setAllowedCapturePolicy(uid, capturePolicy);
+}
+
bool AudioPolicyService::isOffloadSupported(const audio_offload_info_t& info)
{
if (mAudioPolicyManager == NULL) {
@@ -1080,6 +1097,14 @@
return PERMISSION_DENIED;
}
+ bool needCaptureMediaOutput = std::any_of(mixes.begin(), mixes.end(), [](auto& mix) {
+ return mix.mAllowPrivilegedPlaybackCapture; });
+ const uid_t callingUid = IPCThreadState::self()->getCallingUid();
+ const pid_t callingPid = IPCThreadState::self()->getCallingPid();
+ if (needCaptureMediaOutput && !captureMediaOutputAllowed(callingPid, callingUid)) {
+ return PERMISSION_DENIED;
+ }
+
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
@@ -1124,9 +1149,10 @@
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
+ // startAudioSource should be created as the calling uid
+ const uid_t callingUid = IPCThreadState::self()->getCallingUid();
AutoCallerClear acc;
- return mAudioPolicyManager->startAudioSource(source, attributes, portId,
- IPCThreadState::self()->getCallingUid());
+ return mAudioPolicyManager->startAudioSource(source, attributes, portId, callingUid);
}
status_t AudioPolicyService::stopAudioSource(audio_port_handle_t portId)
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 8cbf3af..f63fa81 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -22,8 +22,9 @@
#define __STDINT_LIMITS
#define __STDC_LIMIT_MACROS
#include <stdint.h>
-
#include <sys/time.h>
+
+#include <audio_utils/clock.h>
#include <binder/IServiceManager.h>
#include <utils/Log.h>
#include <cutils/properties.h>
@@ -48,8 +49,7 @@
static const char kDeadlockedString[] = "AudioPolicyService may be deadlocked\n";
static const char kCmdDeadlockedString[] = "AudioPolicyService command thread may be deadlocked\n";
-static const int kDumpLockRetries = 50;
-static const int kDumpLockSleepUs = 20000;
+static const int kDumpLockTimeoutNs = 1 * NANOS_PER_SECOND;
static const nsecs_t kAudioCommandTimeoutNs = seconds(3); // 3 seconds
@@ -376,17 +376,10 @@
IPCThreadState::self()->getCallingPid());
}
-static bool tryLock(Mutex& mutex)
+static bool dumpTryLock(Mutex& mutex)
{
- bool locked = false;
- for (int i = 0; i < kDumpLockRetries; ++i) {
- if (mutex.tryLock() == NO_ERROR) {
- locked = true;
- break;
- }
- usleep(kDumpLockSleepUs);
- }
- return locked;
+ status_t err = mutex.timedLock(kDumpLockTimeoutNs);
+ return err == NO_ERROR;
}
status_t AudioPolicyService::dumpInternals(int fd)
@@ -414,32 +407,35 @@
{
// Go over all active clients and allow capture (does not force silence) in the
// following cases:
-// The client is the assistant
+// Another client in the same UID has already been allowed to capture
+// OR The client is the assistant
// AND an accessibility service is on TOP
// AND the source is VOICE_RECOGNITION or HOTWORD
// OR uses VOICE_RECOGNITION AND is on TOP OR latest started
// OR uses HOTWORD
-// AND there is no privacy sensitive active capture
+// AND there is no active privacy sensitive capture or call
+// OR client has CAPTURE_AUDIO_OUTPUT privileged permission
// OR The client is an accessibility service
// AND is on TOP OR latest started
// AND the source is VOICE_RECOGNITION or HOTWORD
-// OR the source is one of: AUDIO_SOURCE_VOICE_DOWNLINK, AUDIO_SOURCE_VOICE_UPLINK,
-// AUDIO_SOURCE_VOICE_CALL
+// OR the client source is virtual (remote submix, call audio TX or RX...)
// OR Any other client
// AND The assistant is not on TOP
-// AND is on TOP OR latest started
-// AND there is no privacy sensitive active capture
+// AND there is no active privacy sensitive capture or call
+// OR client has CAPTURE_AUDIO_OUTPUT privileged permission
//TODO: mamanage pre processing effects according to use case priority
sp<AudioRecordClient> topActive;
sp<AudioRecordClient> latestActive;
sp<AudioRecordClient> latestSensitiveActive;
+
nsecs_t topStartNs = 0;
nsecs_t latestStartNs = 0;
nsecs_t latestSensitiveStartNs = 0;
bool isA11yOnTop = mUidPolicy->isA11yOnTop();
bool isAssistantOnTop = false;
bool isSensitiveActive = false;
+ bool isInCall = mPhoneState == AUDIO_MODE_IN_CALL;
// if Sensor Privacy is enabled then all recordings should be silenced.
if (mSensorPrivacyPolicy->isSensorPrivacyEnabled()) {
@@ -449,15 +445,18 @@
for (size_t i =0; i < mAudioRecordClients.size(); i++) {
sp<AudioRecordClient> current = mAudioRecordClients[i];
- if (!current->active) continue;
- if (isPrivacySensitiveSource(current->attributes.source)) {
- if (current->startTimeNs > latestSensitiveStartNs) {
- latestSensitiveActive = current;
- latestSensitiveStartNs = current->startTimeNs;
- }
- isSensitiveActive = true;
+ if (!current->active) {
+ continue;
}
- if (mUidPolicy->getUidState(current->uid) == ActivityManager::PROCESS_STATE_TOP) {
+
+ app_state_t appState = apmStatFromAmState(mUidPolicy->getUidState(current->uid));
+ // clients which app is in IDLE state are not eligible for top active or
+ // latest active
+ if (appState == APP_STATE_IDLE) {
+ continue;
+ }
+
+ if (appState == APP_STATE_TOP) {
if (current->startTimeNs > topStartNs) {
topActive = current;
topStartNs = current->startTimeNs;
@@ -470,72 +469,105 @@
latestActive = current;
latestStartNs = current->startTimeNs;
}
+ if (isPrivacySensitiveSource(current->attributes.source)) {
+ if (current->startTimeNs > latestSensitiveStartNs) {
+ latestSensitiveActive = current;
+ latestSensitiveStartNs = current->startTimeNs;
+ }
+ isSensitiveActive = true;
+ }
}
- if (topActive == nullptr && latestActive == nullptr) {
- return;
+ // if no active client with UI on Top, consider latest active as top
+ if (topActive == nullptr) {
+ topActive = latestActive;
}
- if (topActive != nullptr) {
- latestActive = nullptr;
- }
+ std::vector<uid_t> enabledUids;
for (size_t i =0; i < mAudioRecordClients.size(); i++) {
sp<AudioRecordClient> current = mAudioRecordClients[i];
- if (!current->active) continue;
+ if (!current->active) {
+ continue;
+ }
+
+ // keep capture allowed if another client with the same UID has already
+ // been allowed to capture
+ if (std::find(enabledUids.begin(), enabledUids.end(), current->uid)
+ != enabledUids.end()) {
+ continue;
+ }
audio_source_t source = current->attributes.source;
- bool isOnTop = current == topActive;
- bool isLatest = current == latestActive;
- bool isLatestSensitive = current == latestSensitiveActive;
- bool forceIdle = true;
+ bool isTopOrLatestActive = topActive == nullptr ? false : current->uid == topActive->uid;
+ bool isLatestSensitive = latestSensitiveActive == nullptr ?
+ false : current->uid == latestSensitiveActive->uid;
+
+ // By default allow capture if:
+ // The assistant is not on TOP
+ // AND there is no active privacy sensitive capture or call
+ // OR client has CAPTURE_AUDIO_OUTPUT privileged permission
+ bool allowCapture = !isAssistantOnTop
+ && !(isSensitiveActive && !(isLatestSensitive || current->canCaptureOutput))
+ && !(isInCall && !current->canCaptureOutput);
if (isVirtualSource(source)) {
- forceIdle = false;
+ // Allow capture for virtual (remote submix, call audio TX or RX...) sources
+ allowCapture = true;
} else if (mUidPolicy->isAssistantUid(current->uid)) {
+ // For assistant allow capture if:
+ // An accessibility service is on TOP
+ // AND the source is VOICE_RECOGNITION or HOTWORD
+ // OR is on TOP OR latest started AND uses VOICE_RECOGNITION
+ // OR uses HOTWORD
+ // AND there is no active privacy sensitive capture or call
+ // OR client has CAPTURE_AUDIO_OUTPUT privileged permission
if (isA11yOnTop) {
if (source == AUDIO_SOURCE_HOTWORD || source == AUDIO_SOURCE_VOICE_RECOGNITION) {
- forceIdle = false;
+ allowCapture = true;
}
} else {
- if ((((isOnTop || isLatest) && source == AUDIO_SOURCE_VOICE_RECOGNITION) ||
- source == AUDIO_SOURCE_HOTWORD) && !isSensitiveActive) {
- forceIdle = false;
+ if (((isTopOrLatestActive && source == AUDIO_SOURCE_VOICE_RECOGNITION) ||
+ source == AUDIO_SOURCE_HOTWORD) &&
+ (!(isSensitiveActive || isInCall) || current->canCaptureOutput)) {
+ allowCapture = true;
}
}
} else if (mUidPolicy->isA11yUid(current->uid)) {
- if ((isOnTop || isLatest) &&
- (source == AUDIO_SOURCE_VOICE_RECOGNITION || source == AUDIO_SOURCE_HOTWORD)) {
- forceIdle = false;
- }
- } else {
- if (!isAssistantOnTop && (isOnTop || isLatest) &&
- (!isSensitiveActive || isLatestSensitive)) {
- forceIdle = false;
+ // For accessibility service allow capture if:
+ // Is on TOP OR latest started
+ // AND the source is VOICE_RECOGNITION or HOTWORD
+ if (isTopOrLatestActive &&
+ (source == AUDIO_SOURCE_VOICE_RECOGNITION || source == AUDIO_SOURCE_HOTWORD)) {
+ allowCapture = true;
}
}
setAppState_l(current->uid,
- forceIdle ? APP_STATE_IDLE :
- apmStatFromAmState(mUidPolicy->getUidState(current->uid)));
+ allowCapture ? apmStatFromAmState(mUidPolicy->getUidState(current->uid)) :
+ APP_STATE_IDLE);
+ if (allowCapture) {
+ enabledUids.push_back(current->uid);
+ }
}
}
void AudioPolicyService::silenceAllRecordings_l() {
for (size_t i = 0; i < mAudioRecordClients.size(); i++) {
sp<AudioRecordClient> current = mAudioRecordClients[i];
- setAppState_l(current->uid, APP_STATE_IDLE);
+ if (!isVirtualSource(current->attributes.source)) {
+ setAppState_l(current->uid, APP_STATE_IDLE);
+ }
}
}
/* static */
app_state_t AudioPolicyService::apmStatFromAmState(int amState) {
- switch (amState) {
- case ActivityManager::PROCESS_STATE_UNKNOWN:
+
+ if (amState == ActivityManager::PROCESS_STATE_UNKNOWN) {
return APP_STATE_IDLE;
- case ActivityManager::PROCESS_STATE_TOP:
- return APP_STATE_TOP;
- default:
- break;
+ } else if (amState <= ActivityManager::PROCESS_STATE_TOP) {
+ // include persistent services
+ return APP_STATE_TOP;
}
return APP_STATE_FOREGROUND;
}
@@ -588,7 +620,7 @@
if (!dumpAllowed()) {
dumpPermissionDenial(fd);
} else {
- bool locked = tryLock(mLock);
+ bool locked = dumpTryLock(mLock);
if (!locked) {
String8 result(kDeadlockedString);
write(fd, result.string(), result.size());
@@ -1221,7 +1253,7 @@
result.append(buffer);
write(fd, result.string(), result.size());
- bool locked = tryLock(mLock);
+ bool locked = dumpTryLock(mLock);
if (!locked) {
String8 result2(kCmdDeadlockedString);
write(fd, result2.string(), result2.size());
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index a2e75cd..efdba56 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -182,6 +182,7 @@
audio_io_handle_t output,
int delayMs = 0);
virtual status_t setVoiceVolume(float volume, int delayMs = 0);
+ status_t setAllowedCapturePolicy(uint_t uid, audio_flags_mask_t capturePolicy) override;
virtual bool isOffloadSupported(const audio_offload_info_t &config);
virtual bool isDirectOutputSupported(const audio_config_base_t& config,
const audio_attributes_t& attributes);
@@ -753,13 +754,17 @@
AudioRecordClient(const audio_attributes_t attributes,
const audio_io_handle_t io, uid_t uid, pid_t pid,
const audio_session_t session, const audio_port_handle_t deviceId,
- const String16& opPackageName) :
+ const String16& opPackageName,
+ bool canCaptureOutput, bool canCaptureHotword) :
AudioClient(attributes, io, uid, pid, session, deviceId),
- opPackageName(opPackageName), startTimeNs(0) {}
+ opPackageName(opPackageName), startTimeNs(0),
+ canCaptureOutput(canCaptureOutput), canCaptureHotword(canCaptureHotword) {}
~AudioRecordClient() override = default;
const String16 opPackageName; // client package name
nsecs_t startTimeNs;
+ const bool canCaptureOutput;
+ const bool canCaptureHotword;
};
// --- AudioPlaybackClient ---
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 62ec955..8113c3f 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -972,8 +972,9 @@
userid_t clientUserId = multiuser_get_user_id(clientUid);
// Only allow clients who are being used by the current foreground device user, unless calling
- // from our own process.
- if (callingPid != getpid() && (mAllowedUsers.find(clientUserId) == mAllowedUsers.end())) {
+ // from our own process OR the caller is using the cameraserver's HIDL interface.
+ if (!hardware::IPCThreadState::self()->isServingCall() && callingPid != getpid() &&
+ (mAllowedUsers.find(clientUserId) == mAllowedUsers.end())) {
ALOGE("CameraService::connect X (PID %d) rejected (cannot connect from "
"device user %d, currently allowed device users: %s)", callingPid, clientUserId,
toString(mAllowedUsers).string());
@@ -2180,31 +2181,37 @@
return mp;
}
-void CameraService::loadSound() {
+void CameraService::increaseSoundRef() {
+ Mutex::Autolock lock(mSoundLock);
+ mSoundRef++;
+}
+
+void CameraService::loadSoundLocked(sound_kind kind) {
ATRACE_CALL();
- Mutex::Autolock lock(mSoundLock);
- LOG1("CameraService::loadSound ref=%d", mSoundRef);
- if (mSoundRef++) return;
-
- mSoundPlayer[SOUND_SHUTTER] = newMediaPlayer("/product/media/audio/ui/camera_click.ogg");
- if (mSoundPlayer[SOUND_SHUTTER] == nullptr) {
- mSoundPlayer[SOUND_SHUTTER] = newMediaPlayer("/system/media/audio/ui/camera_click.ogg");
- }
- mSoundPlayer[SOUND_RECORDING_START] = newMediaPlayer("/product/media/audio/ui/VideoRecord.ogg");
- if (mSoundPlayer[SOUND_RECORDING_START] == nullptr) {
- mSoundPlayer[SOUND_RECORDING_START] =
+ LOG1("CameraService::loadSoundLocked ref=%d", mSoundRef);
+ if (SOUND_SHUTTER == kind && mSoundPlayer[SOUND_SHUTTER] == NULL) {
+ mSoundPlayer[SOUND_SHUTTER] = newMediaPlayer("/product/media/audio/ui/camera_click.ogg");
+ if (mSoundPlayer[SOUND_SHUTTER] == nullptr) {
+ mSoundPlayer[SOUND_SHUTTER] = newMediaPlayer("/system/media/audio/ui/camera_click.ogg");
+ }
+ } else if (SOUND_RECORDING_START == kind && mSoundPlayer[SOUND_RECORDING_START] == NULL) {
+ mSoundPlayer[SOUND_RECORDING_START] = newMediaPlayer("/product/media/audio/ui/VideoRecord.ogg");
+ if (mSoundPlayer[SOUND_RECORDING_START] == nullptr) {
+ mSoundPlayer[SOUND_RECORDING_START] =
newMediaPlayer("/system/media/audio/ui/VideoRecord.ogg");
- }
- mSoundPlayer[SOUND_RECORDING_STOP] = newMediaPlayer("/product/media/audio/ui/VideoStop.ogg");
- if (mSoundPlayer[SOUND_RECORDING_STOP] == nullptr) {
- mSoundPlayer[SOUND_RECORDING_STOP] = newMediaPlayer("/system/media/audio/ui/VideoStop.ogg");
+ }
+ } else if (SOUND_RECORDING_STOP == kind && mSoundPlayer[SOUND_RECORDING_STOP] == NULL) {
+ mSoundPlayer[SOUND_RECORDING_STOP] = newMediaPlayer("/product/media/audio/ui/VideoStop.ogg");
+ if (mSoundPlayer[SOUND_RECORDING_STOP] == nullptr) {
+ mSoundPlayer[SOUND_RECORDING_STOP] = newMediaPlayer("/system/media/audio/ui/VideoStop.ogg");
+ }
}
}
-void CameraService::releaseSound() {
+void CameraService::decreaseSoundRef() {
Mutex::Autolock lock(mSoundLock);
- LOG1("CameraService::releaseSound ref=%d", mSoundRef);
+ LOG1("CameraService::decreaseSoundRef ref=%d", mSoundRef);
if (--mSoundRef) return;
for (int i = 0; i < NUM_SOUNDS; i++) {
@@ -2220,6 +2227,7 @@
LOG1("playSound(%d)", kind);
Mutex::Autolock lock(mSoundLock);
+ loadSoundLocked(kind);
sp<MediaPlayer> player = mSoundPlayer[kind];
if (player != 0) {
player->seekTo(0);
@@ -2249,7 +2257,7 @@
mRemoteCallback = cameraClient;
- cameraService->loadSound();
+ cameraService->increaseSoundRef();
LOG1("Client::Client X (pid %d, id %d)", callingPid, mCameraId);
}
@@ -2259,7 +2267,7 @@
ALOGV("~Client");
mDestructionStarted = true;
- sCameraService->releaseSound();
+ sCameraService->decreaseSoundRef();
// unconditionally disconnect. function is idempotent
Client::disconnect();
}
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 65727ec..344dd92 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -192,10 +192,10 @@
NUM_SOUNDS
};
- void loadSound();
void playSound(sound_kind kind);
- void releaseSound();
-
+ void loadSoundLocked(sound_kind kind);
+ void decreaseSoundRef();
+ void increaseSoundRef();
/**
* Update the state of a given camera device (open/close/active/idle) with
* the camera proxy service in the system service
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index b512f2b..c7a4f2b 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -604,6 +604,7 @@
stream->v3_2.usage = Camera3Device::mapToConsumerUsage(u);
stream->v3_2.dataSpace = Camera3Device::mapToHidlDataspace(streamInfo.dataSpace);
stream->v3_2.rotation = Camera3Device::mapToStreamRotation(rotation);
+ stream->v3_2.id = -1; // Invalid stream id
stream->physicalCameraId = std::string(physicalId.string());
stream->bufferSize = 0;
}
diff --git a/services/camera/libcameraservice/api2/HeicCompositeStream.cpp b/services/camera/libcameraservice/api2/HeicCompositeStream.cpp
index 9fd0e8b..743c816 100644
--- a/services/camera/libcameraservice/api2/HeicCompositeStream.cpp
+++ b/services/camera/libcameraservice/api2/HeicCompositeStream.cpp
@@ -1177,7 +1177,7 @@
outputFormat->setInt32(KEY_BITRATE_MODE, BITRATE_MODE_CQ);
outputFormat->setInt32(KEY_QUALITY, kDefaultJpegQuality);
// Ask codec to skip timestamp check and encode all frames.
- outputFormat->setInt64("max-pts-gap-to-encoder", kNoFrameDropMaxPtsGap);
+ outputFormat->setInt64(KEY_MAX_PTS_GAP_TO_ENCODER, kNoFrameDropMaxPtsGap);
int32_t gridWidth, gridHeight, gridRows, gridCols;
if (useGrid || mUseHeic) {
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 22e09e4..ef99dea 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -1062,14 +1062,18 @@
nsecs_t waitDuration = kBaseGetBufferWait + getExpectedInFlightDuration();
status_t res = outputStream->getBuffer(&sb, waitDuration);
if (res != OK) {
- ALOGE("%s: Can't get output buffer for stream %d: %s (%d)",
- __FUNCTION__, streamId, strerror(-res), res);
if (res == NO_INIT || res == DEAD_OBJECT) {
+ ALOGV("%s: Can't get output buffer for stream %d: %s (%d)",
+ __FUNCTION__, streamId, strerror(-res), res);
bufRet.val.error(StreamBufferRequestError::STREAM_DISCONNECTED);
- } else if (res == TIMED_OUT || res == NO_MEMORY) {
- bufRet.val.error(StreamBufferRequestError::NO_BUFFER_AVAILABLE);
} else {
- bufRet.val.error(StreamBufferRequestError::UNKNOWN_ERROR);
+ ALOGE("%s: Can't get output buffer for stream %d: %s (%d)",
+ __FUNCTION__, streamId, strerror(-res), res);
+ if (res == TIMED_OUT || res == NO_MEMORY) {
+ bufRet.val.error(StreamBufferRequestError::NO_BUFFER_AVAILABLE);
+ } else {
+ bufRet.val.error(StreamBufferRequestError::UNKNOWN_ERROR);
+ }
}
currentReqSucceeds = false;
break;
@@ -3154,9 +3158,10 @@
// Note: stream may be deallocated at this point, if this buffer was
// the last reference to it.
- if (res != OK) {
- ALOGE("Can't return buffer to its stream: %s (%d)",
- strerror(-res), res);
+ if (res == NO_INIT || res == DEAD_OBJECT) {
+ ALOGV("Can't return buffer to its stream: %s (%d)", strerror(-res), res);
+ } else if (res != OK) {
+ ALOGE("Can't return buffer to its stream: %s (%d)", strerror(-res), res);
}
// Long processing consumers can cause returnBuffer timeout for shared stream
@@ -5580,7 +5585,7 @@
if (mUseHalBufManager) {
if (outputStream->isAbandoned()) {
- ALOGE("%s: stream %d is abandoned.", __FUNCTION__, streamId);
+ ALOGV("%s: stream %d is abandoned, skipping request", __FUNCTION__, streamId);
return TIMED_OUT;
}
// HAL will request buffer through requestStreamBuffer API
@@ -5598,7 +5603,7 @@
// Can't get output buffer from gralloc queue - this could be due to
// abandoned queue or other consumer misbehavior, so not a fatal
// error
- ALOGE("RequestThread: Can't get output buffer, skipping request:"
+ ALOGV("RequestThread: Can't get output buffer, skipping request:"
" %s (%d)", strerror(-res), res);
return TIMED_OUT;
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index baba856..1c77581 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -233,6 +233,7 @@
* queueBuffer
*/
sp<ANativeWindow> currentConsumer = mConsumer;
+ StreamState state = mState;
mLock.unlock();
ANativeWindowBuffer *anwBuffer = container_of(buffer.buffer, ANativeWindowBuffer, handle);
@@ -244,7 +245,7 @@
if (mDropBuffers) {
ALOGV("%s: Dropping a frame for stream %d.", __FUNCTION__, mId);
} else if (buffer.status == CAMERA3_BUFFER_STATUS_ERROR) {
- ALOGW("%s: A frame is dropped for stream %d due to buffer error.", __FUNCTION__, mId);
+ ALOGV("%s: A frame is dropped for stream %d due to buffer error.", __FUNCTION__, mId);
} else {
ALOGE("%s: Stream %d: timestamp shouldn't be 0", __FUNCTION__, mId);
}
@@ -252,7 +253,7 @@
res = currentConsumer->cancelBuffer(currentConsumer.get(),
anwBuffer,
anwReleaseFence);
- if (res != OK) {
+ if (shouldLogError(res, state)) {
ALOGE("%s: Stream %d: Error cancelling buffer to native window:"
" %s (%d)", __FUNCTION__, mId, strerror(-res), res);
}
@@ -284,9 +285,9 @@
}
res = queueBufferToConsumer(currentConsumer, anwBuffer, anwReleaseFence, surface_ids);
- if (res != OK) {
- ALOGE("%s: Stream %d: Error queueing buffer to native window: "
- "%s (%d)", __FUNCTION__, mId, strerror(-res), res);
+ if (shouldLogError(res, state)) {
+ ALOGE("%s: Stream %d: Error queueing buffer to native window:"
+ " %s (%d)", __FUNCTION__, mId, strerror(-res), res);
}
}
mLock.lock();
@@ -534,10 +535,11 @@
// successful return.
*anb = gb.get();
res = mConsumer->attachBuffer(*anb);
- if (res != OK) {
+ if (shouldLogError(res, mState)) {
ALOGE("%s: Stream %d: Can't attach the output buffer to this surface: %s (%d)",
__FUNCTION__, mId, strerror(-res), res);
-
+ }
+ if (res != OK) {
checkRetAndSetAbandonedLocked(res);
return res;
}
@@ -592,9 +594,10 @@
ALOGV("Stream %d: Attached new buffer", getId());
if (res != OK) {
- ALOGE("%s: Stream %d: Can't attach the output buffer to this surface: %s (%d)",
- __FUNCTION__, mId, strerror(-res), res);
-
+ if (shouldLogError(res, mState)) {
+ ALOGE("%s: Stream %d: Can't attach the output buffer to this surface:"
+ " %s (%d)", __FUNCTION__, mId, strerror(-res), res);
+ }
checkRetAndSetAbandonedLocked(res);
return res;
}
@@ -604,9 +607,10 @@
return res;
}
} else if (res != OK) {
- ALOGE("%s: Stream %d: Can't dequeue next output buffer: %s (%d)",
- __FUNCTION__, mId, strerror(-res), res);
-
+ if (shouldLogError(res, mState)) {
+ ALOGE("%s: Stream %d: Can't dequeue next output buffer: %s (%d)",
+ __FUNCTION__, mId, strerror(-res), res);
+ }
checkRetAndSetAbandonedLocked(res);
return res;
}
@@ -639,6 +643,16 @@
}
}
+bool Camera3OutputStream::shouldLogError(status_t res, StreamState state) {
+ if (res == OK) {
+ return false;
+ }
+ if ((res == DEAD_OBJECT || res == NO_INIT) && state == STATE_ABANDONED) {
+ return false;
+ }
+ return true;
+}
+
status_t Camera3OutputStream::disconnectLocked() {
status_t res;
@@ -838,7 +852,9 @@
ALOGW("%s: the released buffer has already been freed by the buffer queue!", __FUNCTION__);
} else if (res != OK) {
// Treat other errors as abandonment
- ALOGE("%s: detach next buffer failed: %s (%d).", __FUNCTION__, strerror(-res), res);
+ if (shouldLogError(res, mState)) {
+ ALOGE("%s: detach next buffer failed: %s (%d).", __FUNCTION__, strerror(-res), res);
+ }
mState = STATE_ABANDONED;
return res;
}
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.h b/services/camera/libcameraservice/device3/Camera3OutputStream.h
index 30fc2f7..729c655 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.h
@@ -317,6 +317,10 @@
// Check return status of IGBP calls and set abandoned state accordingly
void checkRetAndSetAbandonedLocked(status_t res);
+ // If the status indicates abandonded stream, only log when state hasn't been updated to
+ // STATE_ABANDONED
+ static bool shouldLogError(status_t res, StreamState state);
+
static const int32_t kDequeueLatencyBinSize = 5; // in ms
CameraLatencyHistogram mDequeueBufferLatency;
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.cpp b/services/camera/libcameraservice/device3/Camera3Stream.cpp
index 0571741..12ff130 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Stream.cpp
@@ -321,7 +321,7 @@
// so. As documented in hardware/camera3.h:configure_streams().
if (mState == STATE_IN_RECONFIG &&
mOldUsage == mUsage &&
- mOldMaxBuffers == camera3_stream::max_buffers) {
+ mOldMaxBuffers == camera3_stream::max_buffers && !mDataSpaceOverridden) {
mState = STATE_CONFIGURED;
return OK;
}
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.h b/services/camera/libcameraservice/device3/Camera3Stream.h
index 5eb6a23..3d21029 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.h
+++ b/services/camera/libcameraservice/device3/Camera3Stream.h
@@ -458,7 +458,7 @@
// Zero for formats with fixed buffer size for given dimensions.
const size_t mMaxSize;
- enum {
+ enum StreamState {
STATE_ERROR,
STATE_CONSTRUCTED,
STATE_IN_CONFIG,
diff --git a/services/camera/libcameraservice/hidl/Convert.cpp b/services/camera/libcameraservice/hidl/Convert.cpp
index a87812b..c2ed23a 100644
--- a/services/camera/libcameraservice/hidl/Convert.cpp
+++ b/services/camera/libcameraservice/hidl/Convert.cpp
@@ -97,6 +97,21 @@
return outputConfiguration;
}
+hardware::camera2::params::SessionConfiguration convertFromHidl(
+ const HSessionConfiguration &hSessionConfiguration) {
+ hardware::camera2::params::SessionConfiguration sessionConfig(
+ hSessionConfiguration.inputWidth, hSessionConfiguration.inputHeight,
+ hSessionConfiguration.inputFormat,
+ static_cast<int>(hSessionConfiguration.operationMode));
+
+ for (const auto& hConfig : hSessionConfiguration.outputStreams) {
+ hardware::camera2::params::OutputConfiguration config = convertFromHidl(hConfig);
+ sessionConfig.addOutputConfiguration(config);
+ }
+
+ return sessionConfig;
+}
+
// The camera metadata here is cloned. Since we're reading metadata over
// hwbinder we would need to clone it in order to avoid aligment issues.
bool convertFromHidl(const HCameraMetadata &src, CameraMetadata *dst) {
diff --git a/services/camera/libcameraservice/hidl/Convert.h b/services/camera/libcameraservice/hidl/Convert.h
index 82937a3..79683f6 100644
--- a/services/camera/libcameraservice/hidl/Convert.h
+++ b/services/camera/libcameraservice/hidl/Convert.h
@@ -53,6 +53,7 @@
using HOutputConfiguration = frameworks::cameraservice::device::V2_0::OutputConfiguration;
using HPhysicalCameraSettings = frameworks::cameraservice::device::V2_0::PhysicalCameraSettings;
using HPhysicalCaptureResultInfo = frameworks::cameraservice::device::V2_0::PhysicalCaptureResultInfo;
+using HSessionConfiguration = frameworks::cameraservice::device::V2_0::SessionConfiguration;
using HSubmitInfo = frameworks::cameraservice::device::V2_0::SubmitInfo;
using HStatus = frameworks::cameraservice::common::V2_0::Status;
using HStreamConfigurationMode = frameworks::cameraservice::device::V2_0::StreamConfigurationMode;
@@ -70,6 +71,9 @@
hardware::camera2::params::OutputConfiguration convertFromHidl(
const HOutputConfiguration &hOutputConfiguration);
+hardware::camera2::params::SessionConfiguration convertFromHidl(
+ const HSessionConfiguration &hSessionConfiguration);
+
HCameraDeviceStatus convertToHidlCameraDeviceStatus(int32_t status);
void convertToHidl(const std::vector<hardware::CameraStatus> &src,
diff --git a/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.cpp b/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.cpp
index d22ba5a..675ad24 100644
--- a/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.cpp
+++ b/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.cpp
@@ -41,6 +41,7 @@
using hardware::Void;
using HSubmitInfo = device::V2_0::SubmitInfo;
using hardware::camera2::params::OutputConfiguration;
+using hardware::camera2::params::SessionConfiguration;
static constexpr int32_t CAMERA_REQUEST_METADATA_QUEUE_SIZE = 1 << 20 /* 1 MB */;
static constexpr int32_t CAMERA_RESULT_METADATA_QUEUE_SIZE = 1 << 20 /* 1 MB */;
@@ -255,6 +256,18 @@
return B2HStatus(ret);
}
+Return<void> HidlCameraDeviceUser::isSessionConfigurationSupported(
+ const HSessionConfiguration& hSessionConfiguration,
+ isSessionConfigurationSupported_cb _hidl_cb) {
+ bool supported = false;
+ SessionConfiguration sessionConfiguration = convertFromHidl(hSessionConfiguration);
+ binder::Status ret = mDeviceRemote->isSessionConfigurationSupported(
+ sessionConfiguration, &supported);
+ HStatus status = B2HStatus(ret);
+ _hidl_cb(status, supported);
+ return Void();
+}
+
} // implementation
} // V2_0
} // device
diff --git a/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.h b/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.h
index be8f1d6..c3a80fe 100644
--- a/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.h
+++ b/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.h
@@ -53,6 +53,7 @@
using HCameraDeviceUser = device::V2_0::ICameraDeviceUser;
using HCameraMetadata = cameraservice::service::V2_0::CameraMetadata;
using HCaptureRequest = device::V2_0::CaptureRequest;
+using HSessionConfiguration = frameworks::cameraservice::device::V2_0::SessionConfiguration;
using HOutputConfiguration = frameworks::cameraservice::device::V2_0::OutputConfiguration;
using HPhysicalCameraSettings = frameworks::cameraservice::device::V2_0::PhysicalCameraSettings;
using HStatus = frameworks::cameraservice::common::V2_0::Status;
@@ -97,6 +98,10 @@
virtual Return<HStatus> updateOutputConfiguration(
int32_t streamId, const HOutputConfiguration& outputConfiguration) override;
+ virtual Return<void> isSessionConfigurationSupported(
+ const HSessionConfiguration& sessionConfiguration,
+ isSessionConfigurationSupported_cb _hidl_cb) override;
+
bool initStatus() { return mInitSuccess; }
std::shared_ptr<CaptureResultMetadataQueue> getCaptureResultMetadataQueue() {
diff --git a/services/mediaanalytics/MediaAnalyticsService.cpp b/services/mediaanalytics/MediaAnalyticsService.cpp
index 4f3ac1b..06baac9 100644
--- a/services/mediaanalytics/MediaAnalyticsService.cpp
+++ b/services/mediaanalytics/MediaAnalyticsService.cpp
@@ -76,9 +76,6 @@
namespace android {
- using namespace android::base;
- using namespace android::content::pm;
-
// individual records kept in memory: age or count
// age: <= 28 hours (1 1/6 days)
// count: hard limit of # records
@@ -649,7 +646,8 @@
}
if (binder != NULL) {
- sp<IPackageManagerNative> package_mgr = interface_cast<IPackageManagerNative>(binder);
+ sp<content::pm::IPackageManagerNative> package_mgr =
+ interface_cast<content::pm::IPackageManagerNative>(binder);
binder::Status status;
std::vector<int> uids;
diff --git a/services/mediaextractor/Android.mk b/services/mediaextractor/Android.mk
index 661a475..fd34d5b 100644
--- a/services/mediaextractor/Android.mk
+++ b/services/mediaextractor/Android.mk
@@ -22,7 +22,6 @@
LOCAL_SRC_FILES := main_extractorservice.cpp
LOCAL_SHARED_LIBRARIES := libmedia libmediaextractorservice libbinder libutils \
liblog libandroidicu libavservices_minijail
-LOCAL_STATIC_LIBRARIES := libicuandroid_utils
LOCAL_MODULE:= mediaextractor
LOCAL_INIT_RC := mediaextractor.rc
LOCAL_C_INCLUDES := frameworks/av/media/libmedia
diff --git a/services/mediaextractor/main_extractorservice.cpp b/services/mediaextractor/main_extractorservice.cpp
index 3c15bfd..06b532d 100644
--- a/services/mediaextractor/main_extractorservice.cpp
+++ b/services/mediaextractor/main_extractorservice.cpp
@@ -15,6 +15,7 @@
** limitations under the License.
*/
+#include <aicu/AIcu.h>
#include <fcntl.h>
#include <sys/prctl.h>
#include <sys/wait.h>
@@ -29,7 +30,6 @@
#include <utils/misc.h>
// from LOCAL_C_INCLUDES
-#include "IcuUtils.h"
#include "MediaExtractorService.h"
#include "MediaUtils.h"
#include "minijail.h"
@@ -64,7 +64,7 @@
SetUpMinijail(kSystemSeccompPolicyPath, kVendorSeccompPolicyPath);
- InitializeIcuOrDie();
+ AIcu_initializeIcuOrDie();
strcpy(argv[0], "media.extractor");
sp<ProcessState> proc(ProcessState::self());
diff --git a/services/mediaextractor/mediaextractor.rc b/services/mediaextractor/mediaextractor.rc
index 6b2d0a5..5fc2941 100644
--- a/services/mediaextractor/mediaextractor.rc
+++ b/services/mediaextractor/mediaextractor.rc
@@ -2,7 +2,5 @@
class main
user mediaex
group drmrpc mediadrm
- # TODO(b/123275379): Remove updatable when http://aosp/878198 has landed
- updatable
ioprio rt 4
writepid /dev/cpuset/foreground/tasks
diff --git a/services/mediaextractor/seccomp_policy/mediaextractor-arm.policy b/services/mediaextractor/seccomp_policy/mediaextractor-arm.policy
index 87018ed..964acf4 100644
--- a/services/mediaextractor/seccomp_policy/mediaextractor-arm.policy
+++ b/services/mediaextractor/seccomp_policy/mediaextractor-arm.policy
@@ -14,6 +14,7 @@
setpriority: 1
sigaltstack: 1
openat: 1
+open: 1
clone: 1
read: 1
clock_gettime: 1
diff --git a/services/mediaextractor/seccomp_policy/mediaextractor-x86.policy b/services/mediaextractor/seccomp_policy/mediaextractor-x86.policy
index d739ba1..56ad8df 100644
--- a/services/mediaextractor/seccomp_policy/mediaextractor-x86.policy
+++ b/services/mediaextractor/seccomp_policy/mediaextractor-x86.policy
@@ -11,6 +11,7 @@
mmap2: 1
madvise: 1
openat: 1
+open: 1
clock_gettime: 1
writev: 1
brk: 1
diff --git a/services/oboeservice/AAudioServiceEndpointMMAP.cpp b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
index 6c28083..fbf7d10 100644
--- a/services/oboeservice/AAudioServiceEndpointMMAP.cpp
+++ b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
@@ -93,12 +93,14 @@
const audio_source_t source = (direction == AAUDIO_DIRECTION_INPUT)
? AAudioConvert_inputPresetToAudioSource(getInputPreset())
: AUDIO_SOURCE_DEFAULT;
+ const audio_flags_mask_t flags = AUDIO_FLAG_LOW_LATENCY |
+ AAudioConvert_allowCapturePolicyToAudioFlagsMask(getAllowedCapturePolicy());
const audio_attributes_t attributes = {
.content_type = contentType,
.usage = usage,
.source = source,
- .flags = AUDIO_FLAG_LOW_LATENCY,
+ .flags = flags,
.tags = ""
};
diff --git a/services/soundtrigger/Android.bp b/services/soundtrigger/Android.bp
index 1f2283a..3f02f48 100644
--- a/services/soundtrigger/Android.bp
+++ b/services/soundtrigger/Android.bp
@@ -28,6 +28,7 @@
"libhardware",
"libsoundtrigger",
"libaudioclient",
+ "libaudioutils",
"libmediautils",
"libhwbinder",
diff --git a/services/soundtrigger/SoundTriggerHwService.cpp b/services/soundtrigger/SoundTriggerHwService.cpp
index fe2ccf2..f89683a 100644
--- a/services/soundtrigger/SoundTriggerHwService.cpp
+++ b/services/soundtrigger/SoundTriggerHwService.cpp
@@ -22,6 +22,7 @@
#include <sys/types.h>
#include <pthread.h>
+#include <audio_utils/clock.h>
#include <system/sound_trigger.h>
#include <cutils/atomic.h>
#include <cutils/properties.h>
@@ -146,20 +147,12 @@
}
-static const int kDumpLockRetries = 50;
-static const int kDumpLockSleep = 60000;
+static const int kDumpLockTimeoutNs = 1 * NANOS_PER_SECOND;
-static bool tryLock(Mutex& mutex)
+static bool dumpTryLock(Mutex& mutex)
{
- bool locked = false;
- for (int i = 0; i < kDumpLockRetries; ++i) {
- if (mutex.tryLock() == NO_ERROR) {
- locked = true;
- break;
- }
- usleep(kDumpLockSleep);
- }
- return locked;
+ status_t err = mutex.timedLock(kDumpLockTimeoutNs);
+ return err == NO_ERROR;
}
status_t SoundTriggerHwService::dump(int fd, const Vector<String16>& args __unused) {
@@ -168,7 +161,7 @@
result.appendFormat("Permission Denial: can't dump SoundTriggerHwService");
write(fd, result.string(), result.size());
} else {
- bool locked = tryLock(mServiceLock);
+ bool locked = dumpTryLock(mServiceLock);
// failed to lock - SoundTriggerHwService is probably deadlocked
if (!locked) {
result.append("SoundTriggerHwService may be deadlocked\n");