Loading android/app/src/com/android/bluetooth/hfpclient/HeadsetClientService.java +25 −4 Original line number Diff line number Diff line Loading @@ -314,15 +314,21 @@ public class HeadsetClientService extends ProfileService { @Override public boolean connectAudio(BluetoothDevice device) { Log.e(TAG, "connectAudio API not supported"); HeadsetClientService service = getService(); if (service == null) { return false; } return service.connectAudio(device); } @Override public boolean disconnectAudio(BluetoothDevice device) { Log.e(TAG, "disconnectAudio API not supported"); HeadsetClientService service = getService(); if (service == null) { return false; } return service.disconnectAudio(device); } @Override public boolean acceptCall(BluetoothDevice device, int flag) { Loading Loading @@ -869,6 +875,21 @@ public class HeadsetClientService extends ProfileService { return sm; } // Check if any of the state machines are currently holding the SCO audio stream // This function is *only* called from the SMs which are themselves run the same thread and // hence we do not need synchronization here boolean isScoAvailable() { for (BluetoothDevice bd : mStateMachineMap.keySet()) { HeadsetClientStateMachine sm = mStateMachineMap.get(bd); int audioState = sm.getAudioState(bd); if (audioState != BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED) { Log.w(TAG, "Device " + bd + " audio state " + audioState + " not disconnected"); return false; } } return true; } @Override public synchronized void dump(StringBuilder sb) { super.dump(sb); Loading android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java +33 −32 Original line number Diff line number Diff line Loading @@ -168,7 +168,6 @@ public class HeadsetClientStateMachine extends StateMachine { public void dump(StringBuilder sb) { ProfileService.println(sb, "mCurrentDevice: " + mCurrentDevice); ProfileService.println(sb, "mAudioOn: " + mAudioOn); ProfileService.println(sb, "mAudioState: " + mAudioState); ProfileService.println(sb, "mAudioWbs: " + mAudioWbs); ProfileService.println(sb, "mIndicatorNetworkState: " + mIndicatorNetworkState); Loading Loading @@ -1087,18 +1086,27 @@ public class HeadsetClientStateMachine extends StateMachine { break; } break; case CONNECT_AUDIO: // TODO: handle audio connection failure if (!NativeInterface.connectAudioNative(getByteAddress(mCurrentDevice))) { Log.e(TAG, "ERROR: Couldn't connect Audio."); if (!mService.isScoAvailable() || !NativeInterface.connectAudioNative( getByteAddress(mCurrentDevice))) { Log.e(TAG, "ERROR: Couldn't connect Audio for device " + mCurrentDevice + " isScoAvailable " + mService.isScoAvailable()); broadcastAudioState(mCurrentDevice, BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED, BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED); } else { // We have successfully sent a connect request! mAudioState = BluetoothHeadsetClient.STATE_AUDIO_CONNECTING; } break; case DISCONNECT_AUDIO: // TODO: handle audio disconnection failure if (!NativeInterface.disconnectAudioNative(getByteAddress(mCurrentDevice))) { Log.e(TAG, "ERROR: Couldn't connect Audio."); Log.e(TAG, "ERROR: Couldn't disconnect Audio for device " + mCurrentDevice); } break; // Called only for Mute/Un-mute - Mic volume change is not allowed. case SET_MIC_VOLUME: if (mVgmFromStack) { Loading Loading @@ -1443,19 +1451,19 @@ public class HeadsetClientStateMachine extends StateMachine { mAudioManager.setParameters("hfp_volume=" + hfVol); transitionTo(mAudioOn); break; case HeadsetClientHalConstants.AUDIO_STATE_CONNECTING: broadcastAudioState( device, BluetoothHeadsetClient.STATE_AUDIO_CONNECTING, mAudioState); mAudioState = BluetoothHeadsetClient.STATE_AUDIO_CONNECTING; broadcastAudioState(device, BluetoothHeadsetClient.STATE_AUDIO_CONNECTING, BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED); break; case HeadsetClientHalConstants.AUDIO_STATE_DISCONNECTED: if (mAudioState == BluetoothHeadsetClient.STATE_AUDIO_CONNECTING) { broadcastAudioState( device, BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED, mAudioState); mAudioState = BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED; broadcastAudioState(device, BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED, BluetoothHeadsetClient.STATE_AUDIO_CONNECTING); } break; default: Log.e(TAG, "Audio State Device: " + device + " bad state: " + state); break; Loading Loading @@ -1510,14 +1518,10 @@ public class HeadsetClientStateMachine extends StateMachine { * Machines state changing */ if (NativeInterface.disconnectAudioNative(getByteAddress(mCurrentDevice))) { mAudioState = BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED; if (DBG) { Log.d(TAG,"hfp_enable=false"); } mAudioManager.setParameters("hfp_enable=false"); broadcastAudioState(mCurrentDevice, BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED, BluetoothHeadsetClient.STATE_AUDIO_CONNECTED); } break; case StackEvent.STACK_EVENT: Loading Loading @@ -1580,7 +1584,6 @@ public class HeadsetClientStateMachine extends StateMachine { switch (state) { case HeadsetClientHalConstants.AUDIO_STATE_DISCONNECTED: if (mAudioState != BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED) { mAudioState = BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED; // Audio focus may still be held by the entity controlling the actual call // (such as Telecom) and hence this will still keep the call around, there Loading @@ -1590,13 +1593,11 @@ public class HeadsetClientStateMachine extends StateMachine { Log.d(TAG, "hfp_enable=false"); } mAudioManager.setParameters("hfp_enable=false"); broadcastAudioState(device, BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED, broadcastAudioState(device, BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED, BluetoothHeadsetClient.STATE_AUDIO_CONNECTED); } transitionTo(mConnected); break; default: Log.e(TAG, "Audio State Device: " + device + " bad state: " + state); break; Loading Loading
android/app/src/com/android/bluetooth/hfpclient/HeadsetClientService.java +25 −4 Original line number Diff line number Diff line Loading @@ -314,15 +314,21 @@ public class HeadsetClientService extends ProfileService { @Override public boolean connectAudio(BluetoothDevice device) { Log.e(TAG, "connectAudio API not supported"); HeadsetClientService service = getService(); if (service == null) { return false; } return service.connectAudio(device); } @Override public boolean disconnectAudio(BluetoothDevice device) { Log.e(TAG, "disconnectAudio API not supported"); HeadsetClientService service = getService(); if (service == null) { return false; } return service.disconnectAudio(device); } @Override public boolean acceptCall(BluetoothDevice device, int flag) { Loading Loading @@ -869,6 +875,21 @@ public class HeadsetClientService extends ProfileService { return sm; } // Check if any of the state machines are currently holding the SCO audio stream // This function is *only* called from the SMs which are themselves run the same thread and // hence we do not need synchronization here boolean isScoAvailable() { for (BluetoothDevice bd : mStateMachineMap.keySet()) { HeadsetClientStateMachine sm = mStateMachineMap.get(bd); int audioState = sm.getAudioState(bd); if (audioState != BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED) { Log.w(TAG, "Device " + bd + " audio state " + audioState + " not disconnected"); return false; } } return true; } @Override public synchronized void dump(StringBuilder sb) { super.dump(sb); Loading
android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java +33 −32 Original line number Diff line number Diff line Loading @@ -168,7 +168,6 @@ public class HeadsetClientStateMachine extends StateMachine { public void dump(StringBuilder sb) { ProfileService.println(sb, "mCurrentDevice: " + mCurrentDevice); ProfileService.println(sb, "mAudioOn: " + mAudioOn); ProfileService.println(sb, "mAudioState: " + mAudioState); ProfileService.println(sb, "mAudioWbs: " + mAudioWbs); ProfileService.println(sb, "mIndicatorNetworkState: " + mIndicatorNetworkState); Loading Loading @@ -1087,18 +1086,27 @@ public class HeadsetClientStateMachine extends StateMachine { break; } break; case CONNECT_AUDIO: // TODO: handle audio connection failure if (!NativeInterface.connectAudioNative(getByteAddress(mCurrentDevice))) { Log.e(TAG, "ERROR: Couldn't connect Audio."); if (!mService.isScoAvailable() || !NativeInterface.connectAudioNative( getByteAddress(mCurrentDevice))) { Log.e(TAG, "ERROR: Couldn't connect Audio for device " + mCurrentDevice + " isScoAvailable " + mService.isScoAvailable()); broadcastAudioState(mCurrentDevice, BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED, BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED); } else { // We have successfully sent a connect request! mAudioState = BluetoothHeadsetClient.STATE_AUDIO_CONNECTING; } break; case DISCONNECT_AUDIO: // TODO: handle audio disconnection failure if (!NativeInterface.disconnectAudioNative(getByteAddress(mCurrentDevice))) { Log.e(TAG, "ERROR: Couldn't connect Audio."); Log.e(TAG, "ERROR: Couldn't disconnect Audio for device " + mCurrentDevice); } break; // Called only for Mute/Un-mute - Mic volume change is not allowed. case SET_MIC_VOLUME: if (mVgmFromStack) { Loading Loading @@ -1443,19 +1451,19 @@ public class HeadsetClientStateMachine extends StateMachine { mAudioManager.setParameters("hfp_volume=" + hfVol); transitionTo(mAudioOn); break; case HeadsetClientHalConstants.AUDIO_STATE_CONNECTING: broadcastAudioState( device, BluetoothHeadsetClient.STATE_AUDIO_CONNECTING, mAudioState); mAudioState = BluetoothHeadsetClient.STATE_AUDIO_CONNECTING; broadcastAudioState(device, BluetoothHeadsetClient.STATE_AUDIO_CONNECTING, BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED); break; case HeadsetClientHalConstants.AUDIO_STATE_DISCONNECTED: if (mAudioState == BluetoothHeadsetClient.STATE_AUDIO_CONNECTING) { broadcastAudioState( device, BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED, mAudioState); mAudioState = BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED; broadcastAudioState(device, BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED, BluetoothHeadsetClient.STATE_AUDIO_CONNECTING); } break; default: Log.e(TAG, "Audio State Device: " + device + " bad state: " + state); break; Loading Loading @@ -1510,14 +1518,10 @@ public class HeadsetClientStateMachine extends StateMachine { * Machines state changing */ if (NativeInterface.disconnectAudioNative(getByteAddress(mCurrentDevice))) { mAudioState = BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED; if (DBG) { Log.d(TAG,"hfp_enable=false"); } mAudioManager.setParameters("hfp_enable=false"); broadcastAudioState(mCurrentDevice, BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED, BluetoothHeadsetClient.STATE_AUDIO_CONNECTED); } break; case StackEvent.STACK_EVENT: Loading Loading @@ -1580,7 +1584,6 @@ public class HeadsetClientStateMachine extends StateMachine { switch (state) { case HeadsetClientHalConstants.AUDIO_STATE_DISCONNECTED: if (mAudioState != BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED) { mAudioState = BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED; // Audio focus may still be held by the entity controlling the actual call // (such as Telecom) and hence this will still keep the call around, there Loading @@ -1590,13 +1593,11 @@ public class HeadsetClientStateMachine extends StateMachine { Log.d(TAG, "hfp_enable=false"); } mAudioManager.setParameters("hfp_enable=false"); broadcastAudioState(device, BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED, broadcastAudioState(device, BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED, BluetoothHeadsetClient.STATE_AUDIO_CONNECTED); } transitionTo(mConnected); break; default: Log.e(TAG, "Audio State Device: " + device + " bad state: " + state); break; Loading