Merge "libaudiohal: Handle pause-flush-resume for offloaded streams"
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index 0d156a5..9174adf 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -9215,24 +9215,25 @@
* camera's crop region is set to maximum size, the FOV of the physical streams for the
* ultrawide lens will be the same as the logical stream, by making the crop region
* smaller than its active array size to compensate for the smaller focal length.</p>
- * <p>There are two ways for the application to capture RAW images from a logical camera
- * with RAW capability:</p>
+ * <p>For a logical camera, typically the underlying physical cameras have different RAW
+ * capabilities (such as resolution or CFA pattern). There are two ways for the
+ * application to capture RAW images from the logical camera:</p>
* <ul>
- * <li>Because the underlying physical cameras may have different RAW capabilities (such
- * as resolution or CFA pattern), to maintain backward compatibility, when a RAW stream
- * is configured, the camera device makes sure the default active physical camera remains
- * active and does not switch to other physical cameras. (One exception is that, if the
- * logical camera consists of identical image sensors and advertises multiple focalLength
- * due to different lenses, the camera device may generate RAW images from different
- * physical cameras based on the focalLength being set by the application.) This
- * backward-compatible approach usually results in loss of optical zoom, to telephoto
- * lens or to ultrawide lens.</li>
- * <li>Alternatively, to take advantage of the full zoomRatio range of the logical camera,
- * the application should use <a href="https://developer.android.com/reference/android/hardware/camera2/MultiResolutionImageReader.html">MultiResolutionImageReader</a>
- * to capture RAW images from the currently active physical camera. Because different
- * physical camera may have different RAW characteristics, the application needs to use
- * the characteristics and result metadata of the active physical camera for the
- * relevant RAW metadata.</li>
+ * <li>If the logical camera has RAW capability, the application can create and use RAW
+ * streams in the same way as before. In case a RAW stream is configured, to maintain
+ * backward compatibility, the camera device makes sure the default active physical
+ * camera remains active and does not switch to other physical cameras. (One exception
+ * is that, if the logical camera consists of identical image sensors and advertises
+ * multiple focalLength due to different lenses, the camera device may generate RAW
+ * images from different physical cameras based on the focalLength being set by the
+ * application.) This backward-compatible approach usually results in loss of optical
+ * zoom, to telephoto lens or to ultrawide lens.</li>
+ * <li>Alternatively, if supported by the device,
+ * <a href="https://developer.android.com/reference/android/hardware/camera2/MultiResolutionImageReader.html">MultiResolutionImageReader</a>
+ * can be used to capture RAW images from one of the underlying physical cameras (
+ * depending on current zoom level). Because different physical cameras may have
+ * different RAW characteristics, the application needs to use the characteristics
+ * and result metadata of the active physical camera for the relevant RAW metadata.</li>
* </ul>
* <p>The capture request and result metadata tags required for backward compatible camera
* functionalities will be solely based on the logical camera capability. On the other
diff --git a/drm/libmediadrm/DrmMetricsLogger.cpp b/drm/libmediadrm/DrmMetricsLogger.cpp
index 89b1dcc..de6d097 100644
--- a/drm/libmediadrm/DrmMetricsLogger.cpp
+++ b/drm/libmediadrm/DrmMetricsLogger.cpp
@@ -63,6 +63,8 @@
DrmStatus DrmMetricsLogger::createPlugin(const uint8_t uuid[IDRM_UUID_SIZE],
const String8& appPackageName) {
std::memcpy(mUuid.data(), uuid, IDRM_UUID_SIZE);
+ mUuid[0] = betoh64(mUuid[0]);
+ mUuid[1] = betoh64(mUuid[1]);
if (kUuidSchemeMap.count(mUuid)) {
mScheme = kUuidSchemeMap.at(mUuid);
} else {
@@ -460,8 +462,8 @@
void DrmMetricsLogger::reportMediaDrmCreated() const {
mediametrics_handle_t handle(mediametrics_create("mediadrm.created"));
mediametrics_setCString(handle, "scheme", mScheme.c_str());
- mediametrics_setInt64(handle, "uuid_msb", be64toh(mUuid[0]));
- mediametrics_setInt64(handle, "uuid_lsb", be64toh(mUuid[1]));
+ mediametrics_setInt64(handle, "uuid_msb", mUuid[0]);
+ mediametrics_setInt64(handle, "uuid_lsb", mUuid[1]);
mediametrics_setInt32(handle, "frontend", mFrontend);
mediametrics_setCString(handle, "object_nonce", mObjNonce.c_str());
mediametrics_selfRecord(handle);
@@ -471,8 +473,8 @@
void DrmMetricsLogger::reportMediaDrmSessionOpened(const std::vector<uint8_t>& sessionId) const {
mediametrics_handle_t handle(mediametrics_create("mediadrm.session_opened"));
mediametrics_setCString(handle, "scheme", mScheme.c_str());
- mediametrics_setInt64(handle, "uuid_msb", be64toh(mUuid[0]));
- mediametrics_setInt64(handle, "uuid_lsb", be64toh(mUuid[1]));
+ mediametrics_setInt64(handle, "uuid_msb", mUuid[0]);
+ mediametrics_setInt64(handle, "uuid_lsb", mUuid[1]);
mediametrics_setInt32(handle, "frontend", mFrontend);
mediametrics_setCString(handle, "object_nonce", mObjNonce.c_str());
const std::lock_guard<std::mutex> lock(mSessionMapMutex);
@@ -490,8 +492,8 @@
const std::vector<uint8_t>& sessionId) const {
mediametrics_handle_t handle(mediametrics_create("mediadrm.errored"));
mediametrics_setCString(handle, "scheme", mScheme.c_str());
- mediametrics_setInt64(handle, "uuid_msb", be64toh(mUuid[0]));
- mediametrics_setInt64(handle, "uuid_lsb", be64toh(mUuid[1]));
+ mediametrics_setInt64(handle, "uuid_msb", mUuid[0]);
+ mediametrics_setInt64(handle, "uuid_lsb", mUuid[1]);
mediametrics_setInt32(handle, "frontend", mFrontend);
mediametrics_setCString(handle, "object_nonce", mObjNonce.c_str());
if (!sessionId.empty()) {
diff --git a/drm/libmediadrm/DrmSessionManager.cpp b/drm/libmediadrm/DrmSessionManager.cpp
index e31395d..301538f 100644
--- a/drm/libmediadrm/DrmSessionManager.cpp
+++ b/drm/libmediadrm/DrmSessionManager.cpp
@@ -34,6 +34,7 @@
namespace android {
using aidl::android::media::MediaResourceParcel;
+using aidl::android::media::ClientInfoParcel;
namespace {
void ResourceManagerServiceDied(void* cookie) {
@@ -137,7 +138,10 @@
static int64_t clientId = 0;
mSessionMap[toStdVec(sessionId)] = (SessionInfo){pid, uid, clientId};
- mService->addResource(pid, uid, clientId++, drm, toResourceVec(sessionId, INT64_MAX));
+ ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(pid),
+ .uid = static_cast<int32_t>(uid),
+ .id = clientId++};
+ mService->addResource(clientInfo, drm, toResourceVec(sessionId, INT64_MAX));
}
void DrmSessionManager::useSession(const Vector<uint8_t> &sessionId) {
@@ -150,7 +154,10 @@
}
auto info = it->second;
- mService->addResource(info.pid, info.uid, info.clientId, NULL, toResourceVec(sessionId, -1));
+ ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(info.pid),
+ .uid = static_cast<int32_t>(info.uid),
+ .id = info.clientId};
+ mService->addResource(clientInfo, NULL, toResourceVec(sessionId, -1));
}
void DrmSessionManager::removeSession(const Vector<uint8_t> &sessionId) {
@@ -164,7 +171,10 @@
auto info = it->second;
// removeClient instead of removeSession because each client has only one session
- mService->removeClient(info.pid, info.clientId);
+ ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(info.pid),
+ .uid = static_cast<int32_t>(info.uid),
+ .id = info.clientId};
+ mService->removeClient(clientInfo);
mSessionMap.erase(it);
}
@@ -182,9 +192,13 @@
// cannot update mSessionMap because we do not know which sessionId is reclaimed;
// we rely on IResourceManagerClient to removeSession in reclaimResource
- Vector<uint8_t> dummy;
+ Vector<uint8_t> placeHolder;
bool success;
- ScopedAStatus status = service->reclaimResource(callingPid, toResourceVec(dummy, INT64_MAX), &success);
+ uid_t uid = AIBinder_getCallingUid();
+ ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(callingPid),
+ .uid = static_cast<int32_t>(uid)};
+ ScopedAStatus status = service->reclaimResource(
+ clientInfo, toResourceVec(placeHolder, INT64_MAX), &success);
return status.isOk() && success;
}
diff --git a/media/audioaidlconversion/AidlConversionEffect.cpp b/media/audioaidlconversion/AidlConversionEffect.cpp
index 2df97d1..ec380e3 100644
--- a/media/audioaidlconversion/AidlConversionEffect.cpp
+++ b/media/audioaidlconversion/AidlConversionEffect.cpp
@@ -14,12 +14,16 @@
* limitations under the License.
*/
+#include <cstdint>
+#include <inttypes.h>
#include <utility>
#define LOG_TAG "AidlConversionEffect"
//#define LOG_NDEBUG 0
#include <utils/Log.h>
+#include <aidl/android/hardware/audio/effect/DefaultExtension.h>
+#include <aidl/android/hardware/audio/effect/VendorExtension.h>
#include <media/AidlConversionCppNdk.h>
#include <media/AidlConversionEffect.h>
@@ -32,16 +36,21 @@
using ::aidl::android::hardware::audio::effect::AcousticEchoCanceler;
using ::aidl::android::hardware::audio::effect::AutomaticGainControlV2;
using ::aidl::android::hardware::audio::effect::BassBoost;
+using ::aidl::android::hardware::audio::effect::DefaultExtension;
using ::aidl::android::hardware::audio::effect::Descriptor;
using ::aidl::android::hardware::audio::effect::Downmix;
using ::aidl::android::hardware::audio::effect::DynamicsProcessing;
using ::aidl::android::hardware::audio::effect::Flags;
using ::aidl::android::hardware::audio::effect::Parameter;
using ::aidl::android::hardware::audio::effect::PresetReverb;
+using ::aidl::android::hardware::audio::effect::VendorExtension;
+using ::aidl::android::hardware::audio::effect::Visualizer;
using ::aidl::android::media::audio::common::AudioDeviceDescription;
using ::android::BAD_VALUE;
using ::android::base::unexpected;
+using ::android::effect::utils::EffectParamReader;
+using ::android::effect::utils::EffectParamWriter;
////////////////////////////////////////////////////////////////////////////////////////////////////
// Converters
@@ -349,5 +358,100 @@
return static_cast<int32_t>(aidl);
}
+ConversionResult<uint32_t> aidl2legacy_Parameter_Visualizer_ScalingMode_uint32(
+ Visualizer::ScalingMode aidl) {
+ switch (aidl) {
+ case Visualizer::ScalingMode::NORMALIZED: {
+ return 0;
+ }
+ case Visualizer::ScalingMode::AS_PLAYED: {
+ return 1;
+ }
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<Visualizer::ScalingMode> legacy2aidl_Parameter_Visualizer_uint32_ScalingMode(
+ uint32_t legacy) {
+ if (legacy == 0) {
+ return Visualizer::ScalingMode::NORMALIZED;
+ } else if (legacy == 1) {
+ return Visualizer::ScalingMode::AS_PLAYED;
+ } else {
+ return unexpected(BAD_VALUE);
+ }
+}
+
+ConversionResult<uint32_t> aidl2legacy_Parameter_Visualizer_MeasurementMode_uint32(
+ Visualizer::MeasurementMode aidl) {
+ switch (aidl) {
+ case Visualizer::MeasurementMode::NONE: {
+ return 0;
+ }
+ case Visualizer::MeasurementMode::PEAK_RMS: {
+ return 1;
+ }
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<Visualizer::MeasurementMode>
+legacy2aidl_Parameter_Visualizer_uint32_MeasurementMode(uint32_t legacy) {
+ if (legacy == 0) {
+ return Visualizer::MeasurementMode::NONE;
+ } else if (legacy == 1) {
+ return Visualizer::MeasurementMode::PEAK_RMS;
+ } else {
+ return unexpected(BAD_VALUE);
+ }
+}
+
+/**
+ * Copy the entire effect_param_t to DefaultExtension::bytes.
+ */
+ConversionResult<Parameter> legacy2aidl_EffectParameterReader_ParameterExtension(
+ EffectParamReader& param) {
+ size_t len = param.getTotalSize();
+ DefaultExtension ext;
+ ext.bytes.resize(len);
+ std::memcpy(ext.bytes.data(), ¶m.getEffectParam(), len);
+
+ VendorExtension effectParam;
+ effectParam.extension.setParcelable(ext);
+ return UNION_MAKE(Parameter, specific,
+ UNION_MAKE(Parameter::Specific, vendorEffect, effectParam));
+}
+
+ConversionResult<std::vector<uint8_t>> aidl2legacy_ParameterExtension_vector_uint8(
+ const Parameter& param) {
+ VendorExtension effectParam = VALUE_OR_RETURN(
+ (::aidl::android::getParameterSpecific<Parameter, VendorExtension,
+ Parameter::Specific::vendorEffect>(param)));
+ std::optional<DefaultExtension> ext;
+ if (STATUS_OK != effectParam.extension.getParcelable(&ext) || !ext.has_value()) {
+ return unexpected(BAD_VALUE);
+ }
+ return ext.value().bytes;
+}
+
+ConversionResult<::android::status_t> aidl2legacy_ParameterExtension_EffectParameterWriter(
+ const ::aidl::android::hardware::audio::effect::Parameter& aidl,
+ EffectParamWriter& legacy) {
+ const std::vector<uint8_t>& extBytes = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::aidl2legacy_ParameterExtension_vector_uint8(aidl));
+ if (legacy.getTotalSize() < extBytes.size()) {
+ legacy.setStatus(BAD_VALUE);
+ return unexpected(BAD_VALUE);
+ }
+
+ // create a reader wrapper and read the content to legacy EffectParamWriter
+ EffectParamReader reader(*(effect_param_t*)extBytes.data());
+ if (STATUS_OK != legacy.writeToValue(reader.getValueAddress(), reader.getValueSize())) {
+ legacy.setStatus(BAD_VALUE);
+ return unexpected(BAD_VALUE);
+ }
+ return STATUS_OK;
+}
+
} // namespace android
} // aidl
diff --git a/media/audioaidlconversion/include/media/AidlConversionCppNdk.h b/media/audioaidlconversion/include/media/AidlConversionCppNdk.h
index abf0231..e1daf31 100644
--- a/media/audioaidlconversion/include/media/AidlConversionCppNdk.h
+++ b/media/audioaidlconversion/include/media/AidlConversionCppNdk.h
@@ -127,6 +127,11 @@
ConversionResult<media::audio::common::AudioChannelLayout>
legacy2aidl_audio_channel_mask_t_AudioChannelLayout(audio_channel_mask_t legacy, bool isInput);
+audio_channel_mask_t aidl2legacy_AudioChannelLayout_layout_audio_channel_mask_t_bits(
+ int aidlLayout, bool isInput);
+int legacy2aidl_audio_channel_mask_t_bits_AudioChannelLayout_layout(
+ audio_channel_mask_t legacy, bool isInput);
+
enum class AudioPortDirection {
INPUT, OUTPUT
};
diff --git a/media/audioaidlconversion/include/media/AidlConversionEffect.h b/media/audioaidlconversion/include/media/AidlConversionEffect.h
index 83aa614..3aa9ac2 100644
--- a/media/audioaidlconversion/include/media/AidlConversionEffect.h
+++ b/media/audioaidlconversion/include/media/AidlConversionEffect.h
@@ -26,6 +26,7 @@
#include <hardware/audio_effect.h>
#include <media/AidlConversionUtil.h>
#include <system/audio_effect.h>
+#include <system/audio_effects/audio_effects_utils.h>
#include <aidl/android/hardware/audio/effect/IEffect.h>
@@ -126,5 +127,24 @@
ConversionResult<int32_t> aidl2legacy_DynamicsProcessing_ResolutionPreference_int32(
::aidl::android::hardware::audio::effect::DynamicsProcessing::ResolutionPreference aidl);
+ConversionResult<uint32_t> aidl2legacy_Parameter_Visualizer_ScalingMode_uint32(
+ ::aidl::android::hardware::audio::effect::Visualizer::ScalingMode aidl);
+ConversionResult<::aidl::android::hardware::audio::effect::Visualizer::ScalingMode>
+legacy2aidl_Parameter_Visualizer_uint32_ScalingMode(uint32_t legacy);
+
+ConversionResult<uint32_t> aidl2legacy_Parameter_Visualizer_MeasurementMode_uint32(
+ ::aidl::android::hardware::audio::effect::Visualizer::MeasurementMode aidl);
+ConversionResult<::aidl::android::hardware::audio::effect::Visualizer::MeasurementMode>
+legacy2aidl_Parameter_Visualizer_uint32_MeasurementMode(uint32_t legacy);
+
+ConversionResult<::aidl::android::hardware::audio::effect::Parameter>
+legacy2aidl_EffectParameterReader_ParameterExtension(
+ ::android::effect::utils::EffectParamReader& param);
+ConversionResult<std::vector<uint8_t>> aidl2legacy_ParameterExtension_vector_uint8(
+ const ::aidl::android::hardware::audio::effect::Parameter& legacy);
+ConversionResult<::android::status_t> aidl2legacy_ParameterExtension_EffectParameterWriter(
+ const ::aidl::android::hardware::audio::effect::Parameter& aidl,
+ ::android::effect::utils::EffectParamWriter& legacy);
+
} // namespace android
} // namespace aidl
diff --git a/media/libaudiohal/impl/DeviceHalAidl.cpp b/media/libaudiohal/impl/DeviceHalAidl.cpp
index 44f81b7..67f9493 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalAidl.cpp
@@ -45,6 +45,7 @@
using aidl::android::media::audio::common::AudioPort;
using aidl::android::media::audio::common::AudioPortConfig;
using aidl::android::media::audio::common::AudioPortDeviceExt;
+using aidl::android::media::audio::common::AudioPortMixExt;
using aidl::android::media::audio::common::AudioPortExt;
using aidl::android::media::audio::common::AudioSource;
using aidl::android::media::audio::common::Int;
@@ -549,8 +550,19 @@
sources == nullptr || sinks == nullptr || patch == nullptr) {
return BAD_VALUE;
}
- // Note that the patch handle (*patch) is provided by the framework.
- // In tests it's possible that its value is AUDIO_PATCH_HANDLE_NONE.
+ // When the patch handle (*patch) is AUDIO_PATCH_HANDLE_NONE, it means
+ // the framework wants to create a new patch. The handle has to be generated
+ // by the HAL. Since handles generated this way can only be unique within
+ // a HAL module, the framework generates a globally unique handle, and maps
+ // it on the <HAL module, patch handle> pair.
+ // When the patch handle is set, it meant the framework intends to update
+ // an existing patch.
+ //
+ // This behavior corresponds to HAL module behavior, with the only difference
+ // that the HAL module uses `int32_t` for patch IDs. The following assert ensures
+ // that both the framework and the HAL use the same value for "no ID":
+ static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
+ int32_t halPatchId = static_cast<int32_t>(*patch);
// Upon conversion, mix port configs contain audio configuration, while
// device port configs contain device address. This data is used to find
@@ -573,17 +585,12 @@
sinks[i], isInput, 0)));
}
Cleanups cleanups;
- auto existingPatchIt = mPatches.end();
- auto fwkHandlesIt = *patch != AUDIO_PATCH_HANDLE_NONE ?
- mFwkHandles.find(*patch) : mFwkHandles.end();
+ auto existingPatchIt = halPatchId != 0 ? mPatches.find(halPatchId): mPatches.end();
AudioPatch aidlPatch;
- if (fwkHandlesIt != mFwkHandles.end()) {
- existingPatchIt = mPatches.find(fwkHandlesIt->second);
- if (existingPatchIt != mPatches.end()) {
- aidlPatch = existingPatchIt->second;
- aidlPatch.sourcePortConfigIds.clear();
- aidlPatch.sinkPortConfigIds.clear();
- }
+ if (existingPatchIt != mPatches.end()) {
+ aidlPatch = existingPatchIt->second;
+ aidlPatch.sourcePortConfigIds.clear();
+ aidlPatch.sinkPortConfigIds.clear();
}
ALOGD("%s: sources: %s, sinks: %s",
__func__, ::android::internal::ToString(aidlSources).c_str(),
@@ -611,20 +618,8 @@
bool created = false;
RETURN_STATUS_IF_ERROR(findOrCreatePatch(aidlPatch, &aidlPatch, &created));
// Since no cleanup of the patch is needed, 'created' is ignored.
- if (fwkHandlesIt != mFwkHandles.end()) {
- fwkHandlesIt->second = aidlPatch.id;
- // Patch handle (*patch) stays the same.
- } else {
- if (*patch == AUDIO_PATCH_HANDLE_NONE) {
- // This isn't good as the module can't provide a handle which is really unique.
- // However, this situation should only happen in tests.
- *patch = aidlPatch.id;
- LOG_ALWAYS_FATAL_IF(mFwkHandles.count(*patch) > 0,
- "%s: patch id %d clashes with another framework patch handle",
- __func__, *patch);
- }
- mFwkHandles.emplace(*patch, aidlPatch.id);
- }
+ halPatchId = aidlPatch.id;
+ *patch = static_cast<audio_patch_handle_t>(halPatchId);
}
cleanups.disarmAll();
return OK;
@@ -634,12 +629,18 @@
ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
TIME_CHECK();
if (!mModule) return NO_INIT;
- auto idMapIt = mFwkHandles.find(patch);
- if (idMapIt == mFwkHandles.end()) {
+ static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
+ if (patch == AUDIO_PATCH_HANDLE_NONE) {
return BAD_VALUE;
}
- RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->resetAudioPatch(idMapIt->second)));
- mFwkHandles.erase(idMapIt);
+ int32_t halPatchId = static_cast<int32_t>(patch);
+ auto patchIt = mPatches.find(halPatchId);
+ if (patchIt == mPatches.end()) {
+ ALOGE("%s: patch with id %d not found", __func__, halPatchId);
+ return BAD_VALUE;
+ }
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->resetAudioPatch(halPatchId)));
+ mPatches.erase(patchIt);
return OK;
}
@@ -744,22 +745,27 @@
return p.ext.get<AudioPortExt::Tag::device>().device == device;
}
-status_t DeviceHalAidl::createPortConfig(const AudioPortConfig& requestedPortConfig,
- AudioPortConfig* appliedPortConfig) {
+status_t DeviceHalAidl::createPortConfig(
+ const AudioPortConfig& requestedPortConfig, PortConfigs::iterator* result) {
TIME_CHECK();
+ AudioPortConfig appliedPortConfig;
bool applied = false;
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
- requestedPortConfig, appliedPortConfig, &applied)));
+ requestedPortConfig, &appliedPortConfig, &applied)));
if (!applied) {
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
- *appliedPortConfig, appliedPortConfig, &applied)));
+ appliedPortConfig, &appliedPortConfig, &applied)));
if (!applied) {
ALOGE("%s: module %s did not apply suggested config %s",
- __func__, mInstance.c_str(), appliedPortConfig->toString().c_str());
+ __func__, mInstance.c_str(), appliedPortConfig.toString().c_str());
return NO_INIT;
}
}
- mPortConfigs.emplace(appliedPortConfig->id, *appliedPortConfig);
+ auto id = appliedPortConfig.id;
+ auto [it, inserted] = mPortConfigs.emplace(std::move(id), std::move(appliedPortConfig));
+ LOG_ALWAYS_FATAL_IF(!inserted, "%s: port config with id %d already exists",
+ __func__, it->first);
+ *result = it;
return OK;
}
@@ -806,10 +812,7 @@
}
AudioPortConfig requestedPortConfig;
requestedPortConfig.portId = portsIt->first;
- AudioPortConfig appliedPortConfig;
- RETURN_STATUS_IF_ERROR(createPortConfig(requestedPortConfig, &appliedPortConfig));
- portConfigIt = mPortConfigs.insert(
- mPortConfigs.end(), std::make_pair(appliedPortConfig.id, appliedPortConfig));
+ RETURN_STATUS_IF_ERROR(createPortConfig(requestedPortConfig, &portConfigIt));
*created = true;
} else {
*created = false;
@@ -821,23 +824,40 @@
status_t DeviceHalAidl::findOrCreatePortConfig(
const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle,
AudioPortConfig* portConfig, bool* created) {
+ // These flags get removed one by one in this order when retrying port finding.
+ static const std::vector<AudioInputFlags> kOptionalInputFlags{
+ AudioInputFlags::FAST, AudioInputFlags::RAW };
auto portConfigIt = findPortConfig(config, flags, ioHandle);
if (portConfigIt == mPortConfigs.end() && flags.has_value()) {
- auto portsIt = findPort(config, flags.value());
+ auto optionalInputFlagsIt = kOptionalInputFlags.begin();
+ AudioIoFlags matchFlags = flags.value();
+ auto portsIt = findPort(config, matchFlags);
+ while (portsIt == mPorts.end() && matchFlags.getTag() == AudioIoFlags::Tag::input
+ && optionalInputFlagsIt != kOptionalInputFlags.end()) {
+ if (!isBitPositionFlagSet(
+ matchFlags.get<AudioIoFlags::Tag::input>(), *optionalInputFlagsIt)) {
+ ++optionalInputFlagsIt;
+ continue;
+ }
+ matchFlags.set<AudioIoFlags::Tag::input>(matchFlags.get<AudioIoFlags::Tag::input>() &
+ ~makeBitPositionFlagMask(*optionalInputFlagsIt++));
+ portsIt = findPort(config, matchFlags);
+ ALOGI("%s: mix port for config %s, flags %s was not found in the module %s, "
+ "retried with flags %s", __func__, config.toString().c_str(),
+ flags.value().toString().c_str(), mInstance.c_str(),
+ matchFlags.toString().c_str());
+ }
if (portsIt == mPorts.end()) {
ALOGE("%s: mix port for config %s, flags %s is not found in the module %s",
- __func__, config.toString().c_str(), flags.value().toString().c_str(),
+ __func__, config.toString().c_str(), matchFlags.toString().c_str(),
mInstance.c_str());
return BAD_VALUE;
}
AudioPortConfig requestedPortConfig;
requestedPortConfig.portId = portsIt->first;
setPortConfigFromConfig(&requestedPortConfig, config);
- AudioPortConfig appliedPortConfig;
- RETURN_STATUS_IF_ERROR(createPortConfig(requestedPortConfig, &appliedPortConfig));
- appliedPortConfig.ext.get<AudioPortExt::Tag::mix>().handle = ioHandle;
- portConfigIt = mPortConfigs.insert(
- mPortConfigs.end(), std::make_pair(appliedPortConfig.id, appliedPortConfig));
+ requestedPortConfig.ext = AudioPortMixExt{ .handle = ioHandle };
+ RETURN_STATUS_IF_ERROR(createPortConfig(requestedPortConfig, &portConfigIt));
*created = true;
} else if (!flags.has_value()) {
ALOGW("%s: mix port config for %s, handle %d not found in the module %s, "
@@ -899,12 +919,10 @@
DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(
const AudioConfig& config, const AudioIoFlags& flags) {
- using Tag = AudioPortExt::Tag;
- AudioIoFlags matchFlags = flags;
auto matcher = [&](const auto& pair) {
const auto& p = pair.second;
- return p.ext.getTag() == Tag::mix &&
- p.flags == matchFlags &&
+ return p.ext.getTag() == AudioPortExt::Tag::mix &&
+ p.flags == flags &&
std::find_if(p.profiles.begin(), p.profiles.end(),
[&](const auto& prof) {
return prof.format == config.base.format &&
@@ -913,15 +931,7 @@
std::find(prof.sampleRates.begin(), prof.sampleRates.end(),
config.base.sampleRate) != prof.sampleRates.end();
}) != p.profiles.end(); };
- auto it = std::find_if(mPorts.begin(), mPorts.end(), matcher);
- if (it == mPorts.end() && flags.getTag() == AudioIoFlags::Tag::input &&
- isBitPositionFlagSet(flags.get<AudioIoFlags::Tag::input>(), AudioInputFlags::FAST)) {
- // "Fast" input is not a mandatory flag, try without it.
- matchFlags.set<AudioIoFlags::Tag::input>(flags.get<AudioIoFlags::Tag::input>() &
- ~makeBitPositionFlagMask(AudioInputFlags::FAST));
- it = std::find_if(mPorts.begin(), mPorts.end(), matcher);
- }
- return it;
+ return std::find_if(mPorts.begin(), mPorts.end(), matcher);
}
DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(const AudioDevice& device) {
diff --git a/media/libaudiohal/impl/DeviceHalAidl.h b/media/libaudiohal/impl/DeviceHalAidl.h
index 6f16daf..4077f7e 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.h
+++ b/media/libaudiohal/impl/DeviceHalAidl.h
@@ -179,7 +179,7 @@
const ::aidl::android::media::audio::common::AudioPortConfig& p);
status_t createPortConfig(
const ::aidl::android::media::audio::common::AudioPortConfig& requestedPortConfig,
- ::aidl::android::media::audio::common::AudioPortConfig* appliedPortConfig);
+ PortConfigs::iterator* result);
status_t findOrCreatePatch(
const std::set<int32_t>& sourcePortConfigIds,
const std::set<int32_t>& sinkPortConfigIds,
@@ -248,7 +248,6 @@
int32_t mDefaultOutputPortId = -1;
PortConfigs mPortConfigs;
Patches mPatches;
- std::map<audio_patch_handle_t, int32_t /*patch ID*/> mFwkHandles;
std::mutex mLock;
std::map<void*, Callbacks> mCallbacks GUARDED_BY(mLock);
};
diff --git a/media/libaudiohal/impl/EffectBufferHalAidl.cpp b/media/libaudiohal/impl/EffectBufferHalAidl.cpp
index 5af8e24..a701852 100644
--- a/media/libaudiohal/impl/EffectBufferHalAidl.cpp
+++ b/media/libaudiohal/impl/EffectBufferHalAidl.cpp
@@ -14,26 +14,39 @@
* limitations under the License.
*/
+#include <algorithm>
+#include <cstdint>
+#include <cstring>
+#include <sys/mman.h>
#define LOG_TAG "EffectBufferHalAidl"
//#define LOG_NDEBUG 0
+#include <cutils/ashmem.h>
#include <utils/Log.h>
#include "EffectBufferHalAidl.h"
+using ndk::ScopedFileDescriptor;
+
namespace android {
namespace effect {
// static
status_t EffectBufferHalAidl::allocate(size_t size, sp<EffectBufferHalInterface>* buffer) {
- ALOGE("%s not implemented yet %zu %p", __func__, size, buffer);
return mirror(nullptr, size, buffer);
}
status_t EffectBufferHalAidl::mirror(void* external, size_t size,
sp<EffectBufferHalInterface>* buffer) {
- // buffer->setExternalData(external);
- ALOGW("%s not implemented yet %p %zu %p", __func__, external, size, buffer);
+ sp<EffectBufferHalAidl> tempBuffer = new EffectBufferHalAidl(size);
+ status_t status = tempBuffer.get()->init();
+ if (status != OK) {
+ ALOGE("%s init failed %d", __func__, status);
+ return status;
+ }
+
+ tempBuffer->setExternalData(external);
+ *buffer = tempBuffer;
return OK;
}
@@ -48,7 +61,22 @@
}
status_t EffectBufferHalAidl::init() {
- ALOGW("%s not implemented yet", __func__);
+ int fd = ashmem_create_region("audioEffectAidl", mBufferSize);
+ if (fd < 0) {
+ ALOGE("%s create ashmem failed %d", __func__, fd);
+ return fd;
+ }
+
+ ScopedFileDescriptor tempFd(fd);
+ mAudioBuffer.raw = mmap(nullptr /* address */, mBufferSize /* length */, PROT_READ | PROT_WRITE,
+ MAP_SHARED, fd, 0 /* offset */);
+ if (mAudioBuffer.raw == MAP_FAILED) {
+ ALOGE("mmap failed for fd %d", fd);
+ mAudioBuffer.raw = nullptr;
+ return INVALID_OPERATION;
+ }
+
+ mMemory = {std::move(tempFd), static_cast<int64_t>(mBufferSize)};
return OK;
}
@@ -76,11 +104,26 @@
}
void EffectBufferHalAidl::update() {
- ALOGW("%s not implemented yet", __func__);
+ update(mBufferSize);
}
void EffectBufferHalAidl::commit() {
- ALOGW("%s not implemented yet", __func__);
+ commit(mBufferSize);
+}
+
+void EffectBufferHalAidl::copy(void* dst, const void* src, size_t n) const {
+ if (!dst || !src) {
+ return;
+ }
+ std::memcpy(dst, src, std::min(n, mBufferSize));
+}
+
+void EffectBufferHalAidl::update(size_t n) {
+ copy(mAudioBuffer.raw, mExternalData, n);
+}
+
+void EffectBufferHalAidl::commit(size_t n) {
+ copy(mExternalData, mAudioBuffer.raw, n);
}
} // namespace effect
diff --git a/media/libaudiohal/impl/EffectBufferHalAidl.h b/media/libaudiohal/impl/EffectBufferHalAidl.h
index f488708..035314b 100644
--- a/media/libaudiohal/impl/EffectBufferHalAidl.h
+++ b/media/libaudiohal/impl/EffectBufferHalAidl.h
@@ -16,6 +16,8 @@
#pragma once
+#include <aidl/android/hardware/common/Ashmem.h>
+
#include <media/audiohal/EffectBufferHalInterface.h>
#include <system/audio_effect.h>
@@ -44,16 +46,18 @@
private:
friend class EffectBufferHalInterface;
+ // buffer size in bytes
const size_t mBufferSize;
bool mFrameCountChanged;
void* mExternalData;
+ aidl::android::hardware::common::Ashmem mMemory;
audio_buffer_t mAudioBuffer;
// Can not be constructed directly by clients.
explicit EffectBufferHalAidl(size_t size);
~EffectBufferHalAidl();
-
+ void copy(void* dst, const void* src, size_t n) const;
status_t init();
};
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
index 7e25b04..dc47d67 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
@@ -24,6 +24,7 @@
#include <media/AidlConversionCppNdk.h>
#include <media/AidlConversionNdk.h>
#include <media/AidlConversionEffect.h>
+#include <system/audio_effects/effect_visualizer.h>
#include <utils/Log.h>
@@ -59,7 +60,10 @@
{EFFECT_CMD_SET_INPUT_DEVICE, &EffectConversionHelperAidl::handleSetDevice},
{EFFECT_CMD_SET_VOLUME, &EffectConversionHelperAidl::handleSetVolume},
{EFFECT_CMD_OFFLOAD, &EffectConversionHelperAidl::handleSetOffload},
- {EFFECT_CMD_FIRST_PROPRIETARY, &EffectConversionHelperAidl::handleFirstPriority}};
+ {EFFECT_CMD_FIRST_PROPRIETARY, &EffectConversionHelperAidl::handleFirstPriority},
+ // Only visualizer support these commands
+ {VISUALIZER_CMD_CAPTURE, &EffectConversionHelperAidl::handleVisualizerCapture},
+ {VISUALIZER_CMD_MEASURE, &EffectConversionHelperAidl::handleVisualizerMeasure}};
EffectConversionHelperAidl::EffectConversionHelperAidl(
std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
@@ -286,5 +290,45 @@
return OK;
}
+status_t EffectConversionHelperAidl::handleVisualizerCapture(uint32_t cmdSize __unused,
+ const void* pCmdData __unused,
+ uint32_t* replySize,
+ void* pReplyData) {
+ if (!replySize || !pReplyData) {
+ ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
+ return BAD_VALUE;
+ }
+
+ const auto& uuid = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::aidl2legacy_AudioUuid_audio_uuid_t(mDesc.common.id.type));
+ if (0 != memcmp(&uuid, SL_IID_VISUALIZATION, sizeof(effect_uuid_t))) {
+ ALOGE("%s visualizer command not supported by %s", __func__,
+ mDesc.common.id.toString().c_str());
+ return BAD_VALUE;
+ }
+
+ return visualizerCapture(replySize, pReplyData);
+}
+
+status_t EffectConversionHelperAidl::handleVisualizerMeasure(uint32_t cmdSize __unused,
+ const void* pCmdData __unused,
+ uint32_t* replySize,
+ void* pReplyData) {
+ if (!replySize || !pReplyData) {
+ ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
+ return BAD_VALUE;
+ }
+
+ const auto& uuid = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::aidl2legacy_AudioUuid_audio_uuid_t(mDesc.common.id.type));
+ if (0 != memcmp(&uuid, SL_IID_VISUALIZATION, sizeof(effect_uuid_t))) {
+ ALOGE("%s visualizer command not supported by %s", __func__,
+ mDesc.common.id.toString().c_str());
+ return BAD_VALUE;
+ }
+
+ return visualizerMeasure(replySize, pReplyData);
+}
+
} // namespace effect
} // namespace android
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.h b/media/libaudiohal/impl/EffectConversionHelperAidl.h
index 94435c6..f9a4e49 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.h
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.h
@@ -30,6 +30,10 @@
status_t handleCommand(uint32_t cmdCode, uint32_t cmdSize, void* pCmdData, uint32_t* replySize,
void* pReplyData);
virtual ~EffectConversionHelperAidl() {}
+ const ::aidl::android::hardware::audio::effect::IEffect::OpenEffectReturn&
+ getEffectReturnParam() const {
+ return mOpenReturn;
+ }
protected:
const int32_t mSessionId;
@@ -94,10 +98,20 @@
void* pReplyData);
status_t handleFirstPriority(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
void* pReplyData);
+ status_t handleVisualizerCapture(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
+ void* pReplyData);
+ status_t handleVisualizerMeasure(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
+ void* pReplyData);
// implemented by conversion of each effect
virtual status_t setParameter(utils::EffectParamReader& param) = 0;
virtual status_t getParameter(utils::EffectParamWriter& param) = 0;
+ virtual status_t visualizerCapture(uint32_t* replySize __unused, void* pReplyData __unused) {
+ return BAD_VALUE;
+ }
+ virtual status_t visualizerMeasure(uint32_t* replySize __unused, void* pReplyData __unused) {
+ return BAD_VALUE;
+ }
};
} // namespace effect
diff --git a/media/libaudiohal/impl/EffectHalAidl.cpp b/media/libaudiohal/impl/EffectHalAidl.cpp
index 8fa301a..a684dee 100644
--- a/media/libaudiohal/impl/EffectHalAidl.cpp
+++ b/media/libaudiohal/impl/EffectHalAidl.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <cstddef>
#define LOG_TAG "EffectHalAidl"
//#define LOG_NDEBUG 0
@@ -136,24 +137,51 @@
}
status_t EffectHalAidl::setInBuffer(const sp<EffectBufferHalInterface>& buffer) {
- if (buffer == nullptr) {
- return BAD_VALUE;
- }
- ALOGW("%s not implemented yet", __func__);
+ mInBuffer = buffer;
return OK;
}
status_t EffectHalAidl::setOutBuffer(const sp<EffectBufferHalInterface>& buffer) {
- if (buffer == nullptr) {
- return BAD_VALUE;
- }
- ALOGW("%s not implemented yet", __func__);
+ mOutBuffer = buffer;
return OK;
}
+
+// write to input FMQ here, wait for statusMQ STATUS_OK, and read from output FMQ
status_t EffectHalAidl::process() {
- ALOGW("%s not implemented yet", __func__);
- // write to input FMQ here, and wait for statusMQ STATUS_OK
+ size_t available = mInputQ->availableToWrite();
+ size_t floatsToWrite = std::min(available, mInBuffer->getSize() / sizeof(float));
+ if (floatsToWrite == 0) {
+ ALOGW("%s not able to write, floats in buffer %zu, space in FMQ %zu", __func__,
+ mInBuffer->getSize() / sizeof(float), available);
+ return INVALID_OPERATION;
+ }
+ if (!mInputQ->write((float*)mInBuffer->ptr(), floatsToWrite)) {
+ ALOGW("%s failed to write %zu into inputQ", __func__, floatsToWrite);
+ return INVALID_OPERATION;
+ }
+
+ IEffect::Status retStatus{};
+ if (!mStatusQ->readBlocking(&retStatus, 1) || retStatus.status != OK ||
+ (size_t)retStatus.fmqConsumed != floatsToWrite || retStatus.fmqProduced == 0) {
+ ALOGW("%s read status failed: %s", __func__, retStatus.toString().c_str());
+ return INVALID_OPERATION;
+ }
+
+ available = mOutputQ->availableToRead();
+ size_t floatsToRead = std::min(available, mOutBuffer->getSize() / sizeof(float));
+ if (floatsToRead == 0) {
+ ALOGW("%s not able to read, buffer space %zu, floats in FMQ %zu", __func__,
+ mOutBuffer->getSize() / sizeof(float), available);
+ return INVALID_OPERATION;
+ }
+ if (!mOutputQ->read((float*)mOutBuffer->ptr(), floatsToRead)) {
+ ALOGW("%s failed to read %zu from outputQ", __func__, floatsToRead);
+ return INVALID_OPERATION;
+ }
+
+ ALOGD("%s %s consumed %zu produced %zu", __func__, mDesc.common.name.c_str(), floatsToWrite,
+ floatsToRead);
return OK;
}
@@ -165,14 +193,32 @@
status_t EffectHalAidl::command(uint32_t cmdCode, uint32_t cmdSize, void* pCmdData,
uint32_t* replySize, void* pReplyData) {
- return mConversion
- ? mConversion->handleCommand(cmdCode, cmdSize, pCmdData, replySize, pReplyData)
- : INVALID_OPERATION;
+ TIME_CHECK();
+ if (!mConversion) {
+ ALOGE("%s can not handle command %d when conversion not exist", __func__, cmdCode);
+ return INVALID_OPERATION;
+ }
+
+ status_t ret = mConversion->handleCommand(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
+ // update FMQs when effect open successfully
+ if (ret == OK && cmdCode == EFFECT_CMD_INIT) {
+ const auto& retParam = mConversion->getEffectReturnParam();
+ mStatusQ = std::make_unique<StatusMQ>(retParam.statusMQ);
+ mInputQ = std::make_unique<DataMQ>(retParam.inputDataMQ);
+ mOutputQ = std::make_unique<DataMQ>(retParam.outputDataMQ);
+ if (!mStatusQ->isValid() || !mInputQ->isValid() || !mOutputQ->isValid()) {
+ ALOGE("%s return with invalid FMQ", __func__);
+ return NO_INIT;
+ }
+ }
+
+ return ret;
}
status_t EffectHalAidl::getDescriptor(effect_descriptor_t* pDescriptor) {
- ALOGW("%s %p", __func__, pDescriptor);
+ TIME_CHECK();
if (pDescriptor == nullptr) {
+ ALOGE("%s null descriptor pointer", __func__);
return BAD_VALUE;
}
Descriptor aidlDesc;
@@ -184,12 +230,13 @@
}
status_t EffectHalAidl::close() {
+ TIME_CHECK();
return statusTFromBinderStatus(mEffect->close());
}
status_t EffectHalAidl::dump(int fd) {
- ALOGW("%s not implemented yet, fd %d", __func__, fd);
- return OK;
+ TIME_CHECK();
+ return mEffect->dump(fd, nullptr, 0);
}
} // namespace effect
diff --git a/media/libaudiohal/impl/EffectHalAidl.h b/media/libaudiohal/impl/EffectHalAidl.h
index 83b644b..194150d 100644
--- a/media/libaudiohal/impl/EffectHalAidl.h
+++ b/media/libaudiohal/impl/EffectHalAidl.h
@@ -16,11 +16,13 @@
#pragma once
+#include <memory>
+
#include <aidl/android/hardware/audio/effect/IEffect.h>
#include <aidl/android/hardware/audio/effect/IFactory.h>
+#include <fmq/AidlMessageQueue.h>
#include <media/audiohal/EffectHalInterface.h>
#include <system/audio_effect.h>
-#include <memory>
#include "EffectConversionHelperAidl.h"
@@ -29,6 +31,12 @@
class EffectHalAidl : public EffectHalInterface {
public:
+ using StatusMQ = ::android::AidlMessageQueue<
+ ::aidl::android::hardware::audio::effect::IEffect::Status,
+ ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>;
+ using DataMQ = ::android::AidlMessageQueue<
+ float, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>;
+
// Set the input buffer.
status_t setInBuffer(const sp<EffectBufferHalInterface>& buffer) override;
@@ -63,6 +71,9 @@
return mEffect;
}
+ // for TIME_CHECK
+ const std::string getClassName() const { return "EffectHalAidl"; }
+
private:
friend class sp<EffectHalAidl>;
@@ -73,6 +84,8 @@
const int32_t mIoId;
const ::aidl::android::hardware::audio::effect::Descriptor mDesc;
std::unique_ptr<EffectConversionHelperAidl> mConversion;
+ std::unique_ptr<StatusMQ> mStatusQ;
+ std::unique_ptr<DataMQ> mInputQ, mOutputQ;
sp<EffectBufferHalInterface> mInBuffer, mOutBuffer;
effect_config_t mConfig;
diff --git a/media/libaudiohal/impl/EffectHalHidl.cpp b/media/libaudiohal/impl/EffectHalHidl.cpp
index ed952a3..7ecdbd2 100644
--- a/media/libaudiohal/impl/EffectHalHidl.cpp
+++ b/media/libaudiohal/impl/EffectHalHidl.cpp
@@ -107,13 +107,13 @@
}
status_t EffectHalHidl::process() {
- // TIME_CHECK(); // TODO(b/238654698) reenable only when optimized.
+ // TIME_CHECK(); // TODO(b/243839867) reenable only when optimized.
return processImpl(static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS));
}
status_t EffectHalHidl::processReverse() {
- // TIME_CHECK(); // TODO(b/238654698) reenable only when optimized.
+ // TIME_CHECK(); // TODO(b/243839867) reenable only when optimized.
return processImpl(static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS_REVERSE));
}
diff --git a/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
index 0aae87b..b418b6c 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
+++ b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
@@ -20,7 +20,6 @@
#define LOG_TAG "EffectsFactoryHalAidl"
//#define LOG_NDEBUG 0
-#include <aidl/android/hardware/audio/effect/IFactory.h>
#include <error/expected_utils.h>
#include <android/binder_manager.h>
#include <media/AidlConversionCppNdk.h>
@@ -139,20 +138,18 @@
}
status_t EffectsFactoryHalAidl::dumpEffects(int fd) {
- ALOGE("%s not implemented yet, fd %d", __func__, fd);
- return INVALID_OPERATION;
+ // TODO: add proxy dump here because AIDL service EffectFactory doesn't have proxy handle
+ return mFactory->dump(fd, nullptr, 0);
}
status_t EffectsFactoryHalAidl::allocateBuffer(size_t size, sp<EffectBufferHalInterface>* buffer) {
ALOGI("%s size %zu buffer %p", __func__, size, buffer);
- // Buffer doesn't allocated here for AIDL, instead each effect open will return I/O data FMQ.
return EffectBufferHalAidl::allocate(size, buffer);
}
status_t EffectsFactoryHalAidl::mirrorBuffer(void* external, size_t size,
sp<EffectBufferHalInterface>* buffer) {
ALOGI("%s extern %p size %zu buffer %p", __func__, external, size, buffer);
- // TODO: implement with FMQ
return EffectBufferHalAidl::mirror(external, size, buffer);
}
diff --git a/media/libaudiohal/impl/EffectsFactoryHalAidl.h b/media/libaudiohal/impl/EffectsFactoryHalAidl.h
index 1e85da9..9c3643b 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalAidl.h
+++ b/media/libaudiohal/impl/EffectsFactoryHalAidl.h
@@ -20,6 +20,7 @@
#include <memory>
#include <mutex>
+#include <aidl/android/hardware/audio/effect/IFactory.h>
#include <android-base/thread_annotations.h>
#include <media/audiohal/EffectsFactoryHalInterface.h>
#include <system/thread_defs.h>
@@ -59,6 +60,9 @@
detail::AudioHalVersionInfo getHalVersion() const override;
+ // for TIME_CHECK
+ const std::string getClassName() const { return "EffectHalAidl"; }
+
private:
std::mutex mLock;
const std::shared_ptr<IFactory> mFactory;
diff --git a/media/libaudiohal/impl/StreamHalAidl.cpp b/media/libaudiohal/impl/StreamHalAidl.cpp
index f9c9f3d..9d67b67 100644
--- a/media/libaudiohal/impl/StreamHalAidl.cpp
+++ b/media/libaudiohal/impl/StreamHalAidl.cpp
@@ -21,12 +21,14 @@
#include <cstdint>
#include <audio_utils/clock.h>
+#include <media/AidlConversionUtil.h>
#include <mediautils/TimeCheck.h>
#include <utils/Log.h>
#include "DeviceHalAidl.h"
#include "StreamHalAidl.h"
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
using ::aidl::android::hardware::audio::core::IStreamCommon;
using ::aidl::android::hardware::audio::core::IStreamIn;
using ::aidl::android::hardware::audio::core::IStreamOut;
@@ -259,7 +261,7 @@
status_t StreamHalAidl::transfer(void *buffer, size_t bytes, size_t *transferred) {
ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
- // TIME_CHECK(); // TODO(b/238654698) reenable only when optimized.
+ // TIME_CHECK(); // TODO(b/243839867) reenable only when optimized.
if (!mStream || mContext.getDataMQ() == nullptr) return NO_INIT;
mWorkerTid.store(gettid(), std::memory_order_release);
// Switch the stream into an active state if needed.
@@ -354,7 +356,8 @@
return sendCommand(makeHalCommand<HalCommand::Tag::drain>(
mIsInput ? StreamDescriptor::DrainMode::DRAIN_UNSPECIFIED :
earlyNotify ? StreamDescriptor::DrainMode::DRAIN_EARLY_NOTIFY :
- StreamDescriptor::DrainMode::DRAIN_ALL), reply);
+ StreamDescriptor::DrainMode::DRAIN_ALL), reply,
+ true /*safeFromNonWorkerThread*/);
}
status_t StreamHalAidl::flush(StreamDescriptor::Reply* reply) {
@@ -424,7 +427,7 @@
const ::aidl::android::hardware::audio::core::StreamDescriptor::Command &command,
::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply,
bool safeFromNonWorkerThread) {
- // TIME_CHECK(); // TODO(b/238654698) reenable only when optimized.
+ // TIME_CHECK(); // TODO(b/243839867) reenable only when optimized.
if (!safeFromNonWorkerThread) {
const pid_t workerTid = mWorkerTid.load(std::memory_order_acquire);
LOG_ALWAYS_FATAL_IF(workerTid != gettid(),
@@ -492,11 +495,10 @@
return StreamHalAidl::getLatency(latency);
}
-status_t StreamOutHalAidl::setVolume(float left __unused, float right __unused) {
+status_t StreamOutHalAidl::setVolume(float left, float right) {
TIME_CHECK();
if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
- return OK;
+ return statusTFromBinderStatus(mStream->setHwVolume({left, right}));
}
status_t StreamOutHalAidl::selectPresentation(int presentationId __unused, int programId __unused) {
@@ -641,7 +643,7 @@
TIME_CHECK();
if (!mStream) return NO_INIT;
ALOGE("%s not implemented yet", __func__);
- return OK;
+ return BAD_VALUE;
}
status_t StreamOutHalAidl::setPlaybackRateParameters(
@@ -649,7 +651,7 @@
TIME_CHECK();
if (!mStream) return NO_INIT;
ALOGE("%s not implemented yet", __func__);
- return OK;
+ return BAD_VALUE;
}
status_t StreamOutHalAidl::setEventCallback(
diff --git a/media/libaudiohal/impl/StreamHalHidl.cpp b/media/libaudiohal/impl/StreamHalHidl.cpp
index 07c6df5..192790c 100644
--- a/media/libaudiohal/impl/StreamHalHidl.cpp
+++ b/media/libaudiohal/impl/StreamHalHidl.cpp
@@ -441,7 +441,7 @@
#endif
status_t StreamOutHalHidl::write(const void *buffer, size_t bytes, size_t *written) {
- // TIME_CHECK(); // TODO(b/238654698) reenable only when optimized.
+ // TIME_CHECK(); // TODO(b/243839867) reenable only when optimized.
if (mStream == 0) return NO_INIT;
*written = 0;
@@ -587,7 +587,7 @@
}
status_t StreamOutHalHidl::getRenderPosition(uint32_t *dspFrames) {
- // TIME_CHECK(); // TODO(b/238654698) reenable only when optimized.
+ // TIME_CHECK(); // TODO(b/243839867) reenable only when optimized.
if (mStream == 0) return NO_INIT;
Result retval;
Return<void> ret = mStream->getRenderPosition(
@@ -668,7 +668,7 @@
}
status_t StreamOutHalHidl::getPresentationPosition(uint64_t *frames, struct timespec *timestamp) {
- // TIME_CHECK(); // TODO(b/238654698) reenable only when optimized.
+ // TIME_CHECK(); // TODO(b/243839867) reenable only when optimized.
if (mStream == 0) return NO_INIT;
if (mWriterClient == gettid() && mCommandMQ) {
return callWriterThread(
@@ -1012,7 +1012,7 @@
}
status_t StreamInHalHidl::read(void *buffer, size_t bytes, size_t *read) {
- // TIME_CHECK(); // TODO(b/238654698) reenable only when optimized.
+ // TIME_CHECK(); // TODO(b/243839867) reenable only when optimized.
if (mStream == 0) return NO_INIT;
*read = 0;
@@ -1146,7 +1146,7 @@
}
status_t StreamInHalHidl::getCapturePosition(int64_t *frames, int64_t *time) {
- // TIME_CHECK(); // TODO(b/238654698) reenable only when optimized.
+ // TIME_CHECK(); // TODO(b/243839867) reenable only when optimized.
if (mStream == 0) return NO_INIT;
if (mReaderClient == gettid() && mCommandMQ) {
ReadParameters params;
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.cpp
index 91c3dea..9ec593f 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.cpp
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.cpp
@@ -82,7 +82,7 @@
Parameter aidlParam;
switch (type) {
case BASSBOOST_PARAM_STRENGTH: {
- uint32_t value;
+ uint16_t value;
Parameter::Id id =
MAKE_SPECIFIC_PARAMETER_ID(BassBoost, bassBoostTag, BassBoost::strengthPm);
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
@@ -92,7 +92,7 @@
}
case BASSBOOST_PARAM_STRENGTH_SUPPORTED: {
// an invalid range indicates not setting support for this parameter
- uint16_t value =
+ uint32_t value =
::aidl::android::hardware::audio::effect::isRangeValid<Range::Tag::bassBoost>(
BassBoost::strengthPm, mDesc.capability);
return param.writeToValue(&value);
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.cpp
index 960273b..0544e3f 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.cpp
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.cpp
@@ -43,157 +43,208 @@
using utils::EffectParamReader;
using utils::EffectParamWriter;
-#define MAKE_AIDL_PARAMETER(aidlParam, param, value, tag) \
- { \
- if (OK != param.readFromValue(&value)) { \
- ALOGE("%s invalid parameter %s %d", __func__, #tag, value); \
- return BAD_VALUE; \
- } \
- aidlParam = MAKE_SPECIFIC_PARAMETER( \
- EnvironmentalReverb, environmentalReverb, tag, \
- VALUE_OR_RETURN_STATUS(aidl::android::convertIntegral<int>(value))); \
+/**
+ * Macro to get a parameter from effect_param_t wrapper and set it to AIDL effect.
+ *
+ * Return if there is any error, otherwise continue execution.
+ *
+ * @param param EffectParamReader, a reader wrapper of effect_param_t.
+ * @param aidlType Type of the AIDL parameter field, used to construct AIDL Parameter union.
+ * @param valueType Type of the value get from effect_param_t.
+ * @param tag The AIDL parameter union field tag.
+ */
+#define SET_AIDL_PARAMETER(param, aidlType, valueType, tag) \
+ { \
+ Parameter aidlParam; \
+ valueType value; \
+ if (status_t status = param.readFromValue(&value); status != OK) { \
+ ALOGE("%s %s read from parameter failed, ret %d", __func__, #tag, status); \
+ return status; \
+ } \
+ aidlParam = MAKE_SPECIFIC_PARAMETER( \
+ EnvironmentalReverb, environmentalReverb, tag, \
+ VALUE_OR_RETURN_STATUS(aidl::android::convertIntegral<aidlType>(value))); \
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->setParameter(aidlParam))); \
}
-#define GET_AIDL_PARAMETER(tag, value, param) \
+/**
+ * Macro to get a parameter from AIDL effect and write the value to effect_param_t with wrapper.
+ *
+ * Return if there is any error, otherwise continue execution.
+ *
+ * @param param EffectParamWriter, a writer wrapper of effect_param_t.
+ * @param aidlType Type of the AIDL parameter field, used to construct AIDL Parameter union.
+ * @param valueType Type of the value get from effect_param_t.
+ * @param tag The AIDL parameter union field tag.
+ */
+#define GET_AIDL_PARAMETER(param, aidltype, valueType, tag) \
{ \
+ aidltype value; \
Parameter aidlParam; \
Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(EnvironmentalReverb, environmentalReverbTag, \
EnvironmentalReverb::tag); \
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam))); \
- value = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD( \
- aidlParam, EnvironmentalReverb, environmentalReverb, EnvironmentalReverb::tag, \
- std::decay_t<decltype(value)>)); \
- return param.writeToValue(&value); \
+ value = VALUE_OR_RETURN_STATUS( \
+ GET_PARAMETER_SPECIFIC_FIELD(aidlParam, EnvironmentalReverb, environmentalReverb, \
+ EnvironmentalReverb::tag, std::decay_t<aidltype>)); \
+ if (status_t status = param.writeToValue((valueType*)&value); status != OK) { \
+ param.setStatus(status); \
+ ALOGE("%s %s write to parameter failed %d, ret %d", __func__, #tag, value, status); \
+ return status; \
+ } \
}
status_t AidlConversionEnvReverb::setParameter(EffectParamReader& param) {
uint32_t type = 0;
- if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint16_t)) ||
- OK != param.readFromParameter(&type)) {
- ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ if (status_t status = param.readFromParameter(&type); status != OK) {
+ ALOGE("%s failed to read type from %s, ret %d", __func__, param.toString().c_str(), status);
return BAD_VALUE;
}
- Parameter aidlParam;
- uint16_t value16;
- uint32_t value32;
+
switch (type) {
case REVERB_PARAM_ROOM_LEVEL: {
- MAKE_AIDL_PARAMETER(aidlParam, param, value16, roomLevelMb);
+ SET_AIDL_PARAMETER(param, int32_t, int16_t, roomLevelMb);
break;
}
case REVERB_PARAM_ROOM_HF_LEVEL: {
- MAKE_AIDL_PARAMETER(aidlParam, param, value16, roomHfLevelMb);
+ SET_AIDL_PARAMETER(param, int32_t, int16_t, roomHfLevelMb);
break;
}
case REVERB_PARAM_DECAY_TIME: {
- MAKE_AIDL_PARAMETER(aidlParam, param, value32, decayTimeMs);
+ SET_AIDL_PARAMETER(param, int32_t, uint32_t, decayTimeMs);
break;
}
case REVERB_PARAM_DECAY_HF_RATIO: {
- MAKE_AIDL_PARAMETER(aidlParam, param, value16, decayHfRatioPm);
- break;
- }
- case REVERB_PARAM_REVERB_LEVEL: {
- MAKE_AIDL_PARAMETER(aidlParam, param, value16, levelMb);
- break;
- }
- case REVERB_PARAM_REVERB_DELAY: {
- MAKE_AIDL_PARAMETER(aidlParam, param, value32, delayMs);
- break;
- }
- case REVERB_PARAM_DIFFUSION: {
- MAKE_AIDL_PARAMETER(aidlParam, param, value16, diffusionPm);
- break;
- }
- case REVERB_PARAM_DENSITY: {
- MAKE_AIDL_PARAMETER(aidlParam, param, value16, densityPm);
- break;
- }
- case REVERB_PARAM_BYPASS: {
- if (OK != param.readFromValue(&value32)) {
- ALOGE("%s invalid bypass parameter %d", __func__, value32);
- return BAD_VALUE;
- }
- bool isByPass = VALUE_OR_RETURN_STATUS(aidl::android::convertIntegral<bool>(value32));
- aidlParam = MAKE_SPECIFIC_PARAMETER(EnvironmentalReverb, environmentalReverb, bypass,
- isByPass);
+ SET_AIDL_PARAMETER(param, int32_t, int16_t, decayHfRatioPm);
break;
}
case REVERB_PARAM_REFLECTIONS_LEVEL: {
- // TODO
+ SET_AIDL_PARAMETER(param, int32_t, int16_t, reflectionsLevelMb);
break;
}
case REVERB_PARAM_REFLECTIONS_DELAY: {
- // TODO
+ SET_AIDL_PARAMETER(param, int32_t, uint32_t, reflectionsDelayMs);
+ break;
+ }
+ case REVERB_PARAM_REVERB_LEVEL: {
+ SET_AIDL_PARAMETER(param, int32_t, int16_t, levelMb);
+ break;
+ }
+ case REVERB_PARAM_REVERB_DELAY: {
+ SET_AIDL_PARAMETER(param, int32_t, uint32_t, delayMs);
+ break;
+ }
+ case REVERB_PARAM_DIFFUSION: {
+ SET_AIDL_PARAMETER(param, int32_t, int16_t, diffusionPm);
+ break;
+ }
+ case REVERB_PARAM_DENSITY: {
+ SET_AIDL_PARAMETER(param, int32_t, int16_t, densityPm);
+ break;
+ }
+ case REVERB_PARAM_BYPASS: {
+ SET_AIDL_PARAMETER(param, bool, int32_t, bypass);
break;
}
case REVERB_PARAM_PROPERTIES: {
- // TODO
+ if (sizeof(t_reverb_settings) > param.getValueSize()) {
+ ALOGE("%s vsize %zu less than t_reverb_settings size %zu", __func__,
+ param.getValueSize(), sizeof(t_reverb_settings));
+ return BAD_VALUE;
+ }
+ // this sequency needs to be aligned with t_reverb_settings
+ SET_AIDL_PARAMETER(param, int32_t, int16_t, roomLevelMb);
+ SET_AIDL_PARAMETER(param, int32_t, int16_t, roomHfLevelMb);
+ SET_AIDL_PARAMETER(param, int32_t, uint32_t, decayTimeMs);
+ SET_AIDL_PARAMETER(param, int32_t, int16_t, decayHfRatioPm);
+ SET_AIDL_PARAMETER(param, int32_t, int16_t, reflectionsLevelMb);
+ SET_AIDL_PARAMETER(param, int32_t, uint32_t, reflectionsDelayMs);
+ SET_AIDL_PARAMETER(param, int32_t, int16_t, levelMb);
+ SET_AIDL_PARAMETER(param, int32_t, uint32_t, delayMs);
+ SET_AIDL_PARAMETER(param, int32_t, int16_t, diffusionPm);
+ SET_AIDL_PARAMETER(param, int32_t, int16_t, densityPm);
break;
}
default: {
// TODO: handle with vendor extension
}
}
- return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+ return OK;
}
status_t AidlConversionEnvReverb::getParameter(EffectParamWriter& param) {
uint32_t type = 0;
- if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint32_t)) ||
- OK != param.readFromParameter(&type)) {
- ALOGE("%s invalid param %s", __func__, param.toString().c_str());
- param.setStatus(BAD_VALUE);
- return BAD_VALUE;
+ if (status_t status = param.readFromParameter(&type); status != OK) {
+ ALOGE("%s failed to read type from %s", __func__, param.toString().c_str());
+ param.setStatus(status);
+ return status;
}
- uint16_t value16;
- uint32_t value32;
+
switch (type) {
case REVERB_PARAM_ROOM_LEVEL: {
- GET_AIDL_PARAMETER(roomLevelMb, value16, param);
+ GET_AIDL_PARAMETER(param, int32_t, int16_t, roomLevelMb);
+ break;
}
case REVERB_PARAM_ROOM_HF_LEVEL: {
- GET_AIDL_PARAMETER(roomHfLevelMb, value16, param);
+ GET_AIDL_PARAMETER(param, int32_t, int16_t, roomHfLevelMb);
+ break;
}
case REVERB_PARAM_DECAY_TIME: {
- GET_AIDL_PARAMETER(decayTimeMs, value32, param);
+ GET_AIDL_PARAMETER(param, int32_t, uint32_t, decayTimeMs);
+ break;
}
case REVERB_PARAM_DECAY_HF_RATIO: {
- GET_AIDL_PARAMETER(decayHfRatioPm, value16, param);
- }
- case REVERB_PARAM_REVERB_LEVEL: {
- GET_AIDL_PARAMETER(levelMb, value16, param);
- }
- case REVERB_PARAM_REVERB_DELAY: {
- GET_AIDL_PARAMETER(delayMs, value32, param);
- }
- case REVERB_PARAM_DIFFUSION: {
- GET_AIDL_PARAMETER(diffusionPm, value16, param);
- }
- case REVERB_PARAM_DENSITY: {
- GET_AIDL_PARAMETER(densityPm, value16, param);
- }
- case REVERB_PARAM_BYPASS: {
- bool isByPass;
- GET_AIDL_PARAMETER(bypass, isByPass, param);
+ GET_AIDL_PARAMETER(param, int32_t, int16_t, decayHfRatioPm);
+ break;
}
case REVERB_PARAM_REFLECTIONS_LEVEL: {
- // TODO
+ GET_AIDL_PARAMETER(param, int32_t, int16_t, reflectionsLevelMb);
break;
}
case REVERB_PARAM_REFLECTIONS_DELAY: {
- // TODO
+ GET_AIDL_PARAMETER(param, int32_t, uint32_t, reflectionsDelayMs);
+ break;
+ }
+ case REVERB_PARAM_REVERB_LEVEL: {
+ GET_AIDL_PARAMETER(param, int32_t, int16_t, levelMb);
+ break;
+ }
+ case REVERB_PARAM_REVERB_DELAY: {
+ GET_AIDL_PARAMETER(param, int32_t, uint32_t, delayMs);
+ break;
+ }
+ case REVERB_PARAM_DIFFUSION: {
+ GET_AIDL_PARAMETER(param, int32_t, int16_t, diffusionPm);
+ break;
+ }
+ case REVERB_PARAM_DENSITY: {
+ GET_AIDL_PARAMETER(param, int32_t, int16_t, densityPm);
+ break;
+ }
+ case REVERB_PARAM_BYPASS: {
+ GET_AIDL_PARAMETER(param, bool, int32_t, bypass);
break;
}
case REVERB_PARAM_PROPERTIES: {
- // TODO
+ // this sequency needs to be aligned with t_reverb_settings
+ GET_AIDL_PARAMETER(param, int32_t, int16_t, roomLevelMb);
+ GET_AIDL_PARAMETER(param, int32_t, int16_t, roomHfLevelMb);
+ GET_AIDL_PARAMETER(param, int32_t, uint32_t, decayTimeMs);
+ GET_AIDL_PARAMETER(param, int32_t, int16_t, decayHfRatioPm);
+ GET_AIDL_PARAMETER(param, int32_t, int16_t, reflectionsLevelMb);
+ GET_AIDL_PARAMETER(param, int32_t, uint32_t, reflectionsDelayMs);
+ GET_AIDL_PARAMETER(param, int32_t, int16_t, levelMb);
+ GET_AIDL_PARAMETER(param, int32_t, uint32_t, delayMs);
+ GET_AIDL_PARAMETER(param, int32_t, int16_t, diffusionPm);
+ GET_AIDL_PARAMETER(param, int32_t, int16_t, densityPm);
break;
}
default: {
// TODO: handle with vendor extension
+ return BAD_VALUE;
}
}
- return BAD_VALUE;
+ return OK;
}
} // namespace effect
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp
index a10d271..916ed40 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp
@@ -37,16 +37,15 @@
using ::aidl::android::aidl_utils::statusTFromBinderStatus;
using ::aidl::android::hardware::audio::effect::Equalizer;
using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::Range;
+using ::android::base::unexpected;
using ::android::status_t;
using utils::EffectParamReader;
using utils::EffectParamWriter;
status_t AidlConversionEq::setParameter(EffectParamReader& param) {
uint32_t type;
- uint16_t value = 0;
- if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint32_t)) ||
- OK != param.readFromParameter(&type) ||
- OK != param.readFromValue(&value)) {
+ if (OK != param.readFromParameter(&type)) {
ALOGE("%s invalid param %s", __func__, param.toString().c_str());
return BAD_VALUE;
}
@@ -54,23 +53,52 @@
Parameter aidlParam;
switch (type) {
case EQ_PARAM_CUR_PRESET: {
+ uint16_t value = 0;
+ if (OK != param.readFromValue(&value)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
aidlParam = MAKE_SPECIFIC_PARAMETER(Equalizer, equalizer, preset, (int)value);
- break;
+ return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
}
case EQ_PARAM_BAND_LEVEL: {
int32_t band;
- uint16_t level;
- if (OK != param.readFromParameter(&band) || OK != param.readFromParameter(&level)) {
+ int16_t level;
+ if (OK != param.readFromParameter(&band) || OK != param.readFromValue(&level)) {
ALOGE("%s invalid bandLevel param %s", __func__, param.toString().c_str());
return BAD_VALUE;
}
std::vector<Equalizer::BandLevel> bandLevels = {{.index = band, .levelMb = level}};
aidlParam = MAKE_SPECIFIC_PARAMETER(Equalizer, equalizer, bandLevels, bandLevels);
- break;
+ return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
}
case EQ_PARAM_PROPERTIES: {
- // TODO: handle properties setting
- break;
+ int16_t num;
+ if (OK != param.readFromValue(&num)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ // set preset if it's valid
+ if (num >= 0) {
+ aidlParam = MAKE_SPECIFIC_PARAMETER(Equalizer, equalizer, preset, (int)num);
+ return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+ }
+ // set bandLevel if no preset was set
+ if (OK != param.readFromValue(&num)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ std::vector<Equalizer::BandLevel> bandLevels;
+ for (int i = 0; i < num; i++) {
+ Equalizer::BandLevel level({.index = i});
+ if (OK != param.readFromValue((uint16_t*)&level.levelMb)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ bandLevels.push_back(level);
+ }
+ aidlParam = MAKE_SPECIFIC_PARAMETER(Equalizer, equalizer, bandLevels, bandLevels);
+ return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
}
default: {
// TODO: implement vendor extension parameters
@@ -78,8 +106,6 @@
return BAD_VALUE;
}
}
-
- return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
}
aidl::ConversionResult<Parameter> AidlConversionEq::getAidlParameter(Equalizer::Tag tag) {
@@ -89,29 +115,188 @@
return aidlParam;
}
+aidl::ConversionResult<int32_t> AidlConversionEq::getParameterPreset() {
+ Parameter aidlParam = VALUE_OR_RETURN_STATUS(getAidlParameter(Equalizer::preset));
+ return VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(aidlParam, Equalizer, equalizer,
+ Equalizer::preset, int32_t));
+}
+
+aidl::ConversionResult<std::string> AidlConversionEq::getParameterPresetName(
+ EffectParamWriter& param) {
+ int32_t presetIdx;
+ if (OK != param.readFromParameter(&presetIdx)) {
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return unexpected(BAD_VALUE);
+ }
+ Parameter aidlParam = VALUE_OR_RETURN(getAidlParameter(Equalizer::presets));
+ const auto& presets = VALUE_OR_RETURN(GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, Equalizer, equalizer, Equalizer::presets, std::vector<Equalizer::Preset>));
+ for (const auto& preset : presets) {
+ if (presetIdx == preset.index) {
+ return preset.name;
+ }
+ }
+ return unexpected(BAD_VALUE);
+}
+
status_t AidlConversionEq::getParameter(EffectParamWriter& param) {
- uint32_t type = 0, value = 0;
- if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint32_t)) ||
- OK != param.readFromParameter(&type)) {
+ uint32_t type = 0;
+ if (OK != param.readFromParameter(&type)) {
param.setStatus(BAD_VALUE);
ALOGE("%s invalid param %s", __func__, param.toString().c_str());
return BAD_VALUE;
}
- Parameter aidlParam;
+
switch (type) {
case EQ_PARAM_NUM_BANDS: {
- aidlParam = VALUE_OR_RETURN_STATUS(getAidlParameter(Equalizer::bandLevels));
- auto bandLevels = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+ Parameter aidlParam = VALUE_OR_RETURN_STATUS(getAidlParameter(Equalizer::bandLevels));
+ const auto& bandLevels = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
aidlParam, Equalizer, equalizer, Equalizer::bandLevels,
std::vector<Equalizer::BandLevel>));
- uint32_t num = bandLevels.size();
+ uint16_t bands = bandLevels.size();
+ return param.writeToValue(&bands);
+ }
+ case EQ_PARAM_LEVEL_RANGE: {
+ const auto& ranges = mDesc.capability.range.get<Range::equalizer>();
+ for (const auto& r : ranges) {
+ if (r.min.getTag() == Equalizer::bandLevels &&
+ r.max.getTag() == Equalizer::bandLevels) {
+ const auto& aidlMin = r.min.get<Equalizer::bandLevels>();
+ const auto& aidlMax = r.max.get<Equalizer::bandLevels>();
+ int16_t min =
+ std::min_element(aidlMin.begin(), aidlMin.end(), [](auto& a, auto& b) {
+ return a.levelMb < b.levelMb;
+ })->levelMb;
+ int16_t max =
+ std::max_element(aidlMax.begin(), aidlMax.end(), [](auto& a, auto& b) {
+ return a.levelMb < b.levelMb;
+ })->levelMb;
+ return (OK == param.writeToValue(&min) && OK == param.writeToValue(&max))
+ ? OK
+ : BAD_VALUE;
+ }
+ }
+ break;
+ }
+ case EQ_PARAM_BAND_LEVEL: {
+ int32_t bandIdx;
+ if (OK != param.readFromParameter(&bandIdx)) {
+ break;
+ }
+
+ Parameter aidlParam = VALUE_OR_RETURN_STATUS(getAidlParameter(Equalizer::bandLevels));
+ const auto& bandLevels = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, Equalizer, equalizer, Equalizer::bandLevels,
+ std::vector<Equalizer::BandLevel>));
+ for (const auto& band : bandLevels) {
+ if (band.index == bandIdx) {
+ return param.writeToValue((uint16_t *)&band.levelMb);
+ }
+ }
+ break;
+ }
+ case EQ_PARAM_CENTER_FREQ: {
+ int32_t index;
+ if (OK != param.readFromParameter(&index)) {
+ break;
+ }
+
+ Parameter aidlParam = VALUE_OR_RETURN_STATUS(getAidlParameter(Equalizer::centerFreqMh));
+ const auto& freqs = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, Equalizer, equalizer, Equalizer::centerFreqMh, std::vector<int>));
+ if ((size_t)index >= freqs.size()) {
+ ALOGE("%s index %d exceed size %zu", __func__, index, freqs.size());
+ break;
+ }
+ return param.writeToValue(&freqs[index]);
+ }
+ case EQ_PARAM_BAND_FREQ_RANGE: {
+ int32_t index;
+ if (OK != param.readFromParameter(&index)) {
+ break;
+ }
+
+ Parameter aidlParam =
+ VALUE_OR_RETURN_STATUS(getAidlParameter(Equalizer::bandFrequencies));
+ const auto& bands = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, Equalizer, equalizer, Equalizer::bandFrequencies,
+ std::vector<Equalizer::BandFrequency>));
+ for (const auto& band : bands) {
+ if (band.index == index) {
+ return (OK == param.writeToValue(&band.minMh) &&
+ OK == param.writeToValue(&band.maxMh))
+ ? OK
+ : BAD_VALUE;
+ }
+ }
+ break;
+ }
+ case EQ_PARAM_GET_BAND: {
+ int32_t freq;
+ if (OK != param.readFromParameter(&freq)) {
+ break;
+ }
+
+ Parameter aidlParam =
+ VALUE_OR_RETURN_STATUS(getAidlParameter(Equalizer::bandFrequencies));
+ const auto& bands = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, Equalizer, equalizer, Equalizer::bandFrequencies,
+ std::vector<Equalizer::BandFrequency>));
+ for (const auto& band : bands) {
+ if (freq >= band.minMh && freq <= band.maxMh) {
+ return param.writeToValue((uint16_t*)&band.index);
+ }
+ }
+ break;
+ }
+ case EQ_PARAM_CUR_PRESET: {
+ int32_t preset = VALUE_OR_RETURN_STATUS(getParameterPreset());
+ return param.writeToValue((uint16_t*)&preset);
+ }
+ case EQ_PARAM_GET_NUM_OF_PRESETS: {
+ Parameter aidlParam = VALUE_OR_RETURN_STATUS(getAidlParameter(Equalizer::presets));
+ const auto& presets = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, Equalizer, equalizer, Equalizer::presets,
+ std::vector<Equalizer::Preset>));
+ uint16_t num = presets.size();
return param.writeToValue(&num);
}
- default:
+ case EQ_PARAM_GET_PRESET_NAME: {
+ std::string name = VALUE_OR_RETURN_STATUS(getParameterPresetName(param));
+ return param.writeToValue(name.c_str(), name.length());
+ }
+ case EQ_PARAM_PROPERTIES: {
+ int32_t preset = VALUE_OR_RETURN_STATUS(getParameterPreset());
+ if (OK != param.writeToValue((uint16_t*)&preset)) {
+ break;
+ }
+ Parameter aidlParam = VALUE_OR_RETURN_STATUS(getAidlParameter(Equalizer::bandLevels));
+ std::vector<Equalizer::BandLevel> bandLevels =
+ VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, Equalizer, equalizer, Equalizer::bandLevels,
+ std::vector<Equalizer::BandLevel>));
+ uint16_t bands = bandLevels.size();
+ if (OK != param.writeToValue(&bands)) {
+ break;
+ }
+ std::sort(bandLevels.begin(), bandLevels.end(),
+ [](const auto& a, const auto& b) { return a.index < b.index; });
+ for (const auto& level : bandLevels) {
+ if (status_t status = param.writeToValue((uint16_t*)&level.levelMb); status != OK) {
+ return status;
+ }
+ }
+ return OK;
+ }
+ default: {
ALOGW("%s unknown param %s", __func__, param.toString().c_str());
return BAD_VALUE;
+ }
}
- return param.writeToValue(&value);
+
+ param.setStatus(BAD_VALUE);
+ ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
}
} // namespace effect
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.h
index 0433965..2509c20 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.h
@@ -35,6 +35,8 @@
status_t getParameter(utils::EffectParamWriter& param) override;
aidl::ConversionResult<::aidl::android::hardware::audio::effect::Parameter> getAidlParameter(
::aidl::android::hardware::audio::effect::Equalizer::Tag tag);
+ aidl::ConversionResult<int32_t> getParameterPreset();
+ aidl::ConversionResult<std::string> getParameterPresetName(utils::EffectParamWriter& param);
};
} // namespace effect
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.cpp
index 1dac479..d2a94e4 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.cpp
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.cpp
@@ -40,28 +40,24 @@
using utils::EffectParamWriter;
status_t AidlConversionSpatializer::setParameter(EffectParamReader& param) {
- uint32_t type = 0;
- uint16_t value = 0;
- if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint16_t)) ||
- OK != param.readFromParameter(&type) || OK != param.readFromValue(&value)) {
- ALOGE("%s invalid param %s", __func__, param.toString().c_str());
- return BAD_VALUE;
- }
- Parameter aidlParam;
- // TODO
+ Parameter aidlParam = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_EffectParameterReader_ParameterExtension(param));
return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
}
status_t AidlConversionSpatializer::getParameter(EffectParamWriter& param) {
- uint32_t type = 0, value = 0;
- if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint32_t)) ||
- OK != param.readFromParameter(&type)) {
- ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+ Parameter aidlParam;
+ Parameter::Id id = UNION_MAKE(Parameter::Id, vendorEffectTag, 0 /* no tag */);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ const auto& extBytes = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::aidl2legacy_ParameterExtension_vector_uint8(aidlParam));
+ if (param.getValueSize() < extBytes.size()) {
+ ALOGE("%s extension return data %zu exceed vsize %zu", __func__, extBytes.size(),
+ param.getValueSize());
param.setStatus(BAD_VALUE);
return BAD_VALUE;
}
- // TODO
- return param.writeToValue(&value);
+ return param.writeToValue(extBytes.data(), extBytes.size());
}
} // namespace effect
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.cpp
index 3baf72e..584b60e 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.cpp
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.cpp
@@ -50,17 +50,8 @@
* pass down in Parameter as is.
*/
status_t AidlConversionVendorExtension::setParameter(EffectParamReader& param) {
- size_t len = param.getValueSize();
- DefaultExtension ext;
- ext.bytes.resize(len);
- if (OK != param.readFromValue(ext.bytes.data(), len)) {
- ALOGE("%s read value from param %s failed", __func__, param.toString().c_str());
- return BAD_VALUE;
- }
- VendorExtension effectParam;
- effectParam.extension.setParcelable(ext);
- Parameter aidlParam = UNION_MAKE(Parameter, specific,
- UNION_MAKE(Parameter::Specific, vendorEffect, effectParam));
+ Parameter aidlParam = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_EffectParameterReader_ParameterExtension(param));
return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
}
@@ -75,23 +66,11 @@
Parameter aidlParam;
Parameter::Id id = UNION_MAKE(Parameter::Id, vendorEffectTag, tag /* parameter tag */);
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
- VendorExtension effectParam = VALUE_OR_RETURN_STATUS(
- (::aidl::android::getParameterSpecific<Parameter, VendorExtension,
- Parameter::Specific::vendorEffect>(aidlParam)));
- std::optional<DefaultExtension> ext;
- if (STATUS_OK != effectParam.extension.getParcelable(&ext) || !ext.has_value()) {
- ALOGE("%s get extension parcelable failed", __func__);
- param.setStatus(BAD_VALUE);
- return BAD_VALUE;
- }
- const auto& extBytes = ext.value().bytes;
- if (param.getValueSize() < extBytes.size()) {
- ALOGE("%s extension return data %zu exceed vsize %zu", __func__, extBytes.size(),
- param.getValueSize());
- param.setStatus(BAD_VALUE);
- return BAD_VALUE;
- }
- return param.writeToValue(extBytes.data(), extBytes.size());
+
+ // copy the AIDL extension data back to effect_param_t
+ return VALUE_OR_RETURN_STATUS(
+ ::aidl::android::aidl2legacy_ParameterExtension_EffectParameterWriter(aidlParam,
+ param));
}
} // namespace effect
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVirtualizer.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVirtualizer.cpp
index 482114d..fe74c8b 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVirtualizer.cpp
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVirtualizer.cpp
@@ -21,10 +21,12 @@
//#define LOG_NDEBUG 0
#include <error/expected_utils.h>
+#include <media/AidlConversionCppNdk.h>
#include <media/AidlConversionNdk.h>
#include <media/AidlConversionEffect.h>
#include <media/audiohal/AudioEffectUuid.h>
-#include <system/audio_effects/effect_spatializer.h>
+#include <system/audio_effects/aidl_effects_utils.h>
+#include <system/audio_effects/effect_virtualizer.h>
#include <utils/Log.h>
@@ -34,34 +36,128 @@
namespace effect {
using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::getParameterSpecificField;
using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::Range;
+using ::aidl::android::hardware::audio::effect::Virtualizer;
+using ::aidl::android::media::audio::common::AudioDeviceDescription;
using ::android::status_t;
using utils::EffectParamReader;
using utils::EffectParamWriter;
status_t AidlConversionVirtualizer::setParameter(EffectParamReader& param) {
uint32_t type = 0;
- uint16_t value = 0;
- if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint16_t)) ||
- OK != param.readFromParameter(&type) || OK != param.readFromValue(&value)) {
+ if (OK != param.readFromParameter(&type)) {
ALOGE("%s invalid param %s", __func__, param.toString().c_str());
return BAD_VALUE;
}
Parameter aidlParam;
- // TODO
+ switch (type) {
+ case VIRTUALIZER_PARAM_STRENGTH: {
+ int16_t strength = 0;
+ if (OK != param.readFromValue(&strength)) {
+ ALOGE("%s invalid param %s for type %d", __func__, param.toString().c_str(), type);
+ return BAD_VALUE;
+ }
+ aidlParam = MAKE_SPECIFIC_PARAMETER(Virtualizer, virtualizer, strengthPm, strength);
+ break;
+ }
+ case VIRTUALIZER_PARAM_FORCE_VIRTUALIZATION_MODE: {
+ audio_devices_t deviceType;
+ if (OK != param.readFromValue(&deviceType)) {
+ ALOGE("%s invalid param %s for type %d", __func__, param.toString().c_str(), type);
+ return BAD_VALUE;
+ }
+ AudioDeviceDescription deviceDesc = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_devices_t_AudioDeviceDescription(
+ deviceType));
+ aidlParam = MAKE_SPECIFIC_PARAMETER(Virtualizer, virtualizer, device, deviceDesc);
+ break;
+ }
+ default: {
+ // TODO: implement vendor extension parameters
+ ALOGW("%s unknown param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ }
return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
}
status_t AidlConversionVirtualizer::getParameter(EffectParamWriter& param) {
- uint32_t type = 0, value = 0;
- if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint32_t)) ||
- OK != param.readFromParameter(&type)) {
+ uint32_t type = 0;
+ if (OK != param.readFromParameter(&type)) {
ALOGE("%s invalid param %s", __func__, param.toString().c_str());
param.setStatus(BAD_VALUE);
return BAD_VALUE;
}
- // TODO
- return param.writeToValue(&value);
+ Parameter aidlParam;
+ switch (type) {
+ case VIRTUALIZER_PARAM_STRENGTH_SUPPORTED: {
+ // an invalid range indicates not setting support for this parameter
+ uint32_t support =
+ ::aidl::android::hardware::audio::effect::isRangeValid<Range::Tag::virtualizer>(
+ Virtualizer::strengthPm, mDesc.capability);
+ return param.writeToValue(&support);
+ }
+ case VIRTUALIZER_PARAM_STRENGTH: {
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(Virtualizer, virtualizerTag,
+ Virtualizer::strengthPm);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ int16_t strength = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, Virtualizer, virtualizer, Virtualizer::strengthPm, int32_t));
+ return param.writeToValue(&strength);
+ }
+ case VIRTUALIZER_PARAM_VIRTUAL_SPEAKER_ANGLES: {
+ audio_channel_mask_t mask;
+ audio_devices_t device;
+ if (OK != param.readFromParameter(&mask) || OK != param.readFromParameter(&device)) {
+ ALOGW("%s illegal param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ Virtualizer::SpeakerAnglesPayload payload = {
+ .layout = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
+ mask, false)),
+ .device = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_devices_t_AudioDeviceDescription(
+ device))};
+ Virtualizer::Id vId = UNION_MAKE(Virtualizer::Id, speakerAnglesPayload, payload);
+ Parameter::Id id = UNION_MAKE(Parameter::Id, virtualizerTag, vId);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ const auto& angles = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, Virtualizer, virtualizer, Virtualizer::speakerAngles,
+ std::vector<Virtualizer::ChannelAngle>));
+ for (const auto& angle : angles) {
+ const audio_channel_mask_t chMask = ::aidl::android::
+ aidl2legacy_AudioChannelLayout_layout_audio_channel_mask_t_bits(
+ angle.channel, false);
+ ALOGW("%s aidl %d ch %d", __func__, angle.channel, chMask);
+ if (OK != param.writeToValue(&chMask) ||
+ OK != param.writeToValue(&angle.azimuthDegree) ||
+ OK != param.writeToValue(&angle.elevationDegree)) {
+ ALOGW("%s can't write angles to param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ }
+ return OK;
+ }
+ case VIRTUALIZER_PARAM_VIRTUALIZATION_MODE: {
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(Virtualizer, virtualizerTag,
+ Virtualizer::device);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ AudioDeviceDescription device = VALUE_OR_RETURN_STATUS(
+ GET_PARAMETER_SPECIFIC_FIELD(aidlParam, Virtualizer, virtualizer,
+ Virtualizer::device, AudioDeviceDescription));
+ const audio_devices_t deviceType = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::aidl2legacy_AudioDeviceDescription_audio_devices_t(device));
+ return param.writeToValue(&deviceType);
+ }
+ default: {
+ // TODO: implement vendor extension parameters
+ ALOGW("%s unknown param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ }
}
} // namespace effect
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.cpp
index 9ed601f..7e1e6d7 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.cpp
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <cstddef>
#include <cstdint>
#include <cstring>
#include <optional>
@@ -34,34 +35,142 @@
namespace effect {
using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::getParameterSpecificField;
using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::Visualizer;
using ::android::status_t;
using utils::EffectParamReader;
using utils::EffectParamWriter;
status_t AidlConversionVisualizer::setParameter(EffectParamReader& param) {
- uint32_t type = 0;
- uint16_t value = 0;
- if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint16_t)) ||
+ uint32_t type = 0, value = 0;
+ if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint32_t)) ||
OK != param.readFromParameter(&type) || OK != param.readFromValue(&value)) {
ALOGE("%s invalid param %s", __func__, param.toString().c_str());
return BAD_VALUE;
}
Parameter aidlParam;
- // TODO
+ switch (type) {
+ case VISUALIZER_PARAM_CAPTURE_SIZE: {
+ aidlParam = MAKE_SPECIFIC_PARAMETER(Visualizer, visualizer, captureSamples, value);
+ break;
+ }
+ case VISUALIZER_PARAM_SCALING_MODE: {
+ Visualizer::ScalingMode mode = VALUE_OR_RETURN_STATUS(
+ aidl::android::legacy2aidl_Parameter_Visualizer_uint32_ScalingMode(value));
+ aidlParam = MAKE_SPECIFIC_PARAMETER(Visualizer, visualizer, scalingMode, mode);
+ break;
+ }
+ case VISUALIZER_PARAM_LATENCY: {
+ aidlParam = MAKE_SPECIFIC_PARAMETER(Visualizer, visualizer, latencyMs, value);
+ break;
+ }
+ case VISUALIZER_PARAM_MEASUREMENT_MODE: {
+ Visualizer::MeasurementMode mode = VALUE_OR_RETURN_STATUS(
+ aidl::android::legacy2aidl_Parameter_Visualizer_uint32_MeasurementMode(value));
+ aidlParam = MAKE_SPECIFIC_PARAMETER(Visualizer, visualizer, measurementMode, mode);
+ break;
+ }
+ default: {
+ // TODO: implement vendor extension parameters
+ ALOGW("%s unknown param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ }
return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
}
status_t AidlConversionVisualizer::getParameter(EffectParamWriter& param) {
uint32_t type = 0, value = 0;
- if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint32_t)) ||
+ if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(int32_t)) ||
OK != param.readFromParameter(&type)) {
ALOGE("%s invalid param %s", __func__, param.toString().c_str());
param.setStatus(BAD_VALUE);
return BAD_VALUE;
}
- // TODO
- return param.writeToValue(&value);
+ Parameter aidlParam;
+ switch (type) {
+ case VISUALIZER_PARAM_CAPTURE_SIZE: {
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(Visualizer, visualizerTag,
+ Visualizer::captureSamples);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ value = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, Visualizer, visualizer, Visualizer::captureSamples, int32_t));
+ mCaptureSize = value;
+ return param.writeToValue(&value);
+ }
+ case VISUALIZER_PARAM_SCALING_MODE: {
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(Visualizer, visualizerTag,
+ Visualizer::scalingMode);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ Visualizer::ScalingMode mode = VALUE_OR_RETURN_STATUS(
+ GET_PARAMETER_SPECIFIC_FIELD(aidlParam, Visualizer, visualizer,
+ Visualizer::scalingMode, Visualizer::ScalingMode));
+ value = VALUE_OR_RETURN_STATUS(
+ aidl::android::aidl2legacy_Parameter_Visualizer_ScalingMode_uint32(mode));
+ return param.writeToValue(&value);
+ }
+ case VISUALIZER_PARAM_LATENCY: {
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(Visualizer, visualizerTag,
+ Visualizer::latencyMs);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ value = (int32_t)VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, Visualizer, visualizer, Visualizer::latencyMs, int32_t));
+ return param.writeToValue(&value);
+ }
+ case VISUALIZER_PARAM_MEASUREMENT_MODE: {
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(Visualizer, visualizerTag,
+ Visualizer::measurementMode);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ Visualizer::MeasurementMode mode = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, Visualizer, visualizer, Visualizer::measurementMode,
+ Visualizer::MeasurementMode));
+ value = VALUE_OR_RETURN_STATUS(
+ aidl::android::aidl2legacy_Parameter_Visualizer_MeasurementMode_uint32(mode));
+ return param.writeToValue(&value);
+ }
+ default: {
+ // TODO: implement vendor extension parameters
+ ALOGW("%s unknown param %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ }
+}
+
+status_t AidlConversionVisualizer::visualizerCapture(uint32_t* replySize, void* pReplyData) {
+ if (!replySize || !pReplyData || *replySize != mCaptureSize) {
+ ALOGE("%s illegal param replySize %p pReplyData %p", __func__, replySize, pReplyData);
+ return BAD_VALUE;
+ }
+
+ Parameter aidlParam;
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(Visualizer, visualizerTag,
+ Visualizer::captureSampleBuffer);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ const auto& samples = VALUE_OR_RETURN_STATUS(
+ GET_PARAMETER_SPECIFIC_FIELD(aidlParam, Visualizer, visualizer,
+ Visualizer::captureSampleBuffer, std::vector<uint8_t>));
+ size_t len = std::min((size_t)*replySize, samples.size());
+ std::memcpy(pReplyData, samples.data(), *replySize = len);
+ return OK;
+}
+
+status_t AidlConversionVisualizer::visualizerMeasure(uint32_t* replySize, void* pReplyData) {
+ if (!replySize || !pReplyData || *replySize != 2 * sizeof(int32_t)) {
+ ALOGE("%s illegal param replySize %p pReplyData %p", __func__, replySize, pReplyData);
+ return BAD_VALUE;
+ }
+
+ Parameter aidlParam;
+ Parameter::Id id =
+ MAKE_SPECIFIC_PARAMETER_ID(Visualizer, visualizerTag, Visualizer::measurement);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ const auto& measure = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, Visualizer, visualizer, Visualizer::measurement, Visualizer::Measurement));
+ int32_t* reply = (int32_t *) pReplyData;
+ *reply++ = measure.rms;
+ *reply = measure.peak;
+ return OK;
}
} // namespace effect
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.h
index a7e4ea1..e380bc6 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.h
@@ -32,8 +32,11 @@
~AidlConversionVisualizer() {}
private:
+ uint32_t mCaptureSize = 0;
status_t setParameter(utils::EffectParamReader& param) override;
status_t getParameter(utils::EffectParamWriter& param) override;
+ status_t visualizerCapture(uint32_t* replySize, void* pReplyData) override;
+ status_t visualizerMeasure(uint32_t* replySize, void* pReplyData) override;
};
} // namespace effect
diff --git a/media/libaudiohal/include/media/audiohal/AudioEffectUuid.h b/media/libaudiohal/include/media/audiohal/AudioEffectUuid.h
index b21e4c9..3b8076f 100644
--- a/media/libaudiohal/include/media/audiohal/AudioEffectUuid.h
+++ b/media/libaudiohal/include/media/audiohal/AudioEffectUuid.h
@@ -42,11 +42,11 @@
0xa0fc,
{0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
// fa81862a-588b-11ed-9b6a-0242ac120002
-static const AudioUuid kDownmixTypeUUID = {static_cast<int32_t>(0xfa81862a),
- 0x588b,
- 0x11ed,
- 0x9b6a,
- {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+static const AudioUuid kDownmixTypeUUID = {static_cast<int32_t>(0x381e49cc),
+ 0xa858,
+ 0x4aa2,
+ 0x87f6,
+ {0xe8, 0x38, 0x8e, 0x76, 0x01, 0xb2}};
// 7261676f-6d75-7369-6364-28e2fd3ac39e
static const AudioUuid kDynamicsProcessingTypeUUID = {static_cast<int32_t>(0x7261676f),
0x6d75,
@@ -101,12 +101,12 @@
0x11db,
0x8577,
{0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
-// fa819f3e-588b-11ed-9b6a-0242ac120002
-static const AudioUuid kVisualizerTypeUUID = {static_cast<int32_t>(0xfa819f3e),
- 0x588b,
- 0x11ed,
- 0x9b6a,
- {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+// e46b26a0-dddd-11db-8afd-0002a5d5c51b
+static const AudioUuid kVisualizerTypeUUID = {static_cast<int32_t>(0xe46b26a0),
+ 0xdddd,
+ 0x11db,
+ 0x8afd,
+ {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
// fa81a2b8-588b-11ed-9b6a-0242ac120002
static const AudioUuid kVolumeTypeUUID = {static_cast<int32_t>(0xfa81a2b8),
0x588b,
diff --git a/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp b/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp
index 71c7586..a8843d6 100644
--- a/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp
+++ b/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp
@@ -165,7 +165,7 @@
sizeof(int32_t) /* returnValueSize */)),
std::make_tuple(EFFECT_UIID_DOWNMIX,
createEffectParamCombination(DOWNMIX_PARAM_TYPE, DOWNMIX_TYPE_FOLD,
- sizeof(int32_t) /* returnValueSize */)),
+ sizeof(int16_t) /* returnValueSize */)),
std::make_tuple(SL_IID_DYNAMICSPROCESSING,
createEffectParamCombination(
std::array<uint32_t, 2>({DP_PARAM_INPUT_GAIN, 0 /* channel */}),
@@ -264,7 +264,8 @@
if (mCombination->valueSize) {
std::vector<uint8_t> response(mCombination->valueSize);
EXPECT_EQ(OK, parameterGet.readFromValue(response.data(), mCombination->valueSize))
- << parameterGet.toString();
+ << " try get valueSize " << mCombination->valueSize << " from "
+ << parameterGet.toString();
EXPECT_EQ(response, mExpectedValue);
}
}
diff --git a/media/libeffects/lvm/tests/Android.bp b/media/libeffects/lvm/tests/Android.bp
index de6d30b..0568fbd 100644
--- a/media/libeffects/lvm/tests/Android.bp
+++ b/media/libeffects/lvm/tests/Android.bp
@@ -14,10 +14,6 @@
defaults: [
"libeffects-test-defaults",
],
- // TODO(b/269868814)
- test_options: {
- unit_test: false,
- },
srcs: [
"EffectReverbTest.cpp",
],
diff --git a/media/libeffects/lvm/tests/EffectReverbTest.cpp b/media/libeffects/lvm/tests/EffectReverbTest.cpp
index 59453eb..aaac782 100644
--- a/media/libeffects/lvm/tests/EffectReverbTest.cpp
+++ b/media/libeffects/lvm/tests/EffectReverbTest.cpp
@@ -33,6 +33,27 @@
constexpr size_t kNumEffectUuids = std::size(kEffectUuids);
+static constexpr audio_channel_mask_t kChMasks[] = {
+ AUDIO_CHANNEL_OUT_MONO, AUDIO_CHANNEL_OUT_STEREO,
+ AUDIO_CHANNEL_OUT_2POINT1, AUDIO_CHANNEL_OUT_5POINT1,
+ AUDIO_CHANNEL_OUT_7POINT1POINT4, AUDIO_CHANNEL_INDEX_MASK_23,
+ AUDIO_CHANNEL_OUT_22POINT2,
+};
+
+static constexpr size_t kNumChMasks = std::size(kChMasks);
+
+static constexpr size_t kSampleRates[] = {8000, 11025, 44100, 48000, 192000};
+
+static constexpr size_t kNumSampleRates = std::size(kSampleRates);
+
+static constexpr size_t kFrameCounts[] = {4, 512};
+
+static constexpr size_t kNumFrameCounts = std::size(kFrameCounts);
+
+static constexpr size_t kLoopCounts[] = {1, 4};
+
+static constexpr size_t kNumLoopCounts = std::size(kLoopCounts);
+
static bool isAuxMode(const effect_uuid_t* uuid) {
// Update this, if the order of effects in kEffectUuids is updated
return (uuid == &kEffectUuids[2] || uuid == &kEffectUuids[3]);
@@ -50,15 +71,15 @@
class SingleEffectTest : public ::testing::TestWithParam<SingleEffectTestParam> {
public:
SingleEffectTest()
- : mSampleRate(EffectTestHelper::kSampleRates[std::get<1>(GetParam())]),
- mFrameCount(EffectTestHelper::kFrameCounts[std::get<2>(GetParam())]),
- mLoopCount(EffectTestHelper::kLoopCounts[std::get<3>(GetParam())]),
+ : mSampleRate(kSampleRates[std::get<1>(GetParam())]),
+ mFrameCount(kFrameCounts[std::get<2>(GetParam())]),
+ mLoopCount(kLoopCounts[std::get<3>(GetParam())]),
mTotalFrameCount(mFrameCount * mLoopCount),
mUuid(&kEffectUuids[std::get<4>(GetParam())]),
mInChMask(isAuxMode(mUuid) ? AUDIO_CHANNEL_OUT_MONO
- : EffectTestHelper::kChMasks[std::get<0>(GetParam())]),
+ : kChMasks[std::get<0>(GetParam())]),
mInChannelCount(audio_channel_count_from_out_mask(mInChMask)),
- mOutChMask(EffectTestHelper::kChMasks[std::get<0>(GetParam())]),
+ mOutChMask(kChMasks[std::get<0>(GetParam())]),
mOutChannelCount(audio_channel_count_from_out_mask(mOutChMask)),
mPreset(kPresets[std::get<5>(GetParam())]) {}
@@ -100,10 +121,10 @@
INSTANTIATE_TEST_SUITE_P(
EffectReverbTestAll, SingleEffectTest,
- ::testing::Combine(::testing::Range(0, (int)EffectTestHelper::kNumChMasks),
- ::testing::Range(0, (int)EffectTestHelper::kNumSampleRates),
- ::testing::Range(0, (int)EffectTestHelper::kNumFrameCounts),
- ::testing::Range(0, (int)EffectTestHelper::kNumLoopCounts),
+ ::testing::Combine(::testing::Range(0, (int)kNumChMasks),
+ ::testing::Range(0, (int)kNumSampleRates),
+ ::testing::Range(0, (int)kNumFrameCounts),
+ ::testing::Range(0, (int)kNumLoopCounts),
::testing::Range(0, (int)kNumEffectUuids),
::testing::Range(0, (int)kNumPresets)));
@@ -112,9 +133,9 @@
: public ::testing::TestWithParam<SingleEffectComparisonTestParam> {
public:
SingleEffectComparisonTest()
- : mSampleRate(EffectTestHelper::kSampleRates[std::get<0>(GetParam())]),
- mFrameCount(EffectTestHelper::kFrameCounts[std::get<1>(GetParam())]),
- mLoopCount(EffectTestHelper::kLoopCounts[std::get<2>(GetParam())]),
+ : mSampleRate(kSampleRates[std::get<0>(GetParam())]),
+ mFrameCount(kFrameCounts[std::get<1>(GetParam())]),
+ mLoopCount(kLoopCounts[std::get<2>(GetParam())]),
mTotalFrameCount(mFrameCount * mLoopCount),
mUuid(&kEffectUuids[std::get<3>(GetParam())]),
mPreset(kPresets[std::get<4>(GetParam())]) {}
@@ -173,7 +194,7 @@
std::vector<int16_t> monoRefI16(mTotalFrameCount);
memcpy_to_i16_from_float(monoRefI16.data(), monoOutput.data(), mTotalFrameCount);
- for (size_t outChMask : EffectTestHelper::kChMasks) {
+ for (size_t outChMask : kChMasks) {
size_t outChannelCount = audio_channel_count_from_out_mask(outChMask);
size_t inChMask = isAuxMode(mUuid) ? AUDIO_CHANNEL_OUT_MONO : outChMask;
@@ -225,9 +246,9 @@
INSTANTIATE_TEST_SUITE_P(
EffectReverbTestAll, SingleEffectComparisonTest,
- ::testing::Combine(::testing::Range(0, (int)EffectTestHelper::kNumSampleRates),
- ::testing::Range(0, (int)EffectTestHelper::kNumFrameCounts),
- ::testing::Range(0, (int)EffectTestHelper::kNumLoopCounts),
+ ::testing::Combine(::testing::Range(0, (int)kNumSampleRates),
+ ::testing::Range(0, (int)kNumFrameCounts),
+ ::testing::Range(0, (int)kNumLoopCounts),
::testing::Range(0, (int)kNumEffectUuids),
::testing::Range(0, (int)kNumPresets)));
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h b/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
index 4652d8d..520371b 100644
--- a/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
@@ -70,12 +70,11 @@
const std::vector<Range::EqualizerRange> kEqRanges = {
MAKE_RANGE(Equalizer, preset, 0, MAX_NUM_PRESETS - 1),
- MAKE_RANGE(
- Equalizer, bandLevels,
- std::vector<Equalizer::BandLevel>{Equalizer::BandLevel(
- {.index = 0, .levelMb = std::numeric_limits<int>::min()})},
- std::vector<Equalizer::BandLevel>{Equalizer::BandLevel(
- {.index = MAX_NUM_BANDS - 1, .levelMb = std::numeric_limits<int>::max()})}),
+ MAKE_RANGE(Equalizer, bandLevels,
+ std::vector<Equalizer::BandLevel>{
+ Equalizer::BandLevel({.index = 0, .levelMb = -15})},
+ std::vector<Equalizer::BandLevel>{
+ Equalizer::BandLevel({.index = MAX_NUM_BANDS - 1, .levelMb = 15})}),
/* capability definition */
MAKE_RANGE(Equalizer, bandFrequencies, kEqBandFrequency, kEqBandFrequency),
MAKE_RANGE(Equalizer, presets, kEqPresets, kEqPresets),
diff --git a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp
index dc52c16..1678570 100644
--- a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp
+++ b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp
@@ -296,11 +296,19 @@
eqParam.set<Equalizer::preset>(mContext->getEqualizerPreset());
break;
}
+ case Equalizer::bandFrequencies: {
+ eqParam.set<Equalizer::bandFrequencies>(lvm::kEqBandFrequency);
+ break;
+ }
+ case Equalizer::presets: {
+ eqParam.set<Equalizer::presets>(lvm::kEqPresets);
+ break;
+ }
case Equalizer::centerFreqMh: {
eqParam.set<Equalizer::centerFreqMh>(mContext->getEqualizerCenterFreqs());
break;
}
- default: {
+ case Equalizer::vendorExtension: {
LOG(ERROR) << __func__ << " not handled tag: " << toString(tag);
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
EX_ILLEGAL_ARGUMENT, "unsupportedTag");
diff --git a/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.cpp b/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.cpp
index 018f3bc..e9bdf94 100644
--- a/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.cpp
+++ b/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.cpp
@@ -184,6 +184,20 @@
EX_ILLEGAL_ARGUMENT, "setDecayHfRatioFailed");
return ndk::ScopedAStatus::ok();
}
+ case EnvironmentalReverb::reflectionsLevelMb: {
+ RETURN_IF(mContext->setReflectionsLevel(
+ erParam.get<EnvironmentalReverb::reflectionsLevelMb>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setReflectionsLevelFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case EnvironmentalReverb::reflectionsDelayMs: {
+ RETURN_IF(mContext->setReflectionsDelay(
+ erParam.get<EnvironmentalReverb::reflectionsDelayMs>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setReflectionsDelayFailed");
+ return ndk::ScopedAStatus::ok();
+ }
case EnvironmentalReverb::levelMb: {
RETURN_IF(mContext->setEnvironmentalReverbLevel(
erParam.get<EnvironmentalReverb::levelMb>()) != RetCode::SUCCESS,
@@ -292,6 +306,14 @@
mContext->getEnvironmentalReverbDecayHfRatio());
break;
}
+ case EnvironmentalReverb::reflectionsLevelMb: {
+ erParam.set<EnvironmentalReverb::reflectionsLevelMb>(mContext->getReflectionsLevel());
+ break;
+ }
+ case EnvironmentalReverb::reflectionsDelayMs: {
+ erParam.set<EnvironmentalReverb::reflectionsDelayMs>(mContext->getReflectionsDelay());
+ break;
+ }
case EnvironmentalReverb::levelMb: {
erParam.set<EnvironmentalReverb::levelMb>(mContext->getEnvironmentalReverbLevel());
break;
diff --git a/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbContext.h b/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbContext.h
index af49a25..9bb0b1a 100644
--- a/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbContext.h
+++ b/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbContext.h
@@ -83,6 +83,18 @@
RetCode setVolumeStereo(const Parameter::VolumeStereo& volumeStereo) override;
Parameter::VolumeStereo getVolumeStereo() override { return mVolumeStereo; }
+ RetCode setReflectionsDelay(int delay) {
+ mReflectionsDelayMs = delay;
+ return RetCode::SUCCESS;
+ }
+ bool getReflectionsDelay() const { return mReflectionsDelayMs; }
+
+ RetCode setReflectionsLevel(int level) {
+ mReflectionsLevelMb = level;
+ return RetCode::SUCCESS;
+ }
+ bool getReflectionsLevel() const { return mReflectionsLevelMb; }
+
IEffect::Status lvmProcess(float* in, float* out, int samples);
private:
@@ -146,15 +158,17 @@
bool mEnabled = false;
LVREV_Handle_t mInstance GUARDED_BY(mMutex);
- int mRoomLevel;
- int mRoomHfLevel;
- int mDecayTime;
- int mDecayHfRatio;
- int mLevel;
- int mDelay;
- int mDiffusion;
- int mDensity;
- bool mBypass;
+ int mRoomLevel = 0;
+ int mRoomHfLevel = 0;
+ int mDecayTime = 0;
+ int mDecayHfRatio = 0;
+ int mLevel = 0;
+ int mDelay = 0;
+ int mDiffusion = 0;
+ int mDensity = 0;
+ bool mBypass = 0;
+ int mReflectionsLevelMb = 0;
+ int mReflectionsDelayMs = 0;
PresetReverb::Presets mPreset;
PresetReverb::Presets mNextPreset;
diff --git a/media/libeffects/preprocessing/Android.bp b/media/libeffects/preprocessing/Android.bp
index c6e036a..d018c47 100644
--- a/media/libeffects/preprocessing/Android.bp
+++ b/media/libeffects/preprocessing/Android.bp
@@ -58,3 +58,39 @@
"libwebrtc_absl_headers",
],
}
+
+cc_library_shared {
+ name: "libpreprocessingaidl",
+ srcs: [
+ "aidl/PreProcessingContext.cpp",
+ "aidl/EffectPreProcessing.cpp",
+ ":effectCommonFile",
+ ],
+ defaults: [
+ "aidlaudioservice_defaults",
+ "latest_android_hardware_audio_effect_ndk_shared",
+ "latest_android_media_audio_common_types_ndk_shared",
+ ],
+ local_include_dirs: ["aidl"],
+ shared_libs: [
+ "liblog",
+ "libutils",
+ "libaudioutils",
+ ],
+ static_libs: [
+ "webrtc_audio_processing",
+ ],
+ header_libs: [
+ "libwebrtc_absl_headers",
+ "libaudioeffects",
+ "libhardware_headers",
+ ],
+ cflags: [
+ "-Wthread-safety",
+ "-Wno-unused-parameter",
+ ],
+ relative_install_path: "soundfx",
+ visibility: [
+ "//hardware/interfaces/audio/aidl/default",
+ ],
+}
diff --git a/media/libeffects/preprocessing/aidl/EffectPreProcessing.cpp b/media/libeffects/preprocessing/aidl/EffectPreProcessing.cpp
new file mode 100644
index 0000000..b9df915
--- /dev/null
+++ b/media/libeffects/preprocessing/aidl/EffectPreProcessing.cpp
@@ -0,0 +1,453 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "EffectPreProcessing"
+#include <algorithm>
+#include <unordered_set>
+
+#include <Utils.h>
+#include <android-base/logging.h>
+#include <fmq/AidlMessageQueue.h>
+
+#include "EffectPreProcessing.h"
+
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::EffectPreProcessing;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::kAcousticEchoCancelerSwImplUUID;
+using aidl::android::hardware::audio::effect::kAutomaticGainControlV1SwImplUUID;
+using aidl::android::hardware::audio::effect::kAutomaticGainControlV2SwImplUUID;
+using aidl::android::hardware::audio::effect::kNoiseSuppressionSwImplUUID;
+using aidl::android::hardware::audio::effect::State;
+using aidl::android::media::audio::common::AudioUuid;
+
+bool isPreProcessingUuidSupported(const AudioUuid& uuid) {
+ return (uuid == kAcousticEchoCancelerSwImplUUID || uuid == kAutomaticGainControlV1SwImplUUID ||
+ uuid == kAutomaticGainControlV2SwImplUUID || uuid == kNoiseSuppressionSwImplUUID);
+}
+
+extern "C" binder_exception_t createEffect(const AudioUuid* uuid,
+ std::shared_ptr<IEffect>* instanceSpp) {
+ if (!uuid || !isPreProcessingUuidSupported(*uuid)) {
+ LOG(ERROR) << __func__ << "uuid not supported";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+ if (instanceSpp) {
+ *instanceSpp = ndk::SharedRefBase::make<EffectPreProcessing>(*uuid);
+ LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
+ return EX_NONE;
+ } else {
+ LOG(ERROR) << __func__ << " invalid input parameter!";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+}
+
+extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
+ if (!in_impl_uuid || !isPreProcessingUuidSupported(*in_impl_uuid)) {
+ LOG(ERROR) << __func__ << "uuid not supported";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+ if (*in_impl_uuid == kAcousticEchoCancelerSwImplUUID) {
+ *_aidl_return = aidl::android::hardware::audio::effect::kAcousticEchoCancelerDesc;
+ } else if (*in_impl_uuid == kAutomaticGainControlV1SwImplUUID) {
+ *_aidl_return = aidl::android::hardware::audio::effect::kAutomaticGainControlV1Desc;
+ } else if (*in_impl_uuid == kAutomaticGainControlV2SwImplUUID) {
+ *_aidl_return = aidl::android::hardware::audio::effect::kAutomaticGainControlV2Desc;
+ } else if (*in_impl_uuid == kNoiseSuppressionSwImplUUID) {
+ *_aidl_return = aidl::android::hardware::audio::effect::kNoiseSuppressionDesc;
+ }
+ return EX_NONE;
+}
+
+namespace aidl::android::hardware::audio::effect {
+
+EffectPreProcessing::EffectPreProcessing(const AudioUuid& uuid) {
+ LOG(DEBUG) << __func__ << uuid.toString();
+ if (uuid == kAcousticEchoCancelerSwImplUUID) {
+ mType = PreProcessingEffectType::ACOUSTIC_ECHO_CANCELLATION;
+ mDescriptor = &kAcousticEchoCancelerDesc;
+ mEffectName = &kAcousticEchoCancelerEffectName;
+ } else if (uuid == kAutomaticGainControlV1SwImplUUID) {
+ mType = PreProcessingEffectType::AUTOMATIC_GAIN_CONTROL_V1;
+ mDescriptor = &kAutomaticGainControlV1Desc;
+ mEffectName = &kAutomaticGainControlV1EffectName;
+ } else if (uuid == kAutomaticGainControlV2SwImplUUID) {
+ mType = PreProcessingEffectType::AUTOMATIC_GAIN_CONTROL_V2;
+ mDescriptor = &kAutomaticGainControlV2Desc;
+ mEffectName = &kAutomaticGainControlV2EffectName;
+ } else if (uuid == kNoiseSuppressionSwImplUUID) {
+ mType = PreProcessingEffectType::NOISE_SUPPRESSION;
+ mDescriptor = &kNoiseSuppressionDesc;
+ mEffectName = &kNoiseSuppressionEffectName;
+ } else {
+ LOG(ERROR) << __func__ << uuid.toString() << " not supported!";
+ }
+}
+
+EffectPreProcessing::~EffectPreProcessing() {
+ cleanUp();
+ LOG(DEBUG) << __func__;
+}
+
+ndk::ScopedAStatus EffectPreProcessing::getDescriptor(Descriptor* _aidl_return) {
+ RETURN_IF(!_aidl_return, EX_ILLEGAL_ARGUMENT, "Parameter:nullptr");
+ LOG(DEBUG) << _aidl_return->toString();
+ *_aidl_return = *mDescriptor;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectPreProcessing::setParameterSpecific(const Parameter::Specific& specific) {
+ LOG(DEBUG) << __func__ << " specific " << specific.toString();
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ auto tag = specific.getTag();
+ switch (tag) {
+ case Parameter::Specific::acousticEchoCanceler:
+ return setParameterAcousticEchoCanceler(specific);
+ case Parameter::Specific::automaticGainControlV1:
+ return setParameterAutomaticGainControlV1(specific);
+ case Parameter::Specific::automaticGainControlV2:
+ return setParameterAutomaticGainControlV2(specific);
+ case Parameter::Specific::noiseSuppression:
+ return setParameterNoiseSuppression(specific);
+ default:
+ LOG(ERROR) << __func__ << " unsupported tag " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "specificParamNotSupported");
+ }
+}
+
+ndk::ScopedAStatus EffectPreProcessing::setParameterAcousticEchoCanceler(
+ const Parameter::Specific& specific) {
+ auto& param = specific.get<Parameter::Specific::acousticEchoCanceler>();
+ RETURN_IF(!inRange(param, kAcousticEchoCancelerRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
+ auto tag = param.getTag();
+
+ switch (tag) {
+ case AcousticEchoCanceler::echoDelayUs: {
+ RETURN_IF(mContext->setAcousticEchoCancelerEchoDelay(
+ param.get<AcousticEchoCanceler::echoDelayUs>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "echoDelayNotSupported");
+ return ndk::ScopedAStatus::ok();
+ }
+ case AcousticEchoCanceler::mobileMode: {
+ RETURN_IF(mContext->setAcousticEchoCancelerMobileMode(
+ param.get<AcousticEchoCanceler::mobileMode>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "SettingMobileModeNotSupported");
+ return ndk::ScopedAStatus::ok();
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "AcousticEchoCancelerTagNotSupported");
+ }
+ }
+}
+
+ndk::ScopedAStatus EffectPreProcessing::setParameterAutomaticGainControlV1(
+ const Parameter::Specific& specific) {
+ auto& param = specific.get<Parameter::Specific::automaticGainControlV1>();
+ RETURN_IF(!inRange(param, kAutomaticGainControlV1Ranges), EX_ILLEGAL_ARGUMENT, "outOfRange");
+ auto tag = param.getTag();
+
+ switch (tag) {
+ case AutomaticGainControlV1::targetPeakLevelDbFs: {
+ RETURN_IF(mContext->setAutomaticGainControlV1TargetPeakLevel(
+ param.get<AutomaticGainControlV1::targetPeakLevelDbFs>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "targetPeakLevelNotSupported");
+ return ndk::ScopedAStatus::ok();
+ }
+ case AutomaticGainControlV1::maxCompressionGainDb: {
+ RETURN_IF(mContext->setAutomaticGainControlV1MaxCompressionGain(
+ param.get<AutomaticGainControlV1::maxCompressionGainDb>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "maxCompressionGainNotSupported");
+ return ndk::ScopedAStatus::ok();
+ }
+ case AutomaticGainControlV1::enableLimiter: {
+ RETURN_IF(
+ mContext->setAutomaticGainControlV1EnableLimiter(
+ param.get<AutomaticGainControlV1::enableLimiter>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "enableLimiterNotSupported");
+ return ndk::ScopedAStatus::ok();
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "AutomaticGainControlV1TagNotSupported");
+ }
+ }
+}
+
+ndk::ScopedAStatus EffectPreProcessing::setParameterAutomaticGainControlV2(
+ const Parameter::Specific& specific) {
+ auto& param = specific.get<Parameter::Specific::automaticGainControlV2>();
+ RETURN_IF(!inRange(param, kAutomaticGainControlV2Ranges), EX_ILLEGAL_ARGUMENT, "outOfRange");
+ auto tag = param.getTag();
+
+ switch (tag) {
+ case AutomaticGainControlV2::fixedDigitalGainMb: {
+ RETURN_IF(mContext->setAutomaticGainControlV2DigitalGain(
+ param.get<AutomaticGainControlV2::fixedDigitalGainMb>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "digitalGainNotSupported");
+ return ndk::ScopedAStatus::ok();
+ }
+ case AutomaticGainControlV2::levelEstimator: {
+ RETURN_IF(mContext->setAutomaticGainControlV2LevelEstimator(
+ param.get<AutomaticGainControlV2::levelEstimator>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "levelEstimatorNotSupported");
+ return ndk::ScopedAStatus::ok();
+ }
+ case AutomaticGainControlV2::saturationMarginMb: {
+ RETURN_IF(mContext->setAutomaticGainControlV2SaturationMargin(
+ param.get<AutomaticGainControlV2::saturationMarginMb>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "saturationMarginNotSupported");
+ return ndk::ScopedAStatus::ok();
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "AutomaticGainControlV2TagNotSupported");
+ }
+ }
+}
+
+ndk::ScopedAStatus EffectPreProcessing::setParameterNoiseSuppression(
+ const Parameter::Specific& specific) {
+ auto& param = specific.get<Parameter::Specific::noiseSuppression>();
+ auto tag = param.getTag();
+
+ switch (tag) {
+ case NoiseSuppression::level: {
+ RETURN_IF(mContext->setNoiseSuppressionLevel(param.get<NoiseSuppression::level>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "levelNotSupported");
+ return ndk::ScopedAStatus::ok();
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "NoiseSuppressionTagNotSupported");
+ }
+ }
+}
+
+ndk::ScopedAStatus EffectPreProcessing::getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) {
+ RETURN_IF(!specific, EX_NULL_POINTER, "nullPtr");
+ auto tag = id.getTag();
+
+ switch (tag) {
+ case Parameter::Id::acousticEchoCancelerTag:
+ return getParameterAcousticEchoCanceler(
+ id.get<Parameter::Id::acousticEchoCancelerTag>(), specific);
+ case Parameter::Id::automaticGainControlV1Tag:
+ return getParameterAutomaticGainControlV1(
+ id.get<Parameter::Id::automaticGainControlV1Tag>(), specific);
+ case Parameter::Id::automaticGainControlV2Tag:
+ return getParameterAutomaticGainControlV2(
+ id.get<Parameter::Id::automaticGainControlV2Tag>(), specific);
+ case Parameter::Id::noiseSuppressionTag:
+ return getParameterNoiseSuppression(id.get<Parameter::Id::noiseSuppressionTag>(),
+ specific);
+ default:
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "wrongIdTag");
+ }
+}
+
+ndk::ScopedAStatus EffectPreProcessing::getParameterAcousticEchoCanceler(
+ const AcousticEchoCanceler::Id& id, Parameter::Specific* specific) {
+ RETURN_IF(id.getTag() != AcousticEchoCanceler::Id::commonTag, EX_ILLEGAL_ARGUMENT,
+ "AcousticEchoCancelerTagNotSupported");
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+ AcousticEchoCanceler param;
+ auto tag = id.get<AcousticEchoCanceler::Id::commonTag>();
+ switch (tag) {
+ case AcousticEchoCanceler::echoDelayUs: {
+ param.set<AcousticEchoCanceler::echoDelayUs>(
+ mContext->getAcousticEchoCancelerEchoDelay());
+ break;
+ }
+ case AcousticEchoCanceler::mobileMode: {
+ param.set<AcousticEchoCanceler::mobileMode>(
+ mContext->getAcousticEchoCancelerMobileMode());
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "AcousticEchoCancelerTagNotSupported");
+ }
+ }
+
+ specific->set<Parameter::Specific::acousticEchoCanceler>(param);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectPreProcessing::getParameterAutomaticGainControlV1(
+ const AutomaticGainControlV1::Id& id, Parameter::Specific* specific) {
+ RETURN_IF(id.getTag() != AutomaticGainControlV1::Id::commonTag, EX_ILLEGAL_ARGUMENT,
+ "AutomaticGainControlV1TagNotSupported");
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+ AutomaticGainControlV1 param;
+
+ auto tag = id.get<AutomaticGainControlV1::Id::commonTag>();
+ switch (tag) {
+ case AutomaticGainControlV1::targetPeakLevelDbFs: {
+ param.set<AutomaticGainControlV1::targetPeakLevelDbFs>(
+ mContext->getAutomaticGainControlV1TargetPeakLevel());
+ break;
+ }
+ case AutomaticGainControlV1::maxCompressionGainDb: {
+ param.set<AutomaticGainControlV1::maxCompressionGainDb>(
+ mContext->getAutomaticGainControlV1MaxCompressionGain());
+ break;
+ }
+ case AutomaticGainControlV1::enableLimiter: {
+ param.set<AutomaticGainControlV1::enableLimiter>(
+ mContext->getAutomaticGainControlV1EnableLimiter());
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "AutomaticGainControlV1TagNotSupported");
+ }
+ }
+
+ specific->set<Parameter::Specific::automaticGainControlV1>(param);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectPreProcessing::getParameterAutomaticGainControlV2(
+ const AutomaticGainControlV2::Id& id, Parameter::Specific* specific) {
+ RETURN_IF(id.getTag() != AutomaticGainControlV2::Id::commonTag, EX_ILLEGAL_ARGUMENT,
+ "AutomaticGainControlV2TagNotSupported");
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+ AutomaticGainControlV2 param;
+
+ auto tag = id.get<AutomaticGainControlV2::Id::commonTag>();
+ switch (tag) {
+ case AutomaticGainControlV2::fixedDigitalGainMb: {
+ param.set<AutomaticGainControlV2::fixedDigitalGainMb>(
+ mContext->getAutomaticGainControlV2DigitalGain());
+ break;
+ }
+ case AutomaticGainControlV2::levelEstimator: {
+ param.set<AutomaticGainControlV2::levelEstimator>(
+ mContext->getAutomaticGainControlV2LevelEstimator());
+ break;
+ }
+ case AutomaticGainControlV2::saturationMarginMb: {
+ param.set<AutomaticGainControlV2::saturationMarginMb>(
+ mContext->getAutomaticGainControlV2SaturationMargin());
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "AutomaticGainControlV2TagNotSupported");
+ }
+ }
+
+ specific->set<Parameter::Specific::automaticGainControlV2>(param);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectPreProcessing::getParameterNoiseSuppression(
+ const NoiseSuppression::Id& id, Parameter::Specific* specific) {
+ RETURN_IF(id.getTag() != NoiseSuppression::Id::commonTag, EX_ILLEGAL_ARGUMENT,
+ "NoiseSuppressionTagNotSupported");
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+ NoiseSuppression param;
+
+ auto tag = id.get<NoiseSuppression::Id::commonTag>();
+ switch (tag) {
+ case NoiseSuppression::level: {
+ param.set<NoiseSuppression::level>(mContext->getNoiseSuppressionLevel());
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "NoiseSuppressionTagNotSupported");
+ }
+ }
+
+ specific->set<Parameter::Specific::noiseSuppression>(param);
+ return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EffectContext> EffectPreProcessing::createContext(const Parameter::Common& common) {
+ if (mContext) {
+ LOG(DEBUG) << __func__ << " context already exist";
+ } else {
+ // PreProcessingSession is a singleton
+ mContext = PreProcessingSession::getPreProcessingSession().createSession(
+ mType, 1 /* statusFmqDepth */, common);
+ }
+
+ return mContext;
+}
+
+std::shared_ptr<EffectContext> EffectPreProcessing::getContext() {
+ return mContext;
+}
+
+RetCode EffectPreProcessing::releaseContext() {
+ if (mContext) {
+ PreProcessingSession::getPreProcessingSession().releaseSession(mType,
+ mContext->getSessionId());
+ mContext.reset();
+ }
+ return RetCode::SUCCESS;
+}
+
+ndk::ScopedAStatus EffectPreProcessing::commandImpl(CommandId command) {
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+ switch (command) {
+ case CommandId::START:
+ mContext->enable();
+ break;
+ case CommandId::STOP:
+ mContext->disable();
+ break;
+ case CommandId::RESET:
+ mContext->disable();
+ mContext->resetBuffer();
+ break;
+ default:
+ LOG(ERROR) << __func__ << " commandId " << toString(command) << " not supported";
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "commandIdNotSupported");
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+// Processing method running in EffectWorker thread.
+IEffect::Status EffectPreProcessing::effectProcessImpl(float* in, float* out, int sampleToProcess) {
+ IEffect::Status status = {EX_NULL_POINTER, 0, 0};
+ RETURN_VALUE_IF(!mContext, status, "nullContext");
+ return mContext->lvmProcess(in, out, sampleToProcess);
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/preprocessing/aidl/EffectPreProcessing.h b/media/libeffects/preprocessing/aidl/EffectPreProcessing.h
new file mode 100644
index 0000000..fad848a
--- /dev/null
+++ b/media/libeffects/preprocessing/aidl/EffectPreProcessing.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/BnEffect.h>
+
+#include "PreProcessingContext.h"
+#include "PreProcessingSession.h"
+#include "effect-impl/EffectImpl.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class EffectPreProcessing final : public EffectImpl {
+ public:
+ explicit EffectPreProcessing(const AudioUuid& uuid);
+ ~EffectPreProcessing() override;
+
+ ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
+
+ ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
+ ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) override;
+
+ std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+ std::shared_ptr<EffectContext> getContext() override;
+ RetCode releaseContext() override;
+
+ IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
+
+ ndk::ScopedAStatus commandImpl(CommandId command) override;
+
+ std::string getEffectName() override { return *mEffectName; }
+
+ private:
+ std::shared_ptr<PreProcessingContext> mContext;
+ const Descriptor* mDescriptor;
+ const std::string* mEffectName;
+ PreProcessingEffectType mType;
+
+ ndk::ScopedAStatus setParameterAcousticEchoCanceler(const Parameter::Specific& specific);
+ ndk::ScopedAStatus getParameterAcousticEchoCanceler(const AcousticEchoCanceler::Id& id,
+ Parameter::Specific* specific);
+
+ ndk::ScopedAStatus setParameterAutomaticGainControlV1(const Parameter::Specific& specific);
+ ndk::ScopedAStatus getParameterAutomaticGainControlV1(const AutomaticGainControlV1::Id& id,
+ Parameter::Specific* specific);
+
+ ndk::ScopedAStatus setParameterAutomaticGainControlV2(const Parameter::Specific& specific);
+ ndk::ScopedAStatus getParameterAutomaticGainControlV2(const AutomaticGainControlV2::Id& id,
+ Parameter::Specific* specific);
+
+ ndk::ScopedAStatus setParameterNoiseSuppression(const Parameter::Specific& specific);
+ ndk::ScopedAStatus getParameterNoiseSuppression(const NoiseSuppression::Id& id,
+ Parameter::Specific* specific);
+};
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/preprocessing/aidl/PreProcessingContext.cpp b/media/libeffects/preprocessing/aidl/PreProcessingContext.cpp
new file mode 100644
index 0000000..104277e
--- /dev/null
+++ b/media/libeffects/preprocessing/aidl/PreProcessingContext.cpp
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstddef>
+#define LOG_TAG "PreProcessingContext"
+#include <Utils.h>
+
+#include "PreProcessingContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+using aidl::android::media::audio::common::AudioDeviceDescription;
+using aidl::android::media::audio::common::AudioDeviceType;
+
+RetCode PreProcessingContext::init(const Parameter::Common& common) {
+ std::lock_guard lg(mMutex);
+ webrtc::AudioProcessingBuilder apBuilder;
+ mAudioProcessingModule = apBuilder.Create();
+ if (mAudioProcessingModule == nullptr) {
+ LOG(ERROR) << "init could not get apm engine";
+ return RetCode::ERROR_EFFECT_LIB_ERROR;
+ }
+
+ updateConfigs(common);
+
+ mEnabledMsk = 0;
+ mProcessedMsk = 0;
+ mRevEnabledMsk = 0;
+ mRevProcessedMsk = 0;
+
+ auto config = mAudioProcessingModule->GetConfig();
+ switch (mType) {
+ case PreProcessingEffectType::ACOUSTIC_ECHO_CANCELLATION:
+ config.echo_canceller.mobile_mode = true;
+ break;
+ case PreProcessingEffectType::AUTOMATIC_GAIN_CONTROL_V1:
+ config.gain_controller1.target_level_dbfs = kAgcDefaultTargetLevel;
+ config.gain_controller1.compression_gain_db = kAgcDefaultCompGain;
+ config.gain_controller1.enable_limiter = kAgcDefaultLimiter;
+ break;
+ case PreProcessingEffectType::AUTOMATIC_GAIN_CONTROL_V2:
+ config.gain_controller2.fixed_digital.gain_db = 0.f;
+ break;
+ case PreProcessingEffectType::NOISE_SUPPRESSION:
+ config.noise_suppression.level = kNsDefaultLevel;
+ break;
+ }
+ mAudioProcessingModule->ApplyConfig(config);
+ mState = PRE_PROC_STATE_INITIALIZED;
+ return RetCode::SUCCESS;
+}
+
+RetCode PreProcessingContext::deInit() {
+ std::lock_guard lg(mMutex);
+ mAudioProcessingModule = nullptr;
+ mState = PRE_PROC_STATE_UNINITIALIZED;
+ return RetCode::SUCCESS;
+}
+
+RetCode PreProcessingContext::enable() {
+ if (mState != PRE_PROC_STATE_INITIALIZED) {
+ return RetCode::ERROR_EFFECT_LIB_ERROR;
+ }
+ int typeMsk = (1 << int(mType));
+ std::lock_guard lg(mMutex);
+ // Check if effect is already enabled.
+ if ((mEnabledMsk & typeMsk) == typeMsk) {
+ return RetCode::ERROR_ILLEGAL_PARAMETER;
+ }
+ mEnabledMsk |= typeMsk;
+ auto config = mAudioProcessingModule->GetConfig();
+ switch (mType) {
+ case PreProcessingEffectType::ACOUSTIC_ECHO_CANCELLATION:
+ config.echo_canceller.enabled = true;
+ // AEC has reverse stream
+ mRevEnabledMsk |= typeMsk;
+ mRevProcessedMsk = 0;
+ break;
+ case PreProcessingEffectType::AUTOMATIC_GAIN_CONTROL_V1:
+ config.gain_controller1.enabled = true;
+ break;
+ case PreProcessingEffectType::AUTOMATIC_GAIN_CONTROL_V2:
+ config.gain_controller2.enabled = true;
+ break;
+ case PreProcessingEffectType::NOISE_SUPPRESSION:
+ config.noise_suppression.enabled = true;
+ break;
+ }
+ mProcessedMsk = 0;
+ mAudioProcessingModule->ApplyConfig(config);
+ mState = PRE_PROC_STATE_ACTIVE;
+ return RetCode::SUCCESS;
+}
+
+RetCode PreProcessingContext::disable() {
+ if (mState != PRE_PROC_STATE_ACTIVE) {
+ return RetCode::ERROR_EFFECT_LIB_ERROR;
+ }
+ int typeMsk = (1 << int(mType));
+ std::lock_guard lg(mMutex);
+ // Check if effect is already disabled.
+ if ((mEnabledMsk & typeMsk) != typeMsk) {
+ return RetCode::ERROR_ILLEGAL_PARAMETER;
+ }
+ mEnabledMsk &= ~typeMsk;
+ auto config = mAudioProcessingModule->GetConfig();
+ switch (mType) {
+ case PreProcessingEffectType::ACOUSTIC_ECHO_CANCELLATION:
+ config.echo_canceller.enabled = false;
+ // AEC has reverse stream
+ mRevEnabledMsk &= ~typeMsk;
+ mRevProcessedMsk = 0;
+ break;
+ case PreProcessingEffectType::AUTOMATIC_GAIN_CONTROL_V1:
+ config.gain_controller1.enabled = false;
+ break;
+ case PreProcessingEffectType::AUTOMATIC_GAIN_CONTROL_V2:
+ config.gain_controller2.enabled = false;
+ break;
+ case PreProcessingEffectType::NOISE_SUPPRESSION:
+ config.noise_suppression.enabled = false;
+ break;
+ }
+ mProcessedMsk = 0;
+ mAudioProcessingModule->ApplyConfig(config);
+ mState = PRE_PROC_STATE_INITIALIZED;
+ return RetCode::SUCCESS;
+}
+
+RetCode PreProcessingContext::setCommon(const Parameter::Common& common) {
+ mCommon = common;
+ updateConfigs(common);
+ return RetCode::SUCCESS;
+}
+
+void PreProcessingContext::updateConfigs(const Parameter::Common& common) {
+ mInputConfig.set_sample_rate_hz(common.input.base.sampleRate);
+ mInputConfig.set_num_channels(
+ ::android::hardware::audio::common::getChannelCount(common.input.base.channelMask));
+ mOutputConfig.set_sample_rate_hz(common.input.base.sampleRate);
+ mOutputConfig.set_num_channels(
+ ::android::hardware::audio::common::getChannelCount(common.output.base.channelMask));
+}
+
+RetCode PreProcessingContext::setAcousticEchoCancelerEchoDelay(int echoDelayUs) {
+ mEchoDelayUs = echoDelayUs;
+ std::lock_guard lg(mMutex);
+ mAudioProcessingModule->set_stream_delay_ms(mEchoDelayUs / 1000);
+ return RetCode::SUCCESS;
+}
+
+int PreProcessingContext::getAcousticEchoCancelerEchoDelay() const {
+ return mEchoDelayUs;
+}
+
+RetCode PreProcessingContext::setAcousticEchoCancelerMobileMode(bool mobileMode) {
+ mMobileMode = mobileMode;
+ std::lock_guard lg(mMutex);
+ auto config = mAudioProcessingModule->GetConfig();
+ config.echo_canceller.mobile_mode = mobileMode;
+ mAudioProcessingModule->ApplyConfig(config);
+ return RetCode::SUCCESS;
+}
+
+bool PreProcessingContext::getAcousticEchoCancelerMobileMode() const {
+ return mMobileMode;
+}
+
+RetCode PreProcessingContext::setAutomaticGainControlV1TargetPeakLevel(int targetPeakLevel) {
+ mTargetPeakLevel = targetPeakLevel;
+ std::lock_guard lg(mMutex);
+ auto config = mAudioProcessingModule->GetConfig();
+ config.gain_controller1.target_level_dbfs = -(mTargetPeakLevel / 100);
+ mAudioProcessingModule->ApplyConfig(config);
+ return RetCode::SUCCESS;
+}
+
+int PreProcessingContext::getAutomaticGainControlV1TargetPeakLevel() const {
+ return mTargetPeakLevel;
+}
+
+RetCode PreProcessingContext::setAutomaticGainControlV1MaxCompressionGain(int maxCompressionGain) {
+ mMaxCompressionGain = maxCompressionGain;
+ std::lock_guard lg(mMutex);
+ auto config = mAudioProcessingModule->GetConfig();
+ config.gain_controller1.compression_gain_db = mMaxCompressionGain / 100;
+ mAudioProcessingModule->ApplyConfig(config);
+ return RetCode::SUCCESS;
+}
+
+int PreProcessingContext::getAutomaticGainControlV1MaxCompressionGain() const {
+ return mMaxCompressionGain;
+}
+
+RetCode PreProcessingContext::setAutomaticGainControlV1EnableLimiter(bool enableLimiter) {
+ mEnableLimiter = enableLimiter;
+ std::lock_guard lg(mMutex);
+ auto config = mAudioProcessingModule->GetConfig();
+ config.gain_controller1.enable_limiter = mEnableLimiter;
+ mAudioProcessingModule->ApplyConfig(config);
+ return RetCode::SUCCESS;
+}
+
+bool PreProcessingContext::getAutomaticGainControlV1EnableLimiter() const {
+ return mEnableLimiter;
+}
+
+RetCode PreProcessingContext::setAutomaticGainControlV2DigitalGain(int gain) {
+ mDigitalGain = gain;
+ std::lock_guard lg(mMutex);
+ auto config = mAudioProcessingModule->GetConfig();
+ config.gain_controller2.fixed_digital.gain_db = mDigitalGain;
+ mAudioProcessingModule->ApplyConfig(config);
+ return RetCode::SUCCESS;
+}
+
+int PreProcessingContext::getAutomaticGainControlV2DigitalGain() const {
+ return mDigitalGain;
+}
+
+RetCode PreProcessingContext::setAutomaticGainControlV2LevelEstimator(
+ AutomaticGainControlV2::LevelEstimator levelEstimator) {
+ mLevelEstimator = levelEstimator;
+ return RetCode::SUCCESS;
+}
+
+AutomaticGainControlV2::LevelEstimator
+PreProcessingContext::getAutomaticGainControlV2LevelEstimator() const {
+ return mLevelEstimator;
+}
+
+RetCode PreProcessingContext::setAutomaticGainControlV2SaturationMargin(int saturationMargin) {
+ mSaturationMargin = saturationMargin;
+ return RetCode::SUCCESS;
+}
+
+int PreProcessingContext::getAutomaticGainControlV2SaturationMargin() const {
+ return mSaturationMargin;
+}
+
+RetCode PreProcessingContext::setNoiseSuppressionLevel(NoiseSuppression::Level level) {
+ mLevel = level;
+ std::lock_guard lg(mMutex);
+ auto config = mAudioProcessingModule->GetConfig();
+ config.noise_suppression.level =
+ (webrtc::AudioProcessing::Config::NoiseSuppression::Level)level;
+ mAudioProcessingModule->ApplyConfig(config);
+ return RetCode::SUCCESS;
+}
+
+NoiseSuppression::Level PreProcessingContext::getNoiseSuppressionLevel() const {
+ return mLevel;
+}
+
+IEffect::Status PreProcessingContext::lvmProcess(float* in, float* out, int samples) {
+ IEffect::Status status = {EX_NULL_POINTER, 0, 0};
+ RETURN_VALUE_IF(!in, status, "nullInput");
+ RETURN_VALUE_IF(!out, status, "nullOutput");
+ status = {EX_ILLEGAL_STATE, 0, 0};
+ int64_t inputFrameCount = getCommon().input.frameCount;
+ int64_t outputFrameCount = getCommon().output.frameCount;
+ RETURN_VALUE_IF(inputFrameCount != outputFrameCount, status, "FrameCountMismatch");
+ RETURN_VALUE_IF(0 == getInputFrameSize(), status, "zeroFrameSize");
+
+ LOG(DEBUG) << __func__ << " start processing";
+ std::lock_guard lg(mMutex);
+
+ mProcessedMsk |= (1 << int(mType));
+
+ // webrtc implementation clear out was_stream_delay_set every time after ProcessStream() call
+ mAudioProcessingModule->set_stream_delay_ms(mEchoDelayUs / 1000);
+
+ if ((mProcessedMsk & mEnabledMsk) == mEnabledMsk) {
+ mProcessedMsk = 0;
+ int processStatus = mAudioProcessingModule->ProcessStream(
+ (const int16_t* const)in, mInputConfig, mOutputConfig, (int16_t* const)out);
+ if (processStatus != 0) {
+ LOG(ERROR) << "Process stream failed with error " << processStatus;
+ return status;
+ }
+ }
+
+ mRevProcessedMsk |= (1 << int(mType));
+
+ if ((mRevProcessedMsk & mRevEnabledMsk) == mRevEnabledMsk) {
+ mRevProcessedMsk = 0;
+ int revProcessStatus = mAudioProcessingModule->ProcessReverseStream(
+ (const int16_t* const)in, mInputConfig, mInputConfig, (int16_t* const)out);
+ if (revProcessStatus != 0) {
+ LOG(ERROR) << "Process reverse stream failed with error " << revProcessStatus;
+ return status;
+ }
+ }
+
+ return {STATUS_OK, samples, samples};
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/preprocessing/aidl/PreProcessingContext.h b/media/libeffects/preprocessing/aidl/PreProcessingContext.h
new file mode 100644
index 0000000..9ba1bbe
--- /dev/null
+++ b/media/libeffects/preprocessing/aidl/PreProcessingContext.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android-base/logging.h>
+#include <android-base/thread_annotations.h>
+#include <audio_processing.h>
+#include <unordered_map>
+
+#include "PreProcessingTypes.h"
+#include "effect-impl/EffectContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+enum PreProcEffectState {
+ PRE_PROC_STATE_UNINITIALIZED,
+ PRE_PROC_STATE_INITIALIZED,
+ PRE_PROC_STATE_ACTIVE,
+};
+
+class PreProcessingContext final : public EffectContext {
+ public:
+ PreProcessingContext(int statusDepth, const Parameter::Common& common,
+ const PreProcessingEffectType& type)
+ : EffectContext(statusDepth, common), mType(type) {
+ LOG(DEBUG) << __func__ << type;
+ mState = PRE_PROC_STATE_UNINITIALIZED;
+ }
+ ~PreProcessingContext() override { LOG(DEBUG) << __func__; }
+
+ RetCode init(const Parameter::Common& common);
+ RetCode deInit();
+
+ PreProcessingEffectType getPreProcessingType() const { return mType; }
+
+ RetCode enable();
+ RetCode disable();
+
+ RetCode setCommon(const Parameter::Common& common) override;
+ void updateConfigs(const Parameter::Common& common);
+
+ RetCode setAcousticEchoCancelerEchoDelay(int echoDelayUs);
+ int getAcousticEchoCancelerEchoDelay() const;
+ RetCode setAcousticEchoCancelerMobileMode(bool mobileMode);
+ bool getAcousticEchoCancelerMobileMode() const;
+
+ RetCode setAutomaticGainControlV1TargetPeakLevel(int targetPeakLevel);
+ int getAutomaticGainControlV1TargetPeakLevel() const;
+ RetCode setAutomaticGainControlV1MaxCompressionGain(int maxCompressionGain);
+ int getAutomaticGainControlV1MaxCompressionGain() const;
+ RetCode setAutomaticGainControlV1EnableLimiter(bool enableLimiter);
+ bool getAutomaticGainControlV1EnableLimiter() const;
+
+ RetCode setAutomaticGainControlV2DigitalGain(int gain);
+ int getAutomaticGainControlV2DigitalGain() const;
+ RetCode setAutomaticGainControlV2LevelEstimator(
+ AutomaticGainControlV2::LevelEstimator levelEstimator);
+ AutomaticGainControlV2::LevelEstimator getAutomaticGainControlV2LevelEstimator() const;
+ RetCode setAutomaticGainControlV2SaturationMargin(int saturationMargin);
+ int getAutomaticGainControlV2SaturationMargin() const;
+
+ RetCode setNoiseSuppressionLevel(NoiseSuppression::Level level);
+ NoiseSuppression::Level getNoiseSuppressionLevel() const;
+
+ IEffect::Status lvmProcess(float* in, float* out, int samples);
+
+ private:
+ static constexpr inline int kAgcDefaultTargetLevel = 3;
+ static constexpr inline int kAgcDefaultCompGain = 9;
+ static constexpr inline bool kAgcDefaultLimiter = true;
+ static constexpr inline webrtc::AudioProcessing::Config::NoiseSuppression::Level
+ kNsDefaultLevel = webrtc::AudioProcessing::Config::NoiseSuppression::kModerate;
+
+ std::mutex mMutex;
+ const PreProcessingEffectType mType;
+ PreProcEffectState mState; // current state
+
+ // handle on webRTC audio processing module (APM)
+ rtc::scoped_refptr<webrtc::AudioProcessing> mAudioProcessingModule GUARDED_BY(mMutex);
+
+ int mEnabledMsk GUARDED_BY(mMutex); // bit field containing IDs of enabled pre processors
+ int mProcessedMsk GUARDED_BY(mMutex); // bit field containing IDs of pre processors already
+ // processed in current round
+ int mRevEnabledMsk GUARDED_BY(mMutex); // bit field containing IDs of enabled pre processors
+ // with reverse channel
+ int mRevProcessedMsk GUARDED_BY(mMutex); // bit field containing IDs of pre processors with
+ // reverse channel already processed in current round
+
+ webrtc::StreamConfig mInputConfig; // input stream configuration
+ webrtc::StreamConfig mOutputConfig; // output stream configuration
+
+ // Acoustic Echo Canceler
+ int mEchoDelayUs = 0;
+ bool mMobileMode = false;
+
+ // Automatic Gain Control V1
+ int mTargetPeakLevel = 0;
+ int mMaxCompressionGain = 0;
+ bool mEnableLimiter = false;
+
+ // Automatic Gain Control V2
+ int mDigitalGain = 0;
+ AutomaticGainControlV2::LevelEstimator mLevelEstimator =
+ AutomaticGainControlV2::LevelEstimator::RMS;
+ int mSaturationMargin = 2;
+
+ // NoiseSuppression
+ NoiseSuppression::Level mLevel = NoiseSuppression::Level::LOW;
+};
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/preprocessing/aidl/PreProcessingSession.h b/media/libeffects/preprocessing/aidl/PreProcessingSession.h
new file mode 100644
index 0000000..877292f
--- /dev/null
+++ b/media/libeffects/preprocessing/aidl/PreProcessingSession.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <algorithm>
+#include <memory>
+#include <unordered_map>
+
+#include <android-base/logging.h>
+#include <android-base/thread_annotations.h>
+
+#include "PreProcessingContext.h"
+#include "PreProcessingTypes.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+/**
+ * @brief Maintain all effect pre-processing sessions.
+ *
+ * Sessions are identified with the session ID, maximum of MAX_BUNDLE_SESSIONS is supported by the
+ * pre-processing implementation.
+ */
+class PreProcessingSession {
+ public:
+ static PreProcessingSession& getPreProcessingSession() {
+ static PreProcessingSession instance;
+ return instance;
+ }
+
+ static bool findPreProcessingTypeInList(
+ std::vector<std::shared_ptr<PreProcessingContext>>& list,
+ const PreProcessingEffectType& type, bool remove = false) {
+ auto itor = std::find_if(list.begin(), list.end(),
+ [type](const std::shared_ptr<PreProcessingContext>& bundle) {
+ return bundle->getPreProcessingType() == type;
+ });
+ if (itor == list.end()) {
+ return false;
+ }
+ if (remove) {
+ (*itor)->deInit();
+ list.erase(itor);
+ }
+ return true;
+ }
+
+ /**
+ * Create a certain type of PreProcessingContext in shared_ptr container, each session must not
+ * have more than one session for each type.
+ */
+ std::shared_ptr<PreProcessingContext> createSession(const PreProcessingEffectType& type,
+ int statusDepth,
+ const Parameter::Common& common) {
+ int sessionId = common.session;
+ LOG(DEBUG) << __func__ << type << " with sessionId " << sessionId;
+ std::lock_guard lg(mMutex);
+ if (mSessionMap.count(sessionId) == 0 && mSessionMap.size() >= MAX_PRE_PROC_SESSIONS) {
+ LOG(ERROR) << __func__ << " exceed max bundle session";
+ return nullptr;
+ }
+
+ if (mSessionMap.count(sessionId)) {
+ if (findPreProcessingTypeInList(mSessionMap[sessionId], type)) {
+ LOG(ERROR) << __func__ << type << " already exist in session " << sessionId;
+ return nullptr;
+ }
+ }
+
+ auto& list = mSessionMap[sessionId];
+ auto context = std::make_shared<PreProcessingContext>(statusDepth, common, type);
+ RETURN_VALUE_IF(!context, nullptr, "failedToCreateContext");
+
+ RetCode ret = context->init(common);
+ if (RetCode::SUCCESS != ret) {
+ LOG(ERROR) << __func__ << " context init ret " << ret;
+ return nullptr;
+ }
+ list.push_back(context);
+ return context;
+ }
+
+ void releaseSession(const PreProcessingEffectType& type, int sessionId) {
+ LOG(DEBUG) << __func__ << type << " sessionId " << sessionId;
+ std::lock_guard lg(mMutex);
+ if (mSessionMap.count(sessionId)) {
+ auto& list = mSessionMap[sessionId];
+ if (!findPreProcessingTypeInList(list, type, true /* remove */)) {
+ LOG(ERROR) << __func__ << " can't find " << type << "in session " << sessionId;
+ return;
+ }
+ if (list.empty()) {
+ mSessionMap.erase(sessionId);
+ }
+ }
+ }
+
+ private:
+ // Lock for mSessionMap access.
+ std::mutex mMutex;
+ // Max session number supported.
+ static constexpr int MAX_PRE_PROC_SESSIONS = 8;
+ std::unordered_map<int /* session ID */, std::vector<std::shared_ptr<PreProcessingContext>>>
+ mSessionMap GUARDED_BY(mMutex);
+};
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/preprocessing/aidl/PreProcessingTypes.h b/media/libeffects/preprocessing/aidl/PreProcessingTypes.h
new file mode 100644
index 0000000..2c880d4
--- /dev/null
+++ b/media/libeffects/preprocessing/aidl/PreProcessingTypes.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/BnEffect.h>
+
+#include <audio_effects/effect_aec.h>
+#include <audio_effects/effect_agc.h>
+#include <audio_effects/effect_agc2.h>
+#include <audio_effects/effect_ns.h>
+
+#include "effect-impl/EffectTypes.h"
+#include "effect-impl/EffectUUID.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+// Acoustic Echo Cancellation
+static const std::string kAcousticEchoCancelerEffectName = "Acoustic Echo Canceler";
+static const std::vector<Range::AcousticEchoCancelerRange> kAcousticEchoCancelerRanges = {
+ MAKE_RANGE(AcousticEchoCanceler, AcousticEchoCanceler::echoDelayUs, 0, 500)};
+static const Capability kAcousticEchoCancelerCap = {.range = kAcousticEchoCancelerRanges};
+static const Descriptor kAcousticEchoCancelerDesc = {
+ .common = {.id = {.type = kAcousticEchoCancelerTypeUUID,
+ .uuid = kAcousticEchoCancelerSwImplUUID,
+ .proxy = kEffectNullUuid},
+ .flags = {.type = Flags::Type::PRE_PROC, .deviceIndication = true},
+ .name = kAcousticEchoCancelerEffectName,
+ .implementor = "The Android Open Source Project"},
+ .capability = kAcousticEchoCancelerCap};
+
+// Automatic Gain Control 1
+static const std::string kAutomaticGainControlV1EffectName = "Automatic Gain Control V1";
+static const std::vector<Range::AutomaticGainControlV1Range> kAutomaticGainControlV1Ranges = {
+ MAKE_RANGE(AutomaticGainControlV1, AutomaticGainControlV1::targetPeakLevelDbFs, -3100, 0),
+ MAKE_RANGE(AutomaticGainControlV1, AutomaticGainControlV1::maxCompressionGainDb, 0, 9000)};
+static const Capability kAutomaticGainControlV1Cap = {.range = kAutomaticGainControlV1Ranges};
+static const Descriptor kAutomaticGainControlV1Desc = {
+ .common = {.id = {.type = kAutomaticGainControlV1TypeUUID,
+ .uuid = kAutomaticGainControlV1SwImplUUID,
+ .proxy = kEffectNullUuid},
+ .flags = {.type = Flags::Type::PRE_PROC, .deviceIndication = true},
+ .name = kAutomaticGainControlV1EffectName,
+ .implementor = "The Android Open Source Project"},
+ .capability = kAutomaticGainControlV1Cap};
+
+// Automatic Gain Control 2
+static const std::string kAutomaticGainControlV2EffectName = "Automatic Gain Control V2";
+const std::vector<Range::AutomaticGainControlV2Range> kAutomaticGainControlV2Ranges = {
+ MAKE_RANGE(AutomaticGainControlV2, AutomaticGainControlV2::fixedDigitalGainMb, 0, 90),
+ // extra_staturation_margin_db is no longer configurable in webrtc
+ MAKE_RANGE(AutomaticGainControlV2, AutomaticGainControlV2::saturationMarginMb, 2, 2),
+ // WebRTC only supports RMS level estimator now
+ MAKE_RANGE(AutomaticGainControlV2, AutomaticGainControlV2::levelEstimator,
+ AutomaticGainControlV2::LevelEstimator::RMS,
+ AutomaticGainControlV2::LevelEstimator::RMS)};
+static const Capability kAutomaticGainControlV2Cap = {.range = kAutomaticGainControlV2Ranges};
+static const Descriptor kAutomaticGainControlV2Desc = {
+ .common = {.id = {.type = kAutomaticGainControlV2TypeUUID,
+ .uuid = kAutomaticGainControlV2SwImplUUID,
+ .proxy = kEffectNullUuid},
+ .flags = {.type = Flags::Type::PRE_PROC, .deviceIndication = true},
+ .name = kAutomaticGainControlV2EffectName,
+ .implementor = "The Android Open Source Project"},
+ .capability = kAutomaticGainControlV2Cap};
+
+// Noise suppression
+static const std::string kNoiseSuppressionEffectName = "Noise Suppression";
+static const Descriptor kNoiseSuppressionDesc = {
+ .common = {.id = {.type = kNoiseSuppressionTypeUUID,
+ .uuid = kNoiseSuppressionSwImplUUID,
+ .proxy = kEffectNullUuid},
+ .flags = {.type = Flags::Type::PRE_PROC, .deviceIndication = true},
+ .name = kNoiseSuppressionEffectName,
+ .implementor = "The Android Open Source Project"}};
+
+enum class PreProcessingEffectType {
+ ACOUSTIC_ECHO_CANCELLATION,
+ AUTOMATIC_GAIN_CONTROL_V1,
+ AUTOMATIC_GAIN_CONTROL_V2,
+ NOISE_SUPPRESSION,
+};
+
+inline std::ostream& operator<<(std::ostream& out, const PreProcessingEffectType& type) {
+ switch (type) {
+ case PreProcessingEffectType::ACOUSTIC_ECHO_CANCELLATION:
+ return out << kAcousticEchoCancelerEffectName;
+ case PreProcessingEffectType::AUTOMATIC_GAIN_CONTROL_V1:
+ return out << kAutomaticGainControlV1EffectName;
+ case PreProcessingEffectType::AUTOMATIC_GAIN_CONTROL_V2:
+ return out << kAutomaticGainControlV2EffectName;
+ case PreProcessingEffectType::NOISE_SUPPRESSION:
+ return out << kNoiseSuppressionEffectName;
+ }
+ return out << "EnumPreProcessingEffectTypeError";
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp
index 85768bd..5aa9adc 100644
--- a/media/libmedia/MediaProfiles.cpp
+++ b/media/libmedia/MediaProfiles.cpp
@@ -898,10 +898,9 @@
}
}
- for (size_t cameraId = 0; cameraId < mCameraIds.size(); ++cameraId) {
+ for (size_t refIndex = 0; refIndex < mCameraIds.size(); ++refIndex) {
+ const int cameraId = mCameraIds[refIndex];
for (size_t j = 0; j < kNumRequiredProfiles; ++j) {
- int refIndex = getRequiredProfileRefIndex(cameraId);
- CHECK(refIndex != -1);
RequiredProfileRefInfo *info =
&mRequiredProfileRefs[refIndex].mRefs[j];
@@ -931,14 +930,14 @@
int index = getCamcorderProfileIndex(cameraId, profile->mQuality);
if (index != -1) {
- ALOGV("Profile quality %d for camera %zu already exists",
+ ALOGV("Profile quality %d for camera %d already exists",
profile->mQuality, cameraId);
CHECK(index == refIndex);
continue;
}
// Insert the new profile
- ALOGV("Add a profile: quality %d=>%d for camera %zu",
+ ALOGV("Add a profile: quality %d=>%d for camera %d",
mCamcorderProfiles[info->mRefProfileIndex]->mQuality,
profile->mQuality, cameraId);
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index ebbbb5f..cdfd2dd 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -88,6 +88,7 @@
using aidl::android::media::BnResourceManagerClient;
using aidl::android::media::IResourceManagerClient;
using aidl::android::media::IResourceManagerService;
+using aidl::android::media::ClientInfoParcel;
// key for media statistics
static const char *kCodecKeyName = "codec";
@@ -209,8 +210,8 @@
////////////////////////////////////////////////////////////////////////////////
struct ResourceManagerClient : public BnResourceManagerClient {
- explicit ResourceManagerClient(MediaCodec* codec, int32_t pid) :
- mMediaCodec(codec), mPid(pid) {}
+ explicit ResourceManagerClient(MediaCodec* codec, int32_t pid, int32_t uid) :
+ mMediaCodec(codec), mPid(pid), mUid(uid) {}
Status reclaimResource(bool* _aidl_return) override {
sp<MediaCodec> codec = mMediaCodec.promote();
@@ -222,7 +223,10 @@
if (service == nullptr) {
ALOGW("MediaCodec::ResourceManagerClient unable to find ResourceManagerService");
}
- service->removeClient(mPid, getId(this));
+ ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid),
+ .uid = static_cast<int32_t>(mUid),
+ .id = getId(this)};
+ service->removeClient(clientInfo);
*_aidl_return = true;
return Status::ok();
}
@@ -260,6 +264,7 @@
private:
wp<MediaCodec> mMediaCodec;
int32_t mPid;
+ int32_t mUid;
DISALLOW_EVIL_CONSTRUCTORS(ResourceManagerClient);
};
@@ -285,10 +290,15 @@
void markClientForPendingRemoval();
bool reclaimResource(const std::vector<MediaResourceParcel> &resources);
+ inline void setCodecName(const char* name) {
+ mCodecName = name;
+ }
+
private:
Mutex mLock;
pid_t mPid;
uid_t mUid;
+ std::string mCodecName;
std::shared_ptr<IResourceManagerService> mService;
std::shared_ptr<IResourceManagerClient> mClient;
::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
@@ -392,7 +402,11 @@
if (mService == nullptr) {
return;
}
- mService->addResource(mPid, mUid, getId(mClient), mClient, resources);
+ ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid),
+ .uid = static_cast<int32_t>(mUid),
+ .id = getId(mClient),
+ .name = mCodecName};
+ mService->addResource(clientInfo, mClient, resources);
}
void MediaCodec::ResourceManagerServiceProxy::removeResource(
@@ -404,7 +418,11 @@
if (mService == nullptr) {
return;
}
- mService->removeResource(mPid, getId(mClient), resources);
+ ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid),
+ .uid = static_cast<int32_t>(mUid),
+ .id = getId(mClient),
+ .name = mCodecName};
+ mService->removeResource(clientInfo, resources);
}
void MediaCodec::ResourceManagerServiceProxy::removeClient() {
@@ -412,7 +430,11 @@
if (mService == nullptr) {
return;
}
- mService->removeClient(mPid, getId(mClient));
+ ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid),
+ .uid = static_cast<int32_t>(mUid),
+ .id = getId(mClient),
+ .name = mCodecName};
+ mService->removeClient(clientInfo);
}
void MediaCodec::ResourceManagerServiceProxy::markClientForPendingRemoval() {
@@ -420,7 +442,11 @@
if (mService == nullptr) {
return;
}
- mService->markClientForPendingRemoval(mPid, getId(mClient));
+ ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid),
+ .uid = static_cast<int32_t>(mUid),
+ .id = getId(mClient),
+ .name = mCodecName};
+ mService->markClientForPendingRemoval(clientInfo);
}
bool MediaCodec::ResourceManagerServiceProxy::reclaimResource(
@@ -430,7 +456,11 @@
return false;
}
bool success;
- Status status = mService->reclaimResource(mPid, resources, &success);
+ ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid),
+ .uid = static_cast<int32_t>(mUid),
+ .id = getId(mClient),
+ .name = mCodecName};
+ Status status = mService->reclaimResource(clientInfo, resources, &success);
return status.isOk() && success;
}
@@ -835,7 +865,7 @@
mGetCodecBase(getCodecBase),
mGetCodecInfo(getCodecInfo) {
mResourceManagerProxy = new ResourceManagerServiceProxy(pid, uid,
- ::ndk::SharedRefBase::make<ResourceManagerClient>(this, pid));
+ ::ndk::SharedRefBase::make<ResourceManagerClient>(this, pid, uid));
if (!mGetCodecBase) {
mGetCodecBase = [](const AString &name, const char *owner) {
return GetCodecBase(name, owner);
@@ -1606,6 +1636,11 @@
std::vector<MediaResourceParcel> resources;
resources.push_back(MediaResource::CodecResource(secureCodec, toMediaResourceSubType(mDomain)));
+
+ // If the ComponentName is not set yet, use the name passed by the user.
+ if (mComponentName.empty()) {
+ mResourceManagerProxy->setCodecName(name.c_str());
+ }
for (int i = 0; i <= kMaxRetry; ++i) {
if (i > 0) {
// Don't try to reclaim resource for the first time.
@@ -3387,6 +3422,8 @@
if (mComponentName.c_str()) {
mediametrics_setCString(mMetricsHandle, kCodecCodec,
mComponentName.c_str());
+ // Update the codec name.
+ mResourceManagerProxy->setCodecName(mComponentName.c_str());
}
const char *owner = mCodecInfo ? mCodecInfo->getOwnerName() : "";
diff --git a/media/module/extractors/ogg/OggExtractor.cpp b/media/module/extractors/ogg/OggExtractor.cpp
index 1c6f516..4c106b2 100644
--- a/media/module/extractors/ogg/OggExtractor.cpp
+++ b/media/module/extractors/ogg/OggExtractor.cpp
@@ -34,6 +34,9 @@
#include <system/audio.h>
#include <utils/String8.h>
+#include <inttypes.h>
+#include <stdint.h>
+
extern "C" {
#include <Tremolo/codec_internal.h>
@@ -346,66 +349,118 @@
off64_t startOffset, off64_t *pageOffset) {
*pageOffset = startOffset;
- for (;;) {
- char signature[4];
- ssize_t n = mSource->readAt(*pageOffset, &signature, 4);
+ // balance between larger reads and reducing how much we over-read.
+ const int FIND_BUF_SIZE = 2048;
+ const int lenOggS = strlen("OggS");
+ while(1) {
- if (n < 4) {
+ // work with big buffers to amortize readAt() costs
+ char signatureBuffer[FIND_BUF_SIZE];
+ ssize_t n = mSource->readAt(*pageOffset, &signatureBuffer, sizeof(signatureBuffer));
+
+ if (n < lenOggS) {
*pageOffset = 0;
-
return (n < 0) ? n : (status_t)ERROR_END_OF_STREAM;
}
- if (!memcmp(signature, "OggS", 4)) {
- if (*pageOffset > startOffset) {
- ALOGV("skipped %lld bytes of junk to reach next frame",
- (long long)(*pageOffset - startOffset));
- }
-
- return OK;
- }
-
- // see how far ahead to skip; avoid some fruitless comparisons
- unsigned int i;
- for (i = 1; i < 4 ; i++) {
- if (signature[i] == 'O')
+ for(int i = 0; i < n - (lenOggS - 1) ; i++) {
+ // fast scan for 1st character in a signature
+ char *p = (char *)memchr(&signatureBuffer[i], 'O', n - (lenOggS - 1) - i);
+ if (p == NULL) {
+ // no signature start in the rest of this buffer.
break;
+ }
+ int jump = (p-&signatureBuffer[i]);
+ i += jump;
+ if (memcmp("OggS", &signatureBuffer[i], lenOggS) == 0) {
+ *pageOffset += i;
+ if (*pageOffset > startOffset) {
+ ALOGD("skipped %" PRIu64 " bytes of junk to reach next frame",
+ (*pageOffset - startOffset));
+ }
+ return OK;
+ }
}
- *pageOffset += i;
+
+ // on to next block. buffer didn't end with "OggS", but could end with "Ogg".
+ // overlap enough to detect this. n >= lenOggS, so this always advances.
+ *pageOffset += n - (lenOggS - 1);
}
+ return (status_t)ERROR_END_OF_STREAM;
}
// Given the offset of the "current" page, find the page immediately preceding
// it (if any) and return its granule position.
// To do this we back up from the "current" page's offset until we find any
// page preceding it and then scan forward to just before the current page.
+//
status_t MyOggExtractor::findPrevGranulePosition(
off64_t pageOffset, uint64_t *granulePos) {
*granulePos = 0;
- off64_t prevPageOffset = 0;
- off64_t prevGuess = pageOffset;
- for (;;) {
- if (prevGuess >= 5000) {
- prevGuess -= 5000;
+ const int FIND_BUF_SIZE = 2048;
+ const int lenOggS = strlen("OggS");
+
+ if (pageOffset == 0) {
+ ALOGV("no page before the first page");
+ return UNKNOWN_ERROR;
+ }
+
+ off64_t prevPageOffset = pageOffset;
+
+ // we start our search on the byte immediately in front of pageOffset
+ // which could mean "O" immediately before and "ggS" starting at pageOffset
+ //
+ // if there was an "OggS" at pageOffset, we'll have scanned a few extra bytes
+ // but if pageOffset was chosen by a seek operation, we don't know that it
+ // reflects the beginning of a page. By choosing to scan 3 possibly unneeded
+ // bytes at the start we cover both cases.
+ //
+ off64_t firstAfter = pageOffset + lenOggS - 1; // NOT within our buffer
+ off64_t nextOffset = pageOffset;
+
+ while(prevPageOffset == pageOffset) {
+ // work with big buffers to amortize readAt() costs
+ char signatureBuffer[FIND_BUF_SIZE];
+
+ ssize_t desired = sizeof(signatureBuffer);
+ if (firstAfter >= desired) {
+ nextOffset = firstAfter - desired;
} else {
- prevGuess = 0;
+ nextOffset = 0;
+ desired = firstAfter;
}
+ ssize_t n = mSource->readAt(nextOffset, &signatureBuffer, desired);
- ALOGV("backing up %lld bytes", (long long)(pageOffset - prevGuess));
-
- status_t err = findNextPage(prevGuess, &prevPageOffset);
- if (err == ERROR_END_OF_STREAM) {
- // We are at the last page and didn't back off enough;
- // back off 5000 bytes more and try again.
- continue;
- } else if (err != OK) {
- return err;
- }
-
- if (prevPageOffset < pageOffset || prevGuess == 0) {
+ if (n < lenOggS) {
+ ALOGD("short read, get out");
break;
}
+
+ // work backwards
+ // loop control ok for n >= 0
+ for(int i = n - lenOggS; i >= 0 ; i--) {
+ // fast scan for 1st character in the signature
+ char *p = (char *)memrchr(&signatureBuffer[0], 'O', i);
+ if (p == NULL) {
+ // no signature start in the rest of this buffer.
+ break;
+ }
+ i = (p-&signatureBuffer[0]);
+ // loop start chosen to ensure we will always have lenOggS bytes
+ if (memcmp("OggS", &signatureBuffer[i], lenOggS) == 0) {
+ prevPageOffset = nextOffset + i;
+ break;
+ }
+ }
+
+ // back up for next read; make sure we catch overlaps
+ if (nextOffset == 0) {
+ // can't back up any further
+ break;
+ }
+ // current buffer might start with "ggS", include those bytes in the next iteration
+ firstAfter = nextOffset + lenOggS - 1;
}
if (prevPageOffset == pageOffset) {
@@ -413,8 +468,8 @@
return UNKNOWN_ERROR;
}
- ALOGV("prevPageOffset at %lld, pageOffset at %lld",
- (long long)prevPageOffset, (long long)pageOffset);
+ ALOGV("prevPageOffset at %" PRIu64 ", pageOffset at %" PRIu64,
+ prevPageOffset, pageOffset);
uint8_t flag = 0;
for (;;) {
Page prevPage;
@@ -993,16 +1048,21 @@
size_t numerator = mTableOfContents.size();
if (numerator > kMaxNumTOCEntries) {
- size_t denom = numerator - kMaxNumTOCEntries;
+ Vector<TOCEntry> maxTOC;
+ maxTOC.setCapacity(kMaxNumTOCEntries);
+ size_t denom = numerator - kMaxNumTOCEntries;
size_t accum = 0;
- for (ssize_t i = mTableOfContents.size(); i > 0; --i) {
+ for (ssize_t i = 0; i < mTableOfContents.size(); i++) {
accum += denom;
if (accum >= numerator) {
- mTableOfContents.removeAt(i);
accum -= numerator;
+ } else {
+ maxTOC.push(mTableOfContents.itemAt(i));
}
}
+
+ mTableOfContents = maxTOC;
}
}
diff --git a/media/ndk/NdkMediaDrm.cpp b/media/ndk/NdkMediaDrm.cpp
index 5005365..0df7636 100644
--- a/media/ndk/NdkMediaDrm.cpp
+++ b/media/ndk/NdkMediaDrm.cpp
@@ -758,6 +758,9 @@
EXPORT
media_status_t AMediaDrm_setPropertyByteArray(AMediaDrm *mObj,
const char *propertyName, const uint8_t *value, size_t valueSize) {
+ if (!mObj || mObj->mDrm == NULL) {
+ return AMEDIA_ERROR_INVALID_OBJECT;
+ }
Vector<uint8_t> byteArray;
byteArray.appendArray(value, valueSize);
diff --git a/media/utils/ProcessInfo.cpp b/media/utils/ProcessInfo.cpp
index da199c4..8437222 100644
--- a/media/utils/ProcessInfo.cpp
+++ b/media/utils/ProcessInfo.cpp
@@ -40,11 +40,11 @@
int32_t state;
int32_t score = INVALID_ADJ;
status_t err = service->getProcessStatesAndOomScoresFromPids(length, &pid, &state, &score);
+ ALOGV("%s: pid:%d state:%d score:%d err:%d", __FUNCTION__, pid, state, score, err);
if (err != OK) {
ALOGE("getProcessStatesAndOomScoresFromPids failed");
return false;
}
- ALOGV("pid %d state %d score %d", pid, state, score);
if (score <= NATIVE_ADJ) {
std::scoped_lock lock{mOverrideLock};
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 0de7e7d..00b612f 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -2140,9 +2140,19 @@
if (!isStreamInitialized()) {
ALOGE("The stream is not open yet"); // This should not happen.
} else {
- // setEventCallback will need a strong pointer as a parameter. Calling it
- // here instead of constructor of PlaybackThread so that the onFirstRef
- // callback would not be made on an incompletely constructed object.
+ // Callbacks take strong or weak pointers as a parameter.
+ // Since PlaybackThread passes itself as a callback handler, it can only
+ // be done outside of the constructor. Creating weak and especially strong
+ // pointers to a refcounted object in its own constructor is strongly
+ // discouraged, see comments in system/core/libutils/include/utils/RefBase.h.
+ // Even if a function takes a weak pointer, it is possible that it will
+ // need to convert it to a strong pointer down the line.
+ if (mOutput->flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING &&
+ mOutput->stream->setCallback(this) == OK) {
+ mUseAsyncWrite = true;
+ mCallbackThread = new AudioFlinger::AsyncCallbackThread(this);
+ }
+
if (mOutput->stream->setEventCallback(this) != OK) {
ALOGD("Failed to add event callback");
}
@@ -3007,13 +3017,6 @@
mFrameCount);
}
- if (mOutput->flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING) {
- if (mOutput->stream->setCallback(this) == OK) {
- mUseAsyncWrite = true;
- mCallbackThread = new AudioFlinger::AsyncCallbackThread(this);
- }
- }
-
mHwSupportsPause = false;
if (mOutput->flags & AUDIO_OUTPUT_FLAG_DIRECT) {
bool supportsPause = false, supportsResume = false;
diff --git a/services/mediametrics/statsd_drm.cpp b/services/mediametrics/statsd_drm.cpp
index 863fdbe..9f08eca 100644
--- a/services/mediametrics/statsd_drm.cpp
+++ b/services/mediametrics/statsd_drm.cpp
@@ -248,10 +248,10 @@
if (!item->getInt32("frontend", &frontend)) return false;
// Optional to be included
- int64_t apex_version = -1;
- item->getInt64("apex_version", &apex_version);
+ std::string version = "";
+ item->getString("version", &version);
const int result = stats_write(stats::media_metrics::MEDIA_DRM_CREATED,
- scheme, uuid_lsb, uuid_msb, uid, frontend, apex_version);
+ scheme, uuid_lsb, uuid_msb, uid, frontend, version.c_str());
std::stringstream log;
log << "result:" << result << " {"
@@ -262,7 +262,7 @@
<< " uuid_msb:" << uuid_msb
<< " uid:" << uid
<< " frontend:" << frontend
- << " apex_version:" << apex_version
+ << " version:" << version
<< " }";
statsdLog->log(stats::media_metrics::MEDIA_DRM_CREATED, log.str());
return true;
@@ -287,10 +287,10 @@
if (!item->getInt32("opened_security_level", &opened_security_level)) return false;
// Optional to be included
- int64_t apex_version = -1;
- item->getInt64("apex_version", &apex_version);
+ std::string version = "";
+ item->getString("version", &version);
const int result = stats_write(stats::media_metrics::MEDIA_DRM_SESSION_OPENED,
- scheme, uuid_lsb, uuid_msb, uid, frontend, apex_version,
+ scheme, uuid_lsb, uuid_msb, uid, frontend, version.c_str(),
object_nonce.c_str(), requested_security_level,
opened_security_level);
@@ -303,7 +303,7 @@
<< " uuid_msb:" << uuid_msb
<< " uid:" << uid
<< " frontend:" << frontend
- << " apex_version:" << apex_version
+ << " version:" << version
<< " object_nonce:" << object_nonce
<< " requested_security_level:" << requested_security_level
<< " opened_security_level:" << opened_security_level
@@ -334,8 +334,8 @@
if (!item->getInt32("error_code", &error_code)) return false;
// Optional to be included
- int64_t apex_version = -1;
- item->getInt64("apex_version", &apex_version);
+ std::string version = "";
+ item->getString("version", &version);
std::string session_nonce = "";
item->getString("session_nonce", &session_nonce);
@@ -347,7 +347,7 @@
item->getInt32("error_context", &error_context);
const int result = stats_write(stats::media_metrics::MEDIA_DRM_ERRORED, scheme, uuid_lsb,
- uuid_msb, uid, frontend, apex_version, object_nonce.c_str(),
+ uuid_msb, uid, frontend, version.c_str(), object_nonce.c_str(),
session_nonce.c_str(), security_level, api, error_code, cdm_err,
oem_err, error_context);
@@ -360,7 +360,7 @@
<< " uuid_msb:" << uuid_msb
<< " uid:" << uid
<< " frontend:" << frontend
- << " apex_version:" << apex_version
+ << " version:" << version
<< " object_nonce:" << object_nonce
<< " session_nonce:" << session_nonce
<< " security_level:" << security_level
diff --git a/services/mediaresourcemanager/Android.bp b/services/mediaresourcemanager/Android.bp
index 5d80744..2b8245e 100644
--- a/services/mediaresourcemanager/Android.bp
+++ b/services/mediaresourcemanager/Android.bp
@@ -16,6 +16,7 @@
"aidl/android/media/MediaResourceSubType.aidl",
"aidl/android/media/MediaResourceParcel.aidl",
"aidl/android/media/MediaResourcePolicyParcel.aidl",
+ "aidl/android/media/ClientInfoParcel.aidl",
],
path: "aidl",
}
@@ -87,10 +88,15 @@
"libbinder_ndk",
"libutils",
"liblog",
+ "libstats_media_metrics",
+ "libstatspull",
+ "libstatssocket",
+ "libprotobuf-cpp-lite",
],
static_libs: [
"resourceobserver_aidl_interface-V1-ndk",
+ "libplatformprotos",
],
include_dirs: ["frameworks/av/include"],
@@ -101,4 +107,10 @@
],
export_include_dirs: ["."],
+
+ export_shared_lib_headers: [
+ "libstats_media_metrics",
+ "libstatspull",
+ "libstatssocket",
+ ],
}
diff --git a/services/mediaresourcemanager/ResourceManagerService.cpp b/services/mediaresourcemanager/ResourceManagerService.cpp
index 4d18876..f94446f 100644
--- a/services/mediaresourcemanager/ResourceManagerService.cpp
+++ b/services/mediaresourcemanager/ResourceManagerService.cpp
@@ -34,6 +34,7 @@
#include <sys/stat.h>
#include <sys/time.h>
#include <unistd.h>
+#include <stats_media_metrics.h>
#include "IMediaResourceMonitor.h"
#include "ResourceManagerService.h"
@@ -42,6 +43,14 @@
namespace android {
+using stats::media_metrics::stats_write;
+using stats::media_metrics::MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED;
+using stats::media_metrics::MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_SUCCESS;
+using stats::media_metrics::\
+ MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_FAILED_NO_CLIENTS;
+using stats::media_metrics::\
+ MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_FAILED_RECLAIM_RESOURCES;
+
//static
std::mutex ResourceManagerService::sCookieLock;
//static
@@ -97,7 +106,8 @@
service->overridePid(mPid, -1);
// thiz is freed in the call below, so it must be last call referring thiz
- service->removeResource(mPid, mClientId, false /*checkValid*/);
+ ClientInfoParcel clientInfo{.pid = mPid, .id = mClientId};
+ service->removeResource(clientInfo, false /*checkValid*/);
}
class OverrideProcessInfoDeathNotifier : public DeathNotifier {
@@ -183,6 +193,7 @@
}
static ResourceInfo& getResourceInfoForEdit(uid_t uid, int64_t clientId,
+ const std::string& name,
const std::shared_ptr<IResourceManagerClient>& client, ResourceInfos& infos) {
ssize_t index = infos.indexOfKey(clientId);
@@ -190,6 +201,7 @@
ResourceInfo info;
info.uid = uid;
info.clientId = clientId;
+ info.name = name;
info.client = client;
info.cookie = 0;
info.pendingRemoval = false;
@@ -262,7 +274,15 @@
result.append(" Processes:\n");
for (size_t i = 0; i < mapCopy.size(); ++i) {
- snprintf(buffer, SIZE, " Pid: %d\n", mapCopy.keyAt(i));
+ int pid = mapCopy.keyAt(i);
+ snprintf(buffer, SIZE, " Pid: %d\n", pid);
+ result.append(buffer);
+ int priority = 0;
+ if (getPriority_l(pid, &priority)) {
+ snprintf(buffer, SIZE, " Priority: %d\n", priority);
+ } else {
+ snprintf(buffer, SIZE, " Priority: <unknown>\n");
+ }
result.append(buffer);
const ResourceInfos &infos = mapCopy.valueAt(i);
@@ -273,7 +293,7 @@
std::string clientName = "<unknown client>";
if (infos[j].client != nullptr) {
- Status status = infos[j].client->getName(&clientName);
+ clientName = infos[j].name;
}
snprintf(buffer, SIZE, " Name: %s\n", clientName.c_str());
result.append(buffer);
@@ -433,11 +453,15 @@
}
}
-Status ResourceManagerService::addResource(int32_t pid, int32_t uid, int64_t clientId,
+Status ResourceManagerService::addResource(const ClientInfoParcel& clientInfo,
const std::shared_ptr<IResourceManagerClient>& client,
const std::vector<MediaResourceParcel>& resources) {
- String8 log = String8::format("addResource(pid %d, clientId %lld, resources %s)",
- pid, (long long) clientId, getString(resources).string());
+ int32_t pid = clientInfo.pid;
+ int32_t uid = clientInfo.uid;
+ int64_t clientId = clientInfo.id;
+ const std::string& name = clientInfo.name;
+ String8 log = String8::format("addResource(pid %d, uid %d clientId %lld, resources %s)",
+ pid, uid, (long long) clientId, getString(resources).string());
mServiceLog->add(log);
Mutex::Autolock lock(mLock);
@@ -450,7 +474,7 @@
uid = callingUid;
}
ResourceInfos& infos = getResourceInfosForEdit(pid, mMap);
- ResourceInfo& info = getResourceInfoForEdit(uid, clientId, client, infos);
+ ResourceInfo& info = getResourceInfoForEdit(uid, clientId, name, client, infos);
ResourceList resourceAdded;
for (size_t i = 0; i < resources.size(); ++i) {
@@ -489,13 +513,50 @@
mObserverService->onResourceAdded(uid, pid, resourceAdded);
}
notifyResourceGranted(pid, resources);
+
+ // Increase the instance count of the resource associated with this client.
+ increaseResourceInstanceCount(clientId, name);
+
return Status::ok();
}
-Status ResourceManagerService::removeResource(int32_t pid, int64_t clientId,
+void ResourceManagerService::increaseResourceInstanceCount(int64_t clientId,
+ const std::string& name) {
+ // Check whether this client has been looked into already.
+ if (mClientIdSet.find(clientId) == mClientIdSet.end()) {
+ mClientIdSet.insert(clientId);
+ // Update the resource instance count.
+ auto found = mConcurrentResourceCountMap.find(name);
+ if (found == mConcurrentResourceCountMap.end()) {
+ mConcurrentResourceCountMap[name] = 1;
+ } else {
+ found->second++;
+ }
+ }
+}
+
+void ResourceManagerService::decreaseResourceInstanceCount(int64_t clientId,
+ const std::string& name) {
+ // Since this client has been removed, remove it from mClientIdSet
+ mClientIdSet.erase(clientId);
+ // Update the resource instance count also.
+ auto found = mConcurrentResourceCountMap.find(name);
+ if (found != mConcurrentResourceCountMap.end()) {
+ if (found->second == 1) {
+ mConcurrentResourceCountMap.erase(found);
+ } else {
+ found->second--;
+ }
+ }
+}
+
+Status ResourceManagerService::removeResource(const ClientInfoParcel& clientInfo,
const std::vector<MediaResourceParcel>& resources) {
- String8 log = String8::format("removeResource(pid %d, clientId %lld, resources %s)",
- pid, (long long) clientId, getString(resources).string());
+ int32_t pid = clientInfo.pid;
+ int32_t uid = clientInfo.uid;
+ int64_t clientId = clientInfo.id;
+ String8 log = String8::format("removeResource(pid %d, uid %d clientId %lld, resources %s)",
+ pid, uid, (long long) clientId, getString(resources).string());
mServiceLog->add(log);
Mutex::Autolock lock(mLock);
@@ -555,15 +616,17 @@
return Status::ok();
}
-Status ResourceManagerService::removeClient(int32_t pid, int64_t clientId) {
- removeResource(pid, clientId, true /*checkValid*/);
+Status ResourceManagerService::removeClient(const ClientInfoParcel& clientInfo) {
+ removeResource(clientInfo, true /*checkValid*/);
return Status::ok();
}
-Status ResourceManagerService::removeResource(int pid, int64_t clientId, bool checkValid) {
- String8 log = String8::format(
- "removeResource(pid %d, clientId %lld)",
- pid, (long long) clientId);
+Status ResourceManagerService::removeResource(const ClientInfoParcel& clientInfo, bool checkValid) {
+ int32_t pid = clientInfo.pid;
+ int32_t uid = clientInfo.uid;
+ int64_t clientId = clientInfo.id;
+ String8 log = String8::format("removeResource(pid %d, uid %d clientId %lld)",
+ pid, uid, (long long) clientId);
mServiceLog->add(log);
Mutex::Autolock lock(mLock);
@@ -591,6 +654,10 @@
onLastRemoved(it->second, info);
}
+ // Since this client has been removed, decrease the corresponding
+ // resources instance count.
+ decreaseResourceInstanceCount(clientId, info.name);
+
removeCookieAndUnlink_l(info.client, info.cookie);
if (mObserverService != nullptr && !info.resources.empty()) {
@@ -601,25 +668,30 @@
return Status::ok();
}
-void ResourceManagerService::getClientForResource_l(int callingPid, const MediaResourceParcel *res,
+void ResourceManagerService::getClientForResource_l(int callingPid,
+ const MediaResourceParcel *res,
+ PidUidVector* idVector,
Vector<std::shared_ptr<IResourceManagerClient>> *clients) {
if (res == NULL) {
return;
}
std::shared_ptr<IResourceManagerClient> client;
- if (getLowestPriorityBiggestClient_l(callingPid, res->type, res->subType, &client)) {
+ if (getLowestPriorityBiggestClient_l(callingPid, res->type, res->subType, idVector, &client)) {
clients->push_back(client);
}
}
-Status ResourceManagerService::reclaimResource(int32_t callingPid,
+Status ResourceManagerService::reclaimResource(const ClientInfoParcel& clientInfo,
const std::vector<MediaResourceParcel>& resources, bool* _aidl_return) {
- String8 log = String8::format("reclaimResource(callingPid %d, resources %s)",
- callingPid, getString(resources).string());
+ int32_t callingPid = clientInfo.pid;
+ std::string clientName = clientInfo.name;
+ String8 log = String8::format("reclaimResource(callingPid %d, uid %d resources %s)",
+ callingPid, clientInfo.uid, getString(resources).string());
mServiceLog->add(log);
*_aidl_return = false;
Vector<std::shared_ptr<IResourceManagerClient>> clients;
+ PidUidVector idVector;
{
Mutex::Autolock lock(mLock);
if (!mProcessInfo->isPidTrusted(callingPid)) {
@@ -655,13 +727,13 @@
if (secureCodec != NULL) {
if (!mSupportsMultipleSecureCodecs) {
if (!getAllClients_l(callingPid, MediaResource::Type::kSecureCodec,
- secureCodec->subType, &clients)) {
+ secureCodec->subType, &idVector, &clients)) {
return Status::ok();
}
}
if (!mSupportsSecureWithNonSecureCodec) {
if (!getAllClients_l(callingPid, MediaResource::Type::kNonSecureCodec,
- secureCodec->subType, &clients)) {
+ secureCodec->subType, &idVector, &clients)) {
return Status::ok();
}
}
@@ -669,13 +741,13 @@
if (nonSecureCodec != NULL) {
if (!mSupportsSecureWithNonSecureCodec) {
if (!getAllClients_l(callingPid, MediaResource::Type::kSecureCodec,
- nonSecureCodec->subType, &clients)) {
+ nonSecureCodec->subType, &idVector, &clients)) {
return Status::ok();
}
}
}
if (drmSession != NULL) {
- getClientForResource_l(callingPid, drmSession, &clients);
+ getClientForResource_l(callingPid, drmSession, &idVector, &clients);
if (clients.size() == 0) {
return Status::ok();
}
@@ -683,32 +755,108 @@
if (clients.size() == 0) {
// if no secure/non-secure codec conflict, run second pass to handle other resources.
- getClientForResource_l(callingPid, graphicMemory, &clients);
+ getClientForResource_l(callingPid, graphicMemory, &idVector, &clients);
}
if (clients.size() == 0) {
// if we are here, run the third pass to free one codec with the same type.
- getClientForResource_l(callingPid, secureCodec, &clients);
- getClientForResource_l(callingPid, nonSecureCodec, &clients);
+ getClientForResource_l(callingPid, secureCodec, &idVector, &clients);
+ getClientForResource_l(callingPid, nonSecureCodec, &idVector, &clients);
}
if (clients.size() == 0) {
// if we are here, run the fourth pass to free one codec with the different type.
if (secureCodec != NULL) {
MediaResource temp(MediaResource::Type::kNonSecureCodec, secureCodec->subType, 1);
- getClientForResource_l(callingPid, &temp, &clients);
+ getClientForResource_l(callingPid, &temp, &idVector, &clients);
}
if (nonSecureCodec != NULL) {
MediaResource temp(MediaResource::Type::kSecureCodec, nonSecureCodec->subType, 1);
- getClientForResource_l(callingPid, &temp, &clients);
+ getClientForResource_l(callingPid, &temp, &idVector, &clients);
}
}
}
*_aidl_return = reclaimUnconditionallyFrom(clients);
+
+ // Log Reclaim Pushed Atom to statsd
+ pushReclaimAtom(clientInfo, clients, idVector, *_aidl_return);
+
return Status::ok();
}
+void ResourceManagerService::pushReclaimAtom(const ClientInfoParcel& clientInfo,
+ const Vector<std::shared_ptr<IResourceManagerClient>>& clients,
+ const PidUidVector& idVector, bool reclaimed) {
+ // Construct the metrics for codec reclaim as a pushed atom.
+ // 1. Information about the requester.
+ // - UID and the priority (oom score)
+ int32_t callingPid = clientInfo.pid;
+ int32_t requesterUid = clientInfo.uid;
+ std::string clientName = clientInfo.name;
+ int requesterPriority = -1;
+ getPriority_l(callingPid, &requesterPriority);
+
+ // 2. Information about the codec.
+ // - Name of the codec requested
+ // - Number of concurrent codecs running.
+ int32_t noOfConcurrentCodecs = 0;
+ auto found = mConcurrentResourceCountMap.find(clientName);
+ if (found != mConcurrentResourceCountMap.end()) {
+ noOfConcurrentCodecs = found->second;
+ }
+
+ // 3. Information about the Reclaim:
+ // - Status of reclaim request
+ // - How many codecs are reclaimed
+ // - For each codecs reclaimed, information of the process that it belonged to:
+ // - UID and the Priority (oom score)
+ int32_t reclaimStatus = MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_SUCCESS;
+ if (!reclaimed) {
+ if (clients.size() == 0) {
+ // No clients to reclaim from
+ reclaimStatus =
+ MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_FAILED_NO_CLIENTS;
+ } else {
+ // Couldn't reclaim resources from the clients
+ reclaimStatus =
+ MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_FAILED_RECLAIM_RESOURCES;
+ }
+ }
+ int32_t noOfCodecsReclaimed = clients.size();
+ int32_t targetIndex = 1;
+ for (const auto& id : idVector) {
+ int32_t targetUid = id.second;
+ int targetPriority = -1;
+ getPriority_l(id.first, &targetPriority);
+ // Post the pushed atom
+ int result = stats_write(
+ MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED,
+ requesterUid,
+ requesterPriority,
+ clientName.c_str(),
+ noOfConcurrentCodecs,
+ reclaimStatus,
+ noOfCodecsReclaimed,
+ targetIndex,
+ targetUid,
+ targetPriority);
+ ALOGI("%s: Pushed MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED atom: "
+ "Requester[pid(%d): uid(%d): priority(%d)] "
+ "Codec: [%s] "
+ "No of concurrent codecs: %d "
+ "Reclaim Status: %d "
+ "No of codecs reclaimed: %d "
+ "Target[%d][pid(%d): uid(%d): priority(%d)] "
+ "Atom Size: %d",
+ __func__, callingPid, requesterUid, requesterPriority,
+ clientName.c_str(), noOfConcurrentCodecs,
+ reclaimStatus, noOfCodecsReclaimed,
+ targetIndex, id.first, targetUid, targetPriority, result);
+ targetIndex++;
+ }
+}
+
bool ResourceManagerService::reclaimUnconditionallyFrom(
const Vector<std::shared_ptr<IResourceManagerClient>> &clients) {
if (clients.size() == 0) {
@@ -868,7 +1016,9 @@
mProcessInfoOverrideMap.erase(pid);
}
-Status ResourceManagerService::markClientForPendingRemoval(int32_t pid, int64_t clientId) {
+Status ResourceManagerService::markClientForPendingRemoval(const ClientInfoParcel& clientInfo) {
+ int32_t pid = clientInfo.pid;
+ int64_t clientId = clientInfo.id;
String8 log = String8::format(
"markClientForPendingRemoval(pid %d, clientId %lld)",
pid, (long long) clientId);
@@ -926,7 +1076,8 @@
MediaResource::SubType::kVideoCodec,
MediaResource::SubType::kImageCodec}) {
std::shared_ptr<IResourceManagerClient> client;
- if (getBiggestClientPendingRemoval_l(pid, type, subType, &client)) {
+ uid_t uid = 0;
+ if (getBiggestClientPendingRemoval_l(pid, type, subType, uid, &client)) {
clients.add(client);
continue;
}
@@ -935,8 +1086,9 @@
// Non-codec resources are shared by audio, video and image codecs (no subtype).
default:
std::shared_ptr<IResourceManagerClient> client;
+ uid_t uid = 0;
if (getBiggestClientPendingRemoval_l(pid, type,
- MediaResource::SubType::kUnspecifiedSubType, &client)) {
+ MediaResource::SubType::kUnspecifiedSubType, uid, &client)) {
clients.add(client);
}
break;
@@ -963,8 +1115,12 @@
}
bool ResourceManagerService::getAllClients_l(int callingPid, MediaResource::Type type,
- MediaResource::SubType subType, Vector<std::shared_ptr<IResourceManagerClient>> *clients) {
+ MediaResource::SubType subType,
+ PidUidVector* idVector,
+ Vector<std::shared_ptr<IResourceManagerClient>> *clients) {
Vector<std::shared_ptr<IResourceManagerClient>> temp;
+ PidUidVector tempIdList;
+
for (size_t i = 0; i < mMap.size(); ++i) {
ResourceInfos &infos = mMap.editValueAt(i);
for (size_t j = 0; j < infos.size(); ++j) {
@@ -977,6 +1133,7 @@
return false;
}
temp.push_back(infos[j].client);
+ tempIdList.emplace_back(mMap.keyAt(i), infos[j].uid);
}
}
}
@@ -985,19 +1142,24 @@
return true;
}
clients->appendVector(temp);
+ idVector->insert(std::end(*idVector), std::begin(tempIdList), std::end(tempIdList));
return true;
}
bool ResourceManagerService::getLowestPriorityBiggestClient_l(int callingPid,
- MediaResource::Type type, MediaResource::SubType subType,
+ MediaResource::Type type,
+ MediaResource::SubType subType,
+ PidUidVector* idVector,
std::shared_ptr<IResourceManagerClient> *client) {
int lowestPriorityPid;
int lowestPriority;
int callingPriority;
+ uid_t uid = 0;
// Before looking into other processes, check if we have clients marked for
// pending removal in the same process.
- if (getBiggestClientPendingRemoval_l(callingPid, type, subType, client)) {
+ if (getBiggestClientPendingRemoval_l(callingPid, type, subType, uid, client)) {
+ idVector->emplace_back(callingPid, uid);
return true;
}
if (!getPriority_l(callingPid, &callingPriority)) {
@@ -1014,9 +1176,11 @@
return false;
}
- if (!getBiggestClient_l(lowestPriorityPid, type, subType, client)) {
+ if (!getBiggestClient_l(lowestPriorityPid, type, subType, uid, client)) {
return false;
}
+
+ idVector->emplace_back(lowestPriorityPid, uid);
return true;
}
@@ -1068,12 +1232,14 @@
}
bool ResourceManagerService::getBiggestClientPendingRemoval_l(int pid, MediaResource::Type type,
- MediaResource::SubType subType, std::shared_ptr<IResourceManagerClient> *client) {
- return getBiggestClient_l(pid, type, subType, client, true /* pendingRemovalOnly */);
+ MediaResource::SubType subType, uid_t& uid,
+ std::shared_ptr<IResourceManagerClient> *client) {
+ return getBiggestClient_l(pid, type, subType, uid, client, true /* pendingRemovalOnly */);
}
bool ResourceManagerService::getBiggestClient_l(int pid, MediaResource::Type type,
- MediaResource::SubType subType, std::shared_ptr<IResourceManagerClient> *client,
+ MediaResource::SubType subType, uid_t& uid,
+ std::shared_ptr<IResourceManagerClient> *client,
bool pendingRemovalOnly) {
ssize_t index = mMap.indexOfKey(pid);
if (index < 0) {
@@ -1096,6 +1262,7 @@
if (resource.value > largestValue) {
largestValue = resource.value;
clientTemp = infos[i].client;
+ uid = infos[i].uid;
}
}
}
diff --git a/services/mediaresourcemanager/ResourceManagerService.h b/services/mediaresourcemanager/ResourceManagerService.h
index c636a0f..0016a19 100644
--- a/services/mediaresourcemanager/ResourceManagerService.h
+++ b/services/mediaresourcemanager/ResourceManagerService.h
@@ -19,7 +19,9 @@
#define ANDROID_MEDIA_RESOURCEMANAGERSERVICE_H
#include <map>
+#include <set>
#include <mutex>
+#include <string>
#include <aidl/android/media/BnResourceManagerService.h>
#include <arpa/inet.h>
@@ -43,20 +45,24 @@
using ::aidl::android::media::BnResourceManagerService;
using ::aidl::android::media::MediaResourceParcel;
using ::aidl::android::media::MediaResourcePolicyParcel;
+using ::aidl::android::media::ClientInfoParcel;
typedef std::map<std::tuple<
MediaResource::Type, MediaResource::SubType, std::vector<uint8_t>>,
MediaResourceParcel> ResourceList;
struct ResourceInfo {
- int64_t clientId;
uid_t uid;
+ int64_t clientId;
+ std::string name;
std::shared_ptr<IResourceManagerClient> client;
uintptr_t cookie{0};
ResourceList resources;
bool pendingRemoval{false};
};
+typedef std::vector<std::pair<int32_t, uid_t>> PidUidVector;
+
// TODO: convert these to std::map
typedef KeyedVector<int64_t, ResourceInfo> ResourceInfos;
typedef KeyedVector<int, ResourceInfos> PidResourceInfosMap;
@@ -85,31 +91,32 @@
// IResourceManagerService interface
Status config(const std::vector<MediaResourcePolicyParcel>& policies) override;
- Status addResource(int32_t pid, int32_t uid, int64_t clientId,
- const std::shared_ptr<IResourceManagerClient>& client,
- const std::vector<MediaResourceParcel>& resources) override;
+ Status addResource(const ClientInfoParcel& clientInfo,
+ const std::shared_ptr<IResourceManagerClient>& client,
+ const std::vector<MediaResourceParcel>& resources) override;
- Status removeResource(int32_t pid, int64_t clientId,
- const std::vector<MediaResourceParcel>& resources) override;
+ Status removeResource(const ClientInfoParcel& clientInfo,
+ const std::vector<MediaResourceParcel>& resources) override;
- Status removeClient(int32_t pid, int64_t clientId) override;
+ Status removeClient(const ClientInfoParcel& clientInfo) override;
// Tries to reclaim resource from processes with lower priority than the calling process
// according to the requested resources.
// Returns true if any resource has been reclaimed, otherwise returns false.
- Status reclaimResource(int32_t callingPid, const std::vector<MediaResourceParcel>& resources,
- bool* _aidl_return) override;
+ Status reclaimResource(const ClientInfoParcel& clientInfo,
+ const std::vector<MediaResourceParcel>& resources,
+ bool* _aidl_return) override;
- Status overridePid(int originalPid, int newPid) override;
+ Status overridePid(int32_t originalPid, int32_t newPid) override;
- Status overrideProcessInfo(const std::shared_ptr<IResourceManagerClient>& client, int pid,
- int procState, int oomScore) override;
+ Status overrideProcessInfo(const std::shared_ptr<IResourceManagerClient>& client,
+ int32_t pid, int32_t procState, int32_t oomScore) override;
- Status markClientForPendingRemoval(int32_t pid, int64_t clientId) override;
+ Status markClientForPendingRemoval(const ClientInfoParcel& clientInfo) override;
Status reclaimResourcesFromClientsPendingRemoval(int32_t pid) override;
- Status removeResource(int pid, int64_t clientId, bool checkValid);
+ Status removeResource(const ClientInfoParcel& clientInfo, bool checkValid);
private:
friend class ResourceManagerServiceTest;
@@ -124,13 +131,15 @@
// Returns false if any client belongs to a process with higher priority than the
// calling process. The clients will remain unchanged if returns false.
bool getAllClients_l(int callingPid, MediaResource::Type type, MediaResource::SubType subType,
+ PidUidVector* idList,
Vector<std::shared_ptr<IResourceManagerClient>> *clients);
// Gets the client who owns specified resource type from lowest possible priority process.
// Returns false if the calling process priority is not higher than the lowest process
// priority. The client will remain unchanged if returns false.
bool getLowestPriorityBiggestClient_l(int callingPid, MediaResource::Type type,
- MediaResource::SubType subType, std::shared_ptr<IResourceManagerClient> *client);
+ MediaResource::SubType subType, PidUidVector* idList,
+ std::shared_ptr<IResourceManagerClient> *client);
// Gets lowest priority process that has the specified resource type.
// Returns false if failed. The output parameters will remain unchanged if failed.
@@ -141,17 +150,19 @@
// Returns false with no change to client if there are no clients holdiing resources of thisi
// type.
bool getBiggestClient_l(int pid, MediaResource::Type type, MediaResource::SubType subType,
- std::shared_ptr<IResourceManagerClient> *client,
+ uid_t& uid, std::shared_ptr<IResourceManagerClient> *client,
bool pendingRemovalOnly = false);
// Same method as above, but with pendingRemovalOnly as true.
bool getBiggestClientPendingRemoval_l(int pid, MediaResource::Type type,
- MediaResource::SubType subType, std::shared_ptr<IResourceManagerClient> *client);
+ MediaResource::SubType subType, uid_t& uid,
+ std::shared_ptr<IResourceManagerClient> *client);
bool isCallingPriorityHigher_l(int callingPid, int pid);
// A helper function basically calls getLowestPriorityBiggestClient_l and add
// the result client to the given Vector.
void getClientForResource_l(int callingPid, const MediaResourceParcel *res,
+ PidUidVector* idList,
Vector<std::shared_ptr<IResourceManagerClient>> *clients);
void onFirstAdded(const MediaResourceParcel& res, const ResourceInfo& clientInfo);
@@ -171,6 +182,15 @@
void removeCookieAndUnlink_l(const std::shared_ptr<IResourceManagerClient>& client,
uintptr_t cookie);
+ // To increase/decrease the number of instances of a given resource
+ // associated with a client.
+ void increaseResourceInstanceCount(int64_t clientId, const std::string& name);
+ void decreaseResourceInstanceCount(int64_t clientId, const std::string& name);
+
+ void pushReclaimAtom(const ClientInfoParcel& clientInfo,
+ const Vector<std::shared_ptr<IResourceManagerClient>>& clients,
+ const PidUidVector& idList, bool reclaimed);
+
mutable Mutex mLock;
sp<ProcessInfoInterface> mProcessInfo;
sp<SystemCallbackInterface> mSystemCB;
@@ -191,6 +211,11 @@
static std::map<uintptr_t, sp<DeathNotifier> > sCookieToDeathNotifierMap
GUARDED_BY(sCookieLock);
std::shared_ptr<ResourceObserverService> mObserverService;
+
+ // List of active clients
+ std::set<int64_t> mClientIdSet;
+ // Map of resources (name) and number of concurrent instances
+ std::map<std::string, int> mConcurrentResourceCountMap;
};
// ----------------------------------------------------------------------------
diff --git a/services/mediaresourcemanager/aidl/android/media/ClientInfoParcel.aidl b/services/mediaresourcemanager/aidl/android/media/ClientInfoParcel.aidl
new file mode 100644
index 0000000..eb4bc42
--- /dev/null
+++ b/services/mediaresourcemanager/aidl/android/media/ClientInfoParcel.aidl
@@ -0,0 +1,44 @@
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+/**
+ * Description of a Client(codec) information.
+ *
+ * {@hide}
+ */
+parcelable ClientInfoParcel {
+ /**
+ * The PID of the client process.
+ */
+ int pid = -1;
+
+ /**
+ * The UID of the client process.
+ */
+ int uid = -1;
+
+ /**
+ * The ID of the client.
+ */
+ long id = 0;
+
+ /**
+ * Name of the resource associated with the client.
+ */
+ @utf8InCpp String name;
+}
diff --git a/services/mediaresourcemanager/aidl/android/media/IResourceManagerService.aidl b/services/mediaresourcemanager/aidl/android/media/IResourceManagerService.aidl
index 7a0a50f..30ad41b 100644
--- a/services/mediaresourcemanager/aidl/android/media/IResourceManagerService.aidl
+++ b/services/mediaresourcemanager/aidl/android/media/IResourceManagerService.aidl
@@ -19,6 +19,7 @@
import android.media.IResourceManagerClient;
import android.media.MediaResourceParcel;
import android.media.MediaResourcePolicyParcel;
+import android.media.ClientInfoParcel;
/**
* ResourceManagerService interface that keeps track of media resource
@@ -44,46 +45,40 @@
/**
* Add a client to a process with a list of resources.
*
- * @param pid pid of the client.
- * @param uid uid of the client.
- * @param clientId an identifier that uniquely identifies the client within the pid.
+ * @param clientInfo info of the calling client.
* @param client interface for the ResourceManagerService to call the client.
* @param resources an array of resources to be added.
*/
void addResource(
- int pid,
- int uid,
- long clientId,
+ in ClientInfoParcel clientInfo,
IResourceManagerClient client,
in MediaResourceParcel[] resources);
/**
* Remove the listed resources from a client.
*
- * @param pid pid from which the list of resources will be removed.
- * @param clientId clientId within the pid from which the list of resources will be removed.
+ * @param clientInfo info of the calling client.
* @param resources an array of resources to be removed from the client.
*/
- void removeResource(int pid, long clientId, in MediaResourceParcel[] resources);
+ void removeResource(in ClientInfoParcel clientInfo, in MediaResourceParcel[] resources);
/**
* Remove all resources from a client.
*
- * @param pid pid from which the client's resources will be removed.
- * @param clientId clientId within the pid that will be removed.
+ * @param clientInfo info of the calling client.
*/
- void removeClient(int pid, long clientId);
+ void removeClient(in ClientInfoParcel clientInfo);
/**
* Tries to reclaim resource from processes with lower priority than the
* calling process according to the requested resources.
*
- * @param callingPid pid of the calling process.
+ * @param clientInfo info of the calling client.
* @param resources an array of resources to be reclaimed.
*
* @return true if the reclaim was successful and false otherwise.
*/
- boolean reclaimResource(int callingPid, in MediaResourceParcel[] resources);
+ boolean reclaimResource(in ClientInfoParcel clientInfo, in MediaResourceParcel[] resources);
/**
* Override the pid of original calling process with the pid of the process
@@ -120,10 +115,9 @@
/**
* Mark a client for pending removal
*
- * @param pid pid from which the client's resources will be removed.
- * @param clientId clientId within the pid that will be removed.
+ * @param clientInfo info of the calling client.
*/
- void markClientForPendingRemoval(int pid, long clientId);
+ void markClientForPendingRemoval(in ClientInfoParcel clientInfo);
/**
* Reclaim resources from clients pending removal, if any.
diff --git a/services/mediaresourcemanager/fuzzer/Android.bp b/services/mediaresourcemanager/fuzzer/Android.bp
index 81c85e5..1d7f14f 100644
--- a/services/mediaresourcemanager/fuzzer/Android.bp
+++ b/services/mediaresourcemanager/fuzzer/Android.bp
@@ -41,6 +41,9 @@
"libbinder_ndk",
"libmedia",
"libutils",
+ "libstats_media_metrics",
+ "libstatspull",
+ "libstatssocket",
],
fuzz_config: {
cc: [
diff --git a/services/mediaresourcemanager/fuzzer/mediaresourcemanager_fuzzer.cpp b/services/mediaresourcemanager/fuzzer/mediaresourcemanager_fuzzer.cpp
index e4aaea0..5c2fef9 100644
--- a/services/mediaresourcemanager/fuzzer/mediaresourcemanager_fuzzer.cpp
+++ b/services/mediaresourcemanager/fuzzer/mediaresourcemanager_fuzzer.cpp
@@ -135,11 +135,15 @@
};
struct TestClient : public BnResourceManagerClient {
- TestClient(int pid, const shared_ptr<ResourceManagerService>& service)
- : mReclaimed(false), mPid(pid), mService(service) {}
+ TestClient(int pid, int uid, const shared_ptr<ResourceManagerService>& service)
+ : mReclaimed(false), mPid(pid), mUid(uid), mService(service) {}
Status reclaimResource(bool* aidlReturn) override {
- mService->removeClient(mPid, getId(ref<TestClient>()));
+ ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid),
+ .uid = static_cast<int32_t>(mUid),
+ .id = getId(ref<TestClient>()),
+ .name = ""};
+ mService->removeClient(clientInfo);
mReclaimed = true;
*aidlReturn = true;
return Status::ok();
@@ -155,6 +159,7 @@
private:
bool mReclaimed;
int mPid;
+ int mUid;
shared_ptr<ResourceManagerService> mService;
DISALLOW_EVIL_CONSTRUCTORS(TestClient);
};
@@ -176,9 +181,12 @@
static void* addResource(void* arg) {
resourceThreadArgs* tArgs = (resourceThreadArgs*)arg;
if (tArgs) {
+ ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(tArgs->pid),
+ .uid = static_cast<int32_t>(tArgs->uid),
+ .id = tArgs->testClientId,
+ .name = ""};
(tArgs->service)
- ->addResource(tArgs->pid, tArgs->uid, tArgs->testClientId, tArgs->testClient,
- tArgs->mediaResource);
+ ->addResource(clientInfo, tArgs->testClient, tArgs->mediaResource);
}
return nullptr;
}
@@ -187,10 +195,14 @@
resourceThreadArgs* tArgs = (resourceThreadArgs*)arg;
if (tArgs) {
bool result;
- (tArgs->service)->markClientForPendingRemoval(tArgs->pid, tArgs->testClientId);
- (tArgs->service)->removeResource(tArgs->pid, tArgs->testClientId, tArgs->mediaResource);
- (tArgs->service)->reclaimResource(tArgs->pid, tArgs->mediaResource, &result);
- (tArgs->service)->removeClient(tArgs->pid, tArgs->testClientId);
+ ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(tArgs->pid),
+ .uid = static_cast<int32_t>(tArgs->uid),
+ .id = tArgs->testClientId,
+ .name = ""};
+ (tArgs->service)->markClientForPendingRemoval(clientInfo);
+ (tArgs->service)->removeResource(clientInfo, tArgs->mediaResource);
+ (tArgs->service)->reclaimResource(clientInfo, tArgs->mediaResource, &result);
+ (tArgs->service)->removeClient(clientInfo);
(tArgs->service)->overridePid(tArgs->pid, tArgs->pid - 1);
}
return nullptr;
@@ -240,7 +252,8 @@
uint64_t mediaResourceValue = mFuzzedDataProvider->ConsumeIntegral<uint64_t>();
threadArgs[k].service = mService;
shared_ptr<IResourceManagerClient> testClient =
- ::ndk::SharedRefBase::make<TestClient>(threadArgs[k].pid, mService);
+ ::ndk::SharedRefBase::make<TestClient>(threadArgs[k].pid, threadArgs[k].uid,
+ mService);
threadArgs[k].testClient = testClient;
threadArgs[k].testClientId = getId(testClient);
mediaResource[k].push_back(MediaResource(static_cast<MedResType>(mediaResourceType),
@@ -258,7 +271,7 @@
// No resource was added with pid = 0
int32_t pidZero = 0;
shared_ptr<IResourceManagerClient> testClient =
- ::ndk::SharedRefBase::make<TestClient>(pidZero, mService);
+ ::ndk::SharedRefBase::make<TestClient>(pidZero, 0, mService);
int32_t mediaResourceType =
mFuzzedDataProvider->ConsumeIntegralInRange<int32_t>(kMinResourceType, kMaxResourceType);
int32_t mediaResourceSubType =
@@ -269,9 +282,13 @@
static_cast<MedResSubType>(mediaResourceSubType),
mediaResourceValue));
bool result;
- mService->reclaimResource(pidZero, mediaRes, &result);
- mService->removeResource(pidZero, getId(testClient), mediaRes);
- mService->removeClient(pidZero, getId(testClient));
+ ClientInfoParcel pidZeroClient{.pid = static_cast<int32_t>(pidZero),
+ .uid = static_cast<int32_t>(0),
+ .id = getId(testClient),
+ .name = ""};
+ mService->reclaimResource(pidZeroClient, mediaRes, &result);
+ mService->removeResource(pidZeroClient, mediaRes);
+ mService->removeClient(pidZeroClient);
}
void ResourceManagerServiceFuzzer::setServiceLog() {
diff --git a/services/mediaresourcemanager/test/Android.bp b/services/mediaresourcemanager/test/Android.bp
index 618626f..60bb8c3 100644
--- a/services/mediaresourcemanager/test/Android.bp
+++ b/services/mediaresourcemanager/test/Android.bp
@@ -19,6 +19,9 @@
"liblog",
"libmedia",
"libutils",
+ "libstats_media_metrics",
+ "libstatspull",
+ "libstatssocket",
],
include_dirs: [
"frameworks/av/include",
@@ -64,6 +67,9 @@
"liblog",
"libmedia",
"libutils",
+ "libstats_media_metrics",
+ "libstatspull",
+ "libstatssocket",
],
include_dirs: [
"frameworks/av/include",
diff --git a/services/mediaresourcemanager/test/ResourceManagerServiceTestUtils.h b/services/mediaresourcemanager/test/ResourceManagerServiceTestUtils.h
index 5bf44ce..8194e23 100644
--- a/services/mediaresourcemanager/test/ResourceManagerServiceTestUtils.h
+++ b/services/mediaresourcemanager/test/ResourceManagerServiceTestUtils.h
@@ -122,11 +122,15 @@
struct TestClient : public BnResourceManagerClient {
- TestClient(int pid, const std::shared_ptr<ResourceManagerService> &service)
- : mPid(pid), mService(service) {}
+ TestClient(int pid, int uid, const std::shared_ptr<ResourceManagerService> &service)
+ : mPid(pid), mUid(uid), mService(service) {}
Status reclaimResource(bool* _aidl_return) override {
- mService->removeClient(mPid, getId(ref<TestClient>()));
+ ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid),
+ .uid = static_cast<int32_t>(mUid),
+ .id = getId(ref<TestClient>()),
+ .name = "none"};
+ mService->removeClient(clientInfo);
mWasReclaimResourceCalled = true;
*_aidl_return = true;
return Status::ok();
@@ -148,6 +152,7 @@
private:
bool mWasReclaimResourceCalled = false;
int mPid;
+ int mUid;
std::shared_ptr<ResourceManagerService> mService;
DISALLOW_EVIL_CONSTRUCTORS(TestClient);
};
@@ -196,13 +201,13 @@
: mSystemCB(new TestSystemCallback()),
mService(::ndk::SharedRefBase::make<ResourceManagerService>(
new TestProcessInfo, mSystemCB)),
- mTestClient1(::ndk::SharedRefBase::make<TestClient>(kTestPid1, mService)),
- mTestClient2(::ndk::SharedRefBase::make<TestClient>(kTestPid2, mService)),
- mTestClient3(::ndk::SharedRefBase::make<TestClient>(kTestPid2, mService)) {
+ mTestClient1(::ndk::SharedRefBase::make<TestClient>(kTestPid1, kTestUid1, mService)),
+ mTestClient2(::ndk::SharedRefBase::make<TestClient>(kTestPid2, kTestUid2, mService)),
+ mTestClient3(::ndk::SharedRefBase::make<TestClient>(kTestPid2, kTestUid2, mService)) {
}
- std::shared_ptr<IResourceManagerClient> createTestClient(int pid) {
- return ::ndk::SharedRefBase::make<TestClient>(pid, mService);
+ std::shared_ptr<IResourceManagerClient> createTestClient(int pid, int uid) {
+ return ::ndk::SharedRefBase::make<TestClient>(pid, uid, mService);
}
sp<TestSystemCallback> mSystemCB;
diff --git a/services/mediaresourcemanager/test/ResourceManagerService_test.cpp b/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
index 8739c3b..41cccb8 100644
--- a/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
+++ b/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
@@ -98,24 +98,36 @@
// kTestPid1 mTestClient1
std::vector<MediaResourceParcel> resources1;
resources1.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
- mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+ ClientInfoParcel client1Info{.pid = static_cast<int32_t>(kTestPid1),
+ .uid = static_cast<int32_t>(kTestUid1),
+ .id = getId(mTestClient1),
+ .name = "none"};
+ mService->addResource(client1Info, mTestClient1, resources1);
resources1.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 200));
std::vector<MediaResourceParcel> resources11;
resources11.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 200));
- mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources11);
+ mService->addResource(client1Info, mTestClient1, resources11);
// kTestPid2 mTestClient2
std::vector<MediaResourceParcel> resources2;
resources2.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, 1));
resources2.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 300));
- mService->addResource(kTestPid2, kTestUid2, getId(mTestClient2), mTestClient2, resources2);
+ ClientInfoParcel client2Info{.pid = static_cast<int32_t>(kTestPid2),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = getId(mTestClient2),
+ .name = "none"};
+ mService->addResource(client2Info, mTestClient2, resources2);
// kTestPid2 mTestClient3
std::vector<MediaResourceParcel> resources3;
- mService->addResource(kTestPid2, kTestUid2, getId(mTestClient3), mTestClient3, resources3);
+ ClientInfoParcel client3Info{.pid = static_cast<int32_t>(kTestPid2),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = getId(mTestClient3),
+ .name = "none"};
+ mService->addResource(client3Info, mTestClient3, resources3);
resources3.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
resources3.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 100));
- mService->addResource(kTestPid2, kTestUid2, getId(mTestClient3), mTestClient3, resources3);
+ mService->addResource(client3Info, mTestClient3, resources3);
const PidResourceInfosMap &map = mService->mMap;
EXPECT_EQ(2u, map.size());
@@ -138,7 +150,11 @@
std::vector<MediaResourceParcel> resources1;
resources1.push_back(MediaResource(MediaResource::Type::kDrmSession, -100));
resources1.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, -100));
- mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+ ClientInfoParcel client1Info{.pid = static_cast<int32_t>(kTestPid1),
+ .uid = static_cast<int32_t>(kTestUid1),
+ .id = getId(mTestClient1),
+ .name = "none"};
+ mService->addResource(client1Info, mTestClient1, resources1);
// Expected result:
// 1) the client should have been added;
@@ -155,11 +171,11 @@
resources1.clear();
resources1.push_back(MediaResource(MediaResource::Type::kDrmSession, INT64_MAX));
resources1.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, INT64_MAX));
- mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+ mService->addResource(client1Info, mTestClient1, resources1);
resources1.clear();
resources1.push_back(MediaResource(MediaResource::Type::kDrmSession, 10));
resources1.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, 10));
- mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+ mService->addResource(client1Info, mTestClient1, resources1);
// Expected result:
// Both values should saturate to INT64_MAX
@@ -170,7 +186,7 @@
resources1.clear();
resources1.push_back(MediaResource(MediaResource::Type::kDrmSession, -10));
resources1.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, -10));
- mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+ mService->addResource(client1Info, mTestClient1, resources1);
// Expected result:
// 1) DrmSession resource should allow negative value addition, and value should drop accordingly
@@ -182,7 +198,7 @@
resources1.clear();
resources1.push_back(MediaResource(MediaResource::Type::kDrmSession, INT64_MIN));
expected.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, INT64_MIN));
- mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+ mService->addResource(client1Info, mTestClient1, resources1);
// Expected result:
// 1) DrmSession resource value should drop to 0, but the entry shouldn't be removed.
@@ -228,11 +244,15 @@
// kTestPid1 mTestClient1
std::vector<MediaResourceParcel> resources1;
resources1.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
- mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+ ClientInfoParcel client1Info{.pid = static_cast<int32_t>(kTestPid1),
+ .uid = static_cast<int32_t>(kTestUid1),
+ .id = getId(mTestClient1),
+ .name = "none"};
+ mService->addResource(client1Info, mTestClient1, resources1);
std::vector<MediaResourceParcel> resources11;
resources11.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 200));
- mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources11);
+ mService->addResource(client1Info, mTestClient1, resources11);
const PidResourceInfosMap &map = mService->mMap;
EXPECT_EQ(1u, map.size());
@@ -243,7 +263,7 @@
// test adding existing types to combine values
resources1.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 100));
- mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+ mService->addResource(client1Info, mTestClient1, resources1);
std::vector<MediaResourceParcel> expected;
expected.push_back(MediaResource(MediaResource::Type::kSecureCodec, 2));
@@ -253,7 +273,7 @@
// test adding new types (including types that differs only in subType)
resources11.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, 1));
resources11.push_back(MediaResource(MediaResource::Type::kSecureCodec, MediaResource::SubType::kVideoCodec, 1));
- mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources11);
+ mService->addResource(client1Info, mTestClient1, resources11);
expected.clear();
expected.push_back(MediaResource(MediaResource::Type::kSecureCodec, 2));
@@ -267,11 +287,15 @@
// kTestPid1 mTestClient1
std::vector<MediaResourceParcel> resources1;
resources1.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
- mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+ ClientInfoParcel client1Info{.pid = static_cast<int32_t>(kTestPid1),
+ .uid = static_cast<int32_t>(kTestUid1),
+ .id = getId(mTestClient1),
+ .name = "none"};
+ mService->addResource(client1Info, mTestClient1, resources1);
std::vector<MediaResourceParcel> resources11;
resources11.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 200));
- mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources11);
+ mService->addResource(client1Info, mTestClient1, resources11);
const PidResourceInfosMap &map = mService->mMap;
EXPECT_EQ(1u, map.size());
@@ -282,7 +306,7 @@
// test partial removal
resources11[0].value = 100;
- mService->removeResource(kTestPid1, getId(mTestClient1), resources11);
+ mService->removeResource(client1Info, resources11);
std::vector<MediaResourceParcel> expected;
expected.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
@@ -291,13 +315,13 @@
// test removal request with negative value, should be ignored
resources11[0].value = -10000;
- mService->removeResource(kTestPid1, getId(mTestClient1), resources11);
+ mService->removeResource(client1Info, resources11);
expectEqResourceInfo(infos1.valueFor(getId(mTestClient1)), kTestUid1, mTestClient1, expected);
// test complete removal with overshoot value
resources11[0].value = 1000;
- mService->removeResource(kTestPid1, getId(mTestClient1), resources11);
+ mService->removeResource(client1Info, resources11);
expected.clear();
expected.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
@@ -317,19 +341,35 @@
mService->mSupportsSecureWithNonSecureCodec = true;
// priority too low to reclaim resource
- CHECK_STATUS_FALSE(mService->reclaimResource(kLowPriorityPid, resources, &result));
+ ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(kLowPriorityPid),
+ .uid = static_cast<int32_t>(kTestUid1),
+ .id = 0,
+ .name = "none"};
+ CHECK_STATUS_FALSE(mService->reclaimResource(clientInfo, resources, &result));
// override Low Priority Pid with High Priority Pid
mService->overridePid(kLowPriorityPid, kHighPriorityPid);
- CHECK_STATUS_TRUE(mService->reclaimResource(kLowPriorityPid, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(clientInfo, resources, &result));
// restore Low Priority Pid
mService->overridePid(kLowPriorityPid, -1);
- CHECK_STATUS_FALSE(mService->reclaimResource(kLowPriorityPid, resources, &result));
+ CHECK_STATUS_FALSE(mService->reclaimResource(clientInfo, resources, &result));
}
}
void testMarkClientForPendingRemoval() {
+ ClientInfoParcel client1Info{.pid = static_cast<int32_t>(kTestPid1),
+ .uid = static_cast<int32_t>(kTestUid1),
+ .id = getId(mTestClient1),
+ .name = "none"};
+ ClientInfoParcel client2Info{.pid = static_cast<int32_t>(kTestPid2),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = getId(mTestClient2),
+ .name = "none"};
+ ClientInfoParcel client3Info{.pid = static_cast<int32_t>(kTestPid2),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = getId(mTestClient3),
+ .name = "none"};
{
addResource();
mService->mSupportsSecureWithNonSecureCodec = true;
@@ -338,24 +378,24 @@
resources.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, 1));
// Remove low priority clients
- mService->removeClient(kTestPid1, getId(mTestClient1));
+ mService->removeClient(client1Info);
// no lower priority client
- CHECK_STATUS_FALSE(mService->reclaimResource(kTestPid2, resources, &result));
+ CHECK_STATUS_FALSE(mService->reclaimResource(client2Info, resources, &result));
EXPECT_EQ(false, toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_EQ(false, toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_EQ(false, toTestClient(mTestClient3)->checkIfReclaimedAndReset());
- mService->markClientForPendingRemoval(kTestPid2, getId(mTestClient2));
+ mService->markClientForPendingRemoval(client2Info);
// client marked for pending removal from the same process got reclaimed
- CHECK_STATUS_TRUE(mService->reclaimResource(kTestPid2, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(client2Info, resources, &result));
EXPECT_EQ(false, toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_EQ(true, toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_EQ(false, toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// clean up client 3 which still left
- mService->removeClient(kTestPid2, getId(mTestClient3));
+ mService->removeClient(client3Info);
}
{
@@ -365,30 +405,30 @@
std::vector<MediaResourceParcel> resources;
resources.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, 1));
- mService->markClientForPendingRemoval(kTestPid2, getId(mTestClient2));
+ mService->markClientForPendingRemoval(client2Info);
// client marked for pending removal from the same process got reclaimed
// first, even though there are lower priority process
- CHECK_STATUS_TRUE(mService->reclaimResource(kTestPid2, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(client2Info, resources, &result));
EXPECT_EQ(false, toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_EQ(true, toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_EQ(false, toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// lower priority client got reclaimed
- CHECK_STATUS_TRUE(mService->reclaimResource(kTestPid2, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(client2Info, resources, &result));
EXPECT_EQ(true, toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_EQ(false, toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_EQ(false, toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// clean up client 3 which still left
- mService->removeClient(kTestPid2, getId(mTestClient3));
+ mService->removeClient(client3Info);
}
{
addResource();
mService->mSupportsSecureWithNonSecureCodec = true;
- mService->markClientForPendingRemoval(kTestPid2, getId(mTestClient2));
+ mService->markClientForPendingRemoval(client2Info);
// client marked for pending removal got reclaimed
EXPECT_TRUE(mService->reclaimResourcesFromClientsPendingRemoval(kTestPid2).isOk());
@@ -402,7 +442,7 @@
EXPECT_EQ(false, toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_EQ(false, toTestClient(mTestClient3)->checkIfReclaimedAndReset());
- mService->markClientForPendingRemoval(kTestPid2, getId(mTestClient3));
+ mService->markClientForPendingRemoval(client3Info);
// client marked for pending removal got reclaimed
EXPECT_TRUE(mService->reclaimResourcesFromClientsPendingRemoval(kTestPid2).isOk());
@@ -411,14 +451,18 @@
EXPECT_EQ(true, toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// clean up client 1 which still left
- mService->removeClient(kTestPid1, getId(mTestClient1));
+ mService->removeClient(client1Info);
}
}
void testRemoveClient() {
addResource();
- mService->removeClient(kTestPid2, getId(mTestClient2));
+ ClientInfoParcel client2Info{.pid = static_cast<int32_t>(kTestPid2),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = getId(mTestClient2),
+ .name = "none"};
+ mService->removeClient(client2Info);
const PidResourceInfosMap &map = mService->mMap;
EXPECT_EQ(2u, map.size());
@@ -437,11 +481,12 @@
MediaResource::SubType subType = MediaResource::SubType::kUnspecifiedSubType;
Vector<std::shared_ptr<IResourceManagerClient> > clients;
- EXPECT_FALSE(mService->getAllClients_l(kLowPriorityPid, type, subType, &clients));
+ PidUidVector idList;
+ EXPECT_FALSE(mService->getAllClients_l(kLowPriorityPid, type, subType, &idList, &clients));
// some higher priority process (e.g. kTestPid2) owns the resource, so getAllClients_l
// will fail.
- EXPECT_FALSE(mService->getAllClients_l(kMidPriorityPid, type, subType, &clients));
- EXPECT_TRUE(mService->getAllClients_l(kHighPriorityPid, type, subType, &clients));
+ EXPECT_FALSE(mService->getAllClients_l(kMidPriorityPid, type, subType, &idList, &clients));
+ EXPECT_TRUE(mService->getAllClients_l(kHighPriorityPid, type, subType, &idList, &clients));
EXPECT_EQ(2u, clients.size());
// (OK to require ordering in clients[], as the pid map is sorted)
@@ -454,6 +499,19 @@
resources.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
resources.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 150));
+ ClientInfoParcel lowPriorityClient{.pid = static_cast<int32_t>(kLowPriorityPid),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = 0,
+ .name = "none"};
+ ClientInfoParcel midPriorityClient{.pid = static_cast<int32_t>(kMidPriorityPid),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = 0,
+ .name = "none"};
+ ClientInfoParcel highPriorityClient{.pid = static_cast<int32_t>(kHighPriorityPid),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = 0,
+ .name = "none"};
+
// ### secure codec can't coexist and secure codec can coexist with non-secure codec ###
{
addResource();
@@ -461,23 +519,23 @@
mService->mSupportsSecureWithNonSecureCodec = true;
// priority too low
- CHECK_STATUS_FALSE(mService->reclaimResource(kLowPriorityPid, resources, &result));
- CHECK_STATUS_FALSE(mService->reclaimResource(kMidPriorityPid, resources, &result));
+ CHECK_STATUS_FALSE(mService->reclaimResource(lowPriorityClient, resources, &result));
+ CHECK_STATUS_FALSE(mService->reclaimResource(midPriorityClient, resources, &result));
// reclaim all secure codecs
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
EXPECT_TRUE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_TRUE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// call again should reclaim one largest graphic memory from lowest process
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
EXPECT_FALSE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_TRUE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// nothing left
- CHECK_STATUS_FALSE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_FALSE(mService->reclaimResource(highPriorityClient, resources, &result));
}
// ### secure codecs can't coexist and secure codec can't coexist with non-secure codec ###
@@ -487,17 +545,17 @@
mService->mSupportsSecureWithNonSecureCodec = false;
// priority too low
- CHECK_STATUS_FALSE(mService->reclaimResource(kLowPriorityPid, resources, &result));
- CHECK_STATUS_FALSE(mService->reclaimResource(kMidPriorityPid, resources, &result));
+ CHECK_STATUS_FALSE(mService->reclaimResource(lowPriorityClient, resources, &result));
+ CHECK_STATUS_FALSE(mService->reclaimResource(midPriorityClient, resources, &result));
// reclaim all secure and non-secure codecs
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
EXPECT_TRUE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_TRUE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_TRUE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// nothing left
- CHECK_STATUS_FALSE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_FALSE(mService->reclaimResource(highPriorityClient, resources, &result));
}
@@ -508,29 +566,29 @@
mService->mSupportsSecureWithNonSecureCodec = false;
// priority too low
- CHECK_STATUS_FALSE(mService->reclaimResource(kLowPriorityPid, resources, &result));
- CHECK_STATUS_FALSE(mService->reclaimResource(kMidPriorityPid, resources, &result));
+ CHECK_STATUS_FALSE(mService->reclaimResource(lowPriorityClient, resources, &result));
+ CHECK_STATUS_FALSE(mService->reclaimResource(midPriorityClient, resources, &result));
// reclaim all non-secure codecs
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
EXPECT_FALSE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_TRUE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// call again should reclaim one largest graphic memory from lowest process
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
EXPECT_TRUE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// call again should reclaim another largest graphic memory from lowest process
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
EXPECT_FALSE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_TRUE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// nothing left
- CHECK_STATUS_FALSE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_FALSE(mService->reclaimResource(highPriorityClient, resources, &result));
}
// ### secure codecs can coexist and secure codec can coexist with non-secure codec ###
@@ -540,28 +598,28 @@
mService->mSupportsSecureWithNonSecureCodec = true;
// priority too low
- CHECK_STATUS_FALSE(mService->reclaimResource(kLowPriorityPid, resources, &result));
+ CHECK_STATUS_FALSE(mService->reclaimResource(lowPriorityClient, resources, &result));
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
// one largest graphic memory from lowest process got reclaimed
EXPECT_TRUE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// call again should reclaim another graphic memory from lowest process
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
EXPECT_FALSE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_TRUE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// call again should reclaim another graphic memory from lowest process
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
EXPECT_FALSE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_TRUE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// nothing left
- CHECK_STATUS_FALSE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_FALSE(mService->reclaimResource(highPriorityClient, resources, &result));
}
// ### secure codecs can coexist and secure codec can coexist with non-secure codec ###
@@ -573,20 +631,20 @@
std::vector<MediaResourceParcel> resources;
resources.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
// secure codec from lowest process got reclaimed
EXPECT_TRUE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// call again should reclaim another secure codec from lowest process
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
EXPECT_FALSE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_TRUE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// no more secure codec, non-secure codec will be reclaimed.
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
EXPECT_FALSE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_TRUE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
@@ -598,29 +656,42 @@
resources.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, 1));
resources.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 150));
+ ClientInfoParcel lowPriorityClient{.pid = static_cast<int32_t>(kLowPriorityPid),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = 0,
+ .name = "none"};
+ ClientInfoParcel midPriorityClient{.pid = static_cast<int32_t>(kMidPriorityPid),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = 0,
+ .name = "none"};
+ ClientInfoParcel highPriorityClient{.pid = static_cast<int32_t>(kHighPriorityPid),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = 0,
+ .name = "none"};
+
// ### secure codec can't coexist with non-secure codec ###
{
addResource();
mService->mSupportsSecureWithNonSecureCodec = false;
// priority too low
- CHECK_STATUS_FALSE(mService->reclaimResource(kLowPriorityPid, resources, &result));
- CHECK_STATUS_FALSE(mService->reclaimResource(kMidPriorityPid, resources, &result));
+ CHECK_STATUS_FALSE(mService->reclaimResource(lowPriorityClient, resources, &result));
+ CHECK_STATUS_FALSE(mService->reclaimResource(midPriorityClient, resources, &result));
// reclaim all secure codecs
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
EXPECT_TRUE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_TRUE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// call again should reclaim one graphic memory from lowest process
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
EXPECT_FALSE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_TRUE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// nothing left
- CHECK_STATUS_FALSE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_FALSE(mService->reclaimResource(highPriorityClient, resources, &result));
}
@@ -630,28 +701,28 @@
mService->mSupportsSecureWithNonSecureCodec = true;
// priority too low
- CHECK_STATUS_FALSE(mService->reclaimResource(kLowPriorityPid, resources, &result));
+ CHECK_STATUS_FALSE(mService->reclaimResource(lowPriorityClient, resources, &result));
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
// one largest graphic memory from lowest process got reclaimed
EXPECT_TRUE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// call again should reclaim another graphic memory from lowest process
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
EXPECT_FALSE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_TRUE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// call again should reclaim another graphic memory from lowest process
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
EXPECT_FALSE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_TRUE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// nothing left
- CHECK_STATUS_FALSE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_FALSE(mService->reclaimResource(highPriorityClient, resources, &result));
}
// ### secure codec can coexist with non-secure codec ###
@@ -662,20 +733,24 @@
std::vector<MediaResourceParcel> resources;
resources.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, 1));
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
// one non secure codec from lowest process got reclaimed
EXPECT_FALSE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_TRUE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// no more non-secure codec, secure codec from lowest priority process will be reclaimed
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
EXPECT_TRUE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
EXPECT_FALSE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
// clean up client 3 which still left
- mService->removeClient(kTestPid2, getId(mTestClient3));
+ ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(kTestPid2),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = getId(mTestClient3),
+ .name = "none"};
+ mService->removeClient(clientInfo);
}
}
@@ -683,15 +758,16 @@
MediaResource::Type type = MediaResource::Type::kGraphicMemory;
MediaResource::SubType subType = MediaResource::SubType::kUnspecifiedSubType;
std::shared_ptr<IResourceManagerClient> client;
+ PidUidVector idList;
EXPECT_FALSE(mService->getLowestPriorityBiggestClient_l(kHighPriorityPid, type, subType,
- &client));
+ &idList, &client));
addResource();
EXPECT_FALSE(mService->getLowestPriorityBiggestClient_l(kLowPriorityPid, type, subType,
- &client));
+ &idList, &client));
EXPECT_TRUE(mService->getLowestPriorityBiggestClient_l(kHighPriorityPid, type, subType,
- &client));
+ &idList, &client));
// kTestPid1 is the lowest priority process with MediaResource::Type::kGraphicMemory.
// mTestClient1 has the largest MediaResource::Type::kGraphicMemory within kTestPid1.
@@ -737,33 +813,41 @@
// new client request should cause VIDEO_ON
std::vector<MediaResourceParcel> resources1;
resources1.push_back(MediaResource(MediaResource::Type::kBattery, MediaResource::SubType::kVideoCodec, 1));
- mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+ ClientInfoParcel client1Info{.pid = static_cast<int32_t>(kTestPid1),
+ .uid = static_cast<int32_t>(kTestUid1),
+ .id = getId(mTestClient1),
+ .name = "none"};
+ mService->addResource(client1Info, mTestClient1, resources1);
EXPECT_EQ(2u, mSystemCB->eventCount());
EXPECT_EQ(EventEntry({EventType::VIDEO_ON, kTestUid1}), mSystemCB->lastEvent());
// each client should only cause 1 VIDEO_ON
- mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+ mService->addResource(client1Info, mTestClient1, resources1);
EXPECT_EQ(2u, mSystemCB->eventCount());
// new client request should cause VIDEO_ON
std::vector<MediaResourceParcel> resources2;
resources2.push_back(MediaResource(MediaResource::Type::kBattery, MediaResource::SubType::kVideoCodec, 2));
- mService->addResource(kTestPid2, kTestUid2, getId(mTestClient2), mTestClient2, resources2);
+ ClientInfoParcel client2Info{.pid = static_cast<int32_t>(kTestPid2),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = getId(mTestClient2),
+ .name = "none"};
+ mService->addResource(client2Info, mTestClient2, resources2);
EXPECT_EQ(3u, mSystemCB->eventCount());
EXPECT_EQ(EventEntry({EventType::VIDEO_ON, kTestUid2}), mSystemCB->lastEvent());
// partially remove mTestClient1's request, shouldn't be any VIDEO_OFF
- mService->removeResource(kTestPid1, getId(mTestClient1), resources1);
+ mService->removeResource(client1Info, resources1);
EXPECT_EQ(3u, mSystemCB->eventCount());
// remove mTestClient1's request, should be VIDEO_OFF for kTestUid1
// (use resource2 to test removing more instances than previously requested)
- mService->removeResource(kTestPid1, getId(mTestClient1), resources2);
+ mService->removeResource(client1Info, resources2);
EXPECT_EQ(4u, mSystemCB->eventCount());
EXPECT_EQ(EventEntry({EventType::VIDEO_OFF, kTestUid1}), mSystemCB->lastEvent());
// remove mTestClient2, should be VIDEO_OFF for kTestUid2
- mService->removeClient(kTestPid2, getId(mTestClient2));
+ mService->removeClient(client2Info);
EXPECT_EQ(5u, mSystemCB->eventCount());
EXPECT_EQ(EventEntry({EventType::VIDEO_OFF, kTestUid2}), mSystemCB->lastEvent());
}
@@ -776,32 +860,40 @@
// new client request should cause CPUSET_ENABLE
std::vector<MediaResourceParcel> resources1;
resources1.push_back(MediaResource(MediaResource::Type::kCpuBoost, 1));
- mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+ ClientInfoParcel client1Info{.pid = static_cast<int32_t>(kTestPid1),
+ .uid = static_cast<int32_t>(kTestUid1),
+ .id = getId(mTestClient1),
+ .name = "none"};
+ mService->addResource(client1Info, mTestClient1, resources1);
EXPECT_EQ(2u, mSystemCB->eventCount());
EXPECT_EQ(EventType::CPUSET_ENABLE, mSystemCB->lastEventType());
// each client should only cause 1 CPUSET_ENABLE
- mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+ mService->addResource(client1Info, mTestClient1, resources1);
EXPECT_EQ(2u, mSystemCB->eventCount());
// new client request should cause CPUSET_ENABLE
std::vector<MediaResourceParcel> resources2;
resources2.push_back(MediaResource(MediaResource::Type::kCpuBoost, 2));
- mService->addResource(kTestPid2, kTestUid2, getId(mTestClient2), mTestClient2, resources2);
+ ClientInfoParcel client2Info{.pid = static_cast<int32_t>(kTestPid2),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = getId(mTestClient2),
+ .name = "none"};
+ mService->addResource(client2Info, mTestClient2, resources2);
EXPECT_EQ(3u, mSystemCB->eventCount());
EXPECT_EQ(EventType::CPUSET_ENABLE, mSystemCB->lastEventType());
// remove mTestClient2 should not cause CPUSET_DISABLE, mTestClient1 still active
- mService->removeClient(kTestPid2, getId(mTestClient2));
+ mService->removeClient(client2Info);
EXPECT_EQ(3u, mSystemCB->eventCount());
// remove 1 cpuboost from mTestClient1, should not be CPUSET_DISABLE (still 1 left)
- mService->removeResource(kTestPid1, getId(mTestClient1), resources1);
+ mService->removeResource(client1Info, resources1);
EXPECT_EQ(3u, mSystemCB->eventCount());
// remove 2 cpuboost from mTestClient1, should be CPUSET_DISABLE
// (use resource2 to test removing more than previously requested)
- mService->removeResource(kTestPid1, getId(mTestClient1), resources2);
+ mService->removeResource(client1Info, resources2);
EXPECT_EQ(4u, mSystemCB->eventCount());
EXPECT_EQ(EventType::CPUSET_DISABLE, mSystemCB->lastEventType());
}
@@ -814,22 +906,32 @@
std::vector<MediaResourceParcel> audioImageResources;
audioImageResources.push_back(createNonSecureAudioCodecResource());
audioImageResources.push_back(createNonSecureImageCodecResource());
- mService->addResource(kLowPriorityPid, kTestUid1, getId(audioImageTestClient),
- audioImageTestClient, audioImageResources);
+ ClientInfoParcel client1Info{.pid = static_cast<int32_t>(kLowPriorityPid),
+ .uid = static_cast<int32_t>(kTestUid1),
+ .id = getId(audioImageTestClient),
+ .name = "none"};
+ mService->addResource(client1Info, audioImageTestClient, audioImageResources);
// Fail to reclaim a video codec resource
std::vector<MediaResourceParcel> reclaimResources;
reclaimResources.push_back(createNonSecureVideoCodecResource());
- CHECK_STATUS_FALSE(mService->reclaimResource(kHighPriorityPid, reclaimResources, &result));
+ ClientInfoParcel highPriorityClient{.pid = static_cast<int32_t>(kHighPriorityPid),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = 0,
+ .name = "none"};
+ CHECK_STATUS_FALSE(mService->reclaimResource(highPriorityClient, reclaimResources, &result));
// Now add a video codec resource
std::vector<MediaResourceParcel> videoResources;
videoResources.push_back(createNonSecureVideoCodecResource());
- mService->addResource(kLowPriorityPid, kTestUid1, getId(videoTestClient), videoTestClient,
- videoResources);
+ ClientInfoParcel client2Info{.pid = static_cast<int32_t>(kLowPriorityPid),
+ .uid = static_cast<int32_t>(kTestUid1),
+ .id = getId(videoTestClient),
+ .name = "none"};
+ mService->addResource(client2Info, videoTestClient, videoResources);
// Verify that the newly-created video codec resource can be reclaimed
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, reclaimResources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, reclaimResources, &result));
// Verify that the audio and image resources are untouched
EXPECT_FALSE(toTestClient(audioImageTestClient)->checkIfReclaimedAndReset());
@@ -845,22 +947,32 @@
std::vector<MediaResourceParcel> videoImageResources;
videoImageResources.push_back(createNonSecureVideoCodecResource());
videoImageResources.push_back(createNonSecureImageCodecResource());
- mService->addResource(kLowPriorityPid, kTestUid1, getId(videoImageTestClient),
- videoImageTestClient, videoImageResources);
+ ClientInfoParcel client1Info{.pid = static_cast<int32_t>(kLowPriorityPid),
+ .uid = static_cast<int32_t>(kTestUid1),
+ .id = getId(videoImageTestClient),
+ .name = "none"};
+ mService->addResource(client1Info, videoImageTestClient, videoImageResources);
// Fail to reclaim an audio codec resource
std::vector<MediaResourceParcel> reclaimResources;
reclaimResources.push_back(createNonSecureAudioCodecResource());
- CHECK_STATUS_FALSE(mService->reclaimResource(kHighPriorityPid, reclaimResources, &result));
+ ClientInfoParcel highPriorityClient{.pid = static_cast<int32_t>(kHighPriorityPid),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = 0,
+ .name = "none"};
+ CHECK_STATUS_FALSE(mService->reclaimResource(highPriorityClient, reclaimResources, &result));
// Now add an audio codec resource
std::vector<MediaResourceParcel> audioResources;
audioResources.push_back(createNonSecureAudioCodecResource());
- mService->addResource(kLowPriorityPid, kTestUid2, getId(audioTestClient), audioTestClient,
- audioResources);
+ ClientInfoParcel client2Info{.pid = static_cast<int32_t>(kLowPriorityPid),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = getId(audioTestClient),
+ .name = "none"};
+ mService->addResource(client2Info, audioTestClient, audioResources);
// Verify that the newly-created audio codec resource can be reclaimed
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, reclaimResources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, reclaimResources, &result));
// Verify that the video and image resources are untouched
EXPECT_FALSE(toTestClient(videoImageTestClient)->checkIfReclaimedAndReset());
@@ -876,22 +988,32 @@
std::vector<MediaResourceParcel> videoAudioResources;
videoAudioResources.push_back(createNonSecureVideoCodecResource());
videoAudioResources.push_back(createNonSecureAudioCodecResource());
- mService->addResource(kLowPriorityPid, kTestUid1, getId(videoAudioTestClient),
- videoAudioTestClient, videoAudioResources);
+ ClientInfoParcel client1Info{.pid = static_cast<int32_t>(kLowPriorityPid),
+ .uid = static_cast<int32_t>(kTestUid1),
+ .id = getId(videoAudioTestClient),
+ .name = "none"};
+ mService->addResource(client1Info, videoAudioTestClient, videoAudioResources);
// Fail to reclaim an image codec resource
std::vector<MediaResourceParcel> reclaimResources;
reclaimResources.push_back(createNonSecureImageCodecResource());
- CHECK_STATUS_FALSE(mService->reclaimResource(kHighPriorityPid, reclaimResources, &result));
+ ClientInfoParcel highPriorityClient{.pid = static_cast<int32_t>(kHighPriorityPid),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = 0,
+ .name = "none"};
+ CHECK_STATUS_FALSE(mService->reclaimResource(highPriorityClient, reclaimResources, &result));
// Now add an image codec resource
std::vector<MediaResourceParcel> imageResources;
imageResources.push_back(createNonSecureImageCodecResource());
- mService->addResource(kLowPriorityPid, kTestUid2, getId(imageTestClient), imageTestClient,
- imageResources);
+ ClientInfoParcel client2Info{.pid = static_cast<int32_t>(kLowPriorityPid),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = getId(imageTestClient),
+ .name = "none"};
+ mService->addResource(client2Info, imageTestClient, imageResources);
// Verify that the newly-created image codec resource can be reclaimed
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, reclaimResources, &result));
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, reclaimResources, &result));
// Verify that the video and audio resources are untouched
EXPECT_FALSE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
@@ -901,20 +1023,27 @@
void testReclaimResources_whenPartialResourceMatch_reclaims() {
const int onlyUid = kTestUid1;
- const auto onlyClient = createTestClient(kLowPriorityPid);
+ const auto onlyClient = createTestClient(kLowPriorityPid, onlyUid);
std::vector<MediaResourceParcel> ownedResources;
ownedResources.push_back(createNonSecureVideoCodecResource());
ownedResources.push_back(createGraphicMemoryResource(100));
- mService->addResource(kLowPriorityPid, onlyUid, getId(onlyClient), onlyClient,
- ownedResources);
+ ClientInfoParcel onlyClientInfo{.pid = static_cast<int32_t>(kLowPriorityPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(onlyClient),
+ .name = "none"};
+ mService->addResource(onlyClientInfo, onlyClient, ownedResources);
// Reclaim an image codec instead of the video codec that is owned, but also reclaim
// graphics memory, which will trigger the reclaim.
std::vector<MediaResourceParcel> reclaimResources;
reclaimResources.push_back(createNonSecureImageCodecResource());
reclaimResources.push_back(createGraphicMemoryResource(100));
- CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, reclaimResources, &result));
+ ClientInfoParcel highPriorityClient{.pid = static_cast<int32_t>(kHighPriorityPid),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = 0,
+ .name = "none"};
+ CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, reclaimResources, &result));
// Verify that the video codec resources (including the needed graphic memory) is reclaimed
EXPECT_TRUE(toTestClient(onlyClient)->checkIfReclaimedAndReset());
@@ -926,200 +1055,278 @@
const int onlyUid = kTestUid1;
// secure video codec
- const auto smallSecureVideoMarkedClient = createTestClient(onlyPid);
- const auto largeSecureVideoMarkedClient = createTestClient(onlyPid);
- const auto largestSecureVideoActiveClient = createTestClient(onlyPid);
+ const auto smallSecureVideoMarkedClient = createTestClient(onlyPid, onlyUid);
+ const auto largeSecureVideoMarkedClient = createTestClient(onlyPid, onlyUid);
+ const auto largestSecureVideoActiveClient = createTestClient(onlyPid, onlyUid);
+ ClientInfoParcel clientA{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(smallSecureVideoMarkedClient),
+ .name = "none"};
+ ClientInfoParcel clientB{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(largeSecureVideoMarkedClient),
+ .name = "none"};
+ ClientInfoParcel clientC{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(largestSecureVideoActiveClient),
+ .name = "none"};
{
std::vector<MediaResourceParcel> resources;
resources.push_back(createSecureVideoCodecResource(1));
- mService->addResource(onlyPid, onlyUid, getId(smallSecureVideoMarkedClient),
- smallSecureVideoMarkedClient, resources);
+ mService->addResource(clientA, smallSecureVideoMarkedClient, resources);
resources.clear();
resources.push_back(createSecureVideoCodecResource(2));
- mService->addResource(onlyPid, onlyUid, getId(largeSecureVideoMarkedClient),
- largeSecureVideoMarkedClient, resources);
+ mService->addResource(clientB, largeSecureVideoMarkedClient, resources);
resources.clear();
resources.push_back(createSecureVideoCodecResource(3));
- mService->addResource(onlyPid, onlyUid, getId(largestSecureVideoActiveClient),
- largestSecureVideoActiveClient, resources);
+ mService->addResource(clientC, largestSecureVideoActiveClient, resources);
}
- mService->markClientForPendingRemoval(onlyPid, getId(smallSecureVideoMarkedClient));
- mService->markClientForPendingRemoval(onlyPid, getId(largeSecureVideoMarkedClient));
+ mService->markClientForPendingRemoval(clientA);
+ mService->markClientForPendingRemoval(clientB);
// don't mark the largest client
// non-secure video codec
- const auto smallNonSecureVideoMarkedClient = createTestClient(onlyPid);
- const auto largeNonSecureVideoMarkedClient = createTestClient(onlyPid);
- const auto largestNonSecureVideoActiveClient = createTestClient(onlyPid);
+ const auto smallNonSecureVideoMarkedClient = createTestClient(onlyPid, onlyUid);
+ const auto largeNonSecureVideoMarkedClient = createTestClient(onlyPid, onlyUid);
+ const auto largestNonSecureVideoActiveClient = createTestClient(onlyPid, onlyUid);
+ ClientInfoParcel clientD{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(smallNonSecureVideoMarkedClient),
+ .name = "none"};
+ ClientInfoParcel clientE{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(largeNonSecureVideoMarkedClient),
+ .name = "none"};
+ ClientInfoParcel clientF{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(largestNonSecureVideoActiveClient),
+ .name = "none"};
{
std::vector<MediaResourceParcel> resources;
resources.push_back(createNonSecureVideoCodecResource(1));
- mService->addResource(onlyPid, onlyUid, getId(smallNonSecureVideoMarkedClient),
- smallNonSecureVideoMarkedClient, resources);
+ mService->addResource(clientD, smallNonSecureVideoMarkedClient, resources);
resources.clear();
resources.push_back(createNonSecureVideoCodecResource(2));
- mService->addResource(onlyPid, onlyUid, getId(largeNonSecureVideoMarkedClient),
- largeNonSecureVideoMarkedClient, resources);
+ mService->addResource(clientE, largeNonSecureVideoMarkedClient, resources);
resources.clear();
resources.push_back(createNonSecureVideoCodecResource(3));
- mService->addResource(onlyPid, onlyUid, getId(largestNonSecureVideoActiveClient),
- largestNonSecureVideoActiveClient, resources);
+ mService->addResource(clientF, largestNonSecureVideoActiveClient, resources);
}
- mService->markClientForPendingRemoval(onlyPid, getId(smallNonSecureVideoMarkedClient));
- mService->markClientForPendingRemoval(onlyPid, getId(largeNonSecureVideoMarkedClient));
+ mService->markClientForPendingRemoval(clientD);
+ mService->markClientForPendingRemoval(clientE);
// don't mark the largest client
// secure audio codec
- const auto smallSecureAudioMarkedClient = createTestClient(onlyPid);
- const auto largeSecureAudioMarkedClient = createTestClient(onlyPid);
- const auto largestSecureAudioActiveClient = createTestClient(onlyPid);
+ const auto smallSecureAudioMarkedClient = createTestClient(onlyPid, onlyUid);
+ const auto largeSecureAudioMarkedClient = createTestClient(onlyPid, onlyUid);
+ const auto largestSecureAudioActiveClient = createTestClient(onlyPid, onlyUid);
+ ClientInfoParcel clientG{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(smallSecureAudioMarkedClient),
+ .name = "none"};
+ ClientInfoParcel clientH{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(largeSecureAudioMarkedClient),
+ .name = "none"};
+ ClientInfoParcel clientI{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(largestSecureVideoActiveClient),
+ .name = "none"};
{
std::vector<MediaResourceParcel> resources;
resources.push_back(createSecureAudioCodecResource(1));
- mService->addResource(onlyPid, onlyUid, getId(smallSecureAudioMarkedClient),
- smallSecureAudioMarkedClient, resources);
+ mService->addResource(clientG, smallSecureAudioMarkedClient, resources);
resources.clear();
resources.push_back(createSecureAudioCodecResource(2));
- mService->addResource(onlyPid, onlyUid, getId(largeSecureAudioMarkedClient),
- largeSecureAudioMarkedClient, resources);
+ mService->addResource(clientH, largeSecureAudioMarkedClient, resources);
resources.clear();
resources.push_back(createSecureAudioCodecResource(3));
- mService->addResource(onlyPid, onlyUid, getId(largestSecureVideoActiveClient),
- largestSecureVideoActiveClient, resources);
+ mService->addResource(clientI, largestSecureVideoActiveClient, resources);
}
- mService->markClientForPendingRemoval(onlyPid, getId(smallSecureAudioMarkedClient));
- mService->markClientForPendingRemoval(onlyPid, getId(largeSecureAudioMarkedClient));
+ mService->markClientForPendingRemoval(clientG);
+ mService->markClientForPendingRemoval(clientH);
// don't mark the largest client
// non-secure audio codec
- const auto smallNonSecureAudioMarkedClient = createTestClient(onlyPid);
- const auto largeNonSecureAudioMarkedClient = createTestClient(onlyPid);
- const auto largestNonSecureAudioActiveClient = createTestClient(onlyPid);
+ const auto smallNonSecureAudioMarkedClient = createTestClient(onlyPid, onlyUid);
+ const auto largeNonSecureAudioMarkedClient = createTestClient(onlyPid, onlyUid);
+ const auto largestNonSecureAudioActiveClient = createTestClient(onlyPid, onlyUid);
+ ClientInfoParcel clientJ{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(smallNonSecureAudioMarkedClient),
+ .name = "none"};
+ ClientInfoParcel clientK{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(largeNonSecureAudioMarkedClient),
+ .name = "none"};
+ ClientInfoParcel clientL{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(largestNonSecureAudioActiveClient),
+ .name = "none"};
{
std::vector<MediaResourceParcel> resources;
resources.push_back(createNonSecureAudioCodecResource(1));
- mService->addResource(onlyPid, onlyUid, getId(smallNonSecureAudioMarkedClient),
- smallNonSecureAudioMarkedClient, resources);
+ mService->addResource(clientJ, smallNonSecureAudioMarkedClient, resources);
resources.clear();
resources.push_back(createNonSecureAudioCodecResource(2));
- mService->addResource(onlyPid, onlyUid, getId(largeNonSecureAudioMarkedClient),
- largeNonSecureAudioMarkedClient, resources);
+ mService->addResource(clientK, largeNonSecureAudioMarkedClient, resources);
resources.clear();
resources.push_back(createNonSecureAudioCodecResource(3));
- mService->addResource(onlyPid, onlyUid, getId(largestNonSecureAudioActiveClient),
- largestNonSecureAudioActiveClient, resources);
+ mService->addResource(clientL, largestNonSecureAudioActiveClient, resources);
}
- mService->markClientForPendingRemoval(onlyPid, getId(smallNonSecureAudioMarkedClient));
- mService->markClientForPendingRemoval(onlyPid, getId(largeNonSecureAudioMarkedClient));
+ mService->markClientForPendingRemoval(clientJ);
+ mService->markClientForPendingRemoval(clientK);
// don't mark the largest client
// secure image codec
- const auto smallSecureImageMarkedClient = createTestClient(onlyPid);
- const auto largeSecureImageMarkedClient = createTestClient(onlyPid);
- const auto largestSecureImageActiveClient = createTestClient(onlyPid);
+ const auto smallSecureImageMarkedClient = createTestClient(onlyPid, onlyUid);
+ const auto largeSecureImageMarkedClient = createTestClient(onlyPid, onlyUid);
+ const auto largestSecureImageActiveClient = createTestClient(onlyPid, onlyUid);
+ ClientInfoParcel clientM{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(smallSecureImageMarkedClient),
+ .name = "none"};
+ ClientInfoParcel clientN{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(largeSecureImageMarkedClient),
+ .name = "none"};
+ ClientInfoParcel clientO{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(largestSecureImageActiveClient),
+ .name = "none"};
{
std::vector<MediaResourceParcel> resources;
resources.push_back(createSecureImageCodecResource(1));
- mService->addResource(onlyPid, onlyUid, getId(smallSecureImageMarkedClient),
- smallSecureImageMarkedClient, resources);
+ mService->addResource(clientM, smallSecureImageMarkedClient, resources);
resources.clear();
resources.push_back(createSecureImageCodecResource(2));
- mService->addResource(onlyPid, onlyUid, getId(largeSecureImageMarkedClient),
- largeSecureImageMarkedClient, resources);
+ mService->addResource(clientN, largeSecureImageMarkedClient, resources);
resources.clear();
resources.push_back(createSecureImageCodecResource(3));
- mService->addResource(onlyPid, onlyUid, getId(largestSecureImageActiveClient),
- largestSecureImageActiveClient, resources);
+ mService->addResource(clientO, largestSecureImageActiveClient, resources);
}
- mService->markClientForPendingRemoval(onlyPid, getId(smallSecureImageMarkedClient));
- mService->markClientForPendingRemoval(onlyPid, getId(largeSecureImageMarkedClient));
+ mService->markClientForPendingRemoval(clientM);
+ mService->markClientForPendingRemoval(clientN);
// don't mark the largest client
// non-secure image codec
- const auto smallNonSecureImageMarkedClient = createTestClient(onlyPid);
- const auto largeNonSecureImageMarkedClient = createTestClient(onlyPid);
- const auto largestNonSecureImageActiveClient = createTestClient(onlyPid);
+ const auto smallNonSecureImageMarkedClient = createTestClient(onlyPid, onlyUid);
+ const auto largeNonSecureImageMarkedClient = createTestClient(onlyPid, onlyUid);
+ const auto largestNonSecureImageActiveClient = createTestClient(onlyPid, onlyUid);
+ ClientInfoParcel clientP{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(smallNonSecureImageMarkedClient),
+ .name = "none"};
+ ClientInfoParcel clientQ{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(largeNonSecureImageMarkedClient),
+ .name = "none"};
+ ClientInfoParcel clientR{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(largestNonSecureImageActiveClient),
+ .name = "none"};
{
std::vector<MediaResourceParcel> resources;
resources.push_back(createNonSecureImageCodecResource(1));
- mService->addResource(onlyPid, onlyUid, getId(smallNonSecureImageMarkedClient),
- smallNonSecureImageMarkedClient, resources);
+ mService->addResource(clientP, smallNonSecureImageMarkedClient, resources);
resources.clear();
resources.push_back(createNonSecureImageCodecResource(2));
- mService->addResource(onlyPid, onlyUid, getId(largeNonSecureImageMarkedClient),
- largeNonSecureImageMarkedClient, resources);
+ mService->addResource(clientQ, largeNonSecureImageMarkedClient, resources);
resources.clear();
resources.push_back(createNonSecureImageCodecResource(3));
- mService->addResource(onlyPid, onlyUid, getId(largestNonSecureImageActiveClient),
- largestNonSecureImageActiveClient, resources);
+ mService->addResource(clientR, largestNonSecureImageActiveClient, resources);
}
- mService->markClientForPendingRemoval(onlyPid, getId(smallNonSecureImageMarkedClient));
- mService->markClientForPendingRemoval(onlyPid, getId(largeNonSecureImageMarkedClient));
+ mService->markClientForPendingRemoval(clientP);
+ mService->markClientForPendingRemoval(clientQ);
// don't mark the largest client
// graphic memory
- const auto smallGraphicMemoryMarkedClient = createTestClient(onlyPid);
- const auto largeGraphicMemoryMarkedClient = createTestClient(onlyPid);
- const auto largestGraphicMemoryActiveClient = createTestClient(onlyPid);
+ const auto smallGraphicMemoryMarkedClient = createTestClient(onlyPid, onlyUid);
+ const auto largeGraphicMemoryMarkedClient = createTestClient(onlyPid, onlyUid);
+ const auto largestGraphicMemoryActiveClient = createTestClient(onlyPid, onlyUid);
+ ClientInfoParcel clientS{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(smallGraphicMemoryMarkedClient),
+ .name = "none"};
+ ClientInfoParcel clientT{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(largeGraphicMemoryMarkedClient),
+ .name = "none"};
+ ClientInfoParcel clientU{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(largestGraphicMemoryActiveClient),
+ .name = "none"};
{
std::vector<MediaResourceParcel> resources;
resources.push_back(createGraphicMemoryResource(100));
- mService->addResource(onlyPid, onlyUid, getId(smallGraphicMemoryMarkedClient),
- smallGraphicMemoryMarkedClient, resources);
+ mService->addResource(clientS, smallGraphicMemoryMarkedClient, resources);
resources.clear();
resources.push_back(createGraphicMemoryResource(200));
- mService->addResource(onlyPid, onlyUid, getId(largeGraphicMemoryMarkedClient),
- largeGraphicMemoryMarkedClient, resources);
+ mService->addResource(clientT, largeGraphicMemoryMarkedClient, resources);
resources.clear();
resources.push_back(createGraphicMemoryResource(300));
- mService->addResource(onlyPid, onlyUid, getId(largestGraphicMemoryActiveClient),
- largestGraphicMemoryActiveClient, resources);
+ mService->addResource(clientU, largestGraphicMemoryActiveClient, resources);
}
- mService->markClientForPendingRemoval(onlyPid, getId(smallGraphicMemoryMarkedClient));
- mService->markClientForPendingRemoval(onlyPid, getId(largeGraphicMemoryMarkedClient));
+ mService->markClientForPendingRemoval(clientS);
+ mService->markClientForPendingRemoval(clientT);
// don't mark the largest client
// DRM session
- const auto smallDrmSessionMarkedClient = createTestClient(onlyPid);
- const auto largeDrmSessionMarkedClient = createTestClient(onlyPid);
- const auto largestDrmSessionActiveClient = createTestClient(onlyPid);
+ const auto smallDrmSessionMarkedClient = createTestClient(onlyPid, onlyUid);
+ const auto largeDrmSessionMarkedClient = createTestClient(onlyPid, onlyUid);
+ const auto largestDrmSessionActiveClient = createTestClient(onlyPid, onlyUid);
+ ClientInfoParcel clientV{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(smallDrmSessionMarkedClient),
+ .name = "none"};
+ ClientInfoParcel clientW{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(largeDrmSessionMarkedClient),
+ .name = "none"};
+ ClientInfoParcel clientX{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(largestDrmSessionActiveClient),
+ .name = "none"};
{
std::vector<MediaResourceParcel> resources;
resources.push_back(createDrmSessionResource(1));
- mService->addResource(onlyPid, onlyUid, getId(smallDrmSessionMarkedClient),
- smallDrmSessionMarkedClient, resources);
+ mService->addResource(clientV, smallDrmSessionMarkedClient, resources);
resources.clear();
resources.push_back(createDrmSessionResource(2));
- mService->addResource(onlyPid, onlyUid, getId(largeDrmSessionMarkedClient),
- largeDrmSessionMarkedClient, resources);
+ mService->addResource(clientW, largeDrmSessionMarkedClient, resources);
resources.clear();
resources.push_back(createDrmSessionResource(3));
- mService->addResource(onlyPid, onlyUid, getId(largestDrmSessionActiveClient),
- largestDrmSessionActiveClient, resources);
+ mService->addResource(clientX, largestDrmSessionActiveClient, resources);
}
- mService->markClientForPendingRemoval(onlyPid, getId(smallDrmSessionMarkedClient));
- mService->markClientForPendingRemoval(onlyPid, getId(largeDrmSessionMarkedClient));
+ mService->markClientForPendingRemoval(clientV);
+ mService->markClientForPendingRemoval(clientW);
// don't mark the largest client
// battery
- const auto batteryMarkedClient = createTestClient(onlyPid);
+ const auto batteryMarkedClient = createTestClient(onlyPid, onlyUid);
+ ClientInfoParcel clientY{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(batteryMarkedClient),
+ .name = "none"};
{
std::vector<MediaResourceParcel> resources;
resources.push_back(createBatteryResource());
- mService->addResource(onlyPid, onlyUid, getId(batteryMarkedClient),
- batteryMarkedClient, resources);
+ mService->addResource(clientY, batteryMarkedClient, resources);
}
- mService->markClientForPendingRemoval(onlyPid, getId(batteryMarkedClient));
+ mService->markClientForPendingRemoval(clientY);
// CPU boost
- const auto cpuBoostMarkedClient = createTestClient(onlyPid);
+ const auto cpuBoostMarkedClient = createTestClient(onlyPid, onlyUid);
+ ClientInfoParcel clientZ{.pid = static_cast<int32_t>(onlyPid),
+ .uid = static_cast<int32_t>(onlyUid),
+ .id = getId(cpuBoostMarkedClient),
+ .name = "none"};
{
std::vector<MediaResourceParcel> resources;
resources.push_back(createCpuBoostResource());
- mService->addResource(onlyPid, onlyUid, getId(cpuBoostMarkedClient),
- cpuBoostMarkedClient, resources);
+ mService->addResource(clientZ, cpuBoostMarkedClient, resources);
}
- mService->markClientForPendingRemoval(onlyPid, getId(cpuBoostMarkedClient));
+ mService->markClientForPendingRemoval(clientZ);
// now we expect that we only reclaim resources from the biggest marked client
EXPECT_TRUE(mService->reclaimResourcesFromClientsPendingRemoval(onlyPid).isOk());
diff --git a/services/mediaresourcemanager/test/ResourceObserverService_test.cpp b/services/mediaresourcemanager/test/ResourceObserverService_test.cpp
index 003569d..a0d728c 100644
--- a/services/mediaresourcemanager/test/ResourceObserverService_test.cpp
+++ b/services/mediaresourcemanager/test/ResourceObserverService_test.cpp
@@ -251,17 +251,31 @@
observables3 = {{MediaObservableType::kVideoSecureCodec, 1},
{MediaObservableType::kVideoNonSecureCodec, 1}};
+ ClientInfoParcel client1Info{.pid = static_cast<int32_t>(kTestPid1),
+ .uid = static_cast<int32_t>(kTestUid1),
+ .id = getId(mTestClient1),
+ .name = "none"};
+
+ ClientInfoParcel client2Info{.pid = static_cast<int32_t>(kTestPid2),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = getId(mTestClient2),
+ .name = "none"};
+
+ ClientInfoParcel client3Info{.pid = static_cast<int32_t>(kTestPid2),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = getId(mTestClient3),
+ .name = "none"};
std::vector<MediaResourceParcel> resources;
// Add secure video codec.
resources = {createSecureVideoCodecResource()};
- mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources);
+ mService->addResource(client1Info, mTestClient1, resources);
EXPECT_EQ(mTestObserver1->pop(), EventTracker::Busy(kTestUid1, kTestPid1, observables1));
EXPECT_EQ(mTestObserver2->pop(), EventTracker::NoEvent);
EXPECT_EQ(mTestObserver3->pop(), EventTracker::Busy(kTestUid1, kTestPid1, observables1));
// Add non-secure video codec.
resources = {createNonSecureVideoCodecResource()};
- mService->addResource(kTestPid2, kTestUid2, getId(mTestClient2), mTestClient2, resources);
+ mService->addResource(client2Info, mTestClient2, resources);
EXPECT_EQ(mTestObserver1->pop(), EventTracker::NoEvent);
EXPECT_EQ(mTestObserver2->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables2));
EXPECT_EQ(mTestObserver3->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables2));
@@ -269,7 +283,7 @@
// Add secure & non-secure video codecs.
resources = {createSecureVideoCodecResource(),
createNonSecureVideoCodecResource()};
- mService->addResource(kTestPid2, kTestUid2, getId(mTestClient3), mTestClient3, resources);
+ mService->addResource(client3Info, mTestClient3, resources);
EXPECT_EQ(mTestObserver1->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables1));
EXPECT_EQ(mTestObserver2->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables2));
EXPECT_EQ(mTestObserver3->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables3));
@@ -277,7 +291,7 @@
// Add additional audio codecs, should be ignored.
resources.push_back(createSecureAudioCodecResource());
resources.push_back(createNonSecureAudioCodecResource());
- mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources);
+ mService->addResource(client1Info, mTestClient1, resources);
EXPECT_EQ(mTestObserver1->pop(), EventTracker::Busy(kTestUid1, kTestPid1, observables1));
EXPECT_EQ(mTestObserver2->pop(), EventTracker::Busy(kTestUid1, kTestPid1, observables2));
EXPECT_EQ(mTestObserver3->pop(), EventTracker::Busy(kTestUid1, kTestPid1, observables3));
@@ -303,7 +317,11 @@
observables2 = {{MediaObservableType::kVideoNonSecureCodec, 3}};
observables3 = {{MediaObservableType::kVideoSecureCodec, 2},
{MediaObservableType::kVideoNonSecureCodec, 3}};
- mService->addResource(kTestPid2, kTestUid2, getId(mTestClient3), mTestClient3, resources);
+ ClientInfoParcel client3Info{.pid = static_cast<int32_t>(kTestPid2),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = getId(mTestClient3),
+ .name = "none"};
+ mService->addResource(client3Info, mTestClient3, resources);
EXPECT_EQ(mTestObserver1->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables1));
EXPECT_EQ(mTestObserver2->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables2));
EXPECT_EQ(mTestObserver3->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables3));
@@ -318,47 +336,61 @@
observables3 = {{MediaObservableType::kVideoSecureCodec, 1},
{MediaObservableType::kVideoNonSecureCodec, 1}};
+ ClientInfoParcel client1Info{.pid = static_cast<int32_t>(kTestPid1),
+ .uid = static_cast<int32_t>(kTestUid1),
+ .id = getId(mTestClient1),
+ .name = "none"};
+
+ ClientInfoParcel client2Info{.pid = static_cast<int32_t>(kTestPid2),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = getId(mTestClient2),
+ .name = "none"};
+
+ ClientInfoParcel client3Info{.pid = static_cast<int32_t>(kTestPid2),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = getId(mTestClient3),
+ .name = "none"};
std::vector<MediaResourceParcel> resources;
// Add secure video codec to client1.
resources = {createSecureVideoCodecResource()};
- mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources);
+ mService->addResource(client1Info, mTestClient1, resources);
EXPECT_EQ(mTestObserver1->pop(), EventTracker::Busy(kTestUid1, kTestPid1, observables1));
EXPECT_EQ(mTestObserver2->pop(), EventTracker::NoEvent);
EXPECT_EQ(mTestObserver3->pop(), EventTracker::Busy(kTestUid1, kTestPid1, observables1));
// Remove secure video codec. observer 1&3 should receive updates.
- mService->removeResource(kTestPid1, getId(mTestClient1), resources);
+ mService->removeResource(client1Info, resources);
EXPECT_EQ(mTestObserver1->pop(), EventTracker::Idle(kTestUid1, kTestPid1, observables1));
EXPECT_EQ(mTestObserver2->pop(), EventTracker::NoEvent);
EXPECT_EQ(mTestObserver3->pop(), EventTracker::Idle(kTestUid1, kTestPid1, observables1));
// Remove secure video codec again, should have no event.
- mService->removeResource(kTestPid1, getId(mTestClient1), resources);
+ mService->removeResource(client1Info, resources);
EXPECT_EQ(mTestObserver1->pop(), EventTracker::NoEvent);
EXPECT_EQ(mTestObserver2->pop(), EventTracker::NoEvent);
EXPECT_EQ(mTestObserver3->pop(), EventTracker::NoEvent);
// Remove client1, should have no event.
- mService->removeClient(kTestPid1, getId(mTestClient1));
+ mService->removeClient(client1Info);
EXPECT_EQ(mTestObserver1->pop(), EventTracker::NoEvent);
EXPECT_EQ(mTestObserver2->pop(), EventTracker::NoEvent);
EXPECT_EQ(mTestObserver3->pop(), EventTracker::NoEvent);
// Add non-secure video codec to client2.
resources = {createNonSecureVideoCodecResource()};
- mService->addResource(kTestPid2, kTestUid2, getId(mTestClient2), mTestClient2, resources);
+ mService->addResource(client2Info, mTestClient2, resources);
EXPECT_EQ(mTestObserver1->pop(), EventTracker::NoEvent);
EXPECT_EQ(mTestObserver2->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables2));
EXPECT_EQ(mTestObserver3->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables2));
// Remove client2, observer 2&3 should receive updates.
- mService->removeClient(kTestPid2, getId(mTestClient2));
+ mService->removeClient(client2Info);
EXPECT_EQ(mTestObserver1->pop(), EventTracker::NoEvent);
EXPECT_EQ(mTestObserver2->pop(), EventTracker::Idle(kTestUid2, kTestPid2, observables2));
EXPECT_EQ(mTestObserver3->pop(), EventTracker::Idle(kTestUid2, kTestPid2, observables2));
// Remove non-secure codec after client2 removed, should have no event.
- mService->removeResource(kTestPid2, getId(mTestClient2), resources);
+ mService->removeResource(client2Info, resources);
EXPECT_EQ(mTestObserver1->pop(), EventTracker::NoEvent);
EXPECT_EQ(mTestObserver2->pop(), EventTracker::NoEvent);
EXPECT_EQ(mTestObserver3->pop(), EventTracker::NoEvent);
// Remove client2 again, should have no event.
- mService->removeClient(kTestPid2, getId(mTestClient2));
+ mService->removeClient(client2Info);
EXPECT_EQ(mTestObserver1->pop(), EventTracker::NoEvent);
EXPECT_EQ(mTestObserver2->pop(), EventTracker::NoEvent);
EXPECT_EQ(mTestObserver3->pop(), EventTracker::NoEvent);
@@ -368,13 +400,13 @@
createNonSecureVideoCodecResource(),
createSecureAudioCodecResource(),
createNonSecureAudioCodecResource()};
- mService->addResource(kTestPid2, kTestUid2, getId(mTestClient3), mTestClient3, resources);
+ mService->addResource(client3Info, mTestClient3, resources);
EXPECT_EQ(mTestObserver1->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables1));
EXPECT_EQ(mTestObserver2->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables2));
EXPECT_EQ(mTestObserver3->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables3));
// Remove one audio codec, should have no event.
resources = {createSecureAudioCodecResource()};
- mService->removeResource(kTestPid2, getId(mTestClient3), resources);
+ mService->removeResource(client3Info, resources);
EXPECT_EQ(mTestObserver1->pop(), EventTracker::NoEvent);
EXPECT_EQ(mTestObserver2->pop(), EventTracker::NoEvent);
EXPECT_EQ(mTestObserver3->pop(), EventTracker::NoEvent);
@@ -382,12 +414,12 @@
// removal should be reported.
resources = {createNonSecureAudioCodecResource(),
createSecureVideoCodecResource()};
- mService->removeResource(kTestPid2, getId(mTestClient3), resources);
+ mService->removeResource(client3Info, resources);
EXPECT_EQ(mTestObserver1->pop(), EventTracker::Idle(kTestUid2, kTestPid2, observables1));
EXPECT_EQ(mTestObserver2->pop(), EventTracker::NoEvent);
EXPECT_EQ(mTestObserver3->pop(), EventTracker::Idle(kTestUid2, kTestPid2, observables1));
// Remove client3 entirely. Non-secure video codec removal should be reported.
- mService->removeClient(kTestPid2, getId(mTestClient3));
+ mService->removeClient(client3Info);
EXPECT_EQ(mTestObserver1->pop(), EventTracker::NoEvent);
EXPECT_EQ(mTestObserver2->pop(), EventTracker::Idle(kTestUid2, kTestPid2, observables2));
EXPECT_EQ(mTestObserver3->pop(), EventTracker::Idle(kTestUid2, kTestPid2, observables2));
@@ -410,7 +442,12 @@
createNonSecureVideoCodecResource(4),
createSecureAudioCodecResource(),
createNonSecureAudioCodecResource()};
- mService->addResource(kTestPid2, kTestUid2, getId(mTestClient3), mTestClient3, resources);
+
+ ClientInfoParcel client3Info{.pid = static_cast<int32_t>(kTestPid2),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = getId(mTestClient3),
+ .name = "none"};
+ mService->addResource(client3Info, mTestClient3, resources);
observables1 = {{MediaObservableType::kVideoSecureCodec, 1}};
observables2 = {{MediaObservableType::kVideoNonSecureCodec, 4}};
observables3 = {{MediaObservableType::kVideoSecureCodec, 1},
@@ -424,7 +461,7 @@
createSecureVideoCodecResource(),
createSecureVideoCodecResource(),
createNonSecureVideoCodecResource(2)};
- mService->removeResource(kTestPid2, getId(mTestClient3), resources);
+ mService->removeResource(client3Info, resources);
observables1 = {{MediaObservableType::kVideoSecureCodec, 1}};
observables2 = {{MediaObservableType::kVideoNonSecureCodec, 2}};
observables3 = {{MediaObservableType::kVideoSecureCodec, 1},
@@ -433,7 +470,7 @@
EXPECT_EQ(mTestObserver2->pop(), EventTracker::Idle(kTestUid2, kTestPid2, observables2));
EXPECT_EQ(mTestObserver3->pop(), EventTracker::Idle(kTestUid2, kTestPid2, observables3));
// Remove client3 entirely. 2 non-secure video codecs removal should be reported.
- mService->removeClient(kTestPid2, getId(mTestClient3));
+ mService->removeClient(client3Info);
EXPECT_EQ(mTestObserver1->pop(), EventTracker::NoEvent);
EXPECT_EQ(mTestObserver2->pop(), EventTracker::Idle(kTestUid2, kTestPid2, observables2));
EXPECT_EQ(mTestObserver3->pop(), EventTracker::Idle(kTestUid2, kTestPid2, observables2));
@@ -465,13 +502,27 @@
// Add secure & non-secure video codecs.
resources = {createSecureVideoCodecResource(),
createNonSecureVideoCodecResource()};
- mService->addResource(kTestPid2, kTestUid2, getId(mTestClient3), mTestClient3, resources);
+ ClientInfoParcel client1Info{.pid = static_cast<int32_t>(kTestPid1),
+ .uid = static_cast<int32_t>(kTestUid1),
+ .id = getId(mTestClient1),
+ .name = "none"};
+
+ ClientInfoParcel client2Info{.pid = static_cast<int32_t>(kTestPid2),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = getId(mTestClient2),
+ .name = "none"};
+
+ ClientInfoParcel client3Info{.pid = static_cast<int32_t>(kTestPid2),
+ .uid = static_cast<int32_t>(kTestUid2),
+ .id = getId(mTestClient3),
+ .name = "none"};
+ mService->addResource(client3Info, mTestClient3, resources);
EXPECT_EQ(mTestObserver1->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables1));
EXPECT_EQ(mTestObserver2->pop(), EventTracker::NoEvent);
EXPECT_EQ(mTestObserver3->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables2));
// Remove secure & non-secure video codecs.
- mService->removeResource(kTestPid2, getId(mTestClient3), resources);
+ mService->removeResource(client3Info, resources);
EXPECT_EQ(mTestObserver1->pop(), EventTracker::NoEvent);
EXPECT_EQ(mTestObserver2->pop(), EventTracker::Idle(kTestUid2, kTestPid2, observables2));
EXPECT_EQ(mTestObserver3->pop(), EventTracker::Idle(kTestUid2, kTestPid2, observables1));