Merge "APM clear AS routing cache on output activity with preferred device"
diff --git a/drm/libmediadrm/DrmHalAidl.cpp b/drm/libmediadrm/DrmHalAidl.cpp
index c369529..1844acb 100644
--- a/drm/libmediadrm/DrmHalAidl.cpp
+++ b/drm/libmediadrm/DrmHalAidl.cpp
@@ -393,7 +393,8 @@
// DrmHalAidl methods
DrmHalAidl::DrmHalAidl()
- : mListener(::ndk::SharedRefBase::make<DrmHalListener>(&mMetrics)),
+ : mMetrics(std::make_shared<MediaDrmMetrics>()),
+ mListener(::ndk::SharedRefBase::make<DrmHalListener>(mMetrics)),
mFactories(DrmUtils::makeDrmFactoriesAidl()),
mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT) {}
@@ -462,8 +463,8 @@
Uuid uuidAidl = DrmUtils::toAidlUuid(uuid);
std::string appPackageNameAidl = toStdString(appPackageName);
std::shared_ptr<IDrmPluginAidl> pluginAidl;
- mMetrics.SetAppPackageName(appPackageName);
- mMetrics.SetAppUid(AIBinder_getCallingUid());
+ mMetrics->SetAppPackageName(appPackageName);
+ mMetrics->SetAppUid(AIBinder_getCallingUid());
for (ssize_t i = mFactories.size() - 1; i >= 0; i--) {
::ndk::ScopedAStatus status =
mFactories[i]->createDrmPlugin(uuidAidl, appPackageNameAidl, &pluginAidl);
@@ -539,10 +540,10 @@
AIBinder_getCallingPid(), std::static_pointer_cast<IResourceManagerClient>(client),
sessionId);
mOpenSessions.push_back(client);
- mMetrics.SetSessionStart(sessionId);
+ mMetrics->SetSessionStart(sessionId);
}
- mMetrics.mOpenSessionCounter.Increment(err);
+ mMetrics->mOpenSessionCounter.Increment(err);
return err;
}
@@ -562,10 +563,10 @@
}
}
- mMetrics.SetSessionEnd(sessionId);
+ mMetrics->SetSessionEnd(sessionId);
}
- mMetrics.mCloseSessionCounter.Increment(response);
+ mMetrics->mCloseSessionCounter.Increment(response);
return response;
}
@@ -577,7 +578,7 @@
DrmPlugin::KeyRequestType* keyRequestType) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
- EventTimer<status_t> keyRequestTimer(&mMetrics.mGetKeyRequestTimeUs);
+ EventTimer<status_t> keyRequestTimer(&mMetrics->mGetKeyRequestTimeUs);
DrmSessionManager::Instance()->useSession(sessionId);
@@ -618,7 +619,7 @@
Vector<uint8_t>& keySetId) {
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
- EventTimer<status_t> keyResponseTimer(&mMetrics.mProvideKeyResponseTimeUs);
+ EventTimer<status_t> keyResponseTimer(&mMetrics->mProvideKeyResponseTimeUs);
DrmSessionManager::Instance()->useSession(sessionId);
@@ -687,7 +688,7 @@
defaultUrl = toString8(requestAidl.defaultUrl);
err = statusAidlToDrmStatus(status);
- mMetrics.mGetProvisionRequestCounter.Increment(err);
+ mMetrics->mGetProvisionRequestCounter.Increment(err);
return err;
}
@@ -704,7 +705,7 @@
certificate = toVector(result.certificate);
wrappedKey = toVector(result.wrappedKey);
err = statusAidlToDrmStatus(status);
- mMetrics.mProvideProvisionResponseCounter.Increment(err);
+ mMetrics->mProvideProvisionResponseCounter.Increment(err);
return err;
}
@@ -914,7 +915,7 @@
value = toVector(result);
err = statusAidlToDrmStatus(status);
if (name == kPropertyDeviceUniqueId) {
- mMetrics.mGetDeviceUniqueIdCounter.Increment(err);
+ mMetrics->mGetDeviceUniqueIdCounter.Increment(err);
}
return err;
}
@@ -940,7 +941,7 @@
if (consumer == nullptr) {
return DrmStatus(UNEXPECTED_NULL);
}
- consumer->consumeFrameworkMetrics(mMetrics);
+ consumer->consumeFrameworkMetrics(*mMetrics.get());
// Append vendor metrics if they are supported.
@@ -1146,7 +1147,7 @@
getPropertyByteArrayInternal(String8("metrics"), metricsVector) == OK) {
metricsString = toBase64StringNoPad(metricsVector.array(), metricsVector.size());
status_t res = android::reportDrmPluginMetrics(metricsString, vendor, description,
- mMetrics.GetAppUid());
+ mMetrics->GetAppUid());
if (res != OK) {
ALOGE("Metrics were retrieved but could not be reported: %d", res);
}
@@ -1156,7 +1157,7 @@
std::string DrmHalAidl::reportFrameworkMetrics(const std::string& pluginMetrics) const {
mediametrics_handle_t item(mediametrics_create("mediadrm"));
- mediametrics_setUid(item, mMetrics.GetAppUid());
+ mediametrics_setUid(item, mMetrics->GetAppUid());
String8 vendor;
String8 description;
status_t result = getPropertyStringInternal(String8("vendor"), vendor);
@@ -1173,7 +1174,7 @@
}
std::string serializedMetrics;
- result = mMetrics.GetSerializedMetrics(&serializedMetrics);
+ result = mMetrics->GetSerializedMetrics(&serializedMetrics);
if (result != OK) {
ALOGE("Failed to serialize framework metrics: %d", result);
}
diff --git a/drm/libmediadrm/DrmHalListener.cpp b/drm/libmediadrm/DrmHalListener.cpp
index cfcf475..4e868ac 100644
--- a/drm/libmediadrm/DrmHalListener.cpp
+++ b/drm/libmediadrm/DrmHalListener.cpp
@@ -37,12 +37,12 @@
return vec;
}
-DrmHalListener::DrmHalListener(MediaDrmMetrics* metrics)
+DrmHalListener::DrmHalListener(const std::shared_ptr<MediaDrmMetrics>& metrics)
: mMetrics(metrics) {}
DrmHalListener::~DrmHalListener() {}
-void DrmHalListener::setListener(sp<IDrmClient> listener) {
+void DrmHalListener::setListener(const sp<IDrmClient>& listener) {
Mutex::Autolock lock(mEventLock);
mListener = listener;
}
diff --git a/drm/libmediadrm/include/mediadrm/DrmHalAidl.h b/drm/libmediadrm/include/mediadrm/DrmHalAidl.h
index e0b8341..a81b312 100644
--- a/drm/libmediadrm/include/mediadrm/DrmHalAidl.h
+++ b/drm/libmediadrm/include/mediadrm/DrmHalAidl.h
@@ -123,7 +123,7 @@
::ndk::ScopedAStatus onSessionLostState(const std::vector<uint8_t>& in_sessionId);
private:
static Mutex mLock;
- mutable MediaDrmMetrics mMetrics;
+ std::shared_ptr<MediaDrmMetrics> mMetrics;
std::shared_ptr<DrmHalListener> mListener;
const std::vector<std::shared_ptr<IDrmFactoryAidl>> mFactories;
std::shared_ptr<IDrmPluginAidl> mPlugin;
diff --git a/drm/libmediadrm/include/mediadrm/DrmHalListener.h b/drm/libmediadrm/include/mediadrm/DrmHalListener.h
index 22361ad..0eed929 100644
--- a/drm/libmediadrm/include/mediadrm/DrmHalListener.h
+++ b/drm/libmediadrm/include/mediadrm/DrmHalListener.h
@@ -27,7 +27,7 @@
namespace android {
struct DrmHalListener : public BnDrmPluginListener {
- explicit DrmHalListener(MediaDrmMetrics* mMetrics);
+ explicit DrmHalListener(const std::shared_ptr<MediaDrmMetrics>& in_metrics);
~DrmHalListener();
::ndk::ScopedAStatus onEvent(EventTypeAidl in_eventType,
const std::vector<uint8_t>& in_sessionId,
@@ -38,9 +38,9 @@
const std::vector<KeyStatusAidl>& in_keyStatusList,
bool in_hasNewUsableKey);
::ndk::ScopedAStatus onSessionLostState(const std::vector<uint8_t>& in_sessionId);
- void setListener(sp<IDrmClient> listener);
+ void setListener(const sp<IDrmClient>& listener);
private:
- mutable MediaDrmMetrics* mMetrics;
+ std::shared_ptr<MediaDrmMetrics> mMetrics;
sp<IDrmClient> mListener;
mutable Mutex mEventLock;
mutable Mutex mNotifyLock;
diff --git a/media/codec2/components/aom/C2SoftAomEnc.cpp b/media/codec2/components/aom/C2SoftAomEnc.cpp
index 8b852a2..9102a97 100644
--- a/media/codec2/components/aom/C2SoftAomEnc.cpp
+++ b/media/codec2/components/aom/C2SoftAomEnc.cpp
@@ -22,6 +22,7 @@
#include <media/stagefright/foundation/MediaDefs.h>
#include <C2Debug.h>
+#include <Codec2CommonUtils.h>
#include <Codec2Mapper.h>
#include <C2PlatformSupport.h>
#include <SimpleC2Interface.h>
@@ -63,7 +64,8 @@
0u, C2Config::BITRATE_VARIABLE))
.withFields({C2F(mBitrateMode, value)
.oneOf({C2Config::BITRATE_CONST,
- C2Config::BITRATE_VARIABLE})})
+ C2Config::BITRATE_VARIABLE,
+ C2Config::BITRATE_IGNORE})})
.withSetter(Setter<decltype(*mBitrateMode)>::StrictValueWithNoDeps)
.build());
@@ -86,6 +88,12 @@
.withSetter(BitrateSetter)
.build());
+ addParameter(DefineParam(mQuality, C2_PARAMKEY_QUALITY)
+ .withDefault(new C2StreamQualityTuning::output(0u, 80))
+ .withFields({C2F(mQuality, value).inRange(0, 100)})
+ .withSetter(Setter<decltype(*mQuality)>::NonStrictValueWithNoDeps)
+ .build());
+
addParameter(DefineParam(mIntraRefresh, C2_PARAMKEY_INTRA_REFRESH)
.withConstValue(new C2StreamIntraRefreshTuning::output(
0u, C2Config::INTRA_REFRESH_DISABLED, 0.))
@@ -105,19 +113,18 @@
.withSetter(ProfileLevelSetter)
.build());
+ std::vector<uint32_t> pixelFormats = {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
+ HAL_PIXEL_FORMAT_YCBCR_420_888};
+ if (isHalPixelFormatSupported((AHardwareBuffer_Format)HAL_PIXEL_FORMAT_YCBCR_P010)) {
+ pixelFormats.push_back(HAL_PIXEL_FORMAT_YCBCR_P010);
+ }
addParameter(DefineParam(mPixelFormat, C2_PARAMKEY_PIXEL_FORMAT)
- .withDefault(new C2StreamPixelFormatInfo::output(
+ .withDefault(new C2StreamPixelFormatInfo::input(
0u, HAL_PIXEL_FORMAT_YCBCR_420_888))
- .withFields({C2F(mPixelFormat, value).oneOf({
- HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
- HAL_PIXEL_FORMAT_YCBCR_420_888,
- HAL_PIXEL_FORMAT_YCBCR_P010
- })
- })
+ .withFields({C2F(mPixelFormat, value).oneOf({pixelFormats})})
.withSetter((Setter<decltype(*mPixelFormat)>::StrictValueWithNoDeps))
.build());
-
addParameter(DefineParam(mRequestSync, C2_PARAMKEY_REQUEST_SYNC_FRAME)
.withDefault(new C2StreamRequestSyncFrameTuning::output(0u, C2_FALSE))
.withFields({C2F(mRequestSync, value).oneOf({C2_FALSE, C2_TRUE})})
@@ -293,6 +300,12 @@
return onStop();
}
+// c2Quality is in range of 0-100 (the more - the better),
+// for AOM quality we are using a range of 15-50 (the less - the better)
+static int MapC2QualityToAOMQuality (int c2Quality) {
+ return 15 + 35 * (100 - c2Quality) / 100;
+}
+
aom_codec_err_t C2SoftAomEnc::setupCodecParameters() {
aom_codec_err_t codec_return = AOM_CODEC_OK;
@@ -391,6 +404,15 @@
codec_return = aom_codec_control(mCodecContext, AV1E_SET_MAX_REFERENCE_FRAMES, 3);
if (codec_return != AOM_CODEC_OK) goto BailOut;
+ if (mBitrateControlMode == AOM_Q) {
+ const int aomCQLevel = MapC2QualityToAOMQuality(mQuality->value);
+ ALOGV("Set Q from %d to CQL %d",
+ mQuality->value, aomCQLevel);
+
+ codec_return = aom_codec_control(mCodecContext, AOME_SET_CQ_LEVEL, aomCQLevel);
+ if (codec_return != AOM_CODEC_OK) goto BailOut;
+ }
+
ColorAspects sfAspects;
if (!C2Mapper::map(mColorAspects->primaries, &sfAspects.mPrimaries)) {
sfAspects.mPrimaries = android::ColorAspects::PrimariesUnspecified;
@@ -438,6 +460,7 @@
mIntraRefresh = mIntf->getIntraRefresh_l();
mRequestSync = mIntf->getRequestSync_l();
mColorAspects = mIntf->getCodedColorAspects_l();
+ mQuality = mIntf->getQuality_l();
}
@@ -445,6 +468,9 @@
case C2Config::BITRATE_CONST:
mBitrateControlMode = AOM_CBR;
break;
+ case C2Config::BITRATE_IGNORE:
+ mBitrateControlMode = AOM_Q;
+ break;
case C2Config::BITRATE_VARIABLE:
[[fallthrough]];
default:
@@ -484,7 +510,7 @@
mCodecConfiguration->g_timebase.den = 1000000;
// rc_target_bitrate is in kbps, mBitrate in bps
mCodecConfiguration->rc_target_bitrate = (mBitrate->value + 500) / 1000;
- mCodecConfiguration->rc_end_usage = AOM_CBR;
+ mCodecConfiguration->rc_end_usage = mBitrateControlMode == AOM_Q ? AOM_Q : AOM_CBR;
// Disable frame drop - not allowed in MediaCodec now.
mCodecConfiguration->rc_dropframe_thresh = 0;
// Disable lagged encoding.
diff --git a/media/codec2/components/aom/C2SoftAomEnc.h b/media/codec2/components/aom/C2SoftAomEnc.h
index 3e42855..d7832dd 100644
--- a/media/codec2/components/aom/C2SoftAomEnc.h
+++ b/media/codec2/components/aom/C2SoftAomEnc.h
@@ -102,6 +102,7 @@
std::shared_ptr<C2StreamIntraRefreshTuning::output> mIntraRefresh;
std::shared_ptr<C2StreamFrameRateInfo::output> mFrameRate;
std::shared_ptr<C2StreamBitrateInfo::output> mBitrate;
+ std::shared_ptr<C2StreamQualityTuning::output> mQuality;
std::shared_ptr<C2StreamBitrateModeTuning::output> mBitrateMode;
std::shared_ptr<C2StreamRequestSyncFrameTuning::output> mRequestSync;
std::shared_ptr<C2StreamColorAspectsInfo::output> mColorAspects;
@@ -127,6 +128,7 @@
}
std::shared_ptr<C2StreamFrameRateInfo::output> getFrameRate_l() const { return mFrameRate; }
std::shared_ptr<C2StreamBitrateInfo::output> getBitrate_l() const { return mBitrate; }
+ std::shared_ptr<C2StreamQualityTuning::output> getQuality_l() const { return mQuality; }
std::shared_ptr<C2StreamBitrateModeTuning::output> getBitrateMode_l() const {
return mBitrateMode;
}
@@ -136,7 +138,7 @@
std::shared_ptr<C2StreamColorAspectsInfo::output> getCodedColorAspects_l() const {
return mCodedColorAspects;
}
- std::shared_ptr<C2StreamPixelFormatInfo::output> getPixelFormat_l() const {
+ std::shared_ptr<C2StreamPixelFormatInfo::input> getPixelFormat_l() const {
return mPixelFormat;
}
uint32_t getSyncFramePeriod() const;
@@ -152,11 +154,12 @@
std::shared_ptr<C2StreamRequestSyncFrameTuning::output> mRequestSync;
std::shared_ptr<C2StreamSyncFrameIntervalTuning::output> mSyncFramePeriod;
std::shared_ptr<C2StreamBitrateInfo::output> mBitrate;
+ std::shared_ptr<C2StreamQualityTuning::output> mQuality;
std::shared_ptr<C2StreamBitrateModeTuning::output> mBitrateMode;
std::shared_ptr<C2StreamProfileLevelInfo::output> mProfileLevel;
std::shared_ptr<C2StreamColorAspectsInfo::input> mColorAspects;
std::shared_ptr<C2StreamColorAspectsInfo::output> mCodedColorAspects;
- std::shared_ptr<C2StreamPixelFormatInfo::output> mPixelFormat;
+ std::shared_ptr<C2StreamPixelFormatInfo::input> mPixelFormat;
};
diff --git a/media/libaudiohal/impl/DeviceHalAidl.cpp b/media/libaudiohal/impl/DeviceHalAidl.cpp
index 62b9ec7..2951752a 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalAidl.cpp
@@ -20,6 +20,8 @@
#include <algorithm>
#include <forward_list>
+#include <aidl/android/hardware/audio/core/BnStreamCallback.h>
+#include <aidl/android/hardware/audio/core/BnStreamOutEventCallback.h>
#include <aidl/android/hardware/audio/core/StreamDescriptor.h>
#include <error/expected_utils.h>
#include <media/AidlConversionCppNdk.h>
@@ -37,6 +39,7 @@
using aidl::android::media::audio::common::AudioDeviceType;
using aidl::android::media::audio::common::AudioInputFlags;
using aidl::android::media::audio::common::AudioIoFlags;
+using aidl::android::media::audio::common::AudioLatencyMode;
using aidl::android::media::audio::common::AudioMode;
using aidl::android::media::audio::common::AudioOutputFlags;
using aidl::android::media::audio::common::AudioPort;
@@ -299,6 +302,123 @@
return OK;
}
+namespace {
+
+class StreamCallbackBase {
+ protected:
+ explicit StreamCallbackBase(const sp<CallbackBroker>& broker) : mBroker(broker) {}
+ public:
+ void* getCookie() const { return mCookie; }
+ void setCookie(void* cookie) { mCookie = cookie; }
+ sp<CallbackBroker> getBroker() const {
+ if (void* cookie = mCookie; cookie != nullptr) return mBroker.promote();
+ return nullptr;
+ }
+ private:
+ const wp<CallbackBroker> mBroker;
+ std::atomic<void*> mCookie;
+};
+
+template<class C>
+class StreamCallbackBaseHelper {
+ protected:
+ explicit StreamCallbackBaseHelper(const StreamCallbackBase& base) : mBase(base) {}
+ sp<C> getCb(const sp<CallbackBroker>& broker, void* cookie);
+ using CbRef = const sp<C>&;
+ ndk::ScopedAStatus runCb(const std::function<void(CbRef cb)>& f) {
+ if (auto cb = getCb(mBase.getBroker(), mBase.getCookie()); cb != nullptr) f(cb);
+ return ndk::ScopedAStatus::ok();
+ }
+ private:
+ const StreamCallbackBase& mBase;
+};
+
+template<>
+sp<StreamOutHalInterfaceCallback> StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>::getCb(
+ const sp<CallbackBroker>& broker, void* cookie) {
+ if (broker != nullptr) return broker->getStreamOutCallback(cookie);
+ return nullptr;
+}
+
+template<>
+sp<StreamOutHalInterfaceEventCallback>
+StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::getCb(
+ const sp<CallbackBroker>& broker, void* cookie) {
+ if (broker != nullptr) return broker->getStreamOutEventCallback(cookie);
+ return nullptr;
+}
+
+template<>
+sp<StreamOutHalInterfaceLatencyModeCallback>
+StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::getCb(
+ const sp<CallbackBroker>& broker, void* cookie) {
+ if (broker != nullptr) return broker->getStreamOutLatencyModeCallback(cookie);
+ return nullptr;
+}
+
+/*
+Note on the callback ownership.
+
+In the Binder ownership model, the server implementation is kept alive
+as long as there is any client (proxy object) alive. This is done by
+incrementing the refcount of the server-side object by the Binder framework.
+When it detects that the last client is gone, it decrements the refcount back.
+
+Thus, it is not needed to keep any references to StreamCallback on our
+side (after we have sent an instance to the client), because we are
+the server-side. The callback object will be kept alive as long as the HAL server
+holds a strong ref to IStreamCallback proxy.
+*/
+
+class OutputStreamCallbackAidl : public StreamCallbackBase,
+ public StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>,
+ public ::aidl::android::hardware::audio::core::BnStreamCallback {
+ public:
+ explicit OutputStreamCallbackAidl(const sp<CallbackBroker>& broker)
+ : StreamCallbackBase(broker),
+ StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>(
+ *static_cast<StreamCallbackBase*>(this)) {}
+ ndk::ScopedAStatus onTransferReady() override {
+ return runCb([](CbRef cb) { cb->onWriteReady(); });
+ }
+ ndk::ScopedAStatus onError() override {
+ return runCb([](CbRef cb) { cb->onError(); });
+ }
+ ndk::ScopedAStatus onDrainReady() override {
+ return runCb([](CbRef cb) { cb->onDrainReady(); });
+ }
+};
+
+class OutputStreamEventCallbackAidl :
+ public StreamCallbackBase,
+ public StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>,
+ public StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>,
+ public ::aidl::android::hardware::audio::core::BnStreamOutEventCallback {
+ public:
+ explicit OutputStreamEventCallbackAidl(const sp<CallbackBroker>& broker)
+ : StreamCallbackBase(broker),
+ StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>(
+ *static_cast<StreamCallbackBase*>(this)),
+ StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>(
+ *static_cast<StreamCallbackBase*>(this)) {}
+ ndk::ScopedAStatus onCodecFormatChanged(const std::vector<uint8_t>& in_audioMetadata) override {
+ std::basic_string<uint8_t> halMetadata(in_audioMetadata.begin(), in_audioMetadata.end());
+ return StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::runCb(
+ [&halMetadata](auto cb) { cb->onCodecFormatChanged(halMetadata); });
+ }
+ ndk::ScopedAStatus onRecommendedLatencyModeChanged(
+ const std::vector<AudioLatencyMode>& in_modes) override {
+ auto halModes = VALUE_OR_FATAL(
+ ::aidl::android::convertContainer<std::vector<audio_latency_mode_t>>(
+ in_modes,
+ ::aidl::android::aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
+ return StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::runCb(
+ [&halModes](auto cb) { cb->onRecommendedLatencyModeChanged(halModes); });
+ }
+};
+
+} // namespace
+
status_t DeviceHalAidl::openOutputStream(
audio_io_handle_t handle, audio_devices_t devices,
audio_output_flags_t flags, struct audio_config* config,
@@ -326,8 +446,19 @@
&cleanups, &aidlConfig, &mixPortConfig, &nominalLatency));
::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
args.portConfigId = mixPortConfig.id;
- args.offloadInfo = aidlConfig.offloadInfo;
+ const bool isOffload = isBitPositionFlagSet(
+ aidlOutputFlags, AudioOutputFlags::COMPRESS_OFFLOAD);
+ std::shared_ptr<OutputStreamCallbackAidl> streamCb;
+ if (isOffload) {
+ streamCb = ndk::SharedRefBase::make<OutputStreamCallbackAidl>(this);
+ }
+ auto eventCb = ndk::SharedRefBase::make<OutputStreamEventCallbackAidl>(this);
+ if (isOffload) {
+ args.offloadInfo = aidlConfig.offloadInfo;
+ args.callback = streamCb;
+ }
args.bufferSizeFrames = aidlConfig.frameCount;
+ args.eventCallback = eventCb;
::aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openOutputStream(args, &ret)));
StreamContextAidl context(ret.desc);
@@ -337,7 +468,14 @@
return NO_INIT;
}
*outStream = sp<StreamOutHalAidl>::make(*config, std::move(context), nominalLatency,
- std::move(ret.stream));
+ std::move(ret.stream), this /*callbackBroker*/);
+ void* cbCookie = (*outStream).get();
+ {
+ std::lock_guard l(mLock);
+ mCallbacks.emplace(cbCookie, Callbacks{});
+ }
+ if (streamCb) streamCb->setCookie(cbCookie);
+ eventCb->setCookie(cbCookie);
cleanups.disarmAll();
return OK;
}
@@ -883,4 +1021,55 @@
ALOGE("%s: port config id %d not found", __func__, portConfigId);
}
+void DeviceHalAidl::clearCallbacks(void* cookie) {
+ std::lock_guard l(mLock);
+ mCallbacks.erase(cookie);
+}
+
+sp<StreamOutHalInterfaceCallback> DeviceHalAidl::getStreamOutCallback(void* cookie) {
+ return getCallbackImpl(cookie, &Callbacks::out);
+}
+
+void DeviceHalAidl::setStreamOutCallback(
+ void* cookie, const sp<StreamOutHalInterfaceCallback>& cb) {
+ setCallbackImpl(cookie, &Callbacks::out, cb);
+}
+
+sp<StreamOutHalInterfaceEventCallback> DeviceHalAidl::getStreamOutEventCallback(
+ void* cookie) {
+ return getCallbackImpl(cookie, &Callbacks::event);
+}
+
+void DeviceHalAidl::setStreamOutEventCallback(
+ void* cookie, const sp<StreamOutHalInterfaceEventCallback>& cb) {
+ setCallbackImpl(cookie, &Callbacks::event, cb);
+}
+
+sp<StreamOutHalInterfaceLatencyModeCallback> DeviceHalAidl::getStreamOutLatencyModeCallback(
+ void* cookie) {
+ return getCallbackImpl(cookie, &Callbacks::latency);
+}
+
+void DeviceHalAidl::setStreamOutLatencyModeCallback(
+ void* cookie, const sp<StreamOutHalInterfaceLatencyModeCallback>& cb) {
+ setCallbackImpl(cookie, &Callbacks::latency, cb);
+}
+
+template<class C>
+sp<C> DeviceHalAidl::getCallbackImpl(void* cookie, wp<C> DeviceHalAidl::Callbacks::* field) {
+ std::lock_guard l(mLock);
+ if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
+ return ((it->second).*field).promote();
+ }
+ return nullptr;
+}
+template<class C>
+void DeviceHalAidl::setCallbackImpl(
+ void* cookie, wp<C> DeviceHalAidl::Callbacks::* field, const sp<C>& cb) {
+ std::lock_guard l(mLock);
+ if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
+ (it->second).*field = cb;
+ }
+}
+
} // namespace android
diff --git a/media/libaudiohal/impl/DeviceHalAidl.h b/media/libaudiohal/impl/DeviceHalAidl.h
index d666c7c..76e832d 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.h
+++ b/media/libaudiohal/impl/DeviceHalAidl.h
@@ -22,6 +22,7 @@
#include <aidl/android/hardware/audio/core/BpModule.h>
#include <aidl/android/hardware/audio/core/sounddose/BpSoundDose.h>
+#include <android-base/thread_annotations.h>
#include <media/audiohal/DeviceHalInterface.h>
#include <media/audiohal/EffectHalInterface.h>
@@ -29,7 +30,35 @@
namespace android {
-class DeviceHalAidl : public DeviceHalInterface, public ConversionHelperAidl {
+class StreamOutHalInterfaceCallback;
+class StreamOutHalInterfaceEventCallback;
+class StreamOutHalInterfaceLatencyModeCallback;
+
+// The role of the broker is to connect AIDL callback interface implementations
+// with StreamOut callback implementations. Since AIDL requires all callbacks
+// to be provided upfront, while libaudiohal interfaces allow late registration,
+// there is a need to coordinate the matching process.
+class CallbackBroker : public virtual RefBase {
+ public:
+ virtual ~CallbackBroker() = default;
+ // The cookie is always the stream instance pointer. We don't use weak pointers to avoid extra
+ // costs on reference counting. The stream cleans up related entries on destruction. Since
+ // access to the callbacks map is synchronized, the possibility for pointer aliasing due to
+ // allocation of a new stream at the address of previously deleted stream is avoided.
+ virtual void clearCallbacks(void* cookie) = 0;
+ virtual sp<StreamOutHalInterfaceCallback> getStreamOutCallback(void* cookie) = 0;
+ virtual void setStreamOutCallback(void* cookie, const sp<StreamOutHalInterfaceCallback>&) = 0;
+ virtual sp<StreamOutHalInterfaceEventCallback> getStreamOutEventCallback(void* cookie) = 0;
+ virtual void setStreamOutEventCallback(void* cookie,
+ const sp<StreamOutHalInterfaceEventCallback>&) = 0;
+ virtual sp<StreamOutHalInterfaceLatencyModeCallback> getStreamOutLatencyModeCallback(
+ void* cookie) = 0;
+ virtual void setStreamOutLatencyModeCallback(
+ void* cookie, const sp<StreamOutHalInterfaceLatencyModeCallback>&) = 0;
+};
+
+class DeviceHalAidl : public DeviceHalInterface, public ConversionHelperAidl,
+ public CallbackBroker {
public:
// Sets the value of 'devices' to a bitmask of 1 or more values of audio_devices_t.
status_t getSupportedDevices(uint32_t *devices) override;
@@ -127,6 +156,12 @@
private:
friend class sp<DeviceHalAidl>;
+
+ struct Callbacks { // No need to use `atomic_wp` because access is serialized.
+ wp<StreamOutHalInterfaceCallback> out;
+ wp<StreamOutHalInterfaceEventCallback> event;
+ wp<StreamOutHalInterfaceLatencyModeCallback> latency;
+ };
using Patches = std::map<int32_t /*patch ID*/,
::aidl::android::hardware::audio::core::AudioPatch>;
using PortConfigs = std::map<int32_t /*port config ID*/,
@@ -195,6 +230,21 @@
void resetPatch(int32_t patchId);
void resetPortConfig(int32_t portConfigId);
+ // CallbackBroker implementation
+ void clearCallbacks(void* cookie) override;
+ sp<StreamOutHalInterfaceCallback> getStreamOutCallback(void* cookie) override;
+ void setStreamOutCallback(void* cookie, const sp<StreamOutHalInterfaceCallback>& cb) override;
+ sp<StreamOutHalInterfaceEventCallback> getStreamOutEventCallback(void* cookie) override;
+ void setStreamOutEventCallback(void* cookie,
+ const sp<StreamOutHalInterfaceEventCallback>& cb) override;
+ sp<StreamOutHalInterfaceLatencyModeCallback> getStreamOutLatencyModeCallback(
+ void* cookie) override;
+ void setStreamOutLatencyModeCallback(
+ void* cookie, const sp<StreamOutHalInterfaceLatencyModeCallback>& cb) override;
+ // Implementation helpers.
+ template<class C> sp<C> getCallbackImpl(void* cookie, wp<C> Callbacks::* field);
+ template<class C> void setCallbackImpl(void* cookie, wp<C> Callbacks::* field, const sp<C>& cb);
+
const std::string mInstance;
const std::shared_ptr<::aidl::android::hardware::audio::core::IModule> mModule;
std::shared_ptr<::aidl::android::hardware::audio::core::sounddose::ISoundDose>
@@ -204,7 +254,9 @@
int32_t mDefaultOutputPortId = -1;
PortConfigs mPortConfigs;
Patches mPatches;
- std::map<audio_patch_handle_t, int32_t /* patch ID */> mFwkHandles;
+ std::map<audio_patch_handle_t, int32_t /*patch ID*/> mFwkHandles;
+ std::mutex mLock;
+ std::map<void*, Callbacks> mCallbacks GUARDED_BY(mLock);
};
} // namespace android
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
index 6190596..7e25b04 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
@@ -136,29 +136,15 @@
return ret;
}
-status_t EffectConversionHelperAidl::handleSetConfig(uint32_t cmdSize, const void* pCmdData,
+status_t EffectConversionHelperAidl::handleSetConfig(uint32_t cmdSize,
+ const void* pCmdData __unused,
uint32_t* replySize, void* pReplyData) {
if (!replySize || *replySize != sizeof(int) || !pReplyData ||
cmdSize != sizeof(effect_config_t)) {
return BAD_VALUE;
}
- return *static_cast<int32_t*>(pReplyData) = OK;
- const auto& legacyConfig = static_cast<const effect_config_t*>(pCmdData);
- // already open, apply latest settings
- Parameter::Common common;
- common.input.base =
- VALUE_OR_RETURN_STATUS(::aidl::android::legacy2aidl_buffer_config_t_AudioConfigBase(
- legacyConfig->inputCfg, true /* isInput */));
- common.output.base =
- VALUE_OR_RETURN_STATUS(::aidl::android::legacy2aidl_buffer_config_t_AudioConfigBase(
- legacyConfig->outputCfg, false /* isInput */));
- common.session = mSessionId;
- common.ioHandle = mIoId;
- // TODO: add access mode support
- RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
- mEffect->setParameter(Parameter::make<Parameter::common>(common))));
- mCommon = common;
+ // TODO: need to implement setConfig with setParameter(common)
return *static_cast<int32_t*>(pReplyData) = OK;
}
diff --git a/media/libaudiohal/impl/StreamHalAidl.cpp b/media/libaudiohal/impl/StreamHalAidl.cpp
index 2b85f97..17b3c2e 100644
--- a/media/libaudiohal/impl/StreamHalAidl.cpp
+++ b/media/libaudiohal/impl/StreamHalAidl.cpp
@@ -20,7 +20,6 @@
#include <algorithm>
#include <cstdint>
-#include <aidl/android/hardware/audio/core/BnStreamCallback.h>
#include <audio_utils/clock.h>
#include <mediautils/TimeCheck.h>
#include <utils/Log.h>
@@ -287,12 +286,13 @@
if (status_t status = sendCommand(burst, &reply); status != OK) {
return status;
}
+ *transferred = reply.fmqByteCount;
if (mIsInput) {
- *transferred = reply.fmqByteCount;
LOG_ALWAYS_FATAL_IF(*transferred > bytes,
"%s: HAL module read %zu bytes, which exceeds requested count %zu",
__func__, *transferred, bytes);
- if (!mContext.getDataMQ()->read(static_cast<int8_t*>(buffer), *transferred)) {
+ if (!mContext.getDataMQ()->read(static_cast<int8_t*>(buffer),
+ mContext.getDataMQ()->availableToRead())) {
ALOGE("%s: failed to read %zu bytes to data MQ", __func__, *transferred);
return NOT_ENOUGH_DATA;
}
@@ -448,43 +448,18 @@
return OK;
}
-namespace {
-
-/* Notes on callback ownership.
-
-This is how Binder ownership model looks like. The server implementation
-is owned by Binder framework (via sp<>). Proxies are owned by clients.
-When the last proxy disappears, Binder framework releases the server impl.
-
-Thus, it is not needed to keep any references to StreamCallback (this is
-the server impl) -- it will live as long as HAL server holds a strong ref to
-IStreamCallback proxy.
-
-The callback only keeps a weak reference to the stream. The stream is owned
-by AudioFlinger.
-
-*/
-
-class StreamCallback : public ::aidl::android::hardware::audio::core::BnStreamCallback {
- ndk::ScopedAStatus onTransferReady() override {
- return ndk::ScopedAStatus::ok();
- }
- ndk::ScopedAStatus onError() override {
- return ndk::ScopedAStatus::ok();
- }
- ndk::ScopedAStatus onDrainReady() override {
- return ndk::ScopedAStatus::ok();
- }
-};
-
-} // namespace
-
StreamOutHalAidl::StreamOutHalAidl(
const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency,
- const std::shared_ptr<IStreamOut>& stream)
+ const std::shared_ptr<IStreamOut>& stream, const sp<CallbackBroker>& callbackBroker)
: StreamHalAidl("StreamOutHalAidl", false /*isInput*/, config, nominalLatency,
std::move(context), getStreamCommon(stream)),
- mStream(stream) {}
+ mStream(stream), mCallbackBroker(callbackBroker) {}
+
+StreamOutHalAidl::~StreamOutHalAidl() {
+ if (auto broker = mCallbackBroker.promote(); broker != nullptr) {
+ broker->clearCallbacks(this);
+ }
+}
status_t StreamOutHalAidl::getLatency(uint32_t *latency) {
return StreamHalAidl::getLatency(latency);
@@ -529,10 +504,18 @@
return INVALID_OPERATION;
}
-status_t StreamOutHalAidl::setCallback(wp<StreamOutHalInterfaceCallback> callback __unused) {
+status_t StreamOutHalAidl::setCallback(wp<StreamOutHalInterfaceCallback> callback) {
TIME_CHECK();
if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
+ if (auto broker = mCallbackBroker.promote(); broker != nullptr) {
+ if (auto cb = callback.promote(); cb != nullptr) {
+ broker->setStreamOutCallback(this, cb);
+ } else {
+ // It is expected that the framework never passes a null pointer.
+ // In the AIDL model callbacks can't be "unregistered".
+ LOG_ALWAYS_FATAL("%s: received an expired or null callback pointer", __func__);
+ }
+ }
return OK;
}
@@ -639,23 +622,15 @@
}
status_t StreamOutHalAidl::setEventCallback(
- const sp<StreamOutHalInterfaceEventCallback>& callback __unused) {
+ const sp<StreamOutHalInterfaceEventCallback>& callback) {
TIME_CHECK();
if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
+ if (auto broker = mCallbackBroker.promote(); broker != nullptr) {
+ broker->setStreamOutEventCallback(this, callback);
+ }
return OK;
}
-namespace {
-
-struct StreamOutEventCallback {
- StreamOutEventCallback(const wp<StreamOutHalAidl>& stream) : mStream(stream) {}
- private:
- wp<StreamOutHalAidl> mStream;
-};
-
-} // namespace
-
status_t StreamOutHalAidl::setLatencyMode(audio_latency_mode_t mode __unused) {
TIME_CHECK();
if (!mStream) return NO_INIT;
@@ -672,48 +647,15 @@
};
status_t StreamOutHalAidl::setLatencyModeCallback(
- const sp<StreamOutHalInterfaceLatencyModeCallback>& callback __unused) {
+ const sp<StreamOutHalInterfaceLatencyModeCallback>& callback) {
TIME_CHECK();
if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
+ if (auto broker = mCallbackBroker.promote(); broker != nullptr) {
+ broker->setStreamOutLatencyModeCallback(this, callback);
+ }
return OK;
};
-void StreamOutHalAidl::onWriteReady() {
- sp<StreamOutHalInterfaceCallback> callback = mCallback.load().promote();
- if (callback == 0) return;
- ALOGV("asyncCallback onWriteReady");
- callback->onWriteReady();
-}
-
-void StreamOutHalAidl::onDrainReady() {
- sp<StreamOutHalInterfaceCallback> callback = mCallback.load().promote();
- if (callback == 0) return;
- ALOGV("asyncCallback onDrainReady");
- callback->onDrainReady();
-}
-
-void StreamOutHalAidl::onError() {
- sp<StreamOutHalInterfaceCallback> callback = mCallback.load().promote();
- if (callback == 0) return;
- ALOGV("asyncCallback onError");
- callback->onError();
-}
-
-void StreamOutHalAidl::onCodecFormatChanged(const std::basic_string<uint8_t>& metadataBs __unused) {
- sp<StreamOutHalInterfaceEventCallback> callback = mEventCallback.load().promote();
- if (callback == nullptr) return;
- ALOGV("asyncCodecFormatCallback %s", __func__);
- callback->onCodecFormatChanged(metadataBs);
-}
-
-void StreamOutHalAidl::onRecommendedLatencyModeChanged(
- const std::vector<audio_latency_mode_t>& modes __unused) {
- sp<StreamOutHalInterfaceLatencyModeCallback> callback = mLatencyModeCallback.load().promote();
- if (callback == nullptr) return;
- callback->onRecommendedLatencyModeChanged(modes);
-}
-
status_t StreamOutHalAidl::exit() {
return StreamHalAidl::exit();
}
diff --git a/media/libaudiohal/impl/StreamHalAidl.h b/media/libaudiohal/impl/StreamHalAidl.h
index ce6c31c..162c7bc 100644
--- a/media/libaudiohal/impl/StreamHalAidl.h
+++ b/media/libaudiohal/impl/StreamHalAidl.h
@@ -27,7 +27,6 @@
#include <fmq/AidlMessageQueue.h>
#include <media/audiohal/EffectHalInterface.h>
#include <media/audiohal/StreamHalInterface.h>
-#include <mediautils/Synchronization.h>
#include "ConversionHelperAidl.h"
#include "StreamPowerLog.h"
@@ -221,6 +220,8 @@
std::atomic<pid_t> mWorkerTid = -1;
};
+class CallbackBroker;
+
class StreamOutHalAidl : public StreamOutHalInterface, public StreamHalAidl {
public:
// Return the audio hardware driver estimated latency in milliseconds.
@@ -294,33 +295,21 @@
status_t setLatencyModeCallback(
const sp<StreamOutHalInterfaceLatencyModeCallback>& callback) override;
- void onRecommendedLatencyModeChanged(const std::vector<audio_latency_mode_t>& modes);
-
status_t exit() override;
- void onCodecFormatChanged(const std::basic_string<uint8_t>& metadataBs);
-
- // Methods used by StreamOutCallback ().
- // FIXME: Consider the required visibility.
- void onWriteReady();
- void onDrainReady();
- void onError();
-
private:
friend class sp<StreamOutHalAidl>;
- mediautils::atomic_wp<StreamOutHalInterfaceCallback> mCallback;
- mediautils::atomic_wp<StreamOutHalInterfaceEventCallback> mEventCallback;
- mediautils::atomic_wp<StreamOutHalInterfaceLatencyModeCallback> mLatencyModeCallback;
-
const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamOut> mStream;
+ const wp<CallbackBroker> mCallbackBroker;
// Can not be constructed directly by clients.
StreamOutHalAidl(
const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency,
- const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamOut>& stream);
+ const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamOut>& stream,
+ const sp<CallbackBroker>& callbackBroker);
- ~StreamOutHalAidl() override = default;
+ ~StreamOutHalAidl() override;
};
class StreamInHalAidl : public StreamInHalInterface, public StreamHalAidl {
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp
index efa9e89..a10d271 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp
@@ -69,25 +69,7 @@
break;
}
case EQ_PARAM_PROPERTIES: {
- if (value >= 0) {
- aidlParam = MAKE_SPECIFIC_PARAMETER(Equalizer, equalizer, preset, (int)value);
- } else {
- std::vector<Equalizer::BandLevel> bandLevels;
- uint16_t numBands;
- if (OK != param.readFromValue(&numBands)) {
- ALOGE("%s invalid bandLevel param %s", __func__, param.toString().c_str());
- return BAD_VALUE;
- }
- for (int i = 0; i < numBands; i++) {
- uint16_t level;
- if (OK != param.readFromValue(&level)) {
- ALOGE("%s invalid property param %s", __func__, param.toString().c_str());
- return BAD_VALUE;
- }
- bandLevels.push_back({.index = i, .levelMb = level});
- }
- aidlParam = MAKE_SPECIFIC_PARAMETER(Equalizer, equalizer, bandLevels, bandLevels);
- }
+ // TODO: handle properties setting
break;
}
default: {
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.cpp
index 814b58f..9575e7d 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.cpp
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.cpp
@@ -34,6 +34,7 @@
namespace effect {
using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::HapticGenerator;
using ::aidl::android::hardware::audio::effect::Parameter;
using ::android::status_t;
using utils::EffectParamReader;
@@ -41,27 +42,52 @@
status_t AidlConversionHapticGenerator::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)) {
+ OK != param.readFromParameter(&type)) {
ALOGE("%s invalid param %s", __func__, param.toString().c_str());
return BAD_VALUE;
}
Parameter aidlParam;
- // TODO
+ switch (type) {
+ case HG_PARAM_HAPTIC_INTENSITY: {
+ int32_t id = 0, scale;
+ if (OK != param.readFromValue(&id) || OK != param.readFromValue(&scale)) {
+ ALOGE("%s invalid intensity %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ HapticGenerator::HapticScale hpScale(
+ {.id = id, .scale = (HapticGenerator::VibratorScale)(scale)});
+ aidlParam = MAKE_SPECIFIC_PARAMETER(HapticGenerator, hapticGenerator, hapticScales,
+ {hpScale});
+ break;
+ }
+ case HG_PARAM_VIBRATOR_INFO: {
+ float resonantFrequencyHz, qFactor, maxAmplitude;
+ if (OK != param.readFromValue(&resonantFrequencyHz) ||
+ OK != param.readFromValue(&qFactor) || OK != param.readFromValue(&maxAmplitude)) {
+ ALOGE("%s invalid vibrator info %s", __func__, param.toString().c_str());
+ return BAD_VALUE;
+ }
+ HapticGenerator::VibratorInformation info({.resonantFrequencyHz = resonantFrequencyHz,
+ .qFactor = qFactor,
+ .maxAmplitude = maxAmplitude});
+ aidlParam =
+ MAKE_SPECIFIC_PARAMETER(HapticGenerator, hapticGenerator, vibratorInfo, info);
+ 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 AidlConversionHapticGenerator::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());
- param.setStatus(BAD_VALUE);
- return BAD_VALUE;
- }
- // TODO
- return param.writeToValue(&value);
+// No parameter to get for HapticGenerator
+status_t AidlConversionHapticGenerator::getParameter(EffectParamWriter& param __unused) {
+ return OK;
}
} // namespace effect
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.cpp
index 70e0428..e3c898f 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.cpp
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.cpp
@@ -34,6 +34,8 @@
namespace effect {
using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::getParameterSpecificField;
+using ::aidl::android::hardware::audio::effect::LoudnessEnhancer;
using ::aidl::android::hardware::audio::effect::Parameter;
using ::android::status_t;
using utils::EffectParamReader;
@@ -41,27 +43,52 @@
status_t AidlConversionLoudnessEnhancer::setParameter(EffectParamReader& param) {
uint32_t type = 0;
- uint16_t value = 0;
+ int32_t gain = 0;
if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint16_t)) ||
- OK != param.readFromParameter(&type) || OK != param.readFromValue(&value)) {
+ OK != param.readFromParameter(&type) || OK != param.readFromValue(&gain)) {
ALOGE("%s invalid param %s", __func__, param.toString().c_str());
return BAD_VALUE;
}
Parameter aidlParam;
- // TODO
+ switch (type) {
+ case LOUDNESS_ENHANCER_PARAM_TARGET_GAIN_MB: {
+ aidlParam = MAKE_SPECIFIC_PARAMETER(LoudnessEnhancer, loudnessEnhancer, gainMb, gain);
+ 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 AidlConversionLoudnessEnhancer::getParameter(EffectParamWriter& param) {
- uint32_t type = 0, value = 0;
+ 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;
}
- // TODO
- return param.writeToValue(&value);
+ switch (type) {
+ case LOUDNESS_ENHANCER_PARAM_TARGET_GAIN_MB: {
+ Parameter aidlParam;
+ Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(LoudnessEnhancer, loudnessEnhancerTag,
+ LoudnessEnhancer::gainMb);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+ int32_t gain = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+ aidlParam, LoudnessEnhancer, loudnessEnhancer, LoudnessEnhancer::gainMb,
+ std::decay_t<decltype(gain)>));
+ return param.writeToValue(&gain);
+ }
+ 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/include/media/audiohal/DeviceHalInterface.h b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
index d5a1a60..2df2f5d 100644
--- a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
@@ -35,7 +35,7 @@
class StreamInHalInterface;
class StreamOutHalInterface;
-class DeviceHalInterface : public RefBase
+class DeviceHalInterface : public virtual RefBase
{
public:
// Sets the value of 'devices' to a bitmask of 1 or more values of audio_devices_t.
diff --git a/media/libaudiohal/include/media/audiohal/StreamHalInterface.h b/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
index 1d52b7d..a651d9b 100644
--- a/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
@@ -110,8 +110,8 @@
virtual void onError() {}
protected:
- StreamOutHalInterfaceCallback() {}
- virtual ~StreamOutHalInterfaceCallback() {}
+ StreamOutHalInterfaceCallback() = default;
+ virtual ~StreamOutHalInterfaceCallback() = default;
};
class StreamOutHalInterfaceEventCallback : public virtual RefBase {
@@ -119,8 +119,8 @@
virtual void onCodecFormatChanged(const std::basic_string<uint8_t>& metadataBs) = 0;
protected:
- StreamOutHalInterfaceEventCallback() {}
- virtual ~StreamOutHalInterfaceEventCallback() {}
+ StreamOutHalInterfaceEventCallback() = default;
+ virtual ~StreamOutHalInterfaceEventCallback() = default;
};
class StreamOutHalInterfaceLatencyModeCallback : public virtual RefBase {
@@ -131,8 +131,8 @@
virtual void onRecommendedLatencyModeChanged(std::vector<audio_latency_mode_t> modes) = 0;
protected:
- StreamOutHalInterfaceLatencyModeCallback() {}
- virtual ~StreamOutHalInterfaceLatencyModeCallback() {}
+ StreamOutHalInterfaceLatencyModeCallback() = default;
+ virtual ~StreamOutHalInterfaceLatencyModeCallback() = default;
};
class StreamOutHalInterface : public virtual StreamHalInterface {
diff --git a/media/libaudiohal/tests/Android.bp b/media/libaudiohal/tests/Android.bp
index 6600713..2f78dd0 100644
--- a/media/libaudiohal/tests/Android.bp
+++ b/media/libaudiohal/tests/Android.bp
@@ -46,6 +46,7 @@
"libaudiohal",
"liblog",
"libutils",
+ "libvibrator",
],
header_libs: [
diff --git a/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp b/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp
index b7742e4..dda608b 100644
--- a/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp
+++ b/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp
@@ -31,10 +31,13 @@
#include <system/audio_effects/effect_bassboost.h>
#include <system/audio_effects/effect_downmix.h>
#include <system/audio_effects/effect_dynamicsprocessing.h>
+#include <system/audio_effects/effect_hapticgenerator.h>
+#include <system/audio_effects/effect_loudnessenhancer.h>
#include <system/audio_effect.h>
#include <gtest/gtest.h>
#include <utils/RefBase.h>
+#include <vibrator/ExternalVibrationUtils.h>
namespace android {
@@ -162,7 +165,18 @@
std::make_tuple(SL_IID_DYNAMICSPROCESSING,
createEffectParamCombination(
std::array<uint32_t, 2>({DP_PARAM_INPUT_GAIN, 0 /* channel */}),
- 30 /* gainDb */, sizeof(int32_t) /* returnValueSize */))};
+ 30 /* gainDb */, sizeof(int32_t) /* returnValueSize */)),
+ std::make_tuple(
+ FX_IID_HAPTICGENERATOR,
+ createEffectParamCombination(
+ HG_PARAM_HAPTIC_INTENSITY,
+ std::array<uint32_t, 2>(
+ {1, uint32_t(::android::os::HapticScale::HIGH) /* scale */}),
+ 0 /* returnValueSize */)),
+ std::make_tuple(
+ FX_IID_LOUDNESS_ENHANCER,
+ createEffectParamCombination(LOUDNESS_ENHANCER_PARAM_TARGET_GAIN_MB, 5 /* gain */,
+ sizeof(int32_t) /* returnValueSize */))};
class libAudioHalEffectParamTest : public ::testing::TestWithParam<EffectParamTestTuple> {
public:
@@ -237,10 +251,12 @@
&replySize, getParam));
EffectParamReader parameterGet(*getParam);
EXPECT_EQ(replySize, parameterGet.getTotalSize()) << parameterGet.toString();
- std::vector<uint8_t> response(mCombination->valueSize);
- EXPECT_EQ(OK, parameterGet.readFromValue(response.data(), mCombination->valueSize))
+ if (mCombination->valueSize) {
+ std::vector<uint8_t> response(mCombination->valueSize);
+ EXPECT_EQ(OK, parameterGet.readFromValue(response.data(), mCombination->valueSize))
<< parameterGet.toString();
- EXPECT_EQ(response, mExpectedValue);
+ EXPECT_EQ(response, mExpectedValue);
+ }
}
const EffectParamTestTuple mParamTuple;
diff --git a/media/libstagefright/SurfaceUtils.cpp b/media/libstagefright/SurfaceUtils.cpp
index f526e05..291b892 100644
--- a/media/libstagefright/SurfaceUtils.cpp
+++ b/media/libstagefright/SurfaceUtils.cpp
@@ -193,10 +193,38 @@
status_t pushBlankBuffersToNativeWindow(ANativeWindow *nativeWindow /* nonnull */) {
status_t err = NO_ERROR;
- ANativeWindowBuffer* anb = NULL;
+ ANativeWindowBuffer* anb = nullptr;
int numBufs = 0;
int minUndequeuedBufs = 0;
+ auto handleError = [](ANativeWindow *nativeWindow, ANativeWindowBuffer* anb, status_t err)
+ {
+ if (anb != nullptr) {
+ nativeWindow->cancelBuffer(nativeWindow, anb, -1);
+ anb = nullptr;
+ }
+
+ // Clean up after success or error.
+ status_t err2 = native_window_api_disconnect(nativeWindow, NATIVE_WINDOW_API_CPU);
+ if (err2 != NO_ERROR) {
+ ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)",
+ strerror(-err2), -err2);
+ if (err == NO_ERROR) {
+ err = err2;
+ }
+ }
+
+ err2 = nativeWindowConnect(nativeWindow, "pushBlankBuffersToNativeWindow(err2)");
+ if (err2 != NO_ERROR) {
+ ALOGE("error pushing blank frames: api_connect failed: %s (%d)", strerror(-err), -err);
+ if (err == NO_ERROR) {
+ err = err2;
+ }
+ }
+
+ return err;
+ };
+
// We need to reconnect to the ANativeWindow as a CPU client to ensure that
// no frames get dropped by SurfaceFlinger assuming that these are video
// frames.
@@ -217,7 +245,7 @@
nativeWindow, 1, 1, HAL_PIXEL_FORMAT_RGBX_8888, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
false /* reconnect */);
if (err != NO_ERROR) {
- goto error;
+ return handleError(nativeWindow, anb, err);
}
static_cast<Surface*>(nativeWindow)->getIGraphicBufferProducer()->allowAllocation(true);
@@ -232,14 +260,14 @@
if (err != NO_ERROR) {
ALOGE("error pushing blank frames: MIN_UNDEQUEUED_BUFFERS query "
"failed: %s (%d)", strerror(-err), -err);
- goto error;
+ return handleError(nativeWindow, anb, err);
}
numBufs = minUndequeuedBufs + 1;
err = native_window_set_buffer_count(nativeWindow, numBufs);
if (err != NO_ERROR) {
ALOGE("error pushing blank frames: set_buffer_count failed: %s (%d)", strerror(-err), -err);
- goto error;
+ return handleError(nativeWindow, anb, err);
}
// We push numBufs + 1 buffers to ensure that we've drawn into the same
@@ -257,7 +285,7 @@
sp<GraphicBuffer> buf(GraphicBuffer::from(anb));
// Fill the buffer with the a 1x1 checkerboard pattern ;)
- uint32_t *img = NULL;
+ uint32_t *img = nullptr;
err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
if (err != NO_ERROR) {
ALOGE("error pushing blank frames: lock failed: %s (%d)", strerror(-err), -err);
@@ -278,34 +306,10 @@
break;
}
- anb = NULL;
+ anb = nullptr;
}
-error:
-
- if (anb != NULL) {
- nativeWindow->cancelBuffer(nativeWindow, anb, -1);
- anb = NULL;
- }
-
- // Clean up after success or error.
- status_t err2 = native_window_api_disconnect(nativeWindow, NATIVE_WINDOW_API_CPU);
- if (err2 != NO_ERROR) {
- ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)", strerror(-err2), -err2);
- if (err == NO_ERROR) {
- err = err2;
- }
- }
-
- err2 = nativeWindowConnect(nativeWindow, "pushBlankBuffersToNativeWindow(err2)");
- if (err2 != NO_ERROR) {
- ALOGE("error pushing blank frames: api_connect failed: %s (%d)", strerror(-err), -err);
- if (err == NO_ERROR) {
- err = err2;
- }
- }
-
- return err;
+ return handleError(nativeWindow, anb, err);
}
status_t nativeWindowConnect(ANativeWindow *surface, const char *reason) {
diff --git a/media/libstagefright/data/media_codecs_google_video.xml b/media/libstagefright/data/media_codecs_google_video.xml
index 2c258e4..b1d7ff4 100644
--- a/media/libstagefright/data/media_codecs_google_video.xml
+++ b/media/libstagefright/data/media_codecs_google_video.xml
@@ -124,7 +124,8 @@
<Limit name="block-size" value="16x16" />
<Limit name="block-count" range="1-3600" />
<Limit name="bitrate" range="1-40000000" />
- <Feature name="bitrate-modes" value="VBR,CBR" />
+ <Limit name="quality" range="0-100" default="80" />
+ <Feature name="bitrate-modes" value="VBR,CBR,CQ" />
</MediaCodec>
</Encoders>
</Included>
diff --git a/media/libstagefright/data/media_codecs_sw.xml b/media/libstagefright/data/media_codecs_sw.xml
index 05f2760..5f113c5 100644
--- a/media/libstagefright/data/media_codecs_sw.xml
+++ b/media/libstagefright/data/media_codecs_sw.xml
@@ -357,7 +357,8 @@
<Limit name="block-size" value="16x16" />
<Limit name="block-count" range="1-8200" />
<Limit name="bitrate" range="1-40000000" />
- <Feature name="bitrate-modes" value="VBR,CBR" />
+ <Limit name="quality" range="0-100" default="80" />
+ <Feature name="bitrate-modes" value="VBR,CBR,CQ" />
<Attribute name="software-codec" />
</MediaCodec>
</Encoders>
diff --git a/media/utils/Android.bp b/media/utils/Android.bp
index 698752f..7abb0b6 100644
--- a/media/utils/Android.bp
+++ b/media/utils/Android.bp
@@ -103,6 +103,13 @@
logtags: ["EventLogTags.logtags"],
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ "-Wthread-safety",
+ ],
+
export_shared_lib_headers: [
"libpermission",
],
diff --git a/media/utils/TimerThread.cpp b/media/utils/TimerThread.cpp
index b760ee2..3966103 100644
--- a/media/utils/TimerThread.cpp
+++ b/media/utils/TimerThread.cpp
@@ -288,6 +288,7 @@
void TimerThread::MonitorThread::threadFunc() {
std::unique_lock _l(mMutex);
+ ::android::base::ScopedLockAssertion lock_assertion(mMutex);
while (!mShouldExit) {
Handle nextDeadline = INVALID_HANDLE;
Handle now = INVALID_HANDLE;
@@ -381,6 +382,7 @@
std::shared_ptr<const TimerThread::Request> TimerThread::MonitorThread::remove(Handle handle) {
std::pair<std::shared_ptr<const Request>, TimerCallback> data;
std::unique_lock ul(mMutex);
+ ::android::base::ScopedLockAssertion lock_assertion(mMutex);
if (const auto it = mMonitorRequests.find(handle);
it != mMonitorRequests.end()) {
data = std::move(it->second);
diff --git a/media/utils/include/mediautils/TimerThread.h b/media/utils/include/mediautils/TimerThread.h
index d5be177..d84d682 100644
--- a/media/utils/include/mediautils/TimerThread.h
+++ b/media/utils/include/mediautils/TimerThread.h
@@ -340,7 +340,7 @@
std::pair<std::shared_ptr<const Request>, TimerCallback>>
mSecondChanceRequests GUARDED_BY(mMutex);
- RequestQueue& mTimeoutQueue; // locked internally, added to when request times out.
+ RequestQueue& mTimeoutQueue GUARDED_BY(mMutex); // added to when request times out.
// Worker thread variables
bool mShouldExit GUARDED_BY(mMutex) = false;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index c585d74..3a46ee6 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -1060,7 +1060,7 @@
wp<NotificationListener> mListener;
- const String8& mId; // The camera ID
+ const String8 mId; // The camera ID
int mStatusId; // The RequestThread's component ID for
// status tracking
diff --git a/services/mediaresourcemanager/ResourceManagerService.cpp b/services/mediaresourcemanager/ResourceManagerService.cpp
index adf0a5e..5697acd 100644
--- a/services/mediaresourcemanager/ResourceManagerService.cpp
+++ b/services/mediaresourcemanager/ResourceManagerService.cpp
@@ -344,7 +344,8 @@
std::shared_ptr<ResourceManagerService> service =
::ndk::SharedRefBase::make<ResourceManagerService>();
binder_status_t status =
- AServiceManager_addService(service->asBinder().get(), getServiceName());
+ AServiceManager_addServiceWithAllowIsolated(
+ service->asBinder().get(), getServiceName(), /*allowIsolated=*/ true);
if (status != STATUS_OK) {
return;
}
diff --git a/services/mediaresourcemanager/ResourceObserverService.cpp b/services/mediaresourcemanager/ResourceObserverService.cpp
index 4e97406..b64afdc 100644
--- a/services/mediaresourcemanager/ResourceObserverService.cpp
+++ b/services/mediaresourcemanager/ResourceObserverService.cpp
@@ -100,8 +100,10 @@
std::shared_ptr<ResourceObserverService> ResourceObserverService::instantiate() {
std::shared_ptr<ResourceObserverService> observerService =
::ndk::SharedRefBase::make<ResourceObserverService>();
- binder_status_t status = AServiceManager_addService(observerService->asBinder().get(),
- ResourceObserverService::getServiceName());
+ binder_status_t status = AServiceManager_addServiceWithAllowIsolated(
+ observerService->asBinder().get(),ResourceObserverService::getServiceName(),
+ /*allowIsolated=*/ true);
+
if (status != STATUS_OK) {
return nullptr;
}