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

Commit 522ce877 authored by William Escande's avatar William Escande Committed by Gerrit Code Review
Browse files

Merge changes I116d5e08,Ia8d497db,I0218ef71 into main

* changes:
  AICS: getType implementation
  AICS: Audio input control point expose up to aidl
  AICS: getStatus/onStatusChanged implementation
parents f19014d1 8d981af4
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -23,4 +23,9 @@ package android.bluetooth;
 */
oneway interface IAudioInputCallback {
    void onDescriptionChanged(in String description);
    void onStatusChanged(int status);
    void onStateChanged(int gainSetting, int mute, int gainMode);
    void onSetGainSettingFailed();
    void onSetGainModeFailed();
    void onSetMuteFailed();
}
+21 −0
Original line number Diff line number Diff line
@@ -88,4 +88,25 @@ interface IBluetoothVolumeControl {
    boolean isAudioInputDescriptionWritable(in AttributionSource attributionSource, in BluetoothDevice device, int instanceId);
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})")
    boolean setAudioInputDescription(in AttributionSource attributionSource, in BluetoothDevice device, int instanceId, in String description);

    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})")
    int getAudioInputStatus(in AttributionSource attributionSource, in BluetoothDevice device, int instanceId);

    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})")
    int getAudioInputType(in AttributionSource attributionSource, in BluetoothDevice device, int instanceId);

    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})")
    int getAudioInputGainSetting(in AttributionSource attributionSource, in BluetoothDevice device, int instanceId);
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})")
    boolean setAudioInputGainSetting(in AttributionSource attributionSource, in BluetoothDevice device, int instanceId, int gainSetting);

    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})")
    int getAudioInputGainMode(in AttributionSource attributionSource, in BluetoothDevice device, int instanceId);
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})")
    boolean setAudioInputGainMode(in AttributionSource attributionSource, in BluetoothDevice device, int instanceId, int gainMode);

    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})")
    int getAudioInputMute(in AttributionSource attributionSource, in BluetoothDevice device, int instanceId);
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})")
    boolean setAudioInputMute(in AttributionSource attributionSource, in BluetoothDevice device, int instanceId, int mute);
}
+86 −13
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@
#include "hardware/bt_vc.h"
#include "types/raw_address.h"

using bluetooth::aics::GainMode;
using bluetooth::aics::Mute;
using bluetooth::vc::ConnectionState;
using bluetooth::vc::VolumeControlCallbacks;
@@ -51,6 +52,9 @@ static jmethodID method_onExtAudioOutVolumeOffsetChanged;
static jmethodID method_onExtAudioOutLocationChanged;
static jmethodID method_onExtAudioOutDescriptionChanged;
static jmethodID method_onExtAudioInStateChanged;
static jmethodID method_onExtAudioInSetGainSettingFailed;
static jmethodID method_onExtAudioInSetMuteFailed;
static jmethodID method_onExtAudioInSetGainModeFailed;
static jmethodID method_onExtAudioInStatusChanged;
static jmethodID method_onExtAudioInTypeChanged;
static jmethodID method_onExtAudioInGainPropsChanged;
@@ -224,7 +228,7 @@ public:
  }

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

    std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
@@ -246,6 +250,71 @@ public:
                                 (jint)gain_setting, (jint)mute, (jint)gain_mode, addr.get());
  }

  void OnExtAudioInSetGainSettingFailed(const RawAddress& bd_addr, uint8_t ext_input_id) 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_onExtAudioInSetGainSettingFailed,
                                 (jint)ext_input_id, addr.get());
  }

  void OnExtAudioInSetMuteFailed(const RawAddress& bd_addr, uint8_t ext_input_id) 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_onExtAudioInSetMuteFailed,
                                 (jint)ext_input_id, addr.get());
  }
  void OnExtAudioInSetGainModeFailed(const RawAddress& bd_addr, uint8_t ext_input_id) 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_onExtAudioInSetGainModeFailed,
                                 (jint)ext_input_id, addr.get());
  }

  void OnExtAudioInStatusChanged(const RawAddress& bd_addr, uint8_t ext_input_id,
                                 VolumeInputStatus status) override {
    log::info("");
@@ -799,13 +868,13 @@ static jboolean setExtAudioInGainSettingNative(JNIEnv* env, jobject /* object */
  }

  RawAddress* tmpraw = reinterpret_cast<RawAddress*>(addr);
  sVolumeControlInterface->SetExtAudioInGainSetting(*tmpraw, ext_input_id, gain_setting);
  bool ret = sVolumeControlInterface->SetExtAudioInGainSetting(*tmpraw, ext_input_id, gain_setting);
  env->ReleaseByteArrayElements(address, addr, 0);
  return JNI_TRUE;
  return ret ? JNI_TRUE : JNI_FALSE;
}

static jboolean setExtAudioInGainModeNative(JNIEnv* env, jobject /* object */, jbyteArray address,
                                            jint ext_input_id, jboolean mode_auto) {
                                            jint ext_input_id, jint gain_mode) {
  log::info("");
  std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
  if (!sVolumeControlInterface) {
@@ -819,13 +888,14 @@ static jboolean setExtAudioInGainModeNative(JNIEnv* env, jobject /* object */, j
  }

  RawAddress* tmpraw = reinterpret_cast<RawAddress*>(addr);
  sVolumeControlInterface->SetExtAudioInGainMode(*tmpraw, ext_input_id, mode_auto);
  bool ret = sVolumeControlInterface->SetExtAudioInGainMode(
          *tmpraw, ext_input_id, bluetooth::aics::parseGainModeField(gain_mode));
  env->ReleaseByteArrayElements(address, addr, 0);
  return JNI_TRUE;
  return ret ? JNI_TRUE : JNI_FALSE;
}

static jboolean setExtAudioInGainMuteNative(JNIEnv* env, jobject /* object */, jbyteArray address,
                                            jint ext_input_id, jboolean mute) {
static jboolean setExtAudioInMuteNative(JNIEnv* env, jobject /* object */, jbyteArray address,
                                        jint ext_input_id, jint mute) {
  log::info("");
  std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
  if (!sVolumeControlInterface) {
@@ -839,9 +909,10 @@ static jboolean setExtAudioInGainMuteNative(JNIEnv* env, jobject /* object */, j
  }

  RawAddress* tmpraw = reinterpret_cast<RawAddress*>(addr);
  sVolumeControlInterface->SetExtAudioInGainMute(*tmpraw, ext_input_id, mute);
  bool ret = sVolumeControlInterface->SetExtAudioInMute(*tmpraw, ext_input_id,
                                                        bluetooth::aics::parseMuteField(mute));
  env->ReleaseByteArrayElements(address, addr, 0);
  return JNI_TRUE;
  return ret ? JNI_TRUE : JNI_FALSE;
}

int register_com_android_bluetooth_vc(JNIEnv* env) {
@@ -882,10 +953,9 @@ int register_com_android_bluetooth_vc(JNIEnv* env) {
           reinterpret_cast<void*>(setExtAudioInDescriptionNative)},
          {"setExtAudioInGainSettingNative", "([BII)Z",
           reinterpret_cast<void*>(setExtAudioInGainSettingNative)},
          {"setExtAudioInGainModeNative", "([BIZ)Z",
          {"setExtAudioInGainModeNative", "([BII)Z",
           reinterpret_cast<void*>(setExtAudioInGainModeNative)},
          {"setExtAudioInGainMuteNative", "([BIZ)Z",
           reinterpret_cast<void*>(setExtAudioInGainMuteNative)},
          {"setExtAudioInMuteNative", "([BII)Z", reinterpret_cast<void*>(setExtAudioInMuteNative)},
  };
  const int result = REGISTER_NATIVE_METHODS(
          env, "com/android/bluetooth/vc/VolumeControlNativeInterface", methods);
@@ -909,6 +979,9 @@ int register_com_android_bluetooth_vc(JNIEnv* env) {
          {"onExtAudioOutDescriptionChanged", "(ILjava/lang/String;[B)V",
           &method_onExtAudioOutDescriptionChanged},
          {"onExtAudioInStateChanged", "(IIII[B)V", &method_onExtAudioInStateChanged},
          {"onExtAudioInSetGainSettingFailed", "(I[B)V", &method_onExtAudioInSetGainSettingFailed},
          {"onExtAudioInSetMuteFailed", "(I[B)V", &method_onExtAudioInSetMuteFailed},
          {"onExtAudioInSetGainModeFailed", "(I[B)V", &method_onExtAudioInSetGainModeFailed},
          {"onExtAudioInStatusChanged", "(II[B)V", &method_onExtAudioInStatusChanged},
          {"onExtAudioInTypeChanged", "(II[B)V", &method_onExtAudioInTypeChanged},
          {"onExtAudioInGainPropsChanged", "(IIII[B)V", &method_onExtAudioInGainPropsChanged},
+89 −26
Original line number Diff line number Diff line
@@ -20,6 +20,10 @@ import static com.android.bluetooth.Utils.RemoteExceptionIgnoringConsumer;

import static java.util.Objects.requireNonNull;

import android.bluetooth.AudioInputControl.AudioInputStatus;
import android.bluetooth.AudioInputControl.AudioInputType;
import android.bluetooth.AudioInputControl.GainMode;
import android.bluetooth.AudioInputControl.Mute;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.IAudioInputCallback;
import android.os.RemoteCallbackList;
@@ -27,11 +31,6 @@ import android.util.Log;

import com.android.bluetooth.btservice.ProfileService;

import bluetooth.constants.AudioInputType;
import bluetooth.constants.aics.AudioInputStatus;
import bluetooth.constants.aics.GainMode;
import bluetooth.constants.aics.Mute;

class VolumeControlInputDescriptor {
    private static final String TAG = VolumeControlInputDescriptor.class.getSimpleName();

@@ -53,15 +52,13 @@ class VolumeControlInputDescriptor {
    }

    private static class Descriptor {
        int mStatus = AudioInputStatus.INACTIVE;
        @AudioInputStatus int mStatus = bluetooth.constants.aics.AudioInputStatus.INACTIVE;

        int mType = AudioInputType.UNSPECIFIED;
        @AudioInputType int mType = bluetooth.constants.AudioInputType.UNSPECIFIED;

        int mGainSetting = 0;

        int mGainMode = GainMode.MANUAL_ONLY;

        int mMute = Mute.DISABLED;
        @Mute int mMute = bluetooth.constants.aics.Mute.DISABLED;
        @GainMode int mGainMode = bluetooth.constants.aics.GainMode.MANUAL_ONLY;

        /* See AICS 1.0
         * The Gain_Setting (mGainSetting) field is a signed value for which a single increment or
@@ -121,13 +118,14 @@ class VolumeControlInputDescriptor {
        mVolumeInputs[id].unregisterCallback(callback);
    }

    void setStatus(int id, int status) {
    void onStatusChanged(int id, @AudioInputStatus int status) {
        if (!isValidId(id)) return;
        mVolumeInputs[id].mStatus = status;
        mVolumeInputs[id].broadcast("onStatusChanged", (c) -> c.onStatusChanged(status));
    }

    int getStatus(int id) {
        if (!isValidId(id)) return AudioInputStatus.INACTIVE;
        if (!isValidId(id)) return bluetooth.constants.aics.AudioInputStatus.INACTIVE;
        return mVolumeInputs[id].mStatus;
    }

@@ -166,20 +164,10 @@ class VolumeControlInputDescriptor {
    }

    int getType(int id) {
        if (!isValidId(id)) return AudioInputType.UNSPECIFIED;
        if (!isValidId(id)) return bluetooth.constants.AudioInputType.UNSPECIFIED;
        return mVolumeInputs[id].mType;
    }

    int getGainSetting(int id) {
        if (!isValidId(id)) return 0;
        return mVolumeInputs[id].mGainSetting;
    }

    int getMute(int id) {
        if (!isValidId(id)) return Mute.DISABLED;
        return mVolumeInputs[id].mMute;
    }

    void setPropSettings(int id, int gainUnit, int gainMin, int gainMax) {
        if (!isValidId(id)) return;

@@ -188,7 +176,7 @@ class VolumeControlInputDescriptor {
        mVolumeInputs[id].mGainSettingsMax = gainMax;
    }

    void setState(int id, int gainSetting, int mute, int gainMode) {
    void onStateChanged(int id, int gainSetting, @Mute int mute, @GainMode int gainMode) {
        if (!isValidId(id)) return;

        Descriptor desc = mVolumeInputs[id];
@@ -199,8 +187,83 @@ class VolumeControlInputDescriptor {
        }

        desc.mGainSetting = gainSetting;
        desc.mGainMode = gainMode;
        desc.mMute = mute;
        desc.mGainMode = gainMode;

        mVolumeInputs[id].broadcast(
                "onStateChanged", (c) -> c.onStateChanged(gainSetting, mute, gainMode));
    }

    int getGainSetting(int id) {
        if (!isValidId(id)) return 0;
        return mVolumeInputs[id].mGainSetting;
    }

    boolean setGainSetting(int id, int gainSetting) {
        if (!isValidId(id)) return false;

        Descriptor desc = mVolumeInputs[id];

        if (gainSetting > desc.mGainSettingsMax || gainSetting < desc.mGainSettingsMin) {
            throw new IllegalArgumentException("Illegal gainSetting argument: " + gainSetting);
        }

        if (desc.mGainMode == bluetooth.constants.aics.GainMode.AUTOMATIC
                || desc.mGainMode == bluetooth.constants.aics.GainMode.AUTOMATIC_ONLY) {
            throw new IllegalStateException("Disallowed due to gain mode being " + desc.mGainMode);
        }

        return mNativeInterface.setExtAudioInGainSetting(mDevice, id, gainSetting);
    }

    void onSetGainSettingFailed(int id) {
        if (!isValidId(id)) return;
        mVolumeInputs[id].broadcast("onSetGainSettingFailed", (c) -> c.onSetGainSettingFailed());
    }

    @Mute
    int getMute(int id) {
        if (!isValidId(id)) return bluetooth.constants.aics.Mute.DISABLED;
        return mVolumeInputs[id].mMute;
    }

    boolean setMute(int id, @Mute int mute) {
        if (!isValidId(id)) return false;

        if (mVolumeInputs[id].mMute == bluetooth.constants.aics.Mute.DISABLED) {
            throw new IllegalStateException("Disallowed due to mute being disabled");
        }

        return mNativeInterface.setExtAudioInMute(mDevice, id, mute);
    }

    void onSetMuteFailed(int id) {
        if (!isValidId(id)) return;
        mVolumeInputs[id].broadcast("onSetMuteFailed", (c) -> c.onSetMuteFailed());
    }

    @GainMode
    int getGainMode(int id) {
        if (!isValidId(id)) return bluetooth.constants.aics.GainMode.AUTOMATIC_ONLY;
        return mVolumeInputs[id].mGainMode;
    }

    boolean setGainMode(int id, @GainMode int gainMode) {
        if (!isValidId(id)) return false;

        Descriptor desc = mVolumeInputs[id];

        if (desc.mGainMode == bluetooth.constants.aics.GainMode.MANUAL_ONLY
                || desc.mGainMode == bluetooth.constants.aics.GainMode.AUTOMATIC_ONLY) {
            throw new IllegalStateException("Disallowed due to gain mode being " + desc.mGainMode);
        }

        return mNativeInterface.setExtAudioInGainMode(mDevice, id, gainMode);
    }

    void onSetGainModeFailed(int id) {
        if (!isValidId(id)) return;
        mVolumeInputs[id].broadcast("onSetGainModeFailed", (c) -> c.onSetGainModeFailed());
    }

    void dump(StringBuilder sb) {
+23 −3
Original line number Diff line number Diff line
@@ -25,6 +25,10 @@ import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_VOLUME

import static java.util.Objects.requireNonNull;

import android.bluetooth.AudioInputControl.AudioInputStatus;
import android.bluetooth.AudioInputControl.AudioInputType;
import android.bluetooth.AudioInputControl.GainMode;
import android.bluetooth.AudioInputControl.Mute;
import android.bluetooth.BluetoothDevice;
import android.util.Log;

@@ -151,7 +155,8 @@ class VolumeControlNativeCallback {
    }

    @VisibleForTesting
    void onExtAudioInStateChanged(int id, int gainSetting, int gainMode, int mute, byte[] address) {
    void onExtAudioInStateChanged(
            int id, int gainSetting, @Mute int mute, @GainMode int gainMode, byte[] address) {
        sendMessageToService(
                s ->
                        s.onExtAudioInStateChanged(
@@ -159,12 +164,27 @@ class VolumeControlNativeCallback {
    }

    @VisibleForTesting
    void onExtAudioInStatusChanged(int id, int status, byte[] address) {
    void onExtAudioInSetGainSettingFailed(int id, byte[] address) {
        sendMessageToService(s -> s.onExtAudioInSetGainSettingFailed(getDevice(address), id));
    }

    @VisibleForTesting
    void onExtAudioInSetMuteFailed(int id, byte[] address) {
        sendMessageToService(s -> s.onExtAudioInSetMuteFailed(getDevice(address), id));
    }

    @VisibleForTesting
    void onExtAudioInSetGainModeFailed(int id, byte[] address) {
        sendMessageToService(s -> s.onExtAudioInSetGainModeFailed(getDevice(address), id));
    }

    @VisibleForTesting
    void onExtAudioInStatusChanged(int id, @AudioInputStatus int status, byte[] address) {
        sendMessageToService(s -> s.onExtAudioInStatusChanged(getDevice(address), id, status));
    }

    @VisibleForTesting
    void onExtAudioInTypeChanged(int id, int type, byte[] address) {
    void onExtAudioInTypeChanged(int id, @AudioInputType int type, byte[] address) {
        sendMessageToService(s -> s.onExtAudioInTypeChanged(getDevice(address), id, type));
    }

Loading