diff options
author | Phil Burk <philburk@mobileer.com> | 2022-12-07 17:53:03 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-12-07 17:53:03 -0800 |
commit | 2ecb5ff430f5b1bd01536a138222fa8e86f00049 (patch) | |
tree | a35f82bf7e6a04645f24ffc945c24d4856e4db30 | |
parent | 55f9db2f0ea5647f1abe7dcddf4b8c78f21b5fd4 (diff) | |
download | oboe-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
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> |