Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 408ff841 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "leaudio: Workaround for the CIS->SCO handover"

parents 76e59e35 305cb612
Loading
Loading
Loading
Loading
+3 −2
Original line number Original line Diff line number Diff line
@@ -1399,8 +1399,9 @@ public class HeadsetService extends ProfileService {
                LeAudioService leAudioService = mFactory.getLeAudioService();
                LeAudioService leAudioService = mFactory.getLeAudioService();
                if (leAudioService != null) {
                if (leAudioService != null) {
                    Log.i(TAG, "Make sure there is no le audio device active.");
                    Log.i(TAG, "Make sure there is no le audio device active.");
                    leAudioService.setActiveDevice(null);
                    leAudioService.setInactiveForHfpHandover(mActiveDevice);
                }
                }

                broadcastActiveDevice(mActiveDevice);
                broadcastActiveDevice(mActiveDevice);
                int connectStatus = connectAudio(mActiveDevice);
                int connectStatus = connectAudio(mActiveDevice);
                if (connectStatus != BluetoothStatusCodes.SUCCESS) {
                if (connectStatus != BluetoothStatusCodes.SUCCESS) {
@@ -1432,7 +1433,7 @@ public class HeadsetService extends ProfileService {
        }
        }
    }
    }


    int connectAudio() {
    public int connectAudio() {
        synchronized (mStateMachines) {
        synchronized (mStateMachines) {
            BluetoothDevice device = mActiveDevice;
            BluetoothDevice device = mActiveDevice;
            if (device == null) {
            if (device == null) {
+72 −0
Original line number Original line Diff line number Diff line
@@ -60,6 +60,7 @@ import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.btservice.ProfileService;
import com.android.bluetooth.btservice.ProfileService;
import com.android.bluetooth.btservice.ServiceFactory;
import com.android.bluetooth.btservice.ServiceFactory;
import com.android.bluetooth.btservice.storage.DatabaseManager;
import com.android.bluetooth.btservice.storage.DatabaseManager;
import com.android.bluetooth.hfp.HeadsetService;
import com.android.bluetooth.mcp.McpService;
import com.android.bluetooth.mcp.McpService;
import com.android.bluetooth.tbs.TbsGatt;
import com.android.bluetooth.tbs.TbsGatt;
import com.android.bluetooth.vc.VolumeControlService;
import com.android.bluetooth.vc.VolumeControlService;
@@ -117,6 +118,7 @@ public class LeAudioService extends ProfileService {


    LeAudioNativeInterface mLeAudioNativeInterface;
    LeAudioNativeInterface mLeAudioNativeInterface;
    boolean mLeAudioNativeIsInitialized = false;
    boolean mLeAudioNativeIsInitialized = false;
    BluetoothDevice mHfpHandoverDevice = null;
    LeAudioBroadcasterNativeInterface mLeAudioBroadcasterNativeInterface = null;
    LeAudioBroadcasterNativeInterface mLeAudioBroadcasterNativeInterface = null;
    @VisibleForTesting
    @VisibleForTesting
    AudioManager mAudioManager;
    AudioManager mAudioManager;
@@ -331,6 +333,7 @@ public class LeAudioService extends ProfileService {
        mLeAudioNativeInterface.cleanup();
        mLeAudioNativeInterface.cleanup();
        mLeAudioNativeInterface = null;
        mLeAudioNativeInterface = null;
        mLeAudioNativeIsInitialized = false;
        mLeAudioNativeIsInitialized = false;
        mHfpHandoverDevice = null;


        // Set the service and BLE devices as inactive
        // Set the service and BLE devices as inactive
        setLeAudioService(null);
        setLeAudioService(null);
@@ -1173,6 +1176,36 @@ public class LeAudioService extends ProfileService {
        }
        }
    }
    }


    private void handleGroupIdleDuringCall() {
        if (mHfpHandoverDevice == null) {
            if (DBG) {
                Log.d(TAG, "There is no HFP handover");
            }
            return;
        }
        HeadsetService headsetService = mServiceFactory.getHeadsetService();
        if (headsetService == null) {
            if (DBG) {
                Log.d(TAG, "There is no HFP service available");
            }
            return;
        }

        BluetoothDevice activeHfpDevice = headsetService.getActiveDevice();
        if (activeHfpDevice == null) {
            if (DBG) {
                Log.d(TAG, "Make " + mHfpHandoverDevice + " active again ");
            }
            headsetService.setActiveDevice(mHfpHandoverDevice);
        } else {
            if (DBG) {
                Log.d(TAG, "Connect audio to " + activeHfpDevice);
            }
            headsetService.connectAudio();
        }
        mHfpHandoverDevice = null;
    }

    // Suppressed since this is part of a local process
    // Suppressed since this is part of a local process
    @SuppressLint("AndroidFrameworkRequiresPermission")
    @SuppressLint("AndroidFrameworkRequiresPermission")
    void messageFromNative(LeAudioStackEvent stackEvent) {
    void messageFromNative(LeAudioStackEvent stackEvent) {
@@ -1338,6 +1371,10 @@ public class LeAudioService extends ProfileService {
                    handleGroupTransitToInactive(groupId);
                    handleGroupTransitToInactive(groupId);
                    break;
                    break;
                }
                }
                case LeAudioStackEvent.GROUP_STATUS_TURNED_IDLE_DURING_CALL: {
                    handleGroupIdleDuringCall();
                    break;
                }
                default:
                default:
                    break;
                    break;
            }
            }
@@ -1746,6 +1783,20 @@ public class LeAudioService extends ProfileService {
        mLeAudioNativeInterface.setInCall(inCall);
        mLeAudioNativeInterface.setInCall(inCall);
    }
    }


    /**
     * Set Inactive by HFP during handover
     */
    public void setInactiveForHfpHandover(BluetoothDevice hfpHandoverDevice) {
        if (!mLeAudioNativeIsInitialized) {
            Log.e(TAG, "Le Audio not initialized properly.");
            return;
        }
        if (getActiveGroupId() != LE_AUDIO_GROUP_ID_INVALID) {
            mHfpHandoverDevice = hfpHandoverDevice;
            setActiveDevice(null);
        }
    }

    /**
    /**
     * Set connection policy of the profile and connects it if connectionPolicy is
     * Set connection policy of the profile and connects it if connectionPolicy is
     * {@link BluetoothProfile#CONNECTION_POLICY_ALLOWED} or disconnects if connectionPolicy is
     * {@link BluetoothProfile#CONNECTION_POLICY_ALLOWED} or disconnects if connectionPolicy is
@@ -2467,6 +2518,26 @@ public class LeAudioService extends ProfileService {
            }
            }
        }
        }


        @Override
        public void setInactiveForHfpHandover(BluetoothDevice hfpHandoverDevice,
                AttributionSource source,
                SynchronousResultReceiver receiver) {
            try {
                Objects.requireNonNull(source, "source cannot be null");
                Objects.requireNonNull(receiver, "receiver cannot be null");

                LeAudioService service = getService(source);
                if (service == null) {
                    throw new IllegalStateException("service is null");
                }
                enforceBluetoothPrivilegedPermission(service);
                service.setInactiveForHfpHandover(hfpHandoverDevice);
                receiver.send(null);
            } catch (RuntimeException e) {
                receiver.propagateException(e);
            }
        }

        @Override
        @Override
        public void groupRemoveNode(int groupId, BluetoothDevice device,
        public void groupRemoveNode(int groupId, BluetoothDevice device,
                AttributionSource source, SynchronousResultReceiver receiver) {
                AttributionSource source, SynchronousResultReceiver receiver) {
@@ -2712,6 +2783,7 @@ public class LeAudioService extends ProfileService {
        ProfileService.println(sb, "  currentlyActiveGroupId: " + getActiveGroupId());
        ProfileService.println(sb, "  currentlyActiveGroupId: " + getActiveGroupId());
        ProfileService.println(sb, "  mActiveAudioOutDevice: " + mActiveAudioOutDevice);
        ProfileService.println(sb, "  mActiveAudioOutDevice: " + mActiveAudioOutDevice);
        ProfileService.println(sb, "  mActiveAudioInDevice: " + mActiveAudioInDevice);
        ProfileService.println(sb, "  mActiveAudioInDevice: " + mActiveAudioInDevice);
        ProfileService.println(sb, "  mHfpHandoverDevice:" + mHfpHandoverDevice);


        for (Map.Entry<Integer, LeAudioGroupDescriptor> entry : mGroupDescriptors.entrySet()) {
        for (Map.Entry<Integer, LeAudioGroupDescriptor> entry : mGroupDescriptors.entrySet()) {
            LeAudioGroupDescriptor descriptor = entry.getValue();
            LeAudioGroupDescriptor descriptor = entry.getValue();
+3 −0
Original line number Original line Diff line number Diff line
@@ -55,6 +55,7 @@ public class LeAudioStackEvent {


    static final int GROUP_STATUS_INACTIVE = 0;
    static final int GROUP_STATUS_INACTIVE = 0;
    static final int GROUP_STATUS_ACTIVE = 1;
    static final int GROUP_STATUS_ACTIVE = 1;
    static final int GROUP_STATUS_TURNED_IDLE_DURING_CALL = 2;


    static final int GROUP_NODE_ADDED = 1;
    static final int GROUP_NODE_ADDED = 1;
    static final int GROUP_NODE_REMOVED = 2;
    static final int GROUP_NODE_REMOVED = 2;
@@ -192,6 +193,8 @@ public class LeAudioStackEvent {
                        return "GROUP_STATUS_ACTIVE";
                        return "GROUP_STATUS_ACTIVE";
                    case GROUP_STATUS_INACTIVE:
                    case GROUP_STATUS_INACTIVE:
                        return "GROUP_STATUS_INACTIVE";
                        return "GROUP_STATUS_INACTIVE";
                    case GROUP_STATUS_TURNED_IDLE_DURING_CALL:
                        return "GROUP_STATUS_TURNED_IDLE_DURING_CALL";
                    default:
                    default:
                        break;
                        break;
                }
                }
+3 −0
Original line number Original line Diff line number Diff line
@@ -67,12 +67,15 @@ oneway interface IBluetoothLeAudio {
    void setCcidInformation(in ParcelUuid userUuid, in int ccid, in int contextType, in AttributionSource attributionSource, in SynchronousResultReceiver receiver);
    void setCcidInformation(in ParcelUuid userUuid, in int ccid, in int contextType, in AttributionSource attributionSource, in SynchronousResultReceiver receiver);
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})")
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})")
    void setInCall(in boolean inCall, in AttributionSource attributionSource, in SynchronousResultReceiver receiver);
    void setInCall(in boolean inCall, in AttributionSource attributionSource, in SynchronousResultReceiver receiver);
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})")
    void setInactiveForHfpHandover(in BluetoothDevice device, in AttributionSource attributionSource, in SynchronousResultReceiver receiver);


    /* Same value as bluetooth::groups::kGroupUnknown */
    /* Same value as bluetooth::groups::kGroupUnknown */
    const int LE_AUDIO_GROUP_ID_INVALID = -1;
    const int LE_AUDIO_GROUP_ID_INVALID = -1;


    const int GROUP_STATUS_INACTIVE = 0;
    const int GROUP_STATUS_INACTIVE = 0;
    const int GROUP_STATUS_ACTIVE = 1;
    const int GROUP_STATUS_ACTIVE = 1;
    const int GROUP_STATUS_TURNED_IDLE_DURING_CALL = 2;


    const int GROUP_NODE_ADDED = 1;
    const int GROUP_NODE_ADDED = 1;
    const int GROUP_NODE_REMOVED = 2;
    const int GROUP_NODE_REMOVED = 2;
+22 −4
Original line number Original line Diff line number Diff line
@@ -833,15 +833,16 @@ class LeAudioClientImpl : public LeAudioClient {
        return;
        return;
      }
      }


      auto group_id_to_close = active_group_id_;
      active_group_id_ = bluetooth::groups::kGroupUnknown;

      if (alarm_is_scheduled(suspend_timeout_)) alarm_cancel(suspend_timeout_);
      if (alarm_is_scheduled(suspend_timeout_)) alarm_cancel(suspend_timeout_);


      StopAudio();
      StopAudio();
      ClientAudioIntefraceRelease();
      ClientAudioIntefraceRelease();


      GroupStop(active_group_id_);
      GroupStop(group_id_to_close);
      callbacks_->OnGroupStatus(active_group_id_, GroupStatus::INACTIVE);
      callbacks_->OnGroupStatus(group_id_to_close, GroupStatus::INACTIVE);
      active_group_id_ = group_id;

      return;
      return;
    }
    }


@@ -3675,6 +3676,20 @@ class LeAudioClientImpl : public LeAudioClient {
    }
    }
  }
  }


  void NotifyUpperLayerGroupTurnedIdleDuringCall(int group_id) {
    if (!osi_property_get_bool(kNotifyUpperLayerAboutGroupBeingInIdleDuringCall,
                               false)) {
      return;
    }
    /* If group is inactive, phone is in call and Group is not having CIS
     * connected, notify upper layer about it, so it can decide to create SCO if
     * it is in the handover case
     */
    if (in_call_ && active_group_id_ == bluetooth::groups::kGroupUnknown) {
      callbacks_->OnGroupStatus(group_id, GroupStatus::TURNED_IDLE_DURING_CALL);
    }
  }

  void StatusReportCb(int group_id, GroupStreamStatus status) {
  void StatusReportCb(int group_id, GroupStreamStatus status) {
    LOG_INFO("status: %d , audio_sender_state %s, audio_receiver_state %s",
    LOG_INFO("status: %d , audio_sender_state %s, audio_receiver_state %s",
             static_cast<int>(status),
             static_cast<int>(status),
@@ -3745,6 +3760,7 @@ class LeAudioClientImpl : public LeAudioClient {
        }
        }
        CancelStreamingRequest();
        CancelStreamingRequest();
        if (group) {
        if (group) {
          NotifyUpperLayerGroupTurnedIdleDuringCall(group->group_id_);
          HandlePendingAvailableContexts(group);
          HandlePendingAvailableContexts(group);
          HandlePendingDeviceDisconnection(group);
          HandlePendingDeviceDisconnection(group);
        }
        }
@@ -3782,6 +3798,8 @@ class LeAudioClientImpl : public LeAudioClient {
  AudioState audio_sender_state_;
  AudioState audio_sender_state_;
  /* Keep in call state. */
  /* Keep in call state. */
  bool in_call_;
  bool in_call_;
  static constexpr char kNotifyUpperLayerAboutGroupBeingInIdleDuringCall[] =
      "persist.bluetooth.leaudio.notify.idle.during.call";


  /* Current stream configuration */
  /* Current stream configuration */
  LeAudioCodecConfiguration current_source_codec_config;
  LeAudioCodecConfiguration current_source_codec_config;
Loading