summaryrefslogtreecommitdiff
path: root/pandora
diff options
context:
space:
mode:
author Charlie Boutier <charliebout@google.com> 2024-10-04 22:07:58 +0000
committer Charlie Boutier <charliebout@google.com> 2024-10-08 22:28:40 +0000
commit94e3b26ef65d374b2342d365c571773b86220ab5 (patch)
tree3c852418ee035ee7e154019c2aa475dc18775e6e /pandora
parent9d0a929c40309b0658983fb04ab65c6d39c23de9 (diff)
Pandora: Enable Bumble config modification at runtime
Bug: 370701018 Bug: 370608988 Test: atest avatar - manual testing with avatar Change-Id: I9c190c70ca4e6c57bf97350cd5afb3bd32ac390c
Diffstat (limited to 'pandora')
-rw-r--r--pandora/interfaces/pandora_experimental/bumble_config.proto60
-rw-r--r--pandora/interfaces/python/Android.bp5
-rw-r--r--pandora/server/bumble_experimental/bumble_config.py73
3 files changed, 138 insertions, 0 deletions
diff --git a/pandora/interfaces/pandora_experimental/bumble_config.proto b/pandora/interfaces/pandora_experimental/bumble_config.proto
new file mode 100644
index 0000000000..438f2ba16b
--- /dev/null
+++ b/pandora/interfaces/pandora_experimental/bumble_config.proto
@@ -0,0 +1,60 @@
+// Copyright 2024 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+syntax = "proto3";
+
+option java_outer_classname = "BumbleConfigProto";
+
+package pandora;
+
+import "google/protobuf/empty.proto";
+import "pandora/host.proto";
+
+// This service provides runtime configuration for the Bumble Bluetooth stack.
+// It allows overriding the initial configuration provided by the JSON file and
+// the Security Service. This service should only be used by BumbleBluetoothTests.
+service BumbleConfig {
+ // Override the initial Bumble configuration. This will erase any
+ // previous configuration set via JSON file or Security Service.
+ rpc Override(OverrideRequest) returns (google.protobuf.Empty);
+}
+
+message PairingConfig {
+ bool sc = 1;
+ bool mitm = 2;
+ bool bonding = 3;
+ OwnAddressType identity_address_type = 4;
+}
+
+enum IoCapability {
+ DISPLAY_ONLY = 0x00;
+ DISPLAY_YES_NO = 0x01;
+ KEYBOARD_ONLY = 0x02;
+ NO_OUTPUT_NO_INPUT = 0x03;
+ KEYBOARD_DISPLAY = 0x04;
+}
+
+enum KeyDistribution {
+ ENCRYPTION_KEY = 0x00;
+ IDENTITY_KEY = 0x01;
+ SIGNING_KEY = 0x02;
+ LINK_KEY = 0x03;
+}
+
+message OverrideRequest {
+ IoCapability io_capability = 1;
+ PairingConfig pairing_config = 2;
+ KeyDistribution initiator_key_distribution = 3;
+ KeyDistribution responder_key_distribution = 4;
+}
diff --git a/pandora/interfaces/python/Android.bp b/pandora/interfaces/python/Android.bp
index 2abac309db..d295f2cfd3 100644
--- a/pandora/interfaces/python/Android.bp
+++ b/pandora/interfaces/python/Android.bp
@@ -34,6 +34,10 @@ genrule {
"pandora_experimental/avrcp_grpc_aio.py",
"pandora_experimental/avrcp_pb2.py",
"pandora_experimental/avrcp_pb2.pyi",
+ "pandora_experimental/bumble_config_grpc.py",
+ "pandora_experimental/bumble_config_grpc_aio.py",
+ "pandora_experimental/bumble_config_pb2.py",
+ "pandora_experimental/bumble_config_pb2.pyi",
"pandora_experimental/dck_grpc.py",
"pandora_experimental/dck_grpc_aio.py",
"pandora_experimental/dck_pb2.py",
@@ -109,6 +113,7 @@ filegroup {
srcs: [
":pandora_experimental-python-gen-src{pandora_experimental/asha_pb2.pyi}",
":pandora_experimental-python-gen-src{pandora_experimental/avrcp_pb2.pyi}",
+ ":pandora_experimental-python-gen-src{pandora_experimental/bumble_config_pb2.pyi}",
":pandora_experimental-python-gen-src{pandora_experimental/dck_pb2.pyi}",
":pandora_experimental-python-gen-src{pandora_experimental/gatt_pb2.pyi}",
":pandora_experimental-python-gen-src{pandora_experimental/hap_pb2.pyi}",
diff --git a/pandora/server/bumble_experimental/bumble_config.py b/pandora/server/bumble_experimental/bumble_config.py
new file mode 100644
index 0000000000..4435476198
--- /dev/null
+++ b/pandora/server/bumble_experimental/bumble_config.py
@@ -0,0 +1,73 @@
+# Copyright 2024 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import logging
+
+import grpc
+from bumble.device import Connection as BumbleConnection
+from bumble.device import Device
+from bumble.pairing import PairingConfig
+from bumble.pairing import PairingDelegate as BasePairingDelegate
+from bumble.pandora import Config, utils
+from bumble.pandora.security import PairingDelegate
+from google.protobuf.empty_pb2 import Empty
+from pandora.host_pb2 import PUBLIC
+from pandora_experimental.bumble_config_grpc_aio import BumbleConfigServicer
+from pandora_experimental.bumble_config_pb2 import (KeyDistribution,
+ OverrideRequest)
+
+
+class BumbleConfigService(BumbleConfigServicer):
+ device: Device
+
+ def __init__(self, device: Device, server_config: Config) -> None:
+ self.log = utils.BumbleServerLoggerAdapter(logging.getLogger(), {"service_name": "BumbleConfig", "device": device})
+ self.device = device
+ self.server_config = server_config
+
+ @utils.rpc
+ async def Override(self, request: OverrideRequest, context: grpc.ServicerContext) -> Empty:
+
+ def parseProtoKeyDistribution(key: KeyDistribution,) -> BasePairingDelegate.KeyDistribution:
+ return [
+ BasePairingDelegate.KeyDistribution.DISTRIBUTE_ENCRYPTION_KEY,
+ BasePairingDelegate.KeyDistribution.DISTRIBUTE_IDENTITY_KEY,
+ BasePairingDelegate.KeyDistribution.DISTRIBUTE_SIGNING_KEY,
+ BasePairingDelegate.KeyDistribution.DISTRIBUTE_LINK_KEY,
+ ][key] # type: ignore
+
+ def pairing_config_factory(connection: BumbleConnection) -> PairingConfig:
+ pairing_delegate = PairingDelegate(
+ connection=connection,
+ io_capability=BasePairingDelegate.IoCapability(request.io_capability),
+ local_initiator_key_distribution=parseProtoKeyDistribution(request.initiator_key_distribution),
+ local_responder_key_distribution=parseProtoKeyDistribution(request.responder_key_distribution),
+ )
+
+ pc_req = request.pairing_config
+ pairing_config = PairingConfig(
+ sc=pc_req.sc,
+ mitm=pc_req.mitm,
+ bonding=pc_req.bonding,
+ identity_address_type=PairingConfig.AddressType.PUBLIC
+ if request.identity_address_type == PUBLIC else PairingConfig.AddressType.RANDOM,
+ delegate=pairing_delegate,
+ )
+ self.log.debug(f"Override: {pairing_config}")
+
+ return pairing_config
+
+ self.device.pairing_config_factory = pairing_config_factory
+
+ return Empty()