Merge remote-tracking branch 'aosp/upstream-main' into external/oboe
This will reduce build warnings.
Bug: 329456999
Test: mmm external/oboe
Test: mmma cts/apps/CtsVerifier
Test: mmm frameworks/av/media/libaaudio
Change-Id: I5c1e62db88f92af607851c86172d23e30a0d4daa
diff --git a/apps/OboeTester/app/build.gradle b/apps/OboeTester/app/build.gradle
index 0c093f7..702d290 100644
--- a/apps/OboeTester/app/build.gradle
+++ b/apps/OboeTester/app/build.gradle
@@ -6,8 +6,8 @@
applicationId = "com.mobileer.oboetester"
minSdkVersion 23
targetSdkVersion 34
- versionCode 82
- versionName "2.5.11"
+ versionCode 83
+ versionName "2.5.12"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
diff --git a/apps/OboeTester/app/src/main/cpp/analyzer/BaseSineAnalyzer.h b/apps/OboeTester/app/src/main/cpp/analyzer/BaseSineAnalyzer.h
index 7c7fc80..b9ae220 100644
--- a/apps/OboeTester/app/src/main/cpp/analyzer/BaseSineAnalyzer.h
+++ b/apps/OboeTester/app/src/main/cpp/analyzer/BaseSineAnalyzer.h
@@ -45,6 +45,10 @@
mScaledTolerance = mMagnitude * getTolerance();
}
+ /**
+ *
+ * @return valid phase or kPhaseInvalid=-999
+ */
double getPhaseOffset() {
ALOGD("%s(), mPhaseOffset = %f\n", __func__, mPhaseOffset);
return mPhaseOffset;
@@ -129,7 +133,18 @@
double cosMean = mCosAccumulator / mFramesAccumulated;
double magnitude = 2.0 * sqrt((sinMean * sinMean) + (cosMean * cosMean));
if (phasePtr != nullptr) {
- double phase = atan2(cosMean, sinMean);
+ double phase;
+ if (magnitude < kMinValidMagnitude) {
+ phase = kPhaseInvalid;
+ ALOGD("%s() mag very low! sinMean = %7.5f, cosMean = %7.5f",
+ __func__, sinMean, cosMean);
+ } else {
+ phase = atan2(cosMean, sinMean);
+ if (phase == 0.0) {
+ ALOGD("%s() phase zero! sinMean = %7.5f, cosMean = %7.5f",
+ __func__, sinMean, cosMean);
+ }
+ }
*phasePtr = phase;
}
return magnitude;
@@ -153,9 +168,12 @@
if (mFramesAccumulated == mSinePeriod) {
const double coefficient = 0.1;
double magnitude = calculateMagnitudePhase(&mPhaseOffset);
- ALOGD("%s(), mPhaseOffset = %f\n", __func__, mPhaseOffset);
- // One pole averaging filter.
- setMagnitude((mMagnitude * (1.0 - coefficient)) + (magnitude * coefficient));
+
+ ALOGD("%s(), phaseOffset = %f\n", __func__, mPhaseOffset);
+ if (mPhaseOffset != kPhaseInvalid) {
+ // One pole averaging filter.
+ setMagnitude((mMagnitude * (1.0 - coefficient)) + (magnitude * coefficient));
+ }
resetAccumulator();
return true;
} else {
@@ -193,9 +211,19 @@
double mPhaseIncrement = 0.0;
double mOutputPhase = 0.0;
double mOutputAmplitude = 0.75;
+ // This is the phase offset between the output sine wave and the recorded
+ // signal at the tuned frequency.
// If this jumps around then we are probably just hearing noise.
+ // Noise can cause the magnitude to be high but mPhaseOffset will be pretty random.
+ // If we are tracking a sine wave then mPhaseOffset should be consistent.
double mPhaseOffset = 0.0;
+ // kPhaseInvalid indicates that the phase measurement cannot be used.
+ // We were seeing times when a magnitude of zero was causing atan2(s,c) to
+ // return a phase of zero, which looked valid to Java. This is a way of passing
+ // an error code back to Java as a single value to avoid race conditions.
+ static constexpr double kPhaseInvalid = -999.0;
double mMagnitude = 0.0;
+ static constexpr double kMinValidMagnitude = 2.0 / (1 << 16);
int32_t mFramesAccumulated = 0;
double mSinAccumulator = 0.0;
double mCosAccumulator = 0.0;
diff --git a/apps/OboeTester/app/src/main/cpp/analyzer/DataPathAnalyzer.h b/apps/OboeTester/app/src/main/cpp/analyzer/DataPathAnalyzer.h
index 953cf49..f13996b 100644
--- a/apps/OboeTester/app/src/main/cpp/analyzer/DataPathAnalyzer.h
+++ b/apps/OboeTester/app/src/main/cpp/analyzer/DataPathAnalyzer.h
@@ -65,11 +65,13 @@
if (transformSample(sample, mOutputPhase)) {
// Analyze magnitude and phase on every period.
- double diff = fabs(calculatePhaseError(mPhaseOffset, mPreviousPhaseOffset));
- if (diff < mPhaseTolerance) {
- mMaxMagnitude = std::max(mMagnitude, mMaxMagnitude);
+ if (mPhaseOffset != kPhaseInvalid) {
+ double diff = fabs(calculatePhaseError(mPhaseOffset, mPreviousPhaseOffset));
+ if (diff < mPhaseTolerance) {
+ mMaxMagnitude = std::max(mMagnitude, mMaxMagnitude);
+ }
+ mPreviousPhaseOffset = mPhaseOffset;
}
- mPreviousPhaseOffset = mPhaseOffset;
}
return result;
}
diff --git a/apps/OboeTester/app/src/main/cpp/analyzer/GlitchAnalyzer.h b/apps/OboeTester/app/src/main/cpp/analyzer/GlitchAnalyzer.h
index 747c5ea..fff8790 100644
--- a/apps/OboeTester/app/src/main/cpp/analyzer/GlitchAnalyzer.h
+++ b/apps/OboeTester/app/src/main/cpp/analyzer/GlitchAnalyzer.h
@@ -75,7 +75,7 @@
} else {
double signalToNoise = mMeanSquareSignal / mMeanSquareNoise; // power ratio
double signalToNoiseDB = 10.0 * log(signalToNoise);
- if (signalToNoiseDB < MIN_SNR_DB) {
+ if (signalToNoiseDB < static_cast<float>(MIN_SNR_DB)) {
setResult(ERROR_VOLUME_TOO_LOW);
}
return signalToNoiseDB;
@@ -183,17 +183,20 @@
mFramesAccumulated++;
// Must be a multiple of the period or the calculation will not be accurate.
if (mFramesAccumulated == mSinePeriod * PERIODS_NEEDED_FOR_LOCK) {
- setMagnitude(calculateMagnitudePhase(&mPhaseOffset));
- ALOGD("%s() mag = %f, mPhaseOffset = %f",
- __func__, mMagnitude, mPhaseOffset);
- if (mMagnitude > mThreshold) {
- if (fabs(mPhaseOffset) < kMaxPhaseError) {
- mState = STATE_LOCKED;
- mConsecutiveBadFrames = 0;
+ double magnitude = calculateMagnitudePhase(&mPhaseOffset);
+ if (mPhaseOffset != kPhaseInvalid) {
+ setMagnitude(magnitude);
+ ALOGD("%s() mag = %f, mPhaseOffset = %f",
+ __func__, magnitude, mPhaseOffset);
+ if (mMagnitude > mThreshold) {
+ if (fabs(mPhaseOffset) < kMaxPhaseError) {
+ mState = STATE_LOCKED;
+ mConsecutiveBadFrames = 0;
// ALOGD("%5d: switch to STATE_LOCKED", mFrameCounter);
+ }
+ // Adjust mInputPhase to match measured phase
+ mInputPhase += mPhaseOffset;
}
- // Adjust mInputPhase to match measured phase
- mInputPhase += mPhaseOffset;
}
resetAccumulator();
}
diff --git a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/BaseAutoGlitchActivity.java b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/BaseAutoGlitchActivity.java
index 847dc56..e19b5ef 100644
--- a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/BaseAutoGlitchActivity.java
+++ b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/BaseAutoGlitchActivity.java
@@ -214,7 +214,6 @@
protected void appendFailedSummary(String text) {
mAutomatedTestRunner.appendFailedSummary(text);
}
-
protected void appendSummary(String text) {
mAutomatedTestRunner.appendSummary(text);
}
diff --git a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/StreamConfigurationView.java b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/StreamConfigurationView.java
index 418d08e..9a6fd26 100644
--- a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/StreamConfigurationView.java
+++ b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/StreamConfigurationView.java
@@ -520,11 +520,17 @@
}
private void onChannelCountSpinnerSelected() {
- mIsChannelMaskLastSelected = false;
+ if (mChannelCountSpinner.getSelectedItemPosition() != 0) {
+ mChannelMaskSpinner.setSelection(0); // Override the previous channel mask selection
+ mIsChannelMaskLastSelected = false;
+ }
}
private void onChannelMaskSpinnerSelected() {
- mIsChannelMaskLastSelected = true;
+ if (mChannelMaskSpinner.getSelectedItemPosition() != 0) {
+ mChannelCountSpinner.setSelection(0); // Override the previous channel count selection
+ mIsChannelMaskLastSelected = true;
+ }
}
private void onRequestAudioEffectClicked(boolean isChecked) {
diff --git a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/TestDataPathsActivity.java b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/TestDataPathsActivity.java
index 74879f1..bfe4b83 100644
--- a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/TestDataPathsActivity.java
+++ b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/TestDataPathsActivity.java
@@ -19,11 +19,13 @@
import static com.mobileer.oboetester.IntentBasedTestSupport.configureStreamsFromBundle;
import static com.mobileer.oboetester.StreamConfiguration.convertChannelMaskToText;
+import android.app.Instrumentation;
import android.media.AudioDeviceInfo;
import android.media.AudioManager;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
+import android.view.KeyEvent;
import android.widget.CheckBox;
import android.widget.RadioButton;
import android.widget.RadioGroup;
@@ -88,11 +90,13 @@
public static final int DURATION_SECONDS = 3;
private final static double MIN_REQUIRED_MAGNITUDE = 0.001;
- private final static double MAX_SINE_FREQUENCY = 1000.0;
+ private final static int MAX_SINE_FREQUENCY = 1000;
private final static int TYPICAL_SAMPLE_RATE = 48000;
private final static double FRAMES_PER_CYCLE = TYPICAL_SAMPLE_RATE / MAX_SINE_FREQUENCY;
private final static double PHASE_PER_BIN = 2.0 * Math.PI / FRAMES_PER_CYCLE;
- private final static double MAX_ALLOWED_JITTER = 2.0 * PHASE_PER_BIN;
+ private final static double MAX_ALLOWED_JITTER = 0.5 * PHASE_PER_BIN;
+ // This must match the value of kPhaseInvalid in BaseSineAnalyzer.h
+ private final static double PHASE_INVALID = -999.0;
private final static String MAGNITUDE_FORMAT = "%7.5f";
// These define the values returned by the Java API deviceInfo.getChannelMasks().
@@ -266,18 +270,20 @@
// Only look at the phase if we have a signal.
if (mMagnitude >= MIN_REQUIRED_MAGNITUDE) {
double phase = getPhaseDataPaths();
- // Wait for the analyzer to get a lock on the signal.
- // Arbitrary number of phase measurements before we start measuring jitter.
- final int kMinPhaseMeasurementsRequired = 4;
- if (mPhaseCount >= kMinPhaseMeasurementsRequired) {
- double phaseError = Math.abs(calculatePhaseError(phase, mPhase));
- // collect average error
- mPhaseErrorSum += phaseError;
- mPhaseErrorCount++;
- Log.d(TAG, String.format(Locale.getDefault(), "phase = %7.4f, mPhase = %7.4f, phaseError = %7.4f, jitter = %7.4f",
- phase, mPhase, phaseError, getAveragePhaseError()));
+ if (phase != PHASE_INVALID) {
+ // Wait for the analyzer to get a lock on the signal.
+ // Arbitrary number of phase measurements before we start measuring jitter.
+ final int kMinPhaseMeasurementsRequired = 4;
+ if (mPhaseCount >= kMinPhaseMeasurementsRequired) {
+ double phaseError = Math.abs(calculatePhaseError(phase, mPhase));
+ // collect average error
+ mPhaseErrorSum += phaseError;
+ mPhaseErrorCount++;
+ Log.d(TAG, String.format(Locale.getDefault(), "phase = %7.4f, mPhase = %7.4f, phaseError = %7.4f, jitter = %7.4f",
+ phase, mPhase, phaseError, getAveragePhaseError()));
+ }
+ mPhase = phase;
}
- mPhase = phase;
mPhaseCount++;
}
}
@@ -454,7 +460,8 @@
+ " D=" + actualOutConfig.getDeviceId()
+ ", ch=" + channelText(getOutputChannel(), actualOutConfig.getChannelCount())
+ ", SR=" + actualOutConfig.getSampleRate()
- + ", mag = " + getMagnitudeText(mMaxMagnitude);
+ + ", mag = " + getMagnitudeText(mMaxMagnitude)
+ + ", jitter = " + getJitterText();
}
@Override
@@ -533,18 +540,14 @@
}
void logOneLineSummary(TestResult testResult) {
- logOneLineSummary(testResult, "");
- }
-
- void logOneLineSummary(TestResult testResult, String extra) {
int result = testResult.result;
String oneLineSummary;
if (result == TEST_RESULT_SKIPPED) {
- oneLineSummary = "#" + mAutomatedTestRunner.getTestCount() + extra + ", SKIP";
+ oneLineSummary = "#" + mAutomatedTestRunner.getTestCount() + ", SKIP";
} else if (result == TEST_RESULT_FAILED) {
- oneLineSummary = getOneLineSummary() + extra + ", FAIL";
+ oneLineSummary = getOneLineSummary() + ", FAIL";
} else {
- oneLineSummary = getOneLineSummary() + extra;
+ oneLineSummary = getOneLineSummary();
}
appendSummary(oneLineSummary + "\n");
}
@@ -554,11 +557,6 @@
appendSummary(text + "\n");
}
- void logFailed(String text) {
- log(text);
- logAnalysis(text + "\n");
- }
-
private void testDeviceOutputInfo(AudioDeviceInfo outputDeviceInfo) throws InterruptedException {
AudioDeviceInfo inputDeviceInfo = findCompatibleInputDevice(outputDeviceInfo.getType());
showDeviceInfo(outputDeviceInfo, inputDeviceInfo);
diff --git a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/WaveformView.java b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/WaveformView.java
index 4f4705c..f271f6a 100644
--- a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/WaveformView.java
+++ b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/WaveformView.java
@@ -77,8 +77,9 @@
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
mCurrentWidth = w;
mCurrentHeight = h;
- mOffsetY = 0.5f * h;
- mScaleY = 0.0f - mOffsetY;
+ mOffsetY = 0.5f * h; // Center waveform vertically in the viewport.
+ // Scale down so that we can see the top of the waveforms if they are clipped.
+ mScaleY = -0.95f * mOffsetY; // Negate so positive values are on top.
}
public String getMessage() {
@@ -121,8 +122,8 @@
float x0 = 0.0f;
if (xScale < 1.0) {
// Draw a vertical bar for multiple samples.
- float ymin = mOffsetY;
- float ymax = mOffsetY;
+ float ymin = mOffsetY; // vertical center
+ float ymax = mOffsetY; // vertical center
for (int i = 0; i < mSampleCount; i++) {
float x1 = i * xScale;
if ((int) x0 != (int) x1) {
diff --git a/apps/OboeTester/app/src/main/res/layout/activity_data_paths.xml b/apps/OboeTester/app/src/main/res/layout/activity_data_paths.xml
index a3f27c0..061ec83 100644
--- a/apps/OboeTester/app/src/main/res/layout/activity_data_paths.xml
+++ b/apps/OboeTester/app/src/main/res/layout/activity_data_paths.xml
@@ -16,13 +16,6 @@
android:orientation="horizontal">
<CheckBox
- android:id="@+id/checkbox_paths_input_presets"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:checked="true"
- android:text="InPre" />
-
- <CheckBox
android:id="@+id/checkbox_paths_all_channels"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -30,6 +23,13 @@
android:text="AllCh" />
<CheckBox
+ android:id="@+id/checkbox_paths_input_presets"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:checked="true"
+ android:text="InPre" />
+
+ <CheckBox
android:id="@+id/checkbox_paths_all_sample_rates"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
diff --git a/src/aaudio/AudioStreamAAudio.cpp b/src/aaudio/AudioStreamAAudio.cpp
index db7e658..421798d 100644
--- a/src/aaudio/AudioStreamAAudio.cpp
+++ b/src/aaudio/AudioStreamAAudio.cpp
@@ -528,7 +528,7 @@
if (result == DataCallbackResult::Stop) {
LOGD("Oboe callback returned DataCallbackResult::Stop");
} else {
- LOGE("Oboe callback returned unexpected value = %d", result);
+ LOGE("Oboe callback returned unexpected value. Error: %d", static_cast<int>(result));
}
// Returning Stop caused various problems before S. See #1230
diff --git a/src/common/AudioStreamBuilder.cpp b/src/common/AudioStreamBuilder.cpp
index f655f9f..b1549b5 100644
--- a/src/common/AudioStreamBuilder.cpp
+++ b/src/common/AudioStreamBuilder.cpp
@@ -96,7 +96,7 @@
Result AudioStreamBuilder::openStreamInternal(AudioStream **streamPP) {
auto result = isValidConfig();
if (result != Result::OK) {
- LOGW("%s() invalid config %d", __func__, result);
+ LOGW("%s() invalid config. Error %s", __func__, oboe::convertToText(result));
return result;
}
diff --git a/src/common/DataConversionFlowGraph.cpp b/src/common/DataConversionFlowGraph.cpp
index 374fffd..0bb51ae 100644
--- a/src/common/DataConversionFlowGraph.cpp
+++ b/src/common/DataConversionFlowGraph.cpp
@@ -92,14 +92,14 @@
int32_t sinkSampleRate = sinkStream->getSampleRate();
int32_t sinkFramesPerCallback = sinkStream->getFramesPerDataCallback();
- LOGI("%s() flowgraph converts channels: %d to %d, format: %d to %d"
- ", rate: %d to %d, cbsize: %d to %d, qual = %d",
+ LOGI("%s() flowgraph converts channels: %d to %d, format: %s to %s"
+ ", rate: %d to %d, cbsize: %d to %d, qual = %s",
__func__,
sourceChannelCount, sinkChannelCount,
- sourceFormat, sinkFormat,
+ oboe::convertToText(sourceFormat), oboe::convertToText(sinkFormat),
sourceSampleRate, sinkSampleRate,
sourceFramesPerCallback, sinkFramesPerCallback,
- sourceStream->getSampleRateConversionQuality());
+ oboe::convertToText(sourceStream->getSampleRateConversionQuality()));
// Source
// IF OUTPUT and using a callback then call back to the app using a SourceCaller.
@@ -128,7 +128,7 @@
actualSourceFramesPerCallback);
break;
default:
- LOGE("%s() Unsupported source caller format = %d", __func__, sourceFormat);
+ LOGE("%s() Unsupported source caller format = %d", __func__, static_cast<int>(sourceFormat));
return Result::ErrorIllegalArgument;
}
mSourceCaller->setStream(sourceStream);
@@ -150,7 +150,7 @@
mSource = std::make_unique<SourceI32>(sourceChannelCount);
break;
default:
- LOGE("%s() Unsupported source format = %d", __func__, sourceFormat);
+ LOGE("%s() Unsupported source format = %d", __func__, static_cast<int>(sourceFormat));
return Result::ErrorIllegalArgument;
}
if (isInput) {
@@ -226,7 +226,7 @@
mSink = std::make_unique<SinkI32>(sinkChannelCount);
break;
default:
- LOGE("%s() Unsupported sink format = %d", __func__, sinkFormat);
+ LOGE("%s() Unsupported sink format = %d", __func__, static_cast<int>(sinkFormat));
return Result::ErrorIllegalArgument;;
}
lastOutput->connect(&mSink->input);
diff --git a/src/common/Utilities.cpp b/src/common/Utilities.cpp
index f6718af..d84d35f 100644
--- a/src/common/Utilities.cpp
+++ b/src/common/Utilities.cpp
@@ -278,6 +278,20 @@
}
}
+template<>
+const char *convertToText<SampleRateConversionQuality>(SampleRateConversionQuality sampleRateConversionQuality) {
+
+ switch (sampleRateConversionQuality) {
+ case SampleRateConversionQuality::None: return "None";
+ case SampleRateConversionQuality::Fastest: return "Fastest";
+ case SampleRateConversionQuality::Low: return "Low";
+ case SampleRateConversionQuality::Medium: return "Medium";
+ case SampleRateConversionQuality::High: return "High";
+ case SampleRateConversionQuality::Best: return "Best";
+ default: return "Unrecognized sample rate conversion quality";
+ }
+}
+
std::string getPropertyString(const char * name) {
std::string result;
#ifdef __ANDROID__
diff --git a/src/opensles/AudioOutputStreamOpenSLES.cpp b/src/opensles/AudioOutputStreamOpenSLES.cpp
index 0ef87dd..2b68990 100644
--- a/src/opensles/AudioOutputStreamOpenSLES.cpp
+++ b/src/opensles/AudioOutputStreamOpenSLES.cpp
@@ -372,7 +372,7 @@
} else {
SLresult slResult = (*mSimpleBufferQueueInterface)->Clear(mSimpleBufferQueueInterface);
if (slResult != SL_RESULT_SUCCESS){
- LOGW("Failed to clear buffer queue. OpenSLES error: %d", result);
+ LOGW("Failed to clear buffer queue. OpenSLES error: %s", getSLErrStr(slResult));
result = Result::ErrorInternal;
}
}
diff --git a/src/opensles/AudioStreamOpenSLES.cpp b/src/opensles/AudioStreamOpenSLES.cpp
index 9013d61..ec041cc 100644
--- a/src/opensles/AudioStreamOpenSLES.cpp
+++ b/src/opensles/AudioStreamOpenSLES.cpp
@@ -72,8 +72,8 @@
// OpenSL ES only supports I16 and Float
if (mFormat != AudioFormat::I16 && mFormat != AudioFormat::Float) {
- LOGW("%s() Android's OpenSL ES implementation only supports I16 and Float. Format: %d",
- __func__, mFormat);
+ LOGW("%s() Android's OpenSL ES implementation only supports I16 and Float. Format: %s",
+ __func__, oboe::convertToText(mFormat));
return Result::ErrorInvalidFormat;
}
@@ -422,7 +422,7 @@
LOGD("Oboe callback returned Stop");
shouldStopStream = true;
} else {
- LOGW("Oboe callback returned unexpected value = %d", result);
+ LOGW("Oboe callback returned unexpected value = %d", static_cast<int>(result));
shouldStopStream = true;
}
if (shouldStopStream) {