aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhil Burk <philburk@mobileer.com>2022-12-07 17:53:03 -0800
committerGitHub <noreply@github.com>2022-12-07 17:53:03 -0800
commit2ecb5ff430f5b1bd01536a138222fa8e86f00049 (patch)
treea35f82bf7e6a04645f24ffc945c24d4856e4db30
parent55f9db2f0ea5647f1abe7dcddf4b8c78f21b5fd4 (diff)
downloadoboe-2ecb5ff430f5b1bd01536a138222fa8e86f00049.tar.gz
Add BackgroundRunner to HelloOboe (#1669)
If AudioServer has crashed it can cause the UI thread to time out. So call audio in background thread to prevent ANRs. Use a HandlerThread to implement a message queue. Fixes #960 Fixes #1538
-rw-r--r--samples/hello-oboe/src/main/cpp/HelloOboeEngine.cpp46
-rw-r--r--samples/hello-oboe/src/main/cpp/HelloOboeEngine.h20
-rw-r--r--samples/hello-oboe/src/main/cpp/jni_bridge.cpp161
-rw-r--r--samples/hello-oboe/src/main/java/com/google/oboe/samples/hellooboe/BackgroundRunner.java56
-rw-r--r--samples/hello-oboe/src/main/java/com/google/oboe/samples/hellooboe/MainActivity.java107
-rw-r--r--samples/hello-oboe/src/main/java/com/google/oboe/samples/hellooboe/PlaybackEngine.java93
-rw-r--r--samples/shared/DefaultDataCallback.h1
7 files changed, 203 insertions, 281 deletions
diff --git a/samples/hello-oboe/src/main/cpp/HelloOboeEngine.cpp b/samples/hello-oboe/src/main/cpp/HelloOboeEngine.cpp
index 13a50a1a..c27d5a41 100644
--- a/samples/hello-oboe/src/main/cpp/HelloOboeEngine.cpp
+++ b/samples/hello-oboe/src/main/cpp/HelloOboeEngine.cpp
@@ -68,30 +68,6 @@ void HelloOboeEngine::setBufferSizeInBursts(int32_t numBursts) {
}
}
-void HelloOboeEngine::setAudioApi(oboe::AudioApi audioApi) {
- if (mAudioApi != audioApi) {
- mAudioApi = audioApi;
- reopenStream();
- }
-}
-
-void HelloOboeEngine::setChannelCount(int channelCount) {
- if (mChannelCount != channelCount) {
- mChannelCount = channelCount;
- reopenStream();
- }
-}
-
-void HelloOboeEngine::setDeviceId(int32_t deviceId) {
- if (mDeviceId != deviceId) {
- mDeviceId = deviceId;
- if (reopenStream() != oboe::Result::OK) {
- LOGW("Open stream failed, forcing deviceId to Unspecified");
- mDeviceId = oboe::Unspecified;
- }
- }
-}
-
bool HelloOboeEngine::isLatencyDetectionSupported() {
return mIsLatencyDetectionSupported;
}
@@ -130,6 +106,13 @@ void HelloOboeEngine::restart() {
start();
}
+oboe::Result HelloOboeEngine::start(oboe::AudioApi audioApi, int deviceId, int channelCount) {
+ mAudioApi = audioApi;
+ mDeviceId = deviceId;
+ mChannelCount = channelCount;
+ return start();
+}
+
oboe::Result HelloOboeEngine::start() {
std::lock_guard<std::mutex> lock(mLock);
oboe::Result result = oboe::Result::OK;
@@ -143,15 +126,16 @@ oboe::Result HelloOboeEngine::start() {
}
mIsLatencyDetectionSupported = false;
result = openPlaybackStream();
- if (result == oboe::Result::OK){
- mAudioSource = std::make_shared<SoundGenerator>(mStream->getSampleRate(),
- mStream->getChannelCount());
- mLatencyCallback->setSource(std::dynamic_pointer_cast<IRenderableAudio>(mAudioSource));
+ if (result == oboe::Result::OK) {
+ mAudioSource = std::make_shared<SoundGenerator>(mStream->getSampleRate(),
+ mStream->getChannelCount());
+ mLatencyCallback->setSource(
+ std::dynamic_pointer_cast<IRenderableAudio>(mAudioSource));
LOGD("Stream opened: AudioAPI = %d, channelCount = %d, deviceID = %d",
- mStream->getAudioApi(),
- mStream->getChannelCount(),
- mStream->getDeviceId());
+ mStream->getAudioApi(),
+ mStream->getChannelCount(),
+ mStream->getDeviceId());
result = mStream->requestStart();
if (result != oboe::Result::OK) {
diff --git a/samples/hello-oboe/src/main/cpp/HelloOboeEngine.h b/samples/hello-oboe/src/main/cpp/HelloOboeEngine.h
index 1b255816..ea535b15 100644
--- a/samples/hello-oboe/src/main/cpp/HelloOboeEngine.h
+++ b/samples/hello-oboe/src/main/cpp/HelloOboeEngine.h
@@ -37,8 +37,12 @@ public:
/**
* Open and start a stream.
+ * @param deviceId the audio device id, can be obtained through an {@link AudioDeviceInfo} object
+ * using Java/JNI.
* @return error or OK
*/
+ oboe::Result start(oboe::AudioApi audioApi, int deviceId, int channelCount);
+ /* Start using current settings. */
oboe::Result start();
/**
@@ -49,22 +53,6 @@ public:
// From IRestartable
void restart() override;
- // These methods reset the underlying stream with new properties
-
- /**
- * Set the audio device which should be used for playback. Can be set to oboe::kUnspecified if
- * you want to use the default playback device (which is usually the built-in speaker if
- * no other audio devices, such as headphones, are attached).
- *
- * @param deviceId the audio device id, can be obtained through an {@link AudioDeviceInfo} object
- * using Java/JNI.
- */
- void setDeviceId(int32_t deviceId);
-
- void setChannelCount(int channelCount);
-
- void setAudioApi(oboe::AudioApi audioApi);
-
void setBufferSizeInBursts(int32_t numBursts);
/**
diff --git a/samples/hello-oboe/src/main/cpp/jni_bridge.cpp b/samples/hello-oboe/src/main/cpp/jni_bridge.cpp
index 3df32160..8d049c5a 100644
--- a/samples/hello-oboe/src/main/cpp/jni_bridge.cpp
+++ b/samples/hello-oboe/src/main/cpp/jni_bridge.cpp
@@ -20,181 +20,68 @@
#include "logging_macros.h"
extern "C" {
-
-/**
- * Creates the audio engine
- *
- * @return a pointer to the audio engine. This should be passed to other methods
- */
-JNIEXPORT jlong JNICALL
-Java_com_google_oboe_samples_hellooboe_PlaybackEngine_native_1createEngine(
- JNIEnv *env,
- jclass /*unused*/) {
-
- // We use std::nothrow so `new` returns a nullptr if the engine creation fails
- HelloOboeEngine *engine = new(std::nothrow) HelloOboeEngine();
- if (engine == nullptr) {
- LOGE("Could not instantiate HelloOboeEngine");
- return 0;
- }
- return reinterpret_cast<jlong>(engine);
-}
+/* We only need one HelloOboeEngine and it is needed for the entire time.
+ * So just allocate one statically. */
+static HelloOboeEngine sEngine;
JNIEXPORT jint JNICALL
-Java_com_google_oboe_samples_hellooboe_PlaybackEngine_native_1startEngine(
+Java_com_google_oboe_samples_hellooboe_PlaybackEngine_startEngine(
JNIEnv *env,
jclass,
- jlong engineHandle) {
-
- HelloOboeEngine *engine = reinterpret_cast<HelloOboeEngine *>(engineHandle);
- return static_cast<jint>(engine->start());
+ int audioApi, int deviceId, int channelCount) {
+ return static_cast<jint>(sEngine.start((oboe::AudioApi)audioApi, deviceId, channelCount));
}
JNIEXPORT jint JNICALL
-Java_com_google_oboe_samples_hellooboe_PlaybackEngine_native_1stopEngine(
+Java_com_google_oboe_samples_hellooboe_PlaybackEngine_stopEngine(
JNIEnv *env,
- jclass,
- jlong engineHandle) {
-
- HelloOboeEngine *engine = reinterpret_cast<HelloOboeEngine *>(engineHandle);
- return static_cast<jint>(engine->stop());
+ jclass) {
+ return static_cast<jint>(sEngine.stop());
}
JNIEXPORT void JNICALL
-Java_com_google_oboe_samples_hellooboe_PlaybackEngine_native_1deleteEngine(
+Java_com_google_oboe_samples_hellooboe_PlaybackEngine_setToneOn(
JNIEnv *env,
jclass,
- jlong engineHandle) {
-
- HelloOboeEngine *engine = reinterpret_cast<HelloOboeEngine *>(engineHandle);
- engine->stop();
- delete engine;
-}
-
-JNIEXPORT void JNICALL
-Java_com_google_oboe_samples_hellooboe_PlaybackEngine_native_1setToneOn(
- JNIEnv *env,
- jclass,
- jlong engineHandle,
jboolean isToneOn) {
- HelloOboeEngine *engine = reinterpret_cast<HelloOboeEngine *>(engineHandle);
- if (engine == nullptr) {
- LOGE("Engine handle is invalid, call createHandle() to create a new one");
- return;
- }
- engine->tap(isToneOn);
-}
-
-JNIEXPORT void JNICALL
-Java_com_google_oboe_samples_hellooboe_PlaybackEngine_native_1setAudioApi(
- JNIEnv *env,
- jclass type,
- jlong engineHandle,
- jint audioApi) {
-
- HelloOboeEngine *engine = reinterpret_cast<HelloOboeEngine*>(engineHandle);
- if (engine == nullptr) {
- LOGE("Engine handle is invalid, call createHandle() to create a new one");
- return;
- }
-
- oboe::AudioApi api = static_cast<oboe::AudioApi>(audioApi);
- engine->setAudioApi(api);
+ sEngine.tap(isToneOn);
}
-JNIEXPORT void JNICALL
-Java_com_google_oboe_samples_hellooboe_PlaybackEngine_native_1setAudioDeviceId(
- JNIEnv *env,
- jclass,
- jlong engineHandle,
- jint deviceId) {
-
- HelloOboeEngine *engine = reinterpret_cast<HelloOboeEngine*>(engineHandle);
- if (engine == nullptr) {
- LOGE("Engine handle is invalid, call createHandle() to create a new one");
- return;
- }
- engine->setDeviceId(deviceId);
-}
JNIEXPORT void JNICALL
-Java_com_google_oboe_samples_hellooboe_PlaybackEngine_native_1setChannelCount(
- JNIEnv *env,
- jclass type,
- jlong engineHandle,
- jint channelCount) {
-
- HelloOboeEngine *engine = reinterpret_cast<HelloOboeEngine*>(engineHandle);
- if (engine == nullptr) {
- LOGE("Engine handle is invalid, call createHandle() to create a new one");
- return;
- }
- engine->setChannelCount(channelCount);
-}
-
-JNIEXPORT void JNICALL
-Java_com_google_oboe_samples_hellooboe_PlaybackEngine_native_1setBufferSizeInBursts(
+Java_com_google_oboe_samples_hellooboe_PlaybackEngine_setBufferSizeInBursts(
JNIEnv *env,
jclass,
- jlong engineHandle,
jint bufferSizeInBursts) {
-
- HelloOboeEngine *engine = reinterpret_cast<HelloOboeEngine*>(engineHandle);
- if (engine == nullptr) {
- LOGE("Engine handle is invalid, call createHandle() to create a new one");
- return;
- }
- engine->setBufferSizeInBursts(bufferSizeInBursts);
+ sEngine.setBufferSizeInBursts(bufferSizeInBursts);
}
-
JNIEXPORT jdouble JNICALL
-Java_com_google_oboe_samples_hellooboe_PlaybackEngine_native_1getCurrentOutputLatencyMillis(
+Java_com_google_oboe_samples_hellooboe_PlaybackEngine_getCurrentOutputLatencyMillis(
JNIEnv *env,
- jclass,
- jlong engineHandle) {
-
- HelloOboeEngine *engine = reinterpret_cast<HelloOboeEngine*>(engineHandle);
- if (engine == nullptr) {
- LOGE("Engine is null, you must call createEngine before calling this method");
- return static_cast<jdouble>(-1.0);
- }
- return static_cast<jdouble>(engine->getCurrentOutputLatencyMillis());
+ jclass) {
+ return static_cast<jdouble>(sEngine.getCurrentOutputLatencyMillis());
}
JNIEXPORT jboolean JNICALL
-Java_com_google_oboe_samples_hellooboe_PlaybackEngine_native_1isLatencyDetectionSupported(
+Java_com_google_oboe_samples_hellooboe_PlaybackEngine_isLatencyDetectionSupported(
JNIEnv *env,
- jclass type,
- jlong engineHandle) {
-
- HelloOboeEngine *engine = reinterpret_cast<HelloOboeEngine*>(engineHandle);
- if (engine == nullptr) {
- LOGE("Engine is null, you must call createEngine before calling this method");
- return JNI_FALSE;
- }
- return (engine->isLatencyDetectionSupported() ? JNI_TRUE : JNI_FALSE);
+ jclass) {
+ return (sEngine.isLatencyDetectionSupported() ? JNI_TRUE : JNI_FALSE);
}
JNIEXPORT jboolean JNICALL
-Java_com_google_oboe_samples_hellooboe_PlaybackEngine_native_1isAAudioRecommended(
+Java_com_google_oboe_samples_hellooboe_PlaybackEngine_isAAudioRecommended(
JNIEnv *env,
- jclass type,
- jlong engineHandle) {
-
- HelloOboeEngine *engine = reinterpret_cast<HelloOboeEngine*>(engineHandle);
- if (engine == nullptr) {
- LOGE("Engine is null, you must call createEngine before calling this method");
- return JNI_FALSE;
- }
- return (engine->isAAudioRecommended() ? JNI_TRUE : JNI_FALSE);
+ jclass) {
+ return (sEngine.isAAudioRecommended() ? JNI_TRUE : JNI_FALSE);
}
JNIEXPORT void JNICALL
-Java_com_google_oboe_samples_hellooboe_PlaybackEngine_native_1setDefaultStreamValues(
+Java_com_google_oboe_samples_hellooboe_PlaybackEngine_setDefaultStreamValues(
JNIEnv *env,
- jclass type,
+ jclass,
jint sampleRate,
jint framesPerBurst) {
oboe::DefaultStreamValues::SampleRate = (int32_t) sampleRate;
diff --git a/samples/hello-oboe/src/main/java/com/google/oboe/samples/hellooboe/BackgroundRunner.java b/samples/hello-oboe/src/main/java/com/google/oboe/samples/hellooboe/BackgroundRunner.java
new file mode 100644
index 00000000..29e15303
--- /dev/null
+++ b/samples/hello-oboe/src/main/java/com/google/oboe/samples/hellooboe/BackgroundRunner.java
@@ -0,0 +1,56 @@
+package com.google.oboe.samples.hellooboe;
+
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Message;
+
+/** Run Audio function in a background thread.
+ * This will avoid ANRs that can occur if the AudioServer or HAL crashes
+ * and takes a long time to recover.
+ *
+ * This thread will run for the lifetime of the app so only make one BackgroundRunner
+ * and reuse it.
+ */
+public abstract class BackgroundRunner {
+ private Handler mHandler;
+ private HandlerThread mThread = new HandlerThread("BackgroundRunner");
+
+ public BackgroundRunner() {
+ mThread.start();
+ mHandler = new Handler(mThread.getLooper()) {
+ public void handleMessage(Message message) {
+ super.handleMessage(message);
+ handleMessageInBackground(message);
+ }
+ };
+ }
+
+ /**
+ * @param message
+ * @return true if the message was successfully queued
+ */
+ public boolean sendMessage(Message message) {
+ return mHandler.sendMessage(message);
+ }
+
+ /**
+ * @param what command code for background operation
+ * @param arg1 optional argument
+ * @return true if the message was successfully queued
+ */
+ public boolean sendMessage(int what, int arg1) {
+ Message message = mHandler.obtainMessage();
+ message.what = what;
+ message.arg1 = arg1;
+ return sendMessage(message);
+ }
+
+ public boolean sendMessage(int what) {
+ return sendMessage(what, 0);
+ }
+
+ /**
+ * Implement this in your app.
+ */
+ abstract void handleMessageInBackground(Message message);
+}
diff --git a/samples/hello-oboe/src/main/java/com/google/oboe/samples/hellooboe/MainActivity.java b/samples/hello-oboe/src/main/java/com/google/oboe/samples/hellooboe/MainActivity.java
index 4c203e9b..526d1c84 100644
--- a/samples/hello-oboe/src/main/java/com/google/oboe/samples/hellooboe/MainActivity.java
+++ b/samples/hello-oboe/src/main/java/com/google/oboe/samples/hellooboe/MainActivity.java
@@ -25,6 +25,8 @@ import android.os.Bundle;
import androidx.annotation.RequiresApi;
+import android.os.Message;
+import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.AdapterView;
@@ -46,7 +48,7 @@ import java.util.Timer;
import java.util.TimerTask;
public class MainActivity extends Activity {
- private static final String TAG = MainActivity.class.getName();
+ private static final String TAG = "HelloOboe";
private static final long UPDATE_LATENCY_EVERY_MILLIS = 1000;
private static final Integer[] CHANNEL_COUNT_OPTIONS = {1, 2, 3, 4, 5, 6, 7, 8};
// Default to Stereo (OPTIONS is zero-based array so index 1 = 2 channels)
@@ -65,6 +67,67 @@ public class MainActivity extends Activity {
private Timer mLatencyUpdater;
private boolean mScoStarted = false;
+ /** Commands for background thread. */
+ private static final int WHAT_START = 100;
+ private static final int WHAT_STOP = 101;
+ private static final int WHAT_SET_DEVICE_ID = 102;
+ private static final int WHAT_SET_AUDIO_API = 103;
+ private static final int WHAT_SET_CHANNEL_COUNT = 104;
+ private BackgroundRunner mRunner = new MyBackgroundRunner();
+
+ private class MyBackgroundRunner extends BackgroundRunner {
+ // These are initialized to zero by Java.
+ // Zero matches the oboe::Unspecified value.
+ int audioApi;
+ int deviceId;
+ int channelCount;
+
+ @Override
+ /* Execute this in a background thread to avoid ANRs. */
+ void handleMessageInBackground(Message message) {
+ int what = message.what;
+ int arg1 = message.arg1;
+ Log.i(MainActivity.TAG, "got background message, what = " + what + ", arg1 = " + arg1);
+ int result = 0;
+ boolean restart = false;
+ switch (what) {
+ case WHAT_START:
+ result = PlaybackEngine.startEngine(audioApi, deviceId, channelCount);
+ break;
+ case WHAT_STOP:
+ result = PlaybackEngine.stopEngine();
+ break;
+ case WHAT_SET_AUDIO_API:
+ if (audioApi != arg1) {
+ audioApi = arg1;
+ restart = true;
+ }
+ break;
+ case WHAT_SET_DEVICE_ID:
+ if (deviceId != arg1) {
+ deviceId = arg1;
+ restart = true;
+ }
+ break;
+ case WHAT_SET_CHANNEL_COUNT:
+ if (channelCount != arg1) {
+ channelCount = arg1;
+ restart = true;
+ }
+ break;
+ }
+ if (restart) {
+ int result1 = PlaybackEngine.stopEngine();
+ int result2 = PlaybackEngine.startEngine(audioApi, deviceId, channelCount);
+ result = (result2 != 0) ? result2 : result1;
+ }
+ if (result != 0) {
+ Log.e(TAG, "audio error " + result);
+ showToast("Error in audio =" + result);
+ }
+ }
+ }
+
/*
* Hook to user control to start / stop audio playback:
* touch-down: start, and keeps on playing
@@ -94,6 +157,7 @@ public class MainActivity extends Activity {
setupChannelCountSpinner();
setupBufferSizeSpinner();
}
+
/*
* Creating engine in onResume() and destroying in onPause() so the stream retains exclusive
* mode only while in focus. This allows other apps to reclaim exclusive stream mode.
@@ -101,7 +165,7 @@ public class MainActivity extends Activity {
@Override
protected void onResume() {
super.onResume();
- PlaybackEngine.create(this);
+ PlaybackEngine.setDefaultStreamValues(this);
setupLatencyUpdater();
// Return the spinner states to their default value
@@ -115,19 +179,13 @@ public class MainActivity extends Activity {
mAudioApiSpinner.setEnabled(false);
}
- int result = PlaybackEngine.start();
- if (result != 0) {
- showToast("Error opening stream = " + result);
- }
+ startAudioAsync();
}
@Override
protected void onPause() {
if (mLatencyUpdater != null) mLatencyUpdater.cancel();
- int result = PlaybackEngine.stop();
- if (result != 0) {
- showToast("Error stopping stream = " + result);
- }
+ stopAudioAsync();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
clearCommunicationDevice();
@@ -137,8 +195,6 @@ public class MainActivity extends Activity {
mScoStarted = false;
}
}
-
- PlaybackEngine.delete();
super.onPause();
}
@@ -152,7 +208,7 @@ public class MainActivity extends Activity {
mChannelCountSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
- PlaybackEngine.setChannelCount(CHANNEL_COUNT_OPTIONS[mChannelCountSpinner.getSelectedItemPosition()]);
+ setChannelCountAsync(CHANNEL_COUNT_OPTIONS[mChannelCountSpinner.getSelectedItemPosition()]);
}
@Override
@@ -209,7 +265,7 @@ public class MainActivity extends Activity {
mScoStarted = false;
}
}
- PlaybackEngine.setAudioDeviceId(getPlaybackDeviceId());
+ setAudioDeviceIdAsync(getPlaybackDeviceId());
}
@Override
@@ -234,7 +290,7 @@ public class MainActivity extends Activity {
mAudioApiSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
- PlaybackEngine.setAudioApi(i);
+ setAudioApiAsync(i);
if (i == OBOE_API_OPENSL_ES) {
mPlaybackDeviceSpinner.setSelection(SPINNER_DEFAULT_OPTION_INDEX);
mPlaybackDeviceSpinner.setEnabled(false);
@@ -376,4 +432,25 @@ public class MainActivity extends Activity {
AudioManager myAudioMgr = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
myAudioMgr.stopBluetoothSco();
}
+
+
+ void startAudioAsync() {
+ mRunner.sendMessage(WHAT_START);
+ }
+
+ void stopAudioAsync() {
+ mRunner.sendMessage(WHAT_STOP);
+ }
+
+ void setAudioApiAsync(int audioApi){
+ mRunner.sendMessage(WHAT_SET_AUDIO_API, audioApi);
+ }
+
+ void setAudioDeviceIdAsync(int deviceId){
+ mRunner.sendMessage(WHAT_SET_DEVICE_ID, deviceId);
+ }
+
+ void setChannelCountAsync(int channelCount) {
+ mRunner.sendMessage(WHAT_SET_CHANNEL_COUNT, channelCount);
+ }
}
diff --git a/samples/hello-oboe/src/main/java/com/google/oboe/samples/hellooboe/PlaybackEngine.java b/samples/hello-oboe/src/main/java/com/google/oboe/samples/hellooboe/PlaybackEngine.java
index fb07a1c7..d5efba4d 100644
--- a/samples/hello-oboe/src/main/java/com/google/oboe/samples/hellooboe/PlaybackEngine.java
+++ b/samples/hello-oboe/src/main/java/com/google/oboe/samples/hellooboe/PlaybackEngine.java
@@ -20,23 +20,12 @@ import android.media.AudioManager;
import android.os.Build;
public class PlaybackEngine {
-
- static long mEngineHandle = 0;
-
// Load native library
static {
System.loadLibrary("hello-oboe");
}
- static boolean create(Context context){
- if (mEngineHandle == 0){
- setDefaultStreamValues(context);
- mEngineHandle = native_createEngine();
- }
- return (mEngineHandle != 0);
- }
-
- private static void setDefaultStreamValues(Context context) {
+ static void setDefaultStreamValues(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1){
AudioManager myAudioMgr = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
String sampleRateStr = myAudioMgr.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE);
@@ -44,78 +33,20 @@ public class PlaybackEngine {
String framesPerBurstStr = myAudioMgr.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER);
int defaultFramesPerBurst = Integer.parseInt(framesPerBurstStr);
- native_setDefaultStreamValues(defaultSampleRate, defaultFramesPerBurst);
- }
- }
-
- static int start() {
- if (mEngineHandle != 0) {
- return native_startEngine(mEngineHandle);
- } else {
- return -1;
- }
- }
-
- static int stop() {
- if (mEngineHandle != 0) {
- return native_stopEngine(mEngineHandle);
- } else {
- return -1;
- }
- }
-
- static void delete(){
- if (mEngineHandle != 0){
- native_deleteEngine(mEngineHandle);
+ setDefaultStreamValues(defaultSampleRate, defaultFramesPerBurst);
}
- mEngineHandle = 0;
}
- static void setToneOn(boolean isToneOn){
- if (mEngineHandle != 0) native_setToneOn(mEngineHandle, isToneOn);
- }
-
- static void setAudioApi(int audioApi){
- if (mEngineHandle != 0) native_setAudioApi(mEngineHandle, audioApi);
- }
-
- static void setAudioDeviceId(int deviceId){
- if (mEngineHandle != 0) native_setAudioDeviceId(mEngineHandle, deviceId);
- }
-
- static void setChannelCount(int channelCount) {
- if (mEngineHandle != 0) native_setChannelCount(mEngineHandle, channelCount);
- }
- static void setBufferSizeInBursts(int bufferSizeInBursts){
- if (mEngineHandle != 0) native_setBufferSizeInBursts(mEngineHandle, bufferSizeInBursts);
- }
-
- static double getCurrentOutputLatencyMillis(){
- if (mEngineHandle == 0) return 0;
- return native_getCurrentOutputLatencyMillis(mEngineHandle);
- }
-
- static boolean isLatencyDetectionSupported() {
- return mEngineHandle != 0 && native_isLatencyDetectionSupported(mEngineHandle);
- }
-
- static boolean isAAudioRecommended() {
- return mEngineHandle != 0 && native_isAAudioRecommended(mEngineHandle);
- }
+ // Native methods that require audioserver calls and might take several seconds.
+ static native int startEngine(int audioApi, int deviceId, int channelCount);
+ static native int stopEngine();
- // Native methods
- private static native long native_createEngine();
- private static native int native_startEngine(long engineHandle);
- private static native int native_stopEngine(long engineHandle);
- private static native void native_deleteEngine(long engineHandle);
- private static native void native_setToneOn(long engineHandle, boolean isToneOn);
- private static native void native_setAudioApi(long engineHandle, int audioApi);
- private static native void native_setAudioDeviceId(long engineHandle, int deviceId);
- private static native void native_setChannelCount(long mEngineHandle, int channelCount);
- private static native void native_setBufferSizeInBursts(long engineHandle, int bufferSizeInBursts);
- private static native double native_getCurrentOutputLatencyMillis(long engineHandle);
- private static native boolean native_isLatencyDetectionSupported(long engineHandle);
- private static native boolean native_isAAudioRecommended(long engineHandle);
- private static native void native_setDefaultStreamValues(int sampleRate, int framesPerBurst);
+ // Native methods that only talk to the native client code.
+ static native void setToneOn(boolean isToneOn);
+ static native void setBufferSizeInBursts(int bufferSizeInBursts);
+ static native double getCurrentOutputLatencyMillis();
+ static native boolean isLatencyDetectionSupported();
+ static native boolean isAAudioRecommended();
+ static native void setDefaultStreamValues(int sampleRate, int framesPerBurst);
}
diff --git a/samples/shared/DefaultDataCallback.h b/samples/shared/DefaultDataCallback.h
index e7f858e0..212d9760 100644
--- a/samples/shared/DefaultDataCallback.h
+++ b/samples/shared/DefaultDataCallback.h
@@ -17,7 +17,6 @@
#ifndef SAMPLES_DEFAULT_DATA_CALLBACK_H
#define SAMPLES_DEFAULT_DATA_CALLBACK_H
-
#include <vector>
#include <oboe/AudioStreamCallback.h>
#include <logging_macros.h>