Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //
- // Source code recreated from a .class file by IntelliJ IDEA
- // (powered by Fernflower decompiler)
- //
- package com.quickblox.videochat.webrtc;
- import android.annotation.SuppressLint;
- import android.bluetooth.BluetoothAdapter;
- import android.bluetooth.BluetoothDevice;
- import android.bluetooth.BluetoothHeadset;
- import android.bluetooth.BluetoothProfile;
- import android.bluetooth.BluetoothProfile.ServiceListener;
- import android.content.BroadcastReceiver;
- import android.content.Context;
- import android.content.Intent;
- import android.content.IntentFilter;
- import android.media.AudioManager;
- import android.os.Handler;
- import android.os.Looper;
- import android.os.Process;
- import com.quickblox.videochat.webrtc.util.Logger;
- import java.util.Iterator;
- import java.util.List;
- import java.util.Set;
- import org.webrtc.ThreadUtils;
- class AppRTCBluetoothManager {
- private static final String TAG = AppRTCBluetoothManager.class.getSimpleName();
- private static final Logger LOGGER;
- private static final int BLUETOOTH_SCO_TIMEOUT_MS = 4000;
- private static final int MAX_SCO_CONNECTION_ATTEMPTS = 2;
- private final Context apprtcContext;
- private final AppRTCAudioManager apprtcAudioManager;
- private final AudioManager audioManager;
- private final Handler handler;
- int scoConnectionAttempts;
- private AppRTCBluetoothManager.State bluetoothState;
- private final ServiceListener bluetoothServiceListener;
- private BluetoothAdapter bluetoothAdapter;
- private BluetoothHeadset bluetoothHeadset;
- private BluetoothDevice bluetoothDevice;
- private final BroadcastReceiver bluetoothHeadsetReceiver;
- private final Runnable bluetoothTimeoutRunnable = new Runnable() {
- public void run() {
- AppRTCBluetoothManager.this.bluetoothTimeout();
- }
- };
- static AppRTCBluetoothManager create(Context context, AppRTCAudioManager audioManager) {
- LOGGER.d(TAG, "create" + AppRTCUtils.getThreadInfo());
- return new AppRTCBluetoothManager(context, audioManager);
- }
- private AppRTCBluetoothManager(Context context, AppRTCAudioManager audioManager) {
- ThreadUtils.checkIsOnMainThread();
- this.apprtcContext = context;
- this.apprtcAudioManager = audioManager;
- this.audioManager = this.getAudioManager(context);
- this.bluetoothState = AppRTCBluetoothManager.State.UNINITIALIZED;
- this.bluetoothServiceListener = new AppRTCBluetoothManager.BluetoothServiceListener();
- this.bluetoothHeadsetReceiver = new AppRTCBluetoothManager.BluetoothHeadsetBroadcastReceiver();
- this.handler = new Handler(Looper.getMainLooper());
- }
- AppRTCBluetoothManager.State getState() {
- ThreadUtils.checkIsOnMainThread();
- return this.bluetoothState;
- }
- @SuppressLint({"MissingPermission"})
- void start() {
- ThreadUtils.checkIsOnMainThread();
- LOGGER.d(TAG, "start");
- if (!this.hasPermission(this.apprtcContext, "android.permission.BLUETOOTH")) {
- LOGGER.w(TAG, "Process (pid=" + Process.myPid() + ") lacks BLUETOOTH permission");
- } else if (this.bluetoothState != AppRTCBluetoothManager.State.UNINITIALIZED) {
- LOGGER.w(TAG, "Invalid BT state");
- } else {
- this.bluetoothHeadset = null;
- this.bluetoothDevice = null;
- this.scoConnectionAttempts = 0;
- this.bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
- if (this.bluetoothAdapter == null) {
- LOGGER.w(TAG, "Device does not support Bluetooth");
- } else if (!this.audioManager.isBluetoothScoAvailableOffCall()) {
- LOGGER.e(TAG, "Bluetooth SCO audio is not available off call");
- } else {
- this.logBluetoothAdapterInfo(this.bluetoothAdapter);
- if (!this.getBluetoothProfileProxy(this.apprtcContext, this.bluetoothServiceListener, 1)) {
- LOGGER.e(TAG, "BluetoothAdapter.getProfileProxy(HEADSET) failed");
- } else {
- IntentFilter bluetoothHeadsetFilter = new IntentFilter();
- bluetoothHeadsetFilter.addAction("android.bluetooth.headset.profile.action.CONNECTION_STATE_CHANGED");
- bluetoothHeadsetFilter.addAction("android.bluetooth.headset.profile.action.AUDIO_STATE_CHANGED");
- this.registerReceiver(this.bluetoothHeadsetReceiver, bluetoothHeadsetFilter);
- LOGGER.d(TAG, "HEADSET profile state: " + this.stateToString(this.bluetoothAdapter.getProfileConnectionState(1)));
- LOGGER.d(TAG, "Bluetooth proxy for headset profile has started");
- this.bluetoothState = AppRTCBluetoothManager.State.HEADSET_UNAVAILABLE;
- LOGGER.d(TAG, "start done: BT state=" + this.bluetoothState);
- }
- }
- }
- }
- void stop() {
- ThreadUtils.checkIsOnMainThread();
- LOGGER.d(TAG, "stop: BT state=" + this.bluetoothState);
- if (this.bluetoothAdapter != null) {
- this.stopScoAudio();
- if (this.bluetoothState != AppRTCBluetoothManager.State.UNINITIALIZED) {
- this.unregisterReceiver(this.bluetoothHeadsetReceiver);
- this.cancelTimer();
- if (this.bluetoothHeadset != null) {
- this.bluetoothAdapter.closeProfileProxy(1, this.bluetoothHeadset);
- this.bluetoothHeadset = null;
- }
- this.bluetoothAdapter = null;
- this.bluetoothDevice = null;
- this.bluetoothState = AppRTCBluetoothManager.State.UNINITIALIZED;
- LOGGER.d(TAG, "stop done: BT state=" + this.bluetoothState);
- }
- }
- }
- boolean startScoAudio() {
- ThreadUtils.checkIsOnMainThread();
- LOGGER.d(TAG, "startSco: BT state=" + this.bluetoothState + ", attempts: " + this.scoConnectionAttempts + ", SCO is on: " + this.isScoOn());
- if (this.scoConnectionAttempts >= 2) {
- LOGGER.e(TAG, "BT SCO connection fails - no more attempts");
- return false;
- } else if (this.bluetoothState != AppRTCBluetoothManager.State.HEADSET_AVAILABLE) {
- LOGGER.e(TAG, "BT SCO connection fails - no headset available");
- return false;
- } else {
- LOGGER.d(TAG, "Starting Bluetooth SCO and waits for ACTION_AUDIO_STATE_CHANGED...");
- this.bluetoothState = AppRTCBluetoothManager.State.SCO_CONNECTING;
- this.audioManager.startBluetoothSco();
- this.audioManager.setBluetoothScoOn(true);
- ++this.scoConnectionAttempts;
- this.startTimer();
- LOGGER.d(TAG, "startScoAudio done: BT state=" + this.bluetoothState + ", SCO is on: " + this.isScoOn());
- return true;
- }
- }
- void stopScoAudio() {
- ThreadUtils.checkIsOnMainThread();
- LOGGER.d(TAG, "stopScoAudio: BT state=" + this.bluetoothState + ", SCO is on: " + this.isScoOn());
- if (this.bluetoothState == AppRTCBluetoothManager.State.SCO_CONNECTING || this.bluetoothState == AppRTCBluetoothManager.State.SCO_CONNECTED) {
- this.cancelTimer();
- this.audioManager.stopBluetoothSco();
- this.audioManager.setBluetoothScoOn(false);
- this.bluetoothState = AppRTCBluetoothManager.State.SCO_DISCONNECTING;
- LOGGER.d(TAG, "stopScoAudio done: BT state=" + this.bluetoothState + ", SCO is on: " + this.isScoOn());
- }
- }
- @SuppressLint({"MissingPermission"})
- void updateDevice() {
- if (this.bluetoothState != AppRTCBluetoothManager.State.UNINITIALIZED && this.bluetoothHeadset != null) {
- LOGGER.d(TAG, "updateDevice");
- List<BluetoothDevice> devices = this.bluetoothHeadset.getConnectedDevices();
- if (devices.isEmpty()) {
- this.bluetoothDevice = null;
- this.bluetoothState = AppRTCBluetoothManager.State.HEADSET_UNAVAILABLE;
- LOGGER.d(TAG, "No connected bluetooth headset");
- } else {
- this.bluetoothDevice = (BluetoothDevice)devices.get(0);
- this.bluetoothState = AppRTCBluetoothManager.State.HEADSET_AVAILABLE;
- LOGGER.d(TAG, "Connected bluetooth headset: name=" + this.bluetoothDevice.getName() + ", state=" + this.stateToString(this.bluetoothHeadset.getConnectionState(this.bluetoothDevice)) + ", SCO audio=" + this.bluetoothHeadset.isAudioConnected(this.bluetoothDevice));
- }
- LOGGER.d(TAG, "updateDevice done: BT state=" + this.bluetoothState);
- }
- }
- private AudioManager getAudioManager(Context context) {
- return (AudioManager)context.getSystemService("audio");
- }
- private void registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
- this.apprtcContext.registerReceiver(receiver, filter);
- }
- private void unregisterReceiver(BroadcastReceiver receiver) {
- this.apprtcContext.unregisterReceiver(receiver);
- }
- private boolean getBluetoothProfileProxy(Context context, ServiceListener listener, int profile) {
- return this.bluetoothAdapter.getProfileProxy(context, listener, profile);
- }
- private boolean hasPermission(Context context, String permission) {
- return this.apprtcContext.checkPermission(permission, Process.myPid(), Process.myUid()) == 0;
- }
- @SuppressLint({"MissingPermission"})
- private void logBluetoothAdapterInfo(BluetoothAdapter localAdapter) {
- LOGGER.d(TAG, "BluetoothAdapter: enabled=" + localAdapter.isEnabled() + ", state=" + this.stateToString(localAdapter.getState()) + ", name=" + localAdapter.getName() + ", address=" + localAdapter.getAddress());
- Set<BluetoothDevice> pairedDevices = localAdapter.getBondedDevices();
- if (!pairedDevices.isEmpty()) {
- LOGGER.d(TAG, "paired devices:");
- Iterator var3 = pairedDevices.iterator();
- while(var3.hasNext()) {
- BluetoothDevice device = (BluetoothDevice)var3.next();
- LOGGER.d(TAG, " name=" + device.getName() + ", address=" + device.getAddress());
- }
- }
- }
- private void updateAudioDeviceState() {
- ThreadUtils.checkIsOnMainThread();
- LOGGER.d(TAG, "updateAudioDeviceState");
- this.apprtcAudioManager.updateAudioDeviceState();
- }
- private void startTimer() {
- ThreadUtils.checkIsOnMainThread();
- LOGGER.d(TAG, "startTimer");
- this.handler.postDelayed(this.bluetoothTimeoutRunnable, 4000L);
- }
- private void cancelTimer() {
- ThreadUtils.checkIsOnMainThread();
- LOGGER.d(TAG, "cancelTimer");
- this.handler.removeCallbacks(this.bluetoothTimeoutRunnable);
- }
- @SuppressLint({"MissingPermission"})
- private void bluetoothTimeout() {
- ThreadUtils.checkIsOnMainThread();
- if (this.bluetoothState != AppRTCBluetoothManager.State.UNINITIALIZED && this.bluetoothHeadset != null) {
- LOGGER.d(TAG, "bluetoothTimeout: BT state=" + this.bluetoothState + ", attempts: " + this.scoConnectionAttempts + ", SCO is on: " + this.isScoOn());
- if (this.bluetoothState == AppRTCBluetoothManager.State.SCO_CONNECTING) {
- boolean scoConnected = false;
- List<BluetoothDevice> devices = this.bluetoothHeadset.getConnectedDevices();
- if (devices.size() > 0) {
- this.bluetoothDevice = (BluetoothDevice)devices.get(0);
- if (this.bluetoothHeadset.isAudioConnected(this.bluetoothDevice)) {
- LOGGER.d(TAG, "SCO connected with " + this.bluetoothDevice.getName());
- scoConnected = true;
- } else {
- LOGGER.d(TAG, "SCO is not connected with " + this.bluetoothDevice.getName());
- }
- }
- if (scoConnected) {
- this.bluetoothState = AppRTCBluetoothManager.State.SCO_CONNECTED;
- this.scoConnectionAttempts = 0;
- } else {
- LOGGER.w(TAG, "BT failed to connect after timeout");
- this.stopScoAudio();
- }
- this.updateAudioDeviceState();
- LOGGER.d(TAG, "bluetoothTimeout done: BT state=" + this.bluetoothState);
- }
- }
- }
- private boolean isScoOn() {
- return this.audioManager.isBluetoothScoOn();
- }
- private String stateToString(int state) {
- switch(state) {
- case 0:
- return "DISCONNECTED";
- case 1:
- return "CONNECTING";
- case 2:
- return "CONNECTED";
- case 3:
- return "DISCONNECTING";
- case 4:
- case 5:
- case 6:
- case 7:
- case 8:
- case 9:
- default:
- return "INVALID";
- case 10:
- return "OFF";
- case 11:
- return "TURNING_ON";
- case 12:
- return "ON";
- case 13:
- return "TURNING_OFF";
- }
- }
- static {
- LOGGER = Logger.getInstance(BaseClient.TAG);
- }
- private class BluetoothHeadsetBroadcastReceiver extends BroadcastReceiver {
- private BluetoothHeadsetBroadcastReceiver() {
- }
- public void onReceive(Context context, Intent intent) {
- if (AppRTCBluetoothManager.this.bluetoothState != AppRTCBluetoothManager.State.UNINITIALIZED) {
- String action = intent.getAction();
- int state;
- if (action.equals("android.bluetooth.headset.profile.action.CONNECTION_STATE_CHANGED")) {
- state = intent.getIntExtra("android.bluetooth.profile.extra.STATE", 0);
- AppRTCBluetoothManager.LOGGER.d(AppRTCBluetoothManager.TAG, "BluetoothHeadsetBroadcastReceiver.onReceive: a=ACTION_CONNECTION_STATE_CHANGED, s=" + AppRTCBluetoothManager.this.stateToString(state) + ", sb=" + this.isInitialStickyBroadcast() + ", BT state: " + AppRTCBluetoothManager.this.bluetoothState);
- if (state == 2) {
- AppRTCBluetoothManager.this.scoConnectionAttempts = 0;
- AppRTCBluetoothManager.this.updateAudioDeviceState();
- } else if (state != 1 && state != 3 && state == 0) {
- AppRTCBluetoothManager.this.stopScoAudio();
- AppRTCBluetoothManager.this.updateAudioDeviceState();
- }
- } else if (action.equals("android.bluetooth.headset.profile.action.AUDIO_STATE_CHANGED")) {
- state = intent.getIntExtra("android.bluetooth.profile.extra.STATE", 10);
- AppRTCBluetoothManager.LOGGER.d(AppRTCBluetoothManager.TAG, "BluetoothHeadsetBroadcastReceiver.onReceive: a=ACTION_AUDIO_STATE_CHANGED, s=" + AppRTCBluetoothManager.this.stateToString(state) + ", sb=" + this.isInitialStickyBroadcast() + ", BT state: " + AppRTCBluetoothManager.this.bluetoothState);
- if (state == 12) {
- AppRTCBluetoothManager.this.cancelTimer();
- if (AppRTCBluetoothManager.this.bluetoothState == AppRTCBluetoothManager.State.SCO_CONNECTING) {
- AppRTCBluetoothManager.LOGGER.d(AppRTCBluetoothManager.TAG, "+++ Bluetooth audio SCO is now connected");
- AppRTCBluetoothManager.this.bluetoothState = AppRTCBluetoothManager.State.SCO_CONNECTED;
- AppRTCBluetoothManager.this.scoConnectionAttempts = 0;
- AppRTCBluetoothManager.this.updateAudioDeviceState();
- } else {
- AppRTCBluetoothManager.LOGGER.w(AppRTCBluetoothManager.TAG, "Unexpected state BluetoothHeadset.STATE_AUDIO_CONNECTED");
- }
- } else if (state == 11) {
- AppRTCBluetoothManager.LOGGER.d(AppRTCBluetoothManager.TAG, "+++ Bluetooth audio SCO is now connecting...");
- } else if (state == 10) {
- AppRTCBluetoothManager.LOGGER.d(AppRTCBluetoothManager.TAG, "+++ Bluetooth audio SCO is now disconnected");
- if (this.isInitialStickyBroadcast()) {
- AppRTCBluetoothManager.LOGGER.d(AppRTCBluetoothManager.TAG, "Ignore STATE_AUDIO_DISCONNECTED initial sticky broadcast.");
- return;
- }
- AppRTCBluetoothManager.this.updateAudioDeviceState();
- }
- }
- AppRTCBluetoothManager.LOGGER.d(AppRTCBluetoothManager.TAG, "onReceive done: BT state=" + AppRTCBluetoothManager.this.bluetoothState);
- }
- }
- }
- private class BluetoothServiceListener implements ServiceListener {
- private BluetoothServiceListener() {
- }
- public void onServiceConnected(int profile, BluetoothProfile proxy) {
- if (profile == 1 && AppRTCBluetoothManager.this.bluetoothState != AppRTCBluetoothManager.State.UNINITIALIZED) {
- AppRTCBluetoothManager.LOGGER.d(AppRTCBluetoothManager.TAG, "BluetoothServiceListener.onServiceConnected: BT state=" + AppRTCBluetoothManager.this.bluetoothState);
- AppRTCBluetoothManager.this.bluetoothHeadset = (BluetoothHeadset)proxy;
- AppRTCBluetoothManager.this.updateAudioDeviceState();
- AppRTCBluetoothManager.LOGGER.d(AppRTCBluetoothManager.TAG, "onServiceConnected done: BT state=" + AppRTCBluetoothManager.this.bluetoothState);
- }
- }
- public void onServiceDisconnected(int profile) {
- if (profile == 1 && AppRTCBluetoothManager.this.bluetoothState != AppRTCBluetoothManager.State.UNINITIALIZED) {
- AppRTCBluetoothManager.LOGGER.d(AppRTCBluetoothManager.TAG, "BluetoothServiceListener.onServiceDisconnected: BT state=" + AppRTCBluetoothManager.this.bluetoothState);
- AppRTCBluetoothManager.this.stopScoAudio();
- AppRTCBluetoothManager.this.bluetoothHeadset = null;
- AppRTCBluetoothManager.this.bluetoothDevice = null;
- AppRTCBluetoothManager.this.bluetoothState = AppRTCBluetoothManager.State.HEADSET_UNAVAILABLE;
- AppRTCBluetoothManager.this.updateAudioDeviceState();
- AppRTCBluetoothManager.LOGGER.d(AppRTCBluetoothManager.TAG, "onServiceDisconnected done: BT state=" + AppRTCBluetoothManager.this.bluetoothState);
- }
- }
- }
- public static enum State {
- UNINITIALIZED,
- ERROR,
- HEADSET_UNAVAILABLE,
- HEADSET_AVAILABLE,
- SCO_DISCONNECTING,
- SCO_CONNECTING,
- SCO_CONNECTED;
- private State() {
- }
- }
- }
Add Comment
Please, Sign In to add comment