Merge "Add Dolby Vision profile/level string for codec dump"
diff --git a/Android.bp b/Android.bp
index 37f6457..302e250 100644
--- a/Android.bp
+++ b/Android.bp
@@ -102,3 +102,27 @@
},
},
}
+
+aidl_interface {
+ name: "av-audio-types-aidl",
+ unstable: true,
+ host_supported: true,
+ vendor_available: true,
+ double_loadable: true,
+ local_include_dir: "aidl",
+ srcs: [
+ "aidl/android/media/audio/IHalAdapterVendorExtension.aidl",
+ ],
+ imports: [
+ "android.hardware.audio.core-V1",
+ ],
+ backend: {
+ // The C++ backend is disabled transitively due to use of FMQ by the audio core HAL.
+ cpp: {
+ enabled: false,
+ },
+ java: {
+ sdk_version: "module_current",
+ },
+ },
+}
diff --git a/aidl/android/media/audio/IHalAdapterVendorExtension.aidl b/aidl/android/media/audio/IHalAdapterVendorExtension.aidl
new file mode 100644
index 0000000..b7a7678
--- /dev/null
+++ b/aidl/android/media/audio/IHalAdapterVendorExtension.aidl
@@ -0,0 +1,136 @@
+/*
+ * 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.audio;
+
+import android.hardware.audio.core.VendorParameter;
+
+/**
+ * This interface is used by the HAL adapter of the Audio Server. Implementation
+ * is optional. Vendors may provide an implementation on the system_ext
+ * partition. The default instance of this interface, if provided, must be
+ * registered prior to the moment when the audio server connects to HAL modules.
+ *
+ * {@hide}
+ */
+interface IHalAdapterVendorExtension {
+ enum ParameterScope {
+ MODULE = 0,
+ STREAM = 1,
+ }
+
+ /**
+ * Parse raw parameter keys into vendor parameter ids.
+ *
+ * This method prepares arguments for a call to the 'getVendorParameters'
+ * method of an 'IModule' or an 'IStreamCommon' interface instance,
+ * depending on the provided scope.
+ *
+ * The client calls this method in order to prepare arguments for a call to
+ * the particular Core HAL interface. The result returned by the HAL is then
+ * processed using the 'processVendorParameters' method. It is not required
+ * to maintain a 1:1 correspondence between the provided raw keys and the
+ * elements of the parsed result. If the returned list is empty, the call of
+ * 'getVendorParameters' is skipped. The implementation can either ignore
+ * keys which it does not recognize, or throw an error. The latter is
+ * preferred as it can help in discovering malformed key names.
+ *
+ * @param scope The scope of all raw parameter keys.
+ * @param rawKeys Raw parameter keys, joined into a string using a semicolon
+ * (';') as the delimiter.
+ * @return A list of vendor parameter IDs, see android.hardware.audio.core.VendorParameter.
+ * @throws EX_ILLEGAL_ARGUMENT If the implementation can not parse the raw keys
+ * and prefers to signal an error.
+ */
+ @utf8InCpp String[] parseVendorParameterIds(
+ ParameterScope scope, in @utf8InCpp String rawKeys);
+
+ /**
+ * Parse raw parameter key-value pairs into vendor parameters.
+ *
+ * This method prepares arguments for a call to the 'setVendorParameters'
+ * method of an 'IModule' or an 'IStreamCommon' interface instance,
+ * depending on the provided scope.
+ *
+ * The vendor parameters returned using 'syncParameters' argument is then
+ * used to call the 'setVendorParameters' method with 'async = false', and
+ * 'asyncParameters' is used in a subsequent call to the same method, but
+ * with 'async = true'. It is not required to maintain a 1:1 correspondence
+ * between the provided key-value pairs and the elements of parsed
+ * results. If any of the returned lists of vendor parameters is empty, then
+ * the corresponding call is skipped. The implementation can either ignore
+ * keys which it does not recognize, and invalid values, or throw an
+ * error. The latter is preferred as it can help in discovering malformed
+ * key names and values.
+ *
+ * @param scope The scope of all raw key-value pairs.
+ * @param rawKeys Raw key-value pairs, separated by the "equals" sign ('='),
+ * joined into a string using a semicolon (';') as the delimiter.
+ * @param syncParameters A list of vendor parameters to be set synchronously.
+ * @param asyncParameters A list of vendor parameters to be set asynchronously.
+ * @throws EX_ILLEGAL_ARGUMENT If the implementation can not parse raw key-value
+ * pairs and prefers to signal an error.
+ */
+ void parseVendorParameters(
+ ParameterScope scope, in @utf8InCpp String rawKeysAndValues,
+ out VendorParameter[] syncParameters, out VendorParameter[] asyncParameters);
+
+ /**
+ * Parse raw value of the parameter for BT A2DP reconfiguration.
+ *
+ * This method may return any number of vendor parameters (including zero)
+ * which will be passed to the 'IBluetoothA2dp.reconfigureOffload' method.
+ *
+ * @param rawValue An unparsed value of the legacy parameter.
+ * @return A list of vendor parameters.
+ * @throws EX_ILLEGAL_ARGUMENT If the implementation can not parse the raw value.
+ */
+ VendorParameter[] parseBluetoothA2dpReconfigureOffload(in @utf8InCpp String rawValue);
+
+ /**
+ * Parse raw value of the parameter for BT LE reconfiguration.
+ *
+ * This method may return any number of vendor parameters (including zero)
+ * which will be passed to the 'IBluetoothLe.reconfigureOffload' method.
+ *
+ * @param rawValue An unparsed value of the legacy parameter.
+ * @return A list of vendor parameters.
+ * @throws EX_ILLEGAL_ARGUMENT If the implementation can not parse the raw value.
+ */
+ VendorParameter[] parseBluetoothLeReconfigureOffload(in @utf8InCpp String rawValue);
+
+ /**
+ * Process vendor parameters returned by the Audio Core HAL.
+ *
+ * This processes the result returned from a call to the
+ * 'getVendorParameters' method of an 'IModule' or an 'IStreamCommon'
+ * interface instance, depending on the provided scope.
+ *
+ * See 'parseVendorParameterIds' method for the flow description. It is not
+ * required to maintain a 1:1 correspondence between the elements of the
+ * provided list and the emitted key-value pairs. The returned string with
+ * raw key-value pairs is passed back to the framework.
+ *
+ * @param scope The scope of vendor parameters.
+ * @param parameters Vendor parameters, see android.hardware.audio.core.VendorParameter.
+ * @return Key-value pairs, separated by the "equals" sign ('='),
+ * joined into a string using a semicolon (';') as the delimiter.
+ * @throws EX_ILLEGAL_ARGUMENT If the implementation can not emit raw key-value
+ * pairs and prefers to signal an error.
+ */
+ @utf8InCpp String processVendorParameters(
+ ParameterScope scope, in VendorParameter[] parameters);
+}
diff --git a/media/codec2/components/flac/C2SoftFlacEnc.cpp b/media/codec2/components/flac/C2SoftFlacEnc.cpp
index 182edfb..591d56d 100644
--- a/media/codec2/components/flac/C2SoftFlacEnc.cpp
+++ b/media/codec2/components/flac/C2SoftFlacEnc.cpp
@@ -188,12 +188,6 @@
return onStop();
}
-static void fillEmptyWork(const std::unique_ptr<C2Work> &work) {
- work->worklets.front()->output.flags = work->input.flags;
- work->worklets.front()->output.buffers.clear();
- work->worklets.front()->output.ordinal = work->input.ordinal;
-}
-
void C2SoftFlacEnc::process(
const std::unique_ptr<C2Work> &work,
const std::shared_ptr<C2BlockPool> &pool) {
@@ -245,12 +239,10 @@
mWroteHeader = true;
}
- const uint32_t sampleRate = mIntf->getSampleRate();
const uint32_t channelCount = mIntf->getChannelCount();
const bool inputFloat = mIntf->getPcmEncodingInfo() == C2Config::PCM_FLOAT;
const unsigned sampleSize = inputFloat ? sizeof(float) : sizeof(int16_t);
const unsigned frameSize = channelCount * sampleSize;
- const uint64_t outTimeStamp = mProcessedSamples * 1000000ll / sampleRate;
size_t outCapacity = inSize;
outCapacity += mBlockSize * frameSize;
@@ -270,6 +262,33 @@
return;
}
+ class FillWork {
+ public:
+ FillWork(uint32_t flags, C2WorkOrdinalStruct ordinal,
+ const std::shared_ptr<C2Buffer> &buffer)
+ : mFlags(flags), mOrdinal(ordinal), mBuffer(buffer) {}
+ ~FillWork() = default;
+
+ void operator()(const std::unique_ptr<C2Work> &work) {
+ work->worklets.front()->output.flags = (C2FrameData::flags_t)mFlags;
+ work->worklets.front()->output.buffers.clear();
+ work->worklets.front()->output.ordinal = mOrdinal;
+ work->workletsProcessed = 1u;
+ work->result = C2_OK;
+ if (mBuffer) {
+ work->worklets.front()->output.buffers.push_back(mBuffer);
+ }
+ ALOGV("timestamp = %lld, index = %lld, w/%s buffer",
+ mOrdinal.timestamp.peekll(), mOrdinal.frameIndex.peekll(),
+ mBuffer ? "" : "o");
+ }
+
+ private:
+ const uint32_t mFlags;
+ const C2WorkOrdinalStruct mOrdinal;
+ const std::shared_ptr<C2Buffer> mBuffer;
+ };
+
mEncoderWriteData = true;
mEncoderReturnedNbBytes = 0;
size_t inPos = 0;
@@ -308,14 +327,33 @@
mOutputBlock.reset();
return;
}
- fillEmptyWork(work);
- if (mEncoderReturnedNbBytes != 0) {
- std::shared_ptr<C2Buffer> buffer = createLinearBuffer(std::move(mOutputBlock), 0, mEncoderReturnedNbBytes);
- work->worklets.front()->output.buffers.push_back(buffer);
- work->worklets.front()->output.ordinal.timestamp = mAnchorTimeStamp + outTimeStamp;
- } else {
- ALOGV("encoder process_interleaved returned without data to write");
+
+ // cloneAndSend will create clone of work when more than one encoded frame is produced
+ while (mOutputBuffers.size() > 1) {
+ const OutputBuffer& front = mOutputBuffers.front();
+ C2WorkOrdinalStruct ordinal = work->input.ordinal;
+ ordinal.frameIndex = front.frameIndex;
+ ordinal.timestamp = front.timestampUs;
+ cloneAndSend(work->input.ordinal.frameIndex.peeku(), work,
+ FillWork(C2FrameData::FLAG_INCOMPLETE, ordinal, front.buffer));
+ mOutputBuffers.pop_front();
}
+
+ std::shared_ptr<C2Buffer> buffer;
+ C2WorkOrdinalStruct ordinal = work->input.ordinal;
+ if (mOutputBuffers.size() == 1) {
+ const OutputBuffer& front = mOutputBuffers.front();
+ ordinal.frameIndex = front.frameIndex;
+ ordinal.timestamp = front.timestampUs;
+ buffer = front.buffer;
+ mOutputBuffers.pop_front();
+ }
+ // finish the response for the overall transaction.
+ // this includes any final frame that the encoder produced during this request
+ // this response is required even if no data was encoded.
+ FillWork((C2FrameData::flags_t)(eos ? C2FrameData::FLAG_END_OF_STREAM : 0),
+ ordinal, buffer)(work);
+
mOutputBlock = nullptr;
if (eos) {
mSignalledOutputEos = true;
@@ -349,6 +387,8 @@
// write encoded data
C2WriteView wView = mOutputBlock->map().get();
uint8_t* outData = wView.data();
+ const uint32_t sampleRate = mIntf->getSampleRate();
+ const uint64_t outTimeStamp = mProcessedSamples * 1000000ll / sampleRate;
ALOGV("writing %zu bytes of encoded data on output", bytes);
// increment mProcessedSamples to maintain audio synchronization during
// play back
@@ -359,7 +399,12 @@
return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
}
memcpy(outData + mEncoderReturnedNbBytes, buffer, bytes);
+
+ std::shared_ptr<C2Buffer> c2Buffer =
+ createLinearBuffer(mOutputBlock, mEncoderReturnedNbBytes, bytes);
+ mOutputBuffers.push_back({c2Buffer, mAnchorTimeStamp + outTimeStamp, current_frame});
mEncoderReturnedNbBytes += bytes;
+
return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
}
diff --git a/media/codec2/components/flac/C2SoftFlacEnc.h b/media/codec2/components/flac/C2SoftFlacEnc.h
index b3f01d5..a971ab5 100644
--- a/media/codec2/components/flac/C2SoftFlacEnc.h
+++ b/media/codec2/components/flac/C2SoftFlacEnc.h
@@ -79,6 +79,12 @@
unsigned mHeaderOffset;
bool mWroteHeader;
char mHeader[FLAC_HEADER_SIZE];
+ struct OutputBuffer {
+ std::shared_ptr<C2Buffer> buffer;
+ c2_cntr64_t timestampUs;
+ std::uint64_t frameIndex;
+ };
+ std::list<OutputBuffer> mOutputBuffers;
C2_DO_NOT_COPY(C2SoftFlacEnc);
};
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index be00d1e..91a107f 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -1586,7 +1586,8 @@
watcher->inputDelay(inputDelayValue)
.pipelineDelay(pipelineDelayValue)
.outputDelay(outputDelayValue)
- .smoothnessFactor(kSmoothnessFactor);
+ .smoothnessFactor(kSmoothnessFactor)
+ .tunneled(mTunneled);
watcher->flush();
}
diff --git a/media/codec2/sfplugin/CCodecConfig.cpp b/media/codec2/sfplugin/CCodecConfig.cpp
index 0253815..f185a1c 100644
--- a/media/codec2/sfplugin/CCodecConfig.cpp
+++ b/media/codec2/sfplugin/CCodecConfig.cpp
@@ -619,30 +619,30 @@
.limitTo(D::OUTPUT & D::READ));
deprecated(ConfigMapper(KEY_HDR10_PLUS_INFO, C2_PARAMKEY_INPUT_HDR10_PLUS_INFO, "value")
- .limitTo(D::VIDEO & D::PARAM & D::INPUT));
+ .limitTo(D::VIDEO & D::PARAM & D::INPUT & (D::CONFIG | D::PARAM)));
deprecated(ConfigMapper(KEY_HDR10_PLUS_INFO, C2_PARAMKEY_OUTPUT_HDR10_PLUS_INFO, "value")
- .limitTo(D::VIDEO & D::OUTPUT));
+ .limitTo(D::VIDEO & D::OUTPUT & D::READ));
add(ConfigMapper(
std::string(C2_PARAMKEY_INPUT_HDR_DYNAMIC_INFO) + ".type",
C2_PARAMKEY_INPUT_HDR_DYNAMIC_INFO, "type")
- .limitTo(D::VIDEO & D::PARAM & D::INPUT));
+ .limitTo(D::VIDEO & D::PARAM & D::INPUT & (D::CONFIG | D::PARAM)));
add(ConfigMapper(
std::string(C2_PARAMKEY_INPUT_HDR_DYNAMIC_INFO) + ".data",
C2_PARAMKEY_INPUT_HDR_DYNAMIC_INFO, "data")
- .limitTo(D::VIDEO & D::PARAM & D::INPUT));
+ .limitTo(D::VIDEO & D::PARAM & D::INPUT & (D::CONFIG | D::PARAM)));
add(ConfigMapper(
std::string(C2_PARAMKEY_OUTPUT_HDR_DYNAMIC_INFO) + ".type",
C2_PARAMKEY_OUTPUT_HDR_DYNAMIC_INFO, "type")
- .limitTo(D::VIDEO & D::OUTPUT));
+ .limitTo(D::VIDEO & D::OUTPUT & D::READ));
add(ConfigMapper(
std::string(C2_PARAMKEY_OUTPUT_HDR_DYNAMIC_INFO) + ".data",
C2_PARAMKEY_OUTPUT_HDR_DYNAMIC_INFO, "data")
- .limitTo(D::VIDEO & D::OUTPUT));
+ .limitTo(D::VIDEO & D::OUTPUT & D::READ));
add(ConfigMapper(C2_PARAMKEY_TEMPORAL_LAYERING, C2_PARAMKEY_TEMPORAL_LAYERING, "")
.limitTo(D::ENCODER & D::VIDEO & D::OUTPUT));
diff --git a/media/codec2/sfplugin/PipelineWatcher.cpp b/media/codec2/sfplugin/PipelineWatcher.cpp
index bc9197c..fa70a28 100644
--- a/media/codec2/sfplugin/PipelineWatcher.cpp
+++ b/media/codec2/sfplugin/PipelineWatcher.cpp
@@ -45,6 +45,11 @@
return *this;
}
+PipelineWatcher &PipelineWatcher::tunneled(bool value) {
+ mTunneled = value;
+ return *this;
+}
+
void PipelineWatcher::onWorkQueued(
uint64_t frameIndex,
std::vector<std::shared_ptr<C2Buffer>> &&buffers,
@@ -87,8 +92,13 @@
ALOGV("onWorkDone(frameIndex=%llu)", (unsigned long long)frameIndex);
auto it = mFramesInPipeline.find(frameIndex);
if (it == mFramesInPipeline.end()) {
- ALOGD("onWorkDone: frameIndex not found (%llu); ignored",
- (unsigned long long)frameIndex);
+ if (!mTunneled) {
+ ALOGD("onWorkDone: frameIndex not found (%llu); ignored",
+ (unsigned long long)frameIndex);
+ } else {
+ ALOGV("onWorkDone: frameIndex not found (%llu); ignored",
+ (unsigned long long)frameIndex);
+ }
return;
}
(void)mFramesInPipeline.erase(it);
diff --git a/media/codec2/sfplugin/PipelineWatcher.h b/media/codec2/sfplugin/PipelineWatcher.h
index 1e23147..b29c7cd 100644
--- a/media/codec2/sfplugin/PipelineWatcher.h
+++ b/media/codec2/sfplugin/PipelineWatcher.h
@@ -37,7 +37,8 @@
: mInputDelay(0),
mPipelineDelay(0),
mOutputDelay(0),
- mSmoothnessFactor(0) {}
+ mSmoothnessFactor(0),
+ mTunneled(false) {}
~PipelineWatcher() = default;
/**
@@ -65,6 +66,12 @@
PipelineWatcher &smoothnessFactor(uint32_t value);
/**
+ * \param value the new tunneled value
+ * \return this object
+ */
+ PipelineWatcher &tunneled(bool value);
+
+ /**
* Client queued a work item to the component.
*
* \param frameIndex input frame index of this work
@@ -122,6 +129,7 @@
uint32_t mPipelineDelay;
uint32_t mOutputDelay;
uint32_t mSmoothnessFactor;
+ bool mTunneled;
struct Frame {
Frame(std::vector<std::shared_ptr<C2Buffer>> &&b,
diff --git a/media/libaudiohal/TEST_MAPPING b/media/libaudiohal/TEST_MAPPING
index 3de5a9f..78a9dbc 100644
--- a/media/libaudiohal/TEST_MAPPING
+++ b/media/libaudiohal/TEST_MAPPING
@@ -7,6 +7,9 @@
"include-filter": "android.nativemedia.aaudio.AAudioTests#AAudioBasic.*"
}
]
+ },
+ {
+ "name": "CoreAudioHalAidlTest"
}
]
}
diff --git a/media/libaudiohal/impl/Android.bp b/media/libaudiohal/impl/Android.bp
index 502bcc7..fc04cb3 100644
--- a/media/libaudiohal/impl/Android.bp
+++ b/media/libaudiohal/impl/Android.bp
@@ -251,6 +251,7 @@
shared_libs: [
"android.hardware.common-V2-ndk",
"android.hardware.common.fmq-V1-ndk",
+ "av-audio-types-aidl-ndk",
"libaudio_aidl_conversion_common_cpp",
"libaudio_aidl_conversion_common_ndk",
"libaudio_aidl_conversion_common_ndk_cpp",
@@ -309,6 +310,7 @@
filegroup {
name: "core_audio_hal_aidl_src_files",
srcs: [
+ "ConversionHelperAidl.cpp",
"DeviceHalAidl.cpp",
"DevicesFactoryHalAidl.cpp",
"StreamHalAidl.cpp",
diff --git a/media/libaudiohal/impl/ConversionHelperAidl.cpp b/media/libaudiohal/impl/ConversionHelperAidl.cpp
new file mode 100644
index 0000000..7197bf2
--- /dev/null
+++ b/media/libaudiohal/impl/ConversionHelperAidl.cpp
@@ -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.
+ */
+
+#define LOG_TAG "ConversionHelperAidl"
+
+#include <memory>
+
+#include <media/AidlConversionUtil.h>
+#include <utils/Log.h>
+
+#include "ConversionHelperAidl.h"
+
+using aidl::android::aidl_utils::statusTFromBinderStatus;
+using aidl::android::hardware::audio::core::VendorParameter;
+using aidl::android::media::audio::IHalAdapterVendorExtension;
+
+namespace android {
+
+status_t parseAndGetVendorParameters(
+ std::shared_ptr<IHalAdapterVendorExtension> vendorExt,
+ const VendorParametersRecipient& recipient,
+ const AudioParameter& parameterKeys,
+ String8* values) {
+ using ParameterScope = IHalAdapterVendorExtension::ParameterScope;
+ if (parameterKeys.size() == 0) return OK;
+ const String8 rawKeys = parameterKeys.keysToString();
+ if (vendorExt == nullptr) {
+ ALOGW("%s: unknown parameters, ignored: \"%s\"", __func__, rawKeys.c_str());
+ return OK;
+ }
+
+ std::vector<std::string> parameterIds;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(vendorExt->parseVendorParameterIds(
+ ParameterScope(recipient.index()),
+ std::string(rawKeys.c_str()), ¶meterIds)));
+ if (parameterIds.empty()) return OK;
+
+ std::vector<VendorParameter> parameters;
+ if (recipient.index() == static_cast<int>(ParameterScope::MODULE)) {
+ auto module = std::get<static_cast<int>(ParameterScope::MODULE)>(recipient);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(module->getVendorParameters(
+ parameterIds, ¶meters)));
+ } else if (recipient.index() == static_cast<int>(ParameterScope::STREAM)) {
+ auto stream = std::get<static_cast<int>(ParameterScope::STREAM)>(recipient);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(stream->getVendorParameters(
+ parameterIds, ¶meters)));
+ } else {
+ LOG_ALWAYS_FATAL("%s: unexpected recipient variant index: %zu",
+ __func__, recipient.index());
+ }
+ if (!parameters.empty()) {
+ std::string vendorParameters;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(vendorExt->processVendorParameters(
+ ParameterScope(recipient.index()),
+ parameters, &vendorParameters)));
+ // Re-parse the vendor-provided string to ensure that it is correct.
+ AudioParameter reparse(String8(vendorParameters.c_str()));
+ if (reparse.size() != 0) {
+ if (!values->empty()) {
+ values->append(";");
+ }
+ values->append(reparse.toString().c_str());
+ }
+ }
+ return OK;
+}
+
+status_t parseAndSetVendorParameters(
+ std::shared_ptr<IHalAdapterVendorExtension> vendorExt,
+ const VendorParametersRecipient& recipient,
+ const AudioParameter& parameters) {
+ using ParameterScope = IHalAdapterVendorExtension::ParameterScope;
+ if (parameters.size() == 0) return OK;
+ const String8 rawKeysAndValues = parameters.toString();
+ if (vendorExt == nullptr) {
+ ALOGW("%s: unknown parameters, ignored: \"%s\"", __func__, rawKeysAndValues.c_str());
+ return OK;
+ }
+
+ std::vector<VendorParameter> syncParameters, asyncParameters;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(vendorExt->parseVendorParameters(
+ ParameterScope(recipient.index()),
+ std::string(rawKeysAndValues.c_str()),
+ &syncParameters, &asyncParameters)));
+ if (recipient.index() == static_cast<int>(ParameterScope::MODULE)) {
+ auto module = std::get<static_cast<int>(ParameterScope::MODULE)>(recipient);
+ if (!syncParameters.empty()) {
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(module->setVendorParameters(
+ syncParameters, false /*async*/)));
+ }
+ if (!asyncParameters.empty()) {
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(module->setVendorParameters(
+ asyncParameters, true /*async*/)));
+ }
+ } else if (recipient.index() == static_cast<int>(ParameterScope::STREAM)) {
+ auto stream = std::get<static_cast<int>(ParameterScope::STREAM)>(recipient);
+ if (!syncParameters.empty()) {
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(stream->setVendorParameters(
+ syncParameters, false /*async*/)));
+ }
+ if (!asyncParameters.empty()) {
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(stream->setVendorParameters(
+ asyncParameters, true /*async*/)));
+ }
+ } else {
+ LOG_ALWAYS_FATAL("%s: unexpected recipient variant index: %zu",
+ __func__, recipient.index());
+ }
+ return OK;
+}
+
+} // namespace android
diff --git a/media/libaudiohal/impl/ConversionHelperAidl.h b/media/libaudiohal/impl/ConversionHelperAidl.h
index 5534d13..0fadd9c 100644
--- a/media/libaudiohal/impl/ConversionHelperAidl.h
+++ b/media/libaudiohal/impl/ConversionHelperAidl.h
@@ -18,8 +18,12 @@
#include <string>
#include <string_view>
+#include <variant>
#include <vector>
+#include <aidl/android/hardware/audio/core/IModule.h>
+#include <aidl/android/hardware/audio/core/IStreamCommon.h>
+#include <aidl/android/media/audio/IHalAdapterVendorExtension.h>
#include <android-base/expected.h>
#include <error/Result.h>
#include <media/AudioParameter.h>
@@ -74,4 +78,18 @@
return false;
}
+// Must use the same order of elements as IHalAdapterVendorExtension::ParameterScope.
+using VendorParametersRecipient = std::variant<
+ std::shared_ptr<::aidl::android::hardware::audio::core::IModule>,
+ std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon>>;
+status_t parseAndGetVendorParameters(
+ std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension> vendorExt,
+ const VendorParametersRecipient& recipient,
+ const AudioParameter& parameterKeys,
+ String8* values);
+status_t parseAndSetVendorParameters(
+ std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension> vendorExt,
+ const VendorParametersRecipient& recipient,
+ const AudioParameter& parameters);
+
} // namespace android
diff --git a/media/libaudiohal/impl/DeviceHalAidl.cpp b/media/libaudiohal/impl/DeviceHalAidl.cpp
index 922604f..e6e7c6a 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalAidl.cpp
@@ -62,6 +62,7 @@
using aidl::android::media::audio::common::Int;
using aidl::android::media::audio::common::MicrophoneDynamicInfo;
using aidl::android::media::audio::common::MicrophoneInfo;
+using aidl::android::media::audio::IHalAdapterVendorExtension;
using aidl::android::hardware::audio::common::getFrameSizeInBytes;
using aidl::android::hardware::audio::common::isBitPositionFlagSet;
using aidl::android::hardware::audio::common::isDefaultAudioFormat;
@@ -76,6 +77,7 @@
using aidl::android::hardware::audio::core::ITelephony;
using aidl::android::hardware::audio::core::ModuleDebug;
using aidl::android::hardware::audio::core::StreamDescriptor;
+using aidl::android::hardware::audio::core::VendorParameter;
namespace android {
@@ -125,9 +127,10 @@
} // namespace
-DeviceHalAidl::DeviceHalAidl(const std::string& instance, const std::shared_ptr<IModule>& module)
+DeviceHalAidl::DeviceHalAidl(const std::string& instance, const std::shared_ptr<IModule>& module,
+ const std::shared_ptr<IHalAdapterVendorExtension>& vext)
: ConversionHelperAidl("DeviceHalAidl"),
- mInstance(instance), mModule(module),
+ mInstance(instance), mModule(module), mVendorExt(vext),
mTelephony(retrieveSubInterface<ITelephony>(module, &IModule::getTelephony)),
mBluetooth(retrieveSubInterface<IBluetooth>(module, &IModule::getBluetooth)),
mBluetoothA2dp(retrieveSubInterface<IBluetoothA2dp>(module, &IModule::getBluetoothA2dp)),
@@ -286,19 +289,24 @@
if (status_t status = filterAndUpdateBtScoParameters(parameters); status != OK) {
ALOGW("%s: filtering or updating BT SCO parameters failed: %d", __func__, status);
}
-
- ALOGW_IF(parameters.size() != 0, "%s: unknown parameters, ignored: \"%s\"",
- __func__, parameters.toString().c_str());
- return OK;
+ if (status_t status = filterAndUpdateScreenParameters(parameters); status != OK) {
+ ALOGW("%s: filtering or updating screen parameters failed: %d", __func__, status);
+ }
+ return parseAndSetVendorParameters(mVendorExt, mModule, parameters);
}
-status_t DeviceHalAidl::getParameters(const String8& keys __unused, String8 *values) {
+status_t DeviceHalAidl::getParameters(const String8& keys, String8 *values) {
TIME_CHECK();
- // FIXME(b/278976019): Support keyReconfigA2dpSupported via vendor plugin
- values->clear();
if (!mModule) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
- return OK;
+ if (values == nullptr) {
+ return BAD_VALUE;
+ }
+ AudioParameter parameterKeys(keys), result;
+ if (status_t status = filterAndRetrieveBtA2dpParameters(parameterKeys, &result); status != OK) {
+ ALOGW("%s: filtering or retrieving BT A2DP parameters failed: %d", __func__, status);
+ }
+ *values = result.toString();
+ return parseAndGetVendorParameters(mVendorExt, mModule, parameterKeys, values);
}
namespace {
@@ -568,7 +576,7 @@
return NO_INIT;
}
*outStream = sp<StreamOutHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
- std::move(ret.stream), this /*callbackBroker*/);
+ std::move(ret.stream), mVendorExt, this /*callbackBroker*/);
mStreams.insert(std::pair(*outStream, aidlPatch.id));
void* cbCookie = (*outStream).get();
{
@@ -629,7 +637,7 @@
return NO_INIT;
}
*inStream = sp<StreamInHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
- std::move(ret.stream), this /*micInfoProvider*/);
+ std::move(ret.stream), mVendorExt, this /*micInfoProvider*/);
mStreams.insert(std::pair(*inStream, aidlPatch.id));
cleanups.disarmAll();
return OK;
@@ -1090,9 +1098,23 @@
return OK;
}
+status_t DeviceHalAidl::filterAndRetrieveBtA2dpParameters(
+ AudioParameter &keys, AudioParameter *result) {
+ TIME_CHECK();
+ if (String8 key = String8(AudioParameter::keyReconfigA2dpSupported); keys.containsKey(key)) {
+ keys.remove(key);
+ bool supports;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+ mBluetoothA2dp->supportsOffloadReconfiguration(&supports)));
+ result->addInt(key, supports ? 1 : 0);
+ }
+ return OK;
+}
+
status_t DeviceHalAidl::filterAndUpdateBtA2dpParameters(AudioParameter ¶meters) {
TIME_CHECK();
std::optional<bool> a2dpEnabled;
+ std::optional<std::vector<VendorParameter>> reconfigureOffload;
(void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
parameters, String8(AudioParameter::keyBtA2dpSuspended),
[&a2dpEnabled](const String8& trueOrFalse) {
@@ -1107,10 +1129,27 @@
AudioParameter::keyBtA2dpSuspended, trueOrFalse.c_str());
return BAD_VALUE;
}));
- // FIXME(b/278976019): Support keyReconfigA2dp via vendor plugin
+ (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
+ parameters, String8(AudioParameter::keyReconfigA2dp),
+ [&](const String8& value) -> status_t {
+ if (mVendorExt != nullptr) {
+ std::vector<VendorParameter> result;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+ mVendorExt->parseBluetoothA2dpReconfigureOffload(
+ std::string(value.c_str()), &result)));
+ reconfigureOffload = std::move(result);
+ } else {
+ reconfigureOffload = std::vector<VendorParameter>();
+ }
+ return OK;
+ }));
if (mBluetoothA2dp != nullptr && a2dpEnabled.has_value()) {
return statusTFromBinderStatus(mBluetoothA2dp->setEnabled(a2dpEnabled.value()));
}
+ if (mBluetoothA2dp != nullptr && reconfigureOffload.has_value()) {
+ return statusTFromBinderStatus(mBluetoothA2dp->reconfigureOffload(
+ reconfigureOffload.value()));
+ }
return OK;
}
@@ -1234,6 +1273,44 @@
return OK;
}
+status_t DeviceHalAidl::filterAndUpdateScreenParameters(AudioParameter ¶meters) {
+ TIME_CHECK();
+ (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
+ parameters, String8(AudioParameter::keyScreenState),
+ [&](const String8& onOrOff) -> status_t {
+ std::optional<bool> isTurnedOn;
+ if (onOrOff == AudioParameter::valueOn) {
+ isTurnedOn = true;
+ } else if (onOrOff == AudioParameter::valueOff) {
+ isTurnedOn = false;
+ }
+ if (!isTurnedOn.has_value()) {
+ ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
+ AudioParameter::keyScreenState, onOrOff.c_str());
+ return BAD_VALUE;
+ }
+ return statusTFromBinderStatus(
+ mModule->updateScreenState(isTurnedOn.value()));
+ }));
+ (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
+ parameters, String8(AudioParameter::keyScreenRotation),
+ [&](int rotationDegrees) -> status_t {
+ IModule::ScreenRotation rotation;
+ switch (rotationDegrees) {
+ case 0: rotation = IModule::ScreenRotation::DEG_0; break;
+ case 90: rotation = IModule::ScreenRotation::DEG_90; break;
+ case 180: rotation = IModule::ScreenRotation::DEG_180; break;
+ case 270: rotation = IModule::ScreenRotation::DEG_270; break;
+ default:
+ ALOGE("setParameters: parameter key \"%s\" has invalid value %d",
+ AudioParameter::keyScreenRotation, rotationDegrees);
+ return BAD_VALUE;
+ }
+ return statusTFromBinderStatus(mModule->updateScreenRotation(rotation));
+ }));
+ return OK;
+}
+
status_t DeviceHalAidl::findOrCreatePatch(
const AudioPatch& requestedPatch, AudioPatch* patch, bool* created) {
std::set<int32_t> sourcePortConfigIds(requestedPatch.sourcePortConfigIds.begin(),
diff --git a/media/libaudiohal/impl/DeviceHalAidl.h b/media/libaudiohal/impl/DeviceHalAidl.h
index e29ae79..45768a3 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.h
+++ b/media/libaudiohal/impl/DeviceHalAidl.h
@@ -20,6 +20,7 @@
#include <set>
#include <vector>
+#include <aidl/android/media/audio/IHalAdapterVendorExtension.h>
#include <aidl/android/hardware/audio/core/BpModule.h>
#include <android-base/thread_annotations.h>
#include <media/audiohal/DeviceHalInterface.h>
@@ -199,7 +200,8 @@
// Must not be constructed directly by clients.
DeviceHalAidl(
const std::string& instance,
- const std::shared_ptr<::aidl::android::hardware::audio::core::IModule>& module);
+ const std::shared_ptr<::aidl::android::hardware::audio::core::IModule>& module,
+ const std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension>& vext);
~DeviceHalAidl() override = default;
@@ -210,10 +212,12 @@
status_t createOrUpdatePortConfig(
const ::aidl::android::media::audio::common::AudioPortConfig& requestedPortConfig,
PortConfigs::iterator* result, bool *created);
+ status_t filterAndRetrieveBtA2dpParameters(AudioParameter &keys, AudioParameter *result);
status_t filterAndUpdateBtA2dpParameters(AudioParameter ¶meters);
status_t filterAndUpdateBtHfpParameters(AudioParameter ¶meters);
status_t filterAndUpdateBtLeParameters(AudioParameter ¶meters);
status_t filterAndUpdateBtScoParameters(AudioParameter ¶meters);
+ status_t filterAndUpdateScreenParameters(AudioParameter ¶meters);
status_t findOrCreatePatch(
const std::set<int32_t>& sourcePortConfigIds,
const std::set<int32_t>& sinkPortConfigIds,
@@ -287,6 +291,7 @@
const std::string mInstance;
const std::shared_ptr<::aidl::android::hardware::audio::core::IModule> mModule;
+ const std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension> mVendorExt;
const std::shared_ptr<::aidl::android::hardware::audio::core::ITelephony> mTelephony;
const std::shared_ptr<::aidl::android::hardware::audio::core::IBluetooth> mBluetooth;
const std::shared_ptr<::aidl::android::hardware::audio::core::IBluetoothA2dp> mBluetoothA2dp;
diff --git a/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp b/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp
index c8cce96..f00b1a0 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp
+++ b/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp
@@ -34,7 +34,8 @@
using aidl::android::hardware::audio::core::IModule;
using aidl::android::hardware::audio::core::SurroundSoundConfig;
using aidl::android::media::audio::common::AudioHalEngineConfig;
-using ::android::detail::AudioHalVersionInfo;
+using aidl::android::media::audio::IHalAdapterVendorExtension;
+using android::detail::AudioHalVersionInfo;
namespace android {
@@ -92,7 +93,7 @@
ALOGE("%s fromBinder %s failed", __func__, serviceName.c_str());
return NO_INIT;
}
- *device = sp<DeviceHalAidl>::make(name, service);
+ *device = sp<DeviceHalAidl>::make(name, service, getVendorExtension());
return OK;
}
@@ -154,6 +155,20 @@
return OK;
}
+std::shared_ptr<IHalAdapterVendorExtension> DevicesFactoryHalAidl::getVendorExtension() {
+ if (!mVendorExt.has_value()) {
+ auto serviceName = std::string(IHalAdapterVendorExtension::descriptor) + "/default";
+ if (AServiceManager_isDeclared(serviceName.c_str())) {
+ mVendorExt = std::shared_ptr<IHalAdapterVendorExtension>(
+ IHalAdapterVendorExtension::fromBinder(ndk::SpAIBinder(
+ AServiceManager_waitForService(serviceName.c_str()))));
+ } else {
+ mVendorExt = nullptr;
+ }
+ }
+ return mVendorExt.value();
+}
+
// Main entry-point to the shared library.
extern "C" __attribute__((visibility("default"))) void* createIDevicesFactoryImpl() {
auto serviceName = std::string(IConfig::descriptor) + "/default";
diff --git a/media/libaudiohal/impl/DevicesFactoryHalAidl.h b/media/libaudiohal/impl/DevicesFactoryHalAidl.h
index 21957bc..97e3796 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalAidl.h
+++ b/media/libaudiohal/impl/DevicesFactoryHalAidl.h
@@ -17,6 +17,7 @@
#pragma once
#include <aidl/android/hardware/audio/core/IConfig.h>
+#include <aidl/android/media/audio/IHalAdapterVendorExtension.h>
#include <media/audiohal/DevicesFactoryHalInterface.h>
#include <utils/RefBase.h>
@@ -46,6 +47,11 @@
private:
const std::shared_ptr<::aidl::android::hardware::audio::core::IConfig> mConfig;
+ std::optional<std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension>>
+ mVendorExt;
+
+ std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension> getVendorExtension();
+
~DevicesFactoryHalAidl() = default;
};
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
index 52fed91..4c58fe9 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
@@ -72,14 +72,13 @@
EffectConversionHelperAidl::EffectConversionHelperAidl(
std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
- int32_t sessionId, int32_t ioId, const Descriptor& desc)
+ int32_t sessionId, int32_t ioId, const Descriptor& desc, bool isProxy)
: mSessionId(sessionId),
mIoId(ioId),
mDesc(desc),
mEffect(std::move(effect)),
mIsInputStream(mDesc.common.flags.type == Flags::Type::PRE_PROC),
- mIsProxyEffect(mDesc.common.id.proxy.has_value() &&
- mDesc.common.id.proxy.value() == mDesc.common.id.uuid) {
+ mIsProxyEffect(isProxy) {
mCommon.session = sessionId;
mCommon.ioHandle = ioId;
mCommon.input = mCommon.output = kDefaultAudioConfig;
@@ -319,17 +318,25 @@
mEffect->setParameter(Parameter::make<Parameter::deviceDescription>(aidlDevices))));
return *static_cast<int32_t*>(pReplyData) = OK;
}
+
status_t EffectConversionHelperAidl::handleSetVolume(uint32_t cmdSize, const void* pCmdData,
- uint32_t* replySize __unused,
- void* pReplyData __unused) {
+ uint32_t* replySize, void* pReplyData) {
if (cmdSize != 2 * sizeof(uint32_t) || !pCmdData) {
ALOGE("%s parameter invalid %u %p", __func__, cmdSize, pCmdData);
return BAD_VALUE;
}
- Parameter::VolumeStereo volume = {.left = (float)(*(uint32_t*)pCmdData) / (1 << 24),
- .right = (float)(*(uint32_t*)pCmdData + 1) / (1 << 24)};
+
+ constexpr uint32_t unityGain = 1 << 24;
+ Parameter::VolumeStereo volume = {.left = (float)(*(uint32_t*)pCmdData) / unityGain,
+ .right = (float)(*(uint32_t*)pCmdData + 1) / unityGain};
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
mEffect->setParameter(Parameter::make<Parameter::volumeStereo>(volume))));
+
+ // write unity gain back if volume was successfully set
+ if (replySize && *replySize == 2 * sizeof(uint32_t) && pReplyData) {
+ constexpr uint32_t vol_ret[2] = {unityGain, unityGain};
+ memcpy(pReplyData, vol_ret, sizeof(vol_ret));
+ }
return OK;
}
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.h b/media/libaudiohal/impl/EffectConversionHelperAidl.h
index 0c682ff..e2cf87f 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.h
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.h
@@ -54,7 +54,7 @@
EffectConversionHelperAidl(
std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
int32_t sessionId, int32_t ioId,
- const ::aidl::android::hardware::audio::effect::Descriptor& desc);
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc, bool isProxy);
status_t handleSetParameter(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
void* pReplyData);
diff --git a/media/libaudiohal/impl/EffectHalAidl.cpp b/media/libaudiohal/impl/EffectHalAidl.cpp
index faf5f45..a5f2c61 100644
--- a/media/libaudiohal/impl/EffectHalAidl.cpp
+++ b/media/libaudiohal/impl/EffectHalAidl.cpp
@@ -89,64 +89,64 @@
ALOGI("%s create UUID %s", __func__, typeUuid.toString().c_str());
if (typeUuid ==
::aidl::android::hardware::audio::effect::getEffectTypeUuidAcousticEchoCanceler()) {
- mConversion =
- std::make_unique<android::effect::AidlConversionAec>(effect, sessionId, ioId, desc);
+ mConversion = std::make_unique<android::effect::AidlConversionAec>(effect, sessionId, ioId,
+ desc, mIsProxyEffect);
} else if (typeUuid == ::aidl::android::hardware::audio::effect::
getEffectTypeUuidAutomaticGainControlV1()) {
mConversion = std::make_unique<android::effect::AidlConversionAgc1>(effect, sessionId, ioId,
- desc);
+ desc, mIsProxyEffect);
} else if (typeUuid == ::aidl::android::hardware::audio::effect::
getEffectTypeUuidAutomaticGainControlV2()) {
mConversion = std::make_unique<android::effect::AidlConversionAgc2>(effect, sessionId, ioId,
- desc);
+ desc, mIsProxyEffect);
} else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidBassBoost()) {
- mConversion = std::make_unique<android::effect::AidlConversionBassBoost>(effect, sessionId,
- ioId, desc);
+ mConversion = std::make_unique<android::effect::AidlConversionBassBoost>(
+ effect, sessionId, ioId, desc, mIsProxyEffect);
} else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidDownmix()) {
- mConversion = std::make_unique<android::effect::AidlConversionDownmix>(effect, sessionId,
- ioId, desc);
+ mConversion = std::make_unique<android::effect::AidlConversionDownmix>(
+ effect, sessionId, ioId, desc, mIsProxyEffect);
} else if (typeUuid ==
::aidl::android::hardware::audio::effect::getEffectTypeUuidDynamicsProcessing()) {
- mConversion =
- std::make_unique<android::effect::AidlConversionDp>(effect, sessionId, ioId, desc);
+ mConversion = std::make_unique<android::effect::AidlConversionDp>(effect, sessionId, ioId,
+ desc, mIsProxyEffect);
} else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidEnvReverb()) {
- mConversion = std::make_unique<android::effect::AidlConversionEnvReverb>(effect, sessionId,
- ioId, desc);
+ mConversion = std::make_unique<android::effect::AidlConversionEnvReverb>(
+ effect, sessionId, ioId, desc, mIsProxyEffect);
} else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidEqualizer()) {
- mConversion =
- std::make_unique<android::effect::AidlConversionEq>(effect, sessionId, ioId, desc);
+ mConversion = std::make_unique<android::effect::AidlConversionEq>(effect, sessionId, ioId,
+ desc, mIsProxyEffect);
} else if (typeUuid ==
::aidl::android::hardware::audio::effect::getEffectTypeUuidHapticGenerator()) {
mConversion = std::make_unique<android::effect::AidlConversionHapticGenerator>(
- effect, sessionId, ioId, desc);
+ effect, sessionId, ioId, desc, mIsProxyEffect);
} else if (typeUuid ==
::aidl::android::hardware::audio::effect::getEffectTypeUuidLoudnessEnhancer()) {
mConversion = std::make_unique<android::effect::AidlConversionLoudnessEnhancer>(
- effect, sessionId, ioId, desc);
+ effect, sessionId, ioId, desc, mIsProxyEffect);
} else if (typeUuid ==
::aidl::android::hardware::audio::effect::getEffectTypeUuidNoiseSuppression()) {
mConversion = std::make_unique<android::effect::AidlConversionNoiseSuppression>(
- effect, sessionId, ioId, desc);
+ effect, sessionId, ioId, desc, mIsProxyEffect);
} else if (typeUuid ==
::aidl::android::hardware::audio::effect::getEffectTypeUuidPresetReverb()) {
mConversion = std::make_unique<android::effect::AidlConversionPresetReverb>(
- effect, sessionId, ioId, desc);
+ effect, sessionId, ioId, desc, mIsProxyEffect);
} else if (typeUuid ==
::aidl::android::hardware::audio::effect::getEffectTypeUuidSpatializer()) {
mConversion = std::make_unique<android::effect::AidlConversionSpatializer>(
- effect, sessionId, ioId, desc);
+ effect, sessionId, ioId, desc, mIsProxyEffect);
} else if (typeUuid ==
::aidl::android::hardware::audio::effect::getEffectTypeUuidVirtualizer()) {
mConversion = std::make_unique<android::effect::AidlConversionVirtualizer>(
- effect, sessionId, ioId, desc);
+ effect, sessionId, ioId, desc, mIsProxyEffect);
} else if (typeUuid ==
::aidl::android::hardware::audio::effect::getEffectTypeUuidVisualizer()) {
- mConversion = std::make_unique<android::effect::AidlConversionVisualizer>(effect, sessionId,
- ioId, desc);
+ mConversion = std::make_unique<android::effect::AidlConversionVisualizer>(
+ effect, sessionId, ioId, desc, mIsProxyEffect);
} else {
// For unknown UUID, use vendor extension implementation
mConversion = std::make_unique<android::effect::AidlConversionVendorExtension>(
- effect, sessionId, ioId, desc);
+ effect, sessionId, ioId, desc, mIsProxyEffect);
}
return OK;
}
diff --git a/media/libaudiohal/impl/StreamHalAidl.cpp b/media/libaudiohal/impl/StreamHalAidl.cpp
index d1044dc..c84f80f 100644
--- a/media/libaudiohal/impl/StreamHalAidl.cpp
+++ b/media/libaudiohal/impl/StreamHalAidl.cpp
@@ -43,6 +43,7 @@
using ::aidl::android::hardware::audio::core::StreamDescriptor;
using ::aidl::android::hardware::audio::core::MmapBufferDescriptor;
using ::aidl::android::media::audio::common::MicrophoneDynamicInfo;
+using ::aidl::android::media::audio::IHalAdapterVendorExtension;
namespace android {
@@ -73,12 +74,14 @@
StreamHalAidl::StreamHalAidl(
std::string_view className, bool isInput, const audio_config& config,
int32_t nominalLatency, StreamContextAidl&& context,
- const std::shared_ptr<IStreamCommon>& stream)
+ const std::shared_ptr<IStreamCommon>& stream,
+ const std::shared_ptr<IHalAdapterVendorExtension>& vext)
: ConversionHelperAidl(className),
mIsInput(isInput),
mConfig(configToBase(config)),
mContext(std::move(context)),
- mStream(stream) {
+ mStream(stream),
+ mVendorExt(vext) {
{
std::lock_guard l(mLock);
mLastReply.latencyMs = nominalLatency;
@@ -125,7 +128,6 @@
status_t StreamHalAidl::setParameters(const String8& kvPairs) {
TIME_CHECK();
if (!mStream) return NO_INIT;
-
AudioParameter parameters(kvPairs);
ALOGD("%s: parameters: %s", __func__, parameters.toString().c_str());
@@ -134,18 +136,18 @@
[&](int hwAvSyncId) {
return statusTFromBinderStatus(mStream->updateHwAvSyncId(hwAvSyncId));
}));
-
- ALOGW_IF(parameters.size() != 0, "%s: unknown parameters, ignored: %s",
- __func__, parameters.toString().c_str());
- return OK;
+ return parseAndSetVendorParameters(mVendorExt, mStream, parameters);
}
status_t StreamHalAidl::getParameters(const String8& keys __unused, String8 *values) {
- ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
TIME_CHECK();
- values->clear();
- // AIDL HAL doesn't support getParameters API.
- return INVALID_OPERATION;
+ if (!mStream) return NO_INIT;
+ if (values == nullptr) {
+ return BAD_VALUE;
+ }
+ AudioParameter parameterKeys(keys), result;
+ *values = result.toString();
+ return parseAndGetVendorParameters(mVendorExt, mStream, parameterKeys, values);
}
status_t StreamHalAidl::getFrameSize(size_t *size) {
@@ -533,9 +535,11 @@
StreamOutHalAidl::StreamOutHalAidl(
const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency,
- const std::shared_ptr<IStreamOut>& stream, const sp<CallbackBroker>& callbackBroker)
+ const std::shared_ptr<IStreamOut>& stream,
+ const std::shared_ptr<IHalAdapterVendorExtension>& vext,
+ const sp<CallbackBroker>& callbackBroker)
: StreamHalAidl("StreamOutHalAidl", false /*isInput*/, config, nominalLatency,
- std::move(context), getStreamCommon(stream)),
+ std::move(context), getStreamCommon(stream), vext),
mStream(stream), mCallbackBroker(callbackBroker) {
// Initialize the offload metadata
mOffloadMetadata.sampleRate = static_cast<int32_t>(config.sample_rate);
@@ -861,9 +865,11 @@
StreamInHalAidl::StreamInHalAidl(
const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency,
- const std::shared_ptr<IStreamIn>& stream, const sp<MicrophoneInfoProvider>& micInfoProvider)
+ const std::shared_ptr<IStreamIn>& stream,
+ const std::shared_ptr<IHalAdapterVendorExtension>& vext,
+ const sp<MicrophoneInfoProvider>& micInfoProvider)
: StreamHalAidl("StreamInHalAidl", true /*isInput*/, config, nominalLatency,
- std::move(context), getStreamCommon(stream)),
+ std::move(context), getStreamCommon(stream), vext),
mStream(stream), mMicInfoProvider(micInfoProvider) {}
status_t StreamInHalAidl::setGain(float gain) {
diff --git a/media/libaudiohal/impl/StreamHalAidl.h b/media/libaudiohal/impl/StreamHalAidl.h
index 75a1dd9..3b369bd 100644
--- a/media/libaudiohal/impl/StreamHalAidl.h
+++ b/media/libaudiohal/impl/StreamHalAidl.h
@@ -26,9 +26,11 @@
#include <aidl/android/hardware/audio/core/BpStreamIn.h>
#include <aidl/android/hardware/audio/core/BpStreamOut.h>
#include <aidl/android/hardware/audio/core/MmapBufferDescriptor.h>
+#include <aidl/android/media/audio/IHalAdapterVendorExtension.h>
#include <fmq/AidlMessageQueue.h>
#include <media/audiohal/EffectHalInterface.h>
#include <media/audiohal/StreamHalInterface.h>
+#include <media/AidlConversionUtil.h>
#include <media/AudioParameter.h>
#include "ConversionHelperAidl.h"
@@ -48,7 +50,7 @@
typedef AidlMessageQueue<int8_t,
::aidl::android::hardware::common::fmq::SynchronizedReadWrite> DataMQ;
- explicit StreamContextAidl(
+ StreamContextAidl(
::aidl::android::hardware::audio::core::StreamDescriptor& descriptor,
bool isAsynchronous)
: mFrameSizeBytes(descriptor.frameSizeBytes),
@@ -185,6 +187,9 @@
status_t legacyReleaseAudioPatch() override;
protected:
+ // For tests.
+ friend class sp<StreamHalAidl>;
+
template<class T>
static std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon> getStreamCommon(
const std::shared_ptr<T>& stream);
@@ -195,7 +200,8 @@
const audio_config& config,
int32_t nominalLatency,
StreamContextAidl&& context,
- const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon>& stream);
+ const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon>& stream,
+ const std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension>& vext);
~StreamHalAidl() override;
@@ -247,6 +253,7 @@
::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply = nullptr);
const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon> mStream;
+ const std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension> mVendorExt;
std::mutex mLock;
::aidl::android::hardware::audio::core::StreamDescriptor::Reply mLastReply GUARDED_BY(mLock);
// mStreamPowerLog is used for audio signal power logging.
@@ -349,6 +356,7 @@
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::media::audio::IHalAdapterVendorExtension>& vext,
const sp<CallbackBroker>& callbackBroker);
~StreamOutHalAidl() override;
@@ -401,6 +409,7 @@
StreamInHalAidl(
const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency,
const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamIn>& stream,
+ const std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension>& vext,
const sp<MicrophoneInfoProvider>& micInfoProvider);
~StreamInHalAidl() override = default;
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAec.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAec.h
index 3ee419a..61dd36a 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAec.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAec.h
@@ -26,8 +26,9 @@
public:
AidlConversionAec(std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
int32_t sessionId, int32_t ioId,
- const ::aidl::android::hardware::audio::effect::Descriptor& desc)
- : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc,
+ bool isProxyEffect)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {}
~AidlConversionAec() {}
private:
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc1.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc1.h
index b0509fd..364b473 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc1.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc1.h
@@ -26,8 +26,9 @@
public:
AidlConversionAgc1(std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
int32_t sessionId, int32_t ioId,
- const ::aidl::android::hardware::audio::effect::Descriptor& desc)
- : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc,
+ bool isProxyEffect)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {}
~AidlConversionAgc1() {}
private:
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc2.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc2.h
index 8f7eac7..df9a9ec 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc2.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc2.h
@@ -26,8 +26,9 @@
public:
AidlConversionAgc2(std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
int32_t sessionId, int32_t ioId,
- const ::aidl::android::hardware::audio::effect::Descriptor& desc)
- : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc,
+ bool isProxyEffect)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {}
~AidlConversionAgc2() {}
private:
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.h
index 9664aa1..424b837 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.h
@@ -27,8 +27,8 @@
AidlConversionBassBoost(
std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
int32_t sessionId, int32_t ioId,
- const ::aidl::android::hardware::audio::effect::Descriptor& desc)
- : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc, bool isProxyEffect)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {}
~AidlConversionBassBoost() {}
private:
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDownmix.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDownmix.h
index 8b28ca3..f963f66 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDownmix.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDownmix.h
@@ -26,8 +26,9 @@
public:
AidlConversionDownmix(std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
int32_t sessionId, int32_t ioId,
- const ::aidl::android::hardware::audio::effect::Descriptor& desc)
- : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc,
+ bool isProxyEffect)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {}
~AidlConversionDownmix() {}
private:
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.h
index c5d5a54..62714c3 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.h
@@ -26,8 +26,9 @@
public:
AidlConversionDp(std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
int32_t sessionId, int32_t ioId,
- const ::aidl::android::hardware::audio::effect::Descriptor& desc)
- : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc,
+ bool isProxyEffect)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {}
~AidlConversionDp() {}
private:
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.h
index 8b92374..95042eb 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.h
@@ -27,8 +27,8 @@
AidlConversionEnvReverb(
std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
int32_t sessionId, int32_t ioId,
- const ::aidl::android::hardware::audio::effect::Descriptor& desc)
- : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc, bool isProxyEffect)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {}
~AidlConversionEnvReverb() {}
private:
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp
index 45b98a1..fc867c7 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp
@@ -161,6 +161,9 @@
return param.writeToValue(&bands);
}
case EQ_PARAM_LEVEL_RANGE: {
+ if (mDesc.capability.range.getTag() != Range::equalizer) {
+ return OK;
+ }
const auto& ranges = mDesc.capability.range.get<Range::equalizer>();
for (const auto& r : ranges) {
if (r.min.getTag() == Equalizer::bandLevels &&
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.h
index f94556c..53566e2 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.h
@@ -25,9 +25,10 @@
class AidlConversionEq : public EffectConversionHelperAidl {
public:
AidlConversionEq(std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
- int32_t sessionId, int32_t ioId,
- const ::aidl::android::hardware::audio::effect::Descriptor& desc)
- : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ int32_t sessionId, int32_t ioId,
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc,
+ bool isProxyEffect)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {}
~AidlConversionEq() {}
private:
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.h
index 03114a5..9890bfb 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.h
@@ -27,8 +27,8 @@
AidlConversionHapticGenerator(
std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
int32_t sessionId, int32_t ioId,
- const ::aidl::android::hardware::audio::effect::Descriptor& desc)
- : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc, bool isProxyEffect)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {}
~AidlConversionHapticGenerator() {}
private:
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.h
index c0402f9..2ce14a6 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.h
@@ -27,8 +27,8 @@
AidlConversionLoudnessEnhancer(
std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
int32_t sessionId, int32_t ioId,
- const ::aidl::android::hardware::audio::effect::Descriptor& desc)
- : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc, bool isProxyEffect)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {}
~AidlConversionLoudnessEnhancer() {}
private:
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionNoiseSuppression.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionNoiseSuppression.h
index f51e13a..fac121d 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionNoiseSuppression.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionNoiseSuppression.h
@@ -27,8 +27,8 @@
AidlConversionNoiseSuppression(
std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
int32_t sessionId, int32_t ioId,
- const ::aidl::android::hardware::audio::effect::Descriptor& desc)
- : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc, bool isProxyEffect)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {}
~AidlConversionNoiseSuppression() {}
private:
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionPresetReverb.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionPresetReverb.h
index 397d6e6..b975d72 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionPresetReverb.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionPresetReverb.h
@@ -27,8 +27,8 @@
AidlConversionPresetReverb(
std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
int32_t sessionId, int32_t ioId,
- const ::aidl::android::hardware::audio::effect::Descriptor& desc)
- : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc, bool isProxyEffect)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {}
~AidlConversionPresetReverb() {}
private:
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.h
index c44567c..7c60b14 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.h
@@ -27,8 +27,8 @@
AidlConversionSpatializer(
std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
int32_t sessionId, int32_t ioId,
- const ::aidl::android::hardware::audio::effect::Descriptor& desc)
- : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc, bool isProxyEffect)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {}
~AidlConversionSpatializer() {}
private:
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.h
index fd22e5c..16bfeba 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.h
@@ -27,8 +27,8 @@
AidlConversionVendorExtension(
std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
int32_t sessionId, int32_t ioId,
- const ::aidl::android::hardware::audio::effect::Descriptor& desc)
- : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc, bool isProxyEffect)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {}
~AidlConversionVendorExtension() {}
private:
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVirtualizer.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVirtualizer.h
index 91c0fcd..359d884 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVirtualizer.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVirtualizer.h
@@ -27,8 +27,8 @@
AidlConversionVirtualizer(
std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
int32_t sessionId, int32_t ioId,
- const ::aidl::android::hardware::audio::effect::Descriptor& desc)
- : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc, bool isProxyEffect)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {}
~AidlConversionVirtualizer() {}
private:
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.h
index e380bc6..bc9320f 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.h
@@ -27,8 +27,8 @@
AidlConversionVisualizer(
std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
int32_t sessionId, int32_t ioId,
- const ::aidl::android::hardware::audio::effect::Descriptor& desc)
- : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc, bool isProxyEffect)
+ : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {}
~AidlConversionVisualizer() {}
private:
diff --git a/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp b/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp
index 8433c48..ea20794 100644
--- a/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp
+++ b/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp
@@ -15,17 +15,56 @@
*/
#include <memory>
+#include <string>
+#include <vector>
#define LOG_TAG "CoreAudioHalAidlTest"
#include <gtest/gtest.h>
#include <DeviceHalAidl.h>
+#include <StreamHalAidl.h>
#include <aidl/android/hardware/audio/core/BnModule.h>
+#include <aidl/android/hardware/audio/core/BnStreamCommon.h>
+#include <aidl/android/media/audio/BnHalAdapterVendorExtension.h>
+#include <aidl/android/media/audio/common/Int.h>
#include <utils/Log.h>
namespace {
-class ModuleMock : public ::aidl::android::hardware::audio::core::BnModule {
+using ::aidl::android::hardware::audio::core::VendorParameter;
+
+class VendorParameterMock {
+ public:
+ const std::vector<std::string>& getRetrievedParameterIds() const { return mGetParameterIds; }
+ const std::vector<VendorParameter>& getAsyncParameters() const { return mAsyncParameters; }
+ const std::vector<VendorParameter>& getSyncParameters() const { return mSyncParameters; }
+
+ protected:
+ ndk::ScopedAStatus getVendorParametersImpl(const std::vector<std::string>& in_parameterIds) {
+ mGetParameterIds.insert(mGetParameterIds.end(), in_parameterIds.begin(),
+ in_parameterIds.end());
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus setVendorParametersImpl(const std::vector<VendorParameter>& in_parameters,
+ bool async) {
+ if (async) {
+ mAsyncParameters.insert(mAsyncParameters.end(), in_parameters.begin(),
+ in_parameters.end());
+ } else {
+ mSyncParameters.insert(mSyncParameters.end(), in_parameters.begin(),
+ in_parameters.end());
+ }
+ return ndk::ScopedAStatus::ok();
+ }
+
+ private:
+ std::vector<std::string> mGetParameterIds;
+ std::vector<VendorParameter> mAsyncParameters;
+ std::vector<VendorParameter> mSyncParameters;
+};
+
+class ModuleMock : public ::aidl::android::hardware::audio::core::BnModule,
+ public VendorParameterMock {
public:
bool isScreenTurnedOn() const { return mIsScreenTurnedOn; }
ScreenRotation getScreenRotation() const { return mScreenRotation; }
@@ -132,15 +171,13 @@
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus generateHwAvSyncId(int32_t*) override { return ndk::ScopedAStatus::ok(); }
- ndk::ScopedAStatus getVendorParameters(
- const std::vector<std::string>&,
- std::vector<::aidl::android::hardware::audio::core::VendorParameter>*) override {
- return ndk::ScopedAStatus::ok();
+ ndk::ScopedAStatus getVendorParameters(const std::vector<std::string>& in_parameterIds,
+ std::vector<VendorParameter>*) override {
+ return getVendorParametersImpl(in_parameterIds);
}
- ndk::ScopedAStatus setVendorParameters(
- const std::vector<::aidl::android::hardware::audio::core::VendorParameter>&,
- bool) override {
- return ndk::ScopedAStatus::ok();
+ ndk::ScopedAStatus setVendorParameters(const std::vector<VendorParameter>& in_parameters,
+ bool async) override {
+ return setVendorParametersImpl(in_parameters, async);
}
ndk::ScopedAStatus addDeviceEffect(
int32_t,
@@ -169,15 +206,166 @@
ScreenRotation mScreenRotation = ScreenRotation::DEG_0;
};
-android::String8 createParameterString(const char* key, const char* value) {
+class StreamCommonMock : public ::aidl::android::hardware::audio::core::BnStreamCommon,
+ public VendorParameterMock {
+ ndk::ScopedAStatus close() override { return ndk::ScopedAStatus::ok(); }
+ ndk::ScopedAStatus prepareToClose() override { return ndk::ScopedAStatus::ok(); }
+ ndk::ScopedAStatus updateHwAvSyncId(int32_t) override { return ndk::ScopedAStatus::ok(); }
+ ndk::ScopedAStatus getVendorParameters(const std::vector<std::string>& in_parameterIds,
+ std::vector<VendorParameter>*) override {
+ return getVendorParametersImpl(in_parameterIds);
+ }
+ ndk::ScopedAStatus setVendorParameters(const std::vector<VendorParameter>& in_parameters,
+ bool async) override {
+ return setVendorParametersImpl(in_parameters, async);
+ }
+ ndk::ScopedAStatus addEffect(
+ const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>&) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus removeEffect(
+ const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>&) override {
+ return ndk::ScopedAStatus::ok();
+ }
+};
+
+VendorParameter makeVendorParameter(const std::string& id, int value) {
+ VendorParameter result{.id = id};
+ // Note: in real life, a parcelable type defined by vendor must be used,
+ // here we use Int just for test purposes.
+ ::aidl::android::media::audio::common::Int vendorValue{.value = value};
+ result.ext.setParcelable(std::move(vendorValue));
+ return result;
+}
+
+android::status_t parseVendorParameter(const VendorParameter& param, int* value) {
+ std::optional<::aidl::android::media::audio::common::Int> vendorValue;
+ RETURN_STATUS_IF_ERROR(param.ext.getParcelable(&vendorValue));
+ if (!vendorValue.has_value()) return android::BAD_VALUE;
+ *value = vendorValue.value().value;
+ return android::OK;
+}
+
+class TestHalAdapterVendorExtension
+ : public ::aidl::android::media::audio::BnHalAdapterVendorExtension {
+ public:
+ static const std::string kLegacyParameterKey;
+ static const std::string kLegacyAsyncParameterKey;
+ static const std::string kModuleVendorParameterId;
+ static const std::string kStreamVendorParameterId;
+
+ private:
+ ndk::ScopedAStatus parseVendorParameterIds(ParameterScope in_scope,
+ const std::string& in_rawKeys,
+ std::vector<std::string>* _aidl_return) override {
+ android::AudioParameter keys(android::String8(in_rawKeys.c_str()));
+ for (size_t i = 0; i < keys.size(); ++i) {
+ android::String8 key;
+ if (android::status_t status = keys.getAt(i, key); status != android::OK) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ switch (in_scope) {
+ case ParameterScope::MODULE:
+ if (key == android::String8(kLegacyParameterKey.c_str()) ||
+ key == android::String8(kLegacyAsyncParameterKey.c_str())) {
+ _aidl_return->push_back(kModuleVendorParameterId);
+ } else {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ break;
+ case ParameterScope::STREAM:
+ if (key == android::String8(kLegacyParameterKey.c_str()) ||
+ key == android::String8(kLegacyAsyncParameterKey.c_str())) {
+ _aidl_return->push_back(kStreamVendorParameterId);
+ } else {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ break;
+ }
+ }
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus parseVendorParameters(
+ ParameterScope in_scope, const std::string& in_rawKeysAndValues,
+ std::vector<VendorParameter>* out_syncParameters,
+ std::vector<VendorParameter>* out_asyncParameters) override {
+ android::AudioParameter legacy(android::String8(in_rawKeysAndValues.c_str()));
+ for (size_t i = 0; i < legacy.size(); ++i) {
+ android::String8 key;
+ if (android::status_t status = legacy.getAt(i, key); status != android::OK) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ int value;
+ if (android::status_t status = legacy.getInt(key, value); status != android::OK) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ std::string parameterId;
+ switch (in_scope) {
+ case ParameterScope::MODULE:
+ parameterId = kModuleVendorParameterId;
+ break;
+ case ParameterScope::STREAM:
+ parameterId = kStreamVendorParameterId;
+ break;
+ }
+ if (key == android::String8(kLegacyParameterKey.c_str())) {
+ out_syncParameters->push_back(makeVendorParameter(parameterId, value));
+ } else if (key == android::String8(kLegacyAsyncParameterKey.c_str())) {
+ out_asyncParameters->push_back(makeVendorParameter(parameterId, value));
+ } else {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ }
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus parseBluetoothA2dpReconfigureOffload(
+ const std::string&, std::vector<VendorParameter>*) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus parseBluetoothLeReconfigureOffload(const std::string&,
+ std::vector<VendorParameter>*) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus processVendorParameters(ParameterScope in_scope,
+ const std::vector<VendorParameter>& in_parameters,
+ std::string* _aidl_return) override {
+ android::AudioParameter legacy;
+ for (const auto& vendorParam : in_parameters) {
+ if ((in_scope == ParameterScope::MODULE &&
+ vendorParam.id == kModuleVendorParameterId) ||
+ (in_scope == ParameterScope::STREAM &&
+ vendorParam.id == kStreamVendorParameterId)) {
+ int value;
+ if (android::status_t status = parseVendorParameter(vendorParam, &value);
+ status != android::OK) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ legacy.addInt(android::String8(kLegacyParameterKey.c_str()), value);
+ }
+ }
+ *_aidl_return = legacy.toString().c_str();
+ return ndk::ScopedAStatus::ok();
+ }
+};
+
+const std::string TestHalAdapterVendorExtension::kLegacyParameterKey = "aosp_test_param";
+const std::string TestHalAdapterVendorExtension::kLegacyAsyncParameterKey = "aosp_test_param_async";
+// Note: in real life, there is no need to explicitly separate "module" and "stream"
+// parameters, here it's done just for test purposes.
+const std::string TestHalAdapterVendorExtension::kModuleVendorParameterId =
+ "aosp.test.module.parameter";
+const std::string TestHalAdapterVendorExtension::kStreamVendorParameterId =
+ "aosp.test.stream.parameter";
+
+android::String8 createParameterString(const std::string& key, const std::string& value) {
android::AudioParameter params;
- params.add(android::String8(key), android::String8(value));
+ params.add(android::String8(key.c_str()), android::String8(value.c_str()));
return params.toString();
}
-android::String8 createParameterString(const char* key, int value) {
+android::String8 createParameterString(const std::string& key, int value) {
android::AudioParameter params;
- params.addInt(android::String8(key), value);
+ params.addInt(android::String8(key.c_str()), value);
return params.toString();
}
@@ -211,7 +399,7 @@
public:
void SetUp() override {
mModule = ndk::SharedRefBase::make<ModuleMock>();
- mDevice = sp<DeviceHalAidl>::make("test", mModule);
+ mDevice = sp<DeviceHalAidl>::make("test", mModule, nullptr /*vext*/);
}
void TearDown() override {
mDevice.clear();
@@ -251,3 +439,169 @@
mDevice->setParameters(createParameterString(AudioParameter::keyScreenRotation, 42)));
EXPECT_EQ(ScreenRotation::DEG_0, mModule->getScreenRotation());
}
+
+// Without a vendor extension, any unrecognized parameters must be ignored.
+TEST_F(DeviceHalAidlTest, VendorParameterIgnored) {
+ EXPECT_EQ(0UL, mModule->getAsyncParameters().size());
+ EXPECT_EQ(0UL, mModule->getSyncParameters().size());
+ EXPECT_EQ(OK, mDevice->setParameters(createParameterString("random_name", "random_value")));
+ EXPECT_EQ(0UL, mModule->getAsyncParameters().size());
+ EXPECT_EQ(0UL, mModule->getSyncParameters().size());
+
+ EXPECT_EQ(0UL, mModule->getRetrievedParameterIds().size());
+ String8 values;
+ EXPECT_EQ(OK, mDevice->getParameters(String8("random_name"), &values));
+ EXPECT_EQ(0UL, mModule->getRetrievedParameterIds().size());
+ EXPECT_TRUE(values.empty());
+}
+
+class DeviceHalAidlVendorParametersTest : public testing::Test {
+ public:
+ void SetUp() override {
+ mModule = ndk::SharedRefBase::make<ModuleMock>();
+ mVendorExt = ndk::SharedRefBase::make<TestHalAdapterVendorExtension>();
+ mDevice = sp<DeviceHalAidl>::make("test", mModule, mVendorExt);
+ }
+ void TearDown() override {
+ mDevice.clear();
+ mVendorExt.reset();
+ mModule.reset();
+ }
+
+ protected:
+ std::shared_ptr<ModuleMock> mModule;
+ std::shared_ptr<TestHalAdapterVendorExtension> mVendorExt;
+ sp<DeviceHalAidl> mDevice;
+};
+
+TEST_F(DeviceHalAidlVendorParametersTest, GetVendorParameter) {
+ EXPECT_EQ(0UL, mModule->getRetrievedParameterIds().size());
+ String8 values;
+ EXPECT_EQ(OK, mDevice->getParameters(
+ String8(TestHalAdapterVendorExtension::kLegacyParameterKey.c_str()),
+ &values));
+ EXPECT_EQ(1UL, mModule->getRetrievedParameterIds().size());
+ if (mModule->getRetrievedParameterIds().size() >= 1) {
+ EXPECT_EQ(TestHalAdapterVendorExtension::kModuleVendorParameterId,
+ mModule->getRetrievedParameterIds()[0]);
+ }
+}
+
+TEST_F(DeviceHalAidlVendorParametersTest, SetVendorParameter) {
+ EXPECT_EQ(0UL, mModule->getAsyncParameters().size());
+ EXPECT_EQ(0UL, mModule->getSyncParameters().size());
+ EXPECT_EQ(OK, mDevice->setParameters(createParameterString(
+ TestHalAdapterVendorExtension::kLegacyParameterKey, 42)));
+ EXPECT_EQ(0UL, mModule->getAsyncParameters().size());
+ EXPECT_EQ(1UL, mModule->getSyncParameters().size());
+ EXPECT_EQ(OK, mDevice->setParameters(createParameterString(
+ TestHalAdapterVendorExtension::kLegacyAsyncParameterKey, 43)));
+ EXPECT_EQ(1UL, mModule->getAsyncParameters().size());
+ EXPECT_EQ(1UL, mModule->getSyncParameters().size());
+ if (mModule->getSyncParameters().size() >= 1) {
+ EXPECT_EQ(TestHalAdapterVendorExtension::kModuleVendorParameterId,
+ mModule->getSyncParameters()[0].id);
+ int value{};
+ EXPECT_EQ(android::OK, parseVendorParameter(mModule->getSyncParameters()[0], &value));
+ EXPECT_EQ(42, value);
+ }
+ if (mModule->getAsyncParameters().size() >= 1) {
+ EXPECT_EQ(TestHalAdapterVendorExtension::kModuleVendorParameterId,
+ mModule->getAsyncParameters()[0].id);
+ int value{};
+ EXPECT_EQ(android::OK, parseVendorParameter(mModule->getAsyncParameters()[0], &value));
+ EXPECT_EQ(43, value);
+ }
+}
+
+TEST_F(DeviceHalAidlVendorParametersTest, SetInvalidVendorParameters) {
+ android::AudioParameter legacy;
+ legacy.addInt(android::String8(TestHalAdapterVendorExtension::kLegacyParameterKey.c_str()), 42);
+ legacy.addInt(android::String8(TestHalAdapterVendorExtension::kLegacyAsyncParameterKey.c_str()),
+ 43);
+ legacy.addInt(android::String8("random_name"), 44);
+ EXPECT_EQ(0UL, mModule->getAsyncParameters().size());
+ EXPECT_EQ(0UL, mModule->getSyncParameters().size());
+ // TestHalAdapterVendorExtension throws an error for unknown parameters.
+ EXPECT_EQ(android::BAD_VALUE, mDevice->setParameters(legacy.toString()));
+ EXPECT_EQ(0UL, mModule->getAsyncParameters().size());
+ EXPECT_EQ(0UL, mModule->getSyncParameters().size());
+}
+
+class StreamHalAidlVendorParametersTest : public testing::Test {
+ public:
+ void SetUp() override {
+ mStreamCommon = ndk::SharedRefBase::make<StreamCommonMock>();
+ mVendorExt = ndk::SharedRefBase::make<TestHalAdapterVendorExtension>();
+ struct audio_config config = AUDIO_CONFIG_INITIALIZER;
+ ::aidl::android::hardware::audio::core::StreamDescriptor descriptor;
+ mStream = sp<StreamHalAidl>::make("test", false /*isInput*/, config, 0 /*nominalLatency*/,
+ StreamContextAidl(descriptor, false /*isAsynchronous*/),
+ mStreamCommon, mVendorExt);
+ }
+ void TearDown() override {
+ mStream.clear();
+ mVendorExt.reset();
+ mStreamCommon.reset();
+ }
+
+ protected:
+ std::shared_ptr<StreamCommonMock> mStreamCommon;
+ std::shared_ptr<TestHalAdapterVendorExtension> mVendorExt;
+ sp<StreamHalAidl> mStream;
+};
+
+TEST_F(StreamHalAidlVendorParametersTest, GetVendorParameter) {
+ EXPECT_EQ(0UL, mStreamCommon->getRetrievedParameterIds().size());
+ String8 values;
+ EXPECT_EQ(OK, mStream->getParameters(
+ String8(TestHalAdapterVendorExtension::kLegacyParameterKey.c_str()),
+ &values));
+ EXPECT_EQ(1UL, mStreamCommon->getRetrievedParameterIds().size());
+ if (mStreamCommon->getRetrievedParameterIds().size() >= 1) {
+ EXPECT_EQ(TestHalAdapterVendorExtension::kStreamVendorParameterId,
+ mStreamCommon->getRetrievedParameterIds()[0]);
+ }
+}
+
+TEST_F(StreamHalAidlVendorParametersTest, SetVendorParameter) {
+ EXPECT_EQ(0UL, mStreamCommon->getAsyncParameters().size());
+ EXPECT_EQ(0UL, mStreamCommon->getSyncParameters().size());
+ EXPECT_EQ(OK, mStream->setParameters(createParameterString(
+ TestHalAdapterVendorExtension::kLegacyParameterKey, 42)));
+ EXPECT_EQ(0UL, mStreamCommon->getAsyncParameters().size());
+ EXPECT_EQ(1UL, mStreamCommon->getSyncParameters().size());
+ EXPECT_EQ(OK, mStream->setParameters(createParameterString(
+ TestHalAdapterVendorExtension::kLegacyAsyncParameterKey, 43)));
+ EXPECT_EQ(1UL, mStreamCommon->getAsyncParameters().size());
+ EXPECT_EQ(1UL, mStreamCommon->getSyncParameters().size());
+ if (mStreamCommon->getSyncParameters().size() >= 1) {
+ EXPECT_EQ(TestHalAdapterVendorExtension::kStreamVendorParameterId,
+ mStreamCommon->getSyncParameters()[0].id);
+ int value{};
+ EXPECT_EQ(android::OK, parseVendorParameter(mStreamCommon->getSyncParameters()[0], &value));
+ EXPECT_EQ(42, value);
+ }
+ if (mStreamCommon->getAsyncParameters().size() >= 1) {
+ EXPECT_EQ(TestHalAdapterVendorExtension::kStreamVendorParameterId,
+ mStreamCommon->getAsyncParameters()[0].id);
+ int value{};
+ EXPECT_EQ(android::OK,
+ parseVendorParameter(mStreamCommon->getAsyncParameters()[0], &value));
+ EXPECT_EQ(43, value);
+ }
+}
+
+TEST_F(StreamHalAidlVendorParametersTest, SetInvalidVendorParameters) {
+ android::AudioParameter legacy;
+ legacy.addInt(android::String8(TestHalAdapterVendorExtension::kLegacyParameterKey.c_str()), 42);
+ legacy.addInt(android::String8(TestHalAdapterVendorExtension::kLegacyAsyncParameterKey.c_str()),
+ 43);
+ legacy.addInt(android::String8("random_name"), 44);
+ EXPECT_EQ(0UL, mStreamCommon->getAsyncParameters().size());
+ EXPECT_EQ(0UL, mStreamCommon->getSyncParameters().size());
+ // TestHalAdapterVendorExtension throws an error for unknown parameters.
+ EXPECT_EQ(android::BAD_VALUE, mStream->setParameters(legacy.toString()));
+ EXPECT_EQ(0UL, mStreamCommon->getAsyncParameters().size());
+ EXPECT_EQ(0UL, mStreamCommon->getSyncParameters().size());
+}
diff --git a/media/libaudioprocessing/AudioMixerBase.cpp b/media/libaudioprocessing/AudioMixerBase.cpp
index f30eb54..3c34caa 100644
--- a/media/libaudioprocessing/AudioMixerBase.cpp
+++ b/media/libaudioprocessing/AudioMixerBase.cpp
@@ -453,9 +453,9 @@
&track->mVolume[param - VOLUME0],
&track->mPrevVolume[param - VOLUME0],
&track->mVolumeInc[param - VOLUME0])) {
- ALOGV("setParameter(%s, VOLUME%d: %04x)",
- target == VOLUME ? "VOLUME" : "RAMP_VOLUME", param - VOLUME0,
- track->volume[param - VOLUME0]);
+ ALOGV("setParameter(%s, VOLUME%d: %f)",
+ target == VOLUME ? "VOLUME" : "RAMP_VOLUME", param - VOLUME0,
+ track->mVolume[param - VOLUME0]);
invalidate();
}
} else {
@@ -630,7 +630,7 @@
if (t->volumeInc[0]|t->volumeInc[1]) {
volumeRamp = true;
- } else if (!t->doesResample() && t->volumeRL == 0) {
+ } else if (!t->doesResample() && t->isVolumeMuted()) {
n |= NEEDS_MUTE;
}
t->needs = n;
@@ -730,7 +730,7 @@
for (const int name : mEnabled) {
const std::shared_ptr<TrackBase> &t = mTracks[name];
- if (!t->doesResample() && t->volumeRL == 0) {
+ if (!t->doesResample() && t->isVolumeMuted()) {
t->needs |= NEEDS_MUTE;
t->hook = &TrackBase::track__nop;
} else {
diff --git a/media/libaudioprocessing/include/media/AudioMixerBase.h b/media/libaudioprocessing/include/media/AudioMixerBase.h
index 3419816..0d82255 100644
--- a/media/libaudioprocessing/include/media/AudioMixerBase.h
+++ b/media/libaudioprocessing/include/media/AudioMixerBase.h
@@ -290,6 +290,16 @@
audio_channel_mask_t mMixerChannelMask;
uint32_t mMixerChannelCount;
+ // consider volume muted only if all channel volume (floating point) is 0.f
+ inline bool isVolumeMuted() const {
+ for (const auto volume : mVolume) {
+ if (volume != 0) {
+ return false;
+ }
+ }
+ return true;
+ }
+
protected:
// hooks
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Process.cpp b/media/libeffects/lvm/lib/Bundle/src/LVM_Process.cpp
index 4eea04f..bfc5059 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Process.cpp
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Process.cpp
@@ -166,9 +166,9 @@
* Bypass mode or everything off, so copy the input to the output
*/
if (pToProcess != pProcessed) {
- Copy_Float(pToProcess, /* Source */
- pProcessed, /* Destination */
- (LVM_INT16)(NrChannels * NrFrames)); /* Copy all samples */
+ Copy_Float(pToProcess, /* Source */
+ pProcessed, /* Destination */
+ SampleCount); /* Copy all samples */
}
/*
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp b/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp
index d026e2b..0db7a73 100644
--- a/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp
@@ -15,9 +15,11 @@
*/
#include <cstddef>
+#include <cstdio>
#define LOG_TAG "BundleContext"
#include <android-base/logging.h>
+#include <audio_utils/power.h>
#include <Utils.h>
#include "BundleContext.h"
@@ -34,7 +36,7 @@
std::lock_guard lg(mMutex);
// init with pre-defined preset NORMAL
for (std::size_t i = 0; i < lvm::MAX_NUM_BANDS; i++) {
- mBandGaindB[i] = lvm::kSoftPresets[0 /* normal */][i];
+ mBandGainMdB[i] = lvm::kSoftPresets[0 /* normal */][i] * 100;
}
// allocate lvm instance
@@ -212,7 +214,7 @@
if (eqEnabled) {
for (int i = 0; i < lvm::MAX_NUM_BANDS; i++) {
- float bandFactor = mBandGaindB[i] / 15.0;
+ float bandFactor = mBandGainMdB[i] / 1500.0;
float bandCoefficient = lvm::kBandEnergyCoefficient[i];
float bandEnergy = bandFactor * bandCoefficient * bandCoefficient;
if (bandEnergy > 0) energyContribution += bandEnergy;
@@ -221,8 +223,8 @@
// cross EQ coefficients
float bandFactorSum = 0;
for (int i = 0; i < lvm::MAX_NUM_BANDS - 1; i++) {
- float bandFactor1 = mBandGaindB[i] / 15.0;
- float bandFactor2 = mBandGaindB[i + 1] / 15.0;
+ float bandFactor1 = mBandGainMdB[i] / 1500.0;
+ float bandFactor2 = mBandGainMdB[i + 1] / 1500.0;
if (bandFactor1 > 0 && bandFactor2 > 0) {
float crossEnergy =
@@ -244,7 +246,7 @@
if (eqEnabled) {
for (int i = 0; i < lvm::MAX_NUM_BANDS; i++) {
- float bandFactor = mBandGaindB[i] / 15.0;
+ float bandFactor = mBandGainMdB[i] / 1500.0;
float bandCrossCoefficient = lvm::kBassBoostEnergyCrossCoefficient[i];
float bandEnergy = boostFactor * bandFactor * bandCrossCoefficient;
if (bandEnergy > 0) energyBassBoost += bandEnergy;
@@ -397,15 +399,10 @@
return db_fix;
}
-// TODO: replace with more generic approach, like: audio_utils_power_from_amplitude
-int16_t BundleContext::VolToDb(uint32_t vol) const {
- int16_t dB;
-
- dB = LVC_ToDB_s32Tos16(vol << 7);
- dB = (dB + 8) >> 4;
- dB = (dB < -96) ? -96 : dB;
-
- return dB;
+/* static */
+float BundleContext::VolToDb(float vol) {
+ float dB = audio_utils_power_from_amplitude(vol);
+ return std::max(dB, -96.f);
}
RetCode BundleContext::setVolumeStereo(const Parameter::VolumeStereo& volume) {
@@ -413,11 +410,12 @@
LVM_ReturnStatus_en status = LVM_SUCCESS;
// Convert volume to dB
- int leftdB = VolToDb(volume.left);
- int rightdB = VolToDb(volume.right);
- int maxdB = std::max(leftdB, rightdB);
- int pandB = rightdB - leftdB;
- setVolumeLevel(maxdB * 100);
+ float leftdB = VolToDb(volume.left);
+ float rightdB = VolToDb(volume.right);
+
+ float maxdB = std::max(leftdB, rightdB);
+ float pandB = rightdB - leftdB;
+ setVolumeLevel(maxdB);
LOG(DEBUG) << __func__ << " pandB: " << pandB << " maxdB " << maxdB;
{
@@ -441,8 +439,8 @@
std::vector<Equalizer::BandLevel> bandLevels;
bandLevels.reserve(lvm::MAX_NUM_BANDS);
for (std::size_t i = 0; i < lvm::MAX_NUM_BANDS; i++) {
- bandLevels.emplace_back(
- Equalizer::BandLevel{static_cast<int32_t>(i), lvm::kSoftPresets[presetIdx][i]});
+ bandLevels.emplace_back(Equalizer::BandLevel{static_cast<int32_t>(i),
+ lvm::kSoftPresets[presetIdx][i] * 100});
}
RetCode ret = updateControlParameter(bandLevels);
@@ -472,7 +470,8 @@
std::vector<Equalizer::BandLevel> bandLevels;
bandLevels.reserve(lvm::MAX_NUM_BANDS);
for (std::size_t i = 0; i < lvm::MAX_NUM_BANDS; i++) {
- bandLevels.emplace_back(Equalizer::BandLevel{static_cast<int32_t>(i), mBandGaindB[i]});
+ bandLevels.emplace_back(
+ Equalizer::BandLevel{static_cast<int32_t>(i), mBandGainMdB[i]});
}
return bandLevels;
}
@@ -506,7 +505,7 @@
RETURN_VALUE_IF(!isBandLevelIndexInRange(bandLevels), RetCode::ERROR_ILLEGAL_PARAMETER,
"indexOutOfRange");
- std::array<int, lvm::MAX_NUM_BANDS> tempLevel;
+ std::array<int, lvm::MAX_NUM_BANDS> tempLevel(mBandGainMdB);
for (const auto& it : bandLevels) {
tempLevel[it.index] = it.levelMb;
}
@@ -520,14 +519,16 @@
for (std::size_t i = 0; i < lvm::MAX_NUM_BANDS; i++) {
params.pEQNB_BandDefinition[i].Frequency = lvm::kPresetsFrequencies[i];
params.pEQNB_BandDefinition[i].QFactor = lvm::kPresetsQFactors[i];
- params.pEQNB_BandDefinition[i].Gain = tempLevel[i];
+ params.pEQNB_BandDefinition[i].Gain =
+ tempLevel[i] > 0 ? (tempLevel[i] + 50) / 100 : (tempLevel[i] - 50) / 100;
}
RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, ¶ms),
RetCode::ERROR_EFFECT_LIB_ERROR, " setControlParamFailed");
}
- mBandGaindB = tempLevel;
- LOG(INFO) << __func__ << " update bandGain to " << ::android::internal::ToString(mBandGaindB);
+ mBandGainMdB = tempLevel;
+ LOG(DEBUG) << __func__ << " update bandGain to " << ::android::internal::ToString(mBandGainMdB)
+ << "mdB";
return RetCode::SUCCESS;
}
@@ -551,18 +552,18 @@
return limitLevel();
}
-RetCode BundleContext::setVolumeLevel(int level) {
+RetCode BundleContext::setVolumeLevel(float level) {
if (mMuteEnabled) {
- mLevelSaved = level / 100;
+ mLevelSaved = level;
} else {
- mVolume = level / 100;
+ mVolume = level;
}
LOG(INFO) << __func__ << " success with level " << level;
return limitLevel();
}
-int BundleContext::getVolumeLevel() const {
- return (mMuteEnabled ? mLevelSaved * 100 : mVolume * 100);
+float BundleContext::getVolumeLevel() const {
+ return (mMuteEnabled ? mLevelSaved : mVolume);
}
RetCode BundleContext::setVolumeMute(bool mute) {
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleContext.h b/media/libeffects/lvm/wrapper/Aidl/BundleContext.h
index 47d5e5a..62bb6e4 100644
--- a/media/libeffects/lvm/wrapper/Aidl/BundleContext.h
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleContext.h
@@ -80,8 +80,8 @@
RetCode setBassBoostStrength(int strength);
int getBassBoostStrength() const { return mBassStrengthSaved; }
- RetCode setVolumeLevel(int level);
- int getVolumeLevel() const;
+ RetCode setVolumeLevel(float level);
+ float getVolumeLevel() const;
RetCode setVolumeMute(bool mute);
int getVolumeMute() const { return mMuteEnabled; }
@@ -135,20 +135,20 @@
int mBassStrengthSaved = 0;
// Equalizer
int mCurPresetIdx = lvm::PRESET_CUSTOM; /* Current preset being used */
- std::array<int, lvm::MAX_NUM_BANDS> mBandGaindB;
+ std::array<int, lvm::MAX_NUM_BANDS> mBandGainMdB; /* band gain in millibels */
// Virtualizer
int mVirtStrengthSaved = 0; /* Conversion between Get/Set */
bool mVirtualizerTempDisabled = false;
::aidl::android::media::audio::common::AudioDeviceDescription mForceDevice;
// Volume
- int mLevelSaved = 0; /* for when mute is set, level must be saved */
- int mVolume = 0;
+ float mLevelSaved = 0; /* for when mute is set, level must be saved */
+ float mVolume = 0;
bool mMuteEnabled = false; /* Must store as mute = -96dB level */
void initControlParameter(LVM_ControlParams_t& params) const;
void initHeadroomParameter(LVM_HeadroomParams_t& params) const;
RetCode limitLevel();
- int16_t VolToDb(uint32_t vol) const;
+ static float VolToDb(float vol);
LVM_INT16 LVC_ToDB_s32Tos16(LVM_INT32 Lin_fix) const;
RetCode updateControlParameter(const std::vector<Equalizer::BandLevel>& bandLevels);
bool isBandLevelIndexInRange(const std::vector<Equalizer::BandLevel>& bandLevels) const;
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h b/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
index 3bc889c..143329d 100644
--- a/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
@@ -73,9 +73,9 @@
MAKE_RANGE(Equalizer, preset, 0, MAX_NUM_PRESETS - 1),
MAKE_RANGE(Equalizer, bandLevels,
std::vector<Equalizer::BandLevel>{
- Equalizer::BandLevel({.index = 0, .levelMb = -15})},
+ Equalizer::BandLevel({.index = 0, .levelMb = -1500})},
std::vector<Equalizer::BandLevel>{
- Equalizer::BandLevel({.index = MAX_NUM_BANDS - 1, .levelMb = 15})}),
+ Equalizer::BandLevel({.index = MAX_NUM_BANDS - 1, .levelMb = 1500})}),
/* 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 cd9fb60..eb7ab1a 100644
--- a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp
+++ b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp
@@ -355,7 +355,7 @@
auto tag = id.get<Volume::Id::commonTag>();
switch (tag) {
case Volume::levelDb: {
- volParam.set<Volume::levelDb>(mContext->getVolumeLevel());
+ volParam.set<Volume::levelDb>(static_cast<int>(mContext->getVolumeLevel()));
break;
}
case Volume::mute: {
@@ -384,6 +384,7 @@
if (id.getTag() == Virtualizer::Id::speakerAnglesPayload) {
auto angles = mContext->getSpeakerAngles(id.get<Virtualizer::Id::speakerAnglesPayload>());
+ RETURN_IF(angles.size() == 0, EX_ILLEGAL_ARGUMENT, "getSpeakerAnglesFailed");
Virtualizer param = Virtualizer::make<Virtualizer::speakerAngles>(angles);
specific->set<Parameter::Specific::virtualizer>(param);
return ndk::ScopedAStatus::ok();
diff --git a/media/libmedia/CharacterEncodingDetector.cpp b/media/libmedia/CharacterEncodingDetector.cpp
index 64ba977..e33cc0f 100644
--- a/media/libmedia/CharacterEncodingDetector.cpp
+++ b/media/libmedia/CharacterEncodingDetector.cpp
@@ -393,10 +393,6 @@
while (true) {
// demerit the current encoding for each "special" character found after conversion.
// The amount of demerit is somewhat arbitrarily chosen.
- int inchar;
- if (source != sourceLimit) {
- inchar = (source[0] << 8) + source[1];
- }
UChar32 c = ucnv_getNextUChar(conv, &source, sourceLimit, &status);
if (!U_SUCCESS(status)) {
break;
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index ec79b99..6f8c102 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -1254,10 +1254,6 @@
case OUTPUT_FORMAT_MPEG_4:
case OUTPUT_FORMAT_WEBM:
{
- bool isMPEG4 = true;
- if (mOutputFormat == OUTPUT_FORMAT_WEBM) {
- isMPEG4 = false;
- }
sp<MetaData> meta = new MetaData;
setupMPEG4orWEBMMetaData(&meta);
status = mWriter->start(meta.get());
diff --git a/media/libstagefright/data/media_codecs_sw.xml b/media/libstagefright/data/media_codecs_sw.xml
index b29c3b6..8b1ea03 100644
--- a/media/libstagefright/data/media_codecs_sw.xml
+++ b/media/libstagefright/data/media_codecs_sw.xml
@@ -331,8 +331,8 @@
<Limit name="alignment" value="2x2" />
<Limit name="block-size" value="8x8" />
<Limit name="block-count" range="1-4096" /> <!-- max 512x512 -->
- <Limit name="blocks-per-second" range="1-122880" />
- <Limit name="frame-rate" range="1-120" />
+ <Limit name="blocks-per-second" range="1-259200" />
+ <Limit name="frame-rate" range="1-300" />
<Limit name="bitrate" range="1-10000000" />
<Limit name="complexity" range="0-10" default="0" />
<Limit name="quality" range="0-100" default="80" />
diff --git a/media/libstagefright/timedtext/test/fuzzer/Android.bp b/media/libstagefright/timedtext/test/fuzzer/Android.bp
new file mode 100644
index 0000000..6590ebb
--- /dev/null
+++ b/media/libstagefright/timedtext/test/fuzzer/Android.bp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+cc_library_static {
+ name: "timedtext_fuzz-protos",
+
+ srcs: ["timedtext_fuzz.proto"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+ shared_libs: ["libprotobuf-cpp-full"],
+ proto: {
+ type: "full",
+ canonical_path_from_root: false,
+ local_include_dirs: ["."],
+ export_proto_headers: true,
+ },
+}
+
+cc_fuzz {
+ name: "timedtext_fuzzer",
+ srcs: [
+ "timedtext_fuzzer.cpp",
+ ],
+ static_libs: [
+ "libstagefright_timedtext",
+ "timedtext_fuzz-protos",
+ ],
+ shared_libs: [
+ "libstagefright_foundation",
+ "libprotobuf-cpp-full",
+ "libbinder",
+ "libprotobuf-mutator",
+ ],
+ fuzz_config: {
+ cc: [
+ "android-media-fuzzing-reports@google.com",
+ ],
+ componentid: 155276,
+ },
+}
diff --git a/media/libstagefright/timedtext/test/fuzzer/README.md b/media/libstagefright/timedtext/test/fuzzer/README.md
new file mode 100644
index 0000000..f391ea7
--- /dev/null
+++ b/media/libstagefright/timedtext/test/fuzzer/README.md
@@ -0,0 +1,23 @@
+# Fuzzer for libstagefright_timedtext
+
+libstagefright_timedtext supports the following parameters:
+1. Flags (parameter name: `flags`)
+2. TimeMs (parameter name: `timeMs`)
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+| `flags` | 1. `TextDescriptions::OUT_OF_BAND_TEXT_SRT` 2. `TextDescriptions::GLOBAL_DESCRIPTIONS` 3. `TextDescriptions::IN_BAND_TEXT_3GPP` 4. `TextDescriptions::LOCAL_DESCRIPTIONS` | Value chosen from valid values by obtaining index from FuzzedDataProvider|
+| `timeMs` | `INT_MIN` to `INT_MAX` | Value obtained from FuzzedDataProvider|
+
+
+#### Steps to run
+
+1. Build the fuzzer
+```
+ $ mm -j$(nproc) timedtext_fuzzer
+```
+2. Run on device
+```
+ $ adb sync data
+ $ adb shell /data/fuzz/arm64/timedtext_fuzzer/timedtext_fuzzer
+```
diff --git a/media/libstagefright/timedtext/test/fuzzer/timedtext_fuzz.proto b/media/libstagefright/timedtext/test/fuzzer/timedtext_fuzz.proto
new file mode 100644
index 0000000..4c90278
--- /dev/null
+++ b/media/libstagefright/timedtext/test/fuzzer/timedtext_fuzz.proto
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+/*
+ * proto files are used for Structure Aware fuzzing so that fuzzing can be
+ * made more effective.
+ * timedtext_fuzz.proto is used to declare structures, which are used
+ * purely inside timedtext_fuzzer.
+ */
+
+syntax = "proto3";
+
+enum Flag {
+ flag3gppglobal = 0;
+ flag3gpplocal = 1;
+ flagsrtlocal = 2;
+}
+
+enum ChunkType {
+ default = 0;
+ tx3g = 1954034535;
+ styl = 1937013100;
+ krok = 1802661739;
+ hlit = 1751935348;
+ hclr = 1751346290;
+ dlay = 1684824441;
+ href = 1752327526;
+ tbox = 1952608120;
+ blnk = 1651273323;
+ txrp = 1953985136;
+}
+
+message FontRecord {
+ uint32 fontId = 1;
+ repeated uint32 font = 2;
+}
+
+message SRTLocal {
+ repeated uint32 data = 1;
+}
+
+message GPPGlobal {
+ uint64 reservedBytes = 1;
+ uint32 displayFlags = 2;
+ int32 horizontal_vertical_justification = 3;
+ uint32 rgba = 4;
+ int32 textBox = 5;
+ uint32 styleRecordStart = 6;
+ uint32 fontId = 7;
+ uint32 fontStyle = 8;
+ uint32 entryCount = 9;
+ repeated FontRecord fontEntry = 10;
+ uint32 defaultDisparity = 11;
+}
+
+message StyleRecord {
+ uint32 startchar = 1;
+ uint32 font = 2;
+ uint32 rgba = 3;
+}
+
+message TextStyleBox {
+ uint32 count = 1;
+ repeated StyleRecord record = 2;
+}
+
+message HighlightBox {
+ uint32 start = 1;
+ uint32 end = 2;
+}
+
+message HighlightColor {
+ uint32 rgba = 1;
+}
+
+message TextKaraokeBox {
+ uint32 highlightStartTime = 1;
+ uint32 entryCount = 2;
+ repeated uint64 highlightData = 3;
+}
+
+message BoxRecord {
+ uint32 topleft = 1;
+ uint32 bottomright = 2;
+}
+
+message BlinkBox {
+ uint32 charoffset = 1;
+}
+
+message HyperTextBox {
+ uint32 charoffset = 1;
+ uint32 urlLength = 2;
+ repeated uint32 url = 3;
+ uint32 altLength = 4;
+ repeated uint32 altString = 5;
+}
+
+message GPPLocalText {
+ string text = 1;
+}
+
+message GPPLocalFormat {
+ uint64 reservedBytes = 1;
+ oneof formatStyle {
+ TextStyleBox textbox = 2;
+ HighlightBox hltbox = 3;
+ HighlightColor hltcolor = 4;
+ TextKaraokeBox krokbox = 5;
+ uint32 scrollDelay = 6;
+ HyperTextBox hrefBox = 7;
+ BoxRecord boxrecord = 8;
+ BlinkBox blinkBox = 9;
+ uint32 wrapFlag = 10;
+ }
+}
+
+message GPPLocal {
+ GPPLocalText localtext = 1;
+ GPPLocalFormat format = 2;
+}
+
+message TimedText {
+ Flag handle = 1;
+ int32 timeMs = 2;
+ SRTLocal srt = 3;
+ GPPGlobal global = 4;
+ GPPLocal local = 5;
+}
diff --git a/media/libstagefright/timedtext/test/fuzzer/timedtext_fuzzer.cpp b/media/libstagefright/timedtext/test/fuzzer/timedtext_fuzzer.cpp
new file mode 100644
index 0000000..da1bdf8
--- /dev/null
+++ b/media/libstagefright/timedtext/test/fuzzer/timedtext_fuzzer.cpp
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2022 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 <binder/Parcel.h>
+#include <timedtext/TextDescriptions.h>
+#include <timedtext_fuzz.pb.h>
+#include "fuzzer/FuzzedDataProvider.h"
+#include "src/libfuzzer/libfuzzer_macro.h"
+
+using namespace android;
+constexpr int32_t kTextBytes = 2;
+constexpr int32_t kChunkBytes = 8;
+constexpr int32_t kChunkTypeBytes = 4;
+constexpr int32_t kGlobalTextOffset = 0;
+constexpr size_t kByte3Mask = 0xff000000UL;
+constexpr size_t kByte2Mask = 0x00ff0000UL;
+constexpr size_t kByte1Mask = 0x0000ff00UL;
+constexpr size_t kByte0Mask = 0x000000ffUL;
+
+/**
+ * Sets ChunkSize/ChunkType (uint32_t) in timedtext-description vector<uint8_t>
+ * by extracting each byte from ChunkSize and populating the vector.
+ */
+void setChunkParameter(std::vector<uint8_t>& timedtext, size_t param, size_t paramOffset) {
+ timedtext[paramOffset + 0] = (param & kByte3Mask) >> 24;
+ timedtext[paramOffset + 1] = (param & kByte2Mask) >> 16;
+ timedtext[paramOffset + 2] = (param & kByte1Mask) >> 8;
+ timedtext[paramOffset + 3] = (param & kByte0Mask);
+}
+
+/**
+ * Sets TextLength(uint16_t) in 3GPPLocal-description vector<uint8_t>
+ * by extracting each byte from TextLength and populating the vector.
+ */
+void setTextSize(std::vector<uint8_t>& local3GPPDescription, int32_t textLength) {
+ local3GPPDescription[0] = (textLength & kByte1Mask) >> 8;
+ local3GPPDescription[1] = (textLength & kByte0Mask);
+}
+
+DEFINE_PROTO_FUZZER(const TimedText& input) {
+ switch (input.handle()) {
+ case flag3gppglobal: {
+ size_t gppGlobalByteSize = input.global().ByteSizeLong();
+ if (gppGlobalByteSize) {
+ std::vector<uint8_t> global3GPPDescription(gppGlobalByteSize + kChunkBytes);
+ setChunkParameter(global3GPPDescription, gppGlobalByteSize, kGlobalTextOffset);
+ setChunkParameter(global3GPPDescription, tx3g, kGlobalTextOffset + kChunkTypeBytes);
+ input.global().SerializeToArray(global3GPPDescription.data() + kChunkBytes,
+ global3GPPDescription.size());
+ Parcel* parcel = new Parcel();
+ TextDescriptions::getParcelOfDescriptions(
+ global3GPPDescription.data(), global3GPPDescription.size(),
+ TextDescriptions::IN_BAND_TEXT_3GPP | TextDescriptions::GLOBAL_DESCRIPTIONS,
+ input.timems(), parcel);
+ delete parcel;
+ }
+ break;
+ }
+ case flag3gpplocal: {
+ size_t gppLocalByteSize = input.local().ByteSizeLong();
+ if (gppLocalByteSize) {
+ std::vector<uint8_t> local3GPPDescription(gppLocalByteSize + kChunkBytes +
+ kTextBytes);
+ std::string text = input.local().localtext().text();
+ int32_t textLength = text.size();
+ setTextSize(local3GPPDescription, textLength);
+ input.local().localtext().SerializeToArray(local3GPPDescription.data() + kTextBytes,
+ textLength);
+ size_t gppLocalFormatSize = input.local().format().ByteSizeLong();
+ size_t textOffset = textLength + kTextBytes;
+ setChunkParameter(local3GPPDescription, gppLocalFormatSize, textOffset);
+ switch (input.local().format().formatStyle_case()) {
+ case GPPLocalFormat::FormatStyleCase::kTextbox: {
+ setChunkParameter(local3GPPDescription, styl, textOffset + kChunkTypeBytes);
+ input.local().format().SerializeToArray(
+ local3GPPDescription.data() + textOffset + kChunkBytes,
+ gppLocalFormatSize);
+ break;
+ }
+ case GPPLocalFormat::FormatStyleCase::kHltbox: {
+ setChunkParameter(local3GPPDescription, hlit, textOffset + kChunkTypeBytes);
+ input.local().format().SerializeToArray(
+ local3GPPDescription.data() + textOffset + kChunkBytes,
+ gppLocalFormatSize);
+ break;
+ }
+ case GPPLocalFormat::FormatStyleCase::kHltcolor: {
+ setChunkParameter(local3GPPDescription, hclr, textOffset + kChunkTypeBytes);
+ input.local().format().SerializeToArray(
+ local3GPPDescription.data() + textOffset + kChunkBytes,
+ gppLocalFormatSize);
+ break;
+ }
+ case GPPLocalFormat::FormatStyleCase::kKrokbox: {
+ setChunkParameter(local3GPPDescription, krok, textOffset + kChunkTypeBytes);
+ input.local().format().SerializeToArray(
+ local3GPPDescription.data() + textOffset + kChunkBytes,
+ gppLocalFormatSize);
+ break;
+ }
+ case GPPLocalFormat::FormatStyleCase::kScrollDelay: {
+ setChunkParameter(local3GPPDescription, dlay, textOffset + kChunkTypeBytes);
+ input.local().format().SerializeToArray(
+ local3GPPDescription.data() + textOffset + kChunkBytes,
+ gppLocalFormatSize);
+ break;
+ }
+ case GPPLocalFormat::FormatStyleCase::kHrefBox: {
+ setChunkParameter(local3GPPDescription, href, textOffset + kChunkTypeBytes);
+ input.local().format().SerializeToArray(
+ local3GPPDescription.data() + textOffset + kChunkBytes,
+ gppLocalFormatSize);
+ break;
+ }
+ case GPPLocalFormat::FormatStyleCase::kBoxrecord: {
+ setChunkParameter(local3GPPDescription, tbox, textOffset + kChunkTypeBytes);
+ input.local().format().SerializeToArray(
+ local3GPPDescription.data() + textOffset + kChunkBytes,
+ gppLocalFormatSize);
+ break;
+ }
+ case GPPLocalFormat::FormatStyleCase::kBlinkBox: {
+ setChunkParameter(local3GPPDescription, blnk, textOffset + kChunkTypeBytes);
+ input.local().format().SerializeToArray(
+ local3GPPDescription.data() + textOffset + kChunkBytes,
+ gppLocalFormatSize);
+ break;
+ }
+ case GPPLocalFormat::FormatStyleCase::kWrapFlag: {
+ setChunkParameter(local3GPPDescription, txrp, textOffset + kChunkTypeBytes);
+ input.local().format().SerializeToArray(
+ local3GPPDescription.data() + textOffset + kChunkBytes,
+ gppLocalFormatSize);
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ Parcel* parcel = new Parcel();
+ TextDescriptions::getParcelOfDescriptions(
+ local3GPPDescription.data(), local3GPPDescription.size(),
+ TextDescriptions::IN_BAND_TEXT_3GPP | TextDescriptions::LOCAL_DESCRIPTIONS,
+ input.timems(), parcel);
+ delete parcel;
+ }
+ break;
+ }
+ case flagsrtlocal: {
+ size_t srtByteSize = input.srt().ByteSizeLong();
+ if (srtByteSize) {
+ std::vector<uint8_t> srtLocalDescription(srtByteSize);
+ input.srt().SerializeToArray(srtLocalDescription.data(),
+ srtLocalDescription.size());
+ Parcel* parcel = new Parcel();
+ TextDescriptions::getParcelOfDescriptions(
+ srtLocalDescription.data(), srtLocalDescription.size(),
+ TextDescriptions::OUT_OF_BAND_TEXT_SRT |
+ TextDescriptions::LOCAL_DESCRIPTIONS,
+ input.timems(), parcel);
+ delete parcel;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+}
diff --git a/media/module/extractors/mp4/MPEG4Extractor.cpp b/media/module/extractors/mp4/MPEG4Extractor.cpp
index eaca75c..38cf29d 100644
--- a/media/module/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/module/extractors/mp4/MPEG4Extractor.cpp
@@ -6500,6 +6500,16 @@
AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, 1);
}
+ void *presentationsData;
+ size_t presentationsSize;
+ if (AMediaFormat_getBuffer(
+ mFormat, AMEDIAFORMAT_KEY_AUDIO_PRESENTATION_INFO,
+ &presentationsData, &presentationsSize)) {
+ AMediaFormat_setBuffer(
+ meta, AMEDIAFORMAT_KEY_AUDIO_PRESENTATION_INFO,
+ presentationsData, presentationsSize);
+ }
+
++mCurrentSampleIndex;
*out = mBuffer;
diff --git a/media/tests/SampleVideoEncoder/app/src/main/java/com/android/media/samplevideoencoder/MediaCodecSurfaceEncoder.java b/media/tests/SampleVideoEncoder/app/src/main/java/com/android/media/samplevideoencoder/MediaCodecSurfaceEncoder.java
index 011c38c..e2fe177 100644
--- a/media/tests/SampleVideoEncoder/app/src/main/java/com/android/media/samplevideoencoder/MediaCodecSurfaceEncoder.java
+++ b/media/tests/SampleVideoEncoder/app/src/main/java/com/android/media/samplevideoencoder/MediaCodecSurfaceEncoder.java
@@ -90,13 +90,13 @@
}
String decoderMime = decoderFormat.getString(MediaFormat.KEY_MIME);
- ArrayList<String> listOfDeocders =
+ ArrayList<String> decoders =
MediaCodecBase.selectCodecs(decoderMime, null, null, false, mIsCodecSoftware);
- if (listOfDeocders.isEmpty()) {
+ if (decoders.isEmpty()) {
Log.e(TAG, "No suitable decoder found for mime: " + decoderMime);
return -1;
}
- mDecoder = MediaCodec.createByCodecName(listOfDeocders.get(0));
+ mDecoder = MediaCodec.createByCodecName(decoders.get(0));
MediaFormat encoderFormat = setUpEncoderFormat(decoderFormat);
ArrayList<String> listOfEncoders =
diff --git a/media/tests/benchmark/MediaBenchmarkTest/AndroidTest.xml b/media/tests/benchmark/MediaBenchmarkTest/AndroidTest.xml
index 1890661..1b66b01 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/AndroidTest.xml
+++ b/media/tests/benchmark/MediaBenchmarkTest/AndroidTest.xml
@@ -14,18 +14,26 @@
limitations under the License.
-->
<configuration description="Runs Media Benchmark Tests">
+ <option name="test-tag" value="MediaBenchmarkTest" />
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
- <option name="push-file"
- key="https://storage.googleapis.com/android_media/frameworks/av/media/tests/benchmark/MediaBenchmark.zip?unzip=true"
- value="/data/local/tmp/MediaBenchmark/res/" />
</target_preparer>
- <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
- <option name="cleanup-apks" value="false" />
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="host" />
+ <option name="config-filename" value="MediaBenchmarkTest" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+ <option name="push-all" value="true" />
+ <option name="media-folder-name" value="MediaBenchmarkTest-1.1" />
+ <option name="dynamic-config-module" value="MediaBenchmarkTest" />
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
<option name="test-file-name" value="MediaBenchmarkTest.apk" />
</target_preparer>
- <option name="test-tag" value="MediaBenchmarkTest" />
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.media.benchmark" />
<option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
diff --git a/media/tests/benchmark/MediaBenchmarkTest/DynamicConfig.xml b/media/tests/benchmark/MediaBenchmarkTest/DynamicConfig.xml
new file mode 100644
index 0000000..1278f29
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<dynamicConfig>
+ <entry key="media_files_url">
+ <value>https://storage.googleapis.com/android_media/frameworks/av/media/tests/benchmark/MediaBenchmark-1.1.zip</value>
+ </entry>
+</dynamicConfig>
diff --git a/media/tests/benchmark/MediaBenchmarkTest/res/values/strings.xml b/media/tests/benchmark/MediaBenchmarkTest/res/values/strings.xml
index 24dbccc..2bef254 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/res/values/strings.xml
+++ b/media/tests/benchmark/MediaBenchmarkTest/res/values/strings.xml
@@ -1,4 +1,4 @@
<resources>
- <string name="input_file_path">/data/local/tmp/MediaBenchmark/res/</string>
+ <string name="input_file_path">/sdcard/test/MediaBenchmarkTest-1.1/</string>
<string name="output_file_path">/data/local/tmp/MediaBenchmark/output/</string>
</resources>
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 1c46ddd..6963bb9 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -2447,7 +2447,8 @@
// make sure the input buffer configuration for the new first effect in the chain
// is updated if needed (can switch from HAL channel mask to mixer channel mask)
- if (i == 0 && size > 1) {
+ if (type != EFFECT_FLAG_TYPE_AUXILIARY // TODO(b/284522658) breaks for aux FX, why?
+ && i == 0 && size > 1) {
mEffects[0]->configure();
mEffects[0]->setInBuffer(mInBuffer);
mEffects[0]->updateAccessMode(); // reconfig if neeeded.
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 576de02..8c09477 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -3705,7 +3705,7 @@
bool AudioFlinger::PlaybackThread::threadLoop()
NO_THREAD_SAFETY_ANALYSIS // manual locking of AudioFlinger
{
- tlNBLogWriter = mNBLogWriter.get();
+ aflog::setThreadWriter(mNBLogWriter.get());
Vector< sp<Track> > tracksToRemove;
diff --git a/services/audioflinger/afutils/Android.bp b/services/audioflinger/afutils/Android.bp
index 4309bf5..5eac519 100644
--- a/services/audioflinger/afutils/Android.bp
+++ b/services/audioflinger/afutils/Android.bp
@@ -7,11 +7,108 @@
default_applicable_licenses: ["frameworks_av_services_audioflinger_license"],
}
+audioflinger_utils_tidy_errors = [
+ // https://clang.llvm.org/extra/clang-tidy/checks/list.html
+ // For many categories, the checks are too many to specify individually.
+ // Feel free to disable as needed - as warnings are generally ignored,
+ // we treat warnings as errors.
+ "android-*",
+ "bugprone-*",
+ "cert-*",
+ "clang-analyzer-security*",
+ "google-*",
+ "misc-*",
+ //"modernize-*", // explicitly list the modernize as they can be subjective.
+ "modernize-avoid-bind",
+ //"modernize-avoid-c-arrays", // std::array<> can be verbose
+ "modernize-concat-nested-namespaces",
+ //"modernize-deprecated-headers", // C headers still ok even if there is C++ equivalent.
+ "modernize-deprecated-ios-base-aliases",
+ "modernize-loop-convert",
+ "modernize-make-shared",
+ "modernize-make-unique",
+ // "modernize-pass-by-value",
+ "modernize-raw-string-literal",
+ "modernize-redundant-void-arg",
+ "modernize-replace-auto-ptr",
+ "modernize-replace-random-shuffle",
+ "modernize-return-braced-init-list",
+ "modernize-shrink-to-fit",
+ "modernize-unary-static-assert",
+ // "modernize-use-auto", // found in MediaMetricsService.h, debatable - auto can obscure type
+ "modernize-use-bool-literals",
+ "modernize-use-default-member-init",
+ "modernize-use-emplace",
+ "modernize-use-equals-default",
+ "modernize-use-equals-delete",
+ // "modernize-use-nodiscard",
+ "modernize-use-noexcept",
+ "modernize-use-nullptr",
+ "modernize-use-override",
+ //"modernize-use-trailing-return-type", // not necessarily more readable
+ "modernize-use-transparent-functors",
+ "modernize-use-uncaught-exceptions",
+ "modernize-use-using",
+ "performance-*",
+
+ // Remove some pedantic stylistic requirements.
+ "-google-readability-casting", // C++ casts not always necessary and may be verbose
+ "-google-readability-todo", // do not require TODO(info)
+
+ "-bugprone-unhandled-self-assignment",
+ "-bugprone-suspicious-string-compare",
+ "-cert-oop54-cpp", // found in TransactionLog.h
+ "-bugprone-narrowing-conversions", // b/182410845
+
+ // TODO(b/275642749) Reenable these warnings
+ "-misc-non-private-member-variables-in-classes",
+]
+
+// Eventually use common tidy defaults
+cc_defaults {
+ name: "audioflinger_utils_flags_defaults",
+ // https://clang.llvm.org/docs/UsersManual.html#command-line-options
+ // https://clang.llvm.org/docs/DiagnosticsReference.html
+ cflags: [
+ "-Wall",
+ "-Wdeprecated",
+ "-Werror",
+ "-Werror=implicit-fallthrough",
+ "-Werror=sometimes-uninitialized",
+ "-Werror=conditional-uninitialized",
+ "-Wextra",
+
+ // suppress some warning chatter.
+ "-Wno-deprecated-copy-with-dtor",
+ "-Wno-deprecated-copy-with-user-provided-dtor",
+
+ "-Wredundant-decls",
+ "-Wshadow",
+ "-Wstrict-aliasing",
+ "-fstrict-aliasing",
+ "-Wthread-safety",
+ //"-Wthread-safety-negative", // experimental - looks broken in R.
+ "-Wunreachable-code",
+ "-Wunreachable-code-break",
+ "-Wunreachable-code-return",
+ "-Wunused",
+ "-Wused-but-marked-unused",
+ "-D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS",
+ ],
+ // https://clang.llvm.org/extra/clang-tidy/
+ tidy: true,
+ tidy_checks: audioflinger_utils_tidy_errors,
+ tidy_checks_as_errors: audioflinger_utils_tidy_errors,
+ tidy_flags: [
+ "-format-style=file",
+ ],
+}
+
cc_library {
name: "libaudioflinger_utils",
defaults: [
- "audioflinger_flags_defaults",
+ "audioflinger_utils_flags_defaults",
],
srcs: [
diff --git a/services/audioflinger/afutils/AudioWatchdog.cpp b/services/audioflinger/afutils/AudioWatchdog.cpp
index 877e776..48a07a5 100644
--- a/services/audioflinger/afutils/AudioWatchdog.cpp
+++ b/services/audioflinger/afutils/AudioWatchdog.cpp
@@ -38,12 +38,12 @@
mUnderruns, mLogs, buf);
}
-bool AudioWatchdog::threadLoop()
+bool AudioWatchdog::threadLoop() NO_THREAD_SAFETY_ANALYSIS // unique_lock
{
{
- AutoMutex _l(mMyLock);
+ std::unique_lock _l(mLock);
if (mPaused) {
- mMyCond.wait(mMyLock);
+ mCond.wait(_l);
// ignore previous timestamp after resume()
mOldTsValid = false;
// force an immediate log on first underrun after resume()
@@ -65,7 +65,7 @@
return true;
}
time_t sec = newTs.tv_sec - mOldTs.tv_sec;
- long nsec = newTs.tv_nsec - mOldTs.tv_nsec;
+ auto nsec = newTs.tv_nsec - mOldTs.tv_nsec;
if (nsec < 0) {
--sec;
nsec += 1000000000;
@@ -81,7 +81,8 @@
}
}
mLogTs.tv_sec += sec;
- if ((mLogTs.tv_nsec += nsec) >= 1000000000) {
+ mLogTs.tv_nsec += nsec;
+ if (mLogTs.tv_nsec >= 1000000000) {
mLogTs.tv_sec++;
mLogTs.tv_nsec -= 1000000000;
}
@@ -89,7 +90,7 @@
mDump->mUnderruns = ++mUnderruns;
if (mLogTs.tv_sec >= MIN_TIME_BETWEEN_LOGS_SEC) {
mDump->mLogs = ++mLogs;
- mDump->mMostRecent = time(NULL);
+ mDump->mMostRecent = time(nullptr /* tloc */);
ALOGW("Insufficient CPU for load: expected=%.1f actual=%.1f ms; underruns=%u logs=%u",
mPeriodNs * 1e-6, cycleNs * 1e-6, mUnderruns, mLogs);
mLogTs.tv_sec = 0;
@@ -99,7 +100,7 @@
struct timespec req;
req.tv_sec = 0;
req.tv_nsec = mPeriodNs;
- rc = nanosleep(&req, NULL);
+ rc = nanosleep(&req, nullptr /* remaining */);
if (!((rc == 0) || (rc == -1 && errno == EINTR))) {
pause();
return false;
@@ -116,22 +117,23 @@
void AudioWatchdog::pause()
{
- AutoMutex _l(mMyLock);
+ const std::lock_guard _l(mLock);
mPaused = true;
}
void AudioWatchdog::resume()
{
- AutoMutex _l(mMyLock);
+ const std::lock_guard _l(mLock);
if (mPaused) {
mPaused = false;
- mMyCond.signal();
+ mCond.notify_one();
}
}
void AudioWatchdog::setDump(AudioWatchdogDump *dump)
{
- mDump = dump != NULL ? dump : &mDummyDump;
+ const std::lock_guard _l(mLock);
+ mDump = dump != nullptr ? dump : &mDummyDump;
}
} // namespace android
diff --git a/services/audioflinger/afutils/AudioWatchdog.h b/services/audioflinger/afutils/AudioWatchdog.h
index 7b69fc6..1f5dad4 100644
--- a/services/audioflinger/afutils/AudioWatchdog.h
+++ b/services/audioflinger/afutils/AudioWatchdog.h
@@ -19,9 +19,9 @@
// as soon as possible when there appears to be a CPU shortage
// (b) monitor the other threads [not yet implemented]
-#ifndef AUDIO_WATCHDOG_H
-#define AUDIO_WATCHDOG_H
+#pragma once
+#include <mutex>
#include <time.h>
#include <utils/Thread.h>
@@ -30,59 +30,54 @@
// Keeps a cache of AudioWatchdog statistics that can be logged by dumpsys.
// The usual caveats about atomicity of information apply.
struct AudioWatchdogDump {
- AudioWatchdogDump() : mUnderruns(0), mLogs(0), mMostRecent(0) { }
- /*virtual*/ ~AudioWatchdogDump() { }
- uint32_t mUnderruns; // total number of underruns
- uint32_t mLogs; // total number of log messages
- time_t mMostRecent; // time of most recent log
+ uint32_t mUnderruns = 0; // total number of underruns
+ uint32_t mLogs = 0; // total number of log messages
+ time_t mMostRecent = 0; // time of most recent log
void dump(int fd); // should only be called on a stable copy, not the original
};
class AudioWatchdog : public Thread {
public:
- explicit AudioWatchdog(unsigned periodMs = 50) : Thread(false /*canCallJava*/), mPaused(false),
- mPeriodNs(periodMs * 1000000), mMaxCycleNs(mPeriodNs * 2),
- // mOldTs
- // mLogTs initialized below
- mOldTsValid(false), mUnderruns(0), mLogs(0), mDump(&mDummyDump)
+ explicit AudioWatchdog(unsigned periodMs = 50) : Thread(false /*canCallJava*/),
+ mPeriodNs(periodMs * 1000000), mMaxCycleNs(mPeriodNs * 2)
{
-#define MIN_TIME_BETWEEN_LOGS_SEC 60
// force an immediate log on first underrun
mLogTs.tv_sec = MIN_TIME_BETWEEN_LOGS_SEC;
mLogTs.tv_nsec = 0;
}
- virtual ~AudioWatchdog() { }
// Do not call Thread::requestExitAndWait() without first calling requestExit().
// Thread::requestExitAndWait() is not virtual, and the implementation doesn't do enough.
- virtual void requestExit();
+ void requestExit() override;
// FIXME merge API and implementation with AudioTrackThread
- void pause(); // suspend thread from execution at next loop boundary
- void resume(); // allow thread to execute, if not requested to exit
+ void pause(); // suspend thread from execution at next loop boundary
+ void resume(); // allow thread to execute, if not requested to exit
// Where to store the dump, or NULL to not update
void setDump(AudioWatchdogDump* dump);
private:
- virtual bool threadLoop();
+ bool threadLoop() override;
- Mutex mMyLock; // Thread::mLock is private
- Condition mMyCond; // Thread::mThreadExitedCondition is private
- bool mPaused; // whether thread is currently paused
+ static constexpr int32_t MIN_TIME_BETWEEN_LOGS_SEC = 60;
+ const uint32_t mPeriodNs; // nominal period
+ const uint32_t mMaxCycleNs; // maximum allowed time of one cycle before declaring underrun
- uint32_t mPeriodNs; // nominal period
- uint32_t mMaxCycleNs; // maximum allowed time of one cycle before declaring underrun
- struct timespec mOldTs; // monotonic time when threadLoop last ran
- struct timespec mLogTs; // time since last log
- bool mOldTsValid; // whether mOldTs is valid
- uint32_t mUnderruns; // total number of underruns
- uint32_t mLogs; // total number of logs
- AudioWatchdogDump* mDump; // where to store the dump, always non-NULL
+ mutable std::mutex mLock; // Thread::mLock is private
+ std::condition_variable mCond; // Thread::mThreadExitedCondition is private
+ bool mPaused GUARDED_BY(mLock) = false; // whether thread is currently paused
+ bool mOldTsValid GUARDED_BY(mLock) = false; // whether mOldTs is valid
+ struct timespec mOldTs GUARDED_BY(mLock); // monotonic time when threadLoop last ran
+ struct timespec mLogTs GUARDED_BY(mLock); // time since last log (ctor init).
+ uint32_t mUnderruns GUARDED_BY(mLock) = 0; // total number of underruns
+ uint32_t mLogs GUARDED_BY(mLock) = 0; // total number of logs
+
+ // where to store the dump, always non-NULL
+ AudioWatchdogDump* mDump GUARDED_BY(mLock) = &mDummyDump;
AudioWatchdogDump mDummyDump; // default area for dump in case setDump() is not called
};
} // namespace android
-#endif // AUDIO_WATCHDOG_H
diff --git a/services/audioflinger/afutils/BufLog.cpp b/services/audioflinger/afutils/BufLog.cpp
index 5f6aca0..508022f 100644
--- a/services/audioflinger/afutils/BufLog.cpp
+++ b/services/audioflinger/afutils/BufLog.cpp
@@ -28,12 +28,14 @@
#define MIN(a, b) ((a) < (b) ? (a) : (b))
+namespace android {
+
// ------------------------------
// BufLogSingleton
// ------------------------------
pthread_once_t onceControl = PTHREAD_ONCE_INIT;
-BufLog *BufLogSingleton::mInstance = NULL;
+BufLog *BufLogSingleton::mInstance = nullptr;
void BufLogSingleton::initOnce() {
mInstance = new BufLog();
@@ -49,55 +51,39 @@
}
bool BufLogSingleton::instanceExists() {
- return mInstance != NULL;
+ return mInstance != nullptr;
}
// ------------------------------
// BufLog
// ------------------------------
-BufLog::BufLog() {
- memset(mStreams, 0, sizeof(mStreams));
-}
-
BufLog::~BufLog() {
- android::Mutex::Autolock autoLock(mLock);
-
- for (unsigned int id = 0; id < BUFLOG_MAXSTREAMS; id++) {
- BufLogStream *pBLStream = mStreams[id];
- if (pBLStream != NULL) {
- delete pBLStream ;
- mStreams[id] = NULL;
- }
- }
+ reset();
}
size_t BufLog::write(int streamid, const char *tag, int format, int channels,
int samplingRate, size_t maxBytes, const void *buf, size_t size) {
- unsigned int id = streamid % BUFLOG_MAXSTREAMS;
- android::Mutex::Autolock autoLock(mLock);
+ const unsigned int id = streamid % BUFLOG_MAXSTREAMS;
+ const std::lock_guard autoLock(mLock);
BufLogStream *pBLStream = mStreams[id];
- if (pBLStream == NULL) {
+ if (pBLStream == nullptr) {
pBLStream = mStreams[id] = new BufLogStream(id, tag, format, channels,
samplingRate, maxBytes);
- ALOG_ASSERT(pBLStream != NULL, "BufLogStream Failed to be created");
}
return pBLStream->write(buf, size);
}
void BufLog::reset() {
- android::Mutex::Autolock autoLock(mLock);
- ALOGV("Resetting all BufLogs");
+ const std::lock_guard autoLock(mLock);
int count = 0;
-
- for (unsigned int id = 0; id < BUFLOG_MAXSTREAMS; id++) {
- BufLogStream *pBLStream = mStreams[id];
- if (pBLStream != NULL) {
+ for (auto &pBLStream : mStreams) {
+ if (pBLStream != nullptr) {
delete pBLStream;
- mStreams[id] = NULL;
+ pBLStream = nullptr;
count++;
}
}
@@ -115,9 +101,7 @@
unsigned int samplingRate,
size_t maxBytes = 0) : mId(id), mFormat(format), mChannels(channels),
mSamplingRate(samplingRate), mMaxBytes(maxBytes) {
- mByteCount = 0;
- mPaused = false;
- if (tag != NULL) {
+ if (tag != nullptr) {
(void)audio_utils_strlcpy(mTag, tag);
} else {
mTag[0] = 0;
@@ -129,7 +113,7 @@
//timestamp
char timeStr[16]; //size 16: format %Y%m%d%H%M%S 14 chars + string null terminator
struct timeval tv;
- gettimeofday(&tv, NULL);
+ gettimeofday(&tv, nullptr);
struct tm tm;
localtime_r(&tv.tv_sec, &tm);
strftime(timeStr, sizeof(timeStr), "%Y%m%d%H%M%S", &tm);
@@ -139,7 +123,7 @@
ALOGV("data output: %s", logPath);
mFile = fopen(logPath, "wb");
- if (mFile != NULL) {
+ if (mFile != nullptr) {
ALOGV("Success creating file at: %p", mFile);
} else {
ALOGE("Error: could not create file BufLogStream %s", strerror(errno));
@@ -148,24 +132,24 @@
void BufLogStream::closeStream_l() {
ALOGV("Closing BufLogStream id:%d tag:%s", mId, mTag);
- if (mFile != NULL) {
+ if (mFile != nullptr) {
fclose(mFile);
- mFile = NULL;
+ mFile = nullptr;
}
}
BufLogStream::~BufLogStream() {
ALOGV("Destroying BufLogStream id:%d tag:%s", mId, mTag);
- android::Mutex::Autolock autoLock(mLock);
+ const std::lock_guard autoLock(mLock);
closeStream_l();
}
size_t BufLogStream::write(const void *buf, size_t size) {
size_t bytes = 0;
- if (!mPaused && mFile != NULL) {
- if (size > 0 && buf != NULL) {
- android::Mutex::Autolock autoLock(mLock);
+ if (!mPaused && mFile != nullptr) {
+ if (size > 0 && buf != nullptr) {
+ const std::lock_guard autoLock(mLock);
if (mMaxBytes > 0) {
size = MIN(size, mMaxBytes - mByteCount);
}
@@ -185,12 +169,14 @@
}
bool BufLogStream::setPause(bool pause) {
- bool old = mPaused;
+ const bool old = mPaused;
mPaused = pause;
return old;
}
void BufLogStream::finalize() {
- android::Mutex::Autolock autoLock(mLock);
+ const std::lock_guard autoLock(mLock);
closeStream_l();
}
+
+} // namespace android
diff --git a/services/audioflinger/afutils/BufLog.h b/services/audioflinger/afutils/BufLog.h
index 1b402f4..a58d073 100644
--- a/services/audioflinger/afutils/BufLog.h
+++ b/services/audioflinger/afutils/BufLog.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_AUDIO_BUFLOG_H
-#define ANDROID_AUDIO_BUFLOG_H
+#pragma once
/*
* BUFLOG creates up to BUFLOG_MAXSTREAMS simultaneous streams [0:15] of audio buffer data
@@ -99,17 +98,18 @@
BufLogSingleton::instance()->reset(); } } while (0)
#endif
-
+#include <mutex>
#include <stdint.h>
#include <stdio.h>
#include <sys/types.h>
-#include <utils/Mutex.h>
//BufLog configuration
#define BUFLOGSTREAM_MAX_TAGSIZE 32
#define BUFLOG_BASE_PATH "/data/misc/audioserver"
#define BUFLOG_MAX_PATH_SIZE 300
+namespace android {
+
class BufLogStream {
public:
BufLogStream(unsigned int id,
@@ -135,26 +135,24 @@
void finalize();
private:
- bool mPaused;
const unsigned int mId;
- char mTag[BUFLOGSTREAM_MAX_TAGSIZE + 1];
const unsigned int mFormat;
const unsigned int mChannels;
const unsigned int mSamplingRate;
const size_t mMaxBytes;
- size_t mByteCount;
- FILE *mFile;
- mutable android::Mutex mLock;
+ char mTag[BUFLOGSTREAM_MAX_TAGSIZE + 1]; // const, set in ctor.
+
+ mutable std::mutex mLock;
+ bool mPaused = false;
+ size_t mByteCount = 0;
+ FILE *mFile; // set in ctor
void closeStream_l();
};
-
class BufLog {
public:
- BufLog();
~BufLog();
- BufLog(BufLog const&) {};
// streamid: int [0:BUFLOG_MAXSTREAMS-1] buffer id.
// If a buffer doesn't exist, it is created the first time is referenced
@@ -181,9 +179,9 @@
void reset();
protected:
- static const unsigned int BUFLOG_MAXSTREAMS = 16;
- BufLogStream *mStreams[BUFLOG_MAXSTREAMS];
- mutable android::Mutex mLock;
+ static constexpr size_t BUFLOG_MAXSTREAMS = 16;
+ mutable std::mutex mLock;
+ BufLogStream *mStreams[BUFLOG_MAXSTREAMS]{};
};
class BufLogSingleton {
@@ -196,4 +194,4 @@
static BufLog *mInstance;
};
-#endif //ANDROID_AUDIO_BUFLOG_H
+} // namespace android
diff --git a/services/audioflinger/afutils/NBAIO_Tee.cpp b/services/audioflinger/afutils/NBAIO_Tee.cpp
index 53083d5..49057ce 100644
--- a/services/audioflinger/afutils/NBAIO_Tee.cpp
+++ b/services/audioflinger/afutils/NBAIO_Tee.cpp
@@ -91,8 +91,8 @@
/** returns filename of created audio file, else empty string on failure. */
std::string create(
- std::function<ssize_t /* frames_read */
- (void * /* buffer */, size_t /* size_in_frames */)> reader,
+ const std::function<ssize_t /* frames_read */
+ (void * /* buffer */, size_t /* size_in_frames */)>& reader,
uint32_t sampleRate,
uint32_t channelCount,
audio_format_t format,
@@ -109,8 +109,8 @@
/** creates an audio file from a reader functor passed in. */
status_t createInternal(
- std::function<ssize_t /* frames_read */
- (void * /* buffer */, size_t /* size_in_frames */)> reader,
+ const std::function<ssize_t /* frames_read */
+ (void * /* buffer */, size_t /* size_in_frames */)>& reader,
uint32_t sampleRate,
uint32_t channelCount,
audio_format_t format,
@@ -123,7 +123,7 @@
std::string generateFilename(const std::string &suffix) const {
char fileTime[sizeof("YYYYmmdd_HHMMSS_\0")];
struct timeval tv;
- gettimeofday(&tv, NULL);
+ gettimeofday(&tv, nullptr /* struct timezone */);
struct tm tm;
localtime_r(&tv.tv_sec, &tm);
LOG_ALWAYS_FATAL_IF(strftime(fileTime, sizeof(fileTime), "%Y%m%d_%H%M%S_", &tm) == 0,
@@ -159,30 +159,29 @@
// yet another ThreadPool implementation.
class ThreadPool {
public:
- ThreadPool(size_t size)
+ explicit ThreadPool(size_t size)
: mThreadPoolSize(size)
{ }
/** launches task "name" with associated function "func".
if the threadpool is exhausted, it will launch on calling function */
- status_t launch(const std::string &name, std::function<status_t()> func);
+ status_t launch(const std::string &name, const std::function<status_t()>& func);
private:
+ const size_t mThreadPoolSize;
std::mutex mLock;
std::list<std::pair<
- std::string, std::future<status_t>>> mFutures; // GUARDED_BY(mLock)
-
- const size_t mThreadPoolSize;
+ std::string, std::future<status_t>>> mFutures; // GUARDED_BY(mLock);
} mThreadPool;
- const std::string mPrefix;
- std::mutex mLock;
- std::string mDirectory; // GUARDED_BY(mLock)
- std::deque<std::string> mFiles; // GUARDED_BY(mLock) sorted list of files by creation time
-
static constexpr size_t FRAMES_PER_READ = 1024;
static constexpr size_t MAX_FILES_READ = 1024;
static constexpr size_t MAX_FILES_KEEP = 32;
+
+ const std::string mPrefix;
+ std::mutex mLock;
+ std::string mDirectory; // GUARDED_BY(mLock);
+ std::deque<std::string> mFiles; // GUARDED_BY(mLock); // sorted list of files by creation time
};
/* static */
@@ -200,7 +199,7 @@
const NBAIO_Format format = source->format();
bool firstRead = true;
- std::string filename = audioFileHandler.create(
+ const std::string filename = audioFileHandler.create(
// this functor must not hold references to stack
[firstRead, sinkSource] (void *buffer, size_t frames) mutable {
auto &source = sinkSource.second;
@@ -230,14 +229,16 @@
Pipe *pipe = new Pipe(frames, format);
size_t numCounterOffers = 0;
const NBAIO_Format offers[1] = {format};
- ssize_t index = pipe->negotiate(offers, 1, NULL, numCounterOffers);
+ ssize_t index = pipe->negotiate(
+ offers, 1 /* numOffers */, nullptr /* counterOffers */, numCounterOffers);
if (index != 0) {
ALOGW("pipe failure to negotiate: %zd", index);
goto exit;
}
PipeReader *pipeReader = new PipeReader(*pipe);
numCounterOffers = 0;
- index = pipeReader->negotiate(offers, 1, NULL, numCounterOffers);
+ index = pipeReader->negotiate(
+ offers, 1 /* numOffers */, nullptr /* counterOffers */, numCounterOffers);
if (index != 0) {
ALOGW("pipeReader failure to negotiate: %zd", index);
goto exit;
@@ -251,14 +252,14 @@
}
std::string AudioFileHandler::create(
- std::function<ssize_t /* frames_read */
- (void * /* buffer */, size_t /* size_in_frames */)> reader,
+ const std::function<ssize_t /* frames_read */
+ (void * /* buffer */, size_t /* size_in_frames */)>& reader,
uint32_t sampleRate,
uint32_t channelCount,
audio_format_t format,
const std::string &suffix)
{
- const std::string filename = generateFilename(suffix);
+ std::string filename = generateFilename(suffix);
if (mThreadPool.launch(std::string("create ") + filename,
[=]() { return createInternal(reader, sampleRate, channelCount, format, filename); })
@@ -312,7 +313,7 @@
std::sort(files.begin() + toRemove, files.end());
{
- std::lock_guard<std::mutex> _l(mLock);
+ const std::lock_guard<std::mutex> _l(mLock);
mDirectory = directory;
mFiles = std::move(files);
@@ -330,13 +331,13 @@
std::vector<std::string> filesToRemove;
std::string dir;
{
- std::lock_guard<std::mutex> _l(mLock);
+ const std::lock_guard<std::mutex> _l(mLock);
if (!isDirectoryValid(mDirectory)) return NO_INIT;
dir = mDirectory;
if (mFiles.size() > MAX_FILES_KEEP) {
- size_t toRemove = mFiles.size() - MAX_FILES_KEEP;
+ const size_t toRemove = mFiles.size() - MAX_FILES_KEEP;
// use move and erase to efficiently transfer std::string
std::move(mFiles.begin(),
@@ -346,7 +347,7 @@
}
}
- std::string dirp = dir + "/";
+ const std::string dirp = dir + "/";
// remove files outside of lock for better concurrency.
for (const auto &file : filesToRemove) {
(void)unlink((dirp + file).c_str());
@@ -360,14 +361,14 @@
}
status_t AudioFileHandler::ThreadPool::launch(
- const std::string &name, std::function<status_t()> func)
+ const std::string &name, const std::function<status_t()>& func)
{
if (mThreadPoolSize > 1) {
- std::lock_guard<std::mutex> _l(mLock);
+ const std::lock_guard<std::mutex> _l(mLock);
if (mFutures.size() >= mThreadPoolSize) {
for (auto it = mFutures.begin(); it != mFutures.end();) {
const std::string &filename = it->first;
- std::future<status_t> &future = it->second;
+ const std::future<status_t> &future = it->second;
if (!future.valid() ||
future.wait_for(std::chrono::seconds(0)) == std::future_status::ready) {
ALOGV("%s: future %s ready", __func__, filename.c_str());
@@ -389,8 +390,8 @@
}
status_t AudioFileHandler::createInternal(
- std::function<ssize_t /* frames_read */
- (void * /* buffer */, size_t /* size_in_frames */)> reader,
+ const std::function<ssize_t /* frames_read */
+ (void * /* buffer */, size_t /* size_in_frames */)>& reader,
uint32_t sampleRate,
uint32_t channelCount,
audio_format_t format,
@@ -429,9 +430,9 @@
}
std::string directory;
- status_t status = clean(&directory);
+ const status_t status = clean(&directory);
if (status != NO_ERROR) return status;
- std::string dirPrefix = directory + "/";
+ const std::string dirPrefix = directory + "/";
const std::string path = dirPrefix + filename;
@@ -503,7 +504,7 @@
// Success: add our name to managed files.
{
- std::lock_guard<std::mutex> _l(mLock);
+ const std::lock_guard<std::mutex> _l(mLock);
// weak synchronization - only update mFiles if the directory hasn't changed.
if (mDirectory == directory) {
mFiles.emplace_back(filename); // add to the end to preserve sort.
diff --git a/services/audioflinger/afutils/NBAIO_Tee.h b/services/audioflinger/afutils/NBAIO_Tee.h
index fed8cc8..17b6175 100644
--- a/services/audioflinger/afutils/NBAIO_Tee.h
+++ b/services/audioflinger/afutils/NBAIO_Tee.h
@@ -15,8 +15,8 @@
*/
// Enabled with TEE_SINK in Configuration.h
-#ifndef ANDROID_NBAIO_TEE_H
-#define ANDROID_NBAIO_TEE_H
+
+#pragma once
#ifdef TEE_SINK
@@ -216,7 +216,7 @@
// Note: as mentioned in NBAIO_Tee::set(), don't call set() while write() is
// ongoing.
if (enabled) {
- std::lock_guard<std::mutex> _l(mLock);
+ const std::lock_guard<std::mutex> _l(mLock);
mFlags = flags;
mFormat = format; // could get this from the Sink.
mFrames = frames;
@@ -228,7 +228,7 @@
}
void setId(const std::string &id) {
- std::lock_guard<std::mutex> _l(mLock);
+ const std::lock_guard<std::mutex> _l(mLock);
mId = id;
}
@@ -237,7 +237,7 @@
std::string suffix;
NBAIO_SinkSource sinkSource;
{
- std::lock_guard<std::mutex> _l(mLock);
+ const std::lock_guard<std::mutex> _l(mLock);
suffix = mId + reason;
sinkSource = mSinkSource;
}
@@ -281,13 +281,13 @@
class RunningTees {
public:
void add(const std::shared_ptr<NBAIO_TeeImpl> &tee) {
- std::lock_guard<std::mutex> _l(mLock);
+ const std::lock_guard<std::mutex> _l(mLock);
ALOGW_IF(!mTees.emplace(tee).second,
"%s: %p already exists in mTees", __func__, tee.get());
}
void remove(const std::shared_ptr<NBAIO_TeeImpl> &tee) {
- std::lock_guard<std::mutex> _l(mLock);
+ const std::lock_guard<std::mutex> _l(mLock);
ALOGW_IF(mTees.erase(tee) != 1,
"%s: %p doesn't exist in mTees", __func__, tee.get());
}
@@ -295,7 +295,7 @@
void dump(int fd, const std::string &reason) {
std::vector<std::shared_ptr<NBAIO_TeeImpl>> tees; // safe snapshot of tees
{
- std::lock_guard<std::mutex> _l(mLock);
+ const std::lock_guard<std::mutex> _l(mLock);
tees.insert(tees.end(), mTees.begin(), mTees.end());
}
for (const auto &tee : tees) {
@@ -323,4 +323,3 @@
} // namespace android
#endif // TEE_SINK
-#endif // !ANDROID_NBAIO_TEE_H
diff --git a/services/audioflinger/afutils/TypedLogger.cpp b/services/audioflinger/afutils/TypedLogger.cpp
index 57c206b..7c546a5 100644
--- a/services/audioflinger/afutils/TypedLogger.cpp
+++ b/services/audioflinger/afutils/TypedLogger.cpp
@@ -22,6 +22,25 @@
#include <pthread.h>
#include "TypedLogger.h"
-namespace android {
+namespace android::aflog {
+
+// External linkage access of thread local storage outside of this shared library
+// causes orphaned memory allocations. This occurs in the implementation of
+// __emutls_get_address(), see b/284657986.
+//
+// We only expose a thread local storage getter and setter here, not the
+// actual thread local variable.
+
+namespace {
thread_local NBLog::Writer *tlNBLogWriter;
+} // namespace
+
+NBLog::Writer *getThreadWriter() {
+ return tlNBLogWriter;
}
+
+void setThreadWriter(NBLog::Writer *writer) {
+ tlNBLogWriter = writer;
+}
+
+} // namespace android::aflog
diff --git a/services/audioflinger/afutils/TypedLogger.h b/services/audioflinger/afutils/TypedLogger.h
index feb71e3..8c2d239 100644
--- a/services/audioflinger/afutils/TypedLogger.h
+++ b/services/audioflinger/afutils/TypedLogger.h
@@ -15,8 +15,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_TYPED_LOGGER_H
-#define ANDROID_TYPED_LOGGER_H
+#pragma once
// This is the client API for the typed logger.
@@ -85,56 +84,56 @@
// slower than nullptr check when logging is enabled at compile-time and disabled at runtime.
// Write formatted entry to log
-#define LOGT(fmt, ...) do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
+#define LOGT(fmt, ...) do { NBLog::Writer *x = aflog::getThreadWriter(); if (x != nullptr) \
x->logFormat((fmt), hash(__FILE__, __LINE__), ##__VA_ARGS__); } \
while (0)
// Write histogram timestamp entry
-#define LOG_HIST_TS() do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
+#define LOG_HIST_TS() do { NBLog::Writer *x = aflog::getThreadWriter(); if (x != nullptr) \
x->logEventHistTs(NBLog::EVENT_HISTOGRAM_ENTRY_TS, hash(__FILE__, __LINE__)); } while(0)
// Record that audio was turned on/off
-#define LOG_AUDIO_STATE() do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
+#define LOG_AUDIO_STATE() do { NBLog::Writer *x = aflog::getThreadWriter(); if (x != nullptr) \
x->logEventHistTs(NBLog::EVENT_AUDIO_STATE, hash(__FILE__, __LINE__)); } while(0)
// Log the difference bewteen frames presented by HAL and frames written to HAL output sink,
// divided by the sample rate. Parameter ms is of type double.
-#define LOG_LATENCY(ms) do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
+#define LOG_LATENCY(ms) do { NBLog::Writer *x = aflog::getThreadWriter(); if (x != nullptr) \
x->log<NBLog::EVENT_LATENCY>(ms); } while (0)
// Record thread overrun event nanosecond timestamp. Parameter ns is an int64_t.
-#define LOG_OVERRUN(ns) do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
+#define LOG_OVERRUN(ns) do { NBLog::Writer *x = aflog::getThreadWriter(); if (x != nullptr) \
x->log<NBLog::EVENT_OVERRUN>(ns); } while (0)
// Record thread info. This currently includes type, frameCount, and sampleRate.
// Parameter type is thread_info_t as defined in NBLog.h.
-#define LOG_THREAD_INFO(info) do { NBLog::Writer *x = tlNBLogWriter; \
+#define LOG_THREAD_INFO(info) do { NBLog::Writer *x = aflog::getThreadWriter(); \
if (x != nullptr) x->log<NBLog::EVENT_THREAD_INFO>(info); } while (0)
-#define LOG_THREAD_PARAMS(params) do {NBLog::Writer *x = tlNBLogWriter; \
+#define LOG_THREAD_PARAMS(params) do {NBLog::Writer *x = aflog::getThreadWriter(); \
if (x != nullptr) x->log<NBLog::EVENT_THREAD_PARAMS>(params); } while (0)
// Record thread underrun event nanosecond timestamp. Parameter ns is an int64_t.
-#define LOG_UNDERRUN(ns) do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
+#define LOG_UNDERRUN(ns) do { NBLog::Writer *x = aflog::getThreadWriter(); if (x != nullptr) \
x->log<NBLog::EVENT_UNDERRUN>(ns); } while (0)
// Record thread warmup time in milliseconds. Parameter ms is of type double.
-#define LOG_WARMUP_TIME(ms) do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
+#define LOG_WARMUP_TIME(ms) do { \
+ NBLog::Writer *x = aflog::getThreadWriter(); if (x != nullptr) \
x->log<NBLog::EVENT_WARMUP_TIME>(ms); } while (0)
// Record a typed entry that represents a thread's work time in nanoseconds.
// Parameter ns should be of type uint32_t.
-#define LOG_WORK_TIME(ns) do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
+#define LOG_WORK_TIME(ns) do { NBLog::Writer *x = aflog::getThreadWriter(); if (x != nullptr) \
x->log<NBLog::EVENT_WORK_TIME>(ns); } while (0)
-namespace android {
-extern "C" {
+namespace android::aflog {
// TODO consider adding a thread_local NBLog::Writer tlStubNBLogWriter and then
-// initialize below tlNBLogWriter to &tlStubNBLogWriter to remove the need to
+// initialize setThreadWriter() to &tlStubNBLogWriter to remove the need to
// check for nullptr every time. Also reduces the need to add a new logging macro above
// each time we want to log a new type.
-extern thread_local NBLog::Writer *tlNBLogWriter;
-}
-} // namespace android
-#endif // ANDROID_TYPED_LOGGER_H
+NBLog::Writer *getThreadWriter();
+void setThreadWriter(NBLog::Writer *writer);
+
+} // namespace android::aflog
diff --git a/services/audioflinger/fastpath/Android.bp b/services/audioflinger/fastpath/Android.bp
index fb49430..6c024e7 100644
--- a/services/audioflinger/fastpath/Android.bp
+++ b/services/audioflinger/fastpath/Android.bp
@@ -1,3 +1,11 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_services_audioflinger_license"],
+}
fastpath_tidy_errors = [
// https://clang.llvm.org/extra/clang-tidy/checks/list.html
@@ -53,24 +61,7 @@
"-bugprone-narrowing-conversions", // b/182410845
// TODO(b/275642749) Reenable these warnings
- "-bugprone-assignment-in-if-condition",
- "-bugprone-forward-declaration-namespace",
- "-bugprone-parent-virtual-call",
- "-cert-dcl59-cpp",
- "-cert-err34-c",
- "-google-build-namespaces",
- "-google-build-using-namespace",
- "-google-default-arguments",
- "-google-runtime-int",
- "-misc-const-correctness",
"-misc-non-private-member-variables-in-classes",
- "-modernize-concat-nested-namespaces",
- "-modernize-loop-convert",
- "-modernize-use-default-member-init",
- "-modernize-use-equals-default",
- "-modernize-use-nullptr",
- "-modernize-use-override",
- "-modernize-use-using",
"-performance-no-int-to-ptr",
]
@@ -154,9 +145,6 @@
"libmedia_headers",
],
- cflags: [
- "-DSTATE_QUEUE_INSTANTIATIONS=\"StateQueueInstantiations.cpp\"",
- ],
sanitize: {
integer_overflow: true,
},
diff --git a/services/audioflinger/fastpath/AutoPark.h b/services/audioflinger/fastpath/AutoPark.h
index 83f6b7d..6e68327 100644
--- a/services/audioflinger/fastpath/AutoPark.h
+++ b/services/audioflinger/fastpath/AutoPark.h
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#pragma once
+
namespace android {
// T is FastMixer or FastCapture
diff --git a/services/audioflinger/fastpath/FastCapture.cpp b/services/audioflinger/fastpath/FastCapture.cpp
index 2963202..288036d 100644
--- a/services/audioflinger/fastpath/FastCapture.cpp
+++ b/services/audioflinger/fastpath/FastCapture.cpp
@@ -30,24 +30,16 @@
namespace android {
-/*static*/ const FastCaptureState FastCapture::sInitial;
+/*static*/ const FastCaptureState FastCapture::sInitial{};
-FastCapture::FastCapture() : FastThread("cycleC_ms", "loadC_us"),
- mInputSource(NULL), mInputSourceGen(0), mPipeSink(NULL), mPipeSinkGen(0),
- mReadBuffer(NULL), mReadBufferState(-1), mFormat(Format_Invalid), mSampleRate(0),
- // mDummyDumpState
- mTotalNativeFramesRead(0)
+FastCapture::FastCapture() : FastThread("cycleC_ms", "loadC_us")
{
+ // base class initialization
mPrevious = &sInitial;
mCurrent = &sInitial;
-
mDummyDumpState = &mDummyFastCaptureDumpState;
}
-FastCapture::~FastCapture()
-{
-}
-
FastCaptureStateQueue* FastCapture::sq()
{
return &mSQ;
@@ -95,11 +87,11 @@
bool eitherChanged = false;
// check for change in input HAL configuration
- NBAIO_Format previousFormat = mFormat;
+ const NBAIO_Format previousFormat = mFormat;
if (current->mInputSourceGen != mInputSourceGen) {
mInputSource = current->mInputSource;
mInputSourceGen = current->mInputSourceGen;
- if (mInputSource == NULL) {
+ if (mInputSource == nullptr) {
mFormat = Format_Invalid;
mSampleRate = 0;
} else {
@@ -122,19 +114,19 @@
}
// input source and pipe sink must be compatible
- if (eitherChanged && mInputSource != NULL && mPipeSink != NULL) {
+ if (eitherChanged && mInputSource != nullptr && mPipeSink != nullptr) {
ALOG_ASSERT(Format_isEqual(mFormat, mPipeSink->format()));
}
if ((!Format_isEqual(mFormat, previousFormat)) || (frameCount != previous->mFrameCount)) {
// FIXME to avoid priority inversion, don't free here
free(mReadBuffer);
- mReadBuffer = NULL;
+ mReadBuffer = nullptr;
if (frameCount > 0 && mSampleRate > 0) {
// FIXME new may block for unbounded time at internal mutex of the heap
// implementation; it would be better to have normal capture thread allocate for
// us to avoid blocking here and to prevent possible priority inversion
- size_t bufferSize = frameCount * Format_frameSize(mFormat);
+ const size_t bufferSize = frameCount * Format_frameSize(mFormat);
(void)posix_memalign(&mReadBuffer, 32, bufferSize);
memset(mReadBuffer, 0, bufferSize); // if posix_memalign fails, will segv here.
mPeriodNs = (frameCount * 1000000000LL) / mSampleRate; // 1.00
@@ -166,9 +158,9 @@
AudioBufferProvider* fastPatchRecordBufferProvider = current->mFastPatchRecordBufferProvider;
AudioBufferProvider::Buffer patchBuffer;
- if (fastPatchRecordBufferProvider != 0) {
+ if (fastPatchRecordBufferProvider != nullptr) {
patchBuffer.frameCount = ~0;
- status_t status = fastPatchRecordBufferProvider->getNextBuffer(&patchBuffer);
+ const status_t status = fastPatchRecordBufferProvider->getNextBuffer(&patchBuffer);
if (status != NO_ERROR) {
frameCount = 0;
} else if (patchBuffer.frameCount < frameCount) {
@@ -179,11 +171,11 @@
}
if ((command & FastCaptureState::READ) /*&& isWarm*/) {
- ALOG_ASSERT(mInputSource != NULL);
- ALOG_ASSERT(mReadBuffer != NULL);
+ ALOG_ASSERT(mInputSource != nullptr);
+ ALOG_ASSERT(mReadBuffer != nullptr);
dumpState->mReadSequence++;
ATRACE_BEGIN("read");
- ssize_t framesRead = mInputSource->read(mReadBuffer, frameCount);
+ const ssize_t framesRead = mInputSource->read(mReadBuffer, frameCount);
ATRACE_END();
dumpState->mReadSequence++;
if (framesRead >= 0) {
@@ -201,8 +193,8 @@
}
if (command & FastCaptureState::WRITE) {
- ALOG_ASSERT(mPipeSink != NULL);
- ALOG_ASSERT(mReadBuffer != NULL);
+ ALOG_ASSERT(mPipeSink != nullptr);
+ ALOG_ASSERT(mReadBuffer != nullptr);
if (mReadBufferState < 0) {
memset(mReadBuffer, 0, frameCount * Format_frameSize(mFormat));
mReadBufferState = frameCount;
@@ -211,23 +203,23 @@
if (current->mSilenceCapture) {
memset(mReadBuffer, 0, mReadBufferState * Format_frameSize(mFormat));
}
- ssize_t framesWritten = mPipeSink->write(mReadBuffer, mReadBufferState);
+ const ssize_t framesWritten = mPipeSink->write(mReadBuffer, mReadBufferState);
audio_track_cblk_t* cblk = current->mCblk;
- if (fastPatchRecordBufferProvider != 0) {
+ if (fastPatchRecordBufferProvider != nullptr) {
// This indicates the fast track is a patch record, update the cblk by
// calling releaseBuffer().
memcpy_by_audio_format(patchBuffer.raw, current->mFastPatchRecordFormat,
mReadBuffer, mFormat.mFormat, framesWritten * mFormat.mChannelCount);
patchBuffer.frameCount = framesWritten;
fastPatchRecordBufferProvider->releaseBuffer(&patchBuffer);
- } else if (cblk != NULL && framesWritten > 0) {
+ } else if (cblk != nullptr && framesWritten > 0) {
// FIXME This supports at most one fast capture client.
// To handle multiple clients this could be converted to an array,
// or with a lot more work the control block could be shared by all clients.
- int32_t rear = cblk->u.mStreaming.mRear;
+ const int32_t rear = cblk->u.mStreaming.mRear;
android_atomic_release_store(framesWritten + rear, &cblk->u.mStreaming.mRear);
cblk->mServer += framesWritten;
- int32_t old = android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex);
+ const int32_t old = android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex);
if (!(old & CBLK_FUTEX_WAKE)) {
// client is never in server process, so don't use FUTEX_WAKE_PRIVATE
(void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, 1);
diff --git a/services/audioflinger/fastpath/FastCapture.h b/services/audioflinger/fastpath/FastCapture.h
index c3817c0..b565216 100644
--- a/services/audioflinger/fastpath/FastCapture.h
+++ b/services/audioflinger/fastpath/FastCapture.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_AUDIO_FAST_CAPTURE_H
-#define ANDROID_AUDIO_FAST_CAPTURE_H
+#pragma once
#include "FastThread.h"
#include "StateQueue.h"
@@ -24,13 +23,12 @@
namespace android {
-typedef StateQueue<FastCaptureState> FastCaptureStateQueue;
+using FastCaptureStateQueue = StateQueue<FastCaptureState>;
class FastCapture : public FastThread {
public:
FastCapture();
- virtual ~FastCapture();
FastCaptureStateQueue* sq();
@@ -38,32 +36,30 @@
FastCaptureStateQueue mSQ;
// callouts
- virtual const FastThreadState *poll();
- virtual void setNBLogWriter(NBLog::Writer *logWriter);
- virtual void onIdle();
- virtual void onExit();
- virtual bool isSubClassCommand(FastThreadState::Command command);
- virtual void onStateChange();
- virtual void onWork();
+ const FastThreadState *poll() override;
+ void setNBLogWriter(NBLog::Writer *logWriter) override;
+ void onIdle() override;
+ void onExit() override;
+ bool isSubClassCommand(FastThreadState::Command command) override;
+ void onStateChange() override;
+ void onWork() override;
static const FastCaptureState sInitial;
FastCaptureState mPreIdle; // copy of state before we went into idle
// FIXME by renaming, could pull up many of these to FastThread
- NBAIO_Source* mInputSource;
- int mInputSourceGen;
- NBAIO_Sink* mPipeSink;
- int mPipeSinkGen;
- void* mReadBuffer;
- ssize_t mReadBufferState; // number of initialized frames in readBuffer,
- // or -1 to clear
- NBAIO_Format mFormat;
- unsigned mSampleRate;
+ NBAIO_Source* mInputSource = nullptr;
+ int mInputSourceGen = 0;
+ NBAIO_Sink* mPipeSink = nullptr;
+ int mPipeSinkGen = 0;
+ void* mReadBuffer = nullptr;
+ ssize_t mReadBufferState = -1; // number of initialized frames in readBuffer,
+ // or -1 to clear
+ NBAIO_Format mFormat = Format_Invalid;
+ unsigned mSampleRate = 0;
FastCaptureDumpState mDummyFastCaptureDumpState;
- uint32_t mTotalNativeFramesRead; // copied to dumpState->mFramesRead
+ uint32_t mTotalNativeFramesRead = 0; // copied to dumpState->mFramesRead
}; // class FastCapture
} // namespace android
-
-#endif // ANDROID_AUDIO_FAST_CAPTURE_H
diff --git a/services/audioflinger/fastpath/FastCaptureDumpState.cpp b/services/audioflinger/fastpath/FastCaptureDumpState.cpp
index 243dfa5..fe7ea16 100644
--- a/services/audioflinger/fastpath/FastCaptureDumpState.cpp
+++ b/services/audioflinger/fastpath/FastCaptureDumpState.cpp
@@ -24,24 +24,15 @@
namespace android {
-FastCaptureDumpState::FastCaptureDumpState() : FastThreadDumpState(),
- mReadSequence(0), mFramesRead(0), mReadErrors(0), mSampleRate(0), mFrameCount(0)
-{
-}
-
-FastCaptureDumpState::~FastCaptureDumpState()
-{
-}
-
void FastCaptureDumpState::dump(int fd) const
{
if (mCommand == FastCaptureState::INITIAL) {
dprintf(fd, " FastCapture not initialized\n");
return;
}
- double measuredWarmupMs = (mMeasuredWarmupTs.tv_sec * 1000.0) +
+ const double measuredWarmupMs = (mMeasuredWarmupTs.tv_sec * 1000.0) +
(mMeasuredWarmupTs.tv_nsec / 1000000.0);
- double periodSec = (double) mFrameCount / mSampleRate;
+ const double periodSec = (double) mFrameCount / mSampleRate;
dprintf(fd, " FastCapture command=%s readSequence=%u framesRead=%u\n"
" readErrors=%u sampleRate=%u frameCount=%zu\n"
" measuredWarmup=%.3g ms, warmupCycles=%u period=%.2f ms\n"
diff --git a/services/audioflinger/fastpath/FastCaptureDumpState.h b/services/audioflinger/fastpath/FastCaptureDumpState.h
index 34ce456..3dc8a9b 100644
--- a/services/audioflinger/fastpath/FastCaptureDumpState.h
+++ b/services/audioflinger/fastpath/FastCaptureDumpState.h
@@ -14,30 +14,28 @@
* limitations under the License.
*/
-#ifndef ANDROID_AUDIO_FAST_CAPTURE_DUMP_STATE_H
-#define ANDROID_AUDIO_FAST_CAPTURE_DUMP_STATE_H
+#pragma once
#include <stdint.h>
+#include <type_traits>
#include "Configuration.h"
#include "FastThreadDumpState.h"
namespace android {
struct FastCaptureDumpState : FastThreadDumpState {
- FastCaptureDumpState();
- /*virtual*/ ~FastCaptureDumpState();
-
void dump(int fd) const; // should only be called on a stable copy, not the original
// FIXME by renaming, could pull up many of these to FastThreadDumpState
- uint32_t mReadSequence; // incremented before and after each read()
- uint32_t mFramesRead; // total number of frames read successfully
- uint32_t mReadErrors; // total number of read() errors
- uint32_t mSampleRate;
- size_t mFrameCount;
+ uint32_t mReadSequence = 0; // incremented before and after each read()
+ uint32_t mFramesRead = 0; // total number of frames read successfully
+ uint32_t mReadErrors = 0; // total number of read() errors
+ uint32_t mSampleRate = 0;
+ size_t mFrameCount = 0;
bool mSilenced = false; // capture is silenced
};
-} // namespace android
+// No virtuals
+static_assert(!std::is_polymorphic_v<FastCaptureDumpState>);
-#endif // ANDROID_AUDIO_FAST_CAPTURE_DUMP_STATE_H
+} // namespace android
diff --git a/services/audioflinger/fastpath/FastCaptureState.cpp b/services/audioflinger/fastpath/FastCaptureState.cpp
index 918ba9c..77c0c4c 100644
--- a/services/audioflinger/fastpath/FastCaptureState.cpp
+++ b/services/audioflinger/fastpath/FastCaptureState.cpp
@@ -18,20 +18,11 @@
namespace android {
-FastCaptureState::FastCaptureState() : FastThreadState(),
- mInputSource(NULL), mInputSourceGen(0), mPipeSink(NULL), mPipeSinkGen(0), mFrameCount(0)
-{
-}
-
-FastCaptureState::~FastCaptureState()
-{
-}
-
// static
const char *FastCaptureState::commandToString(Command command)
{
const char *str = FastThreadState::commandToString(command);
- if (str != NULL) {
+ if (str != nullptr) {
return str;
}
switch (command) {
@@ -39,7 +30,7 @@
case FastCaptureState::WRITE: return "WRITE";
case FastCaptureState::READ_WRITE: return "READ_WRITE";
}
- LOG_ALWAYS_FATAL("%s", __func__);
+ LOG_ALWAYS_FATAL("%s: command %d invalid", __func__, (int) command);
}
} // namespace android
diff --git a/services/audioflinger/fastpath/FastCaptureState.h b/services/audioflinger/fastpath/FastCaptureState.h
index f949275..0f4126e 100644
--- a/services/audioflinger/fastpath/FastCaptureState.h
+++ b/services/audioflinger/fastpath/FastCaptureState.h
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-#ifndef ANDROID_AUDIO_FAST_CAPTURE_STATE_H
-#define ANDROID_AUDIO_FAST_CAPTURE_STATE_H
+#pragma once
+#include <type_traits>
#include <media/nbaio/NBAIO.h>
#include <media/AudioBufferProvider.h>
#include "FastThreadState.h"
@@ -26,16 +26,14 @@
// Represent a single state of the fast capture
struct FastCaptureState : FastThreadState {
- FastCaptureState();
- /*virtual*/ ~FastCaptureState();
-
// all pointer fields use raw pointers; objects are owned and ref-counted by RecordThread
- NBAIO_Source* mInputSource; // HAL input device, must already be negotiated
+ NBAIO_Source* mInputSource = nullptr; // HAL input device, must already be negotiated
// FIXME by renaming, could pull up these fields to FastThreadState
- int mInputSourceGen; // increment when mInputSource is assigned
- NBAIO_Sink* mPipeSink; // after reading from input source, write to this pipe sink
- int mPipeSinkGen; // increment when mPipeSink is assigned
- size_t mFrameCount; // number of frames per fast capture buffer
+ int mInputSourceGen = 0; // increment when mInputSource is assigned
+ NBAIO_Sink* mPipeSink = nullptr; // after reading from input source,
+ // write to this pipe sink
+ int mPipeSinkGen = 0; // increment when mPipeSink is assigned
+ size_t mFrameCount = 0; // number of frames per fast capture buffer
audio_track_cblk_t* mCblk; // control block for the single fast client, or NULL
audio_format_t mFastPatchRecordFormat = AUDIO_FORMAT_INVALID;
@@ -55,6 +53,7 @@
static const char *commandToString(Command command);
}; // struct FastCaptureState
-} // namespace android
+// No virtuals.
+static_assert(!std::is_polymorphic_v<FastCaptureState>);
-#endif // ANDROID_AUDIO_FAST_CAPTURE_STATE_H
+} // namespace android
diff --git a/services/audioflinger/fastpath/FastMixer.cpp b/services/audioflinger/fastpath/FastMixer.cpp
index 080b0a6..e0a15c1 100644
--- a/services/audioflinger/fastpath/FastMixer.cpp
+++ b/services/audioflinger/fastpath/FastMixer.cpp
@@ -61,48 +61,25 @@
: FastThread("cycle_ms", "load_us"),
// mFastTrackNames
// mGenerations
- mOutputSink(NULL),
- mOutputSinkGen(0),
- mMixer(NULL),
- mSinkBuffer(NULL),
- mSinkBufferSize(0),
- mSinkChannelCount(FCC_2),
- mMixerBuffer(NULL),
- mMixerBufferSize(0),
- mMixerBufferState(UNDEFINED),
- mFormat(Format_Invalid),
- mSampleRate(0),
- mFastTracksGen(0),
- mTotalNativeFramesWritten(0),
// timestamp
- mNativeFramesWrittenButNotPresented(0), // the = 0 is to silence the compiler
- mMasterMono(false),
mThreadIoHandle(parentIoHandle)
{
// FIXME pass sInitial as parameter to base class constructor, and make it static local
mPrevious = &sInitial;
mCurrent = &sInitial;
-
mDummyDumpState = &mDummyFastMixerDumpState;
+
// TODO: Add channel mask to NBAIO_Format.
// We assume that the channel mask must be a valid positional channel mask.
mSinkChannelMask = getChannelMaskFromCount(mSinkChannelCount);
mBalance.setChannelMask(mSinkChannelMask);
- unsigned i;
- for (i = 0; i < FastMixerState::sMaxFastTracks; ++i) {
- mGenerations[i] = 0;
- }
#ifdef FAST_THREAD_STATISTICS
mOldLoad.tv_sec = 0;
mOldLoad.tv_nsec = 0;
#endif
}
-FastMixer::~FastMixer()
-{
-}
-
FastMixerStateQueue* FastMixer::sq()
{
return &mSQ;
@@ -229,13 +206,13 @@
unsigned previousTrackMask;
// check for change in output HAL configuration
- NBAIO_Format previousFormat = mFormat;
+ const NBAIO_Format previousFormat = mFormat;
if (current->mOutputSinkGen != mOutputSinkGen) {
mOutputSink = current->mOutputSink;
mOutputSinkGen = current->mOutputSinkGen;
mSinkChannelMask = current->mSinkChannelMask;
mBalance.setChannelMask(mSinkChannelMask);
- if (mOutputSink == NULL) {
+ if (mOutputSink == nullptr) {
mFormat = Format_Invalid;
mSampleRate = 0;
mSinkChannelCount = 0;
@@ -259,11 +236,11 @@
if ((!Format_isEqual(mFormat, previousFormat)) || (frameCount != previous->mFrameCount)) {
// FIXME to avoid priority inversion, don't delete here
delete mMixer;
- mMixer = NULL;
+ mMixer = nullptr;
free(mMixerBuffer);
- mMixerBuffer = NULL;
+ mMixerBuffer = nullptr;
free(mSinkBuffer);
- mSinkBuffer = NULL;
+ mSinkBuffer = nullptr;
if (frameCount > 0 && mSampleRate > 0) {
// FIXME new may block for unbounded time at internal mutex of the heap
// implementation; it would be better to have normal mixer allocate for us
@@ -320,7 +297,7 @@
// process removed tracks first to avoid running out of track names
unsigned removedTracks = previousTrackMask & ~currentTrackMask;
while (removedTracks != 0) {
- int i = __builtin_ctz(removedTracks);
+ const int i = __builtin_ctz(removedTracks);
removedTracks &= ~(1 << i);
updateMixerTrack(i, REASON_REMOVE);
// don't reset track dump state, since other side is ignoring it
@@ -329,7 +306,7 @@
// now process added tracks
unsigned addedTracks = currentTrackMask & ~previousTrackMask;
while (addedTracks != 0) {
- int i = __builtin_ctz(addedTracks);
+ const int i = __builtin_ctz(addedTracks);
addedTracks &= ~(1 << i);
updateMixerTrack(i, REASON_ADD);
}
@@ -338,7 +315,7 @@
// but may have a different buffer provider or volume provider
unsigned modifiedTracks = currentTrackMask & previousTrackMask;
while (modifiedTracks != 0) {
- int i = __builtin_ctz(modifiedTracks);
+ const int i = __builtin_ctz(modifiedTracks);
modifiedTracks &= ~(1 << i);
updateMixerTrack(i, REASON_MODIFY);
}
@@ -373,8 +350,8 @@
const FastMixerState::Command command = mCommand;
const size_t frameCount = current->mFrameCount;
- if ((command & FastMixerState::MIX) && (mMixer != NULL) && mIsWarm) {
- ALOG_ASSERT(mMixerBuffer != NULL);
+ if ((command & FastMixerState::MIX) && (mMixer != nullptr) && mIsWarm) {
+ ALOG_ASSERT(mMixerBuffer != nullptr);
// AudioMixer::mState.enabledTracks is undefined if mState.hook == process__validate,
// so we keep a side copy of enabledTracks
@@ -383,7 +360,7 @@
// for each track, update volume and check for underrun
unsigned currentTrackMask = current->mTrackMask;
while (currentTrackMask != 0) {
- int i = __builtin_ctz(currentTrackMask);
+ const int i = __builtin_ctz(currentTrackMask);
currentTrackMask &= ~(1 << i);
const FastTrack* fastTrack = ¤t->mFastTracks[i];
@@ -406,8 +383,8 @@
fastTrack->mBufferProvider->onTimestamp(perTrackTimestamp);
const int name = i;
- if (fastTrack->mVolumeProvider != NULL) {
- gain_minifloat_packed_t vlr = fastTrack->mVolumeProvider->getVolumeLR();
+ if (fastTrack->mVolumeProvider != nullptr) {
+ const gain_minifloat_packed_t vlr = fastTrack->mVolumeProvider->getVolumeLR();
float vlf = float_from_gain(gain_minifloat_unpack_left(vlr));
float vrf = float_from_gain(gain_minifloat_unpack_right(vlr));
@@ -418,7 +395,7 @@
// takes a tryLock, which can block
// up to 1 ms. If enough active tracks all blocked in sequence, this would result
// in the overall fast mix cycle being delayed. Should use a non-blocking FIFO.
- size_t framesReady = fastTrack->mBufferProvider->framesReady();
+ const size_t framesReady = fastTrack->mBufferProvider->framesReady();
if (ATRACE_ENABLED()) {
// I wish we had formatted trace names
char traceName[16];
@@ -464,7 +441,8 @@
mMixerBufferState = UNDEFINED;
}
//bool didFullWrite = false; // dumpsys could display a count of partial writes
- if ((command & FastMixerState::WRITE) && (mOutputSink != NULL) && (mMixerBuffer != NULL)) {
+ if ((command & FastMixerState::WRITE)
+ && (mOutputSink != nullptr) && (mMixerBuffer != nullptr)) {
if (mMixerBufferState == UNDEFINED) {
memset(mMixerBuffer, 0, mMixerBufferSize);
mMixerBufferState = ZEROED;
@@ -481,7 +459,7 @@
mBalance.process((float *)mMixerBuffer, frameCount);
// prepare the buffer used to write to sink
- void *buffer = mSinkBuffer != NULL ? mSinkBuffer : mMixerBuffer;
+ void *buffer = mSinkBuffer != nullptr ? mSinkBuffer : mMixerBuffer;
if (mFormat.mFormat != mMixerBufferFormat) { // sink format not the same as mixer format
memcpy_by_audio_format(buffer, mFormat.mFormat, mMixerBuffer, mMixerBufferFormat,
frameCount * Format_channelCount(mFormat));
@@ -493,7 +471,7 @@
audio_bytes_per_sample(mFormat.mFormat),
frameCount * audio_bytes_per_frame(mAudioChannelCount, mFormat.mFormat));
}
- // if non-NULL, then duplicate write() to this non-blocking sink
+ // if non-nullptr, then duplicate write() to this non-blocking sink
#ifdef TEE_SINK
mTee.write(buffer, frameCount);
#endif
@@ -501,7 +479,7 @@
// but this code should be modified to handle both non-blocking and blocking sinks
dumpState->mWriteSequence++;
ATRACE_BEGIN("write");
- ssize_t framesWritten = mOutputSink->write(buffer, frameCount);
+ const ssize_t framesWritten = mOutputSink->write(buffer, frameCount);
ATRACE_END();
dumpState->mWriteSequence++;
if (framesWritten >= 0) {
diff --git a/services/audioflinger/fastpath/FastMixer.h b/services/audioflinger/fastpath/FastMixer.h
index 9847507..48b94a3 100644
--- a/services/audioflinger/fastpath/FastMixer.h
+++ b/services/audioflinger/fastpath/FastMixer.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_AUDIO_FAST_MIXER_H
-#define ANDROID_AUDIO_FAST_MIXER_H
+#pragma once
#include <atomic>
#include <audio_utils/Balance.h>
@@ -29,7 +28,7 @@
class AudioMixer;
-typedef StateQueue<FastMixerState> FastMixerStateQueue;
+using FastMixerStateQueue = StateQueue<FastMixerState>;
class FastMixer : public FastThread {
@@ -37,7 +36,6 @@
/** FastMixer constructor takes as param the parent MixerThread's io handle (id)
for purposes of identification. */
explicit FastMixer(audio_io_handle_t threadIoHandle);
- virtual ~FastMixer();
FastMixerStateQueue* sq();
@@ -51,13 +49,13 @@
FastMixerStateQueue mSQ;
// callouts
- virtual const FastThreadState *poll();
- virtual void setNBLogWriter(NBLog::Writer *logWriter);
- virtual void onIdle();
- virtual void onExit();
- virtual bool isSubClassCommand(FastThreadState::Command command);
- virtual void onStateChange();
- virtual void onWork();
+ const FastThreadState *poll() override;
+ void setNBLogWriter(NBLog::Writer *logWriter) override;
+ void onIdle() override;
+ void onExit() override;
+ bool isSubClassCommand(FastThreadState::Command command) override;
+ void onStateChange() override;
+ void onWork() override;
enum Reason {
REASON_REMOVE,
@@ -71,39 +69,39 @@
static const FastMixerState sInitial;
FastMixerState mPreIdle; // copy of state before we went into idle
- int mGenerations[FastMixerState::kMaxFastTracks];
+ int mGenerations[FastMixerState::kMaxFastTracks]{};
// last observed mFastTracks[i].mGeneration
- NBAIO_Sink* mOutputSink;
- int mOutputSinkGen;
- AudioMixer* mMixer;
+ NBAIO_Sink* mOutputSink = nullptr;
+ int mOutputSinkGen = 0;
+ AudioMixer* mMixer = nullptr;
// mSinkBuffer audio format is stored in format.mFormat.
- void* mSinkBuffer; // used for mixer output format translation
+ void* mSinkBuffer = nullptr; // used for mixer output format translation
// if sink format is different than mixer output.
- size_t mSinkBufferSize;
- uint32_t mSinkChannelCount;
+ size_t mSinkBufferSize = 0;
+ uint32_t mSinkChannelCount = FCC_2;
audio_channel_mask_t mSinkChannelMask;
- void* mMixerBuffer; // mixer output buffer.
- size_t mMixerBufferSize;
+ void* mMixerBuffer = nullptr; // mixer output buffer.
+ size_t mMixerBufferSize = 0;
static constexpr audio_format_t mMixerBufferFormat = AUDIO_FORMAT_PCM_FLOAT;
uint32_t mAudioChannelCount; // audio channel count, excludes haptic channels.
- enum {UNDEFINED, MIXED, ZEROED} mMixerBufferState;
- NBAIO_Format mFormat;
- unsigned mSampleRate;
- int mFastTracksGen;
+ enum {UNDEFINED, MIXED, ZEROED} mMixerBufferState = UNDEFINED;
+ NBAIO_Format mFormat{Format_Invalid};
+ unsigned mSampleRate = 0;
+ int mFastTracksGen = 0;
FastMixerDumpState mDummyFastMixerDumpState;
- int64_t mTotalNativeFramesWritten; // copied to dumpState->mFramesWritten
+ int64_t mTotalNativeFramesWritten = 0; // copied to dumpState->mFramesWritten
// next 2 fields are valid only when timestampStatus == NO_ERROR
ExtendedTimestamp mTimestamp;
- int64_t mNativeFramesWrittenButNotPresented;
+ int64_t mNativeFramesWrittenButNotPresented = 0;
audio_utils::Balance mBalance;
// accessed without lock between multiple threads.
- std::atomic_bool mMasterMono;
+ std::atomic_bool mMasterMono{};
std::atomic<float> mMasterBalance{};
std::atomic_int_fast64_t mBoottimeOffset;
@@ -115,5 +113,3 @@
}; // class FastMixer
} // namespace android
-
-#endif // ANDROID_AUDIO_FAST_MIXER_H
diff --git a/services/audioflinger/fastpath/FastMixerDumpState.cpp b/services/audioflinger/fastpath/FastMixerDumpState.cpp
index d041882..4f79dd6 100644
--- a/services/audioflinger/fastpath/FastMixerDumpState.cpp
+++ b/services/audioflinger/fastpath/FastMixerDumpState.cpp
@@ -29,23 +29,11 @@
namespace android {
-FastMixerDumpState::FastMixerDumpState() : FastThreadDumpState(),
- mWriteSequence(0), mFramesWritten(0),
- mNumTracks(0), mWriteErrors(0),
- mSampleRate(0), mFrameCount(0),
- mTrackMask(0)
-{
-}
-
-FastMixerDumpState::~FastMixerDumpState()
-{
-}
-
// helper function called by qsort()
static int compare_uint32_t(const void *pa, const void *pb)
{
- uint32_t a = *(const uint32_t *)pa;
- uint32_t b = *(const uint32_t *)pb;
+ const uint32_t a = *(const uint32_t *)pa;
+ const uint32_t b = *(const uint32_t *)pb;
if (a < b) {
return -1;
} else if (a > b) {
@@ -61,9 +49,9 @@
dprintf(fd, " FastMixer not initialized\n");
return;
}
- double measuredWarmupMs = (mMeasuredWarmupTs.tv_sec * 1000.0) +
+ const double measuredWarmupMs = (mMeasuredWarmupTs.tv_sec * 1000.0) +
(mMeasuredWarmupTs.tv_nsec / 1000000.0);
- double mixPeriodSec = (double) mFrameCount / mSampleRate;
+ const double mixPeriodSec = (double) mFrameCount / mSampleRate;
dprintf(fd, " FastMixer command=%s writeSequence=%u framesWritten=%u\n"
" numTracks=%u writeErrors=%u underruns=%u overruns=%u\n"
" sampleRate=%u frameCount=%zu measuredWarmup=%.3g ms, warmupCycles=%u\n"
@@ -99,16 +87,16 @@
// the mean account for 99.73% of the population. So if we take each tail to be 1/1000 of the
// sample set, we get 99.8% combined, or close to three standard deviations.
static const uint32_t kTailDenominator = 1000;
- uint32_t *tail = n >= kTailDenominator ? new uint32_t[n] : NULL;
+ uint32_t *tail = n >= kTailDenominator ? new uint32_t[n] : nullptr;
// loop over all the samples
for (uint32_t j = 0; j < n; ++j) {
- size_t i = oldestClosed++ & (mSamplingN - 1);
- uint32_t wallNs = mMonotonicNs[i];
- if (tail != NULL) {
+ const size_t i = oldestClosed++ & (mSamplingN - 1);
+ const uint32_t wallNs = mMonotonicNs[i];
+ if (tail != nullptr) {
tail[j] = wallNs;
}
wall.add(wallNs);
- uint32_t sampleLoadNs = mLoadNs[i];
+ const uint32_t sampleLoadNs = mLoadNs[i];
loadNs.add(sampleLoadNs);
#ifdef CPU_FREQUENCY_STATISTICS
uint32_t sampleCpukHz = mCpukHz[i];
@@ -146,10 +134,10 @@
" mean=%.1f min=%.1f max=%.1f stddev=%.1f\n",
loadMHz.getMean(), loadMHz.getMin(), loadMHz.getMax(), loadMHz.getStdDev());
#endif
- if (tail != NULL) {
+ if (tail != nullptr) {
qsort(tail, n, sizeof(uint32_t), compare_uint32_t);
// assume same number of tail samples on each side, left and right
- uint32_t count = n / kTailDenominator;
+ const uint32_t count = n / kTailDenominator;
audio_utils::Statistics<double> left, right;
for (uint32_t i = 0; i < count; ++i) {
left.add(tail[i]);
@@ -175,7 +163,7 @@
FastMixerState::sMaxFastTracks, trackMask);
dprintf(fd, " Index Active Full Partial Empty Recent Ready Written\n");
for (uint32_t i = 0; i < FastMixerState::sMaxFastTracks; ++i, trackMask >>= 1) {
- bool isActive = trackMask & 1;
+ const bool isActive = trackMask & 1;
const FastTrackDump *ftDump = &mTracks[i];
const FastTrackUnderruns& underruns = ftDump->mUnderruns;
const char *mostRecent;
diff --git a/services/audioflinger/fastpath/FastMixerDumpState.h b/services/audioflinger/fastpath/FastMixerDumpState.h
index 294ef78..1b0e029 100644
--- a/services/audioflinger/fastpath/FastMixerDumpState.h
+++ b/services/audioflinger/fastpath/FastMixerDumpState.h
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-#ifndef ANDROID_AUDIO_FAST_MIXER_DUMP_STATE_H
-#define ANDROID_AUDIO_FAST_MIXER_DUMP_STATE_H
+#pragma once
#include <stdint.h>
+#include <type_traits>
#include <audio_utils/TimestampVerifier.h>
#include "Configuration.h"
#include "FastThreadDumpState.h"
@@ -54,33 +54,32 @@
// Represents the dump state of a fast track
struct FastTrackDump {
- FastTrackDump() : mFramesReady(0) { }
- /*virtual*/ ~FastTrackDump() { }
FastTrackUnderruns mUnderruns;
- size_t mFramesReady; // most recent value only; no long-term statistics kept
+ size_t mFramesReady = 0; // most recent value only; no long-term statistics kept
int64_t mFramesWritten; // last value from track
};
-struct FastMixerDumpState : FastThreadDumpState {
- FastMixerDumpState();
- /*virtual*/ ~FastMixerDumpState();
+// No virtuals.
+static_assert(!std::is_polymorphic_v<FastTrackDump>);
+struct FastMixerDumpState : FastThreadDumpState {
void dump(int fd) const; // should only be called on a stable copy, not the original
- double mLatencyMs = 0.; // measured latency, default of 0 if no valid timestamp read.
- uint32_t mWriteSequence; // incremented before and after each write()
- uint32_t mFramesWritten; // total number of frames written successfully
- uint32_t mNumTracks; // total number of active fast tracks
- uint32_t mWriteErrors; // total number of write() errors
- uint32_t mSampleRate;
- size_t mFrameCount;
- uint32_t mTrackMask; // mask of active tracks
+ double mLatencyMs = 0.; // measured latency, default of 0 if no valid timestamp read.
+ uint32_t mWriteSequence = 0; // incremented before and after each write()
+ uint32_t mFramesWritten = 0; // total number of frames written successfully
+ uint32_t mNumTracks = 0; // total number of active fast tracks
+ uint32_t mWriteErrors = 0; // total number of write() errors
+ uint32_t mSampleRate = 0;
+ size_t mFrameCount = 0;
+ uint32_t mTrackMask = 0; // mask of active tracks
FastTrackDump mTracks[FastMixerState::kMaxFastTracks];
// For timestamp statistics.
TimestampVerifier<int64_t /* frame count */, int64_t /* time ns */> mTimestampVerifier;
};
-} // namespace android
+// No virtuals.
+static_assert(!std::is_polymorphic_v<FastMixerDumpState>);
-#endif // ANDROID_AUDIO_FAST_MIXER_DUMP_STATE_H
+} // namespace android
diff --git a/services/audioflinger/fastpath/FastMixerState.cpp b/services/audioflinger/fastpath/FastMixerState.cpp
index b98842d..4fe2d86 100644
--- a/services/audioflinger/fastpath/FastMixerState.cpp
+++ b/services/audioflinger/fastpath/FastMixerState.cpp
@@ -22,31 +22,14 @@
namespace android {
-FastTrack::FastTrack() :
- mBufferProvider(NULL), mVolumeProvider(NULL),
- mChannelMask(AUDIO_CHANNEL_OUT_STEREO), mFormat(AUDIO_FORMAT_INVALID), mGeneration(0)
+FastMixerState::FastMixerState() : FastThreadState()
{
-}
-
-FastTrack::~FastTrack()
-{
-}
-
-FastMixerState::FastMixerState() : FastThreadState(),
- // mFastTracks
- mFastTracksGen(0), mTrackMask(0), mOutputSink(NULL), mOutputSinkGen(0),
- mFrameCount(0)
-{
- int ok = pthread_once(&sMaxFastTracksOnce, sMaxFastTracksInit);
+ const int ok = pthread_once(&sMaxFastTracksOnce, sMaxFastTracksInit);
if (ok != 0) {
ALOGE("%s pthread_once failed: %d", __func__, ok);
}
}
-FastMixerState::~FastMixerState()
-{
-}
-
// static
unsigned FastMixerState::sMaxFastTracks = kDefaultFastTracks;
@@ -57,7 +40,7 @@
const char *FastMixerState::commandToString(Command command)
{
const char *str = FastThreadState::commandToString(command);
- if (str != NULL) {
+ if (str != nullptr) {
return str;
}
switch (command) {
@@ -72,9 +55,9 @@
void FastMixerState::sMaxFastTracksInit()
{
char value[PROPERTY_VALUE_MAX];
- if (property_get("ro.audio.max_fast_tracks", value, NULL) > 0) {
+ if (property_get("ro.audio.max_fast_tracks", value, nullptr /* default_value */) > 0) {
char *endptr;
- unsigned long ul = strtoul(value, &endptr, 0);
+ const auto ul = strtoul(value, &endptr, 0);
if (*endptr == '\0' && kMinFastTracks <= ul && ul <= kMaxFastTracks) {
sMaxFastTracks = (unsigned) ul;
}
diff --git a/services/audioflinger/fastpath/FastMixerState.h b/services/audioflinger/fastpath/FastMixerState.h
index ce3cc14..fdf3eaa 100644
--- a/services/audioflinger/fastpath/FastMixerState.h
+++ b/services/audioflinger/fastpath/FastMixerState.h
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-#ifndef ANDROID_AUDIO_FAST_MIXER_STATE_H
-#define ANDROID_AUDIO_FAST_MIXER_STATE_H
+#pragma once
#include <math.h>
+#include <type_traits>
#include <audio_utils/minifloat.h>
#include <system/audio.h>
@@ -38,28 +38,32 @@
virtual gain_minifloat_packed_t getVolumeLR() = 0;
protected:
VolumeProvider() { }
- virtual ~VolumeProvider() { }
+ virtual ~VolumeProvider() = default;
};
// Represents the state of a fast track
struct FastTrack {
- FastTrack();
- /*virtual*/ ~FastTrack();
+ // must be nullptr if inactive, or non-nullptr if active
+ ExtendedAudioBufferProvider* mBufferProvider = nullptr;
- ExtendedAudioBufferProvider* mBufferProvider; // must be NULL if inactive, or non-NULL if active
- VolumeProvider* mVolumeProvider; // optional; if NULL then full-scale
- audio_channel_mask_t mChannelMask; // AUDIO_CHANNEL_OUT_MONO or AUDIO_CHANNEL_OUT_STEREO
- audio_format_t mFormat; // track format
- int mGeneration; // increment when any field is assigned
+ // optional: if nullptr then full-scale
+ VolumeProvider* mVolumeProvider = nullptr;
+
+ // AUDIO_CHANNEL_OUT_MONO or AUDIO_CHANNEL_OUT_STEREO
+ audio_channel_mask_t mChannelMask = AUDIO_CHANNEL_OUT_STEREO;
+ audio_format_t mFormat = AUDIO_FORMAT_INVALID; // track format
+ int mGeneration = 0; // increment when any field is assigned
bool mHapticPlaybackEnabled = false; // haptic playback is enabled or not
os::HapticScale mHapticIntensity = os::HapticScale::MUTE; // intensity of haptic data
float mHapticMaxAmplitude = NAN; // max amplitude allowed for haptic data
};
+// No virtuals.
+static_assert(!std::is_polymorphic_v<FastTrack>);
+
// Represents a single state of the fast mixer
struct FastMixerState : FastThreadState {
FastMixerState();
- /*virtual*/ ~FastMixerState();
// These are the minimum, maximum, and default values for maximum number of fast tracks
static const unsigned kMinFastTracks = 2;
@@ -71,11 +75,12 @@
// all pointer fields use raw pointers; objects are owned and ref-counted by the normal mixer
FastTrack mFastTracks[kMaxFastTracks];
- int mFastTracksGen; // increment when any mFastTracks[i].mGeneration is incremented
- unsigned mTrackMask; // bit i is set if and only if mFastTracks[i] is active
- NBAIO_Sink* mOutputSink; // HAL output device, must already be negotiated
- int mOutputSinkGen; // increment when mOutputSink is assigned
- size_t mFrameCount; // number of frames per fast mix buffer
+ int mFastTracksGen = 0; // increment when any
+ // mFastTracks[i].mGeneration is incremented
+ unsigned mTrackMask = 0; // bit i is set if and only if mFastTracks[i] is active
+ NBAIO_Sink* mOutputSink = nullptr; // HAL output device, must already be negotiated
+ int mOutputSinkGen = 0; // increment when mOutputSink is assigned
+ size_t mFrameCount = 0; // number of frames per fast mix buffer
audio_channel_mask_t mSinkChannelMask; // If not AUDIO_CHANNEL_NONE, specifies sink channel
// mask when it cannot be directly calculated from
// channel count
@@ -95,6 +100,7 @@
}; // struct FastMixerState
-} // namespace android
+// No virtuals.
+static_assert(!std::is_polymorphic_v<FastMixerState>);
-#endif // ANDROID_AUDIO_FAST_MIXER_STATE_H
+} // namespace android
diff --git a/services/audioflinger/fastpath/FastThread.cpp b/services/audioflinger/fastpath/FastThread.cpp
index cadbbec..d054d71 100644
--- a/services/audioflinger/fastpath/FastThread.cpp
+++ b/services/audioflinger/fastpath/FastThread.cpp
@@ -38,69 +38,28 @@
namespace android {
-FastThread::FastThread(const char *cycleMs, const char *loadUs) : Thread(false /*canCallJava*/),
- // re-initialized to &sInitial by subclass constructor
- mPrevious(NULL), mCurrent(NULL),
- /* mOldTs({0, 0}), */
- mOldTsValid(false),
- mSleepNs(-1),
- mPeriodNs(0),
- mUnderrunNs(0),
- mOverrunNs(0),
- mForceNs(0),
- mWarmupNsMin(0),
- mWarmupNsMax(LONG_MAX),
- // re-initialized to &mDummySubclassDumpState by subclass constructor
- mDummyDumpState(NULL),
- mDumpState(NULL),
- mIgnoreNextOverrun(true),
-#ifdef FAST_THREAD_STATISTICS
- // mOldLoad
- mOldLoadValid(false),
- mBounds(0),
- mFull(false),
- // mTcu
-#endif
- mColdGen(0),
- mIsWarm(false),
- /* mMeasuredWarmupTs({0, 0}), */
- mWarmupCycles(0),
- mWarmupConsecutiveInRangeCycles(0),
- mTimestampStatus(INVALID_OPERATION),
-
- mCommand(FastThreadState::INITIAL),
-#if 0
- frameCount(0),
-#endif
- mAttemptedWrite(false)
- // mCycleMs(cycleMs)
- // mLoadUs(loadUs)
+FastThread::FastThread(const char *cycleMs, const char *loadUs) : Thread(false /*canCallJava*/)
{
- mOldTs.tv_sec = 0;
- mOldTs.tv_nsec = 0;
- mMeasuredWarmupTs.tv_sec = 0;
- mMeasuredWarmupTs.tv_nsec = 0;
strlcpy(mCycleMs, cycleMs, sizeof(mCycleMs));
strlcpy(mLoadUs, loadUs, sizeof(mLoadUs));
}
-FastThread::~FastThread()
-{
-}
-
bool FastThread::threadLoop()
{
// LOGT now works even if tlNBLogWriter is nullptr, but we're considering changing that,
// so this initialization permits a future change to remove the check for nullptr.
- tlNBLogWriter = mDummyNBLogWriter.get();
+ aflog::setThreadWriter(mDummyNBLogWriter.get());
for (;;) {
// either nanosleep, sched_yield, or busy wait
if (mSleepNs >= 0) {
if (mSleepNs > 0) {
ALOG_ASSERT(mSleepNs < 1000000000);
- const struct timespec req = {0, mSleepNs};
- nanosleep(&req, NULL);
+ const struct timespec req = {
+ 0, // tv_sec
+ static_cast<long>(mSleepNs) // NOLINT(google-runtime-int)
+ };
+ nanosleep(&req, nullptr);
} else {
sched_yield();
}
@@ -110,7 +69,7 @@
// poll for state change
const FastThreadState *next = poll();
- if (next == NULL) {
+ if (next == nullptr) {
// continue to use the default initial state until a real state is available
// FIXME &sInitial not available, should save address earlier
//ALOG_ASSERT(mCurrent == &sInitial && previous == &sInitial);
@@ -121,10 +80,11 @@
if (next != mCurrent) {
// As soon as possible of learning of a new dump area, start using it
- mDumpState = next->mDumpState != NULL ? next->mDumpState : mDummyDumpState;
- tlNBLogWriter = next->mNBLogWriter != NULL ?
+ mDumpState = next->mDumpState != nullptr ? next->mDumpState : mDummyDumpState;
+ NBLog::Writer * const writer = next->mNBLogWriter != nullptr ?
next->mNBLogWriter : mDummyNBLogWriter.get();
- setNBLogWriter(tlNBLogWriter); // This is used for debugging only
+ aflog::setThreadWriter(writer);
+ setNBLogWriter(writer); // This is used for debugging only
// We want to always have a valid reference to the previous (non-idle) state.
// However, the state queue only guarantees access to current and previous states.
@@ -149,7 +109,7 @@
mCurrent = next;
}
#if !LOG_NDEBUG
- next = NULL; // not referenced again
+ next = nullptr; // not referenced again
#endif
mDumpState->mCommand = mCommand;
@@ -167,12 +127,12 @@
// FIXME consider checking previous state and only perform if previous != COLD_IDLE
if (mCurrent->mColdGen != mColdGen) {
int32_t *coldFutexAddr = mCurrent->mColdFutexAddr;
- ALOG_ASSERT(coldFutexAddr != NULL);
- int32_t old = android_atomic_dec(coldFutexAddr);
+ ALOG_ASSERT(coldFutexAddr != nullptr);
+ const int32_t old = android_atomic_dec(coldFutexAddr);
if (old <= 0) {
- syscall(__NR_futex, coldFutexAddr, FUTEX_WAIT_PRIVATE, old - 1, NULL);
+ syscall(__NR_futex, coldFutexAddr, FUTEX_WAIT_PRIVATE, old - 1, nullptr);
}
- int policy = sched_getscheduler(0) & ~SCHED_RESET_ON_FORK;
+ const int policy = sched_getscheduler(0) & ~SCHED_RESET_ON_FORK;
if (!(policy == SCHED_FIFO || policy == SCHED_RR)) {
ALOGE("did not receive expected priority boost on time");
}
@@ -224,7 +184,7 @@
if (rc == 0) {
if (mOldTsValid) {
time_t sec = newTs.tv_sec - mOldTs.tv_sec;
- long nsec = newTs.tv_nsec - mOldTs.tv_nsec;
+ auto nsec = newTs.tv_nsec - mOldTs.tv_nsec;
ALOGE_IF(sec < 0 || (sec == 0 && nsec < 0),
"clock_gettime(CLOCK_MONOTONIC) failed: was %ld.%09ld but now %ld.%09ld",
mOldTs.tv_sec, mOldTs.tv_nsec, newTs.tv_sec, newTs.tv_nsec);
@@ -267,7 +227,7 @@
mSleepNs = -1;
if (mIsWarm) {
if (sec > 0 || nsec > mUnderrunNs) {
- ATRACE_NAME("underrun");
+ ATRACE_NAME("underrun"); // NOLINT(misc-const-correctness)
// FIXME only log occasionally
ALOGV("underrun: time since last cycle %d.%03ld sec",
(int) sec, nsec / 1000000L);
@@ -298,7 +258,7 @@
#ifdef FAST_THREAD_STATISTICS
if (mIsWarm) {
// advance the FIFO queue bounds
- size_t i = mBounds & (mDumpState->mSamplingN - 1);
+ const size_t i = mBounds & (mDumpState->mSamplingN - 1);
mBounds = (mBounds & 0xFFFF0000) | ((mBounds + 1) & 0xFFFF);
if (mFull) {
//mBounds += 0x10000;
diff --git a/services/audioflinger/fastpath/FastThread.h b/services/audioflinger/fastpath/FastThread.h
index 2f0f73f..1f46b29 100644
--- a/services/audioflinger/fastpath/FastThread.h
+++ b/services/audioflinger/fastpath/FastThread.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_AUDIO_FAST_THREAD_H
-#define ANDROID_AUDIO_FAST_THREAD_H
+#pragma once
#include "Configuration.h"
#ifdef CPU_FREQUENCY_STATISTICS
@@ -31,11 +30,10 @@
public:
FastThread(const char *cycleMs, const char *loadUs);
- virtual ~FastThread();
private:
// implement Thread::threadLoop()
- virtual bool threadLoop();
+ bool threadLoop() override;
protected:
// callouts to subclass in same lexical order as they were in original FastMixer.cpp
@@ -49,49 +47,50 @@
virtual void onWork() = 0;
// FIXME these former local variables need comments
- const FastThreadState* mPrevious;
- const FastThreadState* mCurrent;
- struct timespec mOldTs;
- bool mOldTsValid;
- long mSleepNs; // -1: busy wait, 0: sched_yield, > 0: nanosleep
- long mPeriodNs; // expected period; the time required to render one mix buffer
- long mUnderrunNs; // underrun likely when write cycle is greater than this value
- long mOverrunNs; // overrun likely when write cycle is less than this value
- long mForceNs; // if overrun detected,
- // force the write cycle to take this much time
- long mWarmupNsMin; // warmup complete when write cycle is greater than or equal to
- // this value
- long mWarmupNsMax; // and less than or equal to this value
- FastThreadDumpState* mDummyDumpState;
- FastThreadDumpState* mDumpState;
- bool mIgnoreNextOverrun; // used to ignore initial overrun and first after an
- // underrun
+ const FastThreadState* mPrevious = nullptr;
+ const FastThreadState* mCurrent = nullptr;
+ struct timespec mOldTs{};
+ bool mOldTsValid = false;
+ int64_t mSleepNs = -1; // -1: busy wait, 0: sched_yield, > 0: nanosleep
+ int64_t mPeriodNs = 0; // expected period; the time required to
+ // render one mix buffer
+ int64_t mUnderrunNs = 0; // underrun likely when write cycle
+ // is greater than this value
+ int64_t mOverrunNs = 0; // overrun likely when write cycle is less than this value
+ int64_t mForceNs = 0; // if overrun detected,
+ // force the write cycle to take this much time
+ int64_t mWarmupNsMin = 0; // warmup complete when write cycle is greater
+ // than or equal to this value
+ int64_t mWarmupNsMax = INT64_MAX; // and less than or equal to this value
+ FastThreadDumpState* mDummyDumpState = nullptr;
+ FastThreadDumpState* mDumpState = nullptr;
+ bool mIgnoreNextOverrun = true; // used to ignore initial overrun
+ // and first after an underrun
#ifdef FAST_THREAD_STATISTICS
struct timespec mOldLoad; // previous value of clock_gettime(CLOCK_THREAD_CPUTIME_ID)
- bool mOldLoadValid; // whether oldLoad is valid
- uint32_t mBounds;
- bool mFull; // whether we have collected at least mSamplingN samples
+ bool mOldLoadValid = false; // whether oldLoad is valid
+ uint32_t mBounds = 0;
+ bool mFull = false; // whether we have collected at least mSamplingN samples
#ifdef CPU_FREQUENCY_STATISTICS
ThreadCpuUsage mTcu; // for reading the current CPU clock frequency in kHz
#endif
#endif
- unsigned mColdGen; // last observed mColdGen
- bool mIsWarm; // true means ready to mix,
+ unsigned mColdGen = 0; // last observed mColdGen
+ bool mIsWarm = false; // true means ready to mix,
// false means wait for warmup before mixing
- struct timespec mMeasuredWarmupTs; // how long did it take for warmup to complete
- uint32_t mWarmupCycles; // counter of number of loop cycles during warmup phase
- uint32_t mWarmupConsecutiveInRangeCycles; // number of consecutive cycles in range
+ struct timespec mMeasuredWarmupTs{}; // how long did it take for warmup to complete
+ uint32_t mWarmupCycles = 0; // counter of number of loop cycles during warmup phase
+ uint32_t mWarmupConsecutiveInRangeCycles = 0; // number of consecutive cycles in range
const sp<NBLog::Writer> mDummyNBLogWriter{new NBLog::Writer()};
- status_t mTimestampStatus;
+ status_t mTimestampStatus = INVALID_OPERATION;
- FastThreadState::Command mCommand;
- bool mAttemptedWrite;
+ FastThreadState::Command mCommand = FastThreadState::INITIAL;
+ bool mAttemptedWrite = false;
+ // init in constructor
char mCycleMs[16]; // cycle_ms + suffix
char mLoadUs[16]; // load_us + suffix
}; // class FastThread
} // namespace android
-
-#endif // ANDROID_AUDIO_FAST_THREAD_H
diff --git a/services/audioflinger/fastpath/FastThreadDumpState.cpp b/services/audioflinger/fastpath/FastThreadDumpState.cpp
index e91073f..747cb9e 100644
--- a/services/audioflinger/fastpath/FastThreadDumpState.cpp
+++ b/services/audioflinger/fastpath/FastThreadDumpState.cpp
@@ -19,32 +19,20 @@
namespace android {
-FastThreadDumpState::FastThreadDumpState() :
- mCommand(FastThreadState::INITIAL), mUnderruns(0), mOverruns(0),
- /* mMeasuredWarmupTs({0, 0}), */
- mWarmupCycles(0)
-#ifdef FAST_THREAD_STATISTICS
- , mSamplingN(0), mBounds(0)
-#endif
+FastThreadDumpState::FastThreadDumpState()
{
- mMeasuredWarmupTs.tv_sec = 0;
- mMeasuredWarmupTs.tv_nsec = 0;
#ifdef FAST_THREAD_STATISTICS
increaseSamplingN(1);
#endif
}
-FastThreadDumpState::~FastThreadDumpState()
-{
-}
-
#ifdef FAST_THREAD_STATISTICS
void FastThreadDumpState::increaseSamplingN(uint32_t samplingN)
{
if (samplingN <= mSamplingN || samplingN > kSamplingN || roundup(samplingN) != samplingN) {
return;
}
- uint32_t additional = samplingN - mSamplingN;
+ const uint32_t additional = samplingN - mSamplingN;
// sample arrays aren't accessed atomically with respect to the bounds,
// so clearing reduces chance for dumpsys to read random uninitialized samples
memset(&mMonotonicNs[mSamplingN], 0, sizeof(mMonotonicNs[0]) * additional);
diff --git a/services/audioflinger/fastpath/FastThreadDumpState.h b/services/audioflinger/fastpath/FastThreadDumpState.h
index 0b20e55..b7bc404 100644
--- a/services/audioflinger/fastpath/FastThreadDumpState.h
+++ b/services/audioflinger/fastpath/FastThreadDumpState.h
@@ -14,8 +14,9 @@
* limitations under the License.
*/
-#ifndef ANDROID_AUDIO_FAST_THREAD_DUMP_STATE_H
-#define ANDROID_AUDIO_FAST_THREAD_DUMP_STATE_H
+#pragma once
+
+#include <type_traits>
#include "Configuration.h"
#include "FastThreadState.h"
@@ -30,13 +31,12 @@
// It has a different lifetime than the FastThread, and so it can't be a member of FastThread.
struct FastThreadDumpState {
FastThreadDumpState();
- /*virtual*/ ~FastThreadDumpState();
- FastThreadState::Command mCommand; // current command
- uint32_t mUnderruns; // total number of underruns
- uint32_t mOverruns; // total number of overruns
- struct timespec mMeasuredWarmupTs; // measured warmup time
- uint32_t mWarmupCycles; // number of loop cycles required to warmup
+ FastThreadState::Command mCommand = FastThreadState::INITIAL; // current command
+ uint32_t mUnderruns = 0; // total number of underruns
+ uint32_t mOverruns = 0; // total number of overruns
+ struct timespec mMeasuredWarmupTs{}; // measured warmup time
+ uint32_t mWarmupCycles = 0; // number of loop cycles required to warmup
#ifdef FAST_THREAD_STATISTICS
// Recently collected samples of per-cycle monotonic time, thread CPU time, and CPU frequency.
@@ -48,12 +48,12 @@
// This value was chosen such that each array uses 1 small page (4 Kbytes).
static const uint32_t kSamplingNforLowRamDevice = 0x400;
// Corresponding runtime maximum size of sample arrays, must be a power of 2 <= kSamplingN.
- uint32_t mSamplingN;
+ uint32_t mSamplingN = 0;
// The bounds define the interval of valid samples, and are represented as follows:
// newest open (excluded) endpoint = lower 16 bits of bounds, modulo N
// oldest closed (included) endpoint = upper 16 bits of bounds, modulo N
// Number of valid samples is newest - oldest.
- uint32_t mBounds; // bounds for mMonotonicNs, mThreadCpuNs, and mCpukHz
+ uint32_t mBounds = 0; // bounds for mMonotonicNs, mThreadCpuNs, and mCpukHz
// The elements in the *Ns arrays are in units of nanoseconds <= 3999999999.
uint32_t mMonotonicNs[kSamplingN]; // delta monotonic (wall clock) time
uint32_t mLoadNs[kSamplingN]; // delta CPU load in time
@@ -67,6 +67,7 @@
}; // struct FastThreadDumpState
-} // namespace android
+// No virtuals.
+static_assert(!std::is_polymorphic_v<FastThreadDumpState>);
-#endif // ANDROID_AUDIO_FAST_THREAD_DUMP_STATE_H
+} // namespace android
diff --git a/services/audioflinger/fastpath/FastThreadState.cpp b/services/audioflinger/fastpath/FastThreadState.cpp
index ad5f31f..dfe8e65 100644
--- a/services/audioflinger/fastpath/FastThreadState.cpp
+++ b/services/audioflinger/fastpath/FastThreadState.cpp
@@ -19,16 +19,6 @@
namespace android {
-FastThreadState::FastThreadState() :
- mCommand(INITIAL), mColdFutexAddr(NULL), mColdGen(0), mDumpState(NULL), mNBLogWriter(NULL)
-
-{
-}
-
-FastThreadState::~FastThreadState()
-{
-}
-
// static
const char *FastThreadState::commandToString(FastThreadState::Command command)
{
@@ -38,7 +28,7 @@
case FastThreadState::COLD_IDLE: return "COLD_IDLE";
case FastThreadState::EXIT: return "EXIT";
}
- return NULL;
+ return nullptr;
}
} // namespace android
diff --git a/services/audioflinger/fastpath/FastThreadState.h b/services/audioflinger/fastpath/FastThreadState.h
index 9fb4e06..8e5bedd 100644
--- a/services/audioflinger/fastpath/FastThreadState.h
+++ b/services/audioflinger/fastpath/FastThreadState.h
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-#ifndef ANDROID_AUDIO_FAST_THREAD_STATE_H
-#define ANDROID_AUDIO_FAST_THREAD_STATE_H
+#pragma once
+#include <type_traits>
#include "Configuration.h"
#include <stdint.h>
#include <media/nblog/NBLog.h>
@@ -27,10 +27,7 @@
// Represents a single state of a FastThread
struct FastThreadState {
- FastThreadState();
- /*virtual*/ ~FastThreadState();
-
- typedef uint32_t Command;
+ using Command = uint32_t;
static const Command
INITIAL = 0, // used only for the initial state
HOT_IDLE = 1, // do nothing
@@ -38,18 +35,20 @@
IDLE = 3, // either HOT_IDLE or COLD_IDLE
EXIT = 4; // exit from thread
// additional values defined per subclass
- Command mCommand; // current command
- int32_t* mColdFutexAddr; // for COLD_IDLE only, pointer to the associated futex
- unsigned mColdGen; // increment when COLD_IDLE is requested so it's only performed once
+ Command mCommand = INITIAL; // current command
+ int32_t* mColdFutexAddr = nullptr; // for COLD_IDLE only, pointer to the associated futex
+ unsigned mColdGen = 0; // increment when COLD_IDLE is requested
+ // so it's only performed once
// This might be a one-time configuration rather than per-state
- FastThreadDumpState* mDumpState; // if non-NULL, then update dump state periodically
- NBLog::Writer* mNBLogWriter; // non-blocking logger
+ FastThreadDumpState* mDumpState = nullptr; // if non-NULL, then update dump state periodically
+ NBLog::Writer* mNBLogWriter = nullptr; // non-blocking logger
// returns NULL if command belongs to a subclass
static const char *commandToString(Command command);
}; // struct FastThreadState
-} // namespace android
+// No virtuals.
+static_assert(!std::is_polymorphic_v<FastThreadState>);
-#endif // ANDROID_AUDIO_FAST_THREAD_STATE_H
+} // namespace android
diff --git a/services/audioflinger/fastpath/StateQueue.cpp b/services/audioflinger/fastpath/StateQueue.cpp
index 38ce2c2..e896d29 100644
--- a/services/audioflinger/fastpath/StateQueue.cpp
+++ b/services/audioflinger/fastpath/StateQueue.cpp
@@ -38,23 +38,6 @@
}
#endif
-// Constructor and destructor
-
-template<typename T> StateQueue<T>::StateQueue() :
- mAck(NULL), mCurrent(NULL),
- mMutating(&mStates[0]), mExpecting(NULL),
- mInMutation(false), mIsDirty(false), mIsInitialized(false)
-#ifdef STATE_QUEUE_DUMP
- , mObserverDump(&mObserverDummyDump), mMutatorDump(&mMutatorDummyDump)
-#endif
-{
- atomic_init(&mNext, static_cast<uintptr_t>(0));
-}
-
-template<typename T> StateQueue<T>::~StateQueue()
-{
-}
-
// Observer APIs
template<typename T> const T* StateQueue<T>::poll()
@@ -112,7 +95,7 @@
#endif
// wait for prior push to be acknowledged
- if (mExpecting != NULL) {
+ if (mExpecting != nullptr) {
#ifdef STATE_QUEUE_DUMP
unsigned count = 0;
#endif
@@ -120,7 +103,7 @@
const T *ack = (const T *) mAck; // no additional barrier needed
if (ack == mExpecting) {
// unnecessary as we're about to rewrite
- //mExpecting = NULL;
+ //mExpecting = nullptr;
break;
}
if (block == BLOCK_NEVER) {
@@ -132,7 +115,7 @@
}
++count;
#endif
- nanosleep(&req, NULL);
+ nanosleep(&req, nullptr);
}
#ifdef STATE_QUEUE_DUMP
if (count > 1) {
@@ -156,14 +139,14 @@
// optionally wait for this push or a prior push to be acknowledged
if (block == BLOCK_UNTIL_ACKED) {
- if (mExpecting != NULL) {
+ if (mExpecting != nullptr) {
#ifdef STATE_QUEUE_DUMP
unsigned count = 0;
#endif
for (;;) {
const T *ack = (const T *) mAck; // no additional barrier needed
if (ack == mExpecting) {
- mExpecting = NULL;
+ mExpecting = nullptr;
break;
}
#ifdef STATE_QUEUE_DUMP
@@ -172,7 +155,7 @@
}
++count;
#endif
- nanosleep(&req, NULL);
+ nanosleep(&req, nullptr);
}
#ifdef STATE_QUEUE_DUMP
if (count > 1) {
@@ -187,9 +170,14 @@
} // namespace android
-// Hack to avoid explicit template instantiation of
-// template class StateQueue<FastCaptureState>;
-// template class StateQueue<FastMixerState>;
-#ifdef STATE_QUEUE_INSTANTIATIONS
-#include STATE_QUEUE_INSTANTIATIONS // NOLINT(bugprone-suspicious-include)
-#endif
+// Instantiate StateQueue template for the types we need.
+// This needs to be done in the same translation unit as the template
+// method definitions above.
+
+#include "FastCaptureState.h"
+#include "FastMixerState.h"
+
+namespace android {
+template class StateQueue<FastCaptureState>;
+template class StateQueue<FastMixerState>;
+} // namespace android
diff --git a/services/audioflinger/fastpath/StateQueue.h b/services/audioflinger/fastpath/StateQueue.h
index 27f6a28..29d1809 100644
--- a/services/audioflinger/fastpath/StateQueue.h
+++ b/services/audioflinger/fastpath/StateQueue.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_AUDIO_STATE_QUEUE_H
-#define ANDROID_AUDIO_STATE_QUEUE_H
+#pragma once
#include <stdatomic.h>
@@ -127,8 +126,7 @@
template<typename T> class StateQueue {
public:
- StateQueue();
- virtual ~StateQueue();
+ virtual ~StateQueue() = default; // why is this virtual?
// Observer APIs
@@ -188,28 +186,29 @@
T mStates[kN]; // written by mutator, read by observer
// "volatile" is meaningless with SMP, but here it indicates that we're using atomic ops
- atomic_uintptr_t mNext; // written by mutator to advance next, read by observer
- volatile const T* mAck; // written by observer to acknowledge advance of next, read by mutator
+ atomic_uintptr_t mNext{}; // written by mutator to advance next, read by observer
+ volatile const T* mAck = nullptr; // written by observer to acknowledge advance of next,
+ // read by mutator
// only used by observer
- const T* mCurrent; // most recent value returned by poll()
+ const T* mCurrent = nullptr; // most recent value returned by poll()
// only used by mutator
- T* mMutating; // where updates by mutator are done in place
- const T* mExpecting; // what the mutator expects mAck to be set to
- bool mInMutation; // whether we're currently in the middle of a mutation
- bool mIsDirty; // whether mutating state has been modified since last push
- bool mIsInitialized; // whether mutating state has been initialized yet
+ T* mMutating{&mStates[0]}; // where updates by mutator are done in place
+ const T* mExpecting = nullptr; // what the mutator expects mAck to be set to
+ bool mInMutation = false; // whether we're currently in the middle of a mutation
+ bool mIsDirty = false; // whether mutating state has been modified since last push
+ bool mIsInitialized = false; // whether mutating state has been initialized yet
#ifdef STATE_QUEUE_DUMP
StateQueueObserverDump mObserverDummyDump; // default area for observer dump if not set
- StateQueueObserverDump* mObserverDump; // pointer to active observer dump, always non-NULL
+ // pointer to active observer dump, always non-nullptr
+ StateQueueObserverDump* mObserverDump{&mObserverDummyDump};
StateQueueMutatorDump mMutatorDummyDump; // default area for mutator dump if not set
- StateQueueMutatorDump* mMutatorDump; // pointer to active mutator dump, always non-NULL
+ // pointer to active mutator dump, always non-nullptr
+ StateQueueMutatorDump* mMutatorDump{&mMutatorDummyDump};
#endif
}; // class StateQueue
} // namespace android
-
-#endif // ANDROID_AUDIO_STATE_QUEUE_H
diff --git a/services/audioflinger/fastpath/StateQueueInstantiations.cpp b/services/audioflinger/fastpath/StateQueueInstantiations.cpp
deleted file mode 100644
index 6f4505e..0000000
--- a/services/audioflinger/fastpath/StateQueueInstantiations.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2012 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 "Configuration.h"
-#include "FastMixerState.h"
-#include "FastCaptureState.h"
-#include "StateQueue.h"
-
-// FIXME hack for gcc
-
-namespace android {
-
-template class StateQueue<FastMixerState>; // typedef FastMixerStateQueue
-template class StateQueue<FastCaptureState>; // typedef FastCaptureStateQueue
-
-}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index b7abef9..23d4b33 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1088,7 +1088,12 @@
// and AudioSystem::getOutputSamplingRate().
SortedVector<audio_io_handle_t> outputs = getOutputsForDevices(devices, mOutputs);
- const audio_io_handle_t output = selectOutput(outputs);
+ audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE;
+ if (stream == AUDIO_STREAM_MUSIC &&
+ property_get_bool("audio.deep_buffer.media", false /* default_value */)) {
+ flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
+ }
+ const audio_io_handle_t output = selectOutput(outputs, flags);
ALOGV("getOutput() stream %d selected devices %s, output %d", stream,
devices.toString().c_str(), output);
diff --git a/services/mediaextractor/Android.bp b/services/mediaextractor/Android.bp
index acafe56..e22d749 100644
--- a/services/mediaextractor/Android.bp
+++ b/services/mediaextractor/Android.bp
@@ -89,3 +89,25 @@
"code_coverage.policy",
],
}
+
+cc_fuzz {
+ name: "mediaextractor_service_fuzzer",
+ shared_libs: [
+ "libmedia",
+ "libmediaextractorservice",
+ "libmediautils",
+ "liblog",
+ "libavservices_minijail",
+ ],
+ defaults: [
+ "service_fuzzer_defaults",
+ "fuzzer_disable_leaks",
+ ],
+ srcs: ["fuzzers/MediaExtractorServiceFuzzer.cpp"],
+ fuzz_config: {
+ cc: [
+ "android-media-playback+bugs@google.com",
+ ],
+ triage_assignee: "waghpawan@google.com",
+ },
+}
\ No newline at end of file
diff --git a/services/mediaextractor/fuzzers/MediaExtractorServiceFuzzer.cpp b/services/mediaextractor/fuzzers/MediaExtractorServiceFuzzer.cpp
new file mode 100644
index 0000000..d329e54
--- /dev/null
+++ b/services/mediaextractor/fuzzers/MediaExtractorServiceFuzzer.cpp
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <fuzzbinder/libbinder_driver.h>
+
+#include "MediaExtractorService.h"
+
+using ::android::fuzzService;
+using ::android::sp;
+using ::android::MediaExtractorService;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ auto service = sp<MediaExtractorService>::make();
+ fuzzService(service, FuzzedDataProvider(data, size));
+ return 0;
+}