summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--android/app/jni/com_android_bluetooth_vc.cpp12
-rw-r--r--android/app/src/com/android/bluetooth/a2dp/A2dpService.java9
-rw-r--r--android/app/src/com/android/bluetooth/csip/CsipSetCoordinatorService.java9
-rw-r--r--android/app/src/com/android/bluetooth/hap/HapClientService.java9
-rw-r--r--android/app/src/com/android/bluetooth/hearingaid/HearingAidService.java9
-rw-r--r--android/app/src/com/android/bluetooth/hfp/HeadsetService.java10
-rw-r--r--android/app/src/com/android/bluetooth/le_audio/LeAudioService.java9
-rw-r--r--android/app/src/com/android/bluetooth/vc/VolumeControlNativeInterface.java8
-rw-r--r--android/app/src/com/android/bluetooth/vc/VolumeControlService.java77
-rw-r--r--android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java12
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpStateMachineTest.java1
-rw-r--r--system/bta/vc/types.h4
-rw-r--r--system/bta/vc/vc.cc37
-rw-r--r--system/bta/vc/vc_test.cc14
-rw-r--r--system/btif/src/btif_av.cc9
-rw-r--r--system/btif/src/btif_vc.cc16
-rw-r--r--system/gd/rust/facade/src/main.rs11
-rw-r--r--system/include/hardware/bt_vc.h4
18 files changed, 187 insertions, 73 deletions
diff --git a/android/app/jni/com_android_bluetooth_vc.cpp b/android/app/jni/com_android_bluetooth_vc.cpp
index ce760c2206..5bb744db7a 100644
--- a/android/app/jni/com_android_bluetooth_vc.cpp
+++ b/android/app/jni/com_android_bluetooth_vc.cpp
@@ -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";
}
diff --git a/android/app/src/com/android/bluetooth/a2dp/A2dpService.java b/android/app/src/com/android/bluetooth/a2dp/A2dpService.java
index 7a3b7df82b..2c71f6d463 100644
--- a/android/app/src/com/android/bluetooth/a2dp/A2dpService.java
+++ b/android/app/src/com/android/bluetooth/a2dp/A2dpService.java
@@ -216,8 +216,13 @@ public class A2dpService extends ProfileService {
}
if (mStateMachinesThread != null) {
- mStateMachinesThread.quitSafely();
- mStateMachinesThread = null;
+ try {
+ mStateMachinesThread.quitSafely();
+ mStateMachinesThread.join();
+ mStateMachinesThread = null;
+ } catch (InterruptedException e) {
+ // Do not rethrow as we are shutting down anyway
+ }
}
// Step 2: Reset maximum number of connected audio devices
mMaxConnectedAudioDevices = 1;
diff --git a/android/app/src/com/android/bluetooth/csip/CsipSetCoordinatorService.java b/android/app/src/com/android/bluetooth/csip/CsipSetCoordinatorService.java
index dec6db2e4b..d66dbc01e3 100644
--- a/android/app/src/com/android/bluetooth/csip/CsipSetCoordinatorService.java
+++ b/android/app/src/com/android/bluetooth/csip/CsipSetCoordinatorService.java
@@ -182,8 +182,13 @@ public class CsipSetCoordinatorService extends ProfileService {
}
if (mStateMachinesThread != null) {
- mStateMachinesThread.quitSafely();
- mStateMachinesThread = null;
+ try {
+ mStateMachinesThread.quitSafely();
+ mStateMachinesThread.join();
+ mStateMachinesThread = null;
+ } catch (InterruptedException e) {
+ // Do not rethrow as we are shutting down anyway
+ }
}
mDeviceGroupIdMap.clear();
diff --git a/android/app/src/com/android/bluetooth/hap/HapClientService.java b/android/app/src/com/android/bluetooth/hap/HapClientService.java
index b8aaab841b..dca14bfdc7 100644
--- a/android/app/src/com/android/bluetooth/hap/HapClientService.java
+++ b/android/app/src/com/android/bluetooth/hap/HapClientService.java
@@ -208,8 +208,13 @@ public class HapClientService extends ProfileService {
mPresetsMap.clear();
if (mStateMachinesThread != null) {
- mStateMachinesThread.quitSafely();
- mStateMachinesThread = null;
+ try {
+ mStateMachinesThread.quitSafely();
+ mStateMachinesThread.join();
+ mStateMachinesThread = null;
+ } catch (InterruptedException e) {
+ // Do not rethrow as we are shutting down anyway
+ }
}
// Clear AdapterService
diff --git a/android/app/src/com/android/bluetooth/hearingaid/HearingAidService.java b/android/app/src/com/android/bluetooth/hearingaid/HearingAidService.java
index 4f4a45ad6b..98cd2caadc 100644
--- a/android/app/src/com/android/bluetooth/hearingaid/HearingAidService.java
+++ b/android/app/src/com/android/bluetooth/hearingaid/HearingAidService.java
@@ -189,8 +189,13 @@ public class HearingAidService extends ProfileService {
mHiSyncIdConnectedMap.clear();
if (mStateMachinesThread != null) {
- mStateMachinesThread.quitSafely();
- mStateMachinesThread = null;
+ try {
+ mStateMachinesThread.quitSafely();
+ mStateMachinesThread.join();
+ mStateMachinesThread = null;
+ } catch (InterruptedException e) {
+ // Do not rethrow as we are shutting down anyway
+ }
}
// Clear AdapterService, HearingAidNativeInterface
diff --git a/android/app/src/com/android/bluetooth/hfp/HeadsetService.java b/android/app/src/com/android/bluetooth/hfp/HeadsetService.java
index b4eca8f538..361e247cdd 100644
--- a/android/app/src/com/android/bluetooth/hfp/HeadsetService.java
+++ b/android/app/src/com/android/bluetooth/hfp/HeadsetService.java
@@ -236,8 +236,14 @@ public class HeadsetService extends ProfileService {
// Step 3: Destroy system interface
mSystemInterface.stop();
// Step 2: Stop handler thread
- mStateMachinesThread.quitSafely();
- mStateMachinesThread = null;
+ try {
+ mStateMachinesThread.quitSafely();
+ mStateMachinesThread.join();
+ mStateMachinesThread = null;
+ } catch (InterruptedException e) {
+ // Do not rethrow as we are shutting down anyway
+ }
+
mStateMachinesThreadHandler = null;
// Step 1: Clear
synchronized (mStateMachines) {
diff --git a/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java b/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java
index a94a5687c1..e6d06e2e25 100644
--- a/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java
+++ b/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java
@@ -260,8 +260,13 @@ public class LeAudioService extends ProfileService {
}
if (mStateMachinesThread != null) {
- mStateMachinesThread.quitSafely();
- mStateMachinesThread = null;
+ try {
+ mStateMachinesThread.quitSafely();
+ mStateMachinesThread.join();
+ mStateMachinesThread = null;
+ } catch (InterruptedException e) {
+ // Do not rethrow as we are shutting down anyway
+ }
}
mAudioManager = null;
diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlNativeInterface.java b/android/app/src/com/android/bluetooth/vc/VolumeControlNativeInterface.java
index ee6fd37b26..0d2b0ec0af 100644
--- a/android/app/src/com/android/bluetooth/vc/VolumeControlNativeInterface.java
+++ b/android/app/src/com/android/bluetooth/vc/VolumeControlNativeInterface.java
@@ -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);
diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java
index 91fafa0c05..732679a366 100644
--- a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java
+++ b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java
@@ -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");
@@ -164,8 +179,13 @@ public class VolumeControlService extends ProfileService {
if (mStateMachinesThread != null) {
- mStateMachinesThread.quitSafely();
- mStateMachinesThread = null;
+ try {
+ mStateMachinesThread.quitSafely();
+ mStateMachinesThread.join();
+ mStateMachinesThread = null;
+ } catch (InterruptedException e) {
+ // Do not rethrow as we are shutting down anyway
+ }
}
// Clear AdapterService, VolumeControlNativeInterface
@@ -422,18 +442,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 +548,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;
}
}
diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java b/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java
index c5d4aa336b..2750c7e694 100644
--- a/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java
+++ b/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java
@@ -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);
+ }
}
diff --git a/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpStateMachineTest.java
index b38c8423c2..2530facca4 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpStateMachineTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpStateMachineTest.java
@@ -122,6 +122,7 @@ public class A2dpStateMachineTest {
}
mA2dpStateMachine.doQuit();
mHandlerThread.quit();
+ mHandlerThread.join();
TestUtils.clearAdapterService(mAdapterService);
}
diff --git a/system/bta/vc/types.h b/system/bta/vc/types.h
index 4461d65c92..a8a4b252c8 100644
--- a/system/bta/vc/types.h
+++ b/system/bta/vc/types.h
@@ -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) {
diff --git a/system/bta/vc/vc.cc b/system/bta/vc/vc.cc
index 08f61e8774..23a20bf8c8 100644
--- a/system/bta/vc/vc.cc
+++ b/system/bta/vc/vc.cc
@@ -285,7 +285,7 @@ class VolumeControlImpl : public VolumeControl {
if (!csis_api) {
DLOG(INFO) << __func__ << " Csis is not available";
callbacks_->OnVolumeStateChanged(device->address, device->volume,
- device->mute);
+ device->mute, true);
return;
}
@@ -294,7 +294,7 @@ class VolumeControlImpl : public VolumeControl {
if (group_id == bluetooth::groups::kGroupUnknown) {
DLOG(INFO) << __func__ << " No group for device " << device->address;
callbacks_->OnVolumeStateChanged(device->address, device->volume,
- device->mute);
+ device->mute, true);
return;
}
@@ -310,7 +310,7 @@ class VolumeControlImpl : public VolumeControl {
if (is_volume_change) {
std::vector<uint8_t> arg({device->volume});
- PrepareVolumeControlOperation(devices, group_id,
+ PrepareVolumeControlOperation(devices, group_id, true,
kControlPointOpcodeSetAbsoluteVolume, arg);
}
@@ -318,7 +318,7 @@ class VolumeControlImpl : public VolumeControl {
std::vector<uint8_t> arg;
uint8_t opcode =
device->mute ? kControlPointOpcodeMute : kControlPointOpcodeUnmute;
- PrepareVolumeControlOperation(devices, group_id, opcode, arg);
+ PrepareVolumeControlOperation(devices, group_id, true, opcode, arg);
}
StartQueueOperation();
@@ -354,7 +354,7 @@ class VolumeControlImpl : public VolumeControl {
/* This is just a read, send single notification */
if (!is_notification) {
callbacks_->OnVolumeStateChanged(device->address, device->volume,
- device->mute);
+ device->mute, false);
return;
}
@@ -384,12 +384,15 @@ class VolumeControlImpl : public VolumeControl {
return;
}
- if (op->IsGroupOperation())
+ if (op->IsGroupOperation()) {
callbacks_->OnGroupVolumeStateChanged(op->group_id_, device->volume,
- device->mute);
- else
+ device->mute, op->is_autonomous_);
+ } else {
+ /* op->is_autonomous_ will always be false,
+ since we only make it true for group operations */
callbacks_->OnVolumeStateChanged(device->address, device->volume,
- device->mute);
+ device->mute, false);
+ }
ongoing_operations_.erase(op);
StartQueueOperation();
@@ -591,14 +594,16 @@ class VolumeControlImpl : public VolumeControl {
}
void PrepareVolumeControlOperation(std::vector<RawAddress>& devices,
- int group_id, uint8_t opcode,
+ int group_id, bool is_autonomous,
+ uint8_t opcode,
std::vector<uint8_t>& arguments) {
DLOG(INFO) << __func__ << " num of devices: " << devices.size()
- << " group_id: " << group_id << " opcode: " << +opcode
+ << " group_id: " << group_id << " is_autonomous: " << is_autonomous
+ << " opcode: " << +opcode
<< " arg size: " << arguments.size();
- ongoing_operations_.emplace_back(latest_operation_id_++, group_id, opcode,
- arguments, devices);
+ ongoing_operations_.emplace_back(latest_operation_id_++, group_id, is_autonomous,
+ opcode, arguments, devices);
}
void SetVolume(std::variant<RawAddress, int> addr_or_group_id,
@@ -613,7 +618,7 @@ class VolumeControlImpl : public VolumeControl {
std::vector<RawAddress> devices = {
std::get<RawAddress>(addr_or_group_id)};
- PrepareVolumeControlOperation(devices, bluetooth::groups::kGroupUnknown,
+ PrepareVolumeControlOperation(devices, bluetooth::groups::kGroupUnknown, false,
opcode, arg);
} else {
/* Handle group change */
@@ -641,7 +646,7 @@ class VolumeControlImpl : public VolumeControl {
return;
}
- PrepareVolumeControlOperation(devices, group_id, opcode, arg);
+ PrepareVolumeControlOperation(devices, group_id, false, opcode, arg);
}
StartQueueOperation();
@@ -681,7 +686,7 @@ class VolumeControlImpl : public VolumeControl {
// once profile connected we can notify current states
callbacks_->OnVolumeStateChanged(device->address, device->volume,
- device->mute);
+ device->mute, false);
device->EnqueueRemainingRequests(gatt_if_, chrc_read_callback_static,
OnGattWriteCccStatic);
diff --git a/system/bta/vc/vc_test.cc b/system/bta/vc/vc_test.cc
index 41d4f20117..c4ccaa97d9 100644
--- a/system/bta/vc/vc_test.cc
+++ b/system/bta/vc/vc_test.cc
@@ -71,10 +71,10 @@ class MockVolumeControlCallbacks : public VolumeControlCallbacks {
MOCK_METHOD((void), OnConnectionState,
(ConnectionState state, const RawAddress& address), (override));
MOCK_METHOD((void), OnVolumeStateChanged,
- (const RawAddress& address, uint8_t volume, bool mute),
+ (const RawAddress& address, uint8_t volume, bool mute, bool isAutonomous),
(override));
MOCK_METHOD((void), OnGroupVolumeStateChanged,
- (int group_id, uint8_t volume, bool mute), (override));
+ (int group_id, uint8_t volume, bool mute, bool isAutonomous), (override));
private:
DISALLOW_COPY_AND_ASSIGN(MockVolumeControlCallbacks);
@@ -560,7 +560,7 @@ TEST_F(VolumeControlTest, test_subscribe_vcs_volume_state) {
TEST_F(VolumeControlTest, test_read_vcs_volume_state) {
const RawAddress test_address = GetTestAddress(0);
- EXPECT_CALL(*callbacks, OnVolumeStateChanged(test_address, _, _));
+ EXPECT_CALL(*callbacks, OnVolumeStateChanged(test_address, _, _, false));
std::vector<uint16_t> handles({0x0021});
TestReadCharacteristic(test_address, 1, handles);
}
@@ -605,12 +605,12 @@ class VolumeControlCallbackTest : public VolumeControlTest {
TEST_F(VolumeControlCallbackTest, test_volume_state_changed) {
std::vector<uint8_t> value({0x03, 0x01, 0x02});
- EXPECT_CALL(*callbacks, OnVolumeStateChanged(test_address, 0x03, true));
+ EXPECT_CALL(*callbacks, OnVolumeStateChanged(test_address, 0x03, true, true));
GetNotificationEvent(0x0021, value);
}
TEST_F(VolumeControlCallbackTest, test_volume_state_changed_malformed) {
- EXPECT_CALL(*callbacks, OnVolumeStateChanged(test_address, _, _)).Times(0);
+ EXPECT_CALL(*callbacks, OnVolumeStateChanged(test_address, _, _, _)).Times(0);
std::vector<uint8_t> too_short({0x03, 0x01});
GetNotificationEvent(0x0021, too_short);
std::vector<uint8_t> too_long({0x03, 0x01, 0x02, 0x03});
@@ -726,7 +726,7 @@ TEST_F(VolumeControlCsis, test_set_volume) {
VolumeControl::Get()->SetVolume(group_id, 10);
/* Now inject notification and make sure callback is sent up to Java layer */
- EXPECT_CALL(*callbacks, OnGroupVolumeStateChanged(group_id, 0x03, true));
+ EXPECT_CALL(*callbacks, OnGroupVolumeStateChanged(group_id, 0x03, true, false));
std::vector<uint8_t> value({0x03, 0x01, 0x02});
GetNotificationEvent(conn_id_1, test_address_1, 0x0021, value);
@@ -735,7 +735,7 @@ TEST_F(VolumeControlCsis, test_set_volume) {
TEST_F(VolumeControlCsis, autonomus_test_set_volume) {
/* Now inject notification and make sure callback is sent up to Java layer */
- EXPECT_CALL(*callbacks, OnGroupVolumeStateChanged(group_id, 0x03, false));
+ EXPECT_CALL(*callbacks, OnGroupVolumeStateChanged(group_id, 0x03, false, true));
std::vector<uint8_t> value({0x03, 0x00, 0x02});
GetNotificationEvent(conn_id_1, test_address_1, 0x0021, value);
diff --git a/system/btif/src/btif_av.cc b/system/btif/src/btif_av.cc
index b2fc783c32..e67722156f 100644
--- a/system/btif/src/btif_av.cc
+++ b/system/btif/src/btif_av.cc
@@ -2320,6 +2320,15 @@ bool BtifAvStateMachine::StateClosing::ProcessEvent(uint32_t event,
btif_a2dp_on_offload_started(peer_.PeerAddress(), BTA_AV_FAIL);
break;
+ case BTIF_AV_CONNECT_REQ_EVT:
+ BTIF_TRACE_WARNING("%s: Peer %s : Ignore %s in StateClosing",
+ __PRETTY_FUNCTION__,
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str());
+ btif_queue_advance();
+ peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateIdle);
+ break;
+
default:
BTIF_TRACE_WARNING("%s: Peer %s : Unhandled event=%s",
__PRETTY_FUNCTION__,
diff --git a/system/btif/src/btif_vc.cc b/system/btif/src/btif_vc.cc
index 66374e215e..61ecb20172 100644
--- a/system/btif/src/btif_vc.cc
+++ b/system/btif/src/btif_vc.cc
@@ -55,21 +55,21 @@ class VolumeControlInterfaceImpl : public VolumeControlInterface,
}
void OnVolumeStateChanged(const RawAddress& address, uint8_t volume,
- bool mute) override {
- DVLOG(2) << __func__ << " address: " << address << "volume: " << volume
- << "mute: " << mute;
+ bool mute, bool isAutonomous) override {
+ DVLOG(2) << __func__ << " address: " << address << " volume: " << volume
+ << " mute: " << mute << " isAutonomous: " << isAutonomous;
do_in_jni_thread(FROM_HERE,
Bind(&VolumeControlCallbacks::OnVolumeStateChanged,
- Unretained(callbacks_), address, volume, mute));
+ Unretained(callbacks_), address, volume, mute, isAutonomous));
}
void OnGroupVolumeStateChanged(int group_id, uint8_t volume,
- bool mute) override {
- DVLOG(2) << __func__ << "group_id: " << group_id << "volume: " << volume
- << "mute: " << mute;
+ bool mute, bool isAutonomous) override {
+ DVLOG(2) << __func__ << " group_id: " << group_id << " volume: " << volume
+ << " mute: " << mute << " isAutonomous: " << isAutonomous;
do_in_jni_thread(FROM_HERE,
Bind(&VolumeControlCallbacks::OnGroupVolumeStateChanged,
- Unretained(callbacks_), group_id, volume, mute));
+ Unretained(callbacks_), group_id, volume, mute, isAutonomous));
}
void Connect(const RawAddress& address) override {
diff --git a/system/gd/rust/facade/src/main.rs b/system/gd/rust/facade/src/main.rs
index 55cfb0ca8d..3ce456cdff 100644
--- a/system/gd/rust/facade/src/main.rs
+++ b/system/gd/rust/facade/src/main.rs
@@ -14,10 +14,7 @@ use futures::stream::StreamExt;
use grpcio::*;
use log::debug;
use nix::sys::signal;
-use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use std::sync::{Arc, Mutex};
-use tokio::io::AsyncWriteExt;
-use tokio::net::TcpStream;
use tokio::runtime::Runtime;
fn main() {
@@ -51,7 +48,6 @@ async fn async_main(rt: Arc<Runtime>, mut sigint: mpsc::UnboundedReceiver<()>) {
let root_server_port = value_t!(matches, "root-server-port", u16).unwrap();
let grpc_port = value_t!(matches, "grpc-port", u16).unwrap();
- let signal_port = value_t!(matches, "signal-port", u16).unwrap();
let rootcanal_port = value_t!(matches, "rootcanal-port", u16).ok();
let env = Arc::new(Environment::new(2));
let mut server = ServerBuilder::new(env)
@@ -66,17 +62,10 @@ async fn async_main(rt: Arc<Runtime>, mut sigint: mpsc::UnboundedReceiver<()>) {
.unwrap();
server.start();
- indicate_started(signal_port).await;
sigint.next().await;
block_on(server.shutdown()).unwrap();
}
-async fn indicate_started(signal_port: u16) {
- let address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), signal_port);
- let mut stream = TcpStream::connect(address).await.unwrap();
- stream.shutdown().await.unwrap();
-}
-
// TODO: remove as this is a temporary nix-based hack to catch SIGINT
fn install_sigint() -> mpsc::UnboundedReceiver<()> {
let (tx, rx) = mpsc::unbounded();
diff --git a/system/include/hardware/bt_vc.h b/system/include/hardware/bt_vc.h
index fb0b725fac..e7f498b6cb 100644
--- a/system/include/hardware/bt_vc.h
+++ b/system/include/hardware/bt_vc.h
@@ -42,11 +42,11 @@ class VolumeControlCallbacks {
/* Callback for the volume change changed on the device */
virtual void OnVolumeStateChanged(const RawAddress& address, uint8_t volume,
- bool mute) = 0;
+ bool mute, bool isAutonomous) = 0;
/* Callback for the volume change changed on the group*/
virtual void OnGroupVolumeStateChanged(int group_id, uint8_t volume,
- bool mute) = 0;
+ bool mute, bool isAutonomous) = 0;
};
class VolumeControlInterface {