Merge "pdl: fix computation of `SourceLocation` line numbers"
diff --git a/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java b/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java
index 81475bb..7ee881f 100644
--- a/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java
+++ b/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java
@@ -377,7 +377,8 @@
Metadata data = mMetadataCache.get(address);
int connectionPolicy = data.getProfileConnectionPolicy(profile);
- Log.v(TAG, "getProfileConnectionPolicy: " + address + ", profile=" + profile
+ Log.v(TAG, "getProfileConnectionPolicy: " + address + ", profile="
+ + BluetoothProfile.getProfileName(profile)
+ ", connectionPolicy = " + connectionPolicy);
return connectionPolicy;
}
diff --git a/floss/build/Dockerfile b/floss/build/Dockerfile
index 7e938f9..b31e1f4 100644
--- a/floss/build/Dockerfile
+++ b/floss/build/Dockerfile
@@ -5,7 +5,8 @@
# Inherit from a recent Debian version. The slim version is a smaller variant
# meant for containers.
-FROM debian:bookworm-slim
+# This digest is taken from the tag debian:bookworm-slim (if you want to update)
+FROM debian@sha256:b66f66d473ef3128436ba2812198edcae86c268eb530dff44ff6ae26f9a2ee30
# First install all required apt packages.
RUN apt-get update && \
@@ -56,8 +57,10 @@
zlib1g-dev \
;
-# Next install the Rust toolchain.
-RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
+# Next install the Rust toolchain. Download the toolchain to the local folder
+# using curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs
+ADD rustup/rustup.sh /tmp
+RUN /tmp/rustup.sh -y --default-toolchain 1.59.0
# Add .cargo/bin to $PATH
ENV PATH="/root/.cargo/bin:${PATH}"
diff --git a/floss/build/README.md b/floss/build/README.md
index ac58410..1697a39 100644
--- a/floss/build/README.md
+++ b/floss/build/README.md
@@ -1,13 +1,13 @@
-# Docker build for Floss
+# Podman build for Floss
-This repo contains the Docker image build rule, used to generate the docker
-image necessary to build Floss. If building a new docker image, run
-`docker-build-image.py` with the tag `floss:latest`.
+This repo contains the Podman image build rule, used to generate the Podman
+image necessary to build Floss. If building a new Podman image, run
+`podman-build-image.py` with the tag `floss:latest`.
-## Using the docker image to build
+## Using the podman image to build
-Once the Docker image is built (and assuming it's tagged as `floss:latest`), you
-should use the `build-in-docker.py` script to build the current repo.
+Once the Podman image is built (and assuming it's tagged as `floss:latest`), you
+should use the `build-in-podman.py` script to build the current repo.
This script will use the local `floss:latest` (or pull it from the registry),
mount (or create) the `floss-out` volume to `/root/.floss` and the current
@@ -18,6 +18,6 @@
* `./build.py --libdir=/usr/lib/x86-64_linux_gnu/`
If you want to run the build more quickly (or pass other commands), run
-`build-in-docker.py --only-start`. This will only start the container for you
+`build-in-podman.py --only-start`. This will only start the container for you
(doing the correct mounts) and will print the commands it would have run via
-docker exec normally.
+`podman exec` normally.
diff --git a/floss/build/build-in-docker.py b/floss/build/build-in-docker.py
deleted file mode 100755
index d78d404..0000000
--- a/floss/build/build-in-docker.py
+++ /dev/null
@@ -1,164 +0,0 @@
-#!/usr/bin/env python3
-
-import argparse
-import os
-import subprocess
-import sys
-import time
-
-
-class FlossDockerRunner:
- """Runs Floss build inside docker container."""
-
- # Commands to run for build
- BUILD_COMMANDS = [
- # First run bootstrap to get latest code + create symlinks
- ['/root/src/build.py', '--run-bootstrap'],
-
- # Clean up any previous artifacts inside the volume
- ['/root/src/build.py', '--target', 'clean'],
-
- # Run normal code builder
- ['/root/src/build.py', '--target', 'all'],
-
- # Run tests
- ['/root/src/build.py', '--target', 'test'],
- ]
-
- def __init__(self, workdir, rootdir, image_tag, volume_tag):
- """ Constructor.
-
- Args:
- workdir: Current working directory (should be the script path).
- rootdir: Root directory for Bluetooth.
- build_tag: Tag for docker image used for building.
- """
- self.workdir = workdir
- self.rootdir = rootdir
- self.image_tag = image_tag
- self.env = os.environ.copy()
-
- # Name of running container
- self.container_name = 'floss-docker-runner'
-
- # Name of volume where we'll send build output
- self.volume_name = volume_tag
-
- def run_command(self, target, args, cwd=None, env=None, ignore_rc=False):
- """ Run command and stream the output.
- """
- # Set some defaults
- if not cwd:
- cwd = self.workdir
- if not env:
- env = self.env
-
- rc = 0
- process = subprocess.Popen(args, cwd=cwd, env=env, stdout=subprocess.PIPE)
- while True:
- line = process.stdout.readline()
- print(line.decode('utf-8'), end="")
- if not line:
- rc = process.poll()
- if rc is not None:
- break
-
- time.sleep(0.1)
-
- if rc != 0 and not ignore_rc:
- raise Exception("{} failed. Return code is {}".format(target, rc))
-
- def _create_volume_if_needed(self):
- # Check if the volume exists. Otherwise create it.
- try:
- subprocess.check_output(['docker', 'volume', 'inspect', self.volume_name])
- finally:
- self.run_command('docker volume create', ['docker', 'volume', 'create', self.volume_name])
-
- def start_container(self):
- """Starts the docker container with correct mounts."""
- # Stop any previously started container.
- self.stop_container(ignore_error=True)
-
- # Create volume and create mount string
- self._create_volume_if_needed()
- mount_output_volume = 'type=volume,src={},dst=/root/.floss'.format(self.volume_name)
-
- # Mount the source directory
- mount_src_dir = 'type=bind,src={},dst=/root/src'.format(self.rootdir)
-
- # Run the docker image. It will run `tail` indefinitely so the container
- # doesn't close and we can run `docker exec` on it.
- self.run_command('docker run', [
- 'docker', 'run', '--name', self.container_name, '--mount', mount_output_volume, '--mount', mount_src_dir,
- '-d', self.image_tag, 'tail', '-f', '/dev/null'
- ])
-
- def stop_container(self, ignore_error=False):
- """Stops the docker container for build."""
- self.run_command('docker stop', ['docker', 'stop', '-t', '1', self.container_name], ignore_rc=ignore_error)
- self.run_command('docker rm', ['docker', 'rm', self.container_name], ignore_rc=ignore_error)
-
- def do_build(self):
- """Runs the basic build commands."""
- # Start container before building
- self.start_container()
-
- # Run all commands
- for i, cmd in enumerate(self.BUILD_COMMANDS):
- self.run_command('docker exec #{}'.format(i), ['docker', 'exec', '-it', self.container_name] + cmd)
-
- # Stop container before exiting
- self.stop_container()
-
- def print_do_build(self):
- """Prints the commands for building."""
- docker_exec = ['docker', 'exec', '-it', self.container_name]
- print('Normally, build would run the following commands: \n')
- for cmd in self.BUILD_COMMANDS:
- print(' '.join(docker_exec + cmd))
-
- def check_docker_runnable(self):
- try:
- subprocess.check_output(['docker', 'ps'], stderr=subprocess.STDOUT)
- except subprocess.CalledProcessError as err:
- if 'denied' in err.output.decode('utf-8'):
- print('Run script as sudo')
- else:
- print('Unexpected error: {}'.format(err.output.decode('utf-8')))
-
- return False
-
- # No exception means docker is ok
- return True
-
-
-if __name__ == "__main__":
- parser = argparse.ArgumentParser('Builder Floss inside docker image.')
- parser.add_argument(
- '--only-start',
- action='store_true',
- default=False,
- help='Only start the container. Prints the commands it would have ran.')
- parser.add_argument('--only-stop', action='store_true', default=False, help='Only stop the container and exit.')
- parser.add_argument('--image-tag', default='floss:latest', help='Docker image to use to build.')
- parser.add_argument('--volume-tag', default='floss-out', help='Name of volume to use.')
- args = parser.parse_args()
-
- # cwd should be set to same directory as this script (that's where Dockerfile
- # is kept).
- workdir = os.path.dirname(os.path.abspath(sys.argv[0]))
- rootdir = os.path.abspath(os.path.join(workdir, '../..'))
-
- fdr = FlossDockerRunner(workdir, rootdir, args.image_tag, args.volume_tag)
-
- # Make sure docker is runnable before continuing
- if fdr.check_docker_runnable():
- # Handle some flags
- if args.only_start:
- fdr.start_container()
- fdr.print_do_build()
- elif args.only_stop:
- fdr.stop_container()
- else:
- fdr.do_build()
diff --git a/floss/build/build-in-podman.py b/floss/build/build-in-podman.py
new file mode 100755
index 0000000..ba45914
--- /dev/null
+++ b/floss/build/build-in-podman.py
@@ -0,0 +1,188 @@
+#!/usr/bin/env python3
+
+import argparse
+import os
+import subprocess
+import sys
+import time
+
+SRC_MOUNT = "/root/src"
+STAGING_MOUNT = "/root/.floss"
+
+
+class FlossPodmanRunner:
+ """Runs Floss build inside podman container."""
+
+ # Commands to run for build
+ BUILD_COMMANDS = [
+ # First run bootstrap to get latest code + create symlinks
+ [f'{SRC_MOUNT}/build.py', '--run-bootstrap'],
+
+ # Clean up any previous artifacts inside the volume
+ [f'{SRC_MOUNT}/build.py', '--target', 'clean'],
+
+ # Run normal code builder
+ [f'{SRC_MOUNT}/build.py', '--target', 'all'],
+
+ # Run tests
+ [f'{SRC_MOUNT}/build.py', '--target', 'test'],
+ ]
+
+ def __init__(self, workdir, rootdir, image_tag, volume_name, container_name, staging_dir):
+ """ Constructor.
+
+ Args:
+ workdir: Current working directory (should be the script path).
+ rootdir: Root directory for Bluetooth.
+ image_tag: Tag for podman image used for building.
+ volume_name: Volume name used for storing artifacts.
+ container_name: Name for running container instance.
+ staging_dir: Directory to mount for artifacts instead of using volume.
+ """
+ self.workdir = workdir
+ self.rootdir = rootdir
+ self.image_tag = image_tag
+ self.env = os.environ.copy()
+
+ # Name of running container
+ self.container_name = container_name
+
+ # Name of volume to write output.
+ self.volume_name = volume_name
+ # Staging dir where we send output instead of the volume.
+ self.staging_dir = staging_dir
+
+ def run_command(self, target, args, cwd=None, env=None, ignore_rc=False):
+ """ Run command and stream the output.
+ """
+ # Set some defaults
+ if not cwd:
+ cwd = self.workdir
+ if not env:
+ env = self.env
+
+ rc = 0
+ process = subprocess.Popen(args, cwd=cwd, env=env, stdout=subprocess.PIPE)
+ while True:
+ line = process.stdout.readline()
+ print(line.decode('utf-8'), end="")
+ if not line:
+ rc = process.poll()
+ if rc is not None:
+ break
+
+ time.sleep(0.1)
+
+ if rc != 0 and not ignore_rc:
+ raise Exception("{} failed. Return code is {}".format(target, rc))
+
+ def _create_volume_if_needed(self):
+ # Check if the volume exists. Otherwise create it.
+ try:
+ subprocess.check_output(['podman', 'volume', 'inspect', self.volume_name])
+ except:
+ self.run_command('podman volume create', ['podman', 'volume', 'create', self.volume_name])
+
+ def start_container(self):
+ """Starts the podman container with correct mounts."""
+ # Stop any previously started container.
+ self.stop_container(ignore_error=True)
+
+ # Create volume and create mount string
+ if self.staging_dir:
+ mount_output_volume = 'type=bind,src={},dst={}'.format(self.staging_dir, STAGING_MOUNT)
+ else:
+ # If not using staging dir, use the volume instead
+ self._create_volume_if_needed()
+ mount_output_volume = 'type=volume,src={},dst={}'.format(self.volume_name, STAGING_MOUNT)
+
+ # Mount the source directory
+ mount_src_dir = 'type=bind,src={},dst={}'.format(self.rootdir, SRC_MOUNT)
+
+ # Run the podman image. It will run `tail` indefinitely so the container
+ # doesn't close and we can run `podman exec` on it.
+ self.run_command('podman run', [
+ 'podman', 'run', '--name', self.container_name, '--mount', mount_output_volume, '--mount', mount_src_dir,
+ '-d', self.image_tag, 'tail', '-f', '/dev/null'
+ ])
+
+ def stop_container(self, ignore_error=False):
+ """Stops the podman container for build."""
+ self.run_command('podman stop', ['podman', 'stop', '-t', '1', self.container_name], ignore_rc=ignore_error)
+ self.run_command('podman rm', ['podman', 'rm', self.container_name], ignore_rc=ignore_error)
+
+ def do_build(self):
+ """Runs the basic build commands."""
+ # Start container before building
+ self.start_container()
+
+ try:
+ # Run all commands
+ for i, cmd in enumerate(self.BUILD_COMMANDS):
+ self.run_command('podman exec #{}'.format(i), ['podman', 'exec', '-it', self.container_name] + cmd)
+ finally:
+ # Always stop container before exiting
+ self.stop_container()
+
+ def print_do_build(self):
+ """Prints the commands for building."""
+ podman_exec = ['podman', 'exec', '-it', self.container_name]
+ print('Normally, build would run the following commands: \n')
+ for cmd in self.BUILD_COMMANDS:
+ print(' '.join(podman_exec + cmd))
+
+ def check_podman_runnable(self):
+ try:
+ subprocess.check_output(['podman', 'ps'], stderr=subprocess.STDOUT)
+ except subprocess.CalledProcessError as err:
+ if 'denied' in err.output.decode('utf-8'):
+ print('Run script as sudo')
+ else:
+ print('Unexpected error: {}'.format(err.output.decode('utf-8')))
+
+ return False
+
+ # No exception means podman is ok
+ return True
+
+
+if __name__ == "__main__":
+ parser = argparse.ArgumentParser('Builder Floss inside podman image.')
+ parser.add_argument(
+ '--only-start',
+ action='store_true',
+ default=False,
+ help='Only start the container. Prints the commands it would have ran.')
+ parser.add_argument('--only-stop', action='store_true', default=False, help='Only stop the container and exit.')
+ parser.add_argument('--image-tag', default='floss:latest', help='Podman image to use to build.')
+ parser.add_argument(
+ '--volume-tag',
+ default='floss-out',
+ help='Name of volume to use. This is where build artifacts will be stored by default.')
+ parser.add_argument(
+ '--staging-dir',
+ default=None,
+ help='Staging directory to use instead of volume. Build artifacts will be written here.')
+ parser.add_argument('--container-name', default='floss-podman-runner', help='What to name the started container')
+ args = parser.parse_args()
+
+ # cwd should be set to same directory as this script (that's where Podmanfile
+ # is kept).
+ workdir = os.path.dirname(os.path.abspath(sys.argv[0]))
+ rootdir = os.path.abspath(os.path.join(workdir, '../..'))
+
+ # Determine staging directory absolute path
+ staging = os.path.abspath(args.staging_dir) if args.staging_dir else None
+
+ fdr = FlossPodmanRunner(workdir, rootdir, args.image_tag, args.volume_tag, args.container_name, staging)
+
+ # Make sure podman is runnable before continuing
+ if fdr.check_podman_runnable():
+ # Handle some flags
+ if args.only_start:
+ fdr.start_container()
+ fdr.print_do_build()
+ elif args.only_stop:
+ fdr.stop_container()
+ else:
+ fdr.do_build()
diff --git a/floss/build/docker-build-image.py b/floss/build/podman-build-image.py
similarity index 65%
rename from floss/build/docker-build-image.py
rename to floss/build/podman-build-image.py
index 81b622b..af772c2 100755
--- a/floss/build/docker-build-image.py
+++ b/floss/build/podman-build-image.py
@@ -8,8 +8,8 @@
SRC_MOUNT = "/root/src"
-class DockerImageBuilder:
- """Builds the docker image for Floss build environment."""
+class PodmanImageBuilder:
+ """Builds the podman image for Floss build environment."""
def __init__(self, workdir, rootdir, tag):
""" Constructor.
@@ -27,7 +27,7 @@
self.final_tag = tag
self.env = os.environ.copy()
- # Mark dpkg builders for docker
+ # Mark dpkg builders for podman
self.env['LIBCHROME_DOCKER'] = '1'
self.env['MODP_DOCKER'] = '1'
@@ -55,19 +55,19 @@
if rc != 0 and not ignore_rc:
raise Exception("{} failed. Return code is {}".format(target, rc))
- def _docker_build(self):
- self.run_command('docker build', ['docker', 'build', '-t', self.build_tag, '.'])
+ def _podman_build(self):
+ self.run_command('podman build', ['podman', 'build', '-t', self.build_tag, '.'])
def _build_dpkg_and_commit(self):
# Try to remove any previous instance of the container that may be
# running if this script didn't complete cleanly last time.
- self.run_command('docker stop', ['docker', 'stop', '-t', '1', self.container_name], ignore_rc=True)
- self.run_command('docker rm', ['docker', 'rm', self.container_name], ignore_rc=True)
+ self.run_command('podman stop', ['podman', 'stop', '-t', '1', self.container_name], ignore_rc=True)
+ self.run_command('podman rm', ['podman', 'rm', self.container_name], ignore_rc=True)
# Runs never terminating application on the newly built image in detached mode
mount_str = 'type=bind,src={},dst={},readonly'.format(self.rootdir, SRC_MOUNT)
- self.run_command('docker run', [
- 'docker', 'run', '--name', self.container_name, '--mount', mount_str, '-d', self.build_tag, 'tail', '-f',
+ self.run_command('podman run', [
+ 'podman', 'run', '--name', self.container_name, '--mount', mount_str, '-d', self.build_tag, 'tail', '-f',
'/dev/null'
])
@@ -76,13 +76,13 @@
['mkdir', '-p', '/tmp/libchrome', '/tmp/modpb64'],
# Run the dpkg builder for modp_b64
- ['/root/src/system/build/dpkg/modp_b64/gen-src-pkg.sh', '/tmp/modpb64'],
+ [f'{SRC_MOUNT}/system/build/dpkg/modp_b64/gen-src-pkg.sh', '/tmp/modpb64'],
# Install modp_b64 since libchrome depends on it
['find', '/tmp/modpb64', '-name', 'modp*.deb', '-exec', 'dpkg', '-i', '{}', '+'],
# Run the dpkg builder for libchrome
- ['/root/src/system/build/dpkg/libchrome/gen-src-pkg.sh', '/tmp/libchrome'],
+ [f'{SRC_MOUNT}/system/build/dpkg/libchrome/gen-src-pkg.sh', '/tmp/libchrome'],
# Install libchrome.
['find', '/tmp/libchrome', '-name', 'libchrome_*.deb', '-exec', 'dpkg', '-i', '{}', '+'],
@@ -91,20 +91,21 @@
['rm', '-rf', '/tmp/libchrome', '/tmp/modpb64'],
]
- # Run commands in container first to install everything.
- for i, cmd in enumerate(commands):
- self.run_command('docker exec #{}'.format(i), ['docker', 'exec', '-it', self.container_name] + cmd)
-
- # Commit changes into the final tag name
- self.run_command('docker commit', ['docker', 'commit', self.container_name, self.final_tag])
-
- # Stop running the container and remove it
- self.run_command('docker stop', ['docker', 'stop', '-t', '1', self.container_name])
- self.run_command('docker rm', ['docker', 'rm', self.container_name])
-
- def _check_docker_runnable(self):
try:
- subprocess.check_output(['docker', 'ps'], stderr=subprocess.STDOUT)
+ # Run commands in container first to install everything.
+ for i, cmd in enumerate(commands):
+ self.run_command('podman exec #{}'.format(i), ['podman', 'exec', '-it', self.container_name] + cmd)
+
+ # Commit changes into the final tag name
+ self.run_command('podman commit', ['podman', 'commit', self.container_name, self.final_tag])
+ finally:
+ # Stop running the container and remove it
+ self.run_command('podman stop', ['podman', 'stop', '-t', '1', self.container_name])
+ self.run_command('podman rm', ['podman', 'rm', self.container_name])
+
+ def _check_podman_runnable(self):
+ try:
+ subprocess.check_output(['podman', 'ps'], stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as err:
if 'denied' in err.output.decode('utf-8'):
print('Run script as sudo')
@@ -113,24 +114,24 @@
return False
- # No exception means docker is ok
+ # No exception means podman is ok
return True
def build(self):
- if not self._check_docker_runnable():
+ if not self._check_podman_runnable():
return
- # First build the docker image
- self._docker_build()
+ # First build the podman image
+ self._podman_build()
- # Then build libchrome and modp-b64 inside the docker image and install
+ # Then build libchrome and modp-b64 inside the podman image and install
# them. Commit those changes to the final label.
self._build_dpkg_and_commit()
def main():
- parser = argparse.ArgumentParser(description='Build docker image for Floss build environment.')
- parser.add_argument('--tag', required=True, help='Tag for docker image. i.e. floss:latest')
+ parser = argparse.ArgumentParser(description='Build podman image for Floss build environment.')
+ parser.add_argument('--tag', required=True, help='Tag for podman image. i.e. floss:latest')
args = parser.parse_args()
# cwd should be set to same directory as this script (that's where Dockerfile
@@ -138,9 +139,9 @@
workdir = os.path.dirname(os.path.abspath(sys.argv[0]))
rootdir = os.path.abspath(os.path.join(workdir, '../..'))
- # Build the docker image
- dib = DockerImageBuilder(workdir, rootdir, args.tag)
- dib.build()
+ # Build the podman image
+ pib = PodmanImageBuilder(workdir, rootdir, args.tag)
+ pib.build()
if __name__ == '__main__':
diff --git a/floss/build/rustup/LICENSE-APACHE b/floss/build/rustup/LICENSE-APACHE
new file mode 100644
index 0000000..11069ed
--- /dev/null
+++ b/floss/build/rustup/LICENSE-APACHE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+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
+
+ http://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.
diff --git a/floss/build/rustup/README b/floss/build/rustup/README
new file mode 100644
index 0000000..cdcf953
--- /dev/null
+++ b/floss/build/rustup/README
@@ -0,0 +1,2 @@
+This is a locally downloaded copy of the Rustup script using:
+curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs
diff --git a/floss/build/rustup/rustup.sh b/floss/build/rustup/rustup.sh
new file mode 100755
index 0000000..a4a79a2
--- /dev/null
+++ b/floss/build/rustup/rustup.sh
@@ -0,0 +1,662 @@
+#!/bin/sh
+# shellcheck shell=dash
+
+# This is just a little script that can be downloaded from the internet to
+# install rustup. It just does platform detection, downloads the installer
+# and runs it.
+
+# It runs on Unix shells like {a,ba,da,k,z}sh. It uses the common `local`
+# extension. Note: Most shells limit `local` to 1 var per line, contra bash.
+
+if [ "$KSH_VERSION" = 'Version JM 93t+ 2010-03-05' ]; then
+ # The version of ksh93 that ships with many illumos systems does not
+ # support the "local" extension. Print a message rather than fail in
+ # subtle ways later on:
+ echo 'rustup does not work with this ksh93 version; please try bash!' >&2
+ exit 1
+fi
+
+
+set -u
+
+# If RUSTUP_UPDATE_ROOT is unset or empty, default it.
+RUSTUP_UPDATE_ROOT="${RUSTUP_UPDATE_ROOT:-https://static.rust-lang.org/rustup}"
+
+#XXX: If you change anything here, please make the same changes in setup_mode.rs
+usage() {
+ cat 1>&2 <<EOF
+rustup-init 1.24.3 (c1c769109 2021-05-31)
+The installer for rustup
+
+USAGE:
+ rustup-init [FLAGS] [OPTIONS]
+
+FLAGS:
+ -v, --verbose Enable verbose output
+ -q, --quiet Disable progress output
+ -y Disable confirmation prompt.
+ --no-modify-path Don't configure the PATH environment variable
+ -h, --help Prints help information
+ -V, --version Prints version information
+
+OPTIONS:
+ --default-host <default-host> Choose a default host triple
+ --default-toolchain <default-toolchain> Choose a default toolchain to install
+ --default-toolchain none Do not install any toolchains
+ --profile [minimal|default|complete] Choose a profile
+ -c, --component <components>... Component name to also install
+ -t, --target <targets>... Target name to also install
+EOF
+}
+
+main() {
+ downloader --check
+ need_cmd uname
+ need_cmd mktemp
+ need_cmd chmod
+ need_cmd mkdir
+ need_cmd rm
+ need_cmd rmdir
+
+ get_architecture || return 1
+ local _arch="$RETVAL"
+ assert_nz "$_arch" "arch"
+
+ local _ext=""
+ case "$_arch" in
+ *windows*)
+ _ext=".exe"
+ ;;
+ esac
+
+ local _url="${RUSTUP_UPDATE_ROOT}/dist/${_arch}/rustup-init${_ext}"
+
+ local _dir
+ _dir="$(ensure mktemp -d)"
+ local _file="${_dir}/rustup-init${_ext}"
+
+ local _ansi_escapes_are_valid=false
+ if [ -t 2 ]; then
+ if [ "${TERM+set}" = 'set' ]; then
+ case "$TERM" in
+ xterm*|rxvt*|urxvt*|linux*|vt*)
+ _ansi_escapes_are_valid=true
+ ;;
+ esac
+ fi
+ fi
+
+ # check if we have to use /dev/tty to prompt the user
+ local need_tty=yes
+ for arg in "$@"; do
+ case "$arg" in
+ -h|--help)
+ usage
+ exit 0
+ ;;
+ -y)
+ # user wants to skip the prompt -- we don't need /dev/tty
+ need_tty=no
+ ;;
+ *)
+ ;;
+ esac
+ done
+
+ if $_ansi_escapes_are_valid; then
+ printf "\33[1minfo:\33[0m downloading installer\n" 1>&2
+ else
+ printf '%s\n' 'info: downloading installer' 1>&2
+ fi
+
+ ensure mkdir -p "$_dir"
+ ensure downloader "$_url" "$_file" "$_arch"
+ ensure chmod u+x "$_file"
+ if [ ! -x "$_file" ]; then
+ printf '%s\n' "Cannot execute $_file (likely because of mounting /tmp as noexec)." 1>&2
+ printf '%s\n' "Please copy the file to a location where you can execute binaries and run ./rustup-init${_ext}." 1>&2
+ exit 1
+ fi
+
+ if [ "$need_tty" = "yes" ]; then
+ # The installer is going to want to ask for confirmation by
+ # reading stdin. This script was piped into `sh` though and
+ # doesn't have stdin to pass to its children. Instead we're going
+ # to explicitly connect /dev/tty to the installer's stdin.
+ if [ ! -t 1 ]; then
+ err "Unable to run interactively. Run with -y to accept defaults, --help for additional options"
+ fi
+
+ ignore "$_file" "$@" < /dev/tty
+ else
+ ignore "$_file" "$@"
+ fi
+
+ local _retval=$?
+
+ ignore rm "$_file"
+ ignore rmdir "$_dir"
+
+ return "$_retval"
+}
+
+check_proc() {
+ # Check for /proc by looking for the /proc/self/exe link
+ # This is only run on Linux
+ if ! test -L /proc/self/exe ; then
+ err "fatal: Unable to find /proc/self/exe. Is /proc mounted? Installation cannot proceed without /proc."
+ fi
+}
+
+get_bitness() {
+ need_cmd head
+ # Architecture detection without dependencies beyond coreutils.
+ # ELF files start out "\x7fELF", and the following byte is
+ # 0x01 for 32-bit and
+ # 0x02 for 64-bit.
+ # The printf builtin on some shells like dash only supports octal
+ # escape sequences, so we use those.
+ local _current_exe_head
+ _current_exe_head=$(head -c 5 /proc/self/exe )
+ if [ "$_current_exe_head" = "$(printf '\177ELF\001')" ]; then
+ echo 32
+ elif [ "$_current_exe_head" = "$(printf '\177ELF\002')" ]; then
+ echo 64
+ else
+ err "unknown platform bitness"
+ fi
+}
+
+is_host_amd64_elf() {
+ need_cmd head
+ need_cmd tail
+ # ELF e_machine detection without dependencies beyond coreutils.
+ # Two-byte field at offset 0x12 indicates the CPU,
+ # but we're interested in it being 0x3E to indicate amd64, or not that.
+ local _current_exe_machine
+ _current_exe_machine=$(head -c 19 /proc/self/exe | tail -c 1)
+ [ "$_current_exe_machine" = "$(printf '\076')" ]
+}
+
+get_endianness() {
+ local cputype=$1
+ local suffix_eb=$2
+ local suffix_el=$3
+
+ # detect endianness without od/hexdump, like get_bitness() does.
+ need_cmd head
+ need_cmd tail
+
+ local _current_exe_endianness
+ _current_exe_endianness="$(head -c 6 /proc/self/exe | tail -c 1)"
+ if [ "$_current_exe_endianness" = "$(printf '\001')" ]; then
+ echo "${cputype}${suffix_el}"
+ elif [ "$_current_exe_endianness" = "$(printf '\002')" ]; then
+ echo "${cputype}${suffix_eb}"
+ else
+ err "unknown platform endianness"
+ fi
+}
+
+get_architecture() {
+ local _ostype _cputype _bitness _arch _clibtype
+ _ostype="$(uname -s)"
+ _cputype="$(uname -m)"
+ _clibtype="gnu"
+
+ if [ "$_ostype" = Linux ]; then
+ if [ "$(uname -o)" = Android ]; then
+ _ostype=Android
+ fi
+ if ldd --version 2>&1 | grep -q 'musl'; then
+ _clibtype="musl"
+ fi
+ fi
+
+ if [ "$_ostype" = Darwin ] && [ "$_cputype" = i386 ]; then
+ # Darwin `uname -m` lies
+ if sysctl hw.optional.x86_64 | grep -q ': 1'; then
+ _cputype=x86_64
+ fi
+ fi
+
+ if [ "$_ostype" = SunOS ]; then
+ # Both Solaris and illumos presently announce as "SunOS" in "uname -s"
+ # so use "uname -o" to disambiguate. We use the full path to the
+ # system uname in case the user has coreutils uname first in PATH,
+ # which has historically sometimes printed the wrong value here.
+ if [ "$(/usr/bin/uname -o)" = illumos ]; then
+ _ostype=illumos
+ fi
+
+ # illumos systems have multi-arch userlands, and "uname -m" reports the
+ # machine hardware name; e.g., "i86pc" on both 32- and 64-bit x86
+ # systems. Check for the native (widest) instruction set on the
+ # running kernel:
+ if [ "$_cputype" = i86pc ]; then
+ _cputype="$(isainfo -n)"
+ fi
+ fi
+
+ case "$_ostype" in
+
+ Android)
+ _ostype=linux-android
+ ;;
+
+ Linux)
+ check_proc
+ _ostype=unknown-linux-$_clibtype
+ _bitness=$(get_bitness)
+ ;;
+
+ FreeBSD)
+ _ostype=unknown-freebsd
+ ;;
+
+ NetBSD)
+ _ostype=unknown-netbsd
+ ;;
+
+ DragonFly)
+ _ostype=unknown-dragonfly
+ ;;
+
+ Darwin)
+ _ostype=apple-darwin
+ ;;
+
+ illumos)
+ _ostype=unknown-illumos
+ ;;
+
+ MINGW* | MSYS* | CYGWIN*)
+ _ostype=pc-windows-gnu
+ ;;
+
+ *)
+ err "unrecognized OS type: $_ostype"
+ ;;
+
+ esac
+
+ case "$_cputype" in
+
+ i386 | i486 | i686 | i786 | x86)
+ _cputype=i686
+ ;;
+
+ xscale | arm)
+ _cputype=arm
+ if [ "$_ostype" = "linux-android" ]; then
+ _ostype=linux-androideabi
+ fi
+ ;;
+
+ armv6l)
+ _cputype=arm
+ if [ "$_ostype" = "linux-android" ]; then
+ _ostype=linux-androideabi
+ else
+ _ostype="${_ostype}eabihf"
+ fi
+ ;;
+
+ armv7l | armv8l)
+ _cputype=armv7
+ if [ "$_ostype" = "linux-android" ]; then
+ _ostype=linux-androideabi
+ else
+ _ostype="${_ostype}eabihf"
+ fi
+ ;;
+
+ aarch64 | arm64)
+ _cputype=aarch64
+ ;;
+
+ x86_64 | x86-64 | x64 | amd64)
+ _cputype=x86_64
+ ;;
+
+ mips)
+ _cputype=$(get_endianness mips '' el)
+ ;;
+
+ mips64)
+ if [ "$_bitness" -eq 64 ]; then
+ # only n64 ABI is supported for now
+ _ostype="${_ostype}abi64"
+ _cputype=$(get_endianness mips64 '' el)
+ fi
+ ;;
+
+ ppc)
+ _cputype=powerpc
+ ;;
+
+ ppc64)
+ _cputype=powerpc64
+ ;;
+
+ ppc64le)
+ _cputype=powerpc64le
+ ;;
+
+ s390x)
+ _cputype=s390x
+ ;;
+ riscv64)
+ _cputype=riscv64gc
+ ;;
+ *)
+ err "unknown CPU type: $_cputype"
+
+ esac
+
+ # Detect 64-bit linux with 32-bit userland
+ if [ "${_ostype}" = unknown-linux-gnu ] && [ "${_bitness}" -eq 32 ]; then
+ case $_cputype in
+ x86_64)
+ if [ -n "${RUSTUP_CPUTYPE:-}" ]; then
+ _cputype="$RUSTUP_CPUTYPE"
+ else {
+ # 32-bit executable for amd64 = x32
+ if is_host_amd64_elf; then {
+ echo "This host is running an x32 userland; as it stands, x32 support is poor," 1>&2
+ echo "and there isn't a native toolchain -- you will have to install" 1>&2
+ echo "multiarch compatibility with i686 and/or amd64, then select one" 1>&2
+ echo "by re-running this script with the RUSTUP_CPUTYPE environment variable" 1>&2
+ echo "set to i686 or x86_64, respectively." 1>&2
+ echo 1>&2
+ echo "You will be able to add an x32 target after installation by running" 1>&2
+ echo " rustup target add x86_64-unknown-linux-gnux32" 1>&2
+ exit 1
+ }; else
+ _cputype=i686
+ fi
+ }; fi
+ ;;
+ mips64)
+ _cputype=$(get_endianness mips '' el)
+ ;;
+ powerpc64)
+ _cputype=powerpc
+ ;;
+ aarch64)
+ _cputype=armv7
+ if [ "$_ostype" = "linux-android" ]; then
+ _ostype=linux-androideabi
+ else
+ _ostype="${_ostype}eabihf"
+ fi
+ ;;
+ riscv64gc)
+ err "riscv64 with 32-bit userland unsupported"
+ ;;
+ esac
+ fi
+
+ # Detect armv7 but without the CPU features Rust needs in that build,
+ # and fall back to arm.
+ # See https://github.com/rust-lang/rustup.rs/issues/587.
+ if [ "$_ostype" = "unknown-linux-gnueabihf" ] && [ "$_cputype" = armv7 ]; then
+ if ensure grep '^Features' /proc/cpuinfo | grep -q -v neon; then
+ # At least one processor does not have NEON.
+ _cputype=arm
+ fi
+ fi
+
+ _arch="${_cputype}-${_ostype}"
+
+ RETVAL="$_arch"
+}
+
+say() {
+ printf 'rustup: %s\n' "$1"
+}
+
+err() {
+ say "$1" >&2
+ exit 1
+}
+
+need_cmd() {
+ if ! check_cmd "$1"; then
+ err "need '$1' (command not found)"
+ fi
+}
+
+check_cmd() {
+ command -v "$1" > /dev/null 2>&1
+}
+
+assert_nz() {
+ if [ -z "$1" ]; then err "assert_nz $2"; fi
+}
+
+# Run a command that should never fail. If the command fails execution
+# will immediately terminate with an error showing the failing
+# command.
+ensure() {
+ if ! "$@"; then err "command failed: $*"; fi
+}
+
+# This is just for indicating that commands' results are being
+# intentionally ignored. Usually, because it's being executed
+# as part of error handling.
+ignore() {
+ "$@"
+}
+
+# This wraps curl or wget. Try curl first, if not installed,
+# use wget instead.
+downloader() {
+ local _dld
+ local _ciphersuites
+ local _err
+ local _status
+ if check_cmd curl; then
+ _dld=curl
+ elif check_cmd wget; then
+ _dld=wget
+ else
+ _dld='curl or wget' # to be used in error message of need_cmd
+ fi
+
+ if [ "$1" = --check ]; then
+ need_cmd "$_dld"
+ elif [ "$_dld" = curl ]; then
+ get_ciphersuites_for_curl
+ _ciphersuites="$RETVAL"
+ if [ -n "$_ciphersuites" ]; then
+ _err=$(curl --proto '=https' --tlsv1.2 --ciphers "$_ciphersuites" --silent --show-error --fail --location "$1" --output "$2" 2>&1)
+ _status=$?
+ else
+ echo "Warning: Not enforcing strong cipher suites for TLS, this is potentially less secure"
+ if ! check_help_for "$3" curl --proto --tlsv1.2; then
+ echo "Warning: Not enforcing TLS v1.2, this is potentially less secure"
+ _err=$(curl --silent --show-error --fail --location "$1" --output "$2" 2>&1)
+ _status=$?
+ else
+ _err=$(curl --proto '=https' --tlsv1.2 --silent --show-error --fail --location "$1" --output "$2" 2>&1)
+ _status=$?
+ fi
+ fi
+ if [ -n "$_err" ]; then
+ echo "$_err" >&2
+ if echo "$_err" | grep -q 404$; then
+ err "installer for platform '$3' not found, this may be unsupported"
+ fi
+ fi
+ return $_status
+ elif [ "$_dld" = wget ]; then
+ get_ciphersuites_for_wget
+ _ciphersuites="$RETVAL"
+ if [ -n "$_ciphersuites" ]; then
+ _err=$(wget --https-only --secure-protocol=TLSv1_2 --ciphers "$_ciphersuites" "$1" -O "$2" 2>&1)
+ _status=$?
+ else
+ echo "Warning: Not enforcing strong cipher suites for TLS, this is potentially less secure"
+ if ! check_help_for "$3" wget --https-only --secure-protocol; then
+ echo "Warning: Not enforcing TLS v1.2, this is potentially less secure"
+ _err=$(wget "$1" -O "$2" 2>&1)
+ _status=$?
+ else
+ _err=$(wget --https-only --secure-protocol=TLSv1_2 "$1" -O "$2" 2>&1)
+ _status=$?
+ fi
+ fi
+ if [ -n "$_err" ]; then
+ echo "$_err" >&2
+ if echo "$_err" | grep -q ' 404 Not Found$'; then
+ err "installer for platform '$3' not found, this may be unsupported"
+ fi
+ fi
+ return $_status
+ else
+ err "Unknown downloader" # should not reach here
+ fi
+}
+
+check_help_for() {
+ local _arch
+ local _cmd
+ local _arg
+ _arch="$1"
+ shift
+ _cmd="$1"
+ shift
+
+ local _category
+ if "$_cmd" --help | grep -q 'For all options use the manual or "--help all".'; then
+ _category="all"
+ else
+ _category=""
+ fi
+
+ case "$_arch" in
+
+ *darwin*)
+ if check_cmd sw_vers; then
+ case $(sw_vers -productVersion) in
+ 10.*)
+ # If we're running on macOS, older than 10.13, then we always
+ # fail to find these options to force fallback
+ if [ "$(sw_vers -productVersion | cut -d. -f2)" -lt 13 ]; then
+ # Older than 10.13
+ echo "Warning: Detected macOS platform older than 10.13"
+ return 1
+ fi
+ ;;
+ 11.*)
+ # We assume Big Sur will be OK for now
+ ;;
+ *)
+ # Unknown product version, warn and continue
+ echo "Warning: Detected unknown macOS major version: $(sw_vers -productVersion)"
+ echo "Warning TLS capabilities detection may fail"
+ ;;
+ esac
+ fi
+ ;;
+
+ esac
+
+ for _arg in "$@"; do
+ if ! "$_cmd" --help $_category | grep -q -- "$_arg"; then
+ return 1
+ fi
+ done
+
+ true # not strictly needed
+}
+
+# Return cipher suite string specified by user, otherwise return strong TLS 1.2-1.3 cipher suites
+# if support by local tools is detected. Detection currently supports these curl backends:
+# GnuTLS and OpenSSL (possibly also LibreSSL and BoringSSL). Return value can be empty.
+get_ciphersuites_for_curl() {
+ if [ -n "${RUSTUP_TLS_CIPHERSUITES-}" ]; then
+ # user specified custom cipher suites, assume they know what they're doing
+ RETVAL="$RUSTUP_TLS_CIPHERSUITES"
+ return
+ fi
+
+ local _openssl_syntax="no"
+ local _gnutls_syntax="no"
+ local _backend_supported="yes"
+ if curl -V | grep -q ' OpenSSL/'; then
+ _openssl_syntax="yes"
+ elif curl -V | grep -iq ' LibreSSL/'; then
+ _openssl_syntax="yes"
+ elif curl -V | grep -iq ' BoringSSL/'; then
+ _openssl_syntax="yes"
+ elif curl -V | grep -iq ' GnuTLS/'; then
+ _gnutls_syntax="yes"
+ else
+ _backend_supported="no"
+ fi
+
+ local _args_supported="no"
+ if [ "$_backend_supported" = "yes" ]; then
+ # "unspecified" is for arch, allows for possibility old OS using macports, homebrew, etc.
+ if check_help_for "notspecified" "curl" "--tlsv1.2" "--ciphers" "--proto"; then
+ _args_supported="yes"
+ fi
+ fi
+
+ local _cs=""
+ if [ "$_args_supported" = "yes" ]; then
+ if [ "$_openssl_syntax" = "yes" ]; then
+ _cs=$(get_strong_ciphersuites_for "openssl")
+ elif [ "$_gnutls_syntax" = "yes" ]; then
+ _cs=$(get_strong_ciphersuites_for "gnutls")
+ fi
+ fi
+
+ RETVAL="$_cs"
+}
+
+# Return cipher suite string specified by user, otherwise return strong TLS 1.2-1.3 cipher suites
+# if support by local tools is detected. Detection currently supports these wget backends:
+# GnuTLS and OpenSSL (possibly also LibreSSL and BoringSSL). Return value can be empty.
+get_ciphersuites_for_wget() {
+ if [ -n "${RUSTUP_TLS_CIPHERSUITES-}" ]; then
+ # user specified custom cipher suites, assume they know what they're doing
+ RETVAL="$RUSTUP_TLS_CIPHERSUITES"
+ return
+ fi
+
+ local _cs=""
+ if wget -V | grep -q '\-DHAVE_LIBSSL'; then
+ # "unspecified" is for arch, allows for possibility old OS using macports, homebrew, etc.
+ if check_help_for "notspecified" "wget" "TLSv1_2" "--ciphers" "--https-only" "--secure-protocol"; then
+ _cs=$(get_strong_ciphersuites_for "openssl")
+ fi
+ elif wget -V | grep -q '\-DHAVE_LIBGNUTLS'; then
+ # "unspecified" is for arch, allows for possibility old OS using macports, homebrew, etc.
+ if check_help_for "notspecified" "wget" "TLSv1_2" "--ciphers" "--https-only" "--secure-protocol"; then
+ _cs=$(get_strong_ciphersuites_for "gnutls")
+ fi
+ fi
+
+ RETVAL="$_cs"
+}
+
+# Return strong TLS 1.2-1.3 cipher suites in OpenSSL or GnuTLS syntax. TLS 1.2
+# excludes non-ECDHE and non-AEAD cipher suites. DHE is excluded due to bad
+# DH params often found on servers (see RFC 7919). Sequence matches or is
+# similar to Firefox 68 ESR with weak cipher suites disabled via about:config.
+# $1 must be openssl or gnutls.
+get_strong_ciphersuites_for() {
+ if [ "$1" = "openssl" ]; then
+ # OpenSSL is forgiving of unknown values, no problems with TLS 1.3 values on versions that don't support it yet.
+ echo "TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384"
+ elif [ "$1" = "gnutls" ]; then
+ # GnuTLS isn't forgiving of unknown values, so this may require a GnuTLS version that supports TLS 1.3 even if wget doesn't.
+ # Begin with SECURE128 (and higher) then remove/add to build cipher suites. Produces same 9 cipher suites as OpenSSL but in slightly different order.
+ echo "SECURE128:-VERS-SSL3.0:-VERS-TLS1.0:-VERS-TLS1.1:-VERS-DTLS-ALL:-CIPHER-ALL:-MAC-ALL:-KX-ALL:+AEAD:+ECDHE-ECDSA:+ECDHE-RSA:+AES-128-GCM:+CHACHA20-POLY1305:+AES-256-GCM"
+ fi
+}
+
+main "$@" || exit 1
diff --git a/framework/java/android/bluetooth/BluetoothHapClient.java b/framework/java/android/bluetooth/BluetoothHapClient.java
index c05126d..5416d73 100644
--- a/framework/java/android/bluetooth/BluetoothHapClient.java
+++ b/framework/java/android/bluetooth/BluetoothHapClient.java
@@ -601,7 +601,7 @@
if (DBG) log("unregisterCallback");
synchronized (mCallbackExecutorMap) {
- if (mCallbackExecutorMap.remove(callback) != null) {
+ if (mCallbackExecutorMap.remove(callback) == null) {
throw new IllegalArgumentException("This callback has not been registered");
}
}
diff --git a/framework/java/android/bluetooth/BluetoothLeAudio.java b/framework/java/android/bluetooth/BluetoothLeAudio.java
index a1015b4..0c819db 100644
--- a/framework/java/android/bluetooth/BluetoothLeAudio.java
+++ b/framework/java/android/bluetooth/BluetoothLeAudio.java
@@ -1002,7 +1002,7 @@
if (DBG) log("unregisterCallback");
synchronized (mCallbackExecutorMap) {
- if (mCallbackExecutorMap.remove(callback) != null) {
+ if (mCallbackExecutorMap.remove(callback) == null) {
throw new IllegalArgumentException("This callback has not been registered");
}
}
diff --git a/framework/java/android/bluetooth/BluetoothLeBroadcast.java b/framework/java/android/bluetooth/BluetoothLeBroadcast.java
index 38a8b34..72eaf43 100644
--- a/framework/java/android/bluetooth/BluetoothLeBroadcast.java
+++ b/framework/java/android/bluetooth/BluetoothLeBroadcast.java
@@ -485,7 +485,7 @@
if (DBG) log("unregisterCallback");
synchronized (mCallbackExecutorMap) {
- if (mCallbackExecutorMap.remove(callback) != null) {
+ if (mCallbackExecutorMap.remove(callback) == null) {
throw new IllegalArgumentException("This callback has not been registered");
}
}
diff --git a/framework/java/android/bluetooth/BluetoothProfile.java b/framework/java/android/bluetooth/BluetoothProfile.java
index 78d0e13..5c80a9b 100644
--- a/framework/java/android/bluetooth/BluetoothProfile.java
+++ b/framework/java/android/bluetooth/BluetoothProfile.java
@@ -485,8 +485,22 @@
return "HEARING_AID";
case LE_AUDIO:
return "LE_AUDIO";
+ case VOLUME_CONTROL:
+ return "VOLUME_CONTROL";
+ case MCP_SERVER:
+ return "MCP_SERVER";
+ case CSIP_SET_COORDINATOR:
+ return "CSIP_SET_COORDINATOR";
+ case LE_AUDIO_BROADCAST:
+ return "LE_AUDIO_BROADCAST";
+ case LE_CALL_CONTROL:
+ return "LE_CALL_CONTROL";
case HAP_CLIENT:
return "HAP_CLIENT";
+ case LE_AUDIO_BROADCAST_ASSISTANT:
+ return "LE_AUDIO_BROADCAST_ASSISTANT";
+ case BATTERY:
+ return "BATTERY";
default:
return "UNKNOWN_PROFILE";
}
diff --git a/system/blueberry/facade/security/facade.proto b/system/blueberry/facade/security/facade.proto
index abdcd72..b9f8a76 100644
--- a/system/blueberry/facade/security/facade.proto
+++ b/system/blueberry/facade/security/facade.proto
@@ -31,6 +31,7 @@
rpc EnforceSecurityPolicy(SecurityPolicyMessage) returns (google.protobuf.Empty) {}
rpc FetchEnforceSecurityPolicyEvents(google.protobuf.Empty) returns (stream EnforceSecurityPolicyMsg) {}
rpc FetchDisconnectEvents(google.protobuf.Empty) returns (stream DisconnectMsg) {}
+ rpc FetchAdvertisingCallbackEvents(google.protobuf.Empty) returns (stream AdvertisingCallbackMsg) {}
}
message OobDataMessage {
@@ -177,3 +178,20 @@
message DisconnectMsg {
blueberry.facade.BluetoothAddressWithType address = 1;
}
+
+enum AdvertisingCallbackMsgType {
+ ADVERTISING_SET_STARTED = 0;
+ OWN_ADDRESS_READ = 1;
+}
+
+enum AdvertisingSetStarted {
+ NOT_STARTED = 0;
+ STARTED = 1;
+}
+
+message AdvertisingCallbackMsg {
+ AdvertisingCallbackMsgType message_type = 1;
+ uint32 advertiser_id = 2;
+ AdvertisingSetStarted advertising_started = 3;
+ blueberry.facade.BluetoothAddress address = 4;
+}
diff --git a/system/blueberry/tests/gd/cert/event_stream.py b/system/blueberry/tests/gd/cert/event_stream.py
index dc1348a..ee3db75 100644
--- a/system/blueberry/tests/gd/cert/event_stream.py
+++ b/system/blueberry/tests/gd/cert/event_stream.py
@@ -59,7 +59,7 @@
return '{} {}'.format(type(proto_event).__name__, text_format.MessageToString(proto_event, as_one_line=True))
-DEFAULT_TIMEOUT_SECONDS = 10
+DEFAULT_TIMEOUT_SECONDS = 30
class EventStream(IEventStream, Closable):
diff --git a/system/blueberry/tests/gd/cert/py_le_security.py b/system/blueberry/tests/gd/cert/py_le_security.py
index ed53592..f6ef921 100644
--- a/system/blueberry/tests/gd/cert/py_le_security.py
+++ b/system/blueberry/tests/gd/cert/py_le_security.py
@@ -45,6 +45,8 @@
self._ui_event_stream = EventStream(self._device.security.FetchUiEvents(empty_proto.Empty()))
self._bond_event_stream = EventStream(self._device.security.FetchBondEvents(empty_proto.Empty()))
self._helper_event_stream = EventStream(self._device.security.FetchHelperEvents(empty_proto.Empty()))
+ self._advertising_callback_event_stream = EventStream(
+ self._device.security.FetchAdvertisingCallbackEvents(empty_proto.Empty()))
def get_ui_stream(self):
return self._ui_event_stream
@@ -52,6 +54,9 @@
def get_bond_stream(self):
return self._bond_event_stream
+ def get_advertising_callback_event_stream(self):
+ return self._advertising_callback_event_stream
+
def wait_for_ui_event_passkey(self, timeout=timedelta(seconds=3)):
display_passkey_capture = SecurityCaptures.DisplayPasskey()
assertThat(self._ui_event_stream).emits(display_passkey_capture, timeout=timeout)
@@ -79,3 +84,8 @@
safeClose(self._helper_event_stream)
else:
logging.info("DUT: Helper Event Stream is None!")
+
+ if self._advertising_callback_event_stream is not None:
+ safeClose(self._advertising_callback_event_stream)
+ else:
+ logging.info("DUT: Advertising Callback Event Stream is None!")
diff --git a/system/blueberry/tests/gd_sl4a/security/oob_pairing_sl4a_test.py b/system/blueberry/tests/gd_sl4a/security/oob_pairing_sl4a_test.py
index bf8a70f..2e0a1e7 100644
--- a/system/blueberry/tests/gd_sl4a/security/oob_pairing_sl4a_test.py
+++ b/system/blueberry/tests/gd_sl4a/security/oob_pairing_sl4a_test.py
@@ -19,20 +19,51 @@
from google.protobuf import empty_pb2 as empty_proto
+from bluetooth_packets_python3 import hci_packets
+
+from blueberry.tests.gd_sl4a.lib.bt_constants import ble_scan_settings_phys
from blueberry.tests.gd_sl4a.lib.gd_sl4a_base_test import GdSl4aBaseTestClass
+from blueberry.tests.gd.cert.matchers import SecurityMatchers
+from blueberry.tests.gd.cert.py_le_security import PyLeSecurity
from blueberry.tests.gd.cert.truth import assertThat
+from blueberry.facade import common_pb2 as common
+from blueberry.facade.hci import le_advertising_manager_facade_pb2 as le_advertising_facade
+from blueberry.facade.hci import le_initiator_address_facade_pb2 as le_initiator_address_facade
+from blueberry.facade.security.facade_pb2 import AdvertisingCallbackMsgType
+from blueberry.facade.security.facade_pb2 import BondMsgType
+from blueberry.facade.security.facade_pb2 import LeAuthRequirementsMessage
+from blueberry.facade.security.facade_pb2 import LeIoCapabilityMessage
+from blueberry.facade.security.facade_pb2 import LeOobDataPresentMessage
+from blueberry.facade.security.facade_pb2 import UiCallbackMsg
+from blueberry.facade.security.facade_pb2 import UiCallbackType
+from blueberry.facade.security.facade_pb2 import UiMsgType
+
+LeIoCapabilities = LeIoCapabilityMessage.LeIoCapabilities
+LeOobDataFlag = LeOobDataPresentMessage.LeOobDataFlag
+
+DISPLAY_ONLY = LeIoCapabilityMessage(capabilities=LeIoCapabilities.DISPLAY_ONLY)
+
+OOB_NOT_PRESENT = LeOobDataPresentMessage(data_present=LeOobDataFlag.NOT_PRESENT)
+
class OobData:
- def __init__(self):
- pass
+ address = None
+ confirmation = None
+ randomizer = None
+
+ def __init__(self, address, confirmation, randomizer):
+ self.address = address
+ self.confirmation = confirmation
+ self.randomizer = randomizer
class OobPairingSl4aTest(GdSl4aBaseTestClass):
# Events sent from SL4A
SL4A_EVENT_GENERATED = "GeneratedOobData"
SL4A_EVENT_ERROR = "ErrorOobData"
+ SL4A_EVENT_BONDED = "Bonded"
# Matches tBT_TRANSPORT
# Used Strings because ints were causing gRPC problems
@@ -46,8 +77,10 @@
def setup_test(self):
super().setup_test()
+ self.cert_security = PyLeSecurity(self.cert)
def teardown_test(self):
+ self.cert_security.close()
super().teardown_test()
def _generate_sl4a_oob_data(self, transport):
@@ -59,15 +92,79 @@
logging.error("Failed to generate OOB data!")
return None
logging.info("Data received!")
- return OobData()
+ logging.info(event_info["data"])
+ return OobData(event_info["data"]["address_with_type"], event_info["data"]["confirmation"],
+ event_info["data"]["randomizer"])
def _generate_cert_oob_data(self, transport):
if transport == self.TRANSPORT_LE:
- return self.cert.security.GetLeOutOfBandData(empty_proto.Empty())
+ oob_data = self.cert.security.GetLeOutOfBandData(empty_proto.Empty())
+ # GetLeOutOfBandData adds null terminator to string in C code
+ # (length 17) before passing back to python via gRPC where it is
+ # converted back to bytes. Remove the null terminator for handling
+ # in python test, since length is known to be 16 for
+ # confirmation_value and random_value
+ oob_data.confirmation_value = oob_data.confirmation_value[:-1]
+ oob_data.random_value = oob_data.random_value[:-1]
+ return oob_data
return None
+ def set_cert_privacy_policy_with_random_address_but_advertise_resolvable(self, irk):
+ # Random static address below, no random resolvable address at this point
+ random_address_bytes = "DD:34:02:05:5C:EE".encode()
+ private_policy = le_initiator_address_facade.PrivacyPolicy(
+ address_policy=le_initiator_address_facade.AddressPolicy.USE_RESOLVABLE_ADDRESS,
+ address_with_type=common.BluetoothAddressWithType(
+ address=common.BluetoothAddress(address=random_address_bytes), type=common.RANDOM_DEVICE_ADDRESS),
+ rotation_irk=irk)
+ self.cert.security.SetLeInitiatorAddressPolicy(private_policy)
+ # Bluetooth MAC address must be upper case
+ return random_address_bytes.decode('utf-8').upper()
+
+ def wait_for_own_address(self):
+ own_address = common.BluetoothAddress()
+
+ def get_address(event):
+ if event.message_type == AdvertisingCallbackMsgType.OWN_ADDRESS_READ:
+ nonlocal own_address
+ own_address = event.address.address
+ return True
+ return False
+
+ assertThat(self.cert_security.get_advertising_callback_event_stream()).emits(get_address)
+ return own_address
+
+ def wait_for_advertising_set_started(self):
+ advertising_started = False
+
+ def get_advertising_set_started(event):
+ if event.message_type == AdvertisingCallbackMsgType.ADVERTISING_SET_STARTED:
+ nonlocal advertising_started
+ if event.advertising_started == 1:
+ advertising_started = True
+ return True
+ return False
+
+ assertThat(self.cert_security.get_advertising_callback_event_stream()).emits(get_advertising_set_started)
+ return advertising_started
+
+ def wait_for_yes_no_dialog(self):
+ address_with_type = common.BluetoothAddressWithType()
+
+ def get_address_with_type(event):
+ if event.message_type == UiMsgType.DISPLAY_PAIRING_PROMPT:
+ nonlocal address_with_type
+ address_with_type = event.peer
+ return True
+ return False
+
+ assertThat(self.cert_security.get_ui_stream()).emits(get_address_with_type)
+ return address_with_type
+
def test_sl4a_classic_generate_oob_data(self):
oob_data = self._generate_sl4a_oob_data(self.TRANSPORT_BREDR)
+ logging.info("OOB data received")
+ logging.info(oob_data)
assertThat(oob_data).isNotNone()
def test_sl4a_classic_generate_oob_data_twice(self):
@@ -81,3 +178,65 @@
def test_cert_ble_generate_oob_data(self):
oob_data = self._generate_cert_oob_data(self.TRANSPORT_LE)
assertThat(oob_data).isNotNone()
+
+ def test_sl4a_create_bond_out_of_band(self):
+ self.cert.security.SetLeIoCapability(DISPLAY_ONLY)
+ self.cert.security.SetLeOobDataPresent(OOB_NOT_PRESENT)
+ self.cert.security.SetLeAuthRequirements(LeAuthRequirementsMessage(bond=1, mitm=1, secure_connections=1))
+
+ data = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10]
+ byteArrayObject = bytearray(data)
+ irk = bytes(byteArrayObject)
+
+ DEVICE_NAME = 'Im_The_CERT!'
+ self.set_cert_privacy_policy_with_random_address_but_advertise_resolvable(irk)
+
+ gap_name = hci_packets.GapData()
+ gap_name.data_type = hci_packets.GapDataType.COMPLETE_LOCAL_NAME
+ gap_name.data = list(bytes(DEVICE_NAME, encoding='utf8'))
+ gap_data = le_advertising_facade.GapDataMsg(data=bytes(gap_name.Serialize()))
+ config = le_advertising_facade.AdvertisingConfig(
+ advertisement=[gap_data],
+ interval_min=512,
+ interval_max=768,
+ advertising_type=le_advertising_facade.AdvertisingEventType.ADV_IND,
+ own_address_type=common.USE_RANDOM_DEVICE_ADDRESS,
+ channel_map=7,
+ filter_policy=le_advertising_facade.AdvertisingFilterPolicy.ALL_DEVICES)
+ extended_config = le_advertising_facade.ExtendedAdvertisingConfig(
+ include_tx_power=True,
+ connectable=True,
+ legacy_pdus=True,
+ advertising_config=config,
+ secondary_advertising_phy=ble_scan_settings_phys["1m"])
+ request = le_advertising_facade.ExtendedCreateAdvertiserRequest(config=extended_config)
+ create_response = self.cert.hci_le_advertising_manager.ExtendedCreateAdvertiser(request)
+
+ self.wait_for_advertising_set_started()
+
+ get_own_address_request = le_advertising_facade.GetOwnAddressRequest(
+ advertiser_id=create_response.advertiser_id)
+ self.cert.hci_le_advertising_manager.GetOwnAddress(get_own_address_request)
+ advertising_address = self.wait_for_own_address()
+
+ oob_data = self._generate_cert_oob_data(self.TRANSPORT_LE)
+ assertThat(oob_data).isNotNone()
+
+ self.dut.sl4a.bluetoothCreateBondOutOfBand(
+ advertising_address.decode("utf-8").upper(), self.TRANSPORT_LE, oob_data.confirmation_value.hex(),
+ oob_data.random_value.hex())
+
+ address_with_type = self.wait_for_yes_no_dialog()
+ self.cert.security.SendUiCallback(
+ UiCallbackMsg(
+ message_type=UiCallbackType.PAIRING_PROMPT, boolean=True, unique_id=1, address=address_with_type))
+
+ assertThat(self.cert_security.get_bond_stream()).emits(SecurityMatchers.BondMsg(BondMsgType.DEVICE_BONDED))
+
+ try:
+ bond_state = self.dut.ed.pop_event(self.SL4A_EVENT_BONDED, self.default_timeout)
+ except queue.Empty as error:
+ logging.error("Failed to generate OOB data!")
+
+ assertThat(bond_state).isNotNone()
+ assertThat(bond_state["data"]["bonded_state"]).isEqualTo(True)
diff --git a/system/bta/le_audio/client.cc b/system/bta/le_audio/client.cc
index b005037..b4bf14d 100644
--- a/system/bta/le_audio/client.cc
+++ b/system/bta/le_audio/client.cc
@@ -3299,11 +3299,11 @@
stream_setup_start_timestamp_ = 0;
if (group && group->IsPendingConfiguration()) {
SuspendedForReconfiguration();
- if (!groupStateMachine_->ConfigureStream(group,
- current_context_type_)) {
- // DO SOMETHING
+ if (groupStateMachine_->ConfigureStream(group,
+ current_context_type_)) {
+ /* If configuration succeed wait for new status. */
+ return;
}
- return;
}
CancelStreamingRequest();
HandlePendingAvailableContexts(group);
diff --git a/system/bta/le_audio/state_machine.cc b/system/bta/le_audio/state_machine.cc
index 4232bd9..b897444 100644
--- a/system/bta/le_audio/state_machine.cc
+++ b/system/bta/le_audio/state_machine.cc
@@ -709,6 +709,19 @@
}
}
+ static void RemoveDataPathByCisHandle(LeAudioDevice* leAudioDevice,
+ uint16_t cis_conn_hdl) {
+ auto ases_pair = leAudioDevice->GetAsesByCisConnHdl(cis_conn_hdl);
+ IsoManager::GetInstance()->RemoveIsoDataPath(
+ cis_conn_hdl,
+ (ases_pair.sink
+ ? bluetooth::hci::iso_manager::kRemoveIsoDataPathDirectionInput
+ : 0x00) |
+ (ases_pair.source ? bluetooth::hci::iso_manager::
+ kRemoveIsoDataPathDirectionOutput
+ : 0x00));
+ }
+
void ProcessHciNotifCisDisconnected(
LeAudioDeviceGroup* group, LeAudioDevice* leAudioDevice,
const bluetooth::hci::iso_manager::cis_disconnected_evt* event) override {
@@ -825,23 +838,14 @@
}
LOG_ASSERT(ase) << __func__ << " shouldn't be called without an active ASE";
- ases_pair = leAudioDevice->GetAsesByCisConnHdl(ase->cis_conn_hdl);
-
if (ase->data_path_state ==
AudioStreamDataPathState::DATA_PATH_ESTABLISHED) {
- IsoManager::GetInstance()->RemoveIsoDataPath(
- ase->cis_conn_hdl,
- (ases_pair.sink
- ? bluetooth::hci::iso_manager::kRemoveIsoDataPathDirectionOutput
- : 0x00) |
- (ases_pair.source ? bluetooth::hci::iso_manager::
- kRemoveIsoDataPathDirectionInput
- : 0x00));
+ RemoveDataPathByCisHandle(leAudioDevice, ase->cis_conn_hdl);
}
}
private:
- static constexpr uint64_t kStateTransitionTimeoutMs = 5000;
+ static constexpr uint64_t kStateTransitionTimeoutMs = 3500;
static constexpr char kStateTransitionTimeoutMsProp[] =
"persist.bluetooth.leaudio.device.set.state.timeoutms";
Callbacks* state_machine_callbacks_;
@@ -1065,17 +1069,7 @@
AudioStreamDataPathState::DATA_PATH_ESTABLISHED);
LOG_ASSERT(ase) << __func__
<< " Shouldn't be called without an active ASE.";
-
- auto ases_pair = leAudioDevice->GetAsesByCisConnHdl(ase->cis_conn_hdl);
-
- IsoManager::GetInstance()->RemoveIsoDataPath(
- ase->cis_conn_hdl,
- (ases_pair.sink
- ? bluetooth::hci::iso_manager::kRemoveIsoDataPathDirectionOutput
- : 0x00) |
- (ases_pair.source
- ? bluetooth::hci::iso_manager::kRemoveIsoDataPathDirectionInput
- : 0x00));
+ RemoveDataPathByCisHandle(leAudioDevice, ase->cis_conn_hdl);
}
void AseStateMachineProcessIdle(
@@ -1899,16 +1893,7 @@
if (ase->data_path_state ==
AudioStreamDataPathState::DATA_PATH_ESTABLISHED) {
- auto ases_pair =
- leAudioDevice->GetAsesByCisConnHdl(ase->cis_conn_hdl);
- IsoManager::GetInstance()->RemoveIsoDataPath(
- ase->cis_conn_hdl,
- (ases_pair.sink ? bluetooth::hci::iso_manager::
- kRemoveIsoDataPathDirectionOutput
- : 0x00) |
- (ases_pair.source ? bluetooth::hci::iso_manager::
- kRemoveIsoDataPathDirectionInput
- : 0x00));
+ RemoveDataPathByCisHandle(leAudioDevice, ase->cis_conn_hdl);
} else if (ase->data_path_state ==
AudioStreamDataPathState::CIS_ESTABLISHED ||
ase->data_path_state ==
diff --git a/system/btcore/Android.bp b/system/btcore/Android.bp
index 371af6f..d2a2b34 100644
--- a/system/btcore/Android.bp
+++ b/system/btcore/Android.bp
@@ -33,7 +33,7 @@
"com.android.bluetooth",
],
target: {
- linux_glibc: {
+ host_linux: {
cflags: ["-D_GNU_SOURCE"],
},
},
diff --git a/system/btif/src/btif_sock_thread.cc b/system/btif/src/btif_sock_thread.cc
index 6744d3d..10864b9 100644
--- a/system/btif/src/btif_sock_thread.cc
+++ b/system/btif/src/btif_sock_thread.cc
@@ -442,10 +442,11 @@
return true;
}
-static void process_data_sock(int h, struct pollfd* pfds, int count) {
- asrt(count <= ts[h].poll_count);
+static void process_data_sock(int h, struct pollfd* pfds, int pfds_count,
+ int event_count) {
+ asrt(event_count <= pfds_count);
int i;
- for (i = 1; i < ts[h].poll_count; i++) {
+ for (i = 1; i < pfds_count; i++) {
if (pfds[i].revents) {
int ps_i = ts[h].psi[i];
if (ts[h].ps[ps_i].pfd.fd == -1) {
@@ -512,6 +513,7 @@
}
if (ret != 0) {
int need_process_data_fd = true;
+ int pfds_count = ts[h].poll_count;
if (pfds[0].revents) // cmd fd always is the first one
{
asrt(pfds[0].fd == ts[h].cmd_fdr);
@@ -524,7 +526,7 @@
else
ret--; // exclude the cmd fd
}
- if (need_process_data_fd) process_data_sock(h, pfds, ret);
+ if (need_process_data_fd) process_data_sock(h, pfds, pfds_count, ret);
} else {
LOG_INFO("no data, select ret: %d", ret);
};
diff --git a/system/embdrv/lc3/fuzzer/liblc3_fuzzer.cpp b/system/embdrv/lc3/fuzzer/liblc3_fuzzer.cpp
index 00ff5a2..88577bd 100644
--- a/system/embdrv/lc3/fuzzer/liblc3_fuzzer.cpp
+++ b/system/embdrv/lc3/fuzzer/liblc3_fuzzer.cpp
@@ -26,14 +26,15 @@
unsigned enc_size = lc3_encoder_size(dt_us, sr_hz);
uint16_t output_byte_count = fdp.ConsumeIntegralInRange(20, 400);
uint16_t num_frames = lc3_frame_samples(dt_us, sr_hz);
+ uint8_t bytes_per_frame = (pcm_format == LC3_PCM_FORMAT_S16 ? 2 : 4);
- if (fdp.remaining_bytes() < num_frames * 2) {
+ if (fdp.remaining_bytes() < num_frames * bytes_per_frame) {
return;
}
- std::vector<uint16_t> input_frames(num_frames);
- fdp.ConsumeData(input_frames.data(),
- input_frames.size() * 2 /* each frame is 2 bytes */);
+ std::vector<uint32_t> input_frames(
+ num_frames / (pcm_format == LC3_PCM_FORMAT_S16 ? 2 : 1));
+ fdp.ConsumeData(input_frames.data(), num_frames * bytes_per_frame);
void* lc3_encoder_mem = nullptr;
lc3_encoder_mem = malloc(enc_size);
@@ -71,7 +72,8 @@
lc3_decoder_t lc3_decoder =
lc3_setup_decoder(dt_us, sr_hz, 0, lc3_decoder_mem);
- std::vector<uint16_t> output(num_frames);
+ std::vector<uint32_t> output(num_frames /
+ (pcm_format == LC3_PCM_FORMAT_S16 ? 2 : 1));
lc3_decode(lc3_decoder, input.data(), input.size(), pcm_format,
(int16_t*)output.data(), 1);
diff --git a/system/embdrv/lc3/src/lc3.c b/system/embdrv/lc3/src/lc3.c
index 6977442..2f7789f 100644
--- a/system/embdrv/lc3/src/lc3.c
+++ b/system/embdrv/lc3/src/lc3.c
@@ -453,6 +453,7 @@
enum lc3_srate sr = decoder->sr;
enum lc3_srate sr_pcm = decoder->sr_pcm;
int ns = LC3_NS(dt, sr_pcm);
+ int ne = LC3_NE(dt, sr);
int nh = LC3_NH(sr_pcm);
float *xf = decoder->xs;
@@ -474,6 +475,8 @@
} else {
lc3_plc_synthesize(dt, sr, &decoder->plc, xg, xf);
+ memset(xf + ne, 0, (ns - ne) * sizeof(float));
+
lc3_mdct_inverse(dt, sr_pcm, sr, xf, xd, xs);
}
diff --git a/system/gd/Android.bp b/system/gd/Android.bp
index 449639b..b608ea6 100644
--- a/system/gd/Android.bp
+++ b/system/gd/Android.bp
@@ -783,6 +783,18 @@
// Export Python native symbols such as PyType_Type
// suffix: ".cpython-38android-x86_64-linux-gnu",
},
+ linux_musl_x86: {
+ enabled: false,
+ },
+ linux_musl_x86_64: {
+ include_dirs: ["external/python/cpython3/android/linux_x86_64/pyconfig"],
+ cflags: ["-DSOABI=\"cpython-38android-x86_64-linux-gnu\""],
+ // Commenting out the Linux suffix so that cpython-38-x86_64-linux-gnu
+ // Python 3.8 can also import the untagged .so library per PEP 3149
+ // Keep this change until Android py3-cmd can run ACTS, gRPC and can
+ // Export Python native symbols such as PyType_Type
+ // suffix: ".cpython-38android-x86_64-linux-gnu",
+ },
windows: {
enabled: false,
},
diff --git a/system/gd/security/facade.cc b/system/gd/security/facade.cc
index 00c6e86..1b18314 100644
--- a/system/gd/security/facade.cc
+++ b/system/gd/security/facade.cc
@@ -19,6 +19,7 @@
#include "grpc/grpc_event_queue.h"
#include "hci/address_with_type.h"
#include "hci/le_address_manager.h"
+#include "hci/le_advertising_manager.h"
#include "l2cap/classic/security_policy.h"
#include "l2cap/le/l2cap_le_module.h"
#include "os/handler.h"
@@ -54,11 +55,20 @@
} // namespace
-class SecurityModuleFacadeService : public SecurityModuleFacade::Service, public ISecurityManagerListener, public UI {
+class SecurityModuleFacadeService : public SecurityModuleFacade::Service,
+ public ISecurityManagerListener,
+ public UI,
+ public hci::AdvertisingCallback {
public:
SecurityModuleFacadeService(
- SecurityModule* security_module, L2capLeModule* l2cap_le_module, ::bluetooth::os::Handler* security_handler)
- : security_module_(security_module), l2cap_le_module_(l2cap_le_module), security_handler_(security_handler) {
+ SecurityModule* security_module,
+ L2capLeModule* l2cap_le_module,
+ ::bluetooth::os::Handler* security_handler,
+ hci::LeAdvertisingManager* le_advertising_manager)
+ : security_module_(security_module),
+ l2cap_le_module_(l2cap_le_module),
+ security_handler_(security_handler),
+ le_advertising_manager_(le_advertising_manager) {
security_module_->GetSecurityManager()->RegisterCallbackListener(this, security_handler_);
security_module_->GetSecurityManager()->SetUserInterfaceHandler(this, security_handler_);
@@ -224,6 +234,58 @@
::grpc::ServerWriter<SecurityHelperMsg>* writer) override {
return helper_events_.RunLoop(context, writer);
}
+
+ ::grpc::Status FetchAdvertisingCallbackEvents(
+ ::grpc::ServerContext* context,
+ const ::google::protobuf::Empty* request,
+ ::grpc::ServerWriter<AdvertisingCallbackMsg>* writer) override {
+ le_advertising_manager_->RegisterAdvertisingCallback(this);
+ return advertising_callback_events_.RunLoop(context, writer);
+ }
+
+ void OnAdvertisingSetStarted(int reg_id, uint8_t advertiser_id, int8_t tx_power, AdvertisingStatus status) {
+ AdvertisingCallbackMsg advertising_set_started;
+ advertising_set_started.set_message_type(AdvertisingCallbackMsgType::ADVERTISING_SET_STARTED);
+ advertising_set_started.set_advertising_started(AdvertisingSetStarted::STARTED);
+ advertising_set_started.set_advertiser_id(advertiser_id);
+ advertising_callback_events_.OnIncomingEvent(advertising_set_started);
+ }
+
+ void OnAdvertisingEnabled(uint8_t advertiser_id, bool enable, uint8_t status) {
+ // Not used yet
+ }
+
+ void OnAdvertisingDataSet(uint8_t advertiser_id, uint8_t status) {
+ // Not used yet
+ }
+
+ void OnScanResponseDataSet(uint8_t advertiser_id, uint8_t status) {
+ // Not used yet
+ }
+
+ void OnAdvertisingParametersUpdated(uint8_t advertiser_id, int8_t tx_power, uint8_t status) {
+ // Not used yet
+ }
+
+ void OnPeriodicAdvertisingParametersUpdated(uint8_t advertiser_id, uint8_t status) {
+ // Not used yet
+ }
+
+ void OnPeriodicAdvertisingDataSet(uint8_t advertiser_id, uint8_t status) {
+ // Not used yet
+ }
+
+ void OnPeriodicAdvertisingEnabled(uint8_t advertiser_id, bool enable, uint8_t status) {
+ // Not used yet
+ }
+
+ void OnOwnAddressRead(uint8_t advertiser_id, uint8_t address_type, Address address) {
+ AdvertisingCallbackMsg get_own_address;
+ get_own_address.set_message_type(AdvertisingCallbackMsgType::OWN_ADDRESS_READ);
+ get_own_address.mutable_address()->set_address(address.ToString());
+ advertising_callback_events_.OnIncomingEvent(get_own_address);
+ }
+
::grpc::Status SetIoCapability(::grpc::ServerContext* context, const IoCapabilityMessage* request,
::google::protobuf::Empty* response) override {
security_module_->GetFacadeConfigurationApi()->SetIoCapability(
@@ -532,6 +594,7 @@
SecurityModule* security_module_;
L2capLeModule* l2cap_le_module_;
::bluetooth::os::Handler* security_handler_;
+ hci::LeAdvertisingManager* le_advertising_manager_;
::bluetooth::grpc::GrpcEventQueue<UiMsg> ui_events_{"UI events"};
::bluetooth::grpc::GrpcEventQueue<BondMsg> bond_events_{"Bond events"};
::bluetooth::grpc::GrpcEventQueue<SecurityHelperMsg> helper_events_{"Events that don't fit any other category"};
@@ -539,6 +602,7 @@
"Enforce Security Policy Events"};
::bluetooth::grpc::GrpcEventQueue<DisconnectMsg> disconnect_events_{"Disconnect events"};
::bluetooth::grpc::GrpcEventQueue<OobDataBondMessage> oob_events_{"OOB Data events"};
+ ::bluetooth::grpc::GrpcEventQueue<AdvertisingCallbackMsg> advertising_callback_events_{"Advertising callback events"};
uint32_t unique_id{1};
std::map<uint32_t, common::OnceCallback<void(bool)>> user_yes_no_callbacks_;
std::map<uint32_t, common::OnceCallback<void(uint32_t)>> user_passkey_callbacks_;
@@ -548,12 +612,16 @@
::bluetooth::grpc::GrpcFacadeModule::ListDependencies(list);
list->add<SecurityModule>();
list->add<L2capLeModule>();
+ list->add<hci::LeAdvertisingManager>();
}
void SecurityModuleFacadeModule::Start() {
::bluetooth::grpc::GrpcFacadeModule::Start();
- service_ =
- new SecurityModuleFacadeService(GetDependency<SecurityModule>(), GetDependency<L2capLeModule>(), GetHandler());
+ service_ = new SecurityModuleFacadeService(
+ GetDependency<SecurityModule>(),
+ GetDependency<L2capLeModule>(),
+ GetHandler(),
+ GetDependency<hci::LeAdvertisingManager>());
}
void SecurityModuleFacadeModule::Stop() {
diff --git a/system/gd/security/record/security_record_storage.cc b/system/gd/security/record/security_record_storage.cc
index 257f60a..ae7128f 100644
--- a/system/gd/security/record/security_record_storage.cc
+++ b/system/gd/security/record/security_record_storage.cc
@@ -114,10 +114,10 @@
} else if (!record->IsClassicLinkKeyValid() && record->remote_ltk) {
mutation.Add(device.SetDeviceType(hci::DeviceType::LE));
} else {
- LOG_ERROR(
- "Cannot determine device type from security record for '%s'; dropping!",
+ mutation.Add(device.SetDeviceType(hci::DeviceType::LE));
+ LOG_WARN(
+ "Cannot determine device type from security record for '%s'; defaulting to LE",
record->GetPseudoAddress()->ToString().c_str());
- continue;
}
mutation.Commit();
SetClassicData(mutation, record, device);
diff --git a/system/osi/Android.bp b/system/osi/Android.bp
index 47a2b29..ef6404d 100644
--- a/system/osi/Android.bp
+++ b/system/osi/Android.bp
@@ -92,7 +92,7 @@
// should be compatible for a Linux host OS. We should figure out what to do for
// a non-Linux host OS.
target: {
- linux_glibc: {
+ host_linux: {
cflags: [
"-D_GNU_SOURCE",
"-DOS_GENERIC",
@@ -145,7 +145,7 @@
"libc++fs",
],
target: {
- linux_glibc: {
+ host_linux: {
cflags: ["-DOS_GENERIC"],
},
},
diff --git a/system/service/Android.bp b/system/service/Android.bp
index 8e76bef..2d018b2 100644
--- a/system/service/Android.bp
+++ b/system/service/Android.bp
@@ -158,7 +158,7 @@
"test/stub_ipc_handler_binder.cc",
],
},
- linux_glibc: {
+ host_linux: {
srcs: btserviceLinuxSrc + [
// TODO(bcf): Fix this test.
//"test/ipc_linux_unittest.cc",
diff --git a/system/stack/btm/btm_sec.cc b/system/stack/btm/btm_sec.cc
index f06cdf3..a817900 100644
--- a/system/stack/btm/btm_sec.cc
+++ b/system/stack/btm/btm_sec.cc
@@ -4409,7 +4409,11 @@
auto addr = new RawAddress(p_dev_rec->bd_addr);
bt_status_t status = do_in_main_thread_delayed(
FROM_HERE, base::Bind(&btm_sec_auth_timer_timeout, addr),
+#if BASE_VER < 931007
base::TimeDelta::FromMilliseconds(BTM_DELAY_AUTH_MS));
+#else
+ base::Milliseconds(BTM_DELAY_AUTH_MS));
+#endif
if (status != BT_STATUS_SUCCESS) {
LOG(ERROR) << __func__
<< ": do_in_main_thread_delayed failed. directly calling.";
diff --git a/system/test/rootcanal/bluetooth_hci.cc b/system/test/rootcanal/bluetooth_hci.cc
index 7ceff67..0df9bd8 100644
--- a/system/test/rootcanal/bluetooth_hci.cc
+++ b/system/test/rootcanal/bluetooth_hci.cc
@@ -25,8 +25,9 @@
#include "hci_internals.h"
#include "log/log.h"
-#include "model/devices/hci_socket_device.h"
+#include "model/devices/hci_device.h"
#include "model/devices/link_layer_socket_device.h"
+#include "model/hci/hci_socket_transport.h"
namespace android {
namespace hardware {
@@ -37,7 +38,8 @@
using android::hardware::hidl_vec;
using rootcanal::AsyncTaskId;
using rootcanal::DualModeController;
-using rootcanal::HciSocketDevice;
+using rootcanal::HciDevice;
+using rootcanal::HciSocketTransport;
using rootcanal::LinkLayerSocketDevice;
using rootcanal::TaskCallback;
@@ -205,7 +207,8 @@
SetUpTestChannel();
SetUpHciServer([this](std::shared_ptr<AsyncDataChannel> socket,
AsyncDataChannelServer* srv) {
- test_model_.AddHciConnection(HciSocketDevice::Create(socket, ""));
+ auto transport = HciSocketTransport::Create(socket);
+ test_model_.AddHciConnection(HciDevice::Create(transport, ""));
srv->StartListening();
});
SetUpLinkLayerServer([this](std::shared_ptr<AsyncDataChannel> socket,
diff --git a/tools/pdl/src/main.rs b/tools/pdl/src/main.rs
index 5f488fd..7309f98 100644
--- a/tools/pdl/src/main.rs
+++ b/tools/pdl/src/main.rs
@@ -21,10 +21,12 @@
#[derive(Debug, StructOpt)]
#[structopt(name = "pdl-parser", about = "Packet Description Language parser tool.")]
struct Opt {
- #[structopt(short, long = "--version", help = "Print tool version and exit.")]
+ /// Print tool version and exit.
+ #[structopt(short, long = "--version")]
version: bool,
- #[structopt(name = "FILE", help = "Input file.")]
+ /// Input file.
+ #[structopt(name = "FILE")]
input_file: String,
}
diff --git a/tools/rootcanal/Android.bp b/tools/rootcanal/Android.bp
index d2d893a..66e846f 100644
--- a/tools/rootcanal/Android.bp
+++ b/tools/rootcanal/Android.bp
@@ -80,13 +80,14 @@
"model/controller/security_manager.cc",
"model/devices/device.cc",
"model/devices/device_properties.cc",
- "model/devices/h4_data_channel_packetizer.cc",
- "model/devices/h4_packetizer.cc",
- "model/devices/h4_parser.cc",
- "model/devices/hci_protocol.cc",
- "model/devices/hci_socket_device.cc",
+ "model/devices/hci_device.cc",
"model/devices/link_layer_socket_device.cc",
"model/devices/remote_loopback_device.cc",
+ "model/hci/h4_data_channel_packetizer.cc",
+ "model/hci/h4_packetizer.cc",
+ "model/hci/h4_parser.cc",
+ "model/hci/hci_protocol.cc",
+ "model/hci/hci_socket_transport.cc",
"model/setup/async_manager.cc",
"model/setup/phy_layer_factory.cc",
"model/setup/test_channel_transport.cc",
@@ -230,9 +231,9 @@
"gd_defaults",
],
srcs: [
- "model/devices/h4_packetizer.cc",
- "model/devices/h4_parser.cc",
- "model/devices/hci_protocol.cc",
+ "model/hci/h4_packetizer.cc",
+ "model/hci/h4_parser.cc",
+ "model/hci/hci_protocol.cc",
],
local_include_dirs: [
diff --git a/tools/rootcanal/desktop/test_environment.cc b/tools/rootcanal/desktop/test_environment.cc
index 530abab..261dc43 100644
--- a/tools/rootcanal/desktop/test_environment.cc
+++ b/tools/rootcanal/desktop/test_environment.cc
@@ -20,8 +20,8 @@
#include <utility> // for move
#include <vector> // for vector
-#include "model/devices/hci_socket_device.h" // for HciSocketDevice
#include "model/devices/link_layer_socket_device.h" // for LinkLayerSocketDevice
+#include "model/hci/hci_socket_transport.h" // for HciSocketTransport
#include "net/async_data_channel.h" // for AsyncDataChannel
#include "net/async_data_channel_connector.h" // for AsyncDataChannelConnector
#include "os/log.h" // for LOG_INFO, LOG_ERROR, LOG_WARN
@@ -31,7 +31,8 @@
namespace root_canal {
using rootcanal::AsyncTaskId;
-using rootcanal::HciSocketDevice;
+using rootcanal::HciDevice;
+using rootcanal::HciSocketTransport;
using rootcanal::LinkLayerSocketDevice;
using rootcanal::TaskCallback;
@@ -57,8 +58,9 @@
SetUpTestChannel();
SetUpHciServer([this](std::shared_ptr<AsyncDataChannel> socket,
AsyncDataChannelServer* srv) {
+ auto transport = HciSocketTransport::Create(socket);
test_model_.AddHciConnection(
- HciSocketDevice::Create(socket, controller_properties_file_));
+ HciDevice::Create(transport, controller_properties_file_));
srv->StartListening();
});
SetUpLinkLayerServer();
diff --git a/tools/rootcanal/model/devices/hci_device.cc b/tools/rootcanal/model/devices/hci_device.cc
new file mode 100644
index 0000000..a6e48c3
--- /dev/null
+++ b/tools/rootcanal/model/devices/hci_device.cc
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#include "hci_device.h"
+
+#include "os/log.h"
+
+namespace rootcanal {
+
+HciDevice::HciDevice(std::shared_ptr<HciTransport> transport,
+ const std::string& properties_filename)
+ : DualModeController(properties_filename), transport_(transport) {
+ advertising_interval_ms_ = std::chrono::milliseconds(1000);
+
+ page_scan_delay_ms_ = std::chrono::milliseconds(600);
+
+ properties_.SetPageScanRepetitionMode(0);
+ properties_.SetClassOfDevice(0x600420);
+ properties_.SetExtendedInquiryData({
+ 12, // length
+ 9, // Type: Device Name
+ 'g',
+ 'D',
+ 'e',
+ 'v',
+ 'i',
+ 'c',
+ 'e',
+ '-',
+ 'h',
+ 'c',
+ 'i',
+
+ });
+ properties_.SetName({
+ 'g',
+ 'D',
+ 'e',
+ 'v',
+ 'i',
+ 'c',
+ 'e',
+ '-',
+ 'H',
+ 'C',
+ 'I',
+ });
+
+ RegisterEventChannel([this](std::shared_ptr<std::vector<uint8_t>> packet) {
+ transport_->SendEvent(*packet);
+ });
+ RegisterAclChannel([this](std::shared_ptr<std::vector<uint8_t>> packet) {
+ transport_->SendAcl(*packet);
+ });
+ RegisterScoChannel([this](std::shared_ptr<std::vector<uint8_t>> packet) {
+ transport_->SendSco(*packet);
+ });
+ RegisterIsoChannel([this](std::shared_ptr<std::vector<uint8_t>> packet) {
+ transport_->SendIso(*packet);
+ });
+
+ transport_->RegisterCallbacks(
+ [this](const std::shared_ptr<std::vector<uint8_t>> command) {
+ HandleCommand(command);
+ },
+ [this](const std::shared_ptr<std::vector<uint8_t>> acl) {
+ HandleAcl(acl);
+ },
+ [this](const std::shared_ptr<std::vector<uint8_t>> sco) {
+ HandleSco(sco);
+ },
+ [this](const std::shared_ptr<std::vector<uint8_t>> iso) {
+ HandleIso(iso);
+ },
+ [this]() {
+ LOG_INFO("HCI transport closed");
+ Close();
+ });
+}
+
+void HciDevice::TimerTick() {
+ transport_->TimerTick();
+ DualModeController::TimerTick();
+}
+
+void HciDevice::Close() {
+ transport_->Close();
+ DualModeController::Close();
+}
+
+} // namespace rootcanal
diff --git a/tools/rootcanal/model/devices/hci_device.h b/tools/rootcanal/model/devices/hci_device.h
new file mode 100644
index 0000000..eb79cd9
--- /dev/null
+++ b/tools/rootcanal/model/devices/hci_device.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#pragma once
+
+#include <memory> // for shared_ptr, make_...
+#include <string> // for string
+
+#include "model/controller/dual_mode_controller.h" // for DualModeController
+#include "model/hci/hci_transport.h" // for HciTransport
+
+namespace rootcanal {
+
+class HciDevice : public DualModeController {
+ public:
+ HciDevice(std::shared_ptr<HciTransport> transport,
+ const std::string& properties_filename);
+ ~HciDevice() = default;
+
+ static std::shared_ptr<HciDevice> Create(
+ std::shared_ptr<HciTransport> transport,
+ const std::string& properties_filename) {
+ return std::make_shared<HciDevice>(transport, properties_filename);
+ }
+
+ std::string GetTypeString() const override { return "hci_device"; }
+
+ void TimerTick() override;
+
+ void Close() override;
+
+ private:
+ std::shared_ptr<HciTransport> transport_;
+};
+
+} // namespace rootcanal
diff --git a/tools/rootcanal/model/devices/hci_socket_device.cc b/tools/rootcanal/model/devices/hci_socket_device.cc
deleted file mode 100644
index 83bf5e2..0000000
--- a/tools/rootcanal/model/devices/hci_socket_device.cc
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * 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
- *
- * http://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.
- */
-
-#include "hci_socket_device.h"
-
-#include <chrono> // for milliseconds
-#include <type_traits> // for remove_extent_t
-
-#include "model/devices/device_properties.h" // for DeviceProperties
-#include "os/log.h" // for LOG_INFO, LOG_ALWAYS_FATAL
-
-using std::vector;
-
-namespace rootcanal {
-
-HciSocketDevice::HciSocketDevice(std::shared_ptr<AsyncDataChannel> socket,
- const std::string& properties_filename)
- : DualModeController(properties_filename), socket_(socket) {
- advertising_interval_ms_ = std::chrono::milliseconds(1000);
-
- page_scan_delay_ms_ = std::chrono::milliseconds(600);
-
- properties_.SetPageScanRepetitionMode(0);
- properties_.SetClassOfDevice(0x600420);
- properties_.SetExtendedInquiryData({
- 16, // length
- 9, // Type: Device Name
- 'g',
- 'D',
- 'e',
- 'v',
- 'i',
- 'c',
- 'e',
- '-',
- 'h',
- 'c',
- 'i',
- '_',
- 'n',
- 'e',
- 't',
- });
- properties_.SetName({
- 'g',
- 'D',
- 'e',
- 'v',
- 'i',
- 'c',
- 'e',
- '-',
- 'H',
- 'C',
- 'I',
- '_',
- 'N',
- 'e',
- 't',
- });
-
- h4_ = H4DataChannelPacketizer(
- socket,
- [this](const std::vector<uint8_t>& raw_command) {
- std::shared_ptr<std::vector<uint8_t>> packet_copy =
- std::make_shared<std::vector<uint8_t>>(raw_command);
- HandleCommand(packet_copy);
- },
- [](const std::vector<uint8_t>&) {
- LOG_ALWAYS_FATAL("Unexpected Event in HciSocketDevice!");
- },
- [this](const std::vector<uint8_t>& raw_acl) {
- std::shared_ptr<std::vector<uint8_t>> packet_copy =
- std::make_shared<std::vector<uint8_t>>(raw_acl);
- HandleAcl(packet_copy);
- },
- [this](const std::vector<uint8_t>& raw_sco) {
- std::shared_ptr<std::vector<uint8_t>> packet_copy =
- std::make_shared<std::vector<uint8_t>>(raw_sco);
- HandleSco(packet_copy);
- },
- [this](const std::vector<uint8_t>& raw_iso) {
- std::shared_ptr<std::vector<uint8_t>> packet_copy =
- std::make_shared<std::vector<uint8_t>>(raw_iso);
- HandleIso(packet_copy);
- },
- [this]() {
- LOG_INFO("HCI socket device disconnected");
- Close();
- });
-
- RegisterEventChannel([this](std::shared_ptr<std::vector<uint8_t>> packet) {
- SendHci(PacketType::EVENT, packet);
- });
- RegisterAclChannel([this](std::shared_ptr<std::vector<uint8_t>> packet) {
- SendHci(PacketType::ACL, packet);
- });
- RegisterScoChannel([this](std::shared_ptr<std::vector<uint8_t>> packet) {
- SendHci(PacketType::SCO, packet);
- });
- RegisterIsoChannel([this](std::shared_ptr<std::vector<uint8_t>> packet) {
- SendHci(PacketType::ISO, packet);
- });
-}
-
-void HciSocketDevice::TimerTick() {
- h4_.OnDataReady(socket_);
- DualModeController::TimerTick();
-}
-
-void HciSocketDevice::SendHci(
- PacketType packet_type,
- const std::shared_ptr<std::vector<uint8_t>> packet) {
- if (!socket_ || !socket_->Connected()) {
- LOG_INFO("Closed socket. Dropping packet of type %d",
- static_cast<int>(packet_type));
- return;
- }
- uint8_t type = static_cast<uint8_t>(packet_type);
- h4_.Send(type, packet->data(), packet->size());
-}
-
-void HciSocketDevice::Close() {
- if (socket_) {
- socket_->Close();
- }
- DualModeController::Close();
-}
-
-} // namespace rootcanal
diff --git a/tools/rootcanal/model/devices/hci_socket_device.h b/tools/rootcanal/model/devices/hci_socket_device.h
deleted file mode 100644
index 19324e8..0000000
--- a/tools/rootcanal/model/devices/hci_socket_device.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * 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
- *
- * http://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.
- */
-
-#pragma once
-
-#include <cstdint> // for uint8_t
-#include <functional> // for __base, function
-#include <memory> // for shared_ptr, make_...
-#include <string> // for string
-#include <vector> // for vector
-
-#include "model/controller/dual_mode_controller.h" // for DualModeController
-#include "model/devices/h4_data_channel_packetizer.h" // for ClientDisconnectC...
-#include "model/devices/hci_protocol.h" // for PacketReadCallback
-#include "net/async_data_channel.h" // for AsyncDataChannel
-
-namespace rootcanal {
-
-using android::net::AsyncDataChannel;
-
-class HciSocketDevice : public DualModeController {
- public:
- HciSocketDevice(std::shared_ptr<AsyncDataChannel> socket,
- const std::string& properties_filename);
- ~HciSocketDevice() = default;
-
- static std::shared_ptr<HciSocketDevice> Create(
- std::shared_ptr<AsyncDataChannel> socket,
- const std::string& properties_filename) {
- return std::make_shared<HciSocketDevice>(socket, properties_filename);
- }
-
- std::string GetTypeString() const override { return "hci_socket_device"; }
-
- void TimerTick() override;
-
- void SendHci(PacketType packet_type,
- const std::shared_ptr<std::vector<uint8_t>> packet);
-
- void Close() override;
-
- private:
- std::shared_ptr<AsyncDataChannel> socket_;
- H4DataChannelPacketizer h4_{socket_,
- [](const std::vector<uint8_t>&) {},
- [](const std::vector<uint8_t>&) {},
- [](const std::vector<uint8_t>&) {},
- [](const std::vector<uint8_t>&) {},
- [](const std::vector<uint8_t>&) {},
- [] {}};
-};
-
-} // namespace rootcanal
diff --git a/tools/rootcanal/model/devices/h4_data_channel_packetizer.cc b/tools/rootcanal/model/hci/h4_data_channel_packetizer.cc
similarity index 90%
rename from tools/rootcanal/model/devices/h4_data_channel_packetizer.cc
rename to tools/rootcanal/model/hci/h4_data_channel_packetizer.cc
index f089b5d..99f8875 100644
--- a/tools/rootcanal/model/devices/h4_data_channel_packetizer.cc
+++ b/tools/rootcanal/model/hci/h4_data_channel_packetizer.cc
@@ -26,10 +26,10 @@
#include <utility> // for move
#include <vector> // for vector
-#include "model/devices/h4_parser.h" // for H4Parser, ClientDisconnectCa...
-#include "model/devices/hci_protocol.h" // for PacketReadCallback, AsyncDataChannel
-#include "net/async_data_channel.h" // for AsyncDataChannel
-#include "os/log.h" // for LOG_ERROR, LOG_ALWAYS_FATAL
+#include "model/hci/h4_parser.h" // for H4Parser, ClientDisconnectCa...
+#include "model/hci/hci_protocol.h" // for PacketReadCallback, AsyncDataChannel
+#include "net/async_data_channel.h" // for AsyncDataChannel
+#include "os/log.h" // for LOG_ERROR, LOG_ALWAYS_FATAL
namespace rootcanal {
diff --git a/tools/rootcanal/model/devices/h4_data_channel_packetizer.h b/tools/rootcanal/model/hci/h4_data_channel_packetizer.h
similarity index 100%
rename from tools/rootcanal/model/devices/h4_data_channel_packetizer.h
rename to tools/rootcanal/model/hci/h4_data_channel_packetizer.h
diff --git a/tools/rootcanal/model/devices/h4_packetizer.cc b/tools/rootcanal/model/hci/h4_packetizer.cc
similarity index 100%
rename from tools/rootcanal/model/devices/h4_packetizer.cc
rename to tools/rootcanal/model/hci/h4_packetizer.cc
diff --git a/tools/rootcanal/model/devices/h4_packetizer.h b/tools/rootcanal/model/hci/h4_packetizer.h
similarity index 100%
rename from tools/rootcanal/model/devices/h4_packetizer.h
rename to tools/rootcanal/model/hci/h4_packetizer.h
diff --git a/tools/rootcanal/model/devices/h4_parser.cc b/tools/rootcanal/model/hci/h4_parser.cc
similarity index 95%
rename from tools/rootcanal/model/devices/h4_parser.cc
rename to tools/rootcanal/model/hci/h4_parser.cc
index fa9fecf..f55be5c 100644
--- a/tools/rootcanal/model/devices/h4_parser.cc
+++ b/tools/rootcanal/model/hci/h4_parser.cc
@@ -14,7 +14,7 @@
// limitations under the License.
//
-#include "model/devices/h4_parser.h" // for H4Parser, PacketType, H4Pars...
+#include "model/hci/h4_parser.h" // for H4Parser, PacketType, H4Pars...
#include <stddef.h> // for size_t
@@ -23,8 +23,8 @@
#include <utility> // for move
#include <vector> // for vector
-#include "model/devices/hci_protocol.h" // for PacketReadCallback
-#include "os/log.h" // for LOG_ALWAYS_FATAL, LOG_INFO
+#include "model/hci/hci_protocol.h" // for PacketReadCallback
+#include "os/log.h" // for LOG_ALWAYS_FATAL, LOG_INFO
namespace rootcanal {
diff --git a/tools/rootcanal/model/devices/h4_parser.h b/tools/rootcanal/model/hci/h4_parser.h
similarity index 98%
rename from tools/rootcanal/model/devices/h4_parser.h
rename to tools/rootcanal/model/hci/h4_parser.h
index 6886924..8a8802c 100644
--- a/tools/rootcanal/model/devices/h4_parser.h
+++ b/tools/rootcanal/model/hci/h4_parser.h
@@ -23,7 +23,7 @@
#include <ostream> // for operator<<, ostream
#include <vector> // for vector
-#include "model/devices/hci_protocol.h" // for PacketReadCallback
+#include "model/hci/hci_protocol.h" // for PacketReadCallback
namespace rootcanal {
diff --git a/tools/rootcanal/model/devices/hci_protocol.cc b/tools/rootcanal/model/hci/hci_protocol.cc
similarity index 100%
rename from tools/rootcanal/model/devices/hci_protocol.cc
rename to tools/rootcanal/model/hci/hci_protocol.cc
diff --git a/tools/rootcanal/model/devices/hci_protocol.h b/tools/rootcanal/model/hci/hci_protocol.h
similarity index 100%
rename from tools/rootcanal/model/devices/hci_protocol.h
rename to tools/rootcanal/model/hci/hci_protocol.h
diff --git a/tools/rootcanal/model/hci/hci_socket_transport.cc b/tools/rootcanal/model/hci/hci_socket_transport.cc
new file mode 100644
index 0000000..0d6f0c8
--- /dev/null
+++ b/tools/rootcanal/model/hci/hci_socket_transport.cc
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#include "hci_socket_transport.h"
+
+#include "os/log.h" // for LOG_INFO, LOG_ALWAYS_FATAL
+
+namespace rootcanal {
+
+HciSocketTransport::HciSocketTransport(std::shared_ptr<AsyncDataChannel> socket)
+ : socket_(socket) {}
+
+void HciSocketTransport::RegisterCallbacks(PacketCallback command_callback,
+ PacketCallback acl_callback,
+ PacketCallback sco_callback,
+ PacketCallback iso_callback,
+ CloseCallback close_callback) {
+ // TODO: Avoid the copy here by using new buffer in H4DataChannel
+ h4_ = H4DataChannelPacketizer(
+ socket_,
+ [command_callback](const std::vector<uint8_t>& raw_command) {
+ std::shared_ptr<std::vector<uint8_t>> packet_copy =
+ std::make_shared<std::vector<uint8_t>>(raw_command);
+ command_callback(packet_copy);
+ },
+ [](const std::vector<uint8_t>&) {
+ LOG_ALWAYS_FATAL("Unexpected Event in HciSocketTransport!");
+ },
+ [acl_callback](const std::vector<uint8_t>& raw_acl) {
+ std::shared_ptr<std::vector<uint8_t>> packet_copy =
+ std::make_shared<std::vector<uint8_t>>(raw_acl);
+ acl_callback(packet_copy);
+ },
+ [sco_callback](const std::vector<uint8_t>& raw_sco) {
+ std::shared_ptr<std::vector<uint8_t>> packet_copy =
+ std::make_shared<std::vector<uint8_t>>(raw_sco);
+ sco_callback(packet_copy);
+ },
+ [iso_callback](const std::vector<uint8_t>& raw_iso) {
+ std::shared_ptr<std::vector<uint8_t>> packet_copy =
+ std::make_shared<std::vector<uint8_t>>(raw_iso);
+ iso_callback(packet_copy);
+ },
+ close_callback);
+}
+
+void HciSocketTransport::TimerTick() { h4_.OnDataReady(socket_); }
+
+void HciSocketTransport::SendHci(PacketType packet_type,
+ const std::vector<uint8_t>& packet) {
+ if (!socket_ || !socket_->Connected()) {
+ LOG_INFO("Closed socket. Dropping packet of type %d",
+ static_cast<int>(packet_type));
+ return;
+ }
+ uint8_t type = static_cast<uint8_t>(packet_type);
+ h4_.Send(type, packet.data(), packet.size());
+}
+
+void HciSocketTransport::SendEvent(const std::vector<uint8_t>& packet) {
+ SendHci(PacketType::EVENT, packet);
+}
+
+void HciSocketTransport::SendAcl(const std::vector<uint8_t>& packet) {
+ SendHci(PacketType::ACL, packet);
+}
+
+void HciSocketTransport::SendSco(const std::vector<uint8_t>& packet) {
+ SendHci(PacketType::SCO, packet);
+}
+
+void HciSocketTransport::SendIso(const std::vector<uint8_t>& packet) {
+ SendHci(PacketType::ISO, packet);
+}
+
+void HciSocketTransport::Close() { socket_->Close(); }
+
+} // namespace rootcanal
diff --git a/tools/rootcanal/model/hci/hci_socket_transport.h b/tools/rootcanal/model/hci/hci_socket_transport.h
new file mode 100644
index 0000000..f3f42f4
--- /dev/null
+++ b/tools/rootcanal/model/hci/hci_socket_transport.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#pragma once
+
+#include <memory> // for shared_ptr, make_...
+
+#include "model/hci/h4_data_channel_packetizer.h" // for H4DataChannelP...
+#include "model/hci/hci_transport.h" // for HciTransport
+#include "net/async_data_channel.h" // for AsyncDataChannel
+
+namespace rootcanal {
+
+using android::net::AsyncDataChannel;
+
+class HciSocketTransport : public HciTransport {
+ public:
+ HciSocketTransport(std::shared_ptr<AsyncDataChannel> socket);
+ ~HciSocketTransport() = default;
+
+ static std::shared_ptr<HciSocketTransport> Create(
+ std::shared_ptr<AsyncDataChannel> socket) {
+ return std::make_shared<HciSocketTransport>(socket);
+ }
+
+ void SendEvent(const std::vector<uint8_t>& packet) override;
+
+ void SendAcl(const std::vector<uint8_t>& packet) override;
+
+ void SendSco(const std::vector<uint8_t>& packet) override;
+
+ void SendIso(const std::vector<uint8_t>& packet) override;
+
+ void RegisterCallbacks(PacketCallback command_callback,
+ PacketCallback acl_callback,
+ PacketCallback sco_callback,
+ PacketCallback iso_callback,
+ CloseCallback close_callback) override;
+
+ void TimerTick() override;
+
+ void Close() override;
+
+ private:
+ void SendHci(PacketType packet_type, const std::vector<uint8_t>& packet);
+
+ std::shared_ptr<AsyncDataChannel> socket_;
+ H4DataChannelPacketizer h4_{socket_,
+ [](const std::vector<uint8_t>&) {},
+ [](const std::vector<uint8_t>&) {},
+ [](const std::vector<uint8_t>&) {},
+ [](const std::vector<uint8_t>&) {},
+ [](const std::vector<uint8_t>&) {},
+ [] {}};
+};
+
+} // namespace rootcanal
diff --git a/tools/rootcanal/model/hci/hci_transport.h b/tools/rootcanal/model/hci/hci_transport.h
new file mode 100644
index 0000000..8ffb349
--- /dev/null
+++ b/tools/rootcanal/model/hci/hci_transport.h
@@ -0,0 +1,51 @@
+//
+// Copyright 2022 The Android Open Source Project
+//
+// 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
+//
+// http://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.
+//
+
+#pragma once
+
+#include <functional>
+#include <vector>
+
+namespace rootcanal {
+
+using PacketCallback =
+ std::function<void(const std::shared_ptr<std::vector<uint8_t>>)>;
+using CloseCallback = std::function<void()>;
+
+class HciTransport {
+ public:
+ virtual ~HciTransport() = default;
+
+ virtual void SendEvent(const std::vector<uint8_t>& packet) = 0;
+
+ virtual void SendAcl(const std::vector<uint8_t>& packet) = 0;
+
+ virtual void SendSco(const std::vector<uint8_t>& packet) = 0;
+
+ virtual void SendIso(const std::vector<uint8_t>& packet) = 0;
+
+ virtual void RegisterCallbacks(PacketCallback command_callback,
+ PacketCallback acl_callback,
+ PacketCallback sco_callback,
+ PacketCallback iso_callback,
+ CloseCallback close_callback) = 0;
+
+ virtual void TimerTick() = 0;
+
+ virtual void Close() = 0;
+};
+
+} // namespace rootcanal
diff --git a/tools/rootcanal/model/setup/test_model.cc b/tools/rootcanal/model/setup/test_model.cc
index 3b993b4..c2ad281 100644
--- a/tools/rootcanal/model/setup/test_model.cc
+++ b/tools/rootcanal/model/setup/test_model.cc
@@ -171,7 +171,7 @@
AddLinkLayerConnection(dev, phy_type);
}
-void TestModel::AddHciConnection(std::shared_ptr<HciSocketDevice> dev) {
+void TestModel::AddHciConnection(std::shared_ptr<HciDevice> dev) {
size_t index = Add(std::static_pointer_cast<Device>(dev));
std::string addr = "da:4c:10:de:17:"; // Da HCI dev
std::stringstream stream;
diff --git a/tools/rootcanal/model/setup/test_model.h b/tools/rootcanal/model/setup/test_model.h
index 99138a8..263346c 100644
--- a/tools/rootcanal/model/setup/test_model.h
+++ b/tools/rootcanal/model/setup/test_model.h
@@ -25,7 +25,7 @@
#include <vector> // for vector
#include "hci/address.h" // for Address
-#include "model/devices/hci_socket_device.h" // for HciSocketDevice
+#include "model/devices/hci_device.h" // for HciDevice
#include "model/setup/async_manager.h" // for AsyncUserId, AsyncTaskId
#include "phy.h" // for Phy, Phy::Type
#include "phy_layer_factory.h" // for PhyLayerFactory
@@ -76,7 +76,7 @@
// Handle incoming remote connections
void AddLinkLayerConnection(std::shared_ptr<Device> dev, Phy::Type phy_type);
- void AddHciConnection(std::shared_ptr<HciSocketDevice> dev);
+ void AddHciConnection(std::shared_ptr<HciDevice> dev);
// Handle closed remote connections (both hci & link layer)
void OnConnectionClosed(size_t index, AsyncUserId user_id);
diff --git a/tools/rootcanal/test/h4_parser_unittest.cc b/tools/rootcanal/test/h4_parser_unittest.cc
index 0209117..9b74c1c 100644
--- a/tools/rootcanal/test/h4_parser_unittest.cc
+++ b/tools/rootcanal/test/h4_parser_unittest.cc
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "model/devices/h4_parser.h"
+#include "model/hci/h4_parser.h"
#include <gtest/gtest.h>