Merge "Add helper methods for the sound dose test API"
diff --git a/media/libaaudio/src/flowgraph/resampler/MultiChannelResampler.cpp b/media/libaaudio/src/flowgraph/resampler/MultiChannelResampler.cpp
index 7193ff3..a3ce58c 100644
--- a/media/libaaudio/src/flowgraph/resampler/MultiChannelResampler.cpp
+++ b/media/libaaudio/src/flowgraph/resampler/MultiChannelResampler.cpp
@@ -40,7 +40,7 @@
ratio.reduce();
mNumerator = ratio.getNumerator();
mDenominator = ratio.getDenominator();
- mIntegerPhase = mDenominator;
+ mIntegerPhase = mDenominator; // so we start with a write needed
}
// static factory method
diff --git a/media/libaaudio/src/flowgraph/resampler/README.md b/media/libaaudio/src/flowgraph/resampler/README.md
index ea319c7..356f06c 100644
--- a/media/libaaudio/src/flowgraph/resampler/README.md
+++ b/media/libaaudio/src/flowgraph/resampler/README.md
@@ -40,7 +40,7 @@
For example, suppose you are converting from 44100 Hz to 48000 Hz and using an input buffer with 960 frames. If you calculate the number of output frames you get:
- 960 * 48000 * 44100 = 1044.897959...
+ 960.0 * 48000 / 44100 = 1044.897959...
You cannot generate a fractional number of frames. So the resampler will sometimes generate 1044 frames and sometimes 1045 frames. On average it will generate 1044.897959 frames. The resampler stores the fraction internally and keeps track of when to consume or generate a frame.
diff --git a/media/libaaudio/src/flowgraph/resampler/SincResampler.cpp b/media/libaaudio/src/flowgraph/resampler/SincResampler.cpp
index 42d0ca2..a14ee47 100644
--- a/media/libaaudio/src/flowgraph/resampler/SincResampler.cpp
+++ b/media/libaaudio/src/flowgraph/resampler/SincResampler.cpp
@@ -24,9 +24,10 @@
: MultiChannelResampler(builder)
, mSingleFrame2(builder.getChannelCount()) {
assert((getNumTaps() % 4) == 0); // Required for loop unrolling.
- mNumRows = kMaxCoefficients / getNumTaps(); // no guard row needed
- mPhaseScaler = (double) mNumRows / mDenominator;
- double phaseIncrement = 1.0 / mNumRows;
+ mNumRows = kMaxCoefficients / getNumTaps(); // includes guard row
+ const int32_t numRowsNoGuard = mNumRows - 1;
+ mPhaseScaler = (double) numRowsNoGuard / mDenominator;
+ const double phaseIncrement = 1.0 / numRowsNoGuard;
generateCoefficients(builder.getInputRate(),
builder.getOutputRate(),
mNumRows,
@@ -40,39 +41,31 @@
std::fill(mSingleFrame2.begin(), mSingleFrame2.end(), 0.0);
// Determine indices into coefficients table.
- double tablePhase = getIntegerPhase() * mPhaseScaler;
- int index1 = static_cast<int>(floor(tablePhase));
- if (index1 >= mNumRows) { // no guard row needed because we wrap the indices
- tablePhase -= mNumRows;
- index1 -= mNumRows;
- }
-
- int index2 = index1 + 1;
- if (index2 >= mNumRows) { // no guard row needed because we wrap the indices
- index2 -= mNumRows;
- }
-
- float *coefficients1 = &mCoefficients[static_cast<size_t>(index1)
- * static_cast<size_t>(getNumTaps())];
- float *coefficients2 = &mCoefficients[static_cast<size_t>(index2)
- * static_cast<size_t>(getNumTaps())];
+ const double tablePhase = getIntegerPhase() * mPhaseScaler;
+ const int indexLow = static_cast<int>(floor(tablePhase));
+ const int indexHigh = indexLow + 1; // OK because using a guard row.
+ assert (indexHigh < mNumRows);
+ float *coefficientsLow = &mCoefficients[static_cast<size_t>(indexLow)
+ * static_cast<size_t>(getNumTaps())];
+ float *coefficientsHigh = &mCoefficients[static_cast<size_t>(indexHigh)
+ * static_cast<size_t>(getNumTaps())];
float *xFrame = &mX[static_cast<size_t>(mCursor) * static_cast<size_t>(getChannelCount())];
- for (int i = 0; i < mNumTaps; i++) {
- float coefficient1 = *coefficients1++;
- float coefficient2 = *coefficients2++;
+ for (int tap = 0; tap < mNumTaps; tap++) {
+ const float coefficientLow = *coefficientsLow++;
+ const float coefficientHigh = *coefficientsHigh++;
for (int channel = 0; channel < getChannelCount(); channel++) {
- float sample = *xFrame++;
- mSingleFrame[channel] += sample * coefficient1;
- mSingleFrame2[channel] += sample * coefficient2;
+ const float sample = *xFrame++;
+ mSingleFrame[channel] += sample * coefficientLow;
+ mSingleFrame2[channel] += sample * coefficientHigh;
}
}
// Interpolate and copy to output.
- float fraction = tablePhase - index1;
+ const float fraction = tablePhase - indexLow;
for (int channel = 0; channel < getChannelCount(); channel++) {
- float low = mSingleFrame[channel];
- float high = mSingleFrame2[channel];
+ const float low = mSingleFrame[channel];
+ const float high = mSingleFrame2[channel];
frame[channel] = low + (fraction * (high - low));
}
}
diff --git a/media/libaaudio/src/flowgraph/resampler/SincResamplerStereo.cpp b/media/libaaudio/src/flowgraph/resampler/SincResamplerStereo.cpp
index 432137e..d459abf 100644
--- a/media/libaaudio/src/flowgraph/resampler/SincResamplerStereo.cpp
+++ b/media/libaaudio/src/flowgraph/resampler/SincResamplerStereo.cpp
@@ -57,9 +57,6 @@
float *coefficients1 = &mCoefficients[static_cast<size_t>(index1)
* static_cast<size_t>(getNumTaps())];
int index2 = (index1 + 1);
- if (index2 >= mNumRows) { // no guard row needed because we wrap the indices
- index2 = 0;
- }
float *coefficients2 = &mCoefficients[static_cast<size_t>(index2)
* static_cast<size_t>(getNumTaps())];
float *xFrame = &mX[static_cast<size_t>(mCursor) * static_cast<size_t>(getChannelCount())];
diff --git a/media/libaaudio/tests/Android.bp b/media/libaaudio/tests/Android.bp
index 438be0a..24041bc 100644
--- a/media/libaaudio/tests/Android.bp
+++ b/media/libaaudio/tests/Android.bp
@@ -228,3 +228,12 @@
"liblog",
],
}
+
+cc_test {
+ name: "test_resampler",
+ defaults: ["libaaudio_tests_defaults"],
+ srcs: ["test_resampler.cpp"],
+ shared_libs: [
+ "libaaudio_internal",
+ ],
+}
diff --git a/media/libaaudio/tests/test_resampler.cpp b/media/libaaudio/tests/test_resampler.cpp
new file mode 100644
index 0000000..1e4f59c
--- /dev/null
+++ b/media/libaaudio/tests/test_resampler.cpp
@@ -0,0 +1,221 @@
+/*
+ * Copyright 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.
+ */
+
+/*
+ * Test FlowGraph
+ *
+ * This file also tests a few different conversion techniques because
+ * sometimes that have caused compiler bugs.
+ */
+
+#include <iostream>
+
+#include <gtest/gtest.h>
+
+#include "flowgraph/resampler/MultiChannelResampler.h"
+
+using namespace RESAMPLER_OUTER_NAMESPACE::resampler;
+
+// Measure zero crossings.
+static int32_t countZeroCrossingsWithHysteresis(float *input, int32_t numSamples) {
+ const float kHysteresisLevel = 0.25f;
+ int zeroCrossingCount = 0;
+ int state = 0; // can be -1, 0, +1
+ for (int i = 0; i < numSamples; i++) {
+ if (input[i] >= kHysteresisLevel) {
+ if (state < 0) {
+ zeroCrossingCount++;
+ }
+ state = 1;
+ } else if (input[i] <= -kHysteresisLevel) {
+ if (state > 0) {
+ zeroCrossingCount++;
+ }
+ state = -1;
+ }
+ }
+ return zeroCrossingCount;
+}
+
+static constexpr int kChannelCount = 1;
+
+/**
+ * Convert a sine wave and then look for glitches.
+ * Glitches have a high value in the second derivative.
+ */
+static void checkResampler(int32_t sourceRate, int32_t sinkRate,
+ MultiChannelResampler::Quality quality) {
+ const int kNumOutputSamples = 10000;
+ const double framesPerCycle = 81.379; // target output period
+
+ int numInputSamples = kNumOutputSamples * sourceRate / sinkRate;
+
+ std::unique_ptr<float[]> inputBuffer = std::make_unique<float[]>(numInputSamples);
+ std::unique_ptr<float[]> outputBuffer = std::make_unique<float[]>(kNumOutputSamples);
+
+ // Generate a sine wave for input.
+ const double kPhaseIncrement = 2.0 * sinkRate / (framesPerCycle * sourceRate);
+ double phase = 0.0;
+ for (int i = 0; i < numInputSamples; i++) {
+ inputBuffer[i] = sin(phase * M_PI);
+ phase += kPhaseIncrement;
+ while (phase > 1.0) {
+ phase -= 2.0;
+ }
+ }
+ int sourceZeroCrossingCount = countZeroCrossingsWithHysteresis(
+ inputBuffer.get(), numInputSamples);
+
+ // Use a MultiChannelResampler to convert from the sourceRate to the sinkRate.
+ std::unique_ptr<MultiChannelResampler> mcResampler;
+ mcResampler.reset(MultiChannelResampler::make(kChannelCount,
+ sourceRate,
+ sinkRate,
+ quality));
+ int inputFramesLeft = numInputSamples;
+ int numRead = 0;
+ float *input = inputBuffer.get(); // for iteration
+ float *output = outputBuffer.get();
+ while (inputFramesLeft > 0) {
+ if (mcResampler->isWriteNeeded()) {
+ mcResampler->writeNextFrame(input);
+ input++;
+ inputFramesLeft--;
+ } else {
+ mcResampler->readNextFrame(output);
+ output++;
+ numRead++;
+ }
+ }
+
+ ASSERT_LE(numRead, kNumOutputSamples);
+ // Some frames are lost priming the FIR filter.
+ const int kMaxAlgorithmicFrameLoss = 16;
+ EXPECT_GT(numRead, kNumOutputSamples - kMaxAlgorithmicFrameLoss);
+
+ int sinkZeroCrossingCount = countZeroCrossingsWithHysteresis(outputBuffer.get(), numRead);
+ // Some cycles may get chopped off at the end.
+ const int kMaxZeroCrossingDelta = 3;
+ EXPECT_LE(abs(sourceZeroCrossingCount - sinkZeroCrossingCount), kMaxZeroCrossingDelta);
+
+ // Detect glitches by looking for spikes in the second derivative.
+ output = outputBuffer.get();
+ float previousValue = output[0];
+ float previousSlope = output[1] - output[0];
+ for (int i = 0; i < numRead; i++) {
+ float slope = output[i] - previousValue;
+ float slopeDelta = fabs(slope - previousSlope);
+ // Skip a few samples because there are often some steep slope changes at the beginning.
+ if (i > 10) {
+ EXPECT_LT(slopeDelta, 0.1);
+ }
+ previousValue = output[i];
+ previousSlope = slope;
+ }
+
+#if 0
+ // Save to disk for inspection.
+ FILE *fp = fopen( "/sdcard/Download/src_float_out.raw" , "wb" );
+ fwrite(outputBuffer.get(), sizeof(float), numRead, fp );
+ fclose(fp);
+#endif
+}
+
+
+TEST(test_resampler, resampler_scan_all) {
+ // TODO Add 64000, 88200, 96000 when they work. Failing now.
+ const int rates[] = {8000, 11025, 22050, 32000, 44100, 48000};
+ const MultiChannelResampler::Quality qualities[] =
+ {
+ MultiChannelResampler::Quality::Fastest,
+ MultiChannelResampler::Quality::Low,
+ MultiChannelResampler::Quality::Medium,
+ MultiChannelResampler::Quality::High,
+ MultiChannelResampler::Quality::Best
+ };
+ for (int srcRate : rates) {
+ for (int destRate : rates) {
+ for (auto quality : qualities) {
+ if (srcRate != destRate) {
+ checkResampler(srcRate, destRate, quality);
+ }
+ }
+ }
+ }
+}
+
+TEST(test_resampler, resampler_8000_11025_best) {
+ checkResampler(8000, 11025, MultiChannelResampler::Quality::Best);
+}
+TEST(test_resampler, resampler_8000_48000_best) {
+ checkResampler(8000, 48000, MultiChannelResampler::Quality::Best);
+}
+
+TEST(test_resampler, resampler_8000_44100_best) {
+ checkResampler(8000, 44100, MultiChannelResampler::Quality::Best);
+}
+
+TEST(test_resampler, resampler_11025_24000_best) {
+ checkResampler(11025, 24000, MultiChannelResampler::Quality::Best);
+}
+
+TEST(test_resampler, resampler_11025_48000_fastest) {
+ checkResampler(11025, 48000, MultiChannelResampler::Quality::Fastest);
+}
+TEST(test_resampler, resampler_11025_48000_low) {
+ checkResampler(11025, 48000, MultiChannelResampler::Quality::Low);
+}
+TEST(test_resampler, resampler_11025_48000_medium) {
+ checkResampler(11025, 48000, MultiChannelResampler::Quality::Medium);
+}
+TEST(test_resampler, resampler_11025_48000_high) {
+ checkResampler(11025, 48000, MultiChannelResampler::Quality::High);
+}
+
+TEST(test_resampler, resampler_11025_48000_best) {
+ checkResampler(11025, 48000, MultiChannelResampler::Quality::Best);
+}
+
+TEST(test_resampler, resampler_11025_44100_best) {
+ checkResampler(11025, 44100, MultiChannelResampler::Quality::Best);
+}
+
+// TODO This fails because the output is very low.
+//TEST(test_resampler, resampler_11025_88200_best) {
+// checkResampler(11025, 88200, MultiChannelResampler::Quality::Best);
+//}
+
+TEST(test_resampler, resampler_16000_48000_best) {
+ checkResampler(16000, 48000, MultiChannelResampler::Quality::Best);
+}
+
+TEST(test_resampler, resampler_44100_48000_low) {
+ checkResampler(44100, 48000, MultiChannelResampler::Quality::Low);
+}
+TEST(test_resampler, resampler_44100_48000_best) {
+ checkResampler(44100, 48000, MultiChannelResampler::Quality::Best);
+}
+
+// Look for glitches when downsampling.
+TEST(test_resampler, resampler_48000_11025_best) {
+ checkResampler(48000, 11025, MultiChannelResampler::Quality::Best);
+}
+TEST(test_resampler, resampler_48000_44100_best) {
+ checkResampler(48000, 44100, MultiChannelResampler::Quality::Best);
+}
+TEST(test_resampler, resampler_44100_11025_best) {
+ checkResampler(44100, 11025, MultiChannelResampler::Quality::Best);
+}
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 5faa8f3..5a1dc64 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -2459,21 +2459,30 @@
return af->getSupportedLatencyModes(output, modes);
}
-status_t AudioSystem::setBluetoothLatencyModesEnabled(bool enabled) {
+status_t AudioSystem::setBluetoothVariableLatencyEnabled(bool enabled) {
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
if (af == nullptr) {
return PERMISSION_DENIED;
}
- return af->setBluetoothLatencyModesEnabled(enabled);
+ return af->setBluetoothVariableLatencyEnabled(enabled);
}
-status_t AudioSystem::supportsBluetoothLatencyModes(
+status_t AudioSystem::isBluetoothVariableLatencyEnabled(
+ bool *enabled) {
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == nullptr) {
+ return PERMISSION_DENIED;
+ }
+ return af->isBluetoothVariableLatencyEnabled(enabled);
+}
+
+status_t AudioSystem::supportsBluetoothVariableLatency(
bool *support) {
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
if (af == nullptr) {
return PERMISSION_DENIED;
}
- return af->supportsBluetoothLatencyModes(support);
+ return af->supportsBluetoothVariableLatency(support);
}
class CaptureStateListenerImpl : public media::BnCaptureStateListener,
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index ba3e703..d895f80 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -846,17 +846,28 @@
return NO_ERROR;
}
-status_t AudioFlingerClientAdapter::setBluetoothLatencyModesEnabled(bool enabled) {
- return statusTFromBinderStatus(mDelegate->setBluetoothLatencyModesEnabled(enabled));
+status_t AudioFlingerClientAdapter::setBluetoothVariableLatencyEnabled(bool enabled) {
+ return statusTFromBinderStatus(mDelegate->setBluetoothVariableLatencyEnabled(enabled));
}
-status_t AudioFlingerClientAdapter::supportsBluetoothLatencyModes(bool* support) {
+status_t AudioFlingerClientAdapter::isBluetoothVariableLatencyEnabled(bool* enabled) {
+ if (enabled == nullptr) {
+ return BAD_VALUE;
+ }
+
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+ mDelegate->isBluetoothVariableLatencyEnabled(enabled)));
+
+ return NO_ERROR;
+}
+
+status_t AudioFlingerClientAdapter::supportsBluetoothVariableLatency(bool* support) {
if (support == nullptr) {
return BAD_VALUE;
}
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
- mDelegate->supportsBluetoothLatencyModes(support)));
+ mDelegate->supportsBluetoothVariableLatency(support)));
return NO_ERROR;
}
@@ -1389,12 +1400,16 @@
return Status::ok();
}
-Status AudioFlingerServerAdapter::setBluetoothLatencyModesEnabled(bool enabled) {
- return Status::fromStatusT(mDelegate->setBluetoothLatencyModesEnabled(enabled));
+Status AudioFlingerServerAdapter::setBluetoothVariableLatencyEnabled(bool enabled) {
+ return Status::fromStatusT(mDelegate->setBluetoothVariableLatencyEnabled(enabled));
}
-Status AudioFlingerServerAdapter::supportsBluetoothLatencyModes(bool *support) {
- return Status::fromStatusT(mDelegate->supportsBluetoothLatencyModes(support));
+Status AudioFlingerServerAdapter::isBluetoothVariableLatencyEnabled(bool *enabled) {
+ return Status::fromStatusT(mDelegate->isBluetoothVariableLatencyEnabled(enabled));
+}
+
+Status AudioFlingerServerAdapter::supportsBluetoothVariableLatency(bool *support) {
+ return Status::fromStatusT(mDelegate->supportsBluetoothVariableLatency(support));
}
Status AudioFlingerServerAdapter::getSoundDoseInterface(
diff --git a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
index 6497447..7deb384 100644
--- a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
@@ -248,18 +248,23 @@
/**
* Requests if the implementation supports controlling the latency modes
- * over the Bleutooth A2DP or LE Audio links. If it does,
+ * over the Bluetooth A2DP or LE Audio links. If it does,
* setRequestedLatencyMode() and getSupportedLatencyModes() APIs can also be used
* for streams routed to Bluetooth and not just for the spatializer output.
*/
- boolean supportsBluetoothLatencyModes();
+ boolean supportsBluetoothVariableLatency();
/**
* Enables or disables the variable Bluetooth latency control mechanism in the
* audio framework and the audio HAL. This does not apply to the latency mode control
- * on the spatializer output with is a built-in feature.
+ * on the spatializer output as this is a built-in feature.
*/
- void setBluetoothLatencyModesEnabled(boolean enabled);
+ void setBluetoothVariableLatencyEnabled(boolean enabled);
+
+ /**
+ * Indicates if the variable Bluetooth latency control mechanism is enabled or disabled.
+ */
+ boolean isBluetoothVariableLatencyEnabled();
/**
* Registers the sound dose callback and returns the interface for executing
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index e2806c7..5ed8219 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -629,9 +629,11 @@
static status_t getSupportedLatencyModes(audio_io_handle_t output,
std::vector<audio_latency_mode_t>* modes);
- static status_t setBluetoothLatencyModesEnabled(bool enabled);
+ static status_t setBluetoothVariableLatencyEnabled(bool enabled);
- static status_t supportsBluetoothLatencyModes(bool *support);
+ static status_t isBluetoothVariableLatencyEnabled(bool *enabled);
+
+ static status_t supportsBluetoothVariableLatency(bool *support);
static status_t getSupportedMixerAttributes(audio_port_handle_t portId,
std::vector<audio_mixer_attributes_t> *mixerAttrs);
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index 57dd2c1..fdf3113 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -375,9 +375,11 @@
virtual status_t invalidateTracks(const std::vector<audio_port_handle_t>& portIds) = 0;
- virtual status_t setBluetoothLatencyModesEnabled(bool enabled) = 0;
+ virtual status_t setBluetoothVariableLatencyEnabled(bool enabled) = 0;
- virtual status_t supportsBluetoothLatencyModes(bool* support) = 0;
+ virtual status_t isBluetoothVariableLatencyEnabled(bool* enabled) = 0;
+
+ virtual status_t supportsBluetoothVariableLatency(bool* support) = 0;
};
/**
@@ -483,8 +485,9 @@
audio_latency_mode_t mode) override;
status_t getSupportedLatencyModes(
audio_io_handle_t output, std::vector<audio_latency_mode_t>* modes) override;
- status_t setBluetoothLatencyModesEnabled(bool enabled) override;
- status_t supportsBluetoothLatencyModes(bool* support) override;
+ status_t setBluetoothVariableLatencyEnabled(bool enabled) override;
+ status_t isBluetoothVariableLatencyEnabled(bool* enabled) override;
+ status_t supportsBluetoothVariableLatency(bool* support) override;
status_t getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback,
sp<media::ISoundDose>* soundDose) override;
status_t invalidateTracks(const std::vector<audio_port_handle_t>& portIds) override;
@@ -578,10 +581,12 @@
SET_DEVICE_CONNECTED_STATE = media::BnAudioFlingerService::TRANSACTION_setDeviceConnectedState,
SET_REQUESTED_LATENCY_MODE = media::BnAudioFlingerService::TRANSACTION_setRequestedLatencyMode,
GET_SUPPORTED_LATENCY_MODES = media::BnAudioFlingerService::TRANSACTION_getSupportedLatencyModes,
- SET_BLUETOOTH_LATENCY_MODES_ENABLED =
- media::BnAudioFlingerService::TRANSACTION_setBluetoothLatencyModesEnabled,
- SUPPORTS_BLUETOOTH_LATENCY_MODES =
- media::BnAudioFlingerService::TRANSACTION_supportsBluetoothLatencyModes,
+ SET_BLUETOOTH_VARIABLE_LATENCY_ENABLED =
+ media::BnAudioFlingerService::TRANSACTION_setBluetoothVariableLatencyEnabled,
+ IS_BLUETOOTH_VARIABLE_LATENCY_ENABLED =
+ media::BnAudioFlingerService::TRANSACTION_isBluetoothVariableLatencyEnabled,
+ SUPPORTS_BLUETOOTH_VARIABLE_LATENCY =
+ media::BnAudioFlingerService::TRANSACTION_supportsBluetoothVariableLatency,
GET_SOUND_DOSE_INTERFACE = media::BnAudioFlingerService::TRANSACTION_getSoundDoseInterface,
INVALIDATE_TRACKS = media::BnAudioFlingerService::TRANSACTION_invalidateTracks,
};
@@ -707,8 +712,9 @@
Status setRequestedLatencyMode(int output, media::LatencyMode mode) override;
Status getSupportedLatencyModes(int output,
std::vector<media::LatencyMode>* _aidl_return) override;
- Status setBluetoothLatencyModesEnabled(bool enabled) override;
- Status supportsBluetoothLatencyModes(bool* support) override;
+ Status setBluetoothVariableLatencyEnabled(bool enabled) override;
+ Status isBluetoothVariableLatencyEnabled(bool* enabled) override;
+ Status supportsBluetoothVariableLatency(bool* support) override;
Status getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback,
sp<media::ISoundDose>* _aidl_return) override;
Status invalidateTracks(const std::vector<int32_t>& portIds) override;
diff --git a/media/libaudiohal/impl/DeviceHalHidl.h b/media/libaudiohal/impl/DeviceHalHidl.h
index 727e92f..3e33609 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.h
+++ b/media/libaudiohal/impl/DeviceHalHidl.h
@@ -132,7 +132,7 @@
return INVALID_OPERATION;
}
- int32_t supportsBluetoothLatencyModes(bool* supports __unused) override {
+ int32_t supportsBluetoothVariableLatency(bool* supports __unused) override {
// TODO: Implement the HAL query when moving to AIDL HAL.
return INVALID_OPERATION;
}
diff --git a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
index 6379521..3858607 100644
--- a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
@@ -128,7 +128,7 @@
std::vector<media::audio::common::AudioMMapPolicyInfo> *policyInfos) = 0;
virtual int32_t getAAudioMixerBurstCount() = 0;
virtual int32_t getAAudioHardwareBurstMinUsec() = 0;
- virtual int32_t supportsBluetoothLatencyModes(bool* supports) = 0;
+ virtual int32_t supportsBluetoothVariableLatency(bool* supports) = 0;
// Update the connection status of an external device.
virtual status_t setConnectedState(const struct audio_port_v7 *port, bool connected) = 0;
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp b/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp
index 9b42ff1..1bcde74 100644
--- a/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp
@@ -89,6 +89,13 @@
mSamplesToExitCountBb = (mSamplesPerSecond * 0.1);
tempDisabled = mBassTempDisabled;
break;
+ case lvm::BundleEffectType::VIRTUALIZER:
+ LOG(DEBUG) << __func__ << " enable bundle VR";
+ if (mSamplesToExitCountVirt <= 0) mNumberEffectsEnabled++;
+ mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::VIRTUALIZER));
+ mSamplesToExitCountVirt = (mSamplesPerSecond * 0.1);
+ tempDisabled = mVirtualizerTempDisabled;
+ break;
default:
// Add handling for other effects
break;
@@ -112,6 +119,10 @@
LOG(DEBUG) << __func__ << " enable bundle BB";
params.BE_OperatingMode = LVM_BE_ON;
break;
+ case lvm::BundleEffectType::VIRTUALIZER:
+ LOG(DEBUG) << __func__ << " enable bundle VR";
+ params.VirtualizerOperatingMode = LVM_MODE_ON;
+ break;
default:
// Add handling for other effects
break;
@@ -133,6 +144,10 @@
LOG(DEBUG) << __func__ << " disable bundle BB";
mEffectInDrain |= 1 << int(lvm::BundleEffectType::BASS_BOOST);
break;
+ case lvm::BundleEffectType::VIRTUALIZER:
+ LOG(DEBUG) << __func__ << " disable bundle VR";
+ mEffectInDrain |= 1 << int(lvm::BundleEffectType::VIRTUALIZER);
+ break;
default:
// Add handling for other effects
break;
@@ -156,6 +171,10 @@
LOG(DEBUG) << __func__ << " disable bundle BB";
params.BE_OperatingMode = LVM_BE_OFF;
break;
+ case lvm::BundleEffectType::VIRTUALIZER:
+ LOG(DEBUG) << __func__ << " disable bundle VR";
+ params.VirtualizerOperatingMode = LVM_MODE_OFF;
+ break;
default:
// Add handling for other effects
break;
@@ -182,6 +201,7 @@
bool eqEnabled = params.EQNB_OperatingMode == LVM_EQNB_ON;
bool bbEnabled = params.BE_OperatingMode == LVM_BE_ON;
+ bool viEnabled = params.VirtualizerOperatingMode == LVM_MODE_ON;
if (eqEnabled) {
for (int i = 0; i < lvm::MAX_NUM_BANDS; i++) {
@@ -224,6 +244,10 @@
}
}
}
+ // Virtualizer contribution
+ if (viEnabled) {
+ energyContribution += lvm::kVirtualizerContribution * lvm::kVirtualizerContribution;
+ }
double totalEnergyEstimation =
sqrt(energyContribution + energyCross + energyBassBoost) - crossCorrection;
@@ -267,26 +291,55 @@
AudioDeviceDescription::CONNECTION_BT_A2DP});
}
+bool BundleContext::isDeviceSupportedVirtualizer(
+ const aidl::android::media::audio::common::AudioDeviceDescription& device) {
+ return (device == AudioDeviceDescription{AudioDeviceType::OUT_HEADSET,
+ AudioDeviceDescription::CONNECTION_ANALOG} ||
+ device == AudioDeviceDescription{AudioDeviceType::OUT_HEADPHONE,
+ AudioDeviceDescription::CONNECTION_ANALOG} ||
+ device == AudioDeviceDescription{AudioDeviceType::OUT_HEADPHONE,
+ AudioDeviceDescription::CONNECTION_BT_A2DP} ||
+ device == AudioDeviceDescription{AudioDeviceType::OUT_HEADSET,
+ AudioDeviceDescription::CONNECTION_USB});
+}
+
RetCode BundleContext::setOutputDevice(
const aidl::android::media::audio::common::AudioDeviceDescription& device) {
mOutputDevice = device;
- if (mType == lvm::BundleEffectType::BASS_BOOST) {
- if (isDeviceSupportedBassBoost(device)) {
- // If a device doesn't support bass boost, the effect must be temporarily disabled.
- // The effect must still report its original state as this can only be changed by the
- // start/stop commands.
- if (mEnabled) {
- disableOperatingMode();
+ switch (mType) {
+ case lvm::BundleEffectType::BASS_BOOST:
+ if (isDeviceSupportedBassBoost(device)) {
+ // If a device doesn't support bass boost, the effect must be temporarily disabled.
+ // The effect must still report its original state as this can only be changed by
+ // the start/stop commands.
+ if (mEnabled) {
+ disableOperatingMode();
+ }
+ mBassTempDisabled = true;
+ } else {
+ // If a device supports bass boost and the effect has been temporarily disabled
+ // previously then re-enable it
+ if (!mEnabled) {
+ enableOperatingMode();
+ }
+ mBassTempDisabled = false;
}
- mBassTempDisabled = true;
- } else {
- // If a device supports bass boost and the effect has been temporarily disabled
- // previously then re-enable it
- if (!mEnabled) {
- enableOperatingMode();
+ break;
+ case lvm::BundleEffectType::VIRTUALIZER:
+ if (isDeviceSupportedVirtualizer(device)) {
+ if (mEnabled) {
+ disableOperatingMode();
+ }
+ mVirtualizerTempDisabled = true;
+ } else {
+ if (!mEnabled) {
+ enableOperatingMode();
+ }
+ mVirtualizerTempDisabled = false;
}
- mBassTempDisabled = false;
- }
+ break;
+ default:
+ break;
}
return RetCode::SUCCESS;
}
@@ -466,6 +519,30 @@
return limitLevel();
}
+RetCode BundleContext::setVirtualizerStrength(int strength) {
+ if (strength < Virtualizer::MIN_PER_MILLE_STRENGTH ||
+ strength > Virtualizer::MAX_PER_MILLE_STRENGTH) {
+ return RetCode::ERROR_ILLEGAL_PARAMETER;
+ }
+
+ // Update Control Parameter
+ LVM_ControlParams_t params;
+ {
+ std::lock_guard lg(mMutex);
+ RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, " getControlParamFailed");
+
+ params.CS_EffectLevel = ((strength * 32767) / 1000);
+
+ RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, ¶ms),
+ RetCode::ERROR_EFFECT_LIB_ERROR, " setControlParamFailed");
+ }
+
+ mVirtStrengthSaved = strength;
+ LOG(INFO) << __func__ << " success with strength " << strength;
+ return limitLevel();
+}
+
void BundleContext::initControlParameter(LVM_ControlParams_t& params) const {
/* General parameters */
params.OperatingMode = LVM_MODE_ON;
@@ -579,6 +656,12 @@
--mNumberEffectsEnabled;
mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::BASS_BOOST));
}
+ if ((undrainedEffects & 1 << int(lvm::BundleEffectType::VIRTUALIZER)) != 0) {
+ LOG(DEBUG) << "Draining VIRTUALIZER";
+ mSamplesToExitCountVirt = 0;
+ --mNumberEffectsEnabled;
+ mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::VIRTUALIZER));
+ }
}
mEffectProcessCalled |= 1 << int(mType);
if (!mEnabled) {
@@ -609,6 +692,19 @@
LOG(DEBUG) << "Effect_process() this is the last frame for BASS_BOOST";
}
break;
+ case lvm::BundleEffectType::VIRTUALIZER:
+ if (mSamplesToExitCountVirt > 0) {
+ mSamplesToExitCountVirt -= samples;
+ }
+ if (mSamplesToExitCountVirt <= 0) {
+ isDataAvailable = false;
+ if ((mEffectInDrain & 1 << int(lvm::BundleEffectType::VIRTUALIZER)) != 0) {
+ mNumberEffectsEnabled--;
+ mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::VIRTUALIZER));
+ }
+ LOG(DEBUG) << "Effect_process() this is the last frame for VIRTUALIZER";
+ }
+ break;
default:
// Add handling for other effects
break;
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleContext.h b/media/libeffects/lvm/wrapper/Aidl/BundleContext.h
index f3484a2..116ae6f 100644
--- a/media/libeffects/lvm/wrapper/Aidl/BundleContext.h
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleContext.h
@@ -47,7 +47,7 @@
RetCode disable();
RetCode disableOperatingMode();
- void setSampleRate (const int sampleRate) { mSampleRate = sampleRate; }
+ void setSampleRate(const int sampleRate) { mSampleRate = sampleRate; }
int getSampleRate() const { return mSampleRate; }
void setChannelMask(const aidl::android::media::audio::common::AudioChannelLayout& chMask) {
@@ -58,6 +58,8 @@
}
bool isDeviceSupportedBassBoost(
const aidl::android::media::audio::common::AudioDeviceDescription& device);
+ bool isDeviceSupportedVirtualizer(
+ const aidl::android::media::audio::common::AudioDeviceDescription& device);
RetCode setOutputDevice(
const aidl::android::media::audio::common::AudioDeviceDescription& device) override;
@@ -69,6 +71,9 @@
RetCode setBassBoostStrength(int strength);
int getBassBoostStrength() const { return mBassStrengthSaved; }
+ RetCode setVirtualizerStrength(int strength);
+ int getVirtualizerStrength() const { return mVirtStrengthSaved; }
+
RetCode setVolumeStereo(const Parameter::VolumeStereo& volumeStereo) override;
Parameter::VolumeStereo getVolumeStereo() override { return mVolumeStereo; }
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h b/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
index 970043a..95a0dab 100644
--- a/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
@@ -103,8 +103,25 @@
.implementor = "NXP Software Ltd."},
.capability = Capability::make<Capability::bassBoost>(kBassBoostCap)};
+static const Virtualizer::Capability kVirtualizerCap = {.strengthSupported = mStrengthSupported};
+
+static const std::string kVirtualizerEffectName = "Virtualizer";
+
+static const Descriptor kVirtualizerDesc = {
+ .common = {.id = {.type = kVirtualizerTypeUUID,
+ .uuid = kVirtualizerBundleImplUUID,
+ .proxy = kVirtualizerProxyUUID},
+ .flags = {.type = Flags::Type::INSERT,
+ .insert = Flags::Insert::FIRST,
+ .volume = Flags::Volume::CTRL,
+ .deviceIndication = true},
+ .cpuLoad = VIRTUALIZER_CUP_LOAD_ARM9E,
+ .memoryUsage = BUNDLE_MEM_USAGE,
+ .name = kVirtualizerEffectName,
+ .implementor = "NXP Software Ltd."},
+ .capability = Capability::make<Capability::virtualizer>(kVirtualizerCap)};
+
// TODO: add descriptors for other bundle effect types here.
-static const Descriptor kVirtualizerDesc;
static const Descriptor kVolumeDesc;
/* The following tables have been computed using the actual levels measured by the output of
diff --git a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp
index e917ea5..b435ab4 100644
--- a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp
+++ b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp
@@ -34,11 +34,13 @@
using aidl::android::hardware::audio::effect::IEffect;
using aidl::android::hardware::audio::effect::kBassBoostBundleImplUUID;
using aidl::android::hardware::audio::effect::kEqualizerBundleImplUUID;
+using aidl::android::hardware::audio::effect::kVirtualizerBundleImplUUID;
using aidl::android::hardware::audio::effect::State;
using aidl::android::media::audio::common::AudioUuid;
bool isUuidSupported(const AudioUuid* uuid) {
- return (*uuid == kEqualizerBundleImplUUID || *uuid == kBassBoostBundleImplUUID);
+ return (*uuid == kEqualizerBundleImplUUID || *uuid == kBassBoostBundleImplUUID ||
+ *uuid == kVirtualizerBundleImplUUID);
}
extern "C" binder_exception_t createEffect(const AudioUuid* uuid,
@@ -66,6 +68,8 @@
*_aidl_return = aidl::android::hardware::audio::effect::lvm::kEqualizerDesc;
} else if (*in_impl_uuid == kBassBoostBundleImplUUID) {
*_aidl_return = aidl::android::hardware::audio::effect::lvm:: kBassBoostDesc;
+ } else if (*in_impl_uuid == kVirtualizerBundleImplUUID) {
+ *_aidl_return = aidl::android::hardware::audio::effect::lvm::kVirtualizerDesc;
}
return EX_NONE;
}
@@ -82,6 +86,10 @@
mType = lvm::BundleEffectType::BASS_BOOST;
mDescriptor = &lvm::kBassBoostDesc;
mEffectName = &lvm::kBassBoostEffectName;
+ } else if (uuid == kVirtualizerBundleImplUUID) {
+ mType = lvm::BundleEffectType::VIRTUALIZER;
+ mDescriptor = &lvm::kVirtualizerDesc;
+ mEffectName = &lvm::kVirtualizerEffectName;
} else {
// TODO: add other bundle effect types here.
LOG(ERROR) << __func__ << uuid.toString() << " not supported yet!";
@@ -146,6 +154,8 @@
return setParameterEqualizer(specific);
case Parameter::Specific::bassBoost:
return setParameterBassBoost(specific);
+ case Parameter::Specific::virtualizer:
+ return setParameterVirtualizer(specific);
default:
LOG(ERROR) << __func__ << " unsupported tag " << toString(tag);
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
@@ -190,6 +200,23 @@
}
}
+ndk::ScopedAStatus EffectBundleAidl::setParameterVirtualizer(const Parameter::Specific& specific) {
+ auto& vr = specific.get<Parameter::Specific::virtualizer>();
+ auto vrTag = vr.getTag();
+ switch (vrTag) {
+ case Virtualizer::strengthPm: {
+ RETURN_IF(mContext->setVirtualizerStrength(vr.get<Virtualizer::strengthPm>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setStrengthFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ default:
+ LOG(ERROR) << __func__ << " unsupported parameter " << specific.toString();
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "vrTagNotSupported");
+ }
+}
+
ndk::ScopedAStatus EffectBundleAidl::getParameterSpecific(const Parameter::Id& id,
Parameter::Specific* specific) {
RETURN_IF(!specific, EX_NULL_POINTER, "nullPtr");
@@ -200,6 +227,8 @@
return getParameterEqualizer(id.get<Parameter::Id::equalizerTag>(), specific);
case Parameter::Id::bassBoostTag:
return getParameterBassBoost(id.get<Parameter::Id::bassBoostTag>(), specific);
+ case Parameter::Id::virtualizerTag:
+ return getParameterVirtualizer(id.get<Parameter::Id::virtualizerTag>(), specific);
default:
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
@@ -259,6 +288,31 @@
return ndk::ScopedAStatus::ok();
}
+ndk::ScopedAStatus EffectBundleAidl::getParameterVirtualizer(const Virtualizer::Id& id,
+ Parameter::Specific* specific) {
+ RETURN_IF(id.getTag() != Virtualizer::Id::commonTag, EX_ILLEGAL_ARGUMENT,
+ "VirtualizerTagNotSupported");
+
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+ Virtualizer vrParam;
+
+ auto tag = id.get<Virtualizer::Id::commonTag>();
+ switch (tag) {
+ case Virtualizer::strengthPm: {
+ vrParam.set<Virtualizer::strengthPm>(mContext->getVirtualizerStrength());
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << " not handled tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "VirtualizerTagNotSupported");
+ }
+ }
+
+ specific->set<Parameter::Specific::virtualizer>(vrParam);
+ return ndk::ScopedAStatus::ok();
+}
+
std::shared_ptr<EffectContext> EffectBundleAidl::createContext(const Parameter::Common& common) {
if (mContext) {
LOG(DEBUG) << __func__ << " context already exist";
diff --git a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.h b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.h
index 293fae1..ebf100a 100644
--- a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.h
+++ b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.h
@@ -67,6 +67,9 @@
ndk::ScopedAStatus setParameterEqualizer(const Parameter::Specific& specific);
ndk::ScopedAStatus getParameterEqualizer(const Equalizer::Id& id,
Parameter::Specific* specific);
+ ndk::ScopedAStatus setParameterVirtualizer(const Parameter::Specific& specific);
+ ndk::ScopedAStatus getParameterVirtualizer(const Virtualizer::Id& id,
+ Parameter::Specific* specific);
};
} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp
index 6788b56..5e29b3f 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp
@@ -191,8 +191,8 @@
uint8_t key[kBlockSize],
uint8_t iv[kBlockSize],
CryptoPlugin::Mode mode,
- size_t *clearbytes,
- size_t *encryptedbytes)
+ uint32_t *clearbytes,
+ uint32_t *encryptedbytes)
{
// size needed to store all the crypto data
size_t cryptosize;
@@ -236,7 +236,7 @@
if (!meta.findData(kKeyEncryptedSizes, &type, &crypteddata, &cryptedsize)) {
return NULL;
}
- size_t numSubSamples = cryptedsize / sizeof(size_t);
+ size_t numSubSamples = cryptedsize / sizeof(uint32_t);
if (numSubSamples <= 0) {
ALOGE("getSampleCryptoInfo INVALID numSubSamples: %zu", numSubSamples);
@@ -285,8 +285,8 @@
(uint8_t*) key,
(uint8_t*) iv,
(CryptoPlugin::Mode)mode,
- (size_t*) cleardata,
- (size_t*) crypteddata);
+ (uint32_t*) cleardata,
+ (uint32_t*) crypteddata);
}
} // namespace android
diff --git a/media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayerDrm.h b/media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayerDrm.h
index 4360656..232638c 100644
--- a/media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayerDrm.h
+++ b/media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayerDrm.h
@@ -106,8 +106,8 @@
uint8_t key[kBlockSize],
uint8_t iv[kBlockSize],
CryptoPlugin::Mode mode,
- size_t *clearbytes,
- size_t *encryptedbytes);
+ uint32_t *clearbytes,
+ uint32_t *encryptedbytes);
static CryptoInfo *getSampleCryptoInfo(MetaDataBase &meta);
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 33ccf32..d3453f5 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -231,8 +231,9 @@
BINDER_METHOD_ENTRY(setDeviceConnectedState) \
BINDER_METHOD_ENTRY(setRequestedLatencyMode) \
BINDER_METHOD_ENTRY(getSupportedLatencyModes) \
-BINDER_METHOD_ENTRY(setBluetoothLatencyModesEnabled) \
-BINDER_METHOD_ENTRY(supportsBluetoothLatencyModes) \
+BINDER_METHOD_ENTRY(setBluetoothVariableLatencyEnabled) \
+BINDER_METHOD_ENTRY(isBluetoothVariableLatencyEnabled) \
+BINDER_METHOD_ENTRY(supportsBluetoothVariableLatency) \
BINDER_METHOD_ENTRY(getSoundDoseInterface) \
// singleton for Binder Method Statistics for IAudioFlinger
@@ -1669,12 +1670,12 @@
return thread->getSupportedLatencyModes(modes);
}
-status_t AudioFlinger::setBluetoothLatencyModesEnabled(bool enabled) {
+status_t AudioFlinger::setBluetoothVariableLatencyEnabled(bool enabled) {
Mutex::Autolock _l(mLock);
status_t status = INVALID_OPERATION;
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
// Success if at least one PlaybackThread supports Bluetooth latency modes
- if (mPlaybackThreads.valueAt(i)->setBluetoothLatencyModesEnabled(enabled) == NO_ERROR) {
+ if (mPlaybackThreads.valueAt(i)->setBluetoothVariableLatencyEnabled(enabled) == NO_ERROR) {
status = NO_ERROR;
}
}
@@ -1684,14 +1685,22 @@
return status;
}
-status_t AudioFlinger::supportsBluetoothLatencyModes(bool* support) {
+status_t AudioFlinger::isBluetoothVariableLatencyEnabled(bool *enabled) {
+ if (enabled == nullptr) {
+ return BAD_VALUE;
+ }
+ *enabled = mBluetoothLatencyModesEnabled.load();
+ return NO_ERROR;
+}
+
+status_t AudioFlinger::supportsBluetoothVariableLatency(bool* support) {
if (support == nullptr) {
return BAD_VALUE;
}
Mutex::Autolock _l(mLock);
*support = false;
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
- if (mAudioHwDevs.valueAt(i)->supportsBluetoothLatencyModes()) {
+ if (mAudioHwDevs.valueAt(i)->supportsBluetoothVariableLatency()) {
*support = true;
break;
}
@@ -2614,7 +2623,7 @@
if (bool supports = false;
- dev->supportsBluetoothLatencyModes(&supports) == NO_ERROR && supports) {
+ dev->supportsBluetoothVariableLatency(&supports) == NO_ERROR && supports) {
flags = static_cast<AudioHwDevice::Flags>(flags |
AudioHwDevice::AHWD_SUPPORTS_BT_LATENCY_MODES);
}
@@ -2992,7 +3001,7 @@
if (thread->isMsdDevice()) {
thread->setDownStreamPatch(&patch);
}
- thread->setBluetoothLatencyModesEnabled(mBluetoothLatencyModesEnabled.load());
+ thread->setBluetoothVariableLatencyEnabled(mBluetoothLatencyModesEnabled.load());
return thread;
}
}
@@ -4697,8 +4706,9 @@
case TransactionCode::SET_AUDIO_HAL_PIDS:
case TransactionCode::SET_VIBRATOR_INFOS:
case TransactionCode::UPDATE_SECONDARY_OUTPUTS:
- case TransactionCode::SET_BLUETOOTH_LATENCY_MODES_ENABLED:
- case TransactionCode::SUPPORTS_BLUETOOTH_LATENCY_MODES: {
+ case TransactionCode::SET_BLUETOOTH_VARIABLE_LATENCY_ENABLED:
+ case TransactionCode::IS_BLUETOOTH_VARIABLE_LATENCY_ENABLED:
+ case TransactionCode::SUPPORTS_BLUETOOTH_VARIABLE_LATENCY: {
if (!isServiceUid(IPCThreadState::self()->getCallingUid())) {
ALOGW("%s: transaction %d received from PID %d unauthorized UID %d",
__func__, code, IPCThreadState::self()->getCallingPid(),
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 16ad964..6dd1cda 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -305,9 +305,11 @@
virtual status_t getSupportedLatencyModes(audio_io_handle_t output,
std::vector<audio_latency_mode_t>* modes);
- virtual status_t setBluetoothLatencyModesEnabled(bool enabled);
+ virtual status_t setBluetoothVariableLatencyEnabled(bool enabled);
- virtual status_t supportsBluetoothLatencyModes(bool* support);
+ virtual status_t isBluetoothVariableLatencyEnabled(bool* enabled);
+
+ virtual status_t supportsBluetoothVariableLatency(bool* support);
virtual status_t getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback,
sp<media::ISoundDose>* soundDose);
diff --git a/services/audioflinger/AudioHwDevice.h b/services/audioflinger/AudioHwDevice.h
index 0e840a6..1749f3f 100644
--- a/services/audioflinger/AudioHwDevice.h
+++ b/services/audioflinger/AudioHwDevice.h
@@ -66,7 +66,7 @@
return (0 != (mFlags & AHWD_IS_INSERT));
}
- bool supportsBluetoothLatencyModes() const {
+ bool supportsBluetoothVariableLatency() const {
return (0 != (mFlags & AHWD_SUPPORTS_BT_LATENCY_MODES));
}
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index e6d38cc..9598ed9 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -7602,9 +7602,9 @@
return NO_ERROR;
}
-status_t AudioFlinger::PlaybackThread::setBluetoothLatencyModesEnabled(bool enabled) {
+status_t AudioFlinger::PlaybackThread::setBluetoothVariableLatencyEnabled(bool enabled) {
if (mOutput == nullptr || mOutput->audioHwDev == nullptr
- || !mOutput->audioHwDev->supportsBluetoothLatencyModes()) {
+ || !mOutput->audioHwDev->supportsBluetoothVariableLatency()) {
return INVALID_OPERATION;
}
mBluetoothLatencyModesEnabled.store(enabled);
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 247c609..1f0f13a 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -1102,7 +1102,7 @@
return INVALID_OPERATION;
}
- virtual status_t setBluetoothLatencyModesEnabled(bool enabled);
+ virtual status_t setBluetoothVariableLatencyEnabled(bool enabled);
void startMelComputation(const sp<audio_utils::MelProcessor>& processor);
void stopMelComputation();
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index 1abcd86..557245c 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -1523,7 +1523,8 @@
vsyncTime.deadlineTimestamp >= currentTime &&
((!cameraDisplayInSync && vsyncTime.expectedPresentationTime > minPresentT) ||
(cameraDisplayInSync && vsyncTime.expectedPresentationTime >
- mLastPresentTime + minInterval + biasForShortDelay * kTimelineThresholdNs))) {
+ mLastPresentTime + minInterval +
+ static_cast<nsecs_t>(biasForShortDelay * kTimelineThresholdNs)))) {
expectedPresentT = vsyncTime.expectedPresentationTime;
minDiff = std::abs(vsyncTime.expectedPresentationTime - idealPresentT);
}