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

Commit 421121d8 authored by Grzegorz Kolodziejczyk's avatar Grzegorz Kolodziejczyk Committed by Automerger Merge Worker
Browse files

Merge "le_audio: Introduce Sink listening mode" into main am: d6fac7e1

parents 336dc9b1 d6fac7e1
Loading
Loading
Loading
Loading
+30 −0
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ using bluetooth::le_audio::LeAudioBroadcasterCallbacks;
using bluetooth::le_audio::LeAudioBroadcasterInterface;
using bluetooth::le_audio::LeAudioClientCallbacks;
using bluetooth::le_audio::LeAudioClientInterface;
using bluetooth::le_audio::UnicastMonitorModeStatus;

namespace android {
static jmethodID method_onInitialized;
@@ -53,6 +54,7 @@ static jmethodID method_onAudioGroupCurrentCodecConf;
static jmethodID method_onAudioGroupSelectableCodecConf;
static jmethodID method_onHealthBasedRecommendationAction;
static jmethodID method_onHealthBasedGroupRecommendationAction;
static jmethodID method_onUnicastMonitorModeStatus;

static struct {
  jclass clazz;
@@ -345,6 +347,19 @@ class LeAudioClientCallbacksImpl : public LeAudioClientCallbacks {
                                 method_onHealthBasedGroupRecommendationAction,
                                 (jint)group_id, (jint)action);
  }

  void OnUnicastMonitorModeStatus(uint8_t direction,
                                  UnicastMonitorModeStatus status) override {
    LOG(INFO) << __func__;

    std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
    CallbackEnv sCallbackEnv(__func__);
    if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return;

    sCallbackEnv->CallVoidMethod(mCallbacksObj,
                                 method_onUnicastMonitorModeStatus,
                                 (jint)direction, (jint)status);
  }
};

static LeAudioClientCallbacksImpl sLeAudioClientCallbacks;
@@ -681,6 +696,17 @@ static void setInCallNative(JNIEnv* /* env */, jobject /* object */,
  sLeAudioClientInterface->SetInCall(inCall);
}

static void setUnicastMonitorModeNative(JNIEnv* /* env */, jobject /* object */,
                                        jint direction, jboolean enable) {
  std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
  if (!sLeAudioClientInterface) {
    LOG(ERROR) << __func__ << ": Failed to get the Bluetooth LeAudio Interface";
    return;
  }

  sLeAudioClientInterface->SetUnicastMonitorMode(direction, enable);
}

static void sendAudioProfilePreferencesNative(
    JNIEnv* /* env */, jint groupId, jboolean isOutputPreferenceLeAudio,
    jboolean isDuplexPreferenceLeAudio) {
@@ -1548,6 +1574,8 @@ int register_com_android_bluetooth_le_audio(JNIEnv* env) {
       (void*)setCodecConfigPreferenceNative},
      {"setCcidInformationNative", "(II)V", (void*)setCcidInformationNative},
      {"setInCallNative", "(Z)V", (void*)setInCallNative},
      {"setUnicastMonitorModeNative", "(IZ)V",
       (void*)setUnicastMonitorModeNative},
      {"sendAudioProfilePreferencesNative", "(IZZ)V",
       (void*)sendAudioProfilePreferencesNative},
  };
@@ -1582,6 +1610,8 @@ int register_com_android_bluetooth_le_audio(JNIEnv* env) {
       &method_onHealthBasedRecommendationAction},
      {"onHealthBasedGroupRecommendationAction", "(II)V",
       &method_onHealthBasedGroupRecommendationAction},
      {"onUnicastMonitorModeStatus", "(II)V",
       &method_onUnicastMonitorModeStatus},
  };
  GET_JAVA_METHODS(env, "com/android/bluetooth/le_audio/LeAudioNativeInterface",
                   javaMethods);
+30 −0
Original line number Diff line number Diff line
@@ -258,6 +258,20 @@ public class LeAudioNativeInterface {
        }
        sendMessageToService(event);
    }

    @VisibleForTesting
    void onUnicastMonitorModeStatus(int direction, int status) {
        LeAudioStackEvent event =
                new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_UNICAST_MONITOR_MODE_STATUS);
        event.valueInt1 = direction;
        event.valueInt2 = status;

        if (DBG) {
            Log.d(TAG, "onUnicastMonitorModeStatus: " + event);
        }
        sendMessageToService(event);
    }

    /**
     * Initializes the native interface.
     *
@@ -366,6 +380,20 @@ public class LeAudioNativeInterface {
        setInCallNative(inCall);
    }

    /**
     * Set unicast monitor mode flag.
     *
     * @param direction direction for which monitor mode should be used
     * @param enable true when LE Audio device should be listening for streaming status
     *     on direction stream. false otherwise
     */
    public void setUnicastMonitorMode(int direction, boolean enable) {
        if (DBG) {
            Log.d(TAG, "setUnicastMonitorMode enable: " + enable + ", direction : " + direction);
        }
        setUnicastMonitorModeNative(direction, enable);
    }

    /**
     * Sends the audio preferences for the groupId to the native stack.
     *
@@ -398,6 +426,8 @@ public class LeAudioNativeInterface {
            BluetoothLeAudioCodecConfig outputCodecConfig);
    private native void setCcidInformationNative(int ccid, int contextType);
    private native void setInCallNative(boolean inCall);

    private native void setUnicastMonitorModeNative(int direction, boolean enable);
    /*package*/
    private native void sendAudioProfilePreferencesNative(int groupId,
            boolean isOutputPreferenceLeAudio, boolean isDuplexPreferenceLeAudio);
+35 −1
Original line number Diff line number Diff line
@@ -40,8 +40,9 @@ public class LeAudioStackEvent {
    public static final int EVENT_TYPE_NATIVE_INITIALIZED = 9;
    public static final int EVENT_TYPE_HEALTH_BASED_DEV_RECOMMENDATION = 10;
    public static final int EVENT_TYPE_HEALTH_BASED_GROUP_RECOMMENDATION = 11;
    public static final int EVENT_TYPE_UNICAST_MONITOR_MODE_STATUS = 12;
    // -------- DO NOT PUT ANY NEW UNICAST EVENTS BELOW THIS LINE-------------
    public static final int EVENT_TYPE_UNICAST_MAX = 12;
    public static final int EVENT_TYPE_UNICAST_MAX = 13;

    // Broadcast related events
    public static final int EVENT_TYPE_BROADCAST_CREATED = EVENT_TYPE_UNICAST_MAX + 1;
@@ -77,6 +78,17 @@ public class LeAudioStackEvent {
    static final int BROADCAST_STATE_STOPPING = 3;
    static final int BROADCAST_STATE_STREAMING = 4;

    // Do not modify without updating the HAL bt_le_audio.h files.
    // Match up with UnicastMonitorModeStatus enum of bt_le_audio.h
    static final int STATUS_LOCAL_STREAM_REQUESTED = 0;
    static final int STATUS_LOCAL_STREAM_STREAMING = 1;
    static final int STATUS_LOCAL_STREAM_SUSPENDED = 2;

    // Do not modify without updating le_audio_types.h
    // Match up with defines of le_audio_types.h
    static final int DIRECTION_SINK = 1;
    static final int DIRECTION_SOURCE = 2;

    public int type = EVENT_TYPE_NONE;
    public BluetoothDevice device;
    public int valueInt1 = 0;
@@ -170,6 +182,8 @@ public class LeAudioStackEvent {
                return "EVENT_TYPE_HEALTH_BASED_DEV_RECOMMENDATION";
            case EVENT_TYPE_HEALTH_BASED_GROUP_RECOMMENDATION:
                return "EVENT_TYPE_HEALTH_BASED_GROUP_RECOMMENDATION";
            case EVENT_TYPE_UNICAST_MONITOR_MODE_STATUS:
                return "EVENT_TYPE_UNICAST_MONITOR_MODE_STATUS";
            default:
                return "EVENT_TYPE_UNKNOWN:" + type;
        }
@@ -223,6 +237,15 @@ public class LeAudioStackEvent {
                    default:
                        return "UNKNOWN";
                }
            case EVENT_TYPE_UNICAST_MONITOR_MODE_STATUS:
                switch (value) {
                    case DIRECTION_SINK:
                        return "DIRECTION_SINK";
                    case DIRECTION_SOURCE:
                        return "DIRECTION_SOURCE";
                    default:
                        return "UNKNOWN";
                }
            default:
                break;
        }
@@ -265,6 +288,17 @@ public class LeAudioStackEvent {
                    default:
                        return "UNKNOWN";
                }
            case EVENT_TYPE_UNICAST_MONITOR_MODE_STATUS:
                switch (value) {
                    case STATUS_LOCAL_STREAM_REQUESTED:
                        return "STATUS_LOCAL_STREAM_REQUESTED";
                    case STATUS_LOCAL_STREAM_STREAMING:
                        return "STATUS_LOCAL_STREAM_STREAMING";
                    case STATUS_LOCAL_STREAM_SUSPENDED:
                        return "STATUS_LOCAL_STREAM_SUSPENDED";
                    default:
                        return "UNKNOWN";
                }
            default:
                break;
        }
+1 −0
Original line number Diff line number Diff line
@@ -65,6 +65,7 @@ class LeAudioClient {
  virtual void SetInCall(bool in_call) = 0;
  virtual bool IsInCall() = 0;
  virtual void SetInVoipCall(bool in_call) = 0;
  virtual void SetUnicastMonitorMode(uint8_t direction, bool enable) = 0;
  virtual bool IsInVoipCall() = 0;
  virtual void SendAudioProfilePreferences(
      const int group_id, bool is_output_preference_le_audio,
+81 −3
Original line number Diff line number Diff line
@@ -72,6 +72,7 @@ using bluetooth::le_audio::GroupNodeStatus;
using bluetooth::le_audio::GroupStatus;
using bluetooth::le_audio::GroupStreamStatus;
using bluetooth::le_audio::LeAudioHealthBasedAction;
using bluetooth::le_audio::UnicastMonitorModeStatus;
using le_audio::CodecManager;
using le_audio::ContentControlIdKeeper;
using le_audio::DeviceConnectState;
@@ -233,6 +234,8 @@ class LeAudioClientImpl : public LeAudioClient {
        audio_sender_state_(AudioState::IDLE),
        in_call_(false),
        in_voip_call_(false),
        sink_monitor_mode_(false),
        sink_monitor_notified_status_(std::nullopt),
        current_source_codec_config({0, 0, 0, 0}),
        current_sink_codec_config({0, 0, 0, 0}),
        le_audio_source_hal_client_(nullptr),
@@ -1023,6 +1026,31 @@ class LeAudioClientImpl : public LeAudioClient {

  bool IsInVoipCall() override { return in_voip_call_; }

  void SetUnicastMonitorMode(uint8_t direction, bool enable) override {
    if (!IS_FLAG_ENABLED(leaudio_broadcast_audio_handover_policies)) {
      LOG_WARN("Monitor mode is disabled, Set Unicast Monitor mode is ignored");
      return;
    }

    if (direction == le_audio::types::kLeAudioDirectionSink) {
      /* Cleanup Sink HAL client interface if listening mode is toggled off
       * before group activation (active group context would take care of
       * Sink HAL client cleanup).
       */
      if (sink_monitor_mode_ && !enable && le_audio_sink_hal_client_ &&
          active_group_id_ == bluetooth::groups::kGroupUnknown) {
        local_metadata_context_types_.sink.clear();
        le_audio_sink_hal_client_->Stop();
        le_audio_sink_hal_client_.reset();
      }

      LOG_DEBUG("enable: %d", enable);
      sink_monitor_mode_ = enable;
    } else {
      LOG_ERROR("invalid direction: 0x%02x monitor mode set", direction);
    }
  }

  void SendAudioProfilePreferences(
      const int group_id, bool is_output_preference_le_audio,
      bool is_duplex_preference_le_audio) override {
@@ -1137,6 +1165,7 @@ class LeAudioClientImpl : public LeAudioClient {
    }
    auto group_id_to_close = active_group_id_;
    active_group_id_ = bluetooth::groups::kGroupUnknown;
    sink_monitor_notified_status_ = std::nullopt;

    LOG_INFO("Group id: %d", group_id_to_close);
    if (alarm_is_scheduled(suspend_timeout_)) alarm_cancel(suspend_timeout_);
@@ -1242,6 +1271,8 @@ class LeAudioClientImpl : public LeAudioClient {
      callbacks_->OnGroupStatus(previous_active_group, GroupStatus::INACTIVE);
    }

    /* Reset sink listener notified status */
    sink_monitor_notified_status_ = std::nullopt;
    callbacks_->OnGroupStatus(active_group_id_, GroupStatus::ACTIVE);
    SendAudioGroupSelectableCodecConfigChanged(group);
  }
@@ -3745,6 +3776,12 @@ class LeAudioClientImpl : public LeAudioClient {
    dprintf(fd, "  local sink metadata context type mask: %s\n",
            local_metadata_context_types_.sink.to_string().c_str());
    dprintf(fd, "  TBS state: %s\n", in_call_ ? " In call" : "No calls");
    dprintf(fd, "  Sink listening mode: %s\n",
            sink_monitor_mode_ ? "true" : "false");
    if (sink_monitor_notified_status_) {
      dprintf(fd, "  Local sink notified state: %d\n",
              sink_monitor_notified_status_.value());
    }
    dprintf(fd, "  Start time: ");
    for (auto t : stream_start_history_queue_) {
      dprintf(fd, ", %d ms", static_cast<int>(t));
@@ -3769,7 +3806,13 @@ class LeAudioClientImpl : public LeAudioClient {
    if (active_group_id_ != bluetooth::groups::kGroupUnknown) {
      /* Bluetooth turned off while streaming */
      StopAudio();
      SetUnicastMonitorMode(le_audio::types::kLeAudioDirectionSink, false);
      ClientAudioInterfaceRelease();
    } else {
      /* There may be not stopped Sink HAL client due to set Listening mode */
      if (sink_monitor_mode_) {
        SetUnicastMonitorMode(le_audio::types::kLeAudioDirectionSink, false);
      }
    }
    groupStateMachine_->Cleanup();
    aseGroups_.Cleanup();
@@ -4221,6 +4264,16 @@ class LeAudioClientImpl : public LeAudioClient {
        .has_value();
  }

  void notifyAudioLocalSink(UnicastMonitorModeStatus status) {
    if (sink_monitor_notified_status_ != status) {
      LOG_INFO("Stram monitoring status changed to: %d",
               static_cast<int>(status));
      sink_monitor_notified_status_ = status;
      callbacks_->OnUnicastMonitorModeStatus(
          le_audio::types::kLeAudioDirectionSink, status);
    }
  }

  void OnLocalAudioSinkResume() {
    LOG_INFO(
        "active group_id: %d IN: audio_receiver_state_: %s, "
@@ -4233,6 +4286,14 @@ class LeAudioClientImpl : public LeAudioClient {
        "r_state: " + ToString(audio_receiver_state_) +
            ", s_state: " + ToString(audio_sender_state_));

    if (active_group_id_ == bluetooth::groups::kGroupUnknown) {
      if (sink_monitor_mode_ && !sink_monitor_notified_status_) {
        notifyAudioLocalSink(UnicastMonitorModeStatus::STREAMING_REQUESTED);
      }
      CancelLocalAudioSinkStreamingRequest();
      return;
    }

    /* Stop the VBC close watchdog if needed */
    StopVbcCloseTimeout();

@@ -5463,6 +5524,12 @@ class LeAudioClientImpl : public LeAudioClient {
            LOG_INFO("Clear pending configuration flag for group %d",
                    group->group_id_);
            group->ClearPendingConfiguration();
          } else {
            if (sink_monitor_mode_) {
              callbacks_->OnUnicastMonitorModeStatus(
                  le_audio::types::kLeAudioDirectionSink,
                  UnicastMonitorModeStatus::STREAMING_SUSPENDED);
            }
          }
        }

@@ -5537,6 +5604,10 @@ class LeAudioClientImpl : public LeAudioClient {
  /* Keep in call state. */
  bool in_call_;
  bool in_voip_call_;
  /* Listen for streaming status on Sink stream */
  bool sink_monitor_mode_;
  /* Status which has been notified to Service */
  std::optional<UnicastMonitorModeStatus> sink_monitor_notified_status_;

  /* Reconnection mode */
  tBTM_BLE_CONN_TYPE reconnection_mode_;
@@ -5602,12 +5673,19 @@ class LeAudioClientImpl : public LeAudioClient {
      le_audio_source_hal_client_->Stop();
      le_audio_source_hal_client_.reset();
    }
    local_metadata_context_types_.sink.clear();

    if (le_audio_sink_hal_client_) {
      /* Keep session set up to monitor streaming request. This is required if
       * there is another LE Audio device streaming (e.g. Broadcast) and via
       * the session callbacks special action from this Module would be
       * required e.g. to Unicast handover.
       */
      if (!sink_monitor_mode_) {
        local_metadata_context_types_.sink.clear();
        le_audio_sink_hal_client_->Stop();
        le_audio_sink_hal_client_.reset();
      }
    }
    local_metadata_context_types_.source.clear();
    configuration_context_type_ = LeAudioContextType::UNINITIALIZED;

Loading