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

Commit 97880a74 authored by Hyundo Moon's avatar Hyundo Moon Committed by Automerger Merge Worker
Browse files

Merge "Show volume bar when BLE device's volume is changed" am: 4c043ef1

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

Change-Id: I7f960e217995740e1418cd8bbd2b97ac8e91440b
parents 013354ff 4c043ef1
Loading
Loading
Loading
Loading
+6 −6
Original line number Diff line number Diff line
@@ -66,7 +66,7 @@ class VolumeControlCallbacksImpl : public VolumeControlCallbacks {
  }

  void OnVolumeStateChanged(const RawAddress& bd_addr, uint8_t volume,
                            bool mute) override {
                            bool mute, bool isAutonomous) override {
    LOG(INFO) << __func__;

    std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
@@ -83,11 +83,11 @@ class VolumeControlCallbacksImpl : public VolumeControlCallbacks {
    sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
                                     (jbyte*)&bd_addr);
    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onVolumeStateChanged,
                                 (jint)volume, (jboolean)mute, addr.get());
                                 (jint)volume, (jboolean)mute, addr.get(), (jboolean)isAutonomous);
  }

  void OnGroupVolumeStateChanged(int group_id, uint8_t volume,
                                 bool mute) override {
                                 bool mute, bool isAutonomous) override {
    LOG(INFO) << __func__;

    std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
@@ -96,7 +96,7 @@ class VolumeControlCallbacksImpl : public VolumeControlCallbacks {

    sCallbackEnv->CallVoidMethod(mCallbacksObj,
                                 method_onGroupVolumeStateChanged, (jint)volume,
                                 (jboolean)mute, group_id);
                                 (jboolean)mute, group_id, (jboolean)isAutonomous);
  }
};

@@ -107,10 +107,10 @@ static void classInitNative(JNIEnv* env, jclass clazz) {
      env->GetMethodID(clazz, "onConnectionStateChanged", "(I[B)V");

  method_onVolumeStateChanged =
      env->GetMethodID(clazz, "onVolumeStateChanged", "(IZ[B)V");
      env->GetMethodID(clazz, "onVolumeStateChanged", "(IZ[BZ)V");

  method_onGroupVolumeStateChanged =
      env->GetMethodID(clazz, "onGroupVolumeStateChanged", "(IZI)V");
      env->GetMethodID(clazz, "onGroupVolumeStateChanged", "(IZIZ)V");

  LOG(INFO) << __func__ << ": succeeds";
}
+6 −2
Original line number Diff line number Diff line
@@ -154,7 +154,8 @@ public class VolumeControlNativeInterface {
        sendMessageToService(event);
    }

    private void onVolumeStateChanged(int volume, boolean mute, byte[] address) {
    private void onVolumeStateChanged(int volume, boolean mute, byte[] address,
            boolean isAutonomous) {
        VolumeControlStackEvent event =
                new VolumeControlStackEvent(
                        VolumeControlStackEvent.EVENT_TYPE_VOLUME_STATE_CHANGED);
@@ -162,6 +163,7 @@ public class VolumeControlNativeInterface {
        event.valueInt1 = -1;
        event.valueInt2 = volume;
        event.valueBool1 = mute;
        event.valueBool2 = isAutonomous;

        if (DBG) {
            Log.d(TAG, "onVolumeStateChanged: " + event);
@@ -169,7 +171,8 @@ public class VolumeControlNativeInterface {
        sendMessageToService(event);
    }

    private void onGroupVolumeStateChanged(int volume, boolean mute, int groupId) {
    private void onGroupVolumeStateChanged(int volume, boolean mute, int groupId,
            boolean isAutonomous) {
        VolumeControlStackEvent event =
                new VolumeControlStackEvent(
                        VolumeControlStackEvent.EVENT_TYPE_VOLUME_STATE_CHANGED);
@@ -177,6 +180,7 @@ public class VolumeControlNativeInterface {
        event.valueInt1 = groupId;
        event.valueInt2 = volume;
        event.valueBool1 = mute;
        event.valueBool2 = isAutonomous;

        if (DBG) {
            Log.d(TAG, "onGroupVolumeStateChanged: " + event);
+62 −6
Original line number Diff line number Diff line
@@ -32,6 +32,8 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioDeviceAttributes;
import android.media.AudioDeviceInfo;
import android.media.AudioManager;
import android.os.HandlerThread;
import android.os.ParcelUuid;
@@ -56,12 +58,20 @@ public class VolumeControlService extends ProfileService {

    // Upper limit of all VolumeControl devices: Bonded or Connected
    private static final int MAX_VC_STATE_MACHINES = 10;
    private static final int LE_AUDIO_MAX_VOL = 255;
    private static final int LE_AUDIO_MIN_VOL = 0;

    private static VolumeControlService sVolumeControlService;

    private AdapterService mAdapterService;
    private HandlerThread mStateMachinesThread;
    private BluetoothDevice mPreviousAudioDevice;

    private int mMusicMaxVolume = 0;
    private int mMusicMinVolume = 0;
    private int mVoiceCallMaxVolume = 0;
    private int mVoiceCallMinVolume = 0;

    @VisibleForTesting
    VolumeControlNativeInterface mVolumeControlNativeInterface;
    @VisibleForTesting
@@ -106,6 +116,11 @@ public class VolumeControlService extends ProfileService {
        Objects.requireNonNull(mAudioManager,
                "AudioManager cannot be null when VolumeControlService starts");

        mMusicMaxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
        mMusicMinVolume = mAudioManager.getStreamMinVolume(AudioManager.STREAM_MUSIC);
        mVoiceCallMaxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL);
        mVoiceCallMinVolume = mAudioManager.getStreamMinVolume(AudioManager.STREAM_VOICE_CALL);

        // Start handler thread for state machines
        mStateMachines.clear();
        mStateMachinesThread = new HandlerThread("VolumeControlService.StateMachines");
@@ -422,18 +437,51 @@ public class VolumeControlService extends ProfileService {
    }

    void handleVolumeControlChanged(BluetoothDevice device, int groupId,
                                    int volume, boolean mute) {
        /* TODO handle volume change for group in case of unicast le audio
         * or per device in case of broadcast or simple remote controller.
         * Note: minimum volume is 0 and maximum 255.
         */
                                    int volume, boolean mute, boolean isAutonomous) {
        if (!isAutonomous) {
            // If the change is triggered by Android device, the stream is already changed.
            return;
        }
        // TODO: Handle the other arguments: device, groupId, mute.

        int streamType = getBluetoothContextualVolumeStream();
        mAudioManager.setStreamVolume(streamType, getDeviceVolume(streamType, volume),
                AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_BLUETOOTH_ABS_VOLUME);
    }

    int getDeviceVolume(int streamType, int bleVolume) {
        int bleMaxVolume = 255; // min volume is zero
        int deviceMaxVolume = (streamType == AudioManager.STREAM_VOICE_CALL)
                ? mVoiceCallMaxVolume : mMusicMaxVolume;
        int deviceMinVolume = (streamType == AudioManager.STREAM_VOICE_CALL)
                ? mVoiceCallMinVolume : mMusicMinVolume;

        // TODO: Investigate what happens in classic BT when BT volume is changed to zero.
        return (int) Math.floor(
                (double) bleVolume * (deviceMaxVolume - deviceMinVolume) / bleMaxVolume);
    }

    // Copied from AudioService.getBluetoothContextualVolumeStream() and modified it.
    int getBluetoothContextualVolumeStream() {
        int mode = mAudioManager.getMode();
        switch (mode) {
            case AudioManager.MODE_IN_COMMUNICATION:
            case AudioManager.MODE_IN_CALL:
                return AudioManager.STREAM_VOICE_CALL;
            case AudioManager.MODE_NORMAL:
            default:
                // other conditions will influence the stream type choice, read on...
                break;
        }
        return AudioManager.STREAM_MUSIC;
    }

    void messageFromNative(VolumeControlStackEvent stackEvent) {

        if (stackEvent.type == VolumeControlStackEvent.EVENT_TYPE_VOLUME_STATE_CHANGED) {
            handleVolumeControlChanged(stackEvent.device, stackEvent.valueInt1,
                                       stackEvent.valueInt2, stackEvent.valueBool1);
                                       stackEvent.valueInt2, stackEvent.valueBool1,
                                       stackEvent.valueBool2);
          return;
        }

@@ -495,6 +543,14 @@ public class VolumeControlService extends ProfileService {
            sm = VolumeControlStateMachine.make(device, this,
                    mVolumeControlNativeInterface, mStateMachinesThread.getLooper());
            mStateMachines.put(device, sm);

            mAudioManager.setDeviceVolumeBehavior(
                    new AudioDeviceAttributes(
                            AudioDeviceAttributes.ROLE_OUTPUT,
                            // Currently, TYPE_BLUETOOTH_A2DP is the only thing that works.
                            AudioDeviceInfo.TYPE_BLUETOOTH_A2DP,
                            ""),
                    AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE);
            return sm;
        }
    }
+12 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ public class VolumeControlStackEvent {
    public int valueInt1;
    public int valueInt2;
    public boolean valueBool1;
    public boolean valueBool2;
    /* Might need more for other callbacks*/

    VolumeControlStackEvent(int type) {
@@ -52,6 +53,7 @@ public class VolumeControlStackEvent {
        result.append(", valueInt1:" + eventTypeValue1ToString(type, valueInt1));
        result.append(", valueInt2:" + eventTypeValue2ToString(type, valueInt2));
        result.append(", valueBool1:" + eventTypeValueBool1ToString(type, valueBool1));
        result.append(", valueBool2:" + eventTypeValueBool2ToString(type, valueBool2));
        result.append("}");
        return result.toString();
    }
@@ -124,4 +126,14 @@ public class VolumeControlStackEvent {
        }
        return Boolean.toString(value);
    }

    private static String eventTypeValueBool2ToString(int type, boolean value) {
        switch (type) {
            case EVENT_TYPE_VOLUME_STATE_CHANGED:
                return "{isAutonomous:" + value + "}";
            default:
                break;
        }
        return Boolean.toString(value);
    }
}
+3 −1
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ struct VolumeOperation {
  int group_id_;

  bool started_;
  bool is_autonomous_;

  uint8_t opcode_;
  std::vector<uint8_t> arguments_;
@@ -57,11 +58,12 @@ struct VolumeOperation {
  std::vector<RawAddress> devices_;
  alarm_t* operation_timeout_;

  VolumeOperation(int operation_id, int group_id, uint8_t opcode,
  VolumeOperation(int operation_id, int group_id, bool is_autonomous, uint8_t opcode,
                  std::vector<uint8_t> arguments,
                  std::vector<RawAddress> devices)
      : operation_id_(operation_id),
        group_id_(group_id),
        is_autonomous_(is_autonomous),
        opcode_(opcode),
        arguments_(arguments),
        devices_(devices) {
Loading