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

Commit 6e166405 authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge changes I00aefb70,I7c722048 am: eb61e8bf am: 7aadfdf6

Original change: https://android-review.googlesource.com/c/platform/packages/modules/Bluetooth/+/2008030

Change-Id: I6c09f8bb929b0ac877d9bbd6d7410263abb2d093
parents 47bdf87b 7aadfdf6
Loading
Loading
Loading
Loading
+250 −0
Original line number Diff line number Diff line
@@ -34,6 +34,10 @@ namespace android {
static jmethodID method_onConnectionStateChanged;
static jmethodID method_onVolumeStateChanged;
static jmethodID method_onGroupVolumeStateChanged;
static jmethodID method_onDeviceAvailable;
static jmethodID method_onExtAudioOutVolumeOffsetChanged;
static jmethodID method_onExtAudioOutLocationChanged;
static jmethodID method_onExtAudioOutDescriptionChanged;

static VolumeControlInterface* sVolumeControlInterface = nullptr;
static std::shared_timed_mutex interface_mutex;
@@ -98,6 +102,100 @@ class VolumeControlCallbacksImpl : public VolumeControlCallbacks {
                                 method_onGroupVolumeStateChanged, (jint)volume,
                                 (jboolean)mute, group_id, (jboolean)isAutonomous);
  }

  void OnDeviceAvailable(const RawAddress& bd_addr,
                         uint8_t num_offsets) override {
    LOG(INFO) << __func__;

    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 new jbyteArray bd addr for onDeviceAvailable";
      return;
    }

    sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
                                     (jbyte*)&bd_addr);
    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onDeviceAvailable,
                                 (jint)num_offsets, addr.get());
  }

  void OnExtAudioOutVolumeOffsetChanged(const RawAddress& bd_addr,
                                        uint8_t ext_output_id,
                                        int16_t offset) override {
    LOG(INFO) << __func__;

    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 new jbyteArray bd addr for "
                    "OnExtAudioOutVolumeOffsetChanged";
      return;
    }

    sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
                                     (jbyte*)&bd_addr);
    sCallbackEnv->CallVoidMethod(mCallbacksObj,
                                 method_onExtAudioOutVolumeOffsetChanged,
                                 (jint)ext_output_id, (jint)offset, addr.get());
  }

  void OnExtAudioOutLocationChanged(const RawAddress& bd_addr,
                                    uint8_t ext_output_id,
                                    uint32_t location) override {
    LOG(INFO) << __func__;

    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 new jbyteArray bd addr for "
                    "OnExtAudioOutLocationChanged";
      return;
    }

    sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
                                     (jbyte*)&bd_addr);
    sCallbackEnv->CallVoidMethod(
        mCallbacksObj, method_onExtAudioOutLocationChanged, (jint)ext_output_id,
        (jint)location, addr.get());
  }

  void OnExtAudioOutDescriptionChanged(const RawAddress& bd_addr,
                                       uint8_t ext_output_id,
                                       std::string descr) override {
    LOG(INFO) << __func__;

    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 new jbyteArray bd addr for "
                    "OnExtAudioOutDescriptionChanged";
      return;
    }

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

static VolumeControlCallbacksImpl sVolumeControlCallbacks;
@@ -112,6 +210,18 @@ static void classInitNative(JNIEnv* env, jclass clazz) {
  method_onGroupVolumeStateChanged =
      env->GetMethodID(clazz, "onGroupVolumeStateChanged", "(IZIZ)V");

  method_onDeviceAvailable =
      env->GetMethodID(clazz, "onDeviceAvailable", "(I[B)V");

  method_onExtAudioOutVolumeOffsetChanged =
      env->GetMethodID(clazz, "onExtAudioOutVolumeOffsetChanged", "(II[B)V");

  method_onExtAudioOutLocationChanged =
      env->GetMethodID(clazz, "onExtAudioOutLocationChanged", "(II[B)V");

  method_onExtAudioOutDescriptionChanged = env->GetMethodID(
      clazz, "onExtAudioOutDescriptionChanged", "(ILjava/lang/String;[B)V");

  LOG(INFO) << __func__ << ": succeeds";
}

@@ -249,6 +359,134 @@ static void setVolumeGroupNative(JNIEnv* env, jobject object, jint group_id,
  sVolumeControlInterface->SetVolume(group_id, volume);
}

/* Native methods for exterbak audio outputs */
static jboolean getExtAudioOutVolumeOffsetNative(JNIEnv* env, jobject object,
                                                 jbyteArray address,
                                                 jint ext_output_id) {
  LOG(INFO) << __func__;
  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 = (RawAddress*)addr;
  sVolumeControlInterface->GetExtAudioOutVolumeOffset(*tmpraw, ext_output_id);
  env->ReleaseByteArrayElements(address, addr, 0);
  return JNI_TRUE;
}

static jboolean setExtAudioOutVolumeOffsetNative(JNIEnv* env, jobject object,
                                                 jbyteArray address,
                                                 jint ext_output_id,
                                                 jint offset) {
  LOG(INFO) << __func__;
  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 = (RawAddress*)addr;
  sVolumeControlInterface->SetExtAudioOutVolumeOffset(*tmpraw, ext_output_id,
                                                      offset);
  env->ReleaseByteArrayElements(address, addr, 0);
  return JNI_TRUE;
}

static jboolean getExtAudioOutLocationNative(JNIEnv* env, jobject object,
                                             jbyteArray address,
                                             jint ext_output_id) {
  LOG(INFO) << __func__;
  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 = (RawAddress*)addr;
  sVolumeControlInterface->GetExtAudioOutLocation(*tmpraw, ext_output_id);
  env->ReleaseByteArrayElements(address, addr, 0);
  return JNI_TRUE;
}

static jboolean setExtAudioOutLocationNative(JNIEnv* env, jobject object,
                                             jbyteArray address,
                                             jint ext_output_id,
                                             jint location) {
  LOG(INFO) << __func__;
  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 = (RawAddress*)addr;
  sVolumeControlInterface->SetExtAudioOutLocation(*tmpraw, ext_output_id,
                                                  location);
  env->ReleaseByteArrayElements(address, addr, 0);
  return JNI_TRUE;
}

static jboolean getExtAudioOutDescriptionNative(JNIEnv* env, jobject object,
                                                jbyteArray address,
                                                jint ext_output_id) {
  LOG(INFO) << __func__;
  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 = (RawAddress*)addr;
  sVolumeControlInterface->GetExtAudioOutDescription(*tmpraw, ext_output_id);
  env->ReleaseByteArrayElements(address, addr, 0);
  return JNI_TRUE;
}

static jboolean setExtAudioOutDescriptionNative(JNIEnv* env, jobject object,
                                                jbyteArray address,
                                                jint ext_output_id,
                                                jstring descr) {
  LOG(INFO) << __func__;
  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 = (RawAddress*)addr;
  sVolumeControlInterface->SetExtAudioOutDescription(*tmpraw, ext_output_id,
                                                     description);
  env->ReleaseByteArrayElements(address, addr, 0);
  return JNI_TRUE;
}

static JNINativeMethod sMethods[] = {
    {"classInitNative", "()V", (void*)classInitNative},
    {"initNative", "()V", (void*)initNative},
@@ -258,6 +496,18 @@ static JNINativeMethod sMethods[] = {
     (void*)disconnectVolumeControlNative},
    {"setVolumeNative", "([BI)V", (void*)setVolumeNative},
    {"setVolumeGroupNative", "(II)V", (void*)setVolumeGroupNative},
    {"getExtAudioOutVolumeOffsetNative", "([BI)Z",
     (void*)getExtAudioOutVolumeOffsetNative},
    {"setExtAudioOutVolumeOffsetNative", "([BII)Z",
     (void*)setExtAudioOutVolumeOffsetNative},
    {"getExtAudioOutLocationNative", "([BI)Z",
     (void*)getExtAudioOutLocationNative},
    {"setExtAudioOutLocationNative", "([BII)Z",
     (void*)setExtAudioOutLocationNative},
    {"getExtAudioOutDescriptionNative", "([BI)Z",
     (void*)getExtAudioOutDescriptionNative},
    {"setExtAudioOutDescriptionNative", "([BILjava/lang/String;)Z",
     (void*)setExtAudioOutDescriptionNative},
};

int register_com_android_bluetooth_vc(JNIEnv* env) {
+146 −0
Original line number Diff line number Diff line
@@ -117,6 +117,84 @@ public class VolumeControlNativeInterface {
        setVolumeGroupNative(groupId, volume);
    }

    /**
     * Gets external audio output volume offset from a remote device.
     *
     * @param device the remote device
     * @param externalOutputId external audio output id
     * @return true on success, otherwise false.
     */
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    public boolean getExtAudioOutVolumeOffset(BluetoothDevice device, int externalOutputId) {
        return getExtAudioOutVolumeOffsetNative(getByteAddress(device), externalOutputId);
    }

    /**
     * Sets external audio output volume offset to a remote device.
     *
     * @param device the remote device
     * @param externalOutputId external audio output id
     * @param offset requested offset
     * @return true on success, otherwise false.
     */
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    public boolean setExtAudioOutVolumeOffset(BluetoothDevice device, int externalOutputId,
                                                    int offset) {
        return setExtAudioOutVolumeOffsetNative(getByteAddress(device), externalOutputId, offset);
    }

    /**
     * Gets external audio output location from a remote device.
     *
     * @param device the remote device
     * @param externalOutputId external audio output id
     * @return true on success, otherwise false.
     */
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    public boolean getExtAudioOutLocation(BluetoothDevice device, int externalOutputId) {
        return getExtAudioOutLocationNative(getByteAddress(device), externalOutputId);
    }

    /**
     * Sets external audio volume offset to a remote device.
     *
     * @param device the remote device
     * @param externalOutputId external audio output id
     * @param location requested location
     * @return true on success, otherwise false.
     */
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    public boolean setExtAudioOutLocation(BluetoothDevice device, int externalOutputId,
                                            int location) {
        return setExtAudioOutLocationNative(getByteAddress(device), externalOutputId, location);
    }

    /**
     * Gets external audio output description from a remote device.
     *
     * @param device the remote device
     * @param externalOutputId external audio output id
     * @return true on success, otherwise false.
     */
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    public boolean getExtAudioOutDescription(BluetoothDevice device, int externalOutputId) {
        return getExtAudioOutDescriptionNative(getByteAddress(device), externalOutputId);
    }

    /**
     * Sets external audio volume description to a remote device.
     *
     * @param device the remote device
     * @param externalOutputId external audio output id
     * @param descr requested description
     * @return true on success, otherwise false.
     */
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    public boolean setExtAudioOutDescription(BluetoothDevice device, int externalOutputId,
                                                    String descr) {
        return setExtAudioOutDescriptionNative(getByteAddress(device), externalOutputId, descr);
    }

    private BluetoothDevice getDevice(byte[] address) {
        return mAdapter.getRemoteDevice(address);
    }
@@ -188,6 +266,65 @@ public class VolumeControlNativeInterface {
        sendMessageToService(event);
    }

    private void onDeviceAvailable(int numOfExternalOutputs,
                                   byte[] address) {
        VolumeControlStackEvent event =
                new VolumeControlStackEvent(
                        VolumeControlStackEvent.EVENT_TYPE_DEVICE_AVAILABLE);
        event.device = getDevice(address);
        event.valueInt1 = numOfExternalOutputs;

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

    private void onExtAudioOutVolumeOffsetChanged(int externalOutputId, int offset,
                                               byte[] address) {
        VolumeControlStackEvent event =
                new VolumeControlStackEvent(
                    VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_VOL_OFFSET_CHANGED);
        event.device = getDevice(address);
        event.valueInt1 = externalOutputId;
        event.valueInt2 = offset;

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

    private void onExtAudioOutLocationChanged(int externalOutputId, int location,
                                               byte[] address) {
        VolumeControlStackEvent event =
                new VolumeControlStackEvent(
                    VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED);
        event.device = getDevice(address);
        event.valueInt1 = externalOutputId;
        event.valueInt2 = location;

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

    private void onExtAudioOutDescriptionChanged(int externalOutputId, String descr,
                                               byte[] address) {
        VolumeControlStackEvent event =
                new VolumeControlStackEvent(
                    VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED);
        event.device = getDevice(address);
        event.valueInt1 = externalOutputId;
        event.valueString1 = descr;

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

    // Native methods that call into the JNI interface
    private static native void classInitNative();
    private native void initNative();
@@ -196,4 +333,13 @@ public class VolumeControlNativeInterface {
    private native boolean disconnectVolumeControlNative(byte[] address);
    private native void setVolumeNative(byte[] address, int volume);
    private native void setVolumeGroupNative(int groupId, int volume);
    private native boolean getExtAudioOutVolumeOffsetNative(byte[] address, int externalOutputId);
    private native boolean setExtAudioOutVolumeOffsetNative(byte[] address, int externalOutputId,
                                                                int offset);
    private native boolean getExtAudioOutLocationNative(byte[] address, int externalOutputId);
    private native boolean setExtAudioOutLocationNative(byte[] address, int externalOutputId,
                                                            int location);
    private native boolean getExtAudioOutDescriptionNative(byte[] address, int externalOutputId);
    private native boolean setExtAudioOutDescriptionNative(byte[] address, int externalOutputId,
                                                                String descr);
}
+301 −7

File changed.

Preview size limit exceeded, changes collapsed.

+31 −0
Original line number Diff line number Diff line
@@ -24,6 +24,10 @@ public class VolumeControlStackEvent {
    private static final int EVENT_TYPE_NONE = 0;
    public static final int EVENT_TYPE_CONNECTION_STATE_CHANGED = 1;
    public static final int EVENT_TYPE_VOLUME_STATE_CHANGED = 2;
    public static final int EVENT_TYPE_DEVICE_AVAILABLE = 3;
    public static final int EVENT_TYPE_EXT_AUDIO_OUT_VOL_OFFSET_CHANGED = 4;
    public static final int EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED = 5;
    public static final int EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED = 6;

    // Do not modify without updating the HAL bt_vc_aid.h files.
    // Match up with enum class ConnectionState of bt_vc_aid.h.
@@ -38,6 +42,8 @@ public class VolumeControlStackEvent {
    public int valueInt2;
    public boolean valueBool1;
    public boolean valueBool2;
    public String valueString1;

    /* Might need more for other callbacks*/

    VolumeControlStackEvent(int type) {
@@ -54,6 +60,7 @@ public class VolumeControlStackEvent {
        result.append(", valueInt2:" + eventTypeValue2ToString(type, valueInt2));
        result.append(", valueBool1:" + eventTypeValueBool1ToString(type, valueBool1));
        result.append(", valueBool2:" + eventTypeValueBool2ToString(type, valueBool2));
        result.append(", valueString1:" + eventTypeString1ToString(type, valueString1));
        result.append("}");
        return result.toString();
    }
@@ -66,6 +73,14 @@ public class VolumeControlStackEvent {
                return "EVENT_TYPE_CONNECTION_STATE_CHANGED";
            case EVENT_TYPE_VOLUME_STATE_CHANGED:
                return "EVENT_TYPE_VOLUME_STATE_CHANGED";
            case EVENT_TYPE_DEVICE_AVAILABLE:
                return "EVENT_TYPE_DEVICE_AVAILABLE";
            case EVENT_TYPE_EXT_AUDIO_OUT_VOL_OFFSET_CHANGED:
                return "EVENT_TYPE_EXT_AUDIO_OUT_VOL_OFFSET_CHANGED";
            case EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED:
                return "EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED";
            case EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED:
                return "EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED";
            default:
                return "EVENT_TYPE_UNKNOWN:" + type;
        }
@@ -88,6 +103,12 @@ public class VolumeControlStackEvent {
                }
            case EVENT_TYPE_VOLUME_STATE_CHANGED:
                return "{group_id:" + value + "}";
            case EVENT_TYPE_DEVICE_AVAILABLE:
                return "{num_ext_outputs:"  + value + "}";
            case EVENT_TYPE_EXT_AUDIO_OUT_VOL_OFFSET_CHANGED:
            case EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED:
            case EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED:
                return "{ext output id:" + value + "}";
            default:
                break;
        }
@@ -136,4 +157,14 @@ public class VolumeControlStackEvent {
        }
        return Boolean.toString(value);
    }

    private static String eventTypeString1ToString(int type, String value) {
        switch (type) {
            case EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED:
                return "{descrition:" + value + "}";
            default:
                break;
        }
        return value;
    }
}
+1 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ filegroup {
        "android/bluetooth/IBluetoothHapClient.aidl",
        "android/bluetooth/IBluetoothHapClientCallback.aidl",
        "android/bluetooth/IBluetoothVolumeControl.aidl",
        "android/bluetooth/IBluetoothVolumeControlCallback.aidl",
        "android/bluetooth/IBluetoothHidHost.aidl",
        "android/bluetooth/IBluetoothLeAudio.aidl",
        "android/bluetooth/IBluetoothLeBroadcastCallback.aidl",
Loading