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

Commit 03c4b80e authored by Jakub Tyszkowski's avatar Jakub Tyszkowski
Browse files

broadcaster: Refactor handling broadcast ID

This patch is another step to properly align the Java API
with the native layer implementation.

This change makes use of the broadcast ID in the native
layer API in place of the vague instance ID, to seamlesly
match the Java API and simplify the native layer API and avoid
any translations between the two. Previously used instance ID
(after the advertising instance identifier) is now only used
when talking to the advertiser module but is no longer exposed
to the upper layers, where only broadcast ID exists.

This also fixes the following error that was caused by the broadcast
ID being not yet known to the Java layer at the time broadcast is created:
  LeAudioService  D  Broadcast Instance id: 15740086 paused.
  LeAudioService  E  Unknown Broadcast ID for broadcast instance: 15740086

Bug: 150670922
Tag: #feature
Test: atest BluetoothInstrumentationTests bluetooth_test_broadcaster_sm bluetooth_test_broadcaster
Sponsor: jpawlowski@
Change-Id: Ie524da6fd560bc20ed1eab4fea5035cedbe18f5c
parent 504169f6
Loading
Loading
Loading
Loading
+17 −53
Original line number Diff line number Diff line
@@ -493,7 +493,6 @@ static JNINativeMethod sMethods[] = {
static jmethodID method_onBroadcastCreated;
static jmethodID method_onBroadcastDestroyed;
static jmethodID method_onBroadcastStateChanged;
static jmethodID method_onBroadcastId;

static LeAudioBroadcasterInterface* sLeAudioBroadcasterInterface = nullptr;
static std::shared_timed_mutex sBroadcasterInterfaceMutex;
@@ -505,7 +504,7 @@ class LeAudioBroadcasterCallbacksImpl : public LeAudioBroadcasterCallbacks {
 public:
  ~LeAudioBroadcasterCallbacksImpl() = default;

  void OnBroadcastCreated(uint8_t instance_id, bool success) override {
  void OnBroadcastCreated(uint32_t broadcast_id, bool success) override {
    LOG(INFO) << __func__;

    std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterCallbacksMutex);
@@ -513,11 +512,11 @@ class LeAudioBroadcasterCallbacksImpl : public LeAudioBroadcasterCallbacks {

    if (!sCallbackEnv.valid() || sBroadcasterCallbacksObj == nullptr) return;
    sCallbackEnv->CallVoidMethod(sBroadcasterCallbacksObj,
                                 method_onBroadcastCreated, (jint)instance_id,
                                 method_onBroadcastCreated, (jint)broadcast_id,
                                 success ? JNI_TRUE : JNI_FALSE);
  }

  void OnBroadcastDestroyed(uint8_t instance_id) override {
  void OnBroadcastDestroyed(uint32_t broadcast_id) override {
    LOG(INFO) << __func__;

    std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterCallbacksMutex);
@@ -526,10 +525,10 @@ class LeAudioBroadcasterCallbacksImpl : public LeAudioBroadcasterCallbacks {
    if (!sCallbackEnv.valid() || sBroadcasterCallbacksObj == nullptr) return;
    sCallbackEnv->CallVoidMethod(sBroadcasterCallbacksObj,
                                 method_onBroadcastDestroyed,
                                 (jint)instance_id);
                                 (jint)broadcast_id);
  }

  void OnBroadcastStateChanged(uint8_t instance_id,
  void OnBroadcastStateChanged(uint32_t broadcast_id,
                               BroadcastState state) override {
    LOG(INFO) << __func__;

@@ -539,35 +538,9 @@ class LeAudioBroadcasterCallbacksImpl : public LeAudioBroadcasterCallbacks {
    if (!sCallbackEnv.valid() || sBroadcasterCallbacksObj == nullptr) return;
    sCallbackEnv->CallVoidMethod(
        sBroadcasterCallbacksObj, method_onBroadcastStateChanged,
        (jint)instance_id,
        (jint)broadcast_id,
        (jint) static_cast<std::underlying_type<BroadcastState>::type>(state));
  }

  void OnBroadcastId(uint8_t instance_id,
                     const BroadcastId& broadcast_id) override {
    LOG(INFO) << __func__;

    std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterCallbacksMutex);
    CallbackEnv sCallbackEnv(__func__);

    // broadcast_id
    int field_size = broadcast_id.size();
    ScopedLocalRef<jbyteArray> serialized_broadcast_id(
        sCallbackEnv.get(), sCallbackEnv->NewByteArray(field_size));
    if (!serialized_broadcast_id.get()) {
      LOG(ERROR) << "Failed to allocate new jbyteArray broadcast_id for the "
                    "announcement";
      return;
    }

    sCallbackEnv->SetByteArrayRegion(serialized_broadcast_id.get(), 0,
                                     field_size, (jbyte*)broadcast_id.data());

    if (!sCallbackEnv.valid() || sBroadcasterCallbacksObj == nullptr) return;
    sCallbackEnv->CallVoidMethod(sBroadcasterCallbacksObj, method_onBroadcastId,
                                 (jint)instance_id,
                                 serialized_broadcast_id.get());
  }
};

static LeAudioBroadcasterCallbacksImpl sLeAudioBroadcasterCallbacks;
@@ -579,7 +552,6 @@ static void BroadcasterClassInitNative(JNIEnv* env, jclass clazz) {
      env->GetMethodID(clazz, "onBroadcastDestroyed", "(I)V");
  method_onBroadcastStateChanged =
      env->GetMethodID(clazz, "onBroadcastStateChanged", "(II)V");
  method_onBroadcastId = env->GetMethodID(clazz, "onBroadcastId", "(I[B)V");
}

static void BroadcasterInitNative(JNIEnv* env, jobject object) {
@@ -674,52 +646,45 @@ static void CreateBroadcastNative(JNIEnv* env, jobject object,
  env->ReleaseByteArrayElements(metadata, meta, 0);
}

static void UpdateMetadataNative(JNIEnv* env, jobject object, jint instance_id,
static void UpdateMetadataNative(JNIEnv* env, jobject object, jint broadcast_id,
                                 jbyteArray metadata) {
  jbyte* meta = env->GetByteArrayElements(metadata, nullptr);
  sLeAudioBroadcasterInterface->UpdateMetadata(
      instance_id,
      broadcast_id,
      std::vector<uint8_t>(meta, meta + env->GetArrayLength(metadata)));
  env->ReleaseByteArrayElements(metadata, meta, 0);
}

static void StartBroadcastNative(JNIEnv* env, jobject object,
                                 jint instance_id) {
                                 jint broadcast_id) {
  LOG(INFO) << __func__;
  std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterInterfaceMutex);
  if (!sLeAudioBroadcasterInterface) return;
  sLeAudioBroadcasterInterface->StartBroadcast(instance_id);
  sLeAudioBroadcasterInterface->StartBroadcast(broadcast_id);
}

static void StopBroadcastNative(JNIEnv* env, jobject object, jint instance_id) {
static void StopBroadcastNative(JNIEnv* env, jobject object,
                                jint broadcast_id) {
  LOG(INFO) << __func__;
  std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterInterfaceMutex);
  if (!sLeAudioBroadcasterInterface) return;
  sLeAudioBroadcasterInterface->StopBroadcast(instance_id);
  sLeAudioBroadcasterInterface->StopBroadcast(broadcast_id);
}

static void PauseBroadcastNative(JNIEnv* env, jobject object,
                                 jint instance_id) {
                                 jint broadcast_id) {
  LOG(INFO) << __func__;
  std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterInterfaceMutex);
  if (!sLeAudioBroadcasterInterface) return;
  sLeAudioBroadcasterInterface->PauseBroadcast(instance_id);
  sLeAudioBroadcasterInterface->PauseBroadcast(broadcast_id);
}

static void DestroyBroadcastNative(JNIEnv* env, jobject object,
                                   jint instance_id) {
  LOG(INFO) << __func__;
  std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterInterfaceMutex);
  if (!sLeAudioBroadcasterInterface) return;
  sLeAudioBroadcasterInterface->DestroyBroadcast(instance_id);
}

static void GetBroadcastIdNative(JNIEnv* env, jobject object,
                                 jint instance_id) {
                                   jint broadcast_id) {
  LOG(INFO) << __func__;
  std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterInterfaceMutex);
  if (!sLeAudioBroadcasterInterface) return;
  sLeAudioBroadcasterInterface->GetBroadcastId(instance_id);
  sLeAudioBroadcasterInterface->DestroyBroadcast(broadcast_id);
}

static void GetAllBroadcastStatesNative(JNIEnv* env, jobject object) {
@@ -740,7 +705,6 @@ static JNINativeMethod sBroadcasterMethods[] = {
    {"stopBroadcastNative", "(I)V", (void*)StopBroadcastNative},
    {"pauseBroadcastNative", "(I)V", (void*)PauseBroadcastNative},
    {"destroyBroadcastNative", "(I)V", (void*)DestroyBroadcastNative},
    {"getBroadcastIdNative", "(I)V", (void*)GetBroadcastIdNative},
    {"getAllBroadcastStatesNative", "()V", (void*)GetAllBroadcastStatesNative},
};

+29 −52
Original line number Diff line number Diff line
@@ -81,34 +81,34 @@ public class LeAudioBroadcasterNativeInterface {

    // Callbacks from the native stack back into the Java framework.
    @VisibleForTesting
    public void onBroadcastCreated(int instanceId, boolean success) {
    public void onBroadcastCreated(int broadcastId, boolean success) {
        if (DBG) {
            Log.d(TAG, "onBroadcastCreated: instanceId=" + instanceId);
            Log.d(TAG, "onBroadcastCreated: broadcastId=" + broadcastId);
        }
        LeAudioStackEvent event =
                new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_BROADCAST_CREATED);

        event.valueInt1 = instanceId;
        event.valueInt1 = broadcastId;
        event.valueBool1 = success;
        sendMessageToService(event);
    }

    @VisibleForTesting
    public void onBroadcastDestroyed(int instanceId) {
    public void onBroadcastDestroyed(int broadcastId) {
        if (DBG) {
            Log.d(TAG, "onBroadcastDestroyed: instanceId=" + instanceId);
            Log.d(TAG, "onBroadcastDestroyed: broadcastId=" + broadcastId);
        }
        LeAudioStackEvent event =
                new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_BROADCAST_DESTROYED);

        event.valueInt1 = instanceId;
        event.valueInt1 = broadcastId;
        sendMessageToService(event);
    }

    @VisibleForTesting
    public void onBroadcastStateChanged(int instanceId, int state) {
    public void onBroadcastStateChanged(int broadcastId, int state) {
        if (DBG) {
            Log.d(TAG, "onBroadcastStateChanged: instanceId=" + instanceId + " state=" + state);
            Log.d(TAG, "onBroadcastStateChanged: broadcastId=" + broadcastId + " state=" + state);
        }
        LeAudioStackEvent event =
                new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_BROADCAST_STATE);
@@ -120,23 +120,11 @@ public class LeAudioBroadcasterNativeInterface {
         * For now it's only important that this device is a Bluetooth device.
         */
        event.device = getDevice(Utils.getBytesFromAddress("FF:FF:FF:FF:FF:FF"));
        event.valueInt1 = instanceId;
        event.valueInt1 = broadcastId;
        event.valueInt2 = state;
        sendMessageToService(event);
    }

    @VisibleForTesting
    public void onBroadcastId(int instanceId, byte[] broadcastId) {
        LeAudioStackEvent event =
                new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_BROADCAST_ID);
        event.valueInt1 = instanceId;
        event.valueByte1 = broadcastId;
        if (DBG) {
            Log.d(TAG, "onBroadcastId: " + event);
        }
        sendMessageToService(event);
    }

    /**
     * Initializes the native interface.
     *
@@ -178,62 +166,52 @@ public class LeAudioBroadcasterNativeInterface {
    /**
     * Update LeAudio Broadcast instance metadata.
     *
     * @param instanceId broadcast instance identifier
     * @param broadcastId broadcast instance identifier
     * @param metadata metadata buffer with TLVs
     */
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    public void updateMetadata(int instanceId, byte[] metadata) {
        updateMetadataNative(instanceId, metadata);
    public void updateMetadata(int broadcastId, byte[] metadata) {
        updateMetadataNative(broadcastId, metadata);
    }

    /**
     * Start LeAudio Broadcast instance.
     *
     * @param instanceId broadcast instance identifier
     * @param broadcastId broadcast instance identifier
     */
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    public void startBroadcast(int instanceId) {
        startBroadcastNative(instanceId);
    public void startBroadcast(int broadcastId) {
        startBroadcastNative(broadcastId);
    }

    /**
     * Stop LeAudio Broadcast instance.
     *
     * @param instanceId broadcast instance identifier
     * @param broadcastId broadcast instance identifier
     */
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    public void stopBroadcast(int instanceId) {
        stopBroadcastNative(instanceId);
    public void stopBroadcast(int broadcastId) {
        stopBroadcastNative(broadcastId);
    }

    /**
     * Pause LeAudio Broadcast instance.
     *
     * @param instanceId broadcast instance identifier
     * @param broadcastId broadcast instance identifier
     */
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    public void pauseBroadcast(int instanceId) {
        pauseBroadcastNative(instanceId);
    public void pauseBroadcast(int broadcastId) {
        pauseBroadcastNative(broadcastId);
    }

    /**
     * Destroy LeAudio Broadcast instance.
     *
     * @param instanceId broadcast instance identifier
     */
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    public void destroyBroadcast(int instanceId) {
        destroyBroadcastNative(instanceId);
    }

    /**
     * Get LeAudio Broadcast instance advertising address.
     *
     * @param instanceId broadcast instance identifier
     * @param broadcastId broadcast instance identifier
     */
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    public void getBroadcastId(int instanceId) {
        getBroadcastIdNative(instanceId);
    public void destroyBroadcast(int broadcastId) {
        destroyBroadcastNative(broadcastId);
    }

    /**
@@ -250,11 +228,10 @@ public class LeAudioBroadcasterNativeInterface {
    private native void stopNative();
    private native void cleanupNative();
    private native void createBroadcastNative(byte[] metadata, int profile, byte[] broadcastCode);
    private native void updateMetadataNative(int instanceId, byte[] metadata);
    private native void startBroadcastNative(int instanceId);
    private native void stopBroadcastNative(int instanceId);
    private native void pauseBroadcastNative(int instanceId);
    private native void destroyBroadcastNative(int instanceId);
    private native void getBroadcastIdNative(int instanceId);
    private native void updateMetadataNative(int broadcastId, byte[] metadata);
    private native void startBroadcastNative(int broadcastId);
    private native void stopBroadcastNative(int broadcastId);
    private native void pauseBroadcastNative(int broadcastId);
    private native void destroyBroadcastNative(int broadcastId);
    private native void getAllBroadcastStatesNative();
}
+51 −141

File changed.

Preview size limit exceeded, changes collapsed.

+3 −35
Original line number Diff line number Diff line
@@ -42,7 +42,6 @@ public class LeAudioStackEvent {
    public static final int EVENT_TYPE_BROADCAST_CREATED = EVENT_TYPE_UNICAST_MAX + 1;
    public static final int EVENT_TYPE_BROADCAST_DESTROYED = EVENT_TYPE_UNICAST_MAX + 2;
    public static final int EVENT_TYPE_BROADCAST_STATE = EVENT_TYPE_UNICAST_MAX + 3;
    public static final int EVENT_TYPE_BROADCAST_ID = EVENT_TYPE_UNICAST_MAX + 4;

    // Do not modify without updating the HAL bt_le_audio.h files.
    // Match up with GroupStatus enum of bt_le_audio.h
@@ -73,7 +72,6 @@ public class LeAudioStackEvent {
    public int valueInt4 = 0;
    public int valueInt5 = 0;
    public boolean valueBool1 = false;
    public byte[] valueByte1;
    public BluetoothLeAudioCodecConfig valueCodec1;
    public BluetoothLeAudioCodecConfig valueCodec2;
    public List<BluetoothLeAudioCodecConfig> valueCodecList1;
@@ -101,7 +99,6 @@ public class LeAudioStackEvent {
                + eventTypeValueCodecList1ToString(type, valueCodecList1));
        result.append(", valueCodecList2:"
                + eventTypeValueCodecList2ToString(type, valueCodecList2));
        result.append(", " + eventTypeValueByte1ToString(type, valueByte1));
        result.append("}");
        return result.toString();
    }
@@ -126,8 +123,6 @@ public class LeAudioStackEvent {
                return "EVENT_TYPE_BROADCAST_DESTROYED";
            case EVENT_TYPE_BROADCAST_STATE:
                return "EVENT_TYPE_BROADCAST_STATE";
            case EVENT_TYPE_BROADCAST_ID:
                return "EVENT_TYPE_BROADCAST_ID";
            case EVENT_TYPE_AUDIO_LOCAL_CODEC_CONFIG_CAPA_CHANGED:
                return "EVENT_TYPE_AUDIO_LOCAL_CODEC_CONFIG_CAPA_CHANGED";
            case EVENT_TYPE_AUDIO_GROUP_CODEC_CONFIG_CHANGED:
@@ -164,13 +159,11 @@ public class LeAudioStackEvent {
            case EVENT_TYPE_SINK_AUDIO_LOCATION_AVAILABLE:
                return "{sink_audio_location:" + value + "}";
            case EVENT_TYPE_BROADCAST_CREATED:
                return "{instance_id:" + value + "}";
                return "{broadcastId:" + value + "}";
            case EVENT_TYPE_BROADCAST_DESTROYED:
                return "{instance_id:" + value + "}";
                return "{broadcastId:" + value + "}";
            case EVENT_TYPE_BROADCAST_STATE:
                return "{instance_id:" + value + "}";
            case EVENT_TYPE_BROADCAST_ID:
                return "{instance_id:" + value + "}";
                return "{broadcastId:" + value + "}";
            default:
                break;
        }
@@ -202,8 +195,6 @@ public class LeAudioStackEvent {
                return "{group_id:" + Integer.toString(value) + "}";
            case EVENT_TYPE_BROADCAST_STATE:
                return "{state:" + broadcastStateToString(value) + "}";
            case EVENT_TYPE_BROADCAST_ID:
                return "{addr_type:" + addrTypeToString(value) + "}";
            default:
                break;
        }
@@ -242,18 +233,6 @@ public class LeAudioStackEvent {
        return Integer.toString(value);
    }

    private static String eventTypeValueByte1ToString(int type, byte[] value) {
        switch (type) {
            case EVENT_TYPE_BROADCAST_ID:
                if (value == null) {
                    return "empty";
                }
                return "broadcast_id: [" + encodeHexString(value) + "]";
            default:
                return "<unused>";
        }
    }

    private static String eventTypeValueBool1ToString(int type, boolean value) {
        switch (type) {
            case EVENT_TYPE_BROADCAST_CREATED:
@@ -324,17 +303,6 @@ public class LeAudioStackEvent {
        }
    }

    private static String addrTypeToString(int value) {
        switch (value) {
            case 0:
                return "Static";
            case 1:
                return "Random";
            default:
                return "Unknown {" + value + "}";
        }
    }

    protected static String encodeHexString(byte[] pduData) {
        StringBuilder out = new StringBuilder(pduData.length * 2);
        for (int i = 0; i < pduData.length; i++) {
+7 −8
Original line number Diff line number Diff line
@@ -49,17 +49,16 @@ class LeAudioBroadcaster {
      std::vector<uint8_t> metadata, AudioProfile profile,
      std::optional<bluetooth::le_audio::BroadcastCode> broadcast_code =
          std::nullopt) = 0;
  virtual void SuspendAudioBroadcast(uint8_t instance_id) = 0;
  virtual void StartAudioBroadcast(uint8_t instance_id) = 0;
  virtual void StopAudioBroadcast(uint8_t instance_id) = 0;
  virtual void DestroyAudioBroadcast(uint8_t instance_id) = 0;
  virtual void GetBroadcastId(uint8_t instance_id) = 0;
  virtual void SuspendAudioBroadcast(uint32_t broadcast_id) = 0;
  virtual void StartAudioBroadcast(uint32_t broadcast_id) = 0;
  virtual void StopAudioBroadcast(uint32_t broadcast_id) = 0;
  virtual void DestroyAudioBroadcast(uint32_t broadcast_id) = 0;
  virtual void GetAllBroadcastStates(void) = 0;
  virtual void UpdateMetadata(uint8_t instance_id,
  virtual void UpdateMetadata(uint32_t broadcast_id,
                              std::vector<uint8_t> metadata) = 0;
  virtual void IsValidBroadcast(
      uint8_t instance_id, uint8_t addr_type, RawAddress addr,
      base::Callback<void(uint8_t /* instance_id */, uint8_t /* addr_type */,
      uint32_t broadcast_id, uint8_t addr_type, RawAddress addr,
      base::Callback<void(uint8_t /* broadcast_id */, uint8_t /* addr_type */,
                          RawAddress /* addr */, bool /* is_valid */)>
          cb) = 0;

Loading