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

Commit aef0bc3a 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 am: 97880a74

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

Change-Id: I5995e8b71a1da680ea8ada5fadbe3cc96d1cbec1
parents f70695b9 97880a74
Loading
Loading
Loading
Loading
+6 −6
Original line number Original line Diff line number Diff line
@@ -66,7 +66,7 @@ class VolumeControlCallbacksImpl : public VolumeControlCallbacks {
  }
  }


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


    std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
    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),
    sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
                                     (jbyte*)&bd_addr);
                                     (jbyte*)&bd_addr);
    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onVolumeStateChanged,
    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,
  void OnGroupVolumeStateChanged(int group_id, uint8_t volume,
                                 bool mute) override {
                                 bool mute, bool isAutonomous) override {
    LOG(INFO) << __func__;
    LOG(INFO) << __func__;


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


    sCallbackEnv->CallVoidMethod(mCallbacksObj,
    sCallbackEnv->CallVoidMethod(mCallbacksObj,
                                 method_onGroupVolumeStateChanged, (jint)volume,
                                 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");
      env->GetMethodID(clazz, "onConnectionStateChanged", "(I[B)V");


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


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


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


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


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


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


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


    // Upper limit of all VolumeControl devices: Bonded or Connected
    // Upper limit of all VolumeControl devices: Bonded or Connected
    private static final int MAX_VC_STATE_MACHINES = 10;
    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 static VolumeControlService sVolumeControlService;


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


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

    @VisibleForTesting
    @VisibleForTesting
    VolumeControlNativeInterface mVolumeControlNativeInterface;
    VolumeControlNativeInterface mVolumeControlNativeInterface;
    @VisibleForTesting
    @VisibleForTesting
@@ -106,6 +116,11 @@ public class VolumeControlService extends ProfileService {
        Objects.requireNonNull(mAudioManager,
        Objects.requireNonNull(mAudioManager,
                "AudioManager cannot be null when VolumeControlService starts");
                "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
        // Start handler thread for state machines
        mStateMachines.clear();
        mStateMachines.clear();
        mStateMachinesThread = new HandlerThread("VolumeControlService.StateMachines");
        mStateMachinesThread = new HandlerThread("VolumeControlService.StateMachines");
@@ -422,18 +437,51 @@ public class VolumeControlService extends ProfileService {
    }
    }


    void handleVolumeControlChanged(BluetoothDevice device, int groupId,
    void handleVolumeControlChanged(BluetoothDevice device, int groupId,
                                    int volume, boolean mute) {
                                    int volume, boolean mute, boolean isAutonomous) {
        /* TODO handle volume change for group in case of unicast le audio
        if (!isAutonomous) {
         * or per device in case of broadcast or simple remote controller.
            // If the change is triggered by Android device, the stream is already changed.
         * Note: minimum volume is 0 and maximum 255.
            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) {
    void messageFromNative(VolumeControlStackEvent stackEvent) {


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


@@ -495,6 +543,14 @@ public class VolumeControlService extends ProfileService {
            sm = VolumeControlStateMachine.make(device, this,
            sm = VolumeControlStateMachine.make(device, this,
                    mVolumeControlNativeInterface, mStateMachinesThread.getLooper());
                    mVolumeControlNativeInterface, mStateMachinesThread.getLooper());
            mStateMachines.put(device, sm);
            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;
            return sm;
        }
        }
    }
    }
+12 −0
Original line number Original line Diff line number Diff line
@@ -37,6 +37,7 @@ public class VolumeControlStackEvent {
    public int valueInt1;
    public int valueInt1;
    public int valueInt2;
    public int valueInt2;
    public boolean valueBool1;
    public boolean valueBool1;
    public boolean valueBool2;
    /* Might need more for other callbacks*/
    /* Might need more for other callbacks*/


    VolumeControlStackEvent(int type) {
    VolumeControlStackEvent(int type) {
@@ -52,6 +53,7 @@ public class VolumeControlStackEvent {
        result.append(", valueInt1:" + eventTypeValue1ToString(type, valueInt1));
        result.append(", valueInt1:" + eventTypeValue1ToString(type, valueInt1));
        result.append(", valueInt2:" + eventTypeValue2ToString(type, valueInt2));
        result.append(", valueInt2:" + eventTypeValue2ToString(type, valueInt2));
        result.append(", valueBool1:" + eventTypeValueBool1ToString(type, valueBool1));
        result.append(", valueBool1:" + eventTypeValueBool1ToString(type, valueBool1));
        result.append(", valueBool2:" + eventTypeValueBool2ToString(type, valueBool2));
        result.append("}");
        result.append("}");
        return result.toString();
        return result.toString();
    }
    }
@@ -124,4 +126,14 @@ public class VolumeControlStackEvent {
        }
        }
        return Boolean.toString(value);
        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 Original line Diff line number Diff line
@@ -50,6 +50,7 @@ struct VolumeOperation {
  int group_id_;
  int group_id_;


  bool started_;
  bool started_;
  bool is_autonomous_;


  uint8_t opcode_;
  uint8_t opcode_;
  std::vector<uint8_t> arguments_;
  std::vector<uint8_t> arguments_;
@@ -57,11 +58,12 @@ struct VolumeOperation {
  std::vector<RawAddress> devices_;
  std::vector<RawAddress> devices_;
  alarm_t* operation_timeout_;
  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<uint8_t> arguments,
                  std::vector<RawAddress> devices)
                  std::vector<RawAddress> devices)
      : operation_id_(operation_id),
      : operation_id_(operation_id),
        group_id_(group_id),
        group_id_(group_id),
        is_autonomous_(is_autonomous),
        opcode_(opcode),
        opcode_(opcode),
        arguments_(arguments),
        arguments_(arguments),
        devices_(devices) {
        devices_(devices) {
Loading