Loading android/pandora/mmi2grpc/mmi2grpc/__init__.py +1 −1 Original line number Diff line number Diff line Loading @@ -66,7 +66,7 @@ class IUT: # Note: we don't keep a single gRPC channel instance in the IUT class # because reset is allowed to close the gRPC server. with grpc.insecure_channel(f'localhost:{self.port}') as channel: self._retry(Host(channel).Reset)(wait_for_ready=True) self._retry(Host(channel).HardReset)(wait_for_ready=True) def __exit__(self, exc_type, exc_value, exc_traceback): self._a2dp = None Loading android/pandora/server/proto/pandora/host.proto +8 −5 Original line number Diff line number Diff line Loading @@ -11,13 +11,16 @@ import "google/protobuf/empty.proto"; // At startup, the Host must be in BR/EDR connectable mode // (see GAP connectability modes) service Host { // Reset the host. // **After** responding to this command, the GRPC server should loose // Hard reset the host. // **After** responding to this command, the gRPC server should loose // all its state. // This is comparable to a process restart or an hardware reset. // The GRPC server might take some time to be available after // The gRPC server might take some time to be available after // this command. rpc Reset(google.protobuf.Empty) returns (google.protobuf.Empty); rpc HardReset(google.protobuf.Empty) returns (google.protobuf.Empty); // Soft reset the host by performing an HCI reset. Previous bonds must // not be removed and the gRPC server must not be restarted. rpc SoftReset(google.protobuf.Empty) returns (google.protobuf.Empty); // Read the local Bluetooth device address. // This should return the same value as a Read BD_ADDR HCI command. rpc ReadLocalAddress(google.protobuf.Empty) returns (ReadLocalAddressResponse); Loading Loading @@ -56,7 +59,7 @@ message ReadLocalAddressResponse { // A Token representing an ACL connection. // It's acquired via a Connect on the Host service. message Connection { // Opaque value filled by the GRPC server, must not // Opaque value filled by the gRPC server, must not // be modified nor crafted. bytes cookie = 1; } Loading android/pandora/server/src/com/android/pandora/Host.kt +44 −30 Original line number Diff line number Diff line Loading @@ -35,17 +35,17 @@ import io.grpc.stub.StreamObserver import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.cancel import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.channels.trySendBlocking import kotlinx.coroutines.delay import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.shareIn import kotlinx.coroutines.launch import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.channels.trySendBlocking import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.runBlocking import pandora.HostGrpc.HostImplBase import pandora.HostProto.* Loading Loading @@ -80,16 +80,13 @@ class Host(private val context: Context, private val server: Server) : HostImplB scope.cancel() } override fun reset(request: Empty, responseObserver: StreamObserver<Empty>) { grpcUnary<Empty>(scope, responseObserver) { Log.i(TAG, "reset") bluetoothAdapter.clearBluetooth() private suspend fun rebootBluetooth() { Log.i(TAG, "rebootBluetooth") val stateFlow = flow .filter { it.getAction() == BluetoothAdapter.ACTION_STATE_CHANGED } .map { it.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR) } flow.filter { it.getAction() == BluetoothAdapter.ACTION_STATE_CHANGED }.map { it.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR) } if (bluetoothAdapter.isEnabled) { bluetoothAdapter.disable() Loading @@ -101,6 +98,15 @@ class Host(private val context: Context, private val server: Server) : HostImplB bluetoothAdapter.enable() stateFlow.filter { it == BluetoothAdapter.STATE_ON }.first() } override fun hardReset(request: Empty, responseObserver: StreamObserver<Empty>) { grpcUnary<Empty>(scope, responseObserver) { Log.i(TAG, "hardReset") bluetoothAdapter.clearBluetooth() rebootBluetooth() // The last expression is the return value. Empty.getDefaultInstance() Loading @@ -111,6 +117,16 @@ class Host(private val context: Context, private val server: Server) : HostImplB } } override fun softReset(request: Empty, responseObserver: StreamObserver<Empty>) { grpcUnary<Empty>(scope, responseObserver) { Log.i(TAG, "softReset") rebootBluetooth() Empty.getDefaultInstance() } } override fun readLocalAddress( request: Empty, responseObserver: StreamObserver<ReadLocalAddressResponse> Loading Loading @@ -279,9 +295,7 @@ class Host(private val context: Context, private val server: Server) : HostImplB GattInstance(device!!, TRANSPORT_LE, context).waitForState(BluetoothProfile.STATE_CONNECTED) ConnectLEResponse.newBuilder() .setConnection( Connection.newBuilder() .setCookie(ByteString.copyFromUtf8(device.address)) .build() Connection.newBuilder().setCookie(ByteString.copyFromUtf8(device.address)).build() ) .build() } Loading android/pandora/test/connect.py +1 −1 Original line number Diff line number Diff line Loading @@ -30,7 +30,7 @@ class ExampleTest(base_test.BaseTestClass): self.ref = self.pandora_devices[1] def setup_test(self): self.dut.host.Reset() self.dut.host.HardReset() # TODO: wait for server time.sleep(3) Loading Loading
android/pandora/mmi2grpc/mmi2grpc/__init__.py +1 −1 Original line number Diff line number Diff line Loading @@ -66,7 +66,7 @@ class IUT: # Note: we don't keep a single gRPC channel instance in the IUT class # because reset is allowed to close the gRPC server. with grpc.insecure_channel(f'localhost:{self.port}') as channel: self._retry(Host(channel).Reset)(wait_for_ready=True) self._retry(Host(channel).HardReset)(wait_for_ready=True) def __exit__(self, exc_type, exc_value, exc_traceback): self._a2dp = None Loading
android/pandora/server/proto/pandora/host.proto +8 −5 Original line number Diff line number Diff line Loading @@ -11,13 +11,16 @@ import "google/protobuf/empty.proto"; // At startup, the Host must be in BR/EDR connectable mode // (see GAP connectability modes) service Host { // Reset the host. // **After** responding to this command, the GRPC server should loose // Hard reset the host. // **After** responding to this command, the gRPC server should loose // all its state. // This is comparable to a process restart or an hardware reset. // The GRPC server might take some time to be available after // The gRPC server might take some time to be available after // this command. rpc Reset(google.protobuf.Empty) returns (google.protobuf.Empty); rpc HardReset(google.protobuf.Empty) returns (google.protobuf.Empty); // Soft reset the host by performing an HCI reset. Previous bonds must // not be removed and the gRPC server must not be restarted. rpc SoftReset(google.protobuf.Empty) returns (google.protobuf.Empty); // Read the local Bluetooth device address. // This should return the same value as a Read BD_ADDR HCI command. rpc ReadLocalAddress(google.protobuf.Empty) returns (ReadLocalAddressResponse); Loading Loading @@ -56,7 +59,7 @@ message ReadLocalAddressResponse { // A Token representing an ACL connection. // It's acquired via a Connect on the Host service. message Connection { // Opaque value filled by the GRPC server, must not // Opaque value filled by the gRPC server, must not // be modified nor crafted. bytes cookie = 1; } Loading
android/pandora/server/src/com/android/pandora/Host.kt +44 −30 Original line number Diff line number Diff line Loading @@ -35,17 +35,17 @@ import io.grpc.stub.StreamObserver import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.cancel import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.channels.trySendBlocking import kotlinx.coroutines.delay import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.shareIn import kotlinx.coroutines.launch import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.channels.trySendBlocking import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.runBlocking import pandora.HostGrpc.HostImplBase import pandora.HostProto.* Loading Loading @@ -80,16 +80,13 @@ class Host(private val context: Context, private val server: Server) : HostImplB scope.cancel() } override fun reset(request: Empty, responseObserver: StreamObserver<Empty>) { grpcUnary<Empty>(scope, responseObserver) { Log.i(TAG, "reset") bluetoothAdapter.clearBluetooth() private suspend fun rebootBluetooth() { Log.i(TAG, "rebootBluetooth") val stateFlow = flow .filter { it.getAction() == BluetoothAdapter.ACTION_STATE_CHANGED } .map { it.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR) } flow.filter { it.getAction() == BluetoothAdapter.ACTION_STATE_CHANGED }.map { it.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR) } if (bluetoothAdapter.isEnabled) { bluetoothAdapter.disable() Loading @@ -101,6 +98,15 @@ class Host(private val context: Context, private val server: Server) : HostImplB bluetoothAdapter.enable() stateFlow.filter { it == BluetoothAdapter.STATE_ON }.first() } override fun hardReset(request: Empty, responseObserver: StreamObserver<Empty>) { grpcUnary<Empty>(scope, responseObserver) { Log.i(TAG, "hardReset") bluetoothAdapter.clearBluetooth() rebootBluetooth() // The last expression is the return value. Empty.getDefaultInstance() Loading @@ -111,6 +117,16 @@ class Host(private val context: Context, private val server: Server) : HostImplB } } override fun softReset(request: Empty, responseObserver: StreamObserver<Empty>) { grpcUnary<Empty>(scope, responseObserver) { Log.i(TAG, "softReset") rebootBluetooth() Empty.getDefaultInstance() } } override fun readLocalAddress( request: Empty, responseObserver: StreamObserver<ReadLocalAddressResponse> Loading Loading @@ -279,9 +295,7 @@ class Host(private val context: Context, private val server: Server) : HostImplB GattInstance(device!!, TRANSPORT_LE, context).waitForState(BluetoothProfile.STATE_CONNECTED) ConnectLEResponse.newBuilder() .setConnection( Connection.newBuilder() .setCookie(ByteString.copyFromUtf8(device.address)) .build() Connection.newBuilder().setCookie(ByteString.copyFromUtf8(device.address)).build() ) .build() } Loading
android/pandora/test/connect.py +1 −1 Original line number Diff line number Diff line Loading @@ -30,7 +30,7 @@ class ExampleTest(base_test.BaseTestClass): self.ref = self.pandora_devices[1] def setup_test(self): self.dut.host.Reset() self.dut.host.HardReset() # TODO: wait for server time.sleep(3) Loading