Loading android/app/src/com/android/bluetooth/hfp/HeadsetService.java +125 −15 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.media.AudioDeviceCallback; import android.media.AudioDeviceInfo; import android.media.AudioManager; import android.media.BluetoothProfileConnectionInfo; Loading Loading @@ -141,6 +142,7 @@ public class HeadsetService extends ProfileService { private final HeadsetSystemInterface mSystemInterface; private int mMaxHeadsetConnections = 1; private BluetoothDevice mExposedActiveDevice; private BluetoothDevice mActiveDevice; private boolean mAudioRouteAllowed = true; // Indicates whether SCO audio needs to be forced to open regardless ANY OTHER restrictions Loading @@ -155,6 +157,8 @@ public class HeadsetService extends ProfileService { // Timeout when voice recognition is started by remote device @VisibleForTesting static int sStartVrTimeoutMs = 5000; private ArrayList<StateMachineTask> mPendingClccResponses = new ArrayList<>(); private final AudioManagerAudioDeviceCallback mAudioManagerAudioDeviceCallback = new AudioManagerAudioDeviceCallback(); private static HeadsetService sHeadsetService; @VisibleForTesting boolean mIsAptXSwbEnabled = false; Loading Loading @@ -208,7 +212,14 @@ public class HeadsetService extends ProfileService { mNativeInterface.init(mMaxHeadsetConnections + 1, isInbandRingingEnabled()); enableSwbCodec( HeadsetHalConstants.BTHF_SWB_CODEC_VENDOR_APTX, mIsAptXSwbEnabled, mActiveDevice); // Step 6: Setup broadcast receivers // Step 6: Register Audio Device callback if (Utils.isScoManagedByAudioEnabled()) { mSystemInterface .getAudioManager() .registerAudioDeviceCallback(mAudioManagerAudioDeviceCallback, mHandler); } // Step 7: Setup broadcast receivers IntentFilter filter = new IntentFilter(); filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); filter.addAction(Intent.ACTION_BATTERY_CHANGED); Loading @@ -229,11 +240,20 @@ public class HeadsetService extends ProfileService { @Override public void stop() { Log.i(TAG, "stop()"); // Step 6: Tear down broadcast receivers // Step 7: Tear down broadcast receivers unregisterReceiver(mHeadsetReceiver); // Step 6: Unregister Audio Device Callback if (Utils.isScoManagedByAudioEnabled()) { mSystemInterface .getAudioManager() .unregisterAudioDeviceCallback(mAudioManagerAudioDeviceCallback); } synchronized (mStateMachines) { // Reset active device to null if (mActiveDevice != null) { mExposedActiveDevice = null; mActiveDevice = null; broadcastActiveDevice(null); } Loading Loading @@ -1397,6 +1417,8 @@ public class HeadsetService extends ProfileService { } // Make sure the Audio Manager knows the previous active device is no longer active. mActiveDevice = null; mNativeInterface.setActiveDevice(null); if (Utils.isScoManagedByAudioEnabled()) { mSystemInterface .getAudioManager() Loading @@ -1404,11 +1426,10 @@ public class HeadsetService extends ProfileService { null, mActiveDevice, BluetoothProfileConnectionInfo.createHfpInfo()); } else { broadcastActiveDevice(null); } mActiveDevice = null; mNativeInterface.setActiveDevice(null); broadcastActiveDevice(null); if (Flags.updateActiveDeviceInBandRingtone()) { updateInbandRinging(null, true); } Loading Loading @@ -1480,8 +1501,9 @@ public class HeadsetService extends ProfileService { mActiveDevice, previousActiveDevice, BluetoothProfileConnectionInfo.createHfpInfo()); } } else { broadcastActiveDevice(mActiveDevice); } if (Flags.updateActiveDeviceInBandRingtone()) { updateInbandRinging(device, true); } Loading @@ -1494,12 +1516,10 @@ public class HeadsetService extends ProfileService { mActiveDevice, previousActiveDevice, BluetoothProfileConnectionInfo.createHfpInfo()); } broadcastActiveDevice(mActiveDevice); if (Utils.isScoManagedByAudioEnabled()) { // Audio Framework will handle audio transition return true; } broadcastActiveDevice(mActiveDevice); int connectStatus = connectAudio(mActiveDevice); if (connectStatus != BluetoothStatusCodes.SUCCESS) { Log.e( Loading @@ -1525,8 +1545,9 @@ public class HeadsetService extends ProfileService { mActiveDevice, previousActiveDevice, BluetoothProfileConnectionInfo.createHfpInfo()); } } else { broadcastActiveDevice(mActiveDevice); } if (Flags.updateActiveDeviceInBandRingtone()) { updateInbandRinging(device, true); } Loading Loading @@ -2398,6 +2419,95 @@ public class HeadsetService extends ProfileService { Utils.getTempBroadcastOptions().toBundle()); } /* Notifications of audio device connection/disconnection events. */ private class AudioManagerAudioDeviceCallback extends AudioDeviceCallback { @Override public void onAudioDevicesAdded(AudioDeviceInfo[] addedDevices) { if (mSystemInterface.getAudioManager() == null || mAdapterService == null) { Log.e(TAG, "Callback called when A2dpService is stopped"); return; } synchronized (mStateMachines) { for (AudioDeviceInfo deviceInfo : addedDevices) { if (deviceInfo.getType() != AudioDeviceInfo.TYPE_BLUETOOTH_SCO) { continue; } String address = deviceInfo.getAddress(); if (address.equals("00:00:00:00:00:00")) { continue; } byte[] addressBytes = Utils.getBytesFromAddress(address); BluetoothDevice device = mAdapterService.getDeviceFromByte(addressBytes); Log.d( TAG, " onAudioDevicesAdded: " + device + ", device type: " + deviceInfo.getType()); /* Don't expose already exposed active device */ if (device.equals(mExposedActiveDevice)) { Log.d(TAG, " onAudioDevicesAdded: " + device + " is already exposed"); return; } if (!device.equals(mActiveDevice)) { Log.e( TAG, "Added device does not match to the one activated here. (" + device + " != " + mActiveDevice + " / " + mActiveDevice + ")"); continue; } mExposedActiveDevice = device; broadcastActiveDevice(device); return; } } } @Override public void onAudioDevicesRemoved(AudioDeviceInfo[] removedDevices) { if (mSystemInterface.getAudioManager() == null || mAdapterService == null) { Log.e(TAG, "Callback called when LeAudioService is stopped"); return; } synchronized (mStateMachines) { for (AudioDeviceInfo deviceInfo : removedDevices) { if (deviceInfo.getType() != AudioDeviceInfo.TYPE_BLUETOOTH_SCO) { continue; } String address = deviceInfo.getAddress(); if (address.equals("00:00:00:00:00:00")) { continue; } mExposedActiveDevice = null; Log.d( TAG, " onAudioDevicesRemoved: " + address + ", device type: " + deviceInfo.getType() + ", mActiveDevice: " + mActiveDevice); } } } } /** * Check whether it is OK to accept a headset connection from a remote device * Loading android/app/src/com/android/bluetooth/hfp/HeadsetSystemInterface.java +0 −1 Original line number Diff line number Diff line Loading @@ -83,7 +83,6 @@ class HeadsetSystemInterface { * * @return audio manager for setting audio parameters */ @VisibleForTesting public AudioManager getAudioManager() { return mAudioManager; } Loading Loading
android/app/src/com/android/bluetooth/hfp/HeadsetService.java +125 −15 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.media.AudioDeviceCallback; import android.media.AudioDeviceInfo; import android.media.AudioManager; import android.media.BluetoothProfileConnectionInfo; Loading Loading @@ -141,6 +142,7 @@ public class HeadsetService extends ProfileService { private final HeadsetSystemInterface mSystemInterface; private int mMaxHeadsetConnections = 1; private BluetoothDevice mExposedActiveDevice; private BluetoothDevice mActiveDevice; private boolean mAudioRouteAllowed = true; // Indicates whether SCO audio needs to be forced to open regardless ANY OTHER restrictions Loading @@ -155,6 +157,8 @@ public class HeadsetService extends ProfileService { // Timeout when voice recognition is started by remote device @VisibleForTesting static int sStartVrTimeoutMs = 5000; private ArrayList<StateMachineTask> mPendingClccResponses = new ArrayList<>(); private final AudioManagerAudioDeviceCallback mAudioManagerAudioDeviceCallback = new AudioManagerAudioDeviceCallback(); private static HeadsetService sHeadsetService; @VisibleForTesting boolean mIsAptXSwbEnabled = false; Loading Loading @@ -208,7 +212,14 @@ public class HeadsetService extends ProfileService { mNativeInterface.init(mMaxHeadsetConnections + 1, isInbandRingingEnabled()); enableSwbCodec( HeadsetHalConstants.BTHF_SWB_CODEC_VENDOR_APTX, mIsAptXSwbEnabled, mActiveDevice); // Step 6: Setup broadcast receivers // Step 6: Register Audio Device callback if (Utils.isScoManagedByAudioEnabled()) { mSystemInterface .getAudioManager() .registerAudioDeviceCallback(mAudioManagerAudioDeviceCallback, mHandler); } // Step 7: Setup broadcast receivers IntentFilter filter = new IntentFilter(); filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); filter.addAction(Intent.ACTION_BATTERY_CHANGED); Loading @@ -229,11 +240,20 @@ public class HeadsetService extends ProfileService { @Override public void stop() { Log.i(TAG, "stop()"); // Step 6: Tear down broadcast receivers // Step 7: Tear down broadcast receivers unregisterReceiver(mHeadsetReceiver); // Step 6: Unregister Audio Device Callback if (Utils.isScoManagedByAudioEnabled()) { mSystemInterface .getAudioManager() .unregisterAudioDeviceCallback(mAudioManagerAudioDeviceCallback); } synchronized (mStateMachines) { // Reset active device to null if (mActiveDevice != null) { mExposedActiveDevice = null; mActiveDevice = null; broadcastActiveDevice(null); } Loading Loading @@ -1397,6 +1417,8 @@ public class HeadsetService extends ProfileService { } // Make sure the Audio Manager knows the previous active device is no longer active. mActiveDevice = null; mNativeInterface.setActiveDevice(null); if (Utils.isScoManagedByAudioEnabled()) { mSystemInterface .getAudioManager() Loading @@ -1404,11 +1426,10 @@ public class HeadsetService extends ProfileService { null, mActiveDevice, BluetoothProfileConnectionInfo.createHfpInfo()); } else { broadcastActiveDevice(null); } mActiveDevice = null; mNativeInterface.setActiveDevice(null); broadcastActiveDevice(null); if (Flags.updateActiveDeviceInBandRingtone()) { updateInbandRinging(null, true); } Loading Loading @@ -1480,8 +1501,9 @@ public class HeadsetService extends ProfileService { mActiveDevice, previousActiveDevice, BluetoothProfileConnectionInfo.createHfpInfo()); } } else { broadcastActiveDevice(mActiveDevice); } if (Flags.updateActiveDeviceInBandRingtone()) { updateInbandRinging(device, true); } Loading @@ -1494,12 +1516,10 @@ public class HeadsetService extends ProfileService { mActiveDevice, previousActiveDevice, BluetoothProfileConnectionInfo.createHfpInfo()); } broadcastActiveDevice(mActiveDevice); if (Utils.isScoManagedByAudioEnabled()) { // Audio Framework will handle audio transition return true; } broadcastActiveDevice(mActiveDevice); int connectStatus = connectAudio(mActiveDevice); if (connectStatus != BluetoothStatusCodes.SUCCESS) { Log.e( Loading @@ -1525,8 +1545,9 @@ public class HeadsetService extends ProfileService { mActiveDevice, previousActiveDevice, BluetoothProfileConnectionInfo.createHfpInfo()); } } else { broadcastActiveDevice(mActiveDevice); } if (Flags.updateActiveDeviceInBandRingtone()) { updateInbandRinging(device, true); } Loading Loading @@ -2398,6 +2419,95 @@ public class HeadsetService extends ProfileService { Utils.getTempBroadcastOptions().toBundle()); } /* Notifications of audio device connection/disconnection events. */ private class AudioManagerAudioDeviceCallback extends AudioDeviceCallback { @Override public void onAudioDevicesAdded(AudioDeviceInfo[] addedDevices) { if (mSystemInterface.getAudioManager() == null || mAdapterService == null) { Log.e(TAG, "Callback called when A2dpService is stopped"); return; } synchronized (mStateMachines) { for (AudioDeviceInfo deviceInfo : addedDevices) { if (deviceInfo.getType() != AudioDeviceInfo.TYPE_BLUETOOTH_SCO) { continue; } String address = deviceInfo.getAddress(); if (address.equals("00:00:00:00:00:00")) { continue; } byte[] addressBytes = Utils.getBytesFromAddress(address); BluetoothDevice device = mAdapterService.getDeviceFromByte(addressBytes); Log.d( TAG, " onAudioDevicesAdded: " + device + ", device type: " + deviceInfo.getType()); /* Don't expose already exposed active device */ if (device.equals(mExposedActiveDevice)) { Log.d(TAG, " onAudioDevicesAdded: " + device + " is already exposed"); return; } if (!device.equals(mActiveDevice)) { Log.e( TAG, "Added device does not match to the one activated here. (" + device + " != " + mActiveDevice + " / " + mActiveDevice + ")"); continue; } mExposedActiveDevice = device; broadcastActiveDevice(device); return; } } } @Override public void onAudioDevicesRemoved(AudioDeviceInfo[] removedDevices) { if (mSystemInterface.getAudioManager() == null || mAdapterService == null) { Log.e(TAG, "Callback called when LeAudioService is stopped"); return; } synchronized (mStateMachines) { for (AudioDeviceInfo deviceInfo : removedDevices) { if (deviceInfo.getType() != AudioDeviceInfo.TYPE_BLUETOOTH_SCO) { continue; } String address = deviceInfo.getAddress(); if (address.equals("00:00:00:00:00:00")) { continue; } mExposedActiveDevice = null; Log.d( TAG, " onAudioDevicesRemoved: " + address + ", device type: " + deviceInfo.getType() + ", mActiveDevice: " + mActiveDevice); } } } } /** * Check whether it is OK to accept a headset connection from a remote device * Loading
android/app/src/com/android/bluetooth/hfp/HeadsetSystemInterface.java +0 −1 Original line number Diff line number Diff line Loading @@ -83,7 +83,6 @@ class HeadsetSystemInterface { * * @return audio manager for setting audio parameters */ @VisibleForTesting public AudioManager getAudioManager() { return mAudioManager; } Loading