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

Commit 1aa41f8a authored by William Escande's avatar William Escande Committed by Automerger Merge Worker
Browse files

Merge "AICS: add pts-bot testing" into main am: 35af90a3

parents 70561370 35af90a3
Loading
Loading
Loading
Loading
+4 −1
Original line number Original line Diff line number Diff line
@@ -220,7 +220,10 @@ class VolumeControlInputDescriptor {
        Descriptor desc = mVolumeInputs[id];
        Descriptor desc = mVolumeInputs[id];


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

            throw new IllegalArgumentException(
                    ("gainSetting=" + gainSetting + " is not in correct range")
                            + (" [" + desc.mGainSettingsMin + "-" + desc.mGainSettingsMax + "]"));
        }
        }


        if (desc.mGainMode == bluetooth.constants.aics.GainMode.AUTOMATIC
        if (desc.mGainMode == bluetooth.constants.aics.GainMode.AUTOMATIC
+87 −9
Original line number Original line Diff line number Diff line
@@ -94,8 +94,8 @@ class VCPProxy(ProfileProxy):
    def IUT_INITIATE_DISCOVER_CHARACTERISTIC(self, **kwargs):
    def IUT_INITIATE_DISCOVER_CHARACTERISTIC(self, **kwargs):
        """
        """
        Please take action to discover the
        Please take action to discover the
        (Volume Control Point|Volume State|Volume Flags|Offset State|Volume Offset Control Point)
        (Volume (Control Point|State|Flags|Offset Control Point)|Offset State|Audio Input (State|Type|Status|Control Point|Description)|Gain Setting Properties)
        characteristic from the Volume (Offset )?Control. Discover the primary service if needed.
        characteristic from the (Volume( Offset)?|Audio Input) Control. Discover the primary service if needed.
        Description: Verify that the Implementation Under Test \(IUT\) can send
        Description: Verify that the Implementation Under Test \(IUT\) can send
        Discover All Characteristics command.
        Discover All Characteristics command.
        """
        """
@@ -108,9 +108,10 @@ class VCPProxy(ProfileProxy):
    @match_description
    @match_description
    def IUT_READ_CHARACTERISTIC(self, name: str, handle: str, **kwargs):
    def IUT_READ_CHARACTERISTIC(self, name: str, handle: str, **kwargs):
        """
        """
        Please send Read Request to read (?P<name>(Volume State|Volume Flags|Offset State)) characteristic with handle
        Please send Read Request to read (?P<name>(Volume State|Volume Flags|Offset State|Audio Input (State|Status|Type)|Gain Setting Properties)) characteristic with handle
        = (?P<handle>(0x[0-9A-Fa-f]{4})).
        = (?P<handle>(0x[0-9A-Fa-f]{4})).
        """
        """

        # After discovery Android reads these values by itself, after profile connection.
        # After discovery Android reads these values by itself, after profile connection.
        # Although, for some tests, this is used as validation, for example for tests with invalid
        # Although, for some tests, this is used as validation, for example for tests with invalid
        # behavior (BI tests). Just send GATT read to sattisfy this conditions, as VCP has no exposed
        # behavior (BI tests). Just send GATT read to sattisfy this conditions, as VCP has no exposed
@@ -139,7 +140,7 @@ class VCPProxy(ProfileProxy):
    def IUT_CONFIG_NOTIFICATION(self, name: str, **kwargs):
    def IUT_CONFIG_NOTIFICATION(self, name: str, **kwargs):
        """
        """
        Please write to Client Characteristic Configuration Descriptor of
        Please write to Client Characteristic Configuration Descriptor of
        (?P<name>(Volume State|Offset State)) characteristic to enable notification.
        (?P<name>(Volume State|Offset State|Audio Input State)) characteristic to enable notification.(.*)
        """
        """


        # After discovery Android subscribes by itself, after profile connection
        # After discovery Android subscribes by itself, after profile connection
@@ -149,12 +150,12 @@ class VCPProxy(ProfileProxy):
    def IUT_SEND_WRITE_REQUEST(self, description: str, chr_name: str, op_code: str, **kwargs):
    def IUT_SEND_WRITE_REQUEST(self, description: str, chr_name: str, op_code: str, **kwargs):
        r"""
        r"""
        Please send write request to handle 0x([0-9A-Fa-f]{4}) with following value.
        Please send write request to handle 0x([0-9A-Fa-f]{4}) with following value.
        (?P<chr_name>(Volume Control Point|Volume Offset Control Point)):
        (?P<chr_name>(Volume Control Point|Volume Offset Control Point|Audio Input Control Point)):
            Op Code: (?P<op_code>((<WildCard: Exists>)|(\[[0-9] \(0x0[0-9]\)\]\s([\w]*\s){1,3})))(.*)
            Op Code: (?P<op_code>((<WildCard: Exists>)|(\[[0-9] \(0x0[0-9]\)\]\s([\w]*\s){1,4})))(.*)
        """
        """


        # Wait a couple seconds so the VCP is ready (subscriptions and reads are completed)
        # Wait a couple seconds so the VCP is ready (subscriptions and reads are completed)
        sleep(2)
        sleep(4)


        if (chr_name == "Volume Control Point"):
        if (chr_name == "Volume Control Point"):
            if "Set Absolute Volume" in op_code:
            if "Set Absolute Volume" in op_code:
@@ -166,9 +167,23 @@ class VCPProxy(ProfileProxy):
                # Handles sending *any* OP Code on Volume Control Point
                # Handles sending *any* OP Code on Volume Control Point
                self.vcp.SetDeviceVolume(connection=self.connection, volume=42)
                self.vcp.SetDeviceVolume(connection=self.connection, volume=42)
        elif (chr_name == "Volume Offset Control Point"):
        elif (chr_name == "Volume Offset Control Point"):
            if ("Set Volume Offset" in op_code or
            if ("Set Volume Offset" in op_code or "<WildCard: Exists>" in op_code):
                "<WildCard: Exists>" in op_code):
                self.vcp.SetVolumeOffset(connection=self.connection, offset=42)
                self.vcp.SetVolumeOffset(connection=self.connection, offset=42)
        elif (chr_name == "Audio Input Control Point"):
            if "[1 (0x01)] Set Gain Setting" in op_code:
                self.vcp.SetGainSetting(connection=self.connection, gainSetting=42)
            elif "[2 (0x02)] Unmute" in op_code:
                self.vcp.SetMute(connection=self.connection, mute=0x00)
            elif "[3 (0x03)] Mute" in op_code:
                self.vcp.SetMute(connection=self.connection, mute=0x01)
            elif "[4 (0x04)] Set Manual Gain Mode" in op_code:
                self.vcp.SetGainMode(connection=self.connection, gainMode=0x02)
            elif "[5 (0x05)] Set Automatic Gain Mode" in op_code:
                self.vcp.SetGainMode(connection=self.connection, gainMode=0x03)
            elif "<WildCard: Exists>" in op_code:
                self.vcp.SetMute(connection=self.connection, mute=0)
            else:
                assert False, f'Unhandled op_code in IUT_SEND_WRITE_REQUEST:\n{op_code}'
        else:
        else:
            return "No"
            return "No"


@@ -181,3 +196,66 @@ class VCPProxy(ProfileProxy):
        otherwise click 'No'.
        otherwise click 'No'.
        """
        """
        return "OK"
        return "OK"

    @assert_description
    def IUT_WRITE_GAIN_SETTING_MAX(self, **kwargs):
        """
        Please write to Audio Input Control Point with the Set Gain Setting Op
        Code value of 0x01, the Gain Setting parameters set to a random value
        greater than 100 and the Change Counter parameter set.
        """
        # Wait a couple seconds so the VCP is ready (subscriptions and reads are completed)
        sleep(4)

        self.vcp.SetGainSetting(connection=self.connection, gainSetting=101)

        return "OK"

    @assert_description
    def IUT_WRITE_UNMUTE_OPCODE(self, **kwargs):
        """
        Please write to Audio Input Control Point with the Unmute Op Code.
        """
        # Wait a couple seconds so the VCP is ready (subscriptions and reads are completed)
        sleep(4)

        self.vcp.SetMute(connection=self.connection, mute=0x00)

        return "OK"

    @assert_description
    def IUT_WRITE_MUTE_OPCODE(self, **kwargs):
        """
        Please write to Audio Input Control Point with the Mute Op Code.
        """
        # Wait a couple seconds so the VCP is ready (subscriptions and reads are completed)
        sleep(4)

        self.vcp.SetMute(connection=self.connection, mute=0x01)

        return "OK"

    @assert_description
    def IUT_WRITE_SET_MANUAL_GAIN_MODE_OPCODE(self, **kwargs):
        """
        Please write to Audio Input Control Point with the Set Manual Op Code.
        """
        # Wait a couple seconds so the VCP is ready (subscriptions and reads are completed)
        sleep(4)

        self.vcp.SetGainMode(connection=self.connection, gainMode=0x02)

        return "OK"

    @assert_description
    def IUT_WRITE_SET_AUTOMATIC_GAIN_MODE_OPCODE(self, **kwargs):
        """
        Please write to Audio Input Control Point with the Set Automatic Op
        Code.
        """
        # Wait a couple seconds so the VCP is ready (subscriptions and reads are completed)
        sleep(4)

        self.vcp.SetGainMode(connection=self.connection, gainMode=0x03)

        return "OK"
+73 −0
Original line number Original line Diff line number Diff line
@@ -686,17 +686,38 @@
    "SM/PER/SCJW/BV-03-C",
    "SM/PER/SCJW/BV-03-C",
    "SM/PER/SCPK/BI-03-C",
    "SM/PER/SCPK/BI-03-C",
    "SM/PER/SCPK/BV-02-C",
    "SM/PER/SCPK/BV-02-C",
    "VCP/VC/AICP/BV-01-C",
    "VCP/VC/AICP/BV-02-C",
    "VCP/VC/AICP/BV-03-C",
    "VCP/VC/AICP/BV-04-C",
    "VCP/VC/AICP/BV-05-C",
    "VCP/VC/CGGIT/CHA/BV-01-C",
    "VCP/VC/CGGIT/CHA/BV-01-C",
    "VCP/VC/CGGIT/CHA/BV-02-C",
    "VCP/VC/CGGIT/CHA/BV-02-C",
    "VCP/VC/CGGIT/CHA/BV-03-C",
    "VCP/VC/CGGIT/CHA/BV-03-C",
    "VCP/VC/CGGIT/CHA/BV-04-C",
    "VCP/VC/CGGIT/CHA/BV-04-C",
    "VCP/VC/CGGIT/CHA/BV-06-C",
    "VCP/VC/CGGIT/CHA/BV-06-C",
    "VCP/VC/CGGIT/CHA/BV-08-C",
    "VCP/VC/CGGIT/CHA/BV-09-C",
    "VCP/VC/CGGIT/CHA/BV-10-C",
    "VCP/VC/CGGIT/CHA/BV-11-C",
    "VCP/VC/CGGIT/CHA/BV-12-C",
    "VCP/VC/CGGIT/CHA/BV-13-C",
    "VCP/VC/CGGIT/SER/BV-01-C",
    "VCP/VC/CGGIT/SER/BV-01-C",
    "VCP/VC/CGGIT/SER/BV-02-C",
    "VCP/VC/CGGIT/SER/BV-02-C",
    "VCP/VC/CGGIT/SER/BV-03-C",
    "VCP/VC/SPE/BI-05-C",
    "VCP/VC/SPE/BI-05-C",
    "VCP/VC/SPE/BI-08-C",
    "VCP/VC/SPE/BI-09-C",
    "VCP/VC/SPE/BI-10-C",
    "VCP/VC/SPE/BI-11-C",
    "VCP/VC/SPE/BI-12-C",
    "VCP/VC/SPE/BI-13-C",
    "VCP/VC/SPE/BI-13-C",
    "VCP/VC/SPE/BI-15-C",
    "VCP/VC/SPE/BI-15-C",
    "VCP/VC/SPE/BI-16-C",
    "VCP/VC/SPE/BI-16-C",
    "VCP/VC/SPE/BI-17-C",
    "VCP/VC/SPE/BI-18-C",
    "VCP/VC/SPE/BI-19-C",
    "VCP/VC/SPE/BI-20-C",
    "VCP/VC/VCCP/BV-05-C",
    "VCP/VC/VCCP/BV-05-C",
    "VCP/VC/VOCP/BV-01-C"
    "VCP/VC/VOCP/BV-01-C"
  ],
  ],
@@ -1158,6 +1179,7 @@
    "SM/PER/SIE/BV-01-C",
    "SM/PER/SIE/BV-01-C",
    "SM/PER/SIP/BV-01-C",
    "SM/PER/SIP/BV-01-C",
    "VCP/VC/SPE/BI-06-C",
    "VCP/VC/SPE/BI-06-C",
    "VCP/VC/SPE/BI-14-C",
    "VCP/VC/VCCP/BV-06-C"
    "VCP/VC/VCCP/BV-06-C"
  ],
  ],
  "ics": {
  "ics": {
@@ -3056,6 +3078,7 @@
    "TSPC_VCP_8_1": true,
    "TSPC_VCP_8_1": true,
    "TSPC_VCP_10_1": true,
    "TSPC_VCP_10_1": true,
    "TSPC_VCP_10_2": true,
    "TSPC_VCP_10_2": true,
    "TSPC_VCP_10_3": true,
    "TSPC_VCP_11_1": true,
    "TSPC_VCP_11_1": true,
    "TSPC_VCP_11_2": true,
    "TSPC_VCP_11_2": true,
    "TSPC_VCP_11_3": true,
    "TSPC_VCP_11_3": true,
@@ -3073,6 +3096,26 @@
    "TSPC_VCP_14_3": true,
    "TSPC_VCP_14_3": true,
    "TSPC_VCP_14_4": true,
    "TSPC_VCP_14_4": true,
    "TSPC_VCP_14_6": true,
    "TSPC_VCP_14_6": true,
    "TSPC_VCP_15_1": true,
    "TSPC_VCP_15_2": true,
    "TSPC_VCP_15_3": true,
    "TSPC_VCP_15_4": true,
    "TSPC_VCP_15_5": true,
    "TSPC_VCP_15_6": true,
    "TSPC_VCP_16_1": true,
    "TSPC_VCP_16_2": true,
    "TSPC_VCP_16_3": true,
    "TSPC_VCP_16_4": true,
    "TSPC_VCP_16_5": true,
    "TSPC_VCP_16_6": true,
    "TSPC_VCP_16_7": true,
    "TSPC_VCP_16_8": true,
    "TSPC_VCP_16_9": true,
    "TSPC_VCP_16_10": true,
    "TSPC_VCP_16_11": true,
    "TSPC_VCP_16_12": true,
    "TSPC_VCP_16_13": true,
    "TSPC_VCP_16_14": true,
    "TSPC_VCP_17_1": true,
    "TSPC_VCP_17_1": true,
    "TSPC_VCP_17_2": true,
    "TSPC_VCP_17_2": true,
    "TSPC_VCP_17_3": true,
    "TSPC_VCP_17_3": true,
@@ -3188,6 +3231,36 @@
      "tests": [
      "tests": [
        "HAP"
        "HAP"
      ]
      ]
    },
    {
      "flags": [
        "leaudio_add_aics_support",
        "aics_api"
      ],
      "tests": [
        "VCP/VC/AICP/BV-01-C",
        "VCP/VC/AICP/BV-02-C",
        "VCP/VC/AICP/BV-03-C",
        "VCP/VC/AICP/BV-04-C",
        "VCP/VC/AICP/BV-05-C",
        "VCP/VC/CGGIT/CHA/BV-08-C",
        "VCP/VC/CGGIT/CHA/BV-09-C",
        "VCP/VC/CGGIT/CHA/BV-10-C",
        "VCP/VC/CGGIT/CHA/BV-11-C",
        "VCP/VC/CGGIT/CHA/BV-12-C",
        "VCP/VC/CGGIT/CHA/BV-13-C",
        "VCP/VC/CGGIT/SER/BV-03-C",
        "VCP/VC/SPE/BI-08-C",
        "VCP/VC/SPE/BI-09-C",
        "VCP/VC/SPE/BI-10-C",
        "VCP/VC/SPE/BI-11-C",
        "VCP/VC/SPE/BI-12-C",
        "VCP/VC/SPE/BI-14-C",
        "VCP/VC/SPE/BI-17-C",
        "VCP/VC/SPE/BI-18-C",
        "VCP/VC/SPE/BI-19-C",
        "VCP/VC/SPE/BI-20-C"
      ]
    }
    }
  ]
  ]
}
}
+49 −20
Original line number Original line Diff line number Diff line
@@ -17,37 +17,26 @@
package com.android.pandora
package com.android.pandora


import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothDevice.TRANSPORT_LE
import android.bluetooth.BluetoothVolumeControl
import android.bluetooth.BluetoothManager
import android.bluetooth.BluetoothManager
import android.bluetooth.BluetoothProfile
import android.bluetooth.BluetoothProfile
import android.bluetooth.BluetoothProfile.CONNECTION_POLICY_ALLOWED
import android.bluetooth.BluetoothProfile.CONNECTION_POLICY_ALLOWED
import android.bluetooth.BluetoothVolumeControl
import android.content.Context
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.IntentFilter
import android.util.Log
import android.util.Log
import com.google.protobuf.Empty
import com.google.protobuf.Empty
import io.grpc.Status
import io.grpc.stub.StreamObserver
import io.grpc.stub.StreamObserver
import java.io.Closeable
import java.io.Closeable
import java.io.PrintWriter
import java.io.StringWriter
import java.util.concurrent.Executors
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.cancel
import kotlinx.coroutines.cancel
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.shareIn
import kotlinx.coroutines.flow.shareIn
import pandora.vcp.VCPGrpc.VCPImplBase
import pandora.vcp.VCPGrpc.VCPImplBase
import pandora.vcp.VcpProto.*
import pandora.vcp.VcpProto.*
import pandora.HostProto.Connection


@kotlinx.coroutines.ExperimentalCoroutinesApi
@kotlinx.coroutines.ExperimentalCoroutinesApi
class Vcp(val context: Context) : VCPImplBase(), Closeable {
class Vcp(val context: Context) : VCPImplBase(), Closeable {
@@ -78,7 +67,7 @@ class Vcp(val context: Context) : VCPImplBase(), Closeable {


    override fun setDeviceVolume(
    override fun setDeviceVolume(
        request: SetDeviceVolumeRequest,
        request: SetDeviceVolumeRequest,
        responseObserver: StreamObserver<Empty>
        responseObserver: StreamObserver<Empty>,
    ) {
    ) {
        grpcUnary<Empty>(scope, responseObserver) {
        grpcUnary<Empty>(scope, responseObserver) {
            val device = request.connection.toBluetoothDevice(bluetoothAdapter)
            val device = request.connection.toBluetoothDevice(bluetoothAdapter)
@@ -93,7 +82,7 @@ class Vcp(val context: Context) : VCPImplBase(), Closeable {


    override fun setVolumeOffset(
    override fun setVolumeOffset(
        request: SetVolumeOffsetRequest,
        request: SetVolumeOffsetRequest,
        responseObserver: StreamObserver<Empty>
        responseObserver: StreamObserver<Empty>,
    ) {
    ) {
        grpcUnary<Empty>(scope, responseObserver) {
        grpcUnary<Empty>(scope, responseObserver) {
            val device = request.connection.toBluetoothDevice(bluetoothAdapter)
            val device = request.connection.toBluetoothDevice(bluetoothAdapter)
@@ -106,15 +95,13 @@ class Vcp(val context: Context) : VCPImplBase(), Closeable {
        }
        }
    }
    }


    override fun waitConnect(
    override fun waitConnect(request: WaitConnectRequest, responseObserver: StreamObserver<Empty>) {
        request: WaitConnectRequest,
        responseObserver: StreamObserver<Empty>
    ) {
        grpcUnary<Empty>(scope, responseObserver) {
        grpcUnary<Empty>(scope, responseObserver) {
            val device = request.connection.toBluetoothDevice(bluetoothAdapter)
            val device = request.connection.toBluetoothDevice(bluetoothAdapter)
            Log.i(TAG, "waitPeripheral(${device}")
            Log.i(TAG, "waitPeripheral(${device}")
            if (
            if (
                bluetoothVolumeControl.getConnectionState(device) != BluetoothProfile.STATE_CONNECTED
                bluetoothVolumeControl.getConnectionState(device) !=
                    BluetoothProfile.STATE_CONNECTED
            ) {
            ) {
                Log.d(TAG, "Manual call to setConnectionPolicy")
                Log.d(TAG, "Manual call to setConnectionPolicy")
                bluetoothVolumeControl.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED)
                bluetoothVolumeControl.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED)
@@ -129,4 +116,46 @@ class Vcp(val context: Context) : VCPImplBase(), Closeable {
            Empty.getDefaultInstance()
            Empty.getDefaultInstance()
        }
        }
    }
    }

    override fun setGainSetting(
        request: SetGainSettingRequest,
        responseObserver: StreamObserver<Empty>,
    ) {
        grpcUnary<Empty>(scope, responseObserver) {
            val device = request.connection.toBluetoothDevice(bluetoothAdapter)
            Log.i(TAG, "setGainSetting(${device}, ${request.gainSetting})")

            bluetoothVolumeControl.getAudioInputControlServices(device).forEach {
                it.setGainSetting(request.gainSetting)
            }

            Empty.getDefaultInstance()
        }
    }

    override fun setMute(request: SetMuteRequest, responseObserver: StreamObserver<Empty>) {
        grpcUnary<Empty>(scope, responseObserver) {
            val device = request.connection.toBluetoothDevice(bluetoothAdapter)
            Log.i(TAG, "setMute(${device}, ${request.mute})")

            bluetoothVolumeControl.getAudioInputControlServices(device).forEach {
                it.setMute(request.mute)
            }

            Empty.getDefaultInstance()
        }
    }

    override fun setGainMode(request: SetGainModeRequest, responseObserver: StreamObserver<Empty>) {
        grpcUnary<Empty>(scope, responseObserver) {
            val device = request.connection.toBluetoothDevice(bluetoothAdapter)
            Log.i(TAG, "setMute(${device}, ${request.gainMode})")

            bluetoothVolumeControl.getAudioInputControlServices(device).forEach {
                it.setGainMode(request.gainMode)
            }

            Empty.getDefaultInstance()
        }
    }
}
}
+23 −0
Original line number Original line Diff line number Diff line
@@ -24,6 +24,14 @@ service VCP {
  rpc SetVolumeOffset(SetVolumeOffsetRequest) returns (google.protobuf.Empty);
  rpc SetVolumeOffset(SetVolumeOffsetRequest) returns (google.protobuf.Empty);
  // Wait for device to be connected.
  // Wait for device to be connected.
  rpc WaitConnect(WaitConnectRequest) returns (google.protobuf.Empty);
  rpc WaitConnect(WaitConnectRequest) returns (google.protobuf.Empty);

  // TODO: AICS interfaces could be made a bit more generic by first fetching
  // what are the available instances and using them like the Connection object
  // is used.

  rpc SetGainSetting(SetGainSettingRequest) returns (google.protobuf.Empty);
  rpc SetMute(SetMuteRequest) returns (google.protobuf.Empty);
  rpc SetGainMode(SetGainModeRequest) returns (google.protobuf.Empty);
}
}


// Request of the `SetDeviceVolume` method
// Request of the `SetDeviceVolume` method
@@ -45,3 +53,18 @@ message SetVolumeOffsetRequest{
message WaitConnectRequest {
message WaitConnectRequest {
  Connection connection = 1;
  Connection connection = 1;
}
}

message SetGainSettingRequest {
  Connection connection = 1;
  int32 gainSetting = 2;
}
message SetMuteRequest {
  Connection connection = 1;
  // See Mute.aidl for valid values
  int32 mute = 2;
}
message SetGainModeRequest {
  Connection connection = 1;
  // See GainMode.aidl for valid values
  int32 gainMode = 2;
}