aboutsummaryrefslogtreecommitdiff
path: root/apps/OboeTester/app/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'apps/OboeTester/app/src/main')
-rw-r--r--apps/OboeTester/app/src/main/cpp/InputStreamCallbackAnalyzer.cpp1
-rw-r--r--apps/OboeTester/app/src/main/cpp/NativeAudioContext.h6
-rw-r--r--apps/OboeTester/app/src/main/cpp/OboeStreamCallbackProxy.cpp14
-rw-r--r--apps/OboeTester/app/src/main/cpp/OboeStreamCallbackProxy.h7
-rw-r--r--apps/OboeTester/app/src/main/cpp/OboeTesterStreamCallback.cpp52
-rw-r--r--apps/OboeTester/app/src/main/cpp/OboeTesterStreamCallback.h21
-rw-r--r--apps/OboeTester/app/src/main/cpp/OboeTools.h25
-rw-r--r--apps/OboeTester/app/src/main/cpp/jni-bridge.cpp6
-rw-r--r--apps/OboeTester/app/src/main/java/com/mobileer/oboetester/OboeAudioStream.java2
-rw-r--r--apps/OboeTester/app/src/main/java/com/mobileer/oboetester/TestAudioActivity.java32
-rw-r--r--apps/OboeTester/app/src/main/res/layout/merge_audio_common.xml65
-rw-r--r--apps/OboeTester/app/src/main/res/values/strings.xml14
12 files changed, 197 insertions, 48 deletions
diff --git a/apps/OboeTester/app/src/main/cpp/InputStreamCallbackAnalyzer.cpp b/apps/OboeTester/app/src/main/cpp/InputStreamCallbackAnalyzer.cpp
index 6ac37599..b90dfbc4 100644
--- a/apps/OboeTester/app/src/main/cpp/InputStreamCallbackAnalyzer.cpp
+++ b/apps/OboeTester/app/src/main/cpp/InputStreamCallbackAnalyzer.cpp
@@ -33,6 +33,7 @@ oboe::DataCallbackResult InputStreamCallbackAnalyzer::onAudioReady(
void *audioData,
int numFrames) {
int32_t channelCount = audioStream->getChannelCount();
+
printScheduler();
mInputConverter->convertToInternalOutput(numFrames * channelCount, audioData);
float *floatData = (float *) mInputConverter->getOutputBuffer();
diff --git a/apps/OboeTester/app/src/main/cpp/NativeAudioContext.h b/apps/OboeTester/app/src/main/cpp/NativeAudioContext.h
index 02143a81..e04f0dbf 100644
--- a/apps/OboeTester/app/src/main/cpp/NativeAudioContext.h
+++ b/apps/OboeTester/app/src/main/cpp/NativeAudioContext.h
@@ -52,6 +52,7 @@
#include "InputStreamCallbackAnalyzer.h"
#include "MultiChannelRecording.h"
#include "OboeStreamCallbackProxy.h"
+#include "OboeTools.h"
#include "PlayRecordingCallback.h"
#include "SawPingGenerator.h"
@@ -67,11 +68,6 @@
#define AMPLITUDE_SAW_PING 0.8
#define AMPLITUDE_IMPULSE 0.7
-#define NANOS_PER_MICROSECOND ((int64_t) 1000)
-#define NANOS_PER_MILLISECOND (1000 * NANOS_PER_MICROSECOND)
-#define NANOS_PER_SECOND (1000 * NANOS_PER_MILLISECOND)
-
-#define MILLISECONDS_PER_SECOND 1000
#define SECONDS_TO_RECORD 10
diff --git a/apps/OboeTester/app/src/main/cpp/OboeStreamCallbackProxy.cpp b/apps/OboeTester/app/src/main/cpp/OboeStreamCallbackProxy.cpp
index 7cf8ce98..2734d8a0 100644
--- a/apps/OboeTester/app/src/main/cpp/OboeStreamCallbackProxy.cpp
+++ b/apps/OboeTester/app/src/main/cpp/OboeStreamCallbackProxy.cpp
@@ -17,19 +17,8 @@
#include "common/OboeDebug.h"
#include "OboeStreamCallbackProxy.h"
-#include "synth/IncludeMeOnce.h"
-
bool OboeStreamCallbackProxy::mCallbackReturnStop = false;
-int64_t OboeStreamCallbackProxy::getNanoseconds(clockid_t clockId) {
- struct timespec time;
- int result = clock_gettime(clockId, &time);
- if (result < 0) {
- return result;
- }
- return (time.tv_sec * 1e9) + time.tv_nsec;
-}
-
oboe::DataCallbackResult OboeStreamCallbackProxy::onAudioReady(
oboe::AudioStream *audioStream,
void *audioData,
@@ -37,6 +26,8 @@ oboe::DataCallbackResult OboeStreamCallbackProxy::onAudioReady(
oboe::DataCallbackResult callbackResult = oboe::DataCallbackResult::Stop;
int64_t startTimeNanos = getNanoseconds();
+ maybeHang(startTimeNanos);
+
if (mCpuAffinityMask != mPreviousMask) {
uint32_t mask = mCpuAffinityMask;
applyCpuAffinityMask(mask);
@@ -62,6 +53,7 @@ oboe::DataCallbackResult OboeStreamCallbackProxy::onAudioReady(
mSynthWorkload.renderStereo(buffer, numFrames);
}
+ // Measure CPU load.
int64_t currentTimeNanos = getNanoseconds();
// Sometimes we get a short callback when doing sample rate conversion.
// Just ignore those to avoid noise.
diff --git a/apps/OboeTester/app/src/main/cpp/OboeStreamCallbackProxy.h b/apps/OboeTester/app/src/main/cpp/OboeStreamCallbackProxy.h
index d72eaa96..bd8725d9 100644
--- a/apps/OboeTester/app/src/main/cpp/OboeStreamCallbackProxy.h
+++ b/apps/OboeTester/app/src/main/cpp/OboeStreamCallbackProxy.h
@@ -24,6 +24,7 @@
#include "oboe/Oboe.h"
#include "synth/Synthesizer.h"
#include "synth/SynthTools.h"
+#include "OboeTesterStreamCallback.h"
class DoubleStatistics {
public:
@@ -133,7 +134,7 @@ private:
int mOffFrames = (int) (0.3 * 48000);
};
-class OboeStreamCallbackProxy : public oboe::AudioStreamCallback {
+class OboeStreamCallbackProxy : public OboeTesterStreamCallback {
public:
void setCallback(oboe::AudioStreamCallback *callback) {
@@ -207,8 +208,6 @@ public:
return mStatistics.dump();
}
- static int64_t getNanoseconds(clockid_t clockId = CLOCK_MONOTONIC);
-
/**
* @param cpuIndex
* @return 0 on success or a negative errno
@@ -250,11 +249,13 @@ private:
oboe::AudioStreamCallback *mCallback = nullptr;
static bool mCallbackReturnStop;
+
int64_t mCallbackCount = 0;
std::atomic<int32_t> mFramesPerCallback{0};
std::atomic<uint32_t> mCpuAffinityMask{0};
std::atomic<uint32_t> mPreviousMask{0};
+
};
#endif //NATIVEOBOE_OBOESTREAMCALLBACKPROXY_H
diff --git a/apps/OboeTester/app/src/main/cpp/OboeTesterStreamCallback.cpp b/apps/OboeTester/app/src/main/cpp/OboeTesterStreamCallback.cpp
index 583c9846..5109f67c 100644
--- a/apps/OboeTester/app/src/main/cpp/OboeTesterStreamCallback.cpp
+++ b/apps/OboeTester/app/src/main/cpp/OboeTesterStreamCallback.cpp
@@ -14,13 +14,18 @@
* limitations under the License.
*/
+#include <sched.h>
+#include <cstring>
#include "AudioStreamGateway.h"
-#include "oboe/Oboe.h"
#include "common/OboeDebug.h"
-#include <sched.h>
-#include <cstring>
+#include "oboe/Oboe.h"
+#include "OboeStreamCallbackProxy.h"
#include "OboeTesterStreamCallback.h"
+#include "OboeTools.h"
+#include "synth/IncludeMeOnce.h"
+
+int32_t OboeTesterStreamCallback::mHangTimeMillis = 0;
// Print if scheduler changes.
void OboeTesterStreamCallback::printScheduler() {
@@ -38,3 +43,44 @@ void OboeTesterStreamCallback::printScheduler() {
}
#endif
}
+
+// Sleep to cause an XRun. Then reschedule.
+void OboeTesterStreamCallback::maybeHang(const int64_t startNanos) {
+ if (mHangTimeMillis == 0) return;
+
+ if (startNanos > mNextTimeToHang) {
+ LOGD("%s() start sleeping", __func__);
+ // Take short naps until it is time to wake up.
+ int64_t nowNanos = startNanos;
+ int64_t wakeupNanos = startNanos + (mHangTimeMillis * NANOS_PER_MILLISECOND);
+ while (nowNanos < wakeupNanos && mHangTimeMillis > 0) {
+ int32_t sleepTimeMicros = (int32_t) ((wakeupNanos - nowNanos) / 1000);
+ if (sleepTimeMicros == 0) break;
+ // The usleep() function can fail if it sleeps for more than one second.
+ // So sleep for several small intervals.
+ // This also allows us to exit the loop if mHangTimeMillis gets set to zero.
+ const int32_t maxSleepTimeMicros = 100 * 1000;
+ sleepTimeMicros = std::min(maxSleepTimeMicros, sleepTimeMicros);
+ usleep(sleepTimeMicros);
+ nowNanos = getNanoseconds();
+ }
+ // Calculate when we hang again.
+ const int32_t minDurationMillis = 500;
+ const int32_t maxDurationMillis = std::max(10000, mHangTimeMillis * 2);
+ int32_t durationMillis = mHangTimeMillis * 10;
+ durationMillis = std::max(minDurationMillis, std::min(maxDurationMillis, durationMillis));
+ mNextTimeToHang = startNanos + (durationMillis * NANOS_PER_MILLISECOND);
+ LOGD("%s() slept for %d msec, durationMillis = %d", __func__,
+ (int)((nowNanos - startNanos) / 1e6L),
+ durationMillis);
+ }
+}
+
+int64_t OboeTesterStreamCallback::getNanoseconds(clockid_t clockId) {
+ struct timespec time;
+ int result = clock_gettime(clockId, &time);
+ if (result < 0) {
+ return result;
+ }
+ return (time.tv_sec * 1e9) + time.tv_nsec;
+} \ No newline at end of file
diff --git a/apps/OboeTester/app/src/main/cpp/OboeTesterStreamCallback.h b/apps/OboeTester/app/src/main/cpp/OboeTesterStreamCallback.h
index ec01fe5c..70a719ea 100644
--- a/apps/OboeTester/app/src/main/cpp/OboeTesterStreamCallback.h
+++ b/apps/OboeTester/app/src/main/cpp/OboeTesterStreamCallback.h
@@ -19,8 +19,11 @@
#include <unistd.h>
#include <sys/types.h>
+#include <sys/sysinfo.h>
#include "flowgraph/FlowGraphNode.h"
#include "oboe/Oboe.h"
+#include "synth/Synthesizer.h"
+#include "synth/SynthTools.h"
class OboeTesterStreamCallback : public oboe::AudioStreamCallback {
public:
@@ -31,10 +34,24 @@ public:
mPreviousScheduler = -1;
}
+ static int64_t getNanoseconds(clockid_t clockId = CLOCK_MONOTONIC);
+
+ /**
+ * Specify a sleep time that will hang the audio periodically.
+ *
+ * @param hangTimeMillis
+ */
+ static void setHangTimeMillis(int hangTimeMillis) {
+ mHangTimeMillis = hangTimeMillis;
+ }
+
protected:
- void printScheduler();
+ void printScheduler();
+ void maybeHang(int64_t nowNanos);
- int mPreviousScheduler = -1;
+ int mPreviousScheduler = -1;
+ static int mHangTimeMillis;
+ int64_t mNextTimeToHang = 0;
};
diff --git a/apps/OboeTester/app/src/main/cpp/OboeTools.h b/apps/OboeTester/app/src/main/cpp/OboeTools.h
new file mode 100644
index 00000000..c8b47f84
--- /dev/null
+++ b/apps/OboeTester/app/src/main/cpp/OboeTools.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright 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.
+ */
+
+#ifndef OBOETESTER_OBOETOOLS_H
+#define OBOETESTER_OBOETOOLS_H
+
+#define NANOS_PER_MICROSECOND ((int64_t) 1000)
+#define NANOS_PER_MILLISECOND (1000 * NANOS_PER_MICROSECOND)
+#define NANOS_PER_SECOND (1000 * NANOS_PER_MILLISECOND)
+#define MILLISECONDS_PER_SECOND 1000
+
+#endif //OBOETESTER_OBOETOOLS_H
diff --git a/apps/OboeTester/app/src/main/cpp/jni-bridge.cpp b/apps/OboeTester/app/src/main/cpp/jni-bridge.cpp
index e916dd0f..b46b8e63 100644
--- a/apps/OboeTester/app/src/main/cpp/jni-bridge.cpp
+++ b/apps/OboeTester/app/src/main/cpp/jni-bridge.cpp
@@ -575,6 +575,12 @@ Java_com_mobileer_oboetester_OboeAudioStream_setCallbackReturnStop(JNIEnv *env,
}
JNIEXPORT void JNICALL
+Java_com_mobileer_oboetester_OboeAudioStream_setHangTimeMillis(JNIEnv *env, jclass type,
+ jint hangTimeMillis) {
+ OboeTesterStreamCallback::setHangTimeMillis(hangTimeMillis);
+}
+
+JNIEXPORT void JNICALL
Java_com_mobileer_oboetester_OboeAudioStream_setCallbackSize(JNIEnv *env, jclass type,
jint callbackSize) {
ActivityContext::callbackSize = callbackSize;
diff --git a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/OboeAudioStream.java b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/OboeAudioStream.java
index 32078aaa..5c453e13 100644
--- a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/OboeAudioStream.java
+++ b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/OboeAudioStream.java
@@ -306,6 +306,8 @@ abstract class OboeAudioStream extends AudioStreamBase {
public static native void setCallbackReturnStop(boolean b);
+ public static native void setHangTimeMillis(int hangTimeMillis);
+
public static native void setUseCallback(boolean checked);
public static native void setCallbackSize(int callbackSize);
diff --git a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/TestAudioActivity.java b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/TestAudioActivity.java
index 96ed24a0..680c5e8b 100644
--- a/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/TestAudioActivity.java
+++ b/apps/OboeTester/app/src/main/java/com/mobileer/oboetester/TestAudioActivity.java
@@ -31,13 +31,17 @@ import android.os.Looper;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
+import android.widget.AdapterView;
import android.widget.Button;
import android.widget.CheckBox;
+import android.widget.Spinner;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
+import com.mobileer.audio_device.CommunicationDeviceSpinner;
+
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -90,6 +94,8 @@ abstract class TestAudioActivity extends Activity {
private Button mCloseButton;
private MyStreamSniffer mStreamSniffer;
private CheckBox mCallbackReturnStopBox;
+ private Spinner mHangTimeSpinner;
+
// Only set in some activities
protected CommunicationDeviceView mCommunicationDeviceView;
private int mSampleRate;
@@ -436,6 +442,24 @@ abstract class TestAudioActivity extends Activity {
}
OboeAudioStream.setCallbackReturnStop(false);
+ mHangTimeSpinner = (Spinner) findViewById(R.id.spinner_hang_time);
+ if (mHangTimeSpinner != null) {
+ mHangTimeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+ String hangTimeText = (String) mHangTimeSpinner.getAdapter().getItem(position);
+ int hangTimeMillis = Integer.parseInt(hangTimeText);
+ Log.d(TAG, "Hang Time = " + hangTimeMillis + " msec");
+
+ OboeAudioStream.setHangTimeMillis(hangTimeMillis);
+ }
+
+ public void onNothingSelected(AdapterView<?> parent) {
+ OboeAudioStream.setHangTimeMillis(0);
+ }
+ });
+ }
+ OboeAudioStream.setHangTimeMillis(0);
+
mStreamSniffer = new MyStreamSniffer();
}
@@ -486,8 +510,16 @@ abstract class TestAudioActivity extends Activity {
}
}
+ void clearHangTime() {
+ OboeAudioStream.setHangTimeMillis(0);
+ if (mHangTimeSpinner != null) {
+ mHangTimeSpinner.setSelection(0);
+ }
+ }
+
public void startAudio(View view) {
Log.i(TAG, "startAudio() called =======================================");
+ clearHangTime(); // start running
try {
startAudio();
} catch (Exception e) {
diff --git a/apps/OboeTester/app/src/main/res/layout/merge_audio_common.xml b/apps/OboeTester/app/src/main/res/layout/merge_audio_common.xml
index 9e8fe6cc..a34d40c4 100644
--- a/apps/OboeTester/app/src/main/res/layout/merge_audio_common.xml
+++ b/apps/OboeTester/app/src/main/res/layout/merge_audio_common.xml
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent" android:layout_height="match_parent">
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
<com.mobileer.oboetester.StreamConfigurationView
android:id="@+id/streamConfiguration"
@@ -31,75 +32,91 @@
<Button
android:id="@+id/button_open"
android:layout_width="0dp"
- android:layout_weight="1"
android:layout_height="wrap_content"
+ android:layout_weight="1"
android:backgroundTint="@xml/button_color_selector"
android:backgroundTintMode="src_atop"
- android:textSize="12sp"
android:onClick="openAudio"
- android:text="@string/openAudio" />
+ android:text="@string/openAudio"
+ android:textSize="12sp" />
<Button
android:id="@+id/button_start"
android:layout_width="0dp"
- android:layout_weight="1"
android:layout_height="wrap_content"
+ android:layout_weight="1"
android:backgroundTint="@xml/button_color_selector"
android:backgroundTintMode="src_atop"
- android:textSize="12sp"
android:onClick="startAudio"
- android:text="@string/startAudio" />
+ android:text="@string/startAudio"
+ android:textSize="12sp" />
<Button
android:id="@+id/button_pause"
android:layout_width="0dp"
- android:layout_weight="1"
android:layout_height="wrap_content"
+ android:layout_weight="1"
android:backgroundTint="@xml/button_color_selector"
android:backgroundTintMode="src_atop"
- android:textSize="12sp"
android:onClick="pauseAudio"
- android:text="@string/pauseAudio" />
+ android:text="@string/pauseAudio"
+ android:textSize="12sp" />
<Button
android:id="@+id/button_stop"
android:layout_width="0dp"
- android:layout_weight="1"
android:layout_height="wrap_content"
+ android:layout_weight="1"
android:backgroundTint="@xml/button_color_selector"
android:backgroundTintMode="src_atop"
- android:textSize="12sp"
android:onClick="stopAudio"
- android:text="@string/stopAudio" />
+ android:text="@string/stopAudio"
+ android:textSize="12sp" />
<Button
android:id="@+id/button_release"
android:layout_width="0dp"
- android:layout_weight="1"
android:layout_height="wrap_content"
+ android:layout_weight="1"
android:backgroundTint="@xml/button_color_selector"
android:backgroundTintMode="src_atop"
- android:textSize="12sp"
android:onClick="releaseAudio"
- android:text="@string/releaseAudio" />
+ android:text="@string/releaseAudio"
+ android:textSize="12sp" />
<Button
android:id="@+id/button_close"
android:layout_width="0dp"
- android:layout_weight="1"
android:layout_height="wrap_content"
+ android:layout_weight="1"
android:backgroundTint="@xml/button_color_selector"
android:backgroundTintMode="src_atop"
- android:textSize="12sp"
android:onClick="closeAudio"
- android:text="@string/closeAudio" />
-
+ android:text="@string/closeAudio"
+ android:textSize="12sp" />
</LinearLayout>
- <CheckBox
- android:id="@+id/callbackReturnStop"
- android:layout_width="wrap_content"
+ <LinearLayout
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="callback returns STOP" />
+ android:orientation="horizontal">
+
+ <CheckBox
+ android:id="@+id/callbackReturnStop"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="callback returns STOP" />
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/hang_prompt" />
+
+ <Spinner
+ android:id="@+id/spinner_hang_time"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:entries="@array/hang_times" />
+
+ </LinearLayout>
</merge>
diff --git a/apps/OboeTester/app/src/main/res/values/strings.xml b/apps/OboeTester/app/src/main/res/values/strings.xml
index ddfc689b..00872151 100644
--- a/apps/OboeTester/app/src/main/res/values/strings.xml
+++ b/apps/OboeTester/app/src/main/res/values/strings.xml
@@ -186,6 +186,20 @@
<item>White Noise</item>
</string-array>
+ <string name="hang_prompt">, Hang(ms)</string>
+ <string-array name="hang_times">
+ <item>0</item>
+ <item>4</item>
+ <item>10</item>
+ <item>20</item>
+ <item>30</item>
+ <item>100</item>
+ <item>300</item>
+ <item>1000</item>
+ <item>2000</item>
+ <item>5000</item>
+ </string-array>
+
<string name="synth_sender_text">Select Sender for Synth</string>
<string name="error_port_busy">Selected port is in use or unavailable.</string>
<string name="port_open_ok">Port opened OK.</string>