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

Commit f373eebf authored by Łukasz Rymanowski's avatar Łukasz Rymanowski
Browse files

vc: Add AICS support

Initial support for the AICS

Bug: 291285174
Bug: 361263965
Test: atest bluetooth_vc_test VolumeControlNativeInterfaceTest
Flag: com.android.bluetooth.flags.leaudio_add_aics_support

Change-Id: I68dd438c03a68ffed51364a6d24737575717c41d
parent 353b6cdb
Loading
Loading
Loading
Loading
+336 −3
Original line number Diff line number Diff line
@@ -36,6 +36,11 @@ static jmethodID method_onDeviceAvailable;
static jmethodID method_onExtAudioOutVolumeOffsetChanged;
static jmethodID method_onExtAudioOutLocationChanged;
static jmethodID method_onExtAudioOutDescriptionChanged;
static jmethodID method_onExtAudioInStateChanged;
static jmethodID method_onExtAudioInStatusChanged;
static jmethodID method_onExtAudioInTypeChanged;
static jmethodID method_onExtAudioInGainPropsChanged;
static jmethodID method_onExtAudioInDescriptionChanged;

static VolumeControlInterface* sVolumeControlInterface = nullptr;
static std::shared_timed_mutex interface_mutex;
@@ -105,7 +110,8 @@ public:
                                 (jboolean)mute, group_id, (jboolean)isAutonomous);
  }

  void OnDeviceAvailable(const RawAddress& bd_addr, uint8_t num_offsets) override {
  void OnDeviceAvailable(const RawAddress& bd_addr, uint8_t num_offsets,
                         uint8_t num_inputs) override {
    log::info("");

    std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
@@ -124,7 +130,7 @@ public:
    sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
                                     reinterpret_cast<const jbyte*>(&bd_addr));
    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onDeviceAvailable, (jint)num_offsets,
                                 addr.get());
                                 (jint)num_inputs, addr.get());
  }

  void OnExtAudioOutVolumeOffsetChanged(const RawAddress& bd_addr, uint8_t ext_output_id,
@@ -200,6 +206,122 @@ public:
    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onExtAudioOutDescriptionChanged,
                                 (jint)ext_output_id, description, addr.get());
  }

  void OnExtAudioInStateChanged(const RawAddress& bd_addr, uint8_t ext_input_id, int8_t gain_val,
                                uint8_t gain_mode, bool mute) override {
    log::info("");

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

    ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(),
                                    sCallbackEnv->NewByteArray(sizeof(RawAddress)));
    if (!addr.get()) {
      log::error("Failed to get addr for {}", bd_addr);
      return;
    }

    sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
                                     reinterpret_cast<const jbyte*>(&bd_addr));
    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onExtAudioInStateChanged, (jint)ext_input_id,
                                 (jint)gain_val, (jint)gain_mode, (jboolean)mute, addr.get());
  }

  void OnExtAudioInStatusChanged(const RawAddress& bd_addr, uint8_t ext_input_id,
                                 bluetooth::vc::VolumeInputStatus status) override {
    log::info("");

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

    ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(),
                                    sCallbackEnv->NewByteArray(sizeof(RawAddress)));
    if (!addr.get()) {
      log::error("Failed to get addr for {}", bd_addr);
      return;
    }

    sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
                                     reinterpret_cast<const jbyte*>(&bd_addr));
    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onExtAudioInStatusChanged,
                                 (jint)ext_input_id, (jint)status, addr.get());
  }

  void OnExtAudioInTypeChanged(const RawAddress& bd_addr, uint8_t ext_input_id,
                               bluetooth::vc::VolumeInputType type) override {
    log::info("");

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

    ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(),
                                    sCallbackEnv->NewByteArray(sizeof(RawAddress)));
    if (!addr.get()) {
      log::error("Failed to get addr for {}", bd_addr);
      return;
    }

    sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
                                     reinterpret_cast<const jbyte*>(&bd_addr));
    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onExtAudioInTypeChanged, (jint)ext_input_id,
                                 (jint)type, addr.get());
  }

  void OnExtAudioInGainPropsChanged(const RawAddress& bd_addr, uint8_t ext_input_id, uint8_t unit,
                                    int8_t min, int8_t max) override {
    log::info("");

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

    ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(),
                                    sCallbackEnv->NewByteArray(sizeof(RawAddress)));
    if (!addr.get()) {
      log::error("Failed to get addr for {}", bd_addr);
      return;
    }

    sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
                                     reinterpret_cast<const jbyte*>(&bd_addr));
    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onExtAudioInGainPropsChanged,
                                 (jint)ext_input_id, (jint)unit, (jint)min, (jint)max, addr.get());
  }

  void OnExtAudioInDescriptionChanged(const RawAddress& bd_addr, uint8_t ext_input_id,
                                      std::string descr) override {
    log::info("");

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

    ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(),
                                    sCallbackEnv->NewByteArray(sizeof(RawAddress)));
    if (!addr.get()) {
      log::error("Failed to get addr for {}", bd_addr);
      return;
    }

    sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
                                     reinterpret_cast<const jbyte*>(&bd_addr));
    jstring description = sCallbackEnv->NewStringUTF(descr.c_str());
    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onExtAudioInDescriptionChanged,
                                 (jint)ext_input_id, description, addr.get());
  }
};

static VolumeControlCallbacksImpl sVolumeControlCallbacks;
@@ -514,6 +636,195 @@ static jboolean setExtAudioOutDescriptionNative(JNIEnv* env, jobject /* object *
  return JNI_TRUE;
}

/* Native methods for external audio inputs */
static jboolean getExtAudioInStateNative(JNIEnv* env, jobject /* object */, jbyteArray address,
                                         jint ext_input_id) {
  log::info("");
  std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
  if (!sVolumeControlInterface) {
    return JNI_FALSE;
  }

  jbyte* addr = env->GetByteArrayElements(address, nullptr);
  if (!addr) {
    jniThrowIOException(env, EINVAL);
    return JNI_FALSE;
  }

  RawAddress* tmpraw = reinterpret_cast<RawAddress*>(addr);
  sVolumeControlInterface->GetExtAudioInState(*tmpraw, ext_input_id);
  env->ReleaseByteArrayElements(address, addr, 0);
  return JNI_TRUE;
}

static jboolean getExtAudioInStatusNative(JNIEnv* env, jobject /* object */, jbyteArray address,
                                          jint ext_input_id) {
  log::info("");
  std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
  if (!sVolumeControlInterface) {
    return JNI_FALSE;
  }

  jbyte* addr = env->GetByteArrayElements(address, nullptr);
  if (!addr) {
    jniThrowIOException(env, EINVAL);
    return JNI_FALSE;
  }

  RawAddress* tmpraw = reinterpret_cast<RawAddress*>(addr);
  sVolumeControlInterface->GetExtAudioInStatus(*tmpraw, ext_input_id);
  env->ReleaseByteArrayElements(address, addr, 0);
  return JNI_TRUE;
}

static jboolean getExtAudioInTypeNative(JNIEnv* env, jobject /* object */, jbyteArray address,
                                        jint ext_input_id) {
  log::info("");
  std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
  if (!sVolumeControlInterface) {
    return JNI_FALSE;
  }

  jbyte* addr = env->GetByteArrayElements(address, nullptr);
  if (!addr) {
    jniThrowIOException(env, EINVAL);
    return JNI_FALSE;
  }

  RawAddress* tmpraw = reinterpret_cast<RawAddress*>(addr);
  sVolumeControlInterface->GetExtAudioInType(*tmpraw, ext_input_id);
  env->ReleaseByteArrayElements(address, addr, 0);
  return JNI_TRUE;
}

static jboolean getExtAudioInGainPropsNative(JNIEnv* env, jobject /* object */, jbyteArray address,
                                             jint ext_input_id) {
  log::info("");
  std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
  if (!sVolumeControlInterface) {
    return JNI_FALSE;
  }

  jbyte* addr = env->GetByteArrayElements(address, nullptr);
  if (!addr) {
    jniThrowIOException(env, EINVAL);
    return JNI_FALSE;
  }

  RawAddress* tmpraw = reinterpret_cast<RawAddress*>(addr);
  sVolumeControlInterface->GetExtAudioInGainProps(*tmpraw, ext_input_id);
  env->ReleaseByteArrayElements(address, addr, 0);
  return JNI_TRUE;
}

static jboolean getExtAudioInDescriptionNative(JNIEnv* env, jobject /* object */,
                                               jbyteArray address, jint ext_input_id) {
  log::info("");
  std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
  if (!sVolumeControlInterface) {
    return JNI_FALSE;
  }

  jbyte* addr = env->GetByteArrayElements(address, nullptr);
  if (!addr) {
    jniThrowIOException(env, EINVAL);
    return JNI_FALSE;
  }

  RawAddress* tmpraw = reinterpret_cast<RawAddress*>(addr);
  sVolumeControlInterface->GetExtAudioInDescription(*tmpraw, ext_input_id);
  env->ReleaseByteArrayElements(address, addr, 0);
  return JNI_TRUE;
}

static jboolean setExtAudioInDescriptionNative(JNIEnv* env, jobject /* object */,
                                               jbyteArray address, jint ext_input_id,
                                               jstring descr) {
  log::info("");
  std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
  if (!sVolumeControlInterface) {
    return JNI_FALSE;
  }

  jbyte* addr = env->GetByteArrayElements(address, nullptr);
  if (!addr) {
    jniThrowIOException(env, EINVAL);
    return JNI_FALSE;
  }

  std::string description;
  if (descr != nullptr) {
    const char* value = env->GetStringUTFChars(descr, nullptr);
    description = std::string(value);
    env->ReleaseStringUTFChars(descr, value);
  }

  RawAddress* tmpraw = reinterpret_cast<RawAddress*>(addr);
  sVolumeControlInterface->SetExtAudioInDescription(*tmpraw, ext_input_id, description);
  env->ReleaseByteArrayElements(address, addr, 0);
  return JNI_TRUE;
}

static jboolean setExtAudioInGainValueNative(JNIEnv* env, jobject /* object */, jbyteArray address,
                                             jint ext_input_id, jint gain_val) {
  log::info("");
  std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
  if (!sVolumeControlInterface) {
    return JNI_FALSE;
  }

  jbyte* addr = env->GetByteArrayElements(address, nullptr);
  if (!addr) {
    jniThrowIOException(env, EINVAL);
    return JNI_FALSE;
  }

  RawAddress* tmpraw = reinterpret_cast<RawAddress*>(addr);
  sVolumeControlInterface->SetExtAudioInGainValue(*tmpraw, ext_input_id, gain_val);
  env->ReleaseByteArrayElements(address, addr, 0);
  return JNI_TRUE;
}

static jboolean setExtAudioInGainModeNative(JNIEnv* env, jobject /* object */, jbyteArray address,
                                            jint ext_input_id, jboolean mode_auto) {
  log::info("");
  std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
  if (!sVolumeControlInterface) {
    return JNI_FALSE;
  }

  jbyte* addr = env->GetByteArrayElements(address, nullptr);
  if (!addr) {
    jniThrowIOException(env, EINVAL);
    return JNI_FALSE;
  }

  RawAddress* tmpraw = reinterpret_cast<RawAddress*>(addr);
  sVolumeControlInterface->SetExtAudioInGainMode(*tmpraw, ext_input_id, mode_auto);
  env->ReleaseByteArrayElements(address, addr, 0);
  return JNI_TRUE;
}

static jboolean setExtAudioInGainMuteNative(JNIEnv* env, jobject /* object */, jbyteArray address,
                                            jint ext_input_id, jboolean mute) {
  log::info("");
  std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
  if (!sVolumeControlInterface) {
    return JNI_FALSE;
  }

  jbyte* addr = env->GetByteArrayElements(address, nullptr);
  if (!addr) {
    jniThrowIOException(env, EINVAL);
    return JNI_FALSE;
  }

  RawAddress* tmpraw = reinterpret_cast<RawAddress*>(addr);
  sVolumeControlInterface->SetExtAudioInGainMute(*tmpraw, ext_input_id, mute);
  env->ReleaseByteArrayElements(address, addr, 0);
  return JNI_TRUE;
}

int register_com_android_bluetooth_vc(JNIEnv* env) {
  const JNINativeMethod methods[] = {
          {"initNative", "()V", reinterpret_cast<void*>(initNative)},
@@ -540,6 +851,22 @@ int register_com_android_bluetooth_vc(JNIEnv* env) {
           reinterpret_cast<void*>(getExtAudioOutDescriptionNative)},
          {"setExtAudioOutDescriptionNative", "([BILjava/lang/String;)Z",
           reinterpret_cast<void*>(setExtAudioOutDescriptionNative)},
          {"getExtAudioInStateNative", "([BI)Z", reinterpret_cast<void*>(getExtAudioInStateNative)},
          {"getExtAudioInStatusNative", "([BI)Z",
           reinterpret_cast<void*>(getExtAudioInStatusNative)},
          {"getExtAudioInTypeNative", "([BI)Z", reinterpret_cast<void*>(getExtAudioInTypeNative)},
          {"getExtAudioInGainPropsNative", "([BI)Z",
           reinterpret_cast<void*>(getExtAudioInGainPropsNative)},
          {"getExtAudioInDescriptionNative", "([BI)Z",
           reinterpret_cast<void*>(getExtAudioInDescriptionNative)},
          {"setExtAudioInDescriptionNative", "([BILjava/lang/String;)Z",
           reinterpret_cast<void*>(setExtAudioInDescriptionNative)},
          {"setExtAudioInGainValueNative", "([BII)Z",
           reinterpret_cast<void*>(setExtAudioInGainValueNative)},
          {"setExtAudioInGainModeNative", "([BIZ)Z",
           reinterpret_cast<void*>(setExtAudioInGainModeNative)},
          {"setExtAudioInGainMuteNative", "([BIZ)Z",
           reinterpret_cast<void*>(setExtAudioInGainMuteNative)},
  };
  const int result = REGISTER_NATIVE_METHODS(
          env, "com/android/bluetooth/vc/VolumeControlNativeInterface", methods);
@@ -551,11 +878,17 @@ int register_com_android_bluetooth_vc(JNIEnv* env) {
          {"onConnectionStateChanged", "(I[B)V", &method_onConnectionStateChanged},
          {"onVolumeStateChanged", "(IZI[BZ)V", &method_onVolumeStateChanged},
          {"onGroupVolumeStateChanged", "(IZIZ)V", &method_onGroupVolumeStateChanged},
          {"onDeviceAvailable", "(I[B)V", &method_onDeviceAvailable},
          {"onDeviceAvailable", "(II[B)V", &method_onDeviceAvailable},
          {"onExtAudioOutVolumeOffsetChanged", "(II[B)V", &method_onExtAudioOutVolumeOffsetChanged},
          {"onExtAudioOutLocationChanged", "(II[B)V", &method_onExtAudioOutLocationChanged},
          {"onExtAudioOutDescriptionChanged", "(ILjava/lang/String;[B)V",
           &method_onExtAudioOutDescriptionChanged},
          {"onExtAudioInStateChanged", "(IIIZ[B)V", &method_onExtAudioInStateChanged},
          {"onExtAudioInStatusChanged", "(II[B)V", &method_onExtAudioInStatusChanged},
          {"onExtAudioInTypeChanged", "(II[B)V", &method_onExtAudioInTypeChanged},
          {"onExtAudioInGainPropsChanged", "(IIII[B)V", &method_onExtAudioInGainPropsChanged},
          {"onExtAudioInDescriptionChanged", "(ILjava/lang/String;[B)V",
           &method_onExtAudioInDescriptionChanged},
  };
  GET_JAVA_METHODS(env, "com/android/bluetooth/vc/VolumeControlNativeInterface", javaMethods);

Loading