android: run all audio and bluetooth operation on a dedicated thread

This commit is contained in:
Saúl Ibarra Corretgé 2018-07-26 15:37:50 +02:00 committed by Paweł Domas
parent 92001f4d37
commit 243dd16285
2 changed files with 21 additions and 20 deletions

View File

@ -25,8 +25,6 @@ import android.content.pm.PackageManager;
import android.media.AudioDeviceInfo; import android.media.AudioDeviceInfo;
import android.media.AudioManager; import android.media.AudioManager;
import android.os.Build; import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.util.Log; import android.util.Log;
import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.Arguments;
@ -41,6 +39,8 @@ import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/** /**
* Module implementing a simple API to select the appropriate audio device for a * Module implementing a simple API to select the appropriate audio device for a
@ -118,10 +118,11 @@ class AudioModeModule
private BluetoothHeadsetMonitor bluetoothHeadsetMonitor; private BluetoothHeadsetMonitor bluetoothHeadsetMonitor;
/** /**
* {@link Handler} for running all operations on the main thread. * {@link ExecutorService} for running all audio operations on a dedicated
* thread.
*/ */
private final Handler mainThreadHandler private static final ExecutorService executor
= new Handler(Looper.getMainLooper()); = Executors.newSingleThreadExecutor();
/** /**
* {@link Runnable} for running audio device detection the main thread. * {@link Runnable} for running audio device detection the main thread.
@ -228,7 +229,7 @@ class AudioModeModule
// Do an initial detection on Android >= M. // Do an initial detection on Android >= M.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mainThreadHandler.post(onAudioDeviceChangeRunner); runInAudioThread(onAudioDeviceChangeRunner);
} else { } else {
// On Android < M, detect if we have an earpiece. // On Android < M, detect if we have an earpiece.
PackageManager pm = reactContext.getPackageManager(); PackageManager pm = reactContext.getPackageManager();
@ -268,7 +269,7 @@ class AudioModeModule
*/ */
@ReactMethod @ReactMethod
public void getAudioDevices(final Promise promise) { public void getAudioDevices(final Promise promise) {
mainThreadHandler.post(new Runnable() { runInAudioThread(new Runnable() {
@Override @Override
public void run() { public void run() {
WritableMap map = Arguments.createMap(); WritableMap map = Arguments.createMap();
@ -305,7 +306,7 @@ class AudioModeModule
* Only used on Android >= M. * Only used on Android >= M.
*/ */
void onAudioDeviceChange() { void onAudioDeviceChange() {
mainThreadHandler.post(onAudioDeviceChangeRunner); runInAudioThread(onAudioDeviceChangeRunner);
} }
/** /**
@ -333,7 +334,7 @@ class AudioModeModule
* Only used on Android < M. * Only used on Android < M.
*/ */
void onHeadsetDeviceChange() { void onHeadsetDeviceChange() {
mainThreadHandler.post(new Runnable() { runInAudioThread(new Runnable() {
@Override @Override
public void run() { public void run() {
// XXX: isWiredHeadsetOn is not deprecated when used just for // XXX: isWiredHeadsetOn is not deprecated when used just for
@ -383,6 +384,14 @@ class AudioModeModule
} }
} }
/**
* Helper function to run operations on a dedicated thread.
* @param runnable
*/
public void runInAudioThread(Runnable runnable) {
executor.execute(runnable);
}
/** /**
* Sets the user selected audio device as the active audio device. * Sets the user selected audio device as the active audio device.
* *
@ -390,7 +399,7 @@ class AudioModeModule
*/ */
@ReactMethod @ReactMethod
public void setAudioDevice(final String device) { public void setAudioDevice(final String device) {
mainThreadHandler.post(new Runnable() { runInAudioThread(new Runnable() {
@Override @Override
public void run() { public void run() {
if (!availableDevices.contains(device)) { if (!availableDevices.contains(device)) {
@ -461,7 +470,7 @@ class AudioModeModule
} }
} }
}; };
mainThreadHandler.post(r); runInAudioThread(r);
} }
/** /**

View File

@ -24,8 +24,6 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.media.AudioManager; import android.media.AudioManager;
import android.os.Handler;
import android.os.Looper;
import android.util.Log; import android.util.Log;
/** /**
@ -55,12 +53,6 @@ class BluetoothHeadsetMonitor {
*/ */
private boolean headsetAvailable = false; private boolean headsetAvailable = false;
/**
* {@link Handler} for running all operations on the main thread.
*/
private final Handler mainThreadHandler
= new Handler(Looper.getMainLooper());
/** /**
* Helper for running Bluetooth operations on the main thread. * Helper for running Bluetooth operations on the main thread.
*/ */
@ -200,6 +192,6 @@ class BluetoothHeadsetMonitor {
* {@link AudioModeModule#onAudioDeviceChange()} callback. * {@link AudioModeModule#onAudioDeviceChange()} callback.
*/ */
private void updateDevices() { private void updateDevices() {
mainThreadHandler.post(updateDevicesRunnable); audioModeModule.runInAudioThread(updateDevicesRunnable);
} }
} }