googlesamples / glass-enterprise-samples

Glass Enterprise Edition 2 Samples
Apache License 2.0
123 stars 93 forks source link

Bluetooth headsets not working in WebRTCSample #17

Closed fede87 closed 4 years ago

fede87 commented 4 years ago

Description

We are developing a custom solution based on WebRTC tecnology running on android devices as well as on Google Glass Enterprise Edition 2 smart glasses.

We found a possible issue regarding bluetooth headset connection that we are able to reproduce on the webRTC sample. Bluetooth headsets seems not to be working during webRTC calls.

The capability of connecting bluetooth headsets is critical when the webRTC solution running on Google Glass is used in noisy environments for field services or shop assistance use cases.

Wired headsets are currently working with webRTC solutions running on Google Glass, but it is obviously needed an usb-c/jack adapter which is becoming less popular nowadays in favour of true wireless bluetooth headset devices and it is also a less ergonomic way to join a call.

Steps to Reproduce

  1. Pair a bluetooth headset from Google Glass system settings and keep it connected and active.
  2. Run the webRTC sample app.
  3. Connect to the webRTC suggested room from the Google Glass sample app and connect a desktop to the same suggested room.
  4. The audio keeps coming from the speaker and the bluetooth headset is not capable of reproducing the room audio.

Code

The error seems to be related to the bluetooth adapter proxy discover process that is never completed, the following snipped is taken from AppRTCBluetoothManager.java class:


/**
   * Implementation of an interface that notifies BluetoothProfile IPC clients when they have been
   * connected to or disconnected from the service.
   */
  private class BluetoothServiceListener implements BluetoothProfile.ServiceListener {
    @Override
    // Called to notify the client when the proxy object has been connected to the service.
    // Once we have the profile proxy object, we can use it to monitor the state of the
    // connection and perform other operations that are relevant to the headset profile.
    public void onServiceConnected(int profile, BluetoothProfile proxy) {
      if (profile != BluetoothProfile.HEADSET || bluetoothState == State.UNINITIALIZED) {
        return;
      }
      Log.d(TAG, "BluetoothServiceListener.onServiceConnected: BT state=" + bluetoothState);
      // Android only supports one connected Bluetooth Headset at a time.
      bluetoothHeadset = (BluetoothHeadset) proxy;
      updateAudioDeviceState();
      Log.d(TAG, "onServiceConnected done: BT state=" + bluetoothState);
    }

    @Override
    /** Notifies the client when the proxy object has been disconnected from the service. */
    public void onServiceDisconnected(int profile) {
      if (profile != BluetoothProfile.HEADSET || bluetoothState == State.UNINITIALIZED) {
        return;
      }
      Log.d(TAG, "BluetoothServiceListener.onServiceDisconnected: BT state=" + bluetoothState);
      stopScoAudio();
      bluetoothHeadset = null;
      bluetoothDevice = null;
      bluetoothState = State.HEADSET_UNAVAILABLE;
      updateAudioDeviceState();
      Log.d(TAG, "onServiceDisconnected done: BT state=" + bluetoothState);
    }
  }

  /**
   * Activates components required to detect Bluetooth devices and to enable
   * BT SCO (audio is routed via BT SCO) for the headset profile. The end
   * state will be HEADSET_UNAVAILABLE but a state machine has started which
   * will start a state change sequence where the final outcome depends on
   * if/when the BT headset is enabled.
   * Example of state change sequence when start() is called while BT device
   * is connected and enabled:
   *   UNINITIALIZED --> HEADSET_UNAVAILABLE --> HEADSET_AVAILABLE -->
   *   SCO_CONNECTING --> SCO_CONNECTED <==> audio is now routed via BT SCO.
   * Note that the AppRTCAudioManager is also involved in driving this state
   * change.
   */
  public void start() {

    [...]

    if (!getBluetoothProfileProxy(
            apprtcContext, bluetoothServiceListener, BluetoothProfile.HEADSET)) {
      Log.e(TAG, "BluetoothAdapter.getProfileProxy(HEADSET) failed");
      return;
    }

   [...] 

  }

  protected boolean getBluetoothProfileProxy(Context context,
  BluetoothProfile.ServiceListener listener, int profile) {
    return bluetoothAdapter.getProfileProxy(context, listener, profile);
  }

The function getBluetoothProfileProxy(Context context, BluetoothProfile.ServiceListener listener, int profile) called in the start() function is always called and always returns true, that means that the proxy retrieve process will start without any initial error, but the callback onServiceConnected(int profile, BluetoothProfile proxy) of the BluetoothServiceListener object is never been called.

The same behaviour seems to be occurring in our codebase where the bluetooth proxy retrieve process is accomplished in the same way.

The following lines are the most significant console outputs that appear just right after the getBluetoothProfileProxy(Context context, BluetoothProfile.ServiceListener listener, int profile) is called:

D/BluetoothManagerService: Creating new ProfileServiceConnections object for profile: 1
E/BluetoothManagerService: Fail to bind to: Intent { act=android.bluetooth.IBluetoothHeadset }

Expected Behavior

The onServiceConnected(int profile, BluetoothProfile proxy) of the BluetoothServiceListener object should be called or at least getBluetoothProfileProxy(Context context, BluetoothProfile.ServiceListener listener, int profile) should return false instead of true.

Google Glass O.S.

Tested and occurring with the following Google Glass O.S.:

jbolinger commented 4 years ago

Thanks for this detailed report @fede87. We're planning to update this sample soon and we will take a look at this.

kekkokk commented 4 years ago

Hi guys, any news on this? we're experiencing the same issue and it's quite a blocking issue and is business critical. Thanks!

jbolinger commented 4 years ago

We have a release coming soon that includes a fix for some bluetooth issues. Give us a little more time to get it out and then let us know if you're still running into this problem.

kekkokk commented 4 years ago

We have a release coming soon that includes a fix for some bluetooth issues. Give us a little more time to get it out and then let us know if you're still running into this problem.

are you talking about webrtc core or a glasses firmware update? thanks!

jbolinger commented 4 years ago

firmware update

kekkokk commented 4 years ago

I don't think it's directly related, but since we're here... I opened a bug report in the glasses website suggesting that with the latest firmware there's a bug when changing volume from the launcher dedicated setting card. when you move the bar and release the touch, the launcher crashes very often. it's definitely a minor issue but maybe it's easy to fix.

jbolinger commented 4 years ago

Thanks for reporting that again @kekkokk. I'm not sure we'll be able to get it in our next update but we'll try and get it fixed as soon as we can.

jbolinger commented 4 years ago

The latest firmware includes some bluetooth changes. Please let us know if you are still having trouble with the headsets.

fede87 commented 4 years ago

Hi, thank you for the update, we had the opportunity to test the last canary OPP.200529.001 and the last firmware OPM1.200625.001 and the issue is now resolved.