Compare commits
13 Commits
v0.0.172
...
gbg/androi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dc6b466a42 | ||
|
|
5e5c9c2580 | ||
|
|
246b11925c | ||
|
|
dfa9131192 | ||
|
|
88c801b4c2 | ||
|
|
a1b55b94e0 | ||
|
|
80db9e2e2f | ||
|
|
ce74690420 | ||
|
|
50de4dfb5d | ||
|
|
9bcdf860f4 | ||
|
|
511ab4b630 | ||
|
|
7e331c2944 | ||
|
|
50fd2218fa |
@@ -1425,10 +1425,10 @@ class Device(CompositeEventEmitter):
|
||||
check_result=True,
|
||||
)
|
||||
|
||||
self.advertising_own_address_type = own_address_type
|
||||
self.auto_restart_advertising = auto_restart
|
||||
self.advertising_type = advertising_type
|
||||
self.advertising_own_address_type = own_address_type
|
||||
self.advertising = True
|
||||
self.auto_restart_advertising = auto_restart
|
||||
|
||||
async def stop_advertising(self) -> None:
|
||||
# Disable advertising
|
||||
@@ -1438,9 +1438,9 @@ class Device(CompositeEventEmitter):
|
||||
check_result=True,
|
||||
)
|
||||
|
||||
self.advertising_type = None
|
||||
self.advertising_own_address_type = None
|
||||
self.advertising = False
|
||||
self.advertising_type = None
|
||||
self.auto_restart_advertising = False
|
||||
|
||||
@property
|
||||
@@ -2630,7 +2630,6 @@ class Device(CompositeEventEmitter):
|
||||
own_address_type = self.advertising_own_address_type
|
||||
|
||||
# We are no longer advertising
|
||||
self.advertising_own_address_type = None
|
||||
self.advertising = False
|
||||
|
||||
if own_address_type in (
|
||||
@@ -2687,7 +2686,6 @@ class Device(CompositeEventEmitter):
|
||||
and self.advertising
|
||||
and self.advertising_type.is_directed
|
||||
):
|
||||
self.advertising_own_address_type = None
|
||||
self.advertising = False
|
||||
|
||||
# Notify listeners
|
||||
|
||||
@@ -33,7 +33,7 @@ from typing import (
|
||||
Union,
|
||||
overload,
|
||||
)
|
||||
from functools import wraps
|
||||
from functools import wraps, partial
|
||||
from pyee import EventEmitter
|
||||
|
||||
from .colors import color
|
||||
@@ -410,3 +410,20 @@ class FlowControlAsyncPipe:
|
||||
self.resume_source()
|
||||
|
||||
self.check_pump()
|
||||
|
||||
|
||||
async def async_call(function, *args, **kwargs):
|
||||
"""
|
||||
Immediately calls the function with provided args and kwargs, wrapping it in an async function.
|
||||
Rust's `pyo3_asyncio` library needs functions to be marked async to properly inject a running loop.
|
||||
|
||||
result = await async_call(some_function, ...)
|
||||
"""
|
||||
return function(*args, **kwargs)
|
||||
|
||||
|
||||
def wrap_async(function):
|
||||
"""
|
||||
Wraps the provided function in an async function.
|
||||
"""
|
||||
return partial(async_call, function)
|
||||
|
||||
@@ -67,6 +67,9 @@ nav:
|
||||
- Zephyr: platforms/zephyr.md
|
||||
- Examples:
|
||||
- Overview: examples/index.md
|
||||
- Extras:
|
||||
- Overview: extras/index.md
|
||||
- Android Remote HCI: extras/android_remote_hci.md
|
||||
|
||||
copyright: Copyright 2021-2023 Google LLC
|
||||
|
||||
|
||||
141
docs/mkdocs/src/extras/android_remote_hci.md
Normal file
@@ -0,0 +1,141 @@
|
||||
ANDROID REMOTE HCI APP
|
||||
======================
|
||||
|
||||
This application allows using an android phone's built-in Bluetooth controller with
|
||||
a Bumble host stack running outside the phone (typically a development laptop or desktop).
|
||||
The app runs an HCI proxy between a TCP socket on the "outside" and the Bluetooth HCI HAL
|
||||
on the "inside". (See [this page](https://source.android.com/docs/core/connect/bluetooth) for a high level
|
||||
description of the Android Bluetooth HCI HAL).
|
||||
The HCI packets received on the TCP socket are forwarded to the phone's controller, and the
|
||||
packets coming from the controller are forwarded to the TCP socket.
|
||||
|
||||
|
||||
Building
|
||||
--------
|
||||
|
||||
You can build the app by running `./gradlew build` (use `gradlew.bat` on Windows) from the `RemoteHCI` top level directory.
|
||||
You can also build with Android Studio: open the `RemoteHCI` project. You can build and/or debug from there.
|
||||
|
||||
If the build succeeds, you can find the app APKs (debug and release) at:
|
||||
|
||||
* [Release] ``app/build/outputs/apk/release/app-release-unsigned.apk``
|
||||
* [Debug] ``app/build/outputs/apk/debug/app-debug.apk``
|
||||
|
||||
|
||||
Running
|
||||
-------
|
||||
|
||||
### Preconditions
|
||||
When the proxy starts (tapping the "Start" button in the app's main activity), it will try to
|
||||
bind to the Bluetooth HAL. This requires disabling SELinux temporarily, and being the only HAL client.
|
||||
|
||||
#### Disabling SELinux
|
||||
Binding to the Bluetooth HCI HAL requires certain SELinux permissions that can't simply be changed
|
||||
on a device without rebuilding its system image. To bypass these restrictions, you will need
|
||||
to disable SELinux on your phone (please be aware that this is global, not just for the proxy app,
|
||||
so proceed with caution).
|
||||
In order to disable SELinux, you need to root the phone (it may be advisable to do this on a
|
||||
development phone).
|
||||
|
||||
!!! tip "Disabling SELinux Temporarily"
|
||||
Restart `adb` as root:
|
||||
```bash
|
||||
$ adb root
|
||||
```
|
||||
|
||||
Then disable SELinux
|
||||
```bash
|
||||
$ adb shell setenforce 0
|
||||
```
|
||||
|
||||
Once you're done using the proxy, you can restore SELinux, if you need to, with
|
||||
```bash
|
||||
$ adb shell setenforce 1
|
||||
```
|
||||
|
||||
This state will also reset to the normal SELinux enforcement when you reboot.
|
||||
|
||||
#### Stopping the bluetooth process
|
||||
Since the Bluetooth HAL service can only accept one client, and that in normal conditions
|
||||
that client is the Android's bluetooth stack, it is required to first shut down the
|
||||
Android bluetooth stack process.
|
||||
|
||||
!!! tip "Checking if the Bluetooth process is running"
|
||||
```bash
|
||||
$ adb shell "ps -A | grep com.google.android.bluetooth"
|
||||
```
|
||||
If the process is running, you will get a line like:
|
||||
```
|
||||
bluetooth 10759 876 17455796 136620 do_epoll_wait 0 S com.google.android.bluetooth
|
||||
```
|
||||
If you don't, it means that the process is not running and you are clear to proceed.
|
||||
|
||||
Simply turning Bluetooth off from the phone's settings does not ensure that the bluetooth process will exit.
|
||||
If the bluetooth process is still running after toggling Bluetooth off from the settings, you may try enabling
|
||||
Airplane Mode, then rebooting. The bluetooth process should, in theory, not restart after the reboot.
|
||||
|
||||
!!! tip "Stopping the bluetooth process with adb"
|
||||
```bash
|
||||
$ adb shell cmd bluetooth_manager disable
|
||||
```
|
||||
|
||||
### Starting the app
|
||||
You can start the app from the Android launcher, from Android Studio, or with `adb`
|
||||
|
||||
#### Launching from the launcher
|
||||
Just tap the app icon on the launcher, check the TCP port that is configured, and tap
|
||||
the "Start" button.
|
||||
|
||||
#### Launching with `adb`
|
||||
Using the `am` command, you can start the activity, and pass it arguments so that you can
|
||||
automatically start the proxy, and/or set the port number.
|
||||
|
||||
!!! tip "Launching from adb with auto-start"
|
||||
```bash
|
||||
$ adb shell am start -n com.github.google.bumble.remotehci/.MainActivity --ez autostart true
|
||||
```
|
||||
|
||||
!!! tip "Launching from adb with auto-start and a port"
|
||||
In this example, we auto-start the proxy upon launch, with the port set to 9995
|
||||
```bash
|
||||
$ adb shell am start -n com.github.google.bumble.remotehci/.MainActivity --ez autostart true --ei port 9995
|
||||
```
|
||||
|
||||
#### Selecting a TCP port
|
||||
The RemoteHCI app's main activity has a "TCP Port" setting where you can change the port on
|
||||
which the proxy is accepting connections. If the default value isn't suitable, you can
|
||||
change it there (you can also use the special value 0 to let the OS assign a port number for you).
|
||||
|
||||
### Connecting to the proxy
|
||||
To connect the Bumble stack to the proxy, you need to be able to reach the phone's network
|
||||
stack. This can be done over the phone's WiFi connection, or, alternatively, using an `adb`
|
||||
TCP forward (which should be faster than over WiFi).
|
||||
|
||||
!!! tip "Forwarding TCP with `adb`"
|
||||
To connect to the proxy via an `adb` TCP forward, use:
|
||||
```bash
|
||||
$ adb forward tcp:<outside-port> tcp:<inside-port>
|
||||
```
|
||||
Where ``<outside-port>`` is the port number for a listening socket on your laptop or
|
||||
desktop machine, and <inside-port> is the TCP port selected in the app's user interface.
|
||||
Those two ports may be the same, of course.
|
||||
For example, with the default TCP port 9993:
|
||||
```bash
|
||||
$ adb forward tcp:9993 tcp:9993
|
||||
```
|
||||
|
||||
Once you've ensured that you can reach the proxy's TCP port on the phone, either directly or
|
||||
via an `adb` forward, you can then use it as a Bumble transport, using the transport name:
|
||||
``tcp-client:<host>:<port>`` syntax.
|
||||
|
||||
!!! example "Connecting a Bumble client"
|
||||
Connecting the `bumble-controller-info` app to the phone's controller.
|
||||
Assuming you have set up an `adb` forward on port 9993:
|
||||
```bash
|
||||
$ bumble-controller-info tcp-client:localhost:9993
|
||||
```
|
||||
|
||||
Or over WiFi with, in this example, the IP address of the phone being ```192.168.86.27```
|
||||
```bash
|
||||
$ bumble-controller-info tcp-client:192.168.86.27:9993
|
||||
```
|
||||
11
docs/mkdocs/src/extras/index.md
Normal file
@@ -0,0 +1,11 @@
|
||||
EXTRAS
|
||||
======
|
||||
|
||||
A collection of add-ons, apps and tools, to the Bumble project.
|
||||
|
||||
Android Remote HCI
|
||||
------------------
|
||||
|
||||
Allows using an Android phone's built-in Bluetooth controller with a Bumble
|
||||
stack running on a development machine.
|
||||
See [Android Remote HCI](android_remote_hci.md) for details.
|
||||
@@ -3,7 +3,7 @@ HARDWARE
|
||||
|
||||
The Bumble Host connects to a controller over an [HCI Transport](../transports/index.md).
|
||||
To use a hardware controller attached to the host on which the host application is running, the transport is typically either [HCI over UART](../transports/serial.md) or [HCI over USB](../transports/usb.md).
|
||||
On Linux, the [VHCI Transport](../transports/vhci.md) can be used to communicate with any controller hardware managed by the operating system. Alternatively, a remote controller (a phyiscal controller attached to a remote host) can be used by connecting one of the networked transports (such as the [TCP Client transport](../transports/tcp_client.md), the [TCP Server transport](../transports/tcp_server.md) or the [UDP Transport](../transports/udp.md)) to an [HCI Bridge](../apps_and_tools/hci_bridge) bridging the network transport to a physical controller on a remote host.
|
||||
On Linux, the [VHCI Transport](../transports/vhci.md) can be used to communicate with any controller hardware managed by the operating system. Alternatively, a remote controller (a phyiscal controller attached to a remote host) can be used by connecting one of the networked transports (such as the [TCP Client transport](../transports/tcp_client.md), the [TCP Server transport](../transports/tcp_server.md) or the [UDP Transport](../transports/udp.md)) to an [HCI Bridge](../apps_and_tools/hci_bridge.md) bridging the network transport to a physical controller on a remote host.
|
||||
|
||||
In theory, any controller that is compliant with the HCI over UART or HCI over USB protocols can be used.
|
||||
|
||||
|
||||
10
extras/android/RemoteHCI/.gitignore
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
.cxx
|
||||
local.properties
|
||||
1
extras/android/RemoteHCI/app/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
||||
73
extras/android/RemoteHCI/app/build.gradle.kts
Normal file
@@ -0,0 +1,73 @@
|
||||
@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed
|
||||
plugins {
|
||||
alias(libs.plugins.androidApplication)
|
||||
alias(libs.plugins.kotlinAndroid)
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "com.github.google.bumble.remotehci"
|
||||
compileSdk = 33
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "com.github.google.bumble.remotehci"
|
||||
minSdk = 26
|
||||
targetSdk = 33
|
||||
versionCode = 1
|
||||
versionName = "1.0"
|
||||
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
vectorDrawables {
|
||||
useSupportLibrary = true
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
isMinifyEnabled = false
|
||||
proguardFiles(
|
||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||
"proguard-rules.pro"
|
||||
)
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
buildFeatures {
|
||||
compose = true
|
||||
aidl = false
|
||||
}
|
||||
composeOptions {
|
||||
kotlinCompilerExtensionVersion = "1.4.3"
|
||||
}
|
||||
packaging {
|
||||
resources {
|
||||
excludes += "/META-INF/{AL2.0,LGPL2.1}"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(kotlin("reflect"))
|
||||
implementation(libs.core.ktx)
|
||||
implementation(libs.lifecycle.runtime.ktx)
|
||||
implementation(libs.activity.compose)
|
||||
implementation(platform(libs.compose.bom))
|
||||
implementation(libs.ui)
|
||||
implementation(libs.ui.graphics)
|
||||
implementation(libs.ui.tooling.preview)
|
||||
implementation(libs.material3)
|
||||
compileOnly(project(":lib"))
|
||||
testImplementation(libs.junit)
|
||||
androidTestImplementation(libs.androidx.test.ext.junit)
|
||||
androidTestImplementation(libs.espresso.core)
|
||||
androidTestImplementation(platform(libs.compose.bom))
|
||||
androidTestImplementation(libs.ui.test.junit4)
|
||||
debugImplementation(libs.ui.tooling)
|
||||
debugImplementation(libs.ui.test.manifest)
|
||||
//compileOnly(files("${project.rootDir.absolutePath}/sdk/framework.jar"))
|
||||
}
|
||||
21
extras/android/RemoteHCI/app/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
29
extras/android/RemoteHCI/app/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.RemoteHCI"
|
||||
tools:targetApi="31">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/Theme.RemoteHCI">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL file. Do not edit it manually. There are
|
||||
// two cases:
|
||||
// 1). this is a frozen version file - do not edit this in any case.
|
||||
// 2). this is a 'current' file. If you make a backwards compatible change to
|
||||
// the interface (from the latest frozen version), the build system will
|
||||
// prompt you to update this file with `m <name>-update-api`.
|
||||
//
|
||||
// You must not make a backward incompatible change to any AIDL file built
|
||||
// with the aidl_interface module type with versions property set. The module
|
||||
// type is used to build AIDL files in a way that they can be used across
|
||||
// independently updatable components of the system. If a device is shipped
|
||||
// with such a backward incompatible change, it has a high risk of breaking
|
||||
// later when a module using the interface is updated, e.g., Mainline modules.
|
||||
|
||||
package android.hardware.bluetooth;
|
||||
@VintfStability
|
||||
interface IBluetoothHci {
|
||||
void close();
|
||||
void initialize(in android.hardware.bluetooth.IBluetoothHciCallbacks callback);
|
||||
void sendAclData(in byte[] data);
|
||||
void sendHciCommand(in byte[] command);
|
||||
void sendIsoData(in byte[] data);
|
||||
void sendScoData(in byte[] data);
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL file. Do not edit it manually. There are
|
||||
// two cases:
|
||||
// 1). this is a frozen version file - do not edit this in any case.
|
||||
// 2). this is a 'current' file. If you make a backwards compatible change to
|
||||
// the interface (from the latest frozen version), the build system will
|
||||
// prompt you to update this file with `m <name>-update-api`.
|
||||
//
|
||||
// You must not make a backward incompatible change to any AIDL file built
|
||||
// with the aidl_interface module type with versions property set. The module
|
||||
// type is used to build AIDL files in a way that they can be used across
|
||||
// independently updatable components of the system. If a device is shipped
|
||||
// with such a backward incompatible change, it has a high risk of breaking
|
||||
// later when a module using the interface is updated, e.g., Mainline modules.
|
||||
|
||||
package android.hardware.bluetooth;
|
||||
@VintfStability
|
||||
interface IBluetoothHciCallbacks {
|
||||
void aclDataReceived(in byte[] data);
|
||||
void hciEventReceived(in byte[] event);
|
||||
void initializationComplete(in android.hardware.bluetooth.Status status);
|
||||
void isoDataReceived(in byte[] data);
|
||||
void scoDataReceived(in byte[] data);
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL file. Do not edit it manually. There are
|
||||
// two cases:
|
||||
// 1). this is a frozen version file - do not edit this in any case.
|
||||
// 2). this is a 'current' file. If you make a backwards compatible change to
|
||||
// the interface (from the latest frozen version), the build system will
|
||||
// prompt you to update this file with `m <name>-update-api`.
|
||||
//
|
||||
// You must not make a backward incompatible change to any AIDL file built
|
||||
// with the aidl_interface module type with versions property set. The module
|
||||
// type is used to build AIDL files in a way that they can be used across
|
||||
// independently updatable components of the system. If a device is shipped
|
||||
// with such a backward incompatible change, it has a high risk of breaking
|
||||
// later when a module using the interface is updated, e.g., Mainline modules.
|
||||
|
||||
package android.hardware.bluetooth;
|
||||
@Backing(type="int")
|
||||
@VintfStability
|
||||
enum Status {
|
||||
SUCCESS = 0,
|
||||
ALREADY_INITIALIZED = 1,
|
||||
UNABLE_TO_OPEN_INTERFACE = 2,
|
||||
HARDWARE_INITIALIZATION_ERROR = 3,
|
||||
UNKNOWN = 4,
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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.
|
||||
*/
|
||||
|
||||
package android.hardware.bluetooth@1.1;
|
||||
|
||||
import @1.0::HciPacket;
|
||||
import @1.0::IBluetoothHci;
|
||||
import IBluetoothHciCallbacks;
|
||||
|
||||
/**
|
||||
* The Host Controller Interface (HCI) is the layer defined by the Bluetooth
|
||||
* specification between the software that runs on the host and the Bluetooth
|
||||
* controller chip. This boundary is the natural choice for a Hardware
|
||||
* Abstraction Layer (HAL). Dealing only in HCI packets and events simplifies
|
||||
* the stack and abstracts away power management, initialization, and other
|
||||
* implementation-specific details related to the hardware.
|
||||
*/
|
||||
interface IBluetoothHci extends @1.0::IBluetoothHci {
|
||||
/**
|
||||
* Same as @1.0, but uses 1.1 Callbacks version
|
||||
*/
|
||||
initialize_1_1(@1.1::IBluetoothHciCallbacks callback);
|
||||
|
||||
/**
|
||||
* Send an ISO data packet (as specified in the Bluetooth Core
|
||||
* Specification v5.2) to the Bluetooth controller.
|
||||
* Packets must be processed in order.
|
||||
* @param data HCI data packet to be sent
|
||||
*/
|
||||
sendIsoData(HciPacket data);
|
||||
};
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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.
|
||||
*/
|
||||
|
||||
package android.hardware.bluetooth@1.1;
|
||||
|
||||
import @1.0::HciPacket;
|
||||
import @1.0::IBluetoothHciCallbacks;
|
||||
|
||||
/**
|
||||
* The interface from the Bluetooth Controller to the stack.
|
||||
*/
|
||||
interface IBluetoothHciCallbacks extends @1.0::IBluetoothHciCallbacks {
|
||||
/**
|
||||
* Send a ISO data packet form the controller to the host.
|
||||
* @param data the ISO HCI packet to be passed to the host stack
|
||||
*/
|
||||
isoDataReceived(HciPacket data);
|
||||
};
|
||||
BIN
extras/android/RemoteHCI/app/src/main/ic_launcher-playstore.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
@@ -0,0 +1,259 @@
|
||||
/*
|
||||
* This file is auto-generated. DO NOT MODIFY.
|
||||
*/
|
||||
package android.hardware.bluetooth;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public interface IBluetoothHci extends android.os.IInterface
|
||||
{
|
||||
/** Default implementation for IBluetoothHci. */
|
||||
public static class Default implements android.hardware.bluetooth.IBluetoothHci
|
||||
{
|
||||
@Override public void close() throws android.os.RemoteException
|
||||
{
|
||||
}
|
||||
@Override public void initialize(android.hardware.bluetooth.IBluetoothHciCallbacks callback) throws android.os.RemoteException
|
||||
{
|
||||
}
|
||||
@Override public void sendAclData(byte[] data) throws android.os.RemoteException
|
||||
{
|
||||
}
|
||||
@Override public void sendHciCommand(byte[] command) throws android.os.RemoteException
|
||||
{
|
||||
}
|
||||
@Override public void sendIsoData(byte[] data) throws android.os.RemoteException
|
||||
{
|
||||
}
|
||||
@Override public void sendScoData(byte[] data) throws android.os.RemoteException
|
||||
{
|
||||
}
|
||||
@Override
|
||||
public android.os.IBinder asBinder() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
/** Local-side IPC implementation stub class. */
|
||||
public static abstract class Stub extends android.os.Binder implements android.hardware.bluetooth.IBluetoothHci
|
||||
{
|
||||
/** Construct the stub at attach it to the interface. */
|
||||
public Stub()
|
||||
{
|
||||
//this.markVintfStability();
|
||||
try {
|
||||
Method method = this.getClass().getMethod("markVintfStability", (Class<?>[])null);
|
||||
method.invoke(this);
|
||||
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
this.attachInterface(this, DESCRIPTOR);
|
||||
}
|
||||
/**
|
||||
* Cast an IBinder object into an android.hardware.bluetooth.IBluetoothHci interface,
|
||||
* generating a proxy if needed.
|
||||
*/
|
||||
public static android.hardware.bluetooth.IBluetoothHci asInterface(android.os.IBinder obj)
|
||||
{
|
||||
if ((obj==null)) {
|
||||
return null;
|
||||
}
|
||||
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
|
||||
if (((iin!=null)&&(iin instanceof android.hardware.bluetooth.IBluetoothHci))) {
|
||||
return ((android.hardware.bluetooth.IBluetoothHci)iin);
|
||||
}
|
||||
return new android.hardware.bluetooth.IBluetoothHci.Stub.Proxy(obj);
|
||||
}
|
||||
@Override public android.os.IBinder asBinder()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
|
||||
{
|
||||
java.lang.String descriptor = DESCRIPTOR;
|
||||
if (code >= android.os.IBinder.FIRST_CALL_TRANSACTION && code <= android.os.IBinder.LAST_CALL_TRANSACTION) {
|
||||
data.enforceInterface(descriptor);
|
||||
}
|
||||
switch (code)
|
||||
{
|
||||
case INTERFACE_TRANSACTION:
|
||||
{
|
||||
reply.writeString(descriptor);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
switch (code)
|
||||
{
|
||||
case TRANSACTION_close:
|
||||
{
|
||||
this.close();
|
||||
reply.writeNoException();
|
||||
break;
|
||||
}
|
||||
case TRANSACTION_initialize:
|
||||
{
|
||||
android.hardware.bluetooth.IBluetoothHciCallbacks _arg0;
|
||||
_arg0 = android.hardware.bluetooth.IBluetoothHciCallbacks.Stub.asInterface(data.readStrongBinder());
|
||||
this.initialize(_arg0);
|
||||
reply.writeNoException();
|
||||
break;
|
||||
}
|
||||
case TRANSACTION_sendAclData:
|
||||
{
|
||||
byte[] _arg0;
|
||||
_arg0 = data.createByteArray();
|
||||
this.sendAclData(_arg0);
|
||||
reply.writeNoException();
|
||||
break;
|
||||
}
|
||||
case TRANSACTION_sendHciCommand:
|
||||
{
|
||||
byte[] _arg0;
|
||||
_arg0 = data.createByteArray();
|
||||
this.sendHciCommand(_arg0);
|
||||
reply.writeNoException();
|
||||
break;
|
||||
}
|
||||
case TRANSACTION_sendIsoData:
|
||||
{
|
||||
byte[] _arg0;
|
||||
_arg0 = data.createByteArray();
|
||||
this.sendIsoData(_arg0);
|
||||
reply.writeNoException();
|
||||
break;
|
||||
}
|
||||
case TRANSACTION_sendScoData:
|
||||
{
|
||||
byte[] _arg0;
|
||||
_arg0 = data.createByteArray();
|
||||
this.sendScoData(_arg0);
|
||||
reply.writeNoException();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
return super.onTransact(code, data, reply, flags);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
private static class Proxy implements android.hardware.bluetooth.IBluetoothHci
|
||||
{
|
||||
private android.os.IBinder mRemote;
|
||||
Proxy(android.os.IBinder remote)
|
||||
{
|
||||
mRemote = remote;
|
||||
}
|
||||
@Override public android.os.IBinder asBinder()
|
||||
{
|
||||
return mRemote;
|
||||
}
|
||||
public java.lang.String getInterfaceDescriptor()
|
||||
{
|
||||
return DESCRIPTOR;
|
||||
}
|
||||
@Override public void close() throws android.os.RemoteException
|
||||
{
|
||||
android.os.Parcel _data = android.os.Parcel.obtain();
|
||||
android.os.Parcel _reply = android.os.Parcel.obtain();
|
||||
try {
|
||||
_data.writeInterfaceToken(DESCRIPTOR);
|
||||
boolean _status = mRemote.transact(Stub.TRANSACTION_close, _data, _reply, 0);
|
||||
_reply.readException();
|
||||
}
|
||||
finally {
|
||||
_reply.recycle();
|
||||
_data.recycle();
|
||||
}
|
||||
}
|
||||
@Override public void initialize(android.hardware.bluetooth.IBluetoothHciCallbacks callback) throws android.os.RemoteException
|
||||
{
|
||||
android.os.Parcel _data = android.os.Parcel.obtain();
|
||||
android.os.Parcel _reply = android.os.Parcel.obtain();
|
||||
try {
|
||||
_data.writeInterfaceToken(DESCRIPTOR);
|
||||
_data.writeStrongInterface(callback);
|
||||
boolean _status = mRemote.transact(Stub.TRANSACTION_initialize, _data, _reply, 0);
|
||||
_reply.readException();
|
||||
}
|
||||
finally {
|
||||
_reply.recycle();
|
||||
_data.recycle();
|
||||
}
|
||||
}
|
||||
@Override public void sendAclData(byte[] data) throws android.os.RemoteException
|
||||
{
|
||||
android.os.Parcel _data = android.os.Parcel.obtain();
|
||||
android.os.Parcel _reply = android.os.Parcel.obtain();
|
||||
try {
|
||||
_data.writeInterfaceToken(DESCRIPTOR);
|
||||
_data.writeByteArray(data);
|
||||
boolean _status = mRemote.transact(Stub.TRANSACTION_sendAclData, _data, _reply, 0);
|
||||
_reply.readException();
|
||||
}
|
||||
finally {
|
||||
_reply.recycle();
|
||||
_data.recycle();
|
||||
}
|
||||
}
|
||||
@Override public void sendHciCommand(byte[] command) throws android.os.RemoteException
|
||||
{
|
||||
android.os.Parcel _data = android.os.Parcel.obtain();
|
||||
android.os.Parcel _reply = android.os.Parcel.obtain();
|
||||
try {
|
||||
_data.writeInterfaceToken(DESCRIPTOR);
|
||||
_data.writeByteArray(command);
|
||||
boolean _status = mRemote.transact(Stub.TRANSACTION_sendHciCommand, _data, _reply, 0);
|
||||
_reply.readException();
|
||||
}
|
||||
finally {
|
||||
_reply.recycle();
|
||||
_data.recycle();
|
||||
}
|
||||
}
|
||||
@Override public void sendIsoData(byte[] data) throws android.os.RemoteException
|
||||
{
|
||||
android.os.Parcel _data = android.os.Parcel.obtain();
|
||||
android.os.Parcel _reply = android.os.Parcel.obtain();
|
||||
try {
|
||||
_data.writeInterfaceToken(DESCRIPTOR);
|
||||
_data.writeByteArray(data);
|
||||
boolean _status = mRemote.transact(Stub.TRANSACTION_sendIsoData, _data, _reply, 0);
|
||||
_reply.readException();
|
||||
}
|
||||
finally {
|
||||
_reply.recycle();
|
||||
_data.recycle();
|
||||
}
|
||||
}
|
||||
@Override public void sendScoData(byte[] data) throws android.os.RemoteException
|
||||
{
|
||||
android.os.Parcel _data = android.os.Parcel.obtain();
|
||||
android.os.Parcel _reply = android.os.Parcel.obtain();
|
||||
try {
|
||||
_data.writeInterfaceToken(DESCRIPTOR);
|
||||
_data.writeByteArray(data);
|
||||
boolean _status = mRemote.transact(Stub.TRANSACTION_sendScoData, _data, _reply, 0);
|
||||
_reply.readException();
|
||||
}
|
||||
finally {
|
||||
_reply.recycle();
|
||||
_data.recycle();
|
||||
}
|
||||
}
|
||||
}
|
||||
static final int TRANSACTION_close = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
|
||||
static final int TRANSACTION_initialize = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
|
||||
static final int TRANSACTION_sendAclData = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
|
||||
static final int TRANSACTION_sendHciCommand = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);
|
||||
static final int TRANSACTION_sendIsoData = (android.os.IBinder.FIRST_CALL_TRANSACTION + 4);
|
||||
static final int TRANSACTION_sendScoData = (android.os.IBinder.FIRST_CALL_TRANSACTION + 5);
|
||||
}
|
||||
public static final java.lang.String DESCRIPTOR = "android$hardware$bluetooth$IBluetoothHci".replace('$', '.');
|
||||
public void close() throws android.os.RemoteException;
|
||||
public void initialize(android.hardware.bluetooth.IBluetoothHciCallbacks callback) throws android.os.RemoteException;
|
||||
public void sendAclData(byte[] data) throws android.os.RemoteException;
|
||||
public void sendHciCommand(byte[] command) throws android.os.RemoteException;
|
||||
public void sendIsoData(byte[] data) throws android.os.RemoteException;
|
||||
public void sendScoData(byte[] data) throws android.os.RemoteException;
|
||||
}
|
||||
@@ -0,0 +1,234 @@
|
||||
/*
|
||||
* This file is auto-generated. DO NOT MODIFY.
|
||||
*/
|
||||
package android.hardware.bluetooth;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public interface IBluetoothHciCallbacks extends android.os.IInterface
|
||||
{
|
||||
/** Default implementation for IBluetoothHciCallbacks. */
|
||||
public static class Default implements android.hardware.bluetooth.IBluetoothHciCallbacks
|
||||
{
|
||||
@Override public void aclDataReceived(byte[] data) throws android.os.RemoteException
|
||||
{
|
||||
}
|
||||
@Override public void hciEventReceived(byte[] event) throws android.os.RemoteException
|
||||
{
|
||||
}
|
||||
@Override public void initializationComplete(int status) throws android.os.RemoteException
|
||||
{
|
||||
}
|
||||
@Override public void isoDataReceived(byte[] data) throws android.os.RemoteException
|
||||
{
|
||||
}
|
||||
@Override public void scoDataReceived(byte[] data) throws android.os.RemoteException
|
||||
{
|
||||
}
|
||||
@Override
|
||||
public android.os.IBinder asBinder() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
/** Local-side IPC implementation stub class. */
|
||||
public static abstract class Stub extends android.os.Binder implements android.hardware.bluetooth.IBluetoothHciCallbacks
|
||||
{
|
||||
/** Construct the stub at attach it to the interface. */
|
||||
public Stub()
|
||||
{
|
||||
//this.markVintfStability();
|
||||
try {
|
||||
Method method = this.getClass().getMethod("markVintfStability", (Class<?>[])null);
|
||||
method.invoke(this);
|
||||
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
this.attachInterface(this, DESCRIPTOR);
|
||||
}
|
||||
/**
|
||||
* Cast an IBinder object into an android.hardware.bluetooth.IBluetoothHciCallbacks interface,
|
||||
* generating a proxy if needed.
|
||||
*/
|
||||
public static android.hardware.bluetooth.IBluetoothHciCallbacks asInterface(android.os.IBinder obj)
|
||||
{
|
||||
if ((obj==null)) {
|
||||
return null;
|
||||
}
|
||||
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
|
||||
if (((iin!=null)&&(iin instanceof android.hardware.bluetooth.IBluetoothHciCallbacks))) {
|
||||
return ((android.hardware.bluetooth.IBluetoothHciCallbacks)iin);
|
||||
}
|
||||
return new android.hardware.bluetooth.IBluetoothHciCallbacks.Stub.Proxy(obj);
|
||||
}
|
||||
@Override public android.os.IBinder asBinder()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
|
||||
{
|
||||
java.lang.String descriptor = DESCRIPTOR;
|
||||
if (code >= android.os.IBinder.FIRST_CALL_TRANSACTION && code <= android.os.IBinder.LAST_CALL_TRANSACTION) {
|
||||
data.enforceInterface(descriptor);
|
||||
}
|
||||
switch (code)
|
||||
{
|
||||
case INTERFACE_TRANSACTION:
|
||||
{
|
||||
reply.writeString(descriptor);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
switch (code)
|
||||
{
|
||||
case TRANSACTION_aclDataReceived:
|
||||
{
|
||||
byte[] _arg0;
|
||||
_arg0 = data.createByteArray();
|
||||
this.aclDataReceived(_arg0);
|
||||
reply.writeNoException();
|
||||
break;
|
||||
}
|
||||
case TRANSACTION_hciEventReceived:
|
||||
{
|
||||
byte[] _arg0;
|
||||
_arg0 = data.createByteArray();
|
||||
this.hciEventReceived(_arg0);
|
||||
reply.writeNoException();
|
||||
break;
|
||||
}
|
||||
case TRANSACTION_initializationComplete:
|
||||
{
|
||||
int _arg0;
|
||||
_arg0 = data.readInt();
|
||||
this.initializationComplete(_arg0);
|
||||
reply.writeNoException();
|
||||
break;
|
||||
}
|
||||
case TRANSACTION_isoDataReceived:
|
||||
{
|
||||
byte[] _arg0;
|
||||
_arg0 = data.createByteArray();
|
||||
this.isoDataReceived(_arg0);
|
||||
reply.writeNoException();
|
||||
break;
|
||||
}
|
||||
case TRANSACTION_scoDataReceived:
|
||||
{
|
||||
byte[] _arg0;
|
||||
_arg0 = data.createByteArray();
|
||||
this.scoDataReceived(_arg0);
|
||||
reply.writeNoException();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
return super.onTransact(code, data, reply, flags);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
private static class Proxy implements android.hardware.bluetooth.IBluetoothHciCallbacks
|
||||
{
|
||||
private android.os.IBinder mRemote;
|
||||
Proxy(android.os.IBinder remote)
|
||||
{
|
||||
mRemote = remote;
|
||||
}
|
||||
@Override public android.os.IBinder asBinder()
|
||||
{
|
||||
return mRemote;
|
||||
}
|
||||
public java.lang.String getInterfaceDescriptor()
|
||||
{
|
||||
return DESCRIPTOR;
|
||||
}
|
||||
@Override public void aclDataReceived(byte[] data) throws android.os.RemoteException
|
||||
{
|
||||
android.os.Parcel _data = android.os.Parcel.obtain();
|
||||
android.os.Parcel _reply = android.os.Parcel.obtain();
|
||||
try {
|
||||
_data.writeInterfaceToken(DESCRIPTOR);
|
||||
_data.writeByteArray(data);
|
||||
boolean _status = mRemote.transact(Stub.TRANSACTION_aclDataReceived, _data, _reply, 0);
|
||||
_reply.readException();
|
||||
}
|
||||
finally {
|
||||
_reply.recycle();
|
||||
_data.recycle();
|
||||
}
|
||||
}
|
||||
@Override public void hciEventReceived(byte[] event) throws android.os.RemoteException
|
||||
{
|
||||
android.os.Parcel _data = android.os.Parcel.obtain();
|
||||
android.os.Parcel _reply = android.os.Parcel.obtain();
|
||||
try {
|
||||
_data.writeInterfaceToken(DESCRIPTOR);
|
||||
_data.writeByteArray(event);
|
||||
boolean _status = mRemote.transact(Stub.TRANSACTION_hciEventReceived, _data, _reply, 0);
|
||||
_reply.readException();
|
||||
}
|
||||
finally {
|
||||
_reply.recycle();
|
||||
_data.recycle();
|
||||
}
|
||||
}
|
||||
@Override public void initializationComplete(int status) throws android.os.RemoteException
|
||||
{
|
||||
android.os.Parcel _data = android.os.Parcel.obtain();
|
||||
android.os.Parcel _reply = android.os.Parcel.obtain();
|
||||
try {
|
||||
_data.writeInterfaceToken(DESCRIPTOR);
|
||||
_data.writeInt(status);
|
||||
boolean _status = mRemote.transact(Stub.TRANSACTION_initializationComplete, _data, _reply, 0);
|
||||
_reply.readException();
|
||||
}
|
||||
finally {
|
||||
_reply.recycle();
|
||||
_data.recycle();
|
||||
}
|
||||
}
|
||||
@Override public void isoDataReceived(byte[] data) throws android.os.RemoteException
|
||||
{
|
||||
android.os.Parcel _data = android.os.Parcel.obtain();
|
||||
android.os.Parcel _reply = android.os.Parcel.obtain();
|
||||
try {
|
||||
_data.writeInterfaceToken(DESCRIPTOR);
|
||||
_data.writeByteArray(data);
|
||||
boolean _status = mRemote.transact(Stub.TRANSACTION_isoDataReceived, _data, _reply, 0);
|
||||
_reply.readException();
|
||||
}
|
||||
finally {
|
||||
_reply.recycle();
|
||||
_data.recycle();
|
||||
}
|
||||
}
|
||||
@Override public void scoDataReceived(byte[] data) throws android.os.RemoteException
|
||||
{
|
||||
android.os.Parcel _data = android.os.Parcel.obtain();
|
||||
android.os.Parcel _reply = android.os.Parcel.obtain();
|
||||
try {
|
||||
_data.writeInterfaceToken(DESCRIPTOR);
|
||||
_data.writeByteArray(data);
|
||||
boolean _status = mRemote.transact(Stub.TRANSACTION_scoDataReceived, _data, _reply, 0);
|
||||
_reply.readException();
|
||||
}
|
||||
finally {
|
||||
_reply.recycle();
|
||||
_data.recycle();
|
||||
}
|
||||
}
|
||||
}
|
||||
static final int TRANSACTION_aclDataReceived = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
|
||||
static final int TRANSACTION_hciEventReceived = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
|
||||
static final int TRANSACTION_initializationComplete = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
|
||||
static final int TRANSACTION_isoDataReceived = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);
|
||||
static final int TRANSACTION_scoDataReceived = (android.os.IBinder.FIRST_CALL_TRANSACTION + 4);
|
||||
}
|
||||
public static final java.lang.String DESCRIPTOR = "android$hardware$bluetooth$IBluetoothHciCallbacks".replace('$', '.');
|
||||
public void aclDataReceived(byte[] data) throws android.os.RemoteException;
|
||||
public void hciEventReceived(byte[] event) throws android.os.RemoteException;
|
||||
public void initializationComplete(int status) throws android.os.RemoteException;
|
||||
public void isoDataReceived(byte[] data) throws android.os.RemoteException;
|
||||
public void scoDataReceived(byte[] data) throws android.os.RemoteException;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* This file is auto-generated. DO NOT MODIFY.
|
||||
*/
|
||||
package android.hardware.bluetooth;
|
||||
public @interface Status {
|
||||
public static final int SUCCESS = 0;
|
||||
public static final int ALREADY_INITIALIZED = 1;
|
||||
public static final int UNABLE_TO_OPEN_INTERFACE = 2;
|
||||
public static final int HARDWARE_INITIALIZATION_ERROR = 3;
|
||||
public static final int UNKNOWN = 4;
|
||||
}
|
||||
@@ -0,0 +1,816 @@
|
||||
package android.hardware.bluetooth.V1_0;
|
||||
|
||||
import android.os.HidlSupport;
|
||||
import android.os.HwBinder;
|
||||
import android.os.IHwBinder;
|
||||
import android.os.HwBlob;
|
||||
import android.os.HwParcel;
|
||||
import android.os.IHwInterface;
|
||||
import android.os.NativeHandle;
|
||||
|
||||
/**
|
||||
* The Host Controller Interface (HCI) is the layer defined by the Bluetooth
|
||||
* specification between the software that runs on the host and the Bluetooth
|
||||
* controller chip. This boundary is the natural choice for a Hardware
|
||||
* Abstraction Layer (HAL). Dealing only in HCI packets and events simplifies
|
||||
* the stack and abstracts away power management, initialization, and other
|
||||
* implementation-specific details related to the hardware.
|
||||
*/
|
||||
public interface IBluetoothHci extends android.internal.hidl.base.V1_0.IBase {
|
||||
/**
|
||||
* Fully-qualified interface name for this interface.
|
||||
*/
|
||||
public static final String kInterfaceName = "android.hardware.bluetooth@1.0::IBluetoothHci";
|
||||
|
||||
/**
|
||||
* Does a checked conversion from a binder to this class.
|
||||
*/
|
||||
/* package private */ static IBluetoothHci asInterface(IHwBinder binder) {
|
||||
if (binder == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
IHwInterface iface =
|
||||
binder.queryLocalInterface(kInterfaceName);
|
||||
|
||||
if ((iface != null) && (iface instanceof IBluetoothHci)) {
|
||||
return (IBluetoothHci)iface;
|
||||
}
|
||||
|
||||
IBluetoothHci proxy = new IBluetoothHci.Proxy(binder);
|
||||
|
||||
try {
|
||||
for (String descriptor : proxy.interfaceChain()) {
|
||||
if (descriptor.equals(kInterfaceName)) {
|
||||
return proxy;
|
||||
}
|
||||
}
|
||||
} catch (android.os.RemoteException e) {
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does a checked conversion from any interface to this class.
|
||||
*/
|
||||
public static IBluetoothHci castFrom(IHwInterface iface) {
|
||||
return (iface == null) ? null : IBluetoothHci.asInterface(iface.asBinder());
|
||||
}
|
||||
|
||||
@Override
|
||||
public IHwBinder asBinder();
|
||||
|
||||
/**
|
||||
* This will invoke the equivalent of the C++ getService(std::string) if retry is
|
||||
* true or tryGetService(std::string) if retry is false. If the service is
|
||||
* available on the device and retry is true, this will wait for the service to
|
||||
* start.
|
||||
*
|
||||
*/
|
||||
public static IBluetoothHci getService(String serviceName, boolean retry) throws android.os.RemoteException {
|
||||
return IBluetoothHci.asInterface(HwBinder.getService("android.hardware.bluetooth@1.0::IBluetoothHci", serviceName, retry));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls getService("default",retry).
|
||||
*/
|
||||
public static IBluetoothHci getService(boolean retry) throws android.os.RemoteException {
|
||||
return getService("default", retry);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated this will not wait for the interface to come up if it hasn't yet
|
||||
* started. See getService(String,boolean) instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public static IBluetoothHci getService(String serviceName) throws android.os.RemoteException {
|
||||
return IBluetoothHci.asInterface(HwBinder.getService("android.hardware.bluetooth@1.0::IBluetoothHci", serviceName));
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated this will not wait for the interface to come up if it hasn't yet
|
||||
* started. See getService(boolean) instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public static IBluetoothHci getService() throws android.os.RemoteException {
|
||||
return getService("default");
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the underlying HCI interface.
|
||||
*
|
||||
* This method should be used to initialize any hardware interfaces
|
||||
* required to communicate with the Bluetooth hardware in the
|
||||
* device.
|
||||
*
|
||||
* The |oninitializationComplete| callback must be invoked in response
|
||||
* to this function to indicate success before any other function
|
||||
* (sendHciCommand, sendAclData, * sendScoData) is invoked on this
|
||||
* interface.
|
||||
*
|
||||
* @param callback implements IBluetoothHciCallbacks which will
|
||||
* receive callbacks when incoming HCI packets are received
|
||||
* from the controller to be sent to the host.
|
||||
*/
|
||||
void initialize(android.hardware.bluetooth.V1_0.IBluetoothHciCallbacks callback)
|
||||
throws android.os.RemoteException;
|
||||
/**
|
||||
* Send an HCI command (as specified in the Bluetooth Specification
|
||||
* V4.2, Vol 2, Part 5, Section 5.4.1) to the Bluetooth controller.
|
||||
* Commands must be executed in order.
|
||||
*
|
||||
* @param command is the HCI command to be sent
|
||||
*/
|
||||
void sendHciCommand(java.util.ArrayList<Byte> command)
|
||||
throws android.os.RemoteException;
|
||||
/**
|
||||
* Send an HCI ACL data packet (as specified in the Bluetooth Specification
|
||||
* V4.2, Vol 2, Part 5, Section 5.4.2) to the Bluetooth controller.
|
||||
* Packets must be processed in order.
|
||||
* @param data HCI data packet to be sent
|
||||
*/
|
||||
void sendAclData(java.util.ArrayList<Byte> data)
|
||||
throws android.os.RemoteException;
|
||||
/**
|
||||
* Send an SCO data packet (as specified in the Bluetooth Specification
|
||||
* V4.2, Vol 2, Part 5, Section 5.4.3) to the Bluetooth controller.
|
||||
* Packets must be processed in order.
|
||||
* @param data HCI data packet to be sent
|
||||
*/
|
||||
void sendScoData(java.util.ArrayList<Byte> data)
|
||||
throws android.os.RemoteException;
|
||||
/**
|
||||
* Close the HCI interface
|
||||
*/
|
||||
void close()
|
||||
throws android.os.RemoteException;
|
||||
/*
|
||||
* Provides run-time type information for this object.
|
||||
* For example, for the following interface definition:
|
||||
* package android.hardware.foo@1.0;
|
||||
* interface IParent {};
|
||||
* interface IChild extends IParent {};
|
||||
* Calling interfaceChain on an IChild object must yield the following:
|
||||
* ["android.hardware.foo@1.0::IChild",
|
||||
* "android.hardware.foo@1.0::IParent"
|
||||
* "android.internal.hidl.base@1.0::IBase"]
|
||||
*
|
||||
* @return descriptors a vector of descriptors of the run-time type of the
|
||||
* object.
|
||||
*/
|
||||
java.util.ArrayList<String> interfaceChain()
|
||||
throws android.os.RemoteException;
|
||||
/*
|
||||
* Emit diagnostic information to the given file.
|
||||
*
|
||||
* Optionally overriden.
|
||||
*
|
||||
* @param fd File descriptor to dump data to.
|
||||
* Must only be used for the duration of this call.
|
||||
* @param options Arguments for debugging.
|
||||
* Must support empty for default debug information.
|
||||
*/
|
||||
void debug(NativeHandle fd, java.util.ArrayList<String> options)
|
||||
throws android.os.RemoteException;
|
||||
/*
|
||||
* Provides run-time type information for this object.
|
||||
* For example, for the following interface definition:
|
||||
* package android.hardware.foo@1.0;
|
||||
* interface IParent {};
|
||||
* interface IChild extends IParent {};
|
||||
* Calling interfaceDescriptor on an IChild object must yield
|
||||
* "android.hardware.foo@1.0::IChild"
|
||||
*
|
||||
* @return descriptor a descriptor of the run-time type of the
|
||||
* object (the first element of the vector returned by
|
||||
* interfaceChain())
|
||||
*/
|
||||
String interfaceDescriptor()
|
||||
throws android.os.RemoteException;
|
||||
/*
|
||||
* Returns hashes of the source HAL files that define the interfaces of the
|
||||
* runtime type information on the object.
|
||||
* For example, for the following interface definition:
|
||||
* package android.hardware.foo@1.0;
|
||||
* interface IParent {};
|
||||
* interface IChild extends IParent {};
|
||||
* Calling interfaceChain on an IChild object must yield the following:
|
||||
* [(hash of IChild.hal),
|
||||
* (hash of IParent.hal)
|
||||
* (hash of IBase.hal)].
|
||||
*
|
||||
* SHA-256 is used as the hashing algorithm. Each hash has 32 bytes
|
||||
* according to SHA-256 standard.
|
||||
*
|
||||
* @return hashchain a vector of SHA-1 digests
|
||||
*/
|
||||
java.util.ArrayList<byte[/* 32 */]> getHashChain()
|
||||
throws android.os.RemoteException;
|
||||
/*
|
||||
* This method trigger the interface to enable/disable instrumentation based
|
||||
* on system property hal.instrumentation.enable.
|
||||
*/
|
||||
void setHALInstrumentation()
|
||||
throws android.os.RemoteException;
|
||||
/*
|
||||
* Registers a death recipient, to be called when the process hosting this
|
||||
* interface dies.
|
||||
*
|
||||
* @param recipient a hidl_death_recipient callback object
|
||||
* @param cookie a cookie that must be returned with the callback
|
||||
* @return success whether the death recipient was registered successfully.
|
||||
*/
|
||||
boolean linkToDeath(IHwBinder.DeathRecipient recipient, long cookie)
|
||||
throws android.os.RemoteException;
|
||||
/*
|
||||
* Provides way to determine if interface is running without requesting
|
||||
* any functionality.
|
||||
*/
|
||||
void ping()
|
||||
throws android.os.RemoteException;
|
||||
/*
|
||||
* Get debug information on references on this interface.
|
||||
* @return info debugging information. See comments of DebugInfo.
|
||||
*/
|
||||
android.internal.hidl.base.V1_0.DebugInfo getDebugInfo()
|
||||
throws android.os.RemoteException;
|
||||
/*
|
||||
* This method notifies the interface that one or more system properties
|
||||
* have changed. The default implementation calls
|
||||
* (C++) report_sysprop_change() in libcutils or
|
||||
* (Java) android.os.SystemProperties.reportSyspropChanged,
|
||||
* which in turn calls a set of registered callbacks (eg to update trace
|
||||
* tags).
|
||||
*/
|
||||
void notifySyspropsChanged()
|
||||
throws android.os.RemoteException;
|
||||
/*
|
||||
* Unregisters the registered death recipient. If this service was registered
|
||||
* multiple times with the same exact death recipient, this unlinks the most
|
||||
* recently registered one.
|
||||
*
|
||||
* @param recipient a previously registered hidl_death_recipient callback
|
||||
* @return success whether the death recipient was unregistered successfully.
|
||||
*/
|
||||
boolean unlinkToDeath(IHwBinder.DeathRecipient recipient)
|
||||
throws android.os.RemoteException;
|
||||
|
||||
public static final class Proxy implements IBluetoothHci {
|
||||
private IHwBinder mRemote;
|
||||
|
||||
public Proxy(IHwBinder remote) {
|
||||
mRemote = java.util.Objects.requireNonNull(remote);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IHwBinder asBinder() {
|
||||
return mRemote;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
try {
|
||||
return this.interfaceDescriptor() + "@Proxy";
|
||||
} catch (android.os.RemoteException ex) {
|
||||
/* ignored; handled below. */
|
||||
}
|
||||
return "[class or subclass of " + IBluetoothHci.kInterfaceName + "]@Proxy";
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean equals(java.lang.Object other) {
|
||||
return HidlSupport.interfacesEqual(this, other);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
return this.asBinder().hashCode();
|
||||
}
|
||||
|
||||
// Methods from ::android::hardware::bluetooth::V1_0::IBluetoothHci follow.
|
||||
@Override
|
||||
public void initialize(android.hardware.bluetooth.V1_0.IBluetoothHciCallbacks callback)
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.hardware.bluetooth.V1_0.IBluetoothHci.kInterfaceName);
|
||||
_hidl_request.writeStrongBinder(callback == null ? null : callback.asBinder());
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(1 /* initialize */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendHciCommand(java.util.ArrayList<Byte> command)
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.hardware.bluetooth.V1_0.IBluetoothHci.kInterfaceName);
|
||||
_hidl_request.writeInt8Vector(command);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(2 /* sendHciCommand */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendAclData(java.util.ArrayList<Byte> data)
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.hardware.bluetooth.V1_0.IBluetoothHci.kInterfaceName);
|
||||
_hidl_request.writeInt8Vector(data);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(3 /* sendAclData */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendScoData(java.util.ArrayList<Byte> data)
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.hardware.bluetooth.V1_0.IBluetoothHci.kInterfaceName);
|
||||
_hidl_request.writeInt8Vector(data);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(4 /* sendScoData */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.hardware.bluetooth.V1_0.IBluetoothHci.kInterfaceName);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(5 /* close */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
// Methods from ::android::hidl::base::V1_0::IBase follow.
|
||||
@Override
|
||||
public java.util.ArrayList<String> interfaceChain()
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(256067662 /* interfaceChain */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
|
||||
java.util.ArrayList<String> _hidl_out_descriptors = _hidl_reply.readStringVector();
|
||||
return _hidl_out_descriptors;
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(NativeHandle fd, java.util.ArrayList<String> options)
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
_hidl_request.writeNativeHandle(fd);
|
||||
_hidl_request.writeStringVector(options);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(256131655 /* debug */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String interfaceDescriptor()
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(256136003 /* interfaceDescriptor */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
|
||||
String _hidl_out_descriptor = _hidl_reply.readString();
|
||||
return _hidl_out_descriptor;
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.ArrayList<byte[/* 32 */]> getHashChain()
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(256398152 /* getHashChain */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
|
||||
java.util.ArrayList<byte[/* 32 */]> _hidl_out_hashchain = new java.util.ArrayList<byte[/* 32 */]>();
|
||||
{
|
||||
HwBlob _hidl_blob = _hidl_reply.readBuffer(16 /* size */);
|
||||
{
|
||||
int _hidl_vec_size = _hidl_blob.getInt32(0 /* offset */ + 8 /* offsetof(hidl_vec<T>, mSize) */);
|
||||
HwBlob childBlob = _hidl_reply.readEmbeddedBuffer(
|
||||
_hidl_vec_size * 32,_hidl_blob.handle(),
|
||||
0 /* offset */ + 0 /* offsetof(hidl_vec<T>, mBuffer) */,true /* nullable */);
|
||||
|
||||
((java.util.ArrayList<byte[/* 32 */]>) _hidl_out_hashchain).clear();
|
||||
for (int _hidl_index_0 = 0; _hidl_index_0 < _hidl_vec_size; ++_hidl_index_0) {
|
||||
byte[/* 32 */] _hidl_vec_element = new byte[32];
|
||||
{
|
||||
long _hidl_array_offset_1 = _hidl_index_0 * 32;
|
||||
childBlob.copyToInt8Array(_hidl_array_offset_1, (byte[/* 32 */]) _hidl_vec_element, 32 /* size */);
|
||||
_hidl_array_offset_1 += 32 * 1;
|
||||
}
|
||||
((java.util.ArrayList<byte[/* 32 */]>) _hidl_out_hashchain).add(_hidl_vec_element);
|
||||
}
|
||||
}
|
||||
}
|
||||
return _hidl_out_hashchain;
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHALInstrumentation()
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(256462420 /* setHALInstrumentation */, _hidl_request, _hidl_reply, 1 /* oneway */);
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean linkToDeath(IHwBinder.DeathRecipient recipient, long cookie)
|
||||
throws android.os.RemoteException {
|
||||
return mRemote.linkToDeath(recipient, cookie);
|
||||
}
|
||||
@Override
|
||||
public void ping()
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(256921159 /* ping */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public android.internal.hidl.base.V1_0.DebugInfo getDebugInfo()
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(257049926 /* getDebugInfo */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
|
||||
android.internal.hidl.base.V1_0.DebugInfo _hidl_out_info = new android.internal.hidl.base.V1_0.DebugInfo();
|
||||
((android.internal.hidl.base.V1_0.DebugInfo) _hidl_out_info).readFromParcel(_hidl_reply);
|
||||
return _hidl_out_info;
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifySyspropsChanged()
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(257120595 /* notifySyspropsChanged */, _hidl_request, _hidl_reply, 1 /* oneway */);
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean unlinkToDeath(IHwBinder.DeathRecipient recipient)
|
||||
throws android.os.RemoteException {
|
||||
return mRemote.unlinkToDeath(recipient);
|
||||
}
|
||||
}
|
||||
|
||||
public static abstract class Stub extends HwBinder implements IBluetoothHci {
|
||||
@Override
|
||||
public IHwBinder asBinder() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final java.util.ArrayList<String> interfaceChain() {
|
||||
return new java.util.ArrayList<String>(java.util.Arrays.asList(
|
||||
android.hardware.bluetooth.V1_0.IBluetoothHci.kInterfaceName,
|
||||
android.internal.hidl.base.V1_0.IBase.kInterfaceName));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(NativeHandle fd, java.util.ArrayList<String> options) {
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String interfaceDescriptor() {
|
||||
return android.hardware.bluetooth.V1_0.IBluetoothHci.kInterfaceName;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final java.util.ArrayList<byte[/* 32 */]> getHashChain() {
|
||||
return new java.util.ArrayList<byte[/* 32 */]>(java.util.Arrays.asList(
|
||||
new byte[/* 32 */]{52,124,-25,70,-127,86,7,86,127,95,59,83,-28,-128,9,-104,-54,90,-71,53,81,65,-16,-120,15,-64,-49,12,31,-59,-61,85} /* 347ce746815607567f5f3b53e4800998ca5ab9355141f0880fc0cf0c1fc5c355 */,
|
||||
new byte[/* 32 */]{-20,127,-41,-98,-48,45,-6,-123,-68,73,-108,38,-83,-82,62,-66,35,-17,5,36,-13,-51,105,87,19,-109,36,-72,59,24,-54,76} /* ec7fd79ed02dfa85bc499426adae3ebe23ef0524f3cd6957139324b83b18ca4c */));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setHALInstrumentation() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean linkToDeath(IHwBinder.DeathRecipient recipient, long cookie) {
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void ping() {
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final android.internal.hidl.base.V1_0.DebugInfo getDebugInfo() {
|
||||
android.internal.hidl.base.V1_0.DebugInfo info = new android.internal.hidl.base.V1_0.DebugInfo();
|
||||
info.pid = HidlSupport.getPidIfSharable();
|
||||
info.ptr = 0;
|
||||
info.arch = android.internal.hidl.base.V1_0.DebugInfo.Architecture.UNKNOWN;
|
||||
return info;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void notifySyspropsChanged() {
|
||||
HwBinder.enableInstrumentation();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean unlinkToDeath(IHwBinder.DeathRecipient recipient) {
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public IHwInterface queryLocalInterface(String descriptor) {
|
||||
if (kInterfaceName.equals(descriptor)) {
|
||||
return this;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void registerAsService(String serviceName) throws android.os.RemoteException {
|
||||
registerService(serviceName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.interfaceDescriptor() + "@Stub";
|
||||
}
|
||||
|
||||
//@Override
|
||||
public void onTransact(int _hidl_code, HwParcel _hidl_request, final HwParcel _hidl_reply, int _hidl_flags)
|
||||
throws android.os.RemoteException {
|
||||
switch (_hidl_code) {
|
||||
case 1 /* initialize */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.hardware.bluetooth.V1_0.IBluetoothHci.kInterfaceName);
|
||||
|
||||
android.hardware.bluetooth.V1_0.IBluetoothHciCallbacks callback = android.hardware.bluetooth.V1_0.IBluetoothHciCallbacks.asInterface(_hidl_request.readStrongBinder());
|
||||
initialize(callback);
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 2 /* sendHciCommand */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.hardware.bluetooth.V1_0.IBluetoothHci.kInterfaceName);
|
||||
|
||||
java.util.ArrayList<Byte> command = _hidl_request.readInt8Vector();
|
||||
sendHciCommand(command);
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 3 /* sendAclData */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.hardware.bluetooth.V1_0.IBluetoothHci.kInterfaceName);
|
||||
|
||||
java.util.ArrayList<Byte> data = _hidl_request.readInt8Vector();
|
||||
sendAclData(data);
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 4 /* sendScoData */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.hardware.bluetooth.V1_0.IBluetoothHci.kInterfaceName);
|
||||
|
||||
java.util.ArrayList<Byte> data = _hidl_request.readInt8Vector();
|
||||
sendScoData(data);
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 5 /* close */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.hardware.bluetooth.V1_0.IBluetoothHci.kInterfaceName);
|
||||
|
||||
close();
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 256067662 /* interfaceChain */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
java.util.ArrayList<String> _hidl_out_descriptors = interfaceChain();
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
_hidl_reply.writeStringVector(_hidl_out_descriptors);
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 256131655 /* debug */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
NativeHandle fd = _hidl_request.readNativeHandle();
|
||||
java.util.ArrayList<String> options = _hidl_request.readStringVector();
|
||||
debug(fd, options);
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 256136003 /* interfaceDescriptor */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
String _hidl_out_descriptor = interfaceDescriptor();
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
_hidl_reply.writeString(_hidl_out_descriptor);
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 256398152 /* getHashChain */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
java.util.ArrayList<byte[/* 32 */]> _hidl_out_hashchain = getHashChain();
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
{
|
||||
HwBlob _hidl_blob = new HwBlob(16 /* size */);
|
||||
{
|
||||
int _hidl_vec_size = _hidl_out_hashchain.size();
|
||||
_hidl_blob.putInt32(0 /* offset */ + 8 /* offsetof(hidl_vec<T>, mSize) */, _hidl_vec_size);
|
||||
_hidl_blob.putBool(0 /* offset */ + 12 /* offsetof(hidl_vec<T>, mOwnsBuffer) */, false);
|
||||
HwBlob childBlob = new HwBlob((int)(_hidl_vec_size * 32));
|
||||
for (int _hidl_index_0 = 0; _hidl_index_0 < _hidl_vec_size; ++_hidl_index_0) {
|
||||
{
|
||||
long _hidl_array_offset_1 = _hidl_index_0 * 32;
|
||||
byte[] _hidl_array_item_1 = (byte[/* 32 */]) _hidl_out_hashchain.get(_hidl_index_0);
|
||||
|
||||
if (_hidl_array_item_1 == null || _hidl_array_item_1.length != 32) {
|
||||
throw new IllegalArgumentException("Array element is not of the expected length");
|
||||
}
|
||||
|
||||
childBlob.putInt8Array(_hidl_array_offset_1, _hidl_array_item_1);
|
||||
_hidl_array_offset_1 += 32 * 1;
|
||||
}
|
||||
}
|
||||
_hidl_blob.putBlob(0 /* offset */ + 0 /* offsetof(hidl_vec<T>, mBuffer) */, childBlob);
|
||||
}
|
||||
_hidl_reply.writeBuffer(_hidl_blob);
|
||||
}
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 256462420 /* setHALInstrumentation */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
setHALInstrumentation();
|
||||
break;
|
||||
}
|
||||
|
||||
case 256660548 /* linkToDeath */:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
case 256921159 /* ping */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
ping();
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 257049926 /* getDebugInfo */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
android.internal.hidl.base.V1_0.DebugInfo _hidl_out_info = getDebugInfo();
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
((android.internal.hidl.base.V1_0.DebugInfo) _hidl_out_info).writeToParcel(_hidl_reply);
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 257120595 /* notifySyspropsChanged */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
notifySyspropsChanged();
|
||||
break;
|
||||
}
|
||||
|
||||
case 257250372 /* unlinkToDeath */:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,762 @@
|
||||
package android.hardware.bluetooth.V1_0;
|
||||
|
||||
import android.os.HidlSupport;
|
||||
import android.os.HwBinder;
|
||||
import android.os.IHwBinder;
|
||||
import android.os.HwBlob;
|
||||
import android.os.HwParcel;
|
||||
import android.os.IHwInterface;
|
||||
import android.os.NativeHandle;
|
||||
|
||||
/**
|
||||
* The interface from the Bluetooth Controller to the stack.
|
||||
*/
|
||||
public interface IBluetoothHciCallbacks extends android.internal.hidl.base.V1_0.IBase {
|
||||
/**
|
||||
* Fully-qualified interface name for this interface.
|
||||
*/
|
||||
public static final String kInterfaceName = "android.hardware.bluetooth@1.0::IBluetoothHciCallbacks";
|
||||
|
||||
/**
|
||||
* Does a checked conversion from a binder to this class.
|
||||
*/
|
||||
/* package private */ static IBluetoothHciCallbacks asInterface(IHwBinder binder) {
|
||||
if (binder == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
IHwInterface iface =
|
||||
binder.queryLocalInterface(kInterfaceName);
|
||||
|
||||
if ((iface != null) && (iface instanceof IBluetoothHciCallbacks)) {
|
||||
return (IBluetoothHciCallbacks)iface;
|
||||
}
|
||||
|
||||
IBluetoothHciCallbacks proxy = new IBluetoothHciCallbacks.Proxy(binder);
|
||||
|
||||
try {
|
||||
for (String descriptor : proxy.interfaceChain()) {
|
||||
if (descriptor.equals(kInterfaceName)) {
|
||||
return proxy;
|
||||
}
|
||||
}
|
||||
} catch (android.os.RemoteException e) {
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does a checked conversion from any interface to this class.
|
||||
*/
|
||||
public static IBluetoothHciCallbacks castFrom(IHwInterface iface) {
|
||||
return (iface == null) ? null : IBluetoothHciCallbacks.asInterface(iface.asBinder());
|
||||
}
|
||||
|
||||
@Override
|
||||
public IHwBinder asBinder();
|
||||
|
||||
/**
|
||||
* This will invoke the equivalent of the C++ getService(std::string) if retry is
|
||||
* true or tryGetService(std::string) if retry is false. If the service is
|
||||
* available on the device and retry is true, this will wait for the service to
|
||||
* start.
|
||||
*
|
||||
*/
|
||||
public static IBluetoothHciCallbacks getService(String serviceName, boolean retry) throws android.os.RemoteException {
|
||||
return IBluetoothHciCallbacks.asInterface(HwBinder.getService("android.hardware.bluetooth@1.0::IBluetoothHciCallbacks", serviceName, retry));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls getService("default",retry).
|
||||
*/
|
||||
public static IBluetoothHciCallbacks getService(boolean retry) throws android.os.RemoteException {
|
||||
return getService("default", retry);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated this will not wait for the interface to come up if it hasn't yet
|
||||
* started. See getService(String,boolean) instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public static IBluetoothHciCallbacks getService(String serviceName) throws android.os.RemoteException {
|
||||
return IBluetoothHciCallbacks.asInterface(HwBinder.getService("android.hardware.bluetooth@1.0::IBluetoothHciCallbacks", serviceName));
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated this will not wait for the interface to come up if it hasn't yet
|
||||
* started. See getService(boolean) instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public static IBluetoothHciCallbacks getService() throws android.os.RemoteException {
|
||||
return getService("default");
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked when the Bluetooth controller initialization has been
|
||||
* completed.
|
||||
*/
|
||||
void initializationComplete(int status)
|
||||
throws android.os.RemoteException;
|
||||
/**
|
||||
* This function is invoked when an HCI event is received from the
|
||||
* Bluetooth controller to be forwarded to the Bluetooth stack.
|
||||
* @param event is the HCI event to be sent to the Bluetooth stack.
|
||||
*/
|
||||
void hciEventReceived(java.util.ArrayList<Byte> event)
|
||||
throws android.os.RemoteException;
|
||||
/**
|
||||
* Send an ACL data packet form the controller to the host.
|
||||
* @param data the ACL HCI packet to be passed to the host stack
|
||||
*/
|
||||
void aclDataReceived(java.util.ArrayList<Byte> data)
|
||||
throws android.os.RemoteException;
|
||||
/**
|
||||
* Send a SCO data packet form the controller to the host.
|
||||
* @param data the SCO HCI packet to be passed to the host stack
|
||||
*/
|
||||
void scoDataReceived(java.util.ArrayList<Byte> data)
|
||||
throws android.os.RemoteException;
|
||||
/*
|
||||
* Provides run-time type information for this object.
|
||||
* For example, for the following interface definition:
|
||||
* package android.hardware.foo@1.0;
|
||||
* interface IParent {};
|
||||
* interface IChild extends IParent {};
|
||||
* Calling interfaceChain on an IChild object must yield the following:
|
||||
* ["android.hardware.foo@1.0::IChild",
|
||||
* "android.hardware.foo@1.0::IParent"
|
||||
* "android.internal.hidl.base@1.0::IBase"]
|
||||
*
|
||||
* @return descriptors a vector of descriptors of the run-time type of the
|
||||
* object.
|
||||
*/
|
||||
java.util.ArrayList<String> interfaceChain()
|
||||
throws android.os.RemoteException;
|
||||
/*
|
||||
* Emit diagnostic information to the given file.
|
||||
*
|
||||
* Optionally overriden.
|
||||
*
|
||||
* @param fd File descriptor to dump data to.
|
||||
* Must only be used for the duration of this call.
|
||||
* @param options Arguments for debugging.
|
||||
* Must support empty for default debug information.
|
||||
*/
|
||||
void debug(NativeHandle fd, java.util.ArrayList<String> options)
|
||||
throws android.os.RemoteException;
|
||||
/*
|
||||
* Provides run-time type information for this object.
|
||||
* For example, for the following interface definition:
|
||||
* package android.hardware.foo@1.0;
|
||||
* interface IParent {};
|
||||
* interface IChild extends IParent {};
|
||||
* Calling interfaceDescriptor on an IChild object must yield
|
||||
* "android.hardware.foo@1.0::IChild"
|
||||
*
|
||||
* @return descriptor a descriptor of the run-time type of the
|
||||
* object (the first element of the vector returned by
|
||||
* interfaceChain())
|
||||
*/
|
||||
String interfaceDescriptor()
|
||||
throws android.os.RemoteException;
|
||||
/*
|
||||
* Returns hashes of the source HAL files that define the interfaces of the
|
||||
* runtime type information on the object.
|
||||
* For example, for the following interface definition:
|
||||
* package android.hardware.foo@1.0;
|
||||
* interface IParent {};
|
||||
* interface IChild extends IParent {};
|
||||
* Calling interfaceChain on an IChild object must yield the following:
|
||||
* [(hash of IChild.hal),
|
||||
* (hash of IParent.hal)
|
||||
* (hash of IBase.hal)].
|
||||
*
|
||||
* SHA-256 is used as the hashing algorithm. Each hash has 32 bytes
|
||||
* according to SHA-256 standard.
|
||||
*
|
||||
* @return hashchain a vector of SHA-1 digests
|
||||
*/
|
||||
java.util.ArrayList<byte[/* 32 */]> getHashChain()
|
||||
throws android.os.RemoteException;
|
||||
/*
|
||||
* This method trigger the interface to enable/disable instrumentation based
|
||||
* on system property hal.instrumentation.enable.
|
||||
*/
|
||||
void setHALInstrumentation()
|
||||
throws android.os.RemoteException;
|
||||
/*
|
||||
* Registers a death recipient, to be called when the process hosting this
|
||||
* interface dies.
|
||||
*
|
||||
* @param recipient a hidl_death_recipient callback object
|
||||
* @param cookie a cookie that must be returned with the callback
|
||||
* @return success whether the death recipient was registered successfully.
|
||||
*/
|
||||
boolean linkToDeath(IHwBinder.DeathRecipient recipient, long cookie)
|
||||
throws android.os.RemoteException;
|
||||
/*
|
||||
* Provides way to determine if interface is running without requesting
|
||||
* any functionality.
|
||||
*/
|
||||
void ping()
|
||||
throws android.os.RemoteException;
|
||||
/*
|
||||
* Get debug information on references on this interface.
|
||||
* @return info debugging information. See comments of DebugInfo.
|
||||
*/
|
||||
android.internal.hidl.base.V1_0.DebugInfo getDebugInfo()
|
||||
throws android.os.RemoteException;
|
||||
/*
|
||||
* This method notifies the interface that one or more system properties
|
||||
* have changed. The default implementation calls
|
||||
* (C++) report_sysprop_change() in libcutils or
|
||||
* (Java) android.os.SystemProperties.reportSyspropChanged,
|
||||
* which in turn calls a set of registered callbacks (eg to update trace
|
||||
* tags).
|
||||
*/
|
||||
void notifySyspropsChanged()
|
||||
throws android.os.RemoteException;
|
||||
/*
|
||||
* Unregisters the registered death recipient. If this service was registered
|
||||
* multiple times with the same exact death recipient, this unlinks the most
|
||||
* recently registered one.
|
||||
*
|
||||
* @param recipient a previously registered hidl_death_recipient callback
|
||||
* @return success whether the death recipient was unregistered successfully.
|
||||
*/
|
||||
boolean unlinkToDeath(IHwBinder.DeathRecipient recipient)
|
||||
throws android.os.RemoteException;
|
||||
|
||||
public static final class Proxy implements IBluetoothHciCallbacks {
|
||||
private IHwBinder mRemote;
|
||||
|
||||
public Proxy(IHwBinder remote) {
|
||||
mRemote = java.util.Objects.requireNonNull(remote);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IHwBinder asBinder() {
|
||||
return mRemote;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
try {
|
||||
return this.interfaceDescriptor() + "@Proxy";
|
||||
} catch (android.os.RemoteException ex) {
|
||||
/* ignored; handled below. */
|
||||
}
|
||||
return "[class or subclass of " + IBluetoothHciCallbacks.kInterfaceName + "]@Proxy";
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean equals(java.lang.Object other) {
|
||||
return HidlSupport.interfacesEqual(this, other);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
return this.asBinder().hashCode();
|
||||
}
|
||||
|
||||
// Methods from ::android::hardware::bluetooth::V1_0::IBluetoothHciCallbacks follow.
|
||||
@Override
|
||||
public void initializationComplete(int status)
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.hardware.bluetooth.V1_0.IBluetoothHciCallbacks.kInterfaceName);
|
||||
_hidl_request.writeInt32(status);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(1 /* initializationComplete */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hciEventReceived(java.util.ArrayList<Byte> event)
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.hardware.bluetooth.V1_0.IBluetoothHciCallbacks.kInterfaceName);
|
||||
_hidl_request.writeInt8Vector(event);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(2 /* hciEventReceived */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void aclDataReceived(java.util.ArrayList<Byte> data)
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.hardware.bluetooth.V1_0.IBluetoothHciCallbacks.kInterfaceName);
|
||||
_hidl_request.writeInt8Vector(data);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(3 /* aclDataReceived */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scoDataReceived(java.util.ArrayList<Byte> data)
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.hardware.bluetooth.V1_0.IBluetoothHciCallbacks.kInterfaceName);
|
||||
_hidl_request.writeInt8Vector(data);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(4 /* scoDataReceived */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
// Methods from ::android::hidl::base::V1_0::IBase follow.
|
||||
@Override
|
||||
public java.util.ArrayList<String> interfaceChain()
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(256067662 /* interfaceChain */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
|
||||
java.util.ArrayList<String> _hidl_out_descriptors = _hidl_reply.readStringVector();
|
||||
return _hidl_out_descriptors;
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(NativeHandle fd, java.util.ArrayList<String> options)
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
_hidl_request.writeNativeHandle(fd);
|
||||
_hidl_request.writeStringVector(options);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(256131655 /* debug */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String interfaceDescriptor()
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(256136003 /* interfaceDescriptor */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
|
||||
String _hidl_out_descriptor = _hidl_reply.readString();
|
||||
return _hidl_out_descriptor;
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.ArrayList<byte[/* 32 */]> getHashChain()
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(256398152 /* getHashChain */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
|
||||
java.util.ArrayList<byte[/* 32 */]> _hidl_out_hashchain = new java.util.ArrayList<byte[/* 32 */]>();
|
||||
{
|
||||
HwBlob _hidl_blob = _hidl_reply.readBuffer(16 /* size */);
|
||||
{
|
||||
int _hidl_vec_size = _hidl_blob.getInt32(0 /* offset */ + 8 /* offsetof(hidl_vec<T>, mSize) */);
|
||||
HwBlob childBlob = _hidl_reply.readEmbeddedBuffer(
|
||||
_hidl_vec_size * 32,_hidl_blob.handle(),
|
||||
0 /* offset */ + 0 /* offsetof(hidl_vec<T>, mBuffer) */,true /* nullable */);
|
||||
|
||||
((java.util.ArrayList<byte[/* 32 */]>) _hidl_out_hashchain).clear();
|
||||
for (int _hidl_index_0 = 0; _hidl_index_0 < _hidl_vec_size; ++_hidl_index_0) {
|
||||
byte[/* 32 */] _hidl_vec_element = new byte[32];
|
||||
{
|
||||
long _hidl_array_offset_1 = _hidl_index_0 * 32;
|
||||
childBlob.copyToInt8Array(_hidl_array_offset_1, (byte[/* 32 */]) _hidl_vec_element, 32 /* size */);
|
||||
_hidl_array_offset_1 += 32 * 1;
|
||||
}
|
||||
((java.util.ArrayList<byte[/* 32 */]>) _hidl_out_hashchain).add(_hidl_vec_element);
|
||||
}
|
||||
}
|
||||
}
|
||||
return _hidl_out_hashchain;
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHALInstrumentation()
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(256462420 /* setHALInstrumentation */, _hidl_request, _hidl_reply, 1 /* oneway */);
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean linkToDeath(IHwBinder.DeathRecipient recipient, long cookie)
|
||||
throws android.os.RemoteException {
|
||||
return mRemote.linkToDeath(recipient, cookie);
|
||||
}
|
||||
@Override
|
||||
public void ping()
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(256921159 /* ping */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public android.internal.hidl.base.V1_0.DebugInfo getDebugInfo()
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(257049926 /* getDebugInfo */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
|
||||
android.internal.hidl.base.V1_0.DebugInfo _hidl_out_info = new android.internal.hidl.base.V1_0.DebugInfo();
|
||||
((android.internal.hidl.base.V1_0.DebugInfo) _hidl_out_info).readFromParcel(_hidl_reply);
|
||||
return _hidl_out_info;
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifySyspropsChanged()
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(257120595 /* notifySyspropsChanged */, _hidl_request, _hidl_reply, 1 /* oneway */);
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean unlinkToDeath(IHwBinder.DeathRecipient recipient)
|
||||
throws android.os.RemoteException {
|
||||
return mRemote.unlinkToDeath(recipient);
|
||||
}
|
||||
}
|
||||
|
||||
public static abstract class Stub extends HwBinder implements IBluetoothHciCallbacks {
|
||||
@Override
|
||||
public IHwBinder asBinder() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final java.util.ArrayList<String> interfaceChain() {
|
||||
return new java.util.ArrayList<String>(java.util.Arrays.asList(
|
||||
android.hardware.bluetooth.V1_0.IBluetoothHciCallbacks.kInterfaceName,
|
||||
android.internal.hidl.base.V1_0.IBase.kInterfaceName));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(NativeHandle fd, java.util.ArrayList<String> options) {
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String interfaceDescriptor() {
|
||||
return android.hardware.bluetooth.V1_0.IBluetoothHciCallbacks.kInterfaceName;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final java.util.ArrayList<byte[/* 32 */]> getHashChain() {
|
||||
return new java.util.ArrayList<byte[/* 32 */]>(java.util.Arrays.asList(
|
||||
new byte[/* 32 */]{-125,95,65,-66,34,-127,-65,-78,47,62,51,-58,-6,-121,11,-34,123,-62,30,55,-27,-49,-70,-7,-93,111,-1,23,6,50,-9,84} /* 835f41be2281bfb22f3e33c6fa870bde7bc21e37e5cfbaf9a36fff170632f754 */,
|
||||
new byte[/* 32 */]{-20,127,-41,-98,-48,45,-6,-123,-68,73,-108,38,-83,-82,62,-66,35,-17,5,36,-13,-51,105,87,19,-109,36,-72,59,24,-54,76} /* ec7fd79ed02dfa85bc499426adae3ebe23ef0524f3cd6957139324b83b18ca4c */));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setHALInstrumentation() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean linkToDeath(IHwBinder.DeathRecipient recipient, long cookie) {
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void ping() {
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final android.internal.hidl.base.V1_0.DebugInfo getDebugInfo() {
|
||||
android.internal.hidl.base.V1_0.DebugInfo info = new android.internal.hidl.base.V1_0.DebugInfo();
|
||||
info.pid = HidlSupport.getPidIfSharable();
|
||||
info.ptr = 0;
|
||||
info.arch = android.internal.hidl.base.V1_0.DebugInfo.Architecture.UNKNOWN;
|
||||
return info;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void notifySyspropsChanged() {
|
||||
HwBinder.enableInstrumentation();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean unlinkToDeath(IHwBinder.DeathRecipient recipient) {
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public IHwInterface queryLocalInterface(String descriptor) {
|
||||
if (kInterfaceName.equals(descriptor)) {
|
||||
return this;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void registerAsService(String serviceName) throws android.os.RemoteException {
|
||||
registerService(serviceName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.interfaceDescriptor() + "@Stub";
|
||||
}
|
||||
|
||||
//@Override
|
||||
public void onTransact(int _hidl_code, HwParcel _hidl_request, final HwParcel _hidl_reply, int _hidl_flags)
|
||||
throws android.os.RemoteException {
|
||||
switch (_hidl_code) {
|
||||
case 1 /* initializationComplete */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.hardware.bluetooth.V1_0.IBluetoothHciCallbacks.kInterfaceName);
|
||||
|
||||
int status = _hidl_request.readInt32();
|
||||
initializationComplete(status);
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 2 /* hciEventReceived */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.hardware.bluetooth.V1_0.IBluetoothHciCallbacks.kInterfaceName);
|
||||
|
||||
java.util.ArrayList<Byte> event = _hidl_request.readInt8Vector();
|
||||
hciEventReceived(event);
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 3 /* aclDataReceived */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.hardware.bluetooth.V1_0.IBluetoothHciCallbacks.kInterfaceName);
|
||||
|
||||
java.util.ArrayList<Byte> data = _hidl_request.readInt8Vector();
|
||||
aclDataReceived(data);
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 4 /* scoDataReceived */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.hardware.bluetooth.V1_0.IBluetoothHciCallbacks.kInterfaceName);
|
||||
|
||||
java.util.ArrayList<Byte> data = _hidl_request.readInt8Vector();
|
||||
scoDataReceived(data);
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 256067662 /* interfaceChain */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
java.util.ArrayList<String> _hidl_out_descriptors = interfaceChain();
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
_hidl_reply.writeStringVector(_hidl_out_descriptors);
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 256131655 /* debug */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
NativeHandle fd = _hidl_request.readNativeHandle();
|
||||
java.util.ArrayList<String> options = _hidl_request.readStringVector();
|
||||
debug(fd, options);
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 256136003 /* interfaceDescriptor */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
String _hidl_out_descriptor = interfaceDescriptor();
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
_hidl_reply.writeString(_hidl_out_descriptor);
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 256398152 /* getHashChain */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
java.util.ArrayList<byte[/* 32 */]> _hidl_out_hashchain = getHashChain();
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
{
|
||||
HwBlob _hidl_blob = new HwBlob(16 /* size */);
|
||||
{
|
||||
int _hidl_vec_size = _hidl_out_hashchain.size();
|
||||
_hidl_blob.putInt32(0 /* offset */ + 8 /* offsetof(hidl_vec<T>, mSize) */, _hidl_vec_size);
|
||||
_hidl_blob.putBool(0 /* offset */ + 12 /* offsetof(hidl_vec<T>, mOwnsBuffer) */, false);
|
||||
HwBlob childBlob = new HwBlob((int)(_hidl_vec_size * 32));
|
||||
for (int _hidl_index_0 = 0; _hidl_index_0 < _hidl_vec_size; ++_hidl_index_0) {
|
||||
{
|
||||
long _hidl_array_offset_1 = _hidl_index_0 * 32;
|
||||
byte[] _hidl_array_item_1 = (byte[/* 32 */]) _hidl_out_hashchain.get(_hidl_index_0);
|
||||
|
||||
if (_hidl_array_item_1 == null || _hidl_array_item_1.length != 32) {
|
||||
throw new IllegalArgumentException("Array element is not of the expected length");
|
||||
}
|
||||
|
||||
childBlob.putInt8Array(_hidl_array_offset_1, _hidl_array_item_1);
|
||||
_hidl_array_offset_1 += 32 * 1;
|
||||
}
|
||||
}
|
||||
_hidl_blob.putBlob(0 /* offset */ + 0 /* offsetof(hidl_vec<T>, mBuffer) */, childBlob);
|
||||
}
|
||||
_hidl_reply.writeBuffer(_hidl_blob);
|
||||
}
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 256462420 /* setHALInstrumentation */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
setHALInstrumentation();
|
||||
break;
|
||||
}
|
||||
|
||||
case 256660548 /* linkToDeath */:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
case 256921159 /* ping */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
ping();
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 257049926 /* getDebugInfo */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
android.internal.hidl.base.V1_0.DebugInfo _hidl_out_info = getDebugInfo();
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
((android.internal.hidl.base.V1_0.DebugInfo) _hidl_out_info).writeToParcel(_hidl_reply);
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 257120595 /* notifySyspropsChanged */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
notifySyspropsChanged();
|
||||
break;
|
||||
}
|
||||
|
||||
case 257250372 /* unlinkToDeath */:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package android.hardware.bluetooth.V1_0;
|
||||
|
||||
|
||||
public final class Status {
|
||||
public static final int SUCCESS = 0;
|
||||
public static final int TRANSPORT_ERROR = 1 /* ::android::hardware::bluetooth::V1_0::Status.SUCCESS implicitly + 1 */;
|
||||
public static final int INITIALIZATION_ERROR = 2 /* ::android::hardware::bluetooth::V1_0::Status.TRANSPORT_ERROR implicitly + 1 */;
|
||||
public static final int UNKNOWN = 3 /* ::android::hardware::bluetooth::V1_0::Status.INITIALIZATION_ERROR implicitly + 1 */;
|
||||
public static final String toString(int o) {
|
||||
if (o == SUCCESS) {
|
||||
return "SUCCESS";
|
||||
}
|
||||
if (o == TRANSPORT_ERROR) {
|
||||
return "TRANSPORT_ERROR";
|
||||
}
|
||||
if (o == INITIALIZATION_ERROR) {
|
||||
return "INITIALIZATION_ERROR";
|
||||
}
|
||||
if (o == UNKNOWN) {
|
||||
return "UNKNOWN";
|
||||
}
|
||||
return "0x" + Integer.toHexString(o);
|
||||
}
|
||||
|
||||
public static final String dumpBitfield(int o) {
|
||||
java.util.ArrayList<String> list = new java.util.ArrayList<>();
|
||||
int flipped = 0;
|
||||
list.add("SUCCESS"); // SUCCESS == 0
|
||||
if ((o & TRANSPORT_ERROR) == TRANSPORT_ERROR) {
|
||||
list.add("TRANSPORT_ERROR");
|
||||
flipped |= TRANSPORT_ERROR;
|
||||
}
|
||||
if ((o & INITIALIZATION_ERROR) == INITIALIZATION_ERROR) {
|
||||
list.add("INITIALIZATION_ERROR");
|
||||
flipped |= INITIALIZATION_ERROR;
|
||||
}
|
||||
if ((o & UNKNOWN) == UNKNOWN) {
|
||||
list.add("UNKNOWN");
|
||||
flipped |= UNKNOWN;
|
||||
}
|
||||
if (o != flipped) {
|
||||
list.add("0x" + Integer.toHexString(o & (~flipped)));
|
||||
}
|
||||
return String.join(" | ", list);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -0,0 +1,840 @@
|
||||
package android.hardware.bluetooth.V1_1;
|
||||
|
||||
import android.os.HidlSupport;
|
||||
import android.os.HwBinder;
|
||||
import android.os.IHwBinder;
|
||||
import android.os.HwBlob;
|
||||
import android.os.HwParcel;
|
||||
import android.os.IHwInterface;
|
||||
import android.os.NativeHandle;
|
||||
|
||||
/**
|
||||
* The Host Controller Interface (HCI) is the layer defined by the Bluetooth
|
||||
* specification between the software that runs on the host and the Bluetooth
|
||||
* controller chip. This boundary is the natural choice for a Hardware
|
||||
* Abstraction Layer (HAL). Dealing only in HCI packets and events simplifies
|
||||
* the stack and abstracts away power management, initialization, and other
|
||||
* implementation-specific details related to the hardware.
|
||||
*/
|
||||
public interface IBluetoothHci extends android.hardware.bluetooth.V1_0.IBluetoothHci {
|
||||
/**
|
||||
* Fully-qualified interface name for this interface.
|
||||
*/
|
||||
public static final String kInterfaceName = "android.hardware.bluetooth@1.1::IBluetoothHci";
|
||||
|
||||
/**
|
||||
* Does a checked conversion from a binder to this class.
|
||||
*/
|
||||
/* package private */ static IBluetoothHci asInterface(IHwBinder binder) {
|
||||
if (binder == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
IHwInterface iface =
|
||||
binder.queryLocalInterface(kInterfaceName);
|
||||
|
||||
if ((iface != null) && (iface instanceof IBluetoothHci)) {
|
||||
return (IBluetoothHci)iface;
|
||||
}
|
||||
|
||||
IBluetoothHci proxy = new IBluetoothHci.Proxy(binder);
|
||||
|
||||
try {
|
||||
for (String descriptor : proxy.interfaceChain()) {
|
||||
if (descriptor.equals(kInterfaceName)) {
|
||||
return proxy;
|
||||
}
|
||||
}
|
||||
} catch (android.os.RemoteException e) {
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does a checked conversion from any interface to this class.
|
||||
*/
|
||||
public static IBluetoothHci castFrom(IHwInterface iface) {
|
||||
return (iface == null) ? null : IBluetoothHci.asInterface(iface.asBinder());
|
||||
}
|
||||
|
||||
@Override
|
||||
public IHwBinder asBinder();
|
||||
|
||||
/**
|
||||
* This will invoke the equivalent of the C++ getService(std::string) if retry is
|
||||
* true or tryGetService(std::string) if retry is false. If the service is
|
||||
* available on the device and retry is true, this will wait for the service to
|
||||
* start.
|
||||
*
|
||||
*/
|
||||
public static IBluetoothHci getService(String serviceName, boolean retry) throws android.os.RemoteException {
|
||||
return IBluetoothHci.asInterface(HwBinder.getService("android.hardware.bluetooth@1.1::IBluetoothHci", serviceName, retry));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls getService("default",retry).
|
||||
*/
|
||||
public static IBluetoothHci getService(boolean retry) throws android.os.RemoteException {
|
||||
return getService("default", retry);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated this will not wait for the interface to come up if it hasn't yet
|
||||
* started. See getService(String,boolean) instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public static IBluetoothHci getService(String serviceName) throws android.os.RemoteException {
|
||||
return IBluetoothHci.asInterface(HwBinder.getService("android.hardware.bluetooth@1.1::IBluetoothHci", serviceName));
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated this will not wait for the interface to come up if it hasn't yet
|
||||
* started. See getService(boolean) instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public static IBluetoothHci getService() throws android.os.RemoteException {
|
||||
return getService("default");
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as @1.0, but uses 1.1 Callbacks version
|
||||
*/
|
||||
void initialize_1_1(android.hardware.bluetooth.V1_1.IBluetoothHciCallbacks callback)
|
||||
throws android.os.RemoteException;
|
||||
/**
|
||||
* Send an ISO data packet (as specified in the Bluetooth Core
|
||||
* Specification v5.2) to the Bluetooth controller.
|
||||
* Packets must be processed in order.
|
||||
* @param data HCI data packet to be sent
|
||||
*/
|
||||
void sendIsoData(java.util.ArrayList<Byte> data)
|
||||
throws android.os.RemoteException;
|
||||
/*
|
||||
* Provides run-time type information for this object.
|
||||
* For example, for the following interface definition:
|
||||
* package android.hardware.foo@1.0;
|
||||
* interface IParent {};
|
||||
* interface IChild extends IParent {};
|
||||
* Calling interfaceChain on an IChild object must yield the following:
|
||||
* ["android.hardware.foo@1.0::IChild",
|
||||
* "android.hardware.foo@1.0::IParent"
|
||||
* "android.internal.hidl.base@1.0::IBase"]
|
||||
*
|
||||
* @return descriptors a vector of descriptors of the run-time type of the
|
||||
* object.
|
||||
*/
|
||||
java.util.ArrayList<String> interfaceChain()
|
||||
throws android.os.RemoteException;
|
||||
/*
|
||||
* Emit diagnostic information to the given file.
|
||||
*
|
||||
* Optionally overriden.
|
||||
*
|
||||
* @param fd File descriptor to dump data to.
|
||||
* Must only be used for the duration of this call.
|
||||
* @param options Arguments for debugging.
|
||||
* Must support empty for default debug information.
|
||||
*/
|
||||
void debug(NativeHandle fd, java.util.ArrayList<String> options)
|
||||
throws android.os.RemoteException;
|
||||
/*
|
||||
* Provides run-time type information for this object.
|
||||
* For example, for the following interface definition:
|
||||
* package android.hardware.foo@1.0;
|
||||
* interface IParent {};
|
||||
* interface IChild extends IParent {};
|
||||
* Calling interfaceDescriptor on an IChild object must yield
|
||||
* "android.hardware.foo@1.0::IChild"
|
||||
*
|
||||
* @return descriptor a descriptor of the run-time type of the
|
||||
* object (the first element of the vector returned by
|
||||
* interfaceChain())
|
||||
*/
|
||||
String interfaceDescriptor()
|
||||
throws android.os.RemoteException;
|
||||
/*
|
||||
* Returns hashes of the source HAL files that define the interfaces of the
|
||||
* runtime type information on the object.
|
||||
* For example, for the following interface definition:
|
||||
* package android.hardware.foo@1.0;
|
||||
* interface IParent {};
|
||||
* interface IChild extends IParent {};
|
||||
* Calling interfaceChain on an IChild object must yield the following:
|
||||
* [(hash of IChild.hal),
|
||||
* (hash of IParent.hal)
|
||||
* (hash of IBase.hal)].
|
||||
*
|
||||
* SHA-256 is used as the hashing algorithm. Each hash has 32 bytes
|
||||
* according to SHA-256 standard.
|
||||
*
|
||||
* @return hashchain a vector of SHA-1 digests
|
||||
*/
|
||||
java.util.ArrayList<byte[/* 32 */]> getHashChain()
|
||||
throws android.os.RemoteException;
|
||||
/*
|
||||
* This method trigger the interface to enable/disable instrumentation based
|
||||
* on system property hal.instrumentation.enable.
|
||||
*/
|
||||
void setHALInstrumentation()
|
||||
throws android.os.RemoteException;
|
||||
/*
|
||||
* Registers a death recipient, to be called when the process hosting this
|
||||
* interface dies.
|
||||
*
|
||||
* @param recipient a hidl_death_recipient callback object
|
||||
* @param cookie a cookie that must be returned with the callback
|
||||
* @return success whether the death recipient was registered successfully.
|
||||
*/
|
||||
boolean linkToDeath(IHwBinder.DeathRecipient recipient, long cookie)
|
||||
throws android.os.RemoteException;
|
||||
/*
|
||||
* Provides way to determine if interface is running without requesting
|
||||
* any functionality.
|
||||
*/
|
||||
void ping()
|
||||
throws android.os.RemoteException;
|
||||
/*
|
||||
* Get debug information on references on this interface.
|
||||
* @return info debugging information. See comments of DebugInfo.
|
||||
*/
|
||||
android.internal.hidl.base.V1_0.DebugInfo getDebugInfo()
|
||||
throws android.os.RemoteException;
|
||||
/*
|
||||
* This method notifies the interface that one or more system properties
|
||||
* have changed. The default implementation calls
|
||||
* (C++) report_sysprop_change() in libcutils or
|
||||
* (Java) android.os.SystemProperties.reportSyspropChanged,
|
||||
* which in turn calls a set of registered callbacks (eg to update trace
|
||||
* tags).
|
||||
*/
|
||||
void notifySyspropsChanged()
|
||||
throws android.os.RemoteException;
|
||||
/*
|
||||
* Unregisters the registered death recipient. If this service was registered
|
||||
* multiple times with the same exact death recipient, this unlinks the most
|
||||
* recently registered one.
|
||||
*
|
||||
* @param recipient a previously registered hidl_death_recipient callback
|
||||
* @return success whether the death recipient was unregistered successfully.
|
||||
*/
|
||||
boolean unlinkToDeath(IHwBinder.DeathRecipient recipient)
|
||||
throws android.os.RemoteException;
|
||||
|
||||
public static final class Proxy implements IBluetoothHci {
|
||||
private IHwBinder mRemote;
|
||||
|
||||
public Proxy(IHwBinder remote) {
|
||||
mRemote = java.util.Objects.requireNonNull(remote);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IHwBinder asBinder() {
|
||||
return mRemote;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
try {
|
||||
return this.interfaceDescriptor() + "@Proxy";
|
||||
} catch (android.os.RemoteException ex) {
|
||||
/* ignored; handled below. */
|
||||
}
|
||||
return "[class or subclass of " + IBluetoothHci.kInterfaceName + "]@Proxy";
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean equals(java.lang.Object other) {
|
||||
return HidlSupport.interfacesEqual(this, other);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
return this.asBinder().hashCode();
|
||||
}
|
||||
|
||||
// Methods from ::android::hardware::bluetooth::V1_0::IBluetoothHci follow.
|
||||
@Override
|
||||
public void initialize(android.hardware.bluetooth.V1_0.IBluetoothHciCallbacks callback)
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.hardware.bluetooth.V1_0.IBluetoothHci.kInterfaceName);
|
||||
_hidl_request.writeStrongBinder(callback == null ? null : callback.asBinder());
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(1 /* initialize */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendHciCommand(java.util.ArrayList<Byte> command)
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.hardware.bluetooth.V1_0.IBluetoothHci.kInterfaceName);
|
||||
_hidl_request.writeInt8Vector(command);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(2 /* sendHciCommand */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendAclData(java.util.ArrayList<Byte> data)
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.hardware.bluetooth.V1_0.IBluetoothHci.kInterfaceName);
|
||||
_hidl_request.writeInt8Vector(data);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(3 /* sendAclData */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendScoData(java.util.ArrayList<Byte> data)
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.hardware.bluetooth.V1_0.IBluetoothHci.kInterfaceName);
|
||||
_hidl_request.writeInt8Vector(data);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(4 /* sendScoData */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.hardware.bluetooth.V1_0.IBluetoothHci.kInterfaceName);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(5 /* close */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
// Methods from ::android::hardware::bluetooth::V1_1::IBluetoothHci follow.
|
||||
@Override
|
||||
public void initialize_1_1(android.hardware.bluetooth.V1_1.IBluetoothHciCallbacks callback)
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.hardware.bluetooth.V1_1.IBluetoothHci.kInterfaceName);
|
||||
_hidl_request.writeStrongBinder(callback == null ? null : callback.asBinder());
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(6 /* initialize_1_1 */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendIsoData(java.util.ArrayList<Byte> data)
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.hardware.bluetooth.V1_1.IBluetoothHci.kInterfaceName);
|
||||
_hidl_request.writeInt8Vector(data);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(7 /* sendIsoData */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
// Methods from ::android::hidl::base::V1_0::IBase follow.
|
||||
@Override
|
||||
public java.util.ArrayList<String> interfaceChain()
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(256067662 /* interfaceChain */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
|
||||
java.util.ArrayList<String> _hidl_out_descriptors = _hidl_reply.readStringVector();
|
||||
return _hidl_out_descriptors;
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(NativeHandle fd, java.util.ArrayList<String> options)
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
_hidl_request.writeNativeHandle(fd);
|
||||
_hidl_request.writeStringVector(options);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(256131655 /* debug */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String interfaceDescriptor()
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(256136003 /* interfaceDescriptor */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
|
||||
String _hidl_out_descriptor = _hidl_reply.readString();
|
||||
return _hidl_out_descriptor;
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.ArrayList<byte[/* 32 */]> getHashChain()
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(256398152 /* getHashChain */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
|
||||
java.util.ArrayList<byte[/* 32 */]> _hidl_out_hashchain = new java.util.ArrayList<byte[/* 32 */]>();
|
||||
{
|
||||
HwBlob _hidl_blob = _hidl_reply.readBuffer(16 /* size */);
|
||||
{
|
||||
int _hidl_vec_size = _hidl_blob.getInt32(0 /* offset */ + 8 /* offsetof(hidl_vec<T>, mSize) */);
|
||||
HwBlob childBlob = _hidl_reply.readEmbeddedBuffer(
|
||||
_hidl_vec_size * 32,_hidl_blob.handle(),
|
||||
0 /* offset */ + 0 /* offsetof(hidl_vec<T>, mBuffer) */,true /* nullable */);
|
||||
|
||||
((java.util.ArrayList<byte[/* 32 */]>) _hidl_out_hashchain).clear();
|
||||
for (int _hidl_index_0 = 0; _hidl_index_0 < _hidl_vec_size; ++_hidl_index_0) {
|
||||
byte[/* 32 */] _hidl_vec_element = new byte[32];
|
||||
{
|
||||
long _hidl_array_offset_1 = _hidl_index_0 * 32;
|
||||
childBlob.copyToInt8Array(_hidl_array_offset_1, (byte[/* 32 */]) _hidl_vec_element, 32 /* size */);
|
||||
_hidl_array_offset_1 += 32 * 1;
|
||||
}
|
||||
((java.util.ArrayList<byte[/* 32 */]>) _hidl_out_hashchain).add(_hidl_vec_element);
|
||||
}
|
||||
}
|
||||
}
|
||||
return _hidl_out_hashchain;
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHALInstrumentation()
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(256462420 /* setHALInstrumentation */, _hidl_request, _hidl_reply, 1 /* oneway */);
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean linkToDeath(IHwBinder.DeathRecipient recipient, long cookie)
|
||||
throws android.os.RemoteException {
|
||||
return mRemote.linkToDeath(recipient, cookie);
|
||||
}
|
||||
@Override
|
||||
public void ping()
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(256921159 /* ping */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public android.internal.hidl.base.V1_0.DebugInfo getDebugInfo()
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(257049926 /* getDebugInfo */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
|
||||
android.internal.hidl.base.V1_0.DebugInfo _hidl_out_info = new android.internal.hidl.base.V1_0.DebugInfo();
|
||||
((android.internal.hidl.base.V1_0.DebugInfo) _hidl_out_info).readFromParcel(_hidl_reply);
|
||||
return _hidl_out_info;
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifySyspropsChanged()
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(257120595 /* notifySyspropsChanged */, _hidl_request, _hidl_reply, 1 /* oneway */);
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean unlinkToDeath(IHwBinder.DeathRecipient recipient)
|
||||
throws android.os.RemoteException {
|
||||
return mRemote.unlinkToDeath(recipient);
|
||||
}
|
||||
}
|
||||
|
||||
public static abstract class Stub extends HwBinder implements IBluetoothHci {
|
||||
@Override
|
||||
public IHwBinder asBinder() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final java.util.ArrayList<String> interfaceChain() {
|
||||
return new java.util.ArrayList<String>(java.util.Arrays.asList(
|
||||
android.hardware.bluetooth.V1_1.IBluetoothHci.kInterfaceName,
|
||||
android.hardware.bluetooth.V1_0.IBluetoothHci.kInterfaceName,
|
||||
android.internal.hidl.base.V1_0.IBase.kInterfaceName));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(NativeHandle fd, java.util.ArrayList<String> options) {
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String interfaceDescriptor() {
|
||||
return android.hardware.bluetooth.V1_1.IBluetoothHci.kInterfaceName;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final java.util.ArrayList<byte[/* 32 */]> getHashChain() {
|
||||
return new java.util.ArrayList<byte[/* 32 */]>(java.util.Arrays.asList(
|
||||
new byte[/* 32 */]{54,47,-47,-62,22,65,-62,34,79,59,-128,-61,13,-105,-105,-71,-120,-6,63,52,66,67,-43,49,-70,115,-59,83,119,-102,87,99} /* 362fd1c21641c2224f3b80c30d9797b988fa3f344243d531ba73c553779a5763 */,
|
||||
new byte[/* 32 */]{52,124,-25,70,-127,86,7,86,127,95,59,83,-28,-128,9,-104,-54,90,-71,53,81,65,-16,-120,15,-64,-49,12,31,-59,-61,85} /* 347ce746815607567f5f3b53e4800998ca5ab9355141f0880fc0cf0c1fc5c355 */,
|
||||
new byte[/* 32 */]{-20,127,-41,-98,-48,45,-6,-123,-68,73,-108,38,-83,-82,62,-66,35,-17,5,36,-13,-51,105,87,19,-109,36,-72,59,24,-54,76} /* ec7fd79ed02dfa85bc499426adae3ebe23ef0524f3cd6957139324b83b18ca4c */));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setHALInstrumentation() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean linkToDeath(IHwBinder.DeathRecipient recipient, long cookie) {
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void ping() {
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final android.internal.hidl.base.V1_0.DebugInfo getDebugInfo() {
|
||||
android.internal.hidl.base.V1_0.DebugInfo info = new android.internal.hidl.base.V1_0.DebugInfo();
|
||||
info.pid = HidlSupport.getPidIfSharable();
|
||||
info.ptr = 0;
|
||||
info.arch = android.internal.hidl.base.V1_0.DebugInfo.Architecture.UNKNOWN;
|
||||
return info;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void notifySyspropsChanged() {
|
||||
HwBinder.enableInstrumentation();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean unlinkToDeath(IHwBinder.DeathRecipient recipient) {
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public IHwInterface queryLocalInterface(String descriptor) {
|
||||
if (kInterfaceName.equals(descriptor)) {
|
||||
return this;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void registerAsService(String serviceName) throws android.os.RemoteException {
|
||||
registerService(serviceName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.interfaceDescriptor() + "@Stub";
|
||||
}
|
||||
|
||||
//@Override
|
||||
public void onTransact(int _hidl_code, HwParcel _hidl_request, final HwParcel _hidl_reply, int _hidl_flags)
|
||||
throws android.os.RemoteException {
|
||||
switch (_hidl_code) {
|
||||
case 1 /* initialize */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.hardware.bluetooth.V1_0.IBluetoothHci.kInterfaceName);
|
||||
|
||||
android.hardware.bluetooth.V1_0.IBluetoothHciCallbacks callback = android.hardware.bluetooth.V1_0.IBluetoothHciCallbacks.asInterface(_hidl_request.readStrongBinder());
|
||||
initialize(callback);
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 2 /* sendHciCommand */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.hardware.bluetooth.V1_0.IBluetoothHci.kInterfaceName);
|
||||
|
||||
java.util.ArrayList<Byte> command = _hidl_request.readInt8Vector();
|
||||
sendHciCommand(command);
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 3 /* sendAclData */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.hardware.bluetooth.V1_0.IBluetoothHci.kInterfaceName);
|
||||
|
||||
java.util.ArrayList<Byte> data = _hidl_request.readInt8Vector();
|
||||
sendAclData(data);
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 4 /* sendScoData */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.hardware.bluetooth.V1_0.IBluetoothHci.kInterfaceName);
|
||||
|
||||
java.util.ArrayList<Byte> data = _hidl_request.readInt8Vector();
|
||||
sendScoData(data);
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 5 /* close */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.hardware.bluetooth.V1_0.IBluetoothHci.kInterfaceName);
|
||||
|
||||
close();
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 6 /* initialize_1_1 */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.hardware.bluetooth.V1_1.IBluetoothHci.kInterfaceName);
|
||||
|
||||
android.hardware.bluetooth.V1_1.IBluetoothHciCallbacks callback = android.hardware.bluetooth.V1_1.IBluetoothHciCallbacks.asInterface(_hidl_request.readStrongBinder());
|
||||
initialize_1_1(callback);
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 7 /* sendIsoData */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.hardware.bluetooth.V1_1.IBluetoothHci.kInterfaceName);
|
||||
|
||||
java.util.ArrayList<Byte> data = _hidl_request.readInt8Vector();
|
||||
sendIsoData(data);
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 256067662 /* interfaceChain */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
java.util.ArrayList<String> _hidl_out_descriptors = interfaceChain();
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
_hidl_reply.writeStringVector(_hidl_out_descriptors);
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 256131655 /* debug */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
NativeHandle fd = _hidl_request.readNativeHandle();
|
||||
java.util.ArrayList<String> options = _hidl_request.readStringVector();
|
||||
debug(fd, options);
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 256136003 /* interfaceDescriptor */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
String _hidl_out_descriptor = interfaceDescriptor();
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
_hidl_reply.writeString(_hidl_out_descriptor);
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 256398152 /* getHashChain */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
java.util.ArrayList<byte[/* 32 */]> _hidl_out_hashchain = getHashChain();
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
{
|
||||
HwBlob _hidl_blob = new HwBlob(16 /* size */);
|
||||
{
|
||||
int _hidl_vec_size = _hidl_out_hashchain.size();
|
||||
_hidl_blob.putInt32(0 /* offset */ + 8 /* offsetof(hidl_vec<T>, mSize) */, _hidl_vec_size);
|
||||
_hidl_blob.putBool(0 /* offset */ + 12 /* offsetof(hidl_vec<T>, mOwnsBuffer) */, false);
|
||||
HwBlob childBlob = new HwBlob((int)(_hidl_vec_size * 32));
|
||||
for (int _hidl_index_0 = 0; _hidl_index_0 < _hidl_vec_size; ++_hidl_index_0) {
|
||||
{
|
||||
long _hidl_array_offset_1 = _hidl_index_0 * 32;
|
||||
byte[] _hidl_array_item_1 = (byte[/* 32 */]) _hidl_out_hashchain.get(_hidl_index_0);
|
||||
|
||||
if (_hidl_array_item_1 == null || _hidl_array_item_1.length != 32) {
|
||||
throw new IllegalArgumentException("Array element is not of the expected length");
|
||||
}
|
||||
|
||||
childBlob.putInt8Array(_hidl_array_offset_1, _hidl_array_item_1);
|
||||
_hidl_array_offset_1 += 32 * 1;
|
||||
}
|
||||
}
|
||||
_hidl_blob.putBlob(0 /* offset */ + 0 /* offsetof(hidl_vec<T>, mBuffer) */, childBlob);
|
||||
}
|
||||
_hidl_reply.writeBuffer(_hidl_blob);
|
||||
}
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 256462420 /* setHALInstrumentation */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
setHALInstrumentation();
|
||||
break;
|
||||
}
|
||||
|
||||
case 256660548 /* linkToDeath */:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
case 256921159 /* ping */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
ping();
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 257049926 /* getDebugInfo */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
android.internal.hidl.base.V1_0.DebugInfo _hidl_out_info = getDebugInfo();
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
((android.internal.hidl.base.V1_0.DebugInfo) _hidl_out_info).writeToParcel(_hidl_reply);
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 257120595 /* notifySyspropsChanged */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
notifySyspropsChanged();
|
||||
break;
|
||||
}
|
||||
|
||||
case 257250372 /* unlinkToDeath */:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,774 @@
|
||||
package android.hardware.bluetooth.V1_1;
|
||||
|
||||
import android.os.HidlSupport;
|
||||
import android.os.HwBinder;
|
||||
import android.os.IHwBinder;
|
||||
import android.os.HwBlob;
|
||||
import android.os.HwParcel;
|
||||
import android.os.IHwInterface;
|
||||
import android.os.NativeHandle;
|
||||
|
||||
/**
|
||||
* The interface from the Bluetooth Controller to the stack.
|
||||
*/
|
||||
public interface IBluetoothHciCallbacks extends android.hardware.bluetooth.V1_0.IBluetoothHciCallbacks {
|
||||
/**
|
||||
* Fully-qualified interface name for this interface.
|
||||
*/
|
||||
public static final String kInterfaceName = "android.hardware.bluetooth@1.1::IBluetoothHciCallbacks";
|
||||
|
||||
/**
|
||||
* Does a checked conversion from a binder to this class.
|
||||
*/
|
||||
/* package private */ static IBluetoothHciCallbacks asInterface(IHwBinder binder) {
|
||||
if (binder == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
IHwInterface iface =
|
||||
binder.queryLocalInterface(kInterfaceName);
|
||||
|
||||
if ((iface != null) && (iface instanceof IBluetoothHciCallbacks)) {
|
||||
return (IBluetoothHciCallbacks)iface;
|
||||
}
|
||||
|
||||
IBluetoothHciCallbacks proxy = new IBluetoothHciCallbacks.Proxy(binder);
|
||||
|
||||
try {
|
||||
for (String descriptor : proxy.interfaceChain()) {
|
||||
if (descriptor.equals(kInterfaceName)) {
|
||||
return proxy;
|
||||
}
|
||||
}
|
||||
} catch (android.os.RemoteException e) {
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does a checked conversion from any interface to this class.
|
||||
*/
|
||||
public static IBluetoothHciCallbacks castFrom(IHwInterface iface) {
|
||||
return (iface == null) ? null : IBluetoothHciCallbacks.asInterface(iface.asBinder());
|
||||
}
|
||||
|
||||
@Override
|
||||
public IHwBinder asBinder();
|
||||
|
||||
/**
|
||||
* This will invoke the equivalent of the C++ getService(std::string) if retry is
|
||||
* true or tryGetService(std::string) if retry is false. If the service is
|
||||
* available on the device and retry is true, this will wait for the service to
|
||||
* start.
|
||||
*
|
||||
*/
|
||||
public static IBluetoothHciCallbacks getService(String serviceName, boolean retry) throws android.os.RemoteException {
|
||||
return IBluetoothHciCallbacks.asInterface(HwBinder.getService("android.hardware.bluetooth@1.1::IBluetoothHciCallbacks", serviceName, retry));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls getService("default",retry).
|
||||
*/
|
||||
public static IBluetoothHciCallbacks getService(boolean retry) throws android.os.RemoteException {
|
||||
return getService("default", retry);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated this will not wait for the interface to come up if it hasn't yet
|
||||
* started. See getService(String,boolean) instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public static IBluetoothHciCallbacks getService(String serviceName) throws android.os.RemoteException {
|
||||
return IBluetoothHciCallbacks.asInterface(HwBinder.getService("android.hardware.bluetooth@1.1::IBluetoothHciCallbacks", serviceName));
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated this will not wait for the interface to come up if it hasn't yet
|
||||
* started. See getService(boolean) instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public static IBluetoothHciCallbacks getService() throws android.os.RemoteException {
|
||||
return getService("default");
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a ISO data packet form the controller to the host.
|
||||
* @param data the ISO HCI packet to be passed to the host stack
|
||||
*/
|
||||
void isoDataReceived(java.util.ArrayList<Byte> data)
|
||||
throws android.os.RemoteException;
|
||||
/*
|
||||
* Provides run-time type information for this object.
|
||||
* For example, for the following interface definition:
|
||||
* package android.hardware.foo@1.0;
|
||||
* interface IParent {};
|
||||
* interface IChild extends IParent {};
|
||||
* Calling interfaceChain on an IChild object must yield the following:
|
||||
* ["android.hardware.foo@1.0::IChild",
|
||||
* "android.hardware.foo@1.0::IParent"
|
||||
* "android.internal.hidl.base@1.0::IBase"]
|
||||
*
|
||||
* @return descriptors a vector of descriptors of the run-time type of the
|
||||
* object.
|
||||
*/
|
||||
java.util.ArrayList<String> interfaceChain()
|
||||
throws android.os.RemoteException;
|
||||
/*
|
||||
* Emit diagnostic information to the given file.
|
||||
*
|
||||
* Optionally overriden.
|
||||
*
|
||||
* @param fd File descriptor to dump data to.
|
||||
* Must only be used for the duration of this call.
|
||||
* @param options Arguments for debugging.
|
||||
* Must support empty for default debug information.
|
||||
*/
|
||||
void debug(NativeHandle fd, java.util.ArrayList<String> options)
|
||||
throws android.os.RemoteException;
|
||||
/*
|
||||
* Provides run-time type information for this object.
|
||||
* For example, for the following interface definition:
|
||||
* package android.hardware.foo@1.0;
|
||||
* interface IParent {};
|
||||
* interface IChild extends IParent {};
|
||||
* Calling interfaceDescriptor on an IChild object must yield
|
||||
* "android.hardware.foo@1.0::IChild"
|
||||
*
|
||||
* @return descriptor a descriptor of the run-time type of the
|
||||
* object (the first element of the vector returned by
|
||||
* interfaceChain())
|
||||
*/
|
||||
String interfaceDescriptor()
|
||||
throws android.os.RemoteException;
|
||||
/*
|
||||
* Returns hashes of the source HAL files that define the interfaces of the
|
||||
* runtime type information on the object.
|
||||
* For example, for the following interface definition:
|
||||
* package android.hardware.foo@1.0;
|
||||
* interface IParent {};
|
||||
* interface IChild extends IParent {};
|
||||
* Calling interfaceChain on an IChild object must yield the following:
|
||||
* [(hash of IChild.hal),
|
||||
* (hash of IParent.hal)
|
||||
* (hash of IBase.hal)].
|
||||
*
|
||||
* SHA-256 is used as the hashing algorithm. Each hash has 32 bytes
|
||||
* according to SHA-256 standard.
|
||||
*
|
||||
* @return hashchain a vector of SHA-1 digests
|
||||
*/
|
||||
java.util.ArrayList<byte[/* 32 */]> getHashChain()
|
||||
throws android.os.RemoteException;
|
||||
/*
|
||||
* This method trigger the interface to enable/disable instrumentation based
|
||||
* on system property hal.instrumentation.enable.
|
||||
*/
|
||||
void setHALInstrumentation()
|
||||
throws android.os.RemoteException;
|
||||
/*
|
||||
* Registers a death recipient, to be called when the process hosting this
|
||||
* interface dies.
|
||||
*
|
||||
* @param recipient a hidl_death_recipient callback object
|
||||
* @param cookie a cookie that must be returned with the callback
|
||||
* @return success whether the death recipient was registered successfully.
|
||||
*/
|
||||
boolean linkToDeath(IHwBinder.DeathRecipient recipient, long cookie)
|
||||
throws android.os.RemoteException;
|
||||
/*
|
||||
* Provides way to determine if interface is running without requesting
|
||||
* any functionality.
|
||||
*/
|
||||
void ping()
|
||||
throws android.os.RemoteException;
|
||||
/*
|
||||
* Get debug information on references on this interface.
|
||||
* @return info debugging information. See comments of DebugInfo.
|
||||
*/
|
||||
android.internal.hidl.base.V1_0.DebugInfo getDebugInfo()
|
||||
throws android.os.RemoteException;
|
||||
/*
|
||||
* This method notifies the interface that one or more system properties
|
||||
* have changed. The default implementation calls
|
||||
* (C++) report_sysprop_change() in libcutils or
|
||||
* (Java) android.os.SystemProperties.reportSyspropChanged,
|
||||
* which in turn calls a set of registered callbacks (eg to update trace
|
||||
* tags).
|
||||
*/
|
||||
void notifySyspropsChanged()
|
||||
throws android.os.RemoteException;
|
||||
/*
|
||||
* Unregisters the registered death recipient. If this service was registered
|
||||
* multiple times with the same exact death recipient, this unlinks the most
|
||||
* recently registered one.
|
||||
*
|
||||
* @param recipient a previously registered hidl_death_recipient callback
|
||||
* @return success whether the death recipient was unregistered successfully.
|
||||
*/
|
||||
boolean unlinkToDeath(IHwBinder.DeathRecipient recipient)
|
||||
throws android.os.RemoteException;
|
||||
|
||||
public static final class Proxy implements IBluetoothHciCallbacks {
|
||||
private IHwBinder mRemote;
|
||||
|
||||
public Proxy(IHwBinder remote) {
|
||||
mRemote = java.util.Objects.requireNonNull(remote);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IHwBinder asBinder() {
|
||||
return mRemote;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
try {
|
||||
return this.interfaceDescriptor() + "@Proxy";
|
||||
} catch (android.os.RemoteException ex) {
|
||||
/* ignored; handled below. */
|
||||
}
|
||||
return "[class or subclass of " + IBluetoothHciCallbacks.kInterfaceName + "]@Proxy";
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean equals(java.lang.Object other) {
|
||||
return HidlSupport.interfacesEqual(this, other);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
return this.asBinder().hashCode();
|
||||
}
|
||||
|
||||
// Methods from ::android::hardware::bluetooth::V1_0::IBluetoothHciCallbacks follow.
|
||||
@Override
|
||||
public void initializationComplete(int status)
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.hardware.bluetooth.V1_0.IBluetoothHciCallbacks.kInterfaceName);
|
||||
_hidl_request.writeInt32(status);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(1 /* initializationComplete */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hciEventReceived(java.util.ArrayList<Byte> event)
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.hardware.bluetooth.V1_0.IBluetoothHciCallbacks.kInterfaceName);
|
||||
_hidl_request.writeInt8Vector(event);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(2 /* hciEventReceived */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void aclDataReceived(java.util.ArrayList<Byte> data)
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.hardware.bluetooth.V1_0.IBluetoothHciCallbacks.kInterfaceName);
|
||||
_hidl_request.writeInt8Vector(data);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(3 /* aclDataReceived */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scoDataReceived(java.util.ArrayList<Byte> data)
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.hardware.bluetooth.V1_0.IBluetoothHciCallbacks.kInterfaceName);
|
||||
_hidl_request.writeInt8Vector(data);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(4 /* scoDataReceived */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
// Methods from ::android::hardware::bluetooth::V1_1::IBluetoothHciCallbacks follow.
|
||||
@Override
|
||||
public void isoDataReceived(java.util.ArrayList<Byte> data)
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.hardware.bluetooth.V1_1.IBluetoothHciCallbacks.kInterfaceName);
|
||||
_hidl_request.writeInt8Vector(data);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(5 /* isoDataReceived */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
// Methods from ::android::hidl::base::V1_0::IBase follow.
|
||||
@Override
|
||||
public java.util.ArrayList<String> interfaceChain()
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(256067662 /* interfaceChain */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
|
||||
java.util.ArrayList<String> _hidl_out_descriptors = _hidl_reply.readStringVector();
|
||||
return _hidl_out_descriptors;
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(NativeHandle fd, java.util.ArrayList<String> options)
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
_hidl_request.writeNativeHandle(fd);
|
||||
_hidl_request.writeStringVector(options);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(256131655 /* debug */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String interfaceDescriptor()
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(256136003 /* interfaceDescriptor */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
|
||||
String _hidl_out_descriptor = _hidl_reply.readString();
|
||||
return _hidl_out_descriptor;
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.ArrayList<byte[/* 32 */]> getHashChain()
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(256398152 /* getHashChain */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
|
||||
java.util.ArrayList<byte[/* 32 */]> _hidl_out_hashchain = new java.util.ArrayList<byte[/* 32 */]>();
|
||||
{
|
||||
HwBlob _hidl_blob = _hidl_reply.readBuffer(16 /* size */);
|
||||
{
|
||||
int _hidl_vec_size = _hidl_blob.getInt32(0 /* offset */ + 8 /* offsetof(hidl_vec<T>, mSize) */);
|
||||
HwBlob childBlob = _hidl_reply.readEmbeddedBuffer(
|
||||
_hidl_vec_size * 32,_hidl_blob.handle(),
|
||||
0 /* offset */ + 0 /* offsetof(hidl_vec<T>, mBuffer) */,true /* nullable */);
|
||||
|
||||
((java.util.ArrayList<byte[/* 32 */]>) _hidl_out_hashchain).clear();
|
||||
for (int _hidl_index_0 = 0; _hidl_index_0 < _hidl_vec_size; ++_hidl_index_0) {
|
||||
byte[/* 32 */] _hidl_vec_element = new byte[32];
|
||||
{
|
||||
long _hidl_array_offset_1 = _hidl_index_0 * 32;
|
||||
childBlob.copyToInt8Array(_hidl_array_offset_1, (byte[/* 32 */]) _hidl_vec_element, 32 /* size */);
|
||||
_hidl_array_offset_1 += 32 * 1;
|
||||
}
|
||||
((java.util.ArrayList<byte[/* 32 */]>) _hidl_out_hashchain).add(_hidl_vec_element);
|
||||
}
|
||||
}
|
||||
}
|
||||
return _hidl_out_hashchain;
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHALInstrumentation()
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(256462420 /* setHALInstrumentation */, _hidl_request, _hidl_reply, 1 /* oneway */);
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean linkToDeath(IHwBinder.DeathRecipient recipient, long cookie)
|
||||
throws android.os.RemoteException {
|
||||
return mRemote.linkToDeath(recipient, cookie);
|
||||
}
|
||||
@Override
|
||||
public void ping()
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(256921159 /* ping */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public android.internal.hidl.base.V1_0.DebugInfo getDebugInfo()
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(257049926 /* getDebugInfo */, _hidl_request, _hidl_reply, 0 /* flags */);
|
||||
_hidl_reply.verifySuccess();
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
|
||||
android.internal.hidl.base.V1_0.DebugInfo _hidl_out_info = new android.internal.hidl.base.V1_0.DebugInfo();
|
||||
((android.internal.hidl.base.V1_0.DebugInfo) _hidl_out_info).readFromParcel(_hidl_reply);
|
||||
return _hidl_out_info;
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifySyspropsChanged()
|
||||
throws android.os.RemoteException {
|
||||
HwParcel _hidl_request = new HwParcel();
|
||||
_hidl_request.writeInterfaceToken(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
HwParcel _hidl_reply = new HwParcel();
|
||||
try {
|
||||
mRemote.transact(257120595 /* notifySyspropsChanged */, _hidl_request, _hidl_reply, 1 /* oneway */);
|
||||
_hidl_request.releaseTemporaryStorage();
|
||||
} finally {
|
||||
_hidl_reply.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean unlinkToDeath(IHwBinder.DeathRecipient recipient)
|
||||
throws android.os.RemoteException {
|
||||
return mRemote.unlinkToDeath(recipient);
|
||||
}
|
||||
}
|
||||
|
||||
public static abstract class Stub extends HwBinder implements IBluetoothHciCallbacks {
|
||||
@Override
|
||||
public IHwBinder asBinder() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final java.util.ArrayList<String> interfaceChain() {
|
||||
return new java.util.ArrayList<String>(java.util.Arrays.asList(
|
||||
android.hardware.bluetooth.V1_1.IBluetoothHciCallbacks.kInterfaceName,
|
||||
android.hardware.bluetooth.V1_0.IBluetoothHciCallbacks.kInterfaceName,
|
||||
android.internal.hidl.base.V1_0.IBase.kInterfaceName));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(NativeHandle fd, java.util.ArrayList<String> options) {
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String interfaceDescriptor() {
|
||||
return android.hardware.bluetooth.V1_1.IBluetoothHciCallbacks.kInterfaceName;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final java.util.ArrayList<byte[/* 32 */]> getHashChain() {
|
||||
return new java.util.ArrayList<byte[/* 32 */]>(java.util.Arrays.asList(
|
||||
new byte[/* 32 */]{64,-85,44,104,102,-63,-115,50,-70,-10,-28,-98,48,83,-108,-98,121,96,31,86,-106,58,121,30,-109,-26,-117,-98,-31,-113,113,-115} /* 40ab2c6866c18d32baf6e49e3053949e79601f56963a791e93e68b9ee18f718d */,
|
||||
new byte[/* 32 */]{-125,95,65,-66,34,-127,-65,-78,47,62,51,-58,-6,-121,11,-34,123,-62,30,55,-27,-49,-70,-7,-93,111,-1,23,6,50,-9,84} /* 835f41be2281bfb22f3e33c6fa870bde7bc21e37e5cfbaf9a36fff170632f754 */,
|
||||
new byte[/* 32 */]{-20,127,-41,-98,-48,45,-6,-123,-68,73,-108,38,-83,-82,62,-66,35,-17,5,36,-13,-51,105,87,19,-109,36,-72,59,24,-54,76} /* ec7fd79ed02dfa85bc499426adae3ebe23ef0524f3cd6957139324b83b18ca4c */));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setHALInstrumentation() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean linkToDeath(IHwBinder.DeathRecipient recipient, long cookie) {
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void ping() {
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final android.internal.hidl.base.V1_0.DebugInfo getDebugInfo() {
|
||||
android.internal.hidl.base.V1_0.DebugInfo info = new android.internal.hidl.base.V1_0.DebugInfo();
|
||||
info.pid = HidlSupport.getPidIfSharable();
|
||||
info.ptr = 0;
|
||||
info.arch = android.internal.hidl.base.V1_0.DebugInfo.Architecture.UNKNOWN;
|
||||
return info;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void notifySyspropsChanged() {
|
||||
HwBinder.enableInstrumentation();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean unlinkToDeath(IHwBinder.DeathRecipient recipient) {
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public IHwInterface queryLocalInterface(String descriptor) {
|
||||
if (kInterfaceName.equals(descriptor)) {
|
||||
return this;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void registerAsService(String serviceName) throws android.os.RemoteException {
|
||||
registerService(serviceName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.interfaceDescriptor() + "@Stub";
|
||||
}
|
||||
|
||||
//@Override
|
||||
public void onTransact(int _hidl_code, HwParcel _hidl_request, final HwParcel _hidl_reply, int _hidl_flags)
|
||||
throws android.os.RemoteException {
|
||||
switch (_hidl_code) {
|
||||
case 1 /* initializationComplete */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.hardware.bluetooth.V1_0.IBluetoothHciCallbacks.kInterfaceName);
|
||||
|
||||
int status = _hidl_request.readInt32();
|
||||
initializationComplete(status);
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 2 /* hciEventReceived */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.hardware.bluetooth.V1_0.IBluetoothHciCallbacks.kInterfaceName);
|
||||
|
||||
java.util.ArrayList<Byte> event = _hidl_request.readInt8Vector();
|
||||
hciEventReceived(event);
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 3 /* aclDataReceived */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.hardware.bluetooth.V1_0.IBluetoothHciCallbacks.kInterfaceName);
|
||||
|
||||
java.util.ArrayList<Byte> data = _hidl_request.readInt8Vector();
|
||||
aclDataReceived(data);
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 4 /* scoDataReceived */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.hardware.bluetooth.V1_0.IBluetoothHciCallbacks.kInterfaceName);
|
||||
|
||||
java.util.ArrayList<Byte> data = _hidl_request.readInt8Vector();
|
||||
scoDataReceived(data);
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 5 /* isoDataReceived */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.hardware.bluetooth.V1_1.IBluetoothHciCallbacks.kInterfaceName);
|
||||
|
||||
java.util.ArrayList<Byte> data = _hidl_request.readInt8Vector();
|
||||
isoDataReceived(data);
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 256067662 /* interfaceChain */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
java.util.ArrayList<String> _hidl_out_descriptors = interfaceChain();
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
_hidl_reply.writeStringVector(_hidl_out_descriptors);
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 256131655 /* debug */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
NativeHandle fd = _hidl_request.readNativeHandle();
|
||||
java.util.ArrayList<String> options = _hidl_request.readStringVector();
|
||||
debug(fd, options);
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 256136003 /* interfaceDescriptor */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
String _hidl_out_descriptor = interfaceDescriptor();
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
_hidl_reply.writeString(_hidl_out_descriptor);
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 256398152 /* getHashChain */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
java.util.ArrayList<byte[/* 32 */]> _hidl_out_hashchain = getHashChain();
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
{
|
||||
HwBlob _hidl_blob = new HwBlob(16 /* size */);
|
||||
{
|
||||
int _hidl_vec_size = _hidl_out_hashchain.size();
|
||||
_hidl_blob.putInt32(0 /* offset */ + 8 /* offsetof(hidl_vec<T>, mSize) */, _hidl_vec_size);
|
||||
_hidl_blob.putBool(0 /* offset */ + 12 /* offsetof(hidl_vec<T>, mOwnsBuffer) */, false);
|
||||
HwBlob childBlob = new HwBlob((int)(_hidl_vec_size * 32));
|
||||
for (int _hidl_index_0 = 0; _hidl_index_0 < _hidl_vec_size; ++_hidl_index_0) {
|
||||
{
|
||||
long _hidl_array_offset_1 = _hidl_index_0 * 32;
|
||||
byte[] _hidl_array_item_1 = (byte[/* 32 */]) _hidl_out_hashchain.get(_hidl_index_0);
|
||||
|
||||
if (_hidl_array_item_1 == null || _hidl_array_item_1.length != 32) {
|
||||
throw new IllegalArgumentException("Array element is not of the expected length");
|
||||
}
|
||||
|
||||
childBlob.putInt8Array(_hidl_array_offset_1, _hidl_array_item_1);
|
||||
_hidl_array_offset_1 += 32 * 1;
|
||||
}
|
||||
}
|
||||
_hidl_blob.putBlob(0 /* offset */ + 0 /* offsetof(hidl_vec<T>, mBuffer) */, childBlob);
|
||||
}
|
||||
_hidl_reply.writeBuffer(_hidl_blob);
|
||||
}
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 256462420 /* setHALInstrumentation */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
setHALInstrumentation();
|
||||
break;
|
||||
}
|
||||
|
||||
case 256660548 /* linkToDeath */:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
case 256921159 /* ping */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
ping();
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 257049926 /* getDebugInfo */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
android.internal.hidl.base.V1_0.DebugInfo _hidl_out_info = getDebugInfo();
|
||||
_hidl_reply.writeStatus(HwParcel.STATUS_SUCCESS);
|
||||
((android.internal.hidl.base.V1_0.DebugInfo) _hidl_out_info).writeToParcel(_hidl_reply);
|
||||
_hidl_reply.send();
|
||||
break;
|
||||
}
|
||||
|
||||
case 257120595 /* notifySyspropsChanged */:
|
||||
{
|
||||
_hidl_request.enforceInterface(android.internal.hidl.base.V1_0.IBase.kInterfaceName);
|
||||
|
||||
notifySyspropsChanged();
|
||||
break;
|
||||
}
|
||||
|
||||
case 257250372 /* unlinkToDeath */:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,260 @@
|
||||
package com.github.google.bumble.remotehci;
|
||||
|
||||
import android.hardware.bluetooth.V1_0.Status;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
public interface HciHal {
|
||||
public enum Status {
|
||||
SUCCESS("SUCCESS"),
|
||||
ALREADY_INITIALIZED("ALREADY_INITIALIZED"),
|
||||
UNABLE_TO_OPEN_INTERFACE("UNABLE_TO_OPEN_INTERFACE"),
|
||||
INITIALIZATION_ERROR("INITIALIZATION_ERROR"),
|
||||
TRANSPORT_ERROR("TRANSPORT_ERROR"),
|
||||
UNKNOWN("UNKNOWN");
|
||||
|
||||
public final String label;
|
||||
|
||||
private Status(String label) {
|
||||
this.label = label;
|
||||
}
|
||||
}
|
||||
static final String TAG = "HciHal";
|
||||
public static HciHal create(HciHalCallback hciCallbacks) {
|
||||
// First try HIDL
|
||||
HciHal hciHal = HciHidlHal.create(hciCallbacks);
|
||||
if (hciHal != null) {
|
||||
Log.d(TAG, "Found HIDL HAL");
|
||||
return hciHal;
|
||||
}
|
||||
|
||||
// Then try AIDL
|
||||
hciHal = HciAidlHal.create(hciCallbacks);
|
||||
if (hciHal != null) {
|
||||
Log.d(TAG, "Found AIDL HAL");
|
||||
return hciHal;
|
||||
}
|
||||
|
||||
Log.d(TAG, "No HAL found");
|
||||
return null;
|
||||
}
|
||||
|
||||
public Status initialize() throws RemoteException, InterruptedException;
|
||||
public void sendPacket(HciPacket.Type type, byte[] packet);
|
||||
}
|
||||
|
||||
class HciHidlHal extends android.hardware.bluetooth.V1_0.IBluetoothHciCallbacks.Stub implements HciHal {
|
||||
private static final String TAG = "HciHidlHal";
|
||||
private final android.hardware.bluetooth.V1_0.IBluetoothHci mHciService;
|
||||
private final HciHalCallback mHciCallbacks;
|
||||
private int mInitializationStatus = -1;
|
||||
|
||||
|
||||
public static HciHidlHal create(HciHalCallback hciCallbacks) {
|
||||
// Get the HAL service.
|
||||
android.hardware.bluetooth.V1_0.IBluetoothHci hciService;
|
||||
try {
|
||||
hciService = android.hardware.bluetooth.V1_0.IBluetoothHci.getService(true);
|
||||
} catch (NoSuchElementException e) {
|
||||
Log.d(TAG, "HIDL HAL V1.0 not found");
|
||||
return null;
|
||||
} catch (android.os.RemoteException e) {
|
||||
Log.w(TAG, "Exception from getService: " + e);
|
||||
return null;
|
||||
}
|
||||
Log.d(TAG, "Found HIDL HAL V1.0");
|
||||
return new HciHidlHal(hciService, hciCallbacks);
|
||||
}
|
||||
|
||||
private HciHidlHal(android.hardware.bluetooth.V1_0.IBluetoothHci hciService, HciHalCallback hciCallbacks) {
|
||||
mHciService = hciService;
|
||||
mHciCallbacks = hciCallbacks;
|
||||
}
|
||||
|
||||
public Status initialize() throws RemoteException, InterruptedException {
|
||||
// Trigger the initialization.
|
||||
mHciService.initialize(this);
|
||||
|
||||
// Wait for the initialization to complete.
|
||||
Log.d(TAG, "Waiting for initialization status...");
|
||||
synchronized (this) {
|
||||
while (mInitializationStatus == -1) {
|
||||
wait();
|
||||
}
|
||||
}
|
||||
|
||||
// Map the status code.
|
||||
switch (mInitializationStatus) {
|
||||
case android.hardware.bluetooth.V1_0.Status.SUCCESS:
|
||||
return Status.SUCCESS;
|
||||
|
||||
case android.hardware.bluetooth.V1_0.Status.TRANSPORT_ERROR:
|
||||
return Status.TRANSPORT_ERROR;
|
||||
|
||||
case android.hardware.bluetooth.V1_0.Status.INITIALIZATION_ERROR:
|
||||
return Status.INITIALIZATION_ERROR;
|
||||
|
||||
default:
|
||||
return Status.UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPacket(HciPacket.Type type, byte[] packet) {
|
||||
ArrayList<Byte> data = HciPacket.byteArrayToList(packet);
|
||||
|
||||
try {
|
||||
switch (type) {
|
||||
case COMMAND:
|
||||
mHciService.sendHciCommand(data);
|
||||
break;
|
||||
|
||||
case ACL_DATA:
|
||||
mHciService.sendAclData(data);
|
||||
break;
|
||||
|
||||
case SCO_DATA:
|
||||
mHciService.sendScoData(data);
|
||||
break;
|
||||
}
|
||||
} catch (RemoteException error) {
|
||||
Log.w(TAG, "failed to forward packet: " + error);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void initializationComplete(int status) throws RemoteException {
|
||||
mInitializationStatus = status;
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hciEventReceived(ArrayList<Byte> event) throws RemoteException {
|
||||
byte[] packet = HciPacket.listToByteArray(event);
|
||||
mHciCallbacks.onPacket(HciPacket.Type.EVENT, packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void aclDataReceived(ArrayList<Byte> data) throws RemoteException {
|
||||
byte[] packet = HciPacket.listToByteArray(data);
|
||||
mHciCallbacks.onPacket(HciPacket.Type.ACL_DATA, packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scoDataReceived(ArrayList<Byte> data) throws RemoteException {
|
||||
byte[] packet = HciPacket.listToByteArray(data);
|
||||
mHciCallbacks.onPacket(HciPacket.Type.SCO_DATA, packet);
|
||||
}
|
||||
}
|
||||
|
||||
class HciAidlHal extends android.hardware.bluetooth.IBluetoothHciCallbacks.Stub implements HciHal {
|
||||
private static final String TAG = "HciAidlHal";
|
||||
private final android.hardware.bluetooth.IBluetoothHci mHciService;
|
||||
private final HciHalCallback mHciCallbacks;
|
||||
private int mInitializationStatus = android.hardware.bluetooth.Status.SUCCESS;
|
||||
|
||||
public static HciAidlHal create(HciHalCallback hciCallbacks) {
|
||||
IBinder binder = ServiceManager.getService("android.hardware.bluetooth.IBluetoothHci/default");
|
||||
if (binder == null) {
|
||||
Log.d(TAG, "AIDL HAL not found");
|
||||
return null;
|
||||
}
|
||||
android.hardware.bluetooth.IBluetoothHci hciService = android.hardware.bluetooth.IBluetoothHci.Stub.asInterface(binder);
|
||||
return new HciAidlHal(hciService, hciCallbacks);
|
||||
}
|
||||
|
||||
private HciAidlHal(android.hardware.bluetooth.IBluetoothHci hciService, HciHalCallback hciCallbacks) {
|
||||
super();
|
||||
mHciService = hciService;
|
||||
mHciCallbacks = hciCallbacks;
|
||||
}
|
||||
|
||||
public Status initialize() throws RemoteException, InterruptedException {
|
||||
// Trigger the initialization.
|
||||
mHciService.initialize(this);
|
||||
|
||||
// Wait for the initialization to complete.
|
||||
Log.d(TAG, "Waiting for initialization status...");
|
||||
synchronized (this) {
|
||||
while (mInitializationStatus == -1) {
|
||||
wait();
|
||||
}
|
||||
}
|
||||
|
||||
// Map the status code.
|
||||
switch (mInitializationStatus) {
|
||||
case android.hardware.bluetooth.Status.SUCCESS:
|
||||
return Status.SUCCESS;
|
||||
|
||||
case android.hardware.bluetooth.Status.ALREADY_INITIALIZED:
|
||||
return Status.ALREADY_INITIALIZED;
|
||||
|
||||
case android.hardware.bluetooth.Status.UNABLE_TO_OPEN_INTERFACE:
|
||||
return Status.UNABLE_TO_OPEN_INTERFACE;
|
||||
|
||||
case android.hardware.bluetooth.Status.HARDWARE_INITIALIZATION_ERROR:
|
||||
return Status.INITIALIZATION_ERROR;
|
||||
|
||||
default:
|
||||
return Status.UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
// HciHal methods.
|
||||
@Override
|
||||
public void sendPacket(HciPacket.Type type, byte[] packet) {
|
||||
try {
|
||||
switch (type) {
|
||||
case COMMAND:
|
||||
mHciService.sendHciCommand(packet);
|
||||
break;
|
||||
|
||||
case ACL_DATA:
|
||||
mHciService.sendAclData(packet);
|
||||
break;
|
||||
|
||||
case SCO_DATA:
|
||||
mHciService.sendScoData(packet);
|
||||
break;
|
||||
|
||||
case ISO_DATA:
|
||||
mHciService.sendIsoData(packet);
|
||||
break;
|
||||
}
|
||||
} catch (RemoteException error) {
|
||||
Log.w(TAG, "failed to forward packet: " + error);
|
||||
}
|
||||
}
|
||||
|
||||
// IBluetoothHciCallbacks methods.
|
||||
@Override
|
||||
public synchronized void initializationComplete(int status) throws RemoteException {
|
||||
mInitializationStatus = status;
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hciEventReceived(byte[] event) throws RemoteException {
|
||||
mHciCallbacks.onPacket(HciPacket.Type.EVENT, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void aclDataReceived(byte[] data) throws RemoteException {
|
||||
mHciCallbacks.onPacket(HciPacket.Type.ACL_DATA, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scoDataReceived(byte[] data) throws RemoteException {
|
||||
mHciCallbacks.onPacket(HciPacket.Type.SCO_DATA, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void isoDataReceived(byte[] data) throws RemoteException {
|
||||
mHciCallbacks.onPacket(HciPacket.Type.ISO_DATA, data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.github.google.bumble.remotehci;
|
||||
|
||||
public interface HciHalCallback {
|
||||
public void onPacket(HciPacket.Type type, byte[] packet);
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.github.google.bumble.remotehci;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class HciPacket {
|
||||
public enum Type {
|
||||
COMMAND((byte) 1),
|
||||
ACL_DATA((byte) 2),
|
||||
SCO_DATA((byte) 3),
|
||||
EVENT((byte) 4),
|
||||
ISO_DATA((byte)5);
|
||||
|
||||
final byte value;
|
||||
final int lengthSize;
|
||||
final int lengthOffset;
|
||||
|
||||
Type(byte value) throws IllegalArgumentException {
|
||||
switch (value) {
|
||||
case 1:
|
||||
case 3:
|
||||
lengthSize = 1;
|
||||
lengthOffset = 2;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
case 5:
|
||||
lengthSize = 2;
|
||||
lengthOffset = 2;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
lengthSize = 1;
|
||||
lengthOffset = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new IllegalArgumentException();
|
||||
|
||||
}
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
static Type fromValue(byte value) {
|
||||
for (Type type : values()) {
|
||||
if (type.value == value) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static ArrayList<Byte> byteArrayToList(byte[] byteArray) {
|
||||
ArrayList<Byte> list = new ArrayList<>();
|
||||
list.ensureCapacity(byteArray.length);
|
||||
for (byte x : byteArray) {
|
||||
list.add(x);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public static byte[] listToByteArray(ArrayList<Byte> byteList) {
|
||||
byte[] byteArray = new byte[byteList.size()];
|
||||
for (int i = 0; i < byteList.size(); i++) {
|
||||
byteArray[i] = byteList.get(i);
|
||||
}
|
||||
return byteArray;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package com.github.google.bumble.remotehci;
|
||||
|
||||
import static java.lang.Integer.min;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
|
||||
class HciParser {
|
||||
Sink sink;
|
||||
State state;
|
||||
int bytesNeeded;
|
||||
ByteArrayOutputStream packet = new ByteArrayOutputStream();
|
||||
HciPacket.Type packetType;
|
||||
|
||||
HciParser(Sink sink) {
|
||||
this.sink = sink;
|
||||
reset();
|
||||
}
|
||||
|
||||
void feedData(byte[] data, int dataSize) {
|
||||
int dataOffset = 0;
|
||||
int dataLeft = dataSize;
|
||||
|
||||
while (dataLeft > 0 && bytesNeeded > 0) {
|
||||
int consumed = min(dataLeft, bytesNeeded);
|
||||
if (state != State.NEED_TYPE) {
|
||||
packet.write(data, dataOffset, consumed);
|
||||
}
|
||||
bytesNeeded -= consumed;
|
||||
|
||||
if (bytesNeeded == 0) {
|
||||
if (state == State.NEED_TYPE) {
|
||||
packetType = HciPacket.Type.fromValue(data[dataOffset]);
|
||||
if (packetType == null) {
|
||||
throw new InvalidFormatException();
|
||||
}
|
||||
bytesNeeded = packetType.lengthOffset + packetType.lengthSize;
|
||||
state = State.NEED_LENGTH;
|
||||
} else if (state == State.NEED_LENGTH) {
|
||||
ByteBuffer lengthBuffer =
|
||||
ByteBuffer.wrap(packet.toByteArray())
|
||||
.order(ByteOrder.LITTLE_ENDIAN);
|
||||
bytesNeeded = packetType.lengthSize == 1 ?
|
||||
lengthBuffer.get(packetType.lengthOffset) & 0xFF :
|
||||
lengthBuffer.getShort(packetType.lengthOffset) & 0xFFFF;
|
||||
state = State.NEED_BODY;
|
||||
}
|
||||
|
||||
// Emit a packet if one is complete.
|
||||
if (state == State.NEED_BODY && bytesNeeded == 0) {
|
||||
if (sink != null) {
|
||||
sink.onPacket(packetType, packet.toByteArray());
|
||||
}
|
||||
|
||||
reset();
|
||||
}
|
||||
}
|
||||
|
||||
dataOffset += consumed;
|
||||
dataLeft -= consumed;
|
||||
}
|
||||
}
|
||||
|
||||
void reset() {
|
||||
state = State.NEED_TYPE;
|
||||
bytesNeeded = 1;
|
||||
packet.reset();
|
||||
packetType = null;
|
||||
}
|
||||
|
||||
enum State {
|
||||
NEED_TYPE, NEED_LENGTH, NEED_BODY
|
||||
}
|
||||
|
||||
interface Sink {
|
||||
void onPacket(HciPacket.Type type, byte[] packet);
|
||||
}
|
||||
|
||||
static class InvalidFormatException extends RuntimeException {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
package com.github.google.bumble.remotehci;
|
||||
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class HciProxy {
|
||||
private static final String TAG = "HciProxy";
|
||||
private final HciServer mServer;
|
||||
private final Listener mListener;
|
||||
private int mCommandPacketsReceived;
|
||||
private int mAclPacketsReceived;
|
||||
private int mScoPacketsReceived;
|
||||
private int mEventPacketsSent;
|
||||
private int mAclPacketsSent;
|
||||
private int mScoPacketsSent;
|
||||
|
||||
HciProxy(int port, Listener listener) throws HalException {
|
||||
this.mListener = listener;
|
||||
|
||||
// Instantiate a HAL to communicate with the hardware.
|
||||
HciHal hciHal = HciHal.create(new HciHalCallback() {
|
||||
@Override
|
||||
public void onPacket(HciPacket.Type type, byte[] packet) {
|
||||
mServer.sendPacket(type, packet);
|
||||
|
||||
switch (type) {
|
||||
case EVENT:
|
||||
mEventPacketsSent += 1;
|
||||
break;
|
||||
|
||||
case ACL_DATA:
|
||||
mAclPacketsSent += 1;
|
||||
break;
|
||||
|
||||
case SCO_DATA:
|
||||
mScoPacketsSent += 1;
|
||||
break;
|
||||
}
|
||||
updateHciPacketCount();
|
||||
}
|
||||
});
|
||||
if (hciHal == null) {
|
||||
String message = "Could not instantiate a HAL instance";
|
||||
Log.w(TAG, message);
|
||||
throw new HalException(message);
|
||||
}
|
||||
|
||||
// Initialize the HAL.
|
||||
HciHal.Status status = null;
|
||||
try {
|
||||
status = hciHal.initialize();
|
||||
} catch (RemoteException | InterruptedException e) {
|
||||
throw new HalException("Exception while initializing");
|
||||
}
|
||||
if (status != HciHal.Status.SUCCESS) {
|
||||
String message = "HAL initialization failed: " + status.label;
|
||||
Log.w(TAG, message);
|
||||
throw new HalException(message);
|
||||
}
|
||||
|
||||
// Create a server to accept clients.
|
||||
mServer = new HciServer(port, new HciServer.Listener() {
|
||||
@Override
|
||||
public void onHostConnectionState(boolean connected) {
|
||||
mListener.onHostConnectionState(connected);
|
||||
if (connected) {
|
||||
mCommandPacketsReceived = 0;
|
||||
mAclPacketsReceived = 0;
|
||||
mScoPacketsReceived = 0;
|
||||
mEventPacketsSent = 0;
|
||||
mAclPacketsSent = 0;
|
||||
mScoPacketsSent = 0;
|
||||
updateHciPacketCount();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessage(String message) {
|
||||
listener.onMessage(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacket(HciPacket.Type type, byte[] packet) {
|
||||
Log.d(TAG, String.format("onPacket: type=%s, size=%d", type, packet.length));
|
||||
hciHal.sendPacket(type, packet);
|
||||
|
||||
switch (type) {
|
||||
case COMMAND:
|
||||
mCommandPacketsReceived += 1;
|
||||
break;
|
||||
|
||||
case ACL_DATA:
|
||||
mAclPacketsReceived += 1;
|
||||
break;
|
||||
|
||||
case SCO_DATA:
|
||||
mScoPacketsReceived += 1;
|
||||
break;
|
||||
}
|
||||
updateHciPacketCount();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void run() throws IOException {
|
||||
mServer.run();
|
||||
}
|
||||
|
||||
private void updateHciPacketCount() {
|
||||
mListener.onHciPacketCountChange(
|
||||
mCommandPacketsReceived,
|
||||
mAclPacketsReceived,
|
||||
mScoPacketsReceived,
|
||||
mEventPacketsSent,
|
||||
mAclPacketsSent,
|
||||
mScoPacketsSent
|
||||
);
|
||||
}
|
||||
|
||||
public interface Listener {
|
||||
void onHostConnectionState(boolean connected);
|
||||
|
||||
void onHciPacketCountChange(
|
||||
int commandPacketsReceived,
|
||||
int aclPacketsReceived,
|
||||
int scoPacketsReceived,
|
||||
int eventPacketsSent,
|
||||
int aclPacketsSent,
|
||||
int scoPacketsSent
|
||||
);
|
||||
|
||||
void onMessage(String message);
|
||||
}
|
||||
|
||||
public static class HalException extends RuntimeException {
|
||||
public final String message;
|
||||
public HalException(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package com.github.google.bumble.remotehci;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
|
||||
|
||||
public class HciServer {
|
||||
private static final String TAG = "HciServer";
|
||||
private static final int BUFFER_SIZE = 1024;
|
||||
private final int mPort;
|
||||
private final Listener mListener;
|
||||
private OutputStream mOutputStream;
|
||||
|
||||
public interface Listener extends HciParser.Sink {
|
||||
void onHostConnectionState(boolean connected);
|
||||
void onMessage(String message);
|
||||
}
|
||||
|
||||
HciServer(int port, Listener listener) {
|
||||
this.mPort = port;
|
||||
this.mListener = listener;
|
||||
}
|
||||
|
||||
public void run() throws IOException {
|
||||
for (;;) {
|
||||
try {
|
||||
loop();
|
||||
} catch (IOException error) {
|
||||
mListener.onMessage("Cannot listen on port " + mPort);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void loop() throws IOException {
|
||||
mListener.onHostConnectionState(false);
|
||||
try (ServerSocket serverSocket = new ServerSocket(mPort)) {
|
||||
mListener.onMessage("Waiting for connection on port " + serverSocket.getLocalPort());
|
||||
try (Socket clientSocket = serverSocket.accept()) {
|
||||
mListener.onHostConnectionState(true);
|
||||
mListener.onMessage("Connected");
|
||||
HciParser parser = new HciParser(mListener);
|
||||
InputStream inputStream = clientSocket.getInputStream();
|
||||
synchronized (this) {
|
||||
mOutputStream = clientSocket.getOutputStream();
|
||||
}
|
||||
byte[] buffer = new byte[BUFFER_SIZE];
|
||||
|
||||
try {
|
||||
for (; ; ) {
|
||||
int bytesRead = inputStream.read(buffer);
|
||||
if (bytesRead < 0) {
|
||||
Log.d(TAG, "end of stream");
|
||||
break;
|
||||
}
|
||||
parser.feedData(buffer, bytesRead);
|
||||
}
|
||||
} catch (IOException error) {
|
||||
Log.d(TAG, "exception in read loop: " + error);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
synchronized (this) {
|
||||
mOutputStream = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void sendPacket(HciPacket.Type type, byte[] packet) {
|
||||
// Create a combined data buffer so we can write it out in a single call.
|
||||
byte[] data = new byte[packet.length + 1];
|
||||
data[0] = type.value;
|
||||
System.arraycopy(packet, 0, data, 1, packet.length);
|
||||
|
||||
synchronized (this) {
|
||||
if (mOutputStream != null) {
|
||||
try {
|
||||
mOutputStream.write(data);
|
||||
} catch (IOException error) {
|
||||
Log.w(TAG, "failed to write packet: " + error);
|
||||
}
|
||||
} else {
|
||||
Log.d(TAG, "no client, dropping packet");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,229 @@
|
||||
package com.github.google.bumble.remotehci
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.os.Bundle
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.text.KeyboardActions
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.Divider
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextField
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.github.google.bumble.remotehci.HciProxy.HalException
|
||||
import com.github.google.bumble.remotehci.ui.theme.RemoteHCITheme
|
||||
import java.io.IOException
|
||||
import java.util.logging.Logger
|
||||
import kotlin.concurrent.thread
|
||||
|
||||
const val DEFAULT_TCP_PORT = 9993
|
||||
const val TCP_PORT_PREF_KEY = "tcp_port"
|
||||
|
||||
class AppViewModel : ViewModel(), HciProxy.Listener {
|
||||
private var preferences: SharedPreferences? = null
|
||||
var tcpPort by mutableStateOf(DEFAULT_TCP_PORT)
|
||||
var canStart by mutableStateOf(true)
|
||||
var message by mutableStateOf("")
|
||||
var hostConnected by mutableStateOf(false)
|
||||
var hciCommandPacketsReceived by mutableStateOf(0)
|
||||
var hciAclPacketsReceived by mutableStateOf(0)
|
||||
var hciScoPacketsReceived by mutableStateOf(0)
|
||||
var hciEventPacketsSent by mutableStateOf(0)
|
||||
var hciAclPacketsSent by mutableStateOf(0)
|
||||
var hciScoPacketsSent by mutableStateOf(0)
|
||||
|
||||
fun loadPreferences(preferences: SharedPreferences) {
|
||||
this.preferences = preferences
|
||||
val savedTcpPortString = preferences.getString(TCP_PORT_PREF_KEY, null)
|
||||
if (savedTcpPortString != null) {
|
||||
val savedTcpPortInt = savedTcpPortString.toIntOrNull()
|
||||
if (savedTcpPortInt != null) {
|
||||
tcpPort = savedTcpPortInt
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun updateTcpPort(tcpPort: Int) {
|
||||
this.tcpPort = tcpPort
|
||||
|
||||
// Save the port to the preferences
|
||||
with (preferences!!.edit()) {
|
||||
putString(TCP_PORT_PREF_KEY, tcpPort.toString())
|
||||
apply()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onHostConnectionState(connected: Boolean) {
|
||||
hostConnected = connected
|
||||
}
|
||||
|
||||
override fun onHciPacketCountChange(
|
||||
commandPacketsReceived: Int,
|
||||
aclPacketsReceived: Int,
|
||||
scoPacketsReceived: Int,
|
||||
eventPacketsSent: Int,
|
||||
aclPacketsSent: Int,
|
||||
scoPacketsSent: Int
|
||||
) {
|
||||
hciCommandPacketsReceived = commandPacketsReceived
|
||||
hciAclPacketsReceived = aclPacketsReceived
|
||||
hciScoPacketsReceived = scoPacketsReceived
|
||||
hciEventPacketsSent = eventPacketsSent
|
||||
hciAclPacketsSent = aclPacketsSent
|
||||
hciScoPacketsSent = scoPacketsSent
|
||||
|
||||
}
|
||||
|
||||
override fun onMessage(message: String) {
|
||||
this.message = message
|
||||
}
|
||||
}
|
||||
|
||||
class MainActivity : ComponentActivity() {
|
||||
private val log = Logger.getLogger(MainActivity::class.java.name)
|
||||
private val appViewModel = AppViewModel()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
appViewModel.loadPreferences(getPreferences(Context.MODE_PRIVATE))
|
||||
|
||||
val tcpPort = intent.getIntExtra("port", -1)
|
||||
if (tcpPort >= 0) {
|
||||
appViewModel.tcpPort = tcpPport
|
||||
}
|
||||
|
||||
setContent {
|
||||
MainView(appViewModel, ::startProxy)
|
||||
}
|
||||
|
||||
if (intent.getBooleanExtra("autostart", false)) {
|
||||
startProxy()
|
||||
}
|
||||
}
|
||||
|
||||
private fun startProxy() {
|
||||
// Run the proxy in a thread.
|
||||
appViewModel.message = ""
|
||||
thread {
|
||||
log.info("HCI Proxy thread starting")
|
||||
appViewModel.canStart = false
|
||||
try {
|
||||
val hciProxy = HciProxy(appViewModel.tcpPort, appViewModel)
|
||||
hciProxy.run()
|
||||
} catch (error: IOException) {
|
||||
log.warning("Exception while running HCI Server: $error")
|
||||
} catch (error: HalException) {
|
||||
log.warning("HAL exception: ${error.message}")
|
||||
appViewModel.message = "Cannot bind to HAL (${error.message}). You may need to use the command 'setenforce 0' in a root adb shell."
|
||||
}
|
||||
log.info("HCI Proxy thread ended")
|
||||
appViewModel.canStart = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ActionButton(text: String, onClick: () -> Unit, enabled: Boolean) {
|
||||
Button(onClick = onClick, enabled = enabled) {
|
||||
Text(text = text)
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalComposeUiApi::class)
|
||||
@Composable
|
||||
fun MainView(appViewModel: AppViewModel, startProxy: () -> Unit) {
|
||||
RemoteHCITheme {
|
||||
// A surface container using the 'background' color from the theme
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background
|
||||
) {
|
||||
Column(modifier = Modifier.padding(horizontal = 16.dp)) {
|
||||
Text(
|
||||
text = "Bumble Remote HCI",
|
||||
fontSize = 24.sp,
|
||||
fontWeight = FontWeight.Bold,
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
Divider()
|
||||
Text(
|
||||
text = appViewModel.message
|
||||
)
|
||||
Divider()
|
||||
val keyboardController = LocalSoftwareKeyboardController.current
|
||||
TextField(
|
||||
label = {
|
||||
Text(text = "TCP Port")
|
||||
},
|
||||
value = appViewModel.tcpPort.toString(),
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
keyboardOptions = KeyboardOptions.Default.copy(keyboardType = KeyboardType.Number, imeAction = ImeAction.Done),
|
||||
onValueChange = {
|
||||
if (it.isNotEmpty()) {
|
||||
val tcpPort = it.toIntOrNull()
|
||||
if (tcpPort != null) {
|
||||
appViewModel.updateTcpPort(tcpPort)
|
||||
}
|
||||
}
|
||||
},
|
||||
keyboardActions = KeyboardActions(
|
||||
onDone = {keyboardController?.hide()}
|
||||
)
|
||||
)
|
||||
Divider()
|
||||
val connectState = if (appViewModel.hostConnected) "CONNECTED" else "DISCONNECTED"
|
||||
Text(
|
||||
text = "HOST: $connectState",
|
||||
modifier = Modifier.background(color = if (appViewModel.hostConnected) Color.Green else Color.Red),
|
||||
color = Color.Black
|
||||
)
|
||||
Divider()
|
||||
Text(
|
||||
text = "Command Packets Received: ${appViewModel.hciCommandPacketsReceived}"
|
||||
)
|
||||
Text(
|
||||
text = "ACL Packets Received: ${appViewModel.hciAclPacketsReceived}"
|
||||
)
|
||||
Text(
|
||||
text = "SCO Packets Received: ${appViewModel.hciScoPacketsReceived}"
|
||||
)
|
||||
Text(
|
||||
text = "Event Packets Sent: ${appViewModel.hciEventPacketsSent}"
|
||||
)
|
||||
Text(
|
||||
text = "ACL Packets Sent: ${appViewModel.hciAclPacketsSent}"
|
||||
)
|
||||
Text(
|
||||
text = "SCO Packets Sent: ${appViewModel.hciScoPacketsSent}"
|
||||
)
|
||||
Divider()
|
||||
ActionButton(
|
||||
text = "Start", onClick = startProxy, enabled = appViewModel.canStart
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.github.google.bumble.remotehci.ui.theme
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
||||
val Purple80 = Color(0xFFD0BCFF)
|
||||
val PurpleGrey80 = Color(0xFFCCC2DC)
|
||||
val Pink80 = Color(0xFFEFB8C8)
|
||||
|
||||
val Purple40 = Color(0xFF6650a4)
|
||||
val PurpleGrey40 = Color(0xFF625b71)
|
||||
val Pink40 = Color(0xFF7D5260)
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.github.google.bumble.remotehci.ui.theme
|
||||
|
||||
import android.app.Activity
|
||||
import android.os.Build
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.darkColorScheme
|
||||
import androidx.compose.material3.dynamicDarkColorScheme
|
||||
import androidx.compose.material3.dynamicLightColorScheme
|
||||
import androidx.compose.material3.lightColorScheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.SideEffect
|
||||
import androidx.compose.ui.graphics.toArgb
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalView
|
||||
import androidx.core.view.WindowCompat
|
||||
|
||||
private val DarkColorScheme = darkColorScheme(
|
||||
primary = Purple80,
|
||||
secondary = PurpleGrey80,
|
||||
tertiary = Pink80
|
||||
)
|
||||
|
||||
private val LightColorScheme = lightColorScheme(
|
||||
primary = Purple40,
|
||||
secondary = PurpleGrey40,
|
||||
tertiary = Pink40
|
||||
|
||||
/* Other default colors to override
|
||||
background = Color(0xFFFFFBFE),
|
||||
surface = Color(0xFFFFFBFE),
|
||||
onPrimary = Color.White,
|
||||
onSecondary = Color.White,
|
||||
onTertiary = Color.White,
|
||||
onBackground = Color(0xFF1C1B1F),
|
||||
onSurface = Color(0xFF1C1B1F),
|
||||
*/
|
||||
)
|
||||
|
||||
@Composable
|
||||
fun RemoteHCITheme(
|
||||
darkTheme: Boolean = isSystemInDarkTheme(),
|
||||
// Dynamic color is available on Android 12+
|
||||
dynamicColor: Boolean = true,
|
||||
content: @Composable () -> Unit
|
||||
) {
|
||||
val colorScheme = when {
|
||||
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
|
||||
val context = LocalContext.current
|
||||
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
|
||||
}
|
||||
|
||||
darkTheme -> DarkColorScheme
|
||||
else -> LightColorScheme
|
||||
}
|
||||
val view = LocalView.current
|
||||
if (!view.isInEditMode) {
|
||||
SideEffect {
|
||||
val window = (view.context as Activity).window
|
||||
window.statusBarColor = colorScheme.primary.toArgb()
|
||||
WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme
|
||||
}
|
||||
}
|
||||
|
||||
MaterialTheme(
|
||||
colorScheme = colorScheme,
|
||||
typography = Typography,
|
||||
content = content
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.github.google.bumble.remotehci.ui.theme
|
||||
|
||||
import androidx.compose.material3.Typography
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.sp
|
||||
|
||||
// Set of Material typography styles to start with
|
||||
val Typography = Typography(
|
||||
bodyLarge = TextStyle(
|
||||
fontFamily = FontFamily.Default,
|
||||
fontWeight = FontWeight.Normal,
|
||||
fontSize = 16.sp,
|
||||
lineHeight = 24.sp,
|
||||
letterSpacing = 0.5.sp
|
||||
)
|
||||
/* Other default text styles to override
|
||||
titleLarge = TextStyle(
|
||||
fontFamily = FontFamily.Default,
|
||||
fontWeight = FontWeight.Normal,
|
||||
fontSize = 22.sp,
|
||||
lineHeight = 28.sp,
|
||||
letterSpacing = 0.sp
|
||||
),
|
||||
labelSmall = TextStyle(
|
||||
fontFamily = FontFamily.Default,
|
||||
fontWeight = FontWeight.Medium,
|
||||
fontSize = 11.sp,
|
||||
lineHeight = 16.sp,
|
||||
letterSpacing = 0.5.sp
|
||||
)
|
||||
*/
|
||||
)
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
||||
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 6.0 KiB |
|
After Width: | Height: | Size: 5.5 KiB |
|
After Width: | Height: | Size: 6.9 KiB |
|
After Width: | Height: | Size: 9.6 KiB |
|
After Width: | Height: | Size: 7.3 KiB |
|
After Width: | Height: | Size: 9.3 KiB |
|
After Width: | Height: | Size: 13 KiB |
10
extras/android/RemoteHCI/app/src/main/res/values/colors.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="purple_200">#FFBB86FC</color>
|
||||
<color name="purple_500">#FF6200EE</color>
|
||||
<color name="purple_700">#FF3700B3</color>
|
||||
<color name="teal_200">#FF03DAC5</color>
|
||||
<color name="teal_700">#FF018786</color>
|
||||
<color name="black">#FF000000</color>
|
||||
<color name="white">#FFFFFFFF</color>
|
||||
</resources>
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="ic_launcher_background">#FFFFFF</color>
|
||||
</resources>
|
||||
@@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<string name="app_name">Remote HCI</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<style name="Theme.RemoteHCI" parent="android:Theme.Material.Light.NoActionBar" />
|
||||
</resources>
|
||||
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
Sample backup rules file; uncomment and customize as necessary.
|
||||
See https://developer.android.com/guide/topics/data/autobackup
|
||||
for details.
|
||||
Note: This file is ignored for devices older that API 31
|
||||
See https://developer.android.com/about/versions/12/backup-restore
|
||||
-->
|
||||
<full-backup-content>
|
||||
<!--
|
||||
<include domain="sharedpref" path="."/>
|
||||
<exclude domain="sharedpref" path="device.xml"/>
|
||||
-->
|
||||
</full-backup-content>
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
Sample data extraction rules file; uncomment and customize as necessary.
|
||||
See https://developer.android.com/about/versions/12/backup-restore#xml-changes
|
||||
for details.
|
||||
-->
|
||||
<data-extraction-rules>
|
||||
<cloud-backup>
|
||||
<!-- TODO: Use <include> and <exclude> to control what is backed up.
|
||||
<include .../>
|
||||
<exclude .../>
|
||||
-->
|
||||
</cloud-backup>
|
||||
<!--
|
||||
<device-transfer>
|
||||
<include .../>
|
||||
<exclude .../>
|
||||
</device-transfer>
|
||||
-->
|
||||
</data-extraction-rules>
|
||||
8
extras/android/RemoteHCI/build.gradle.kts
Normal file
@@ -0,0 +1,8 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed
|
||||
plugins {
|
||||
alias(libs.plugins.androidApplication) apply false
|
||||
alias(libs.plugins.kotlinAndroid) apply false
|
||||
alias(libs.plugins.androidLibrary) apply false
|
||||
}
|
||||
true // Needed to make the Suppress annotation work for the plugins block
|
||||
23
extras/android/RemoteHCI/gradle.properties
Normal file
@@ -0,0 +1,23 @@
|
||||
# Project-wide Gradle settings.
|
||||
# IDE (e.g. Android Studio) users:
|
||||
# Gradle settings configured through the IDE *will override*
|
||||
# any settings specified in this file.
|
||||
# For more details on how to configure your build environment visit
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||
# org.gradle.parallel=true
|
||||
# AndroidX package structure to make it clearer which packages are bundled with the
|
||||
# Android operating system, and which are packaged with your app's APK
|
||||
# https://developer.android.com/topic/libraries/support-library/androidx-rn
|
||||
android.useAndroidX=true
|
||||
# Kotlin code style for this project: "official" or "obsolete":
|
||||
kotlin.code.style=official
|
||||
# Enables namespacing of each library's R class so that its R class includes only the
|
||||
# resources declared in the library itself and none from the library's dependencies,
|
||||
# thereby reducing the size of the R class for that library
|
||||
android.nonTransitiveRClass=true
|
||||
36
extras/android/RemoteHCI/gradle/libs.versions.toml
Normal file
@@ -0,0 +1,36 @@
|
||||
[versions]
|
||||
agp = "8.3.0-alpha05"
|
||||
kotlin = "1.8.10"
|
||||
core-ktx = "1.9.0"
|
||||
junit = "4.13.2"
|
||||
androidx-test-ext-junit = "1.1.5"
|
||||
espresso-core = "3.5.1"
|
||||
lifecycle-runtime-ktx = "2.6.1"
|
||||
activity-compose = "1.7.2"
|
||||
compose-bom = "2023.03.00"
|
||||
appcompat = "1.6.1"
|
||||
material = "1.9.0"
|
||||
|
||||
[libraries]
|
||||
core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "core-ktx" }
|
||||
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
||||
androidx-test-ext-junit = { group = "androidx.test.ext", name = "junit", version.ref = "androidx-test-ext-junit" }
|
||||
espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espresso-core" }
|
||||
lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycle-runtime-ktx" }
|
||||
activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activity-compose" }
|
||||
compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "compose-bom" }
|
||||
ui = { group = "androidx.compose.ui", name = "ui" }
|
||||
ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" }
|
||||
ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
|
||||
ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
|
||||
ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
|
||||
ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
|
||||
material3 = { group = "androidx.compose.material3", name = "material3" }
|
||||
appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
|
||||
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
|
||||
|
||||
[plugins]
|
||||
androidApplication = { id = "com.android.application", version.ref = "agp" }
|
||||
kotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
||||
androidLibrary = { id = "com.android.library", version.ref = "agp" }
|
||||
|
||||
BIN
extras/android/RemoteHCI/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
6
extras/android/RemoteHCI/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
#Sun Aug 06 12:53:26 PDT 2023
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-rc-2-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
185
extras/android/RemoteHCI/gradlew
vendored
Executable file
@@ -0,0 +1,185 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#
|
||||
# Copyright 2015 the original author or authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=`expr $i + 1`
|
||||
done
|
||||
case $i in
|
||||
0) set -- ;;
|
||||
1) set -- "$args0" ;;
|
||||
2) set -- "$args0" "$args1" ;;
|
||||
3) set -- "$args0" "$args1" "$args2" ;;
|
||||
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=`save "$@"`
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
89
extras/android/RemoteHCI/gradlew.bat
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
1
extras/android/RemoteHCI/lib/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
||||
39
extras/android/RemoteHCI/lib/build.gradle.kts
Normal file
@@ -0,0 +1,39 @@
|
||||
@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed
|
||||
plugins {
|
||||
alias(libs.plugins.androidLibrary)
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "com.github.google.bumble"
|
||||
compileSdk = 34
|
||||
|
||||
defaultConfig {
|
||||
minSdk = 26
|
||||
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
consumerProguardFiles("consumer-rules.pro")
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
isMinifyEnabled = false
|
||||
proguardFiles(
|
||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||
"proguard-rules.pro"
|
||||
)
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
implementation(libs.appcompat)
|
||||
implementation(libs.material)
|
||||
testImplementation(libs.junit)
|
||||
androidTestImplementation(libs.androidx.test.ext.junit)
|
||||
androidTestImplementation(libs.espresso.core)
|
||||
}
|
||||
0
extras/android/RemoteHCI/lib/consumer-rules.pro
Normal file
21
extras/android/RemoteHCI/lib/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,17 @@
|
||||
package android.internal.hidl.base.V1_0;
|
||||
|
||||
import android.os.HwParcel;
|
||||
|
||||
public class DebugInfo {
|
||||
public static final class Architecture {
|
||||
public static final int UNKNOWN = 0;
|
||||
}
|
||||
|
||||
public int pid = 0;
|
||||
public long ptr = 0L;
|
||||
public int arch = 0;
|
||||
public final void readFromParcel(HwParcel parcel) {
|
||||
}
|
||||
public final void writeToParcel(HwParcel parcel) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package android.internal.hidl.base.V1_0;
|
||||
|
||||
import android.os.IHwBinder;
|
||||
import android.os.IHwInterface;
|
||||
|
||||
public interface IBase extends IHwInterface {
|
||||
public static final String kInterfaceName = "android.hidl.base@1.0::IBase";
|
||||
|
||||
public static abstract class Stub extends android.os.HwBinder implements IBase {
|
||||
public void onTransact(int _hidl_code, android.os.HwParcel _hidl_request, final android.os.HwParcel _hidl_reply, int _hidl_flags)
|
||||
throws android.os.RemoteException {}
|
||||
}
|
||||
|
||||
public static final class Proxy implements IBase {
|
||||
@Override
|
||||
public IHwBinder asBinder() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package android.os;
|
||||
|
||||
public class HidlSupport {
|
||||
public static boolean interfacesEqual(IHwInterface lft, Object rgt) {
|
||||
return false; // STUB
|
||||
}
|
||||
public static native int getPidIfSharable();
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package android.os;
|
||||
|
||||
public class HwBinder implements IHwBinder {
|
||||
public native final void registerService(String serviceName);
|
||||
public static final IHwBinder getService(
|
||||
String iface,
|
||||
String serviceName) {
|
||||
return null; //STUB
|
||||
}
|
||||
|
||||
public static final IHwBinder getService(
|
||||
String iface,
|
||||
String serviceName,
|
||||
boolean retry) {
|
||||
return null; // STUB
|
||||
}
|
||||
|
||||
public static void enableInstrumentation() {
|
||||
|
||||
}
|
||||
@Override
|
||||
public IHwInterface queryLocalInterface(String descriptor) {
|
||||
return null; // STUB
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transact(int code, HwParcel request, HwParcel reply, int flags) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean linkToDeath(DeathRecipient recipient, long cookie) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean unlinkToDeath(DeathRecipient recipient) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package android.os;
|
||||
|
||||
public class HwBlob {
|
||||
public HwBlob(int size) {}
|
||||
public native final long handle();
|
||||
|
||||
public native final int getInt32(long offset);
|
||||
public native final void putInt32(long offset, int x);
|
||||
public native final void putBool(long offset, boolean x);
|
||||
public native final void putInt8Array(long offset, byte[] x);
|
||||
public native final void putBlob(long offset, HwBlob blob);
|
||||
public native final void copyToInt8Array(long offset, byte[] array, int size);
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
package android.os;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class HwParcel {
|
||||
public static final int STATUS_SUCCESS = 0;
|
||||
public native final void writeInterfaceToken(String interfaceName);
|
||||
public native final void writeBool(boolean val);
|
||||
public native final void writeInt8(byte val);
|
||||
public native final void writeInt16(short val);
|
||||
public native final void writeInt32(int val);
|
||||
public native final void writeInt64(long val);
|
||||
public native final void writeFloat(float val);
|
||||
public native final void writeDouble(double val);
|
||||
public native final void writeString(String val);
|
||||
public native final void writeNativeHandle(NativeHandle val);
|
||||
private native final void writeBoolVector(boolean[] val);
|
||||
private native final void writeInt8Vector(byte[] val);
|
||||
private native final void writeInt16Vector(short[] val);
|
||||
private native final void writeInt32Vector(int[] val);
|
||||
private native final void writeInt64Vector(long[] val);
|
||||
private native final void writeFloatVector(float[] val);
|
||||
private native final void writeDoubleVector(double[] val);
|
||||
private native final void writeStringVector(String[] val);
|
||||
private native final void writeNativeHandleVector(NativeHandle[] val);
|
||||
public final void writeBoolVector(ArrayList<Boolean> val) {
|
||||
}
|
||||
public final void writeInt8Vector(ArrayList<Byte> val) {
|
||||
}
|
||||
public final void writeInt16Vector(ArrayList<Short> val) {
|
||||
}
|
||||
public final void writeInt32Vector(ArrayList<Integer> val) {
|
||||
}
|
||||
public final void writeInt64Vector(ArrayList<Long> val) {
|
||||
}
|
||||
public final void writeFloatVector(ArrayList<Float> val) {
|
||||
}
|
||||
public final void writeDoubleVector(ArrayList<Double> val) {
|
||||
}
|
||||
public final void writeStringVector(ArrayList<String> val) {
|
||||
}
|
||||
public final void writeNativeHandleVector(ArrayList<NativeHandle> val) {
|
||||
}
|
||||
public native final void writeStrongBinder(IHwBinder binder);
|
||||
//public native final void writeHidlMemory(HidlMemory memory);
|
||||
public native final void enforceInterface(String interfaceName);
|
||||
public native final boolean readBool();
|
||||
public native final byte readInt8();
|
||||
public native final short readInt16();
|
||||
public native final int readInt32();
|
||||
public native final long readInt64();
|
||||
public native final float readFloat();
|
||||
public native final double readDouble();
|
||||
public native final String readString();
|
||||
public native final NativeHandle readNativeHandle();
|
||||
public native final NativeHandle readEmbeddedNativeHandle(
|
||||
long parentHandle, long offset);
|
||||
private native final boolean[] readBoolVectorAsArray();
|
||||
private native final byte[] readInt8VectorAsArray();
|
||||
private native final short[] readInt16VectorAsArray();
|
||||
private native final int[] readInt32VectorAsArray();
|
||||
private native final long[] readInt64VectorAsArray();
|
||||
private native final float[] readFloatVectorAsArray();
|
||||
private native final double[] readDoubleVectorAsArray();
|
||||
private native final String[] readStringVectorAsArray();
|
||||
private native final NativeHandle[] readNativeHandleAsArray();
|
||||
public final ArrayList<Boolean> readBoolVector() {
|
||||
return null;
|
||||
}
|
||||
public final ArrayList<Byte> readInt8Vector() {
|
||||
return null;
|
||||
}
|
||||
public final ArrayList<Short> readInt16Vector() {
|
||||
return null;
|
||||
}
|
||||
public final ArrayList<Integer> readInt32Vector() {
|
||||
return null;
|
||||
}
|
||||
public final ArrayList<Long> readInt64Vector() {
|
||||
return null;
|
||||
}
|
||||
public final ArrayList<Float> readFloatVector() {
|
||||
return null;
|
||||
}
|
||||
public final ArrayList<Double> readDoubleVector() {
|
||||
return null;
|
||||
}
|
||||
public final ArrayList<String> readStringVector() {
|
||||
return null;
|
||||
}
|
||||
public final ArrayList<NativeHandle> readNativeHandleVector() {
|
||||
return null;
|
||||
}
|
||||
public native final IHwBinder readStrongBinder();
|
||||
// public native final HidlMemory readHidlMemory();
|
||||
// public native final
|
||||
// HidlMemory readEmbeddedHidlMemory(long fieldHandle, long parentHandle, long offset);
|
||||
public native final HwBlob readBuffer(long expectedSize);
|
||||
public native final HwBlob readEmbeddedBuffer(
|
||||
long expectedSize, long parentHandle, long offset,
|
||||
boolean nullable);
|
||||
public native final void writeBuffer(HwBlob blob);
|
||||
public native final void writeStatus(int status);
|
||||
public native final void verifySuccess();
|
||||
public native final void releaseTemporaryStorage();
|
||||
public native final void release();
|
||||
public native final void send();}
|
||||
@@ -0,0 +1,11 @@
|
||||
package android.os;
|
||||
|
||||
public interface IHwBinder {
|
||||
public interface DeathRecipient {
|
||||
public void serviceDied(long cookie);
|
||||
}
|
||||
public IHwInterface queryLocalInterface(String descriptor);
|
||||
public void transact(int code, HwParcel request, HwParcel reply, int flags);
|
||||
public boolean linkToDeath(DeathRecipient recipient, long cookie);
|
||||
public boolean unlinkToDeath(DeathRecipient recipient);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package android.os;
|
||||
|
||||
public interface IHwInterface {
|
||||
public IHwBinder asBinder();
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package android.os;
|
||||
|
||||
public class NativeHandle {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package android.os;
|
||||
|
||||
public final class ServiceManager {
|
||||
public static IBinder getService(String name) {
|
||||
return null; // Stub
|
||||
}
|
||||
}
|
||||
32
extras/android/RemoteHCI/scripts/generate_java_from_aidl.sh
Normal file
@@ -0,0 +1,32 @@
|
||||
# Run this script to generate the .java files from the .aidl files
|
||||
# then replace `this.markVintfStability()` with:
|
||||
# try {
|
||||
# Method method = this.getClass().getMethod("markVintfStability", null);
|
||||
# method.invoke(this);
|
||||
# } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
|
||||
# throw new RuntimeException(e);
|
||||
# }
|
||||
|
||||
AIDL=$ANDROID_SDK_ROOT/build-tools/34.0.0/aidl
|
||||
|
||||
$AIDL \
|
||||
-oapp/src/main/java \
|
||||
-Iapp/src/main/aidl \
|
||||
--stability=vintf \
|
||||
--structured \
|
||||
app/src/main/aidl/android/hardware/bluetooth/IBluetoothHci.aidl
|
||||
|
||||
$AIDL \
|
||||
-oapp/src/main/java \
|
||||
-Iapp/src/main/aidl \
|
||||
--stability=vintf \
|
||||
--structured \
|
||||
app/src/main/aidl/android/hardware/bluetooth/IBluetoothHciCallbacks.aidl
|
||||
|
||||
$AIDL \
|
||||
-oapp/src/main/java \
|
||||
-Iapp/src/main/aidl \
|
||||
--stability=vintf \
|
||||
--structured \
|
||||
app/src/main/aidl/android/hardware/bluetooth/Status.aidl
|
||||
|
||||
18
extras/android/RemoteHCI/settings.gradle.kts
Normal file
@@ -0,0 +1,18 @@
|
||||
pluginManagement {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
dependencyResolutionManagement {
|
||||
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.name = "RemoteHCI"
|
||||
include(":app")
|
||||
include(":lib")
|
||||
229
rust/Cargo.lock
generated
@@ -80,6 +80,37 @@ version = "1.0.75"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
|
||||
|
||||
[[package]]
|
||||
name = "argh"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7af5ba06967ff7214ce4c7419c7d185be7ecd6cc4965a8f6e1d8ce0398aad219"
|
||||
dependencies = [
|
||||
"argh_derive",
|
||||
"argh_shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "argh_derive"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56df0aeedf6b7a2fc67d06db35b09684c3e8da0c95f8f27685cb17e08413d87a"
|
||||
dependencies = [
|
||||
"argh_shared",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.29",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "argh_shared"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5693f39141bda5760ecc4111ab08da40565d1771038c4a0250f03457ec707531"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
@@ -130,6 +161,15 @@ version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bstr"
|
||||
version = "1.6.2"
|
||||
@@ -145,6 +185,7 @@ name = "bumble"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
"clap 4.4.1",
|
||||
"directories",
|
||||
"env_logger",
|
||||
@@ -158,6 +199,8 @@ dependencies = [
|
||||
"nix",
|
||||
"nom",
|
||||
"owo-colors",
|
||||
"pdl-derive",
|
||||
"pdl-runtime",
|
||||
"pyo3",
|
||||
"pyo3-asyncio",
|
||||
"rand",
|
||||
@@ -178,9 +221,9 @@ checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.4.0"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
|
||||
checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
@@ -262,6 +305,16 @@ version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961"
|
||||
|
||||
[[package]]
|
||||
name = "codespan-reporting"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e"
|
||||
dependencies = [
|
||||
"termcolor",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.0"
|
||||
@@ -284,6 +337,15 @@ version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam"
|
||||
version = "0.8.2"
|
||||
@@ -351,6 +413,26 @@ dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"crypto-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "directories"
|
||||
version = "5.0.1"
|
||||
@@ -559,6 +641,16 @@ dependencies = [
|
||||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.10"
|
||||
@@ -1064,12 +1156,100 @@ dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pdl-compiler"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee66995739fb9ddd9155767990a54aadd226ee32408a94f99f94883ff445ceba"
|
||||
dependencies = [
|
||||
"argh",
|
||||
"codespan-reporting",
|
||||
"heck",
|
||||
"pest",
|
||||
"pest_derive",
|
||||
"prettyplease",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"syn 2.0.29",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pdl-derive"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "113e4a1215c407466b36d2c2f6a6318819d6b22ccdd3acb7bb35e27a68806034"
|
||||
dependencies = [
|
||||
"codespan-reporting",
|
||||
"pdl-compiler",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.29",
|
||||
"termcolor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pdl-runtime"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2d36c2f9799613babe78eb5cd9a353d527daaba6c3d1f39a1175657a35790732"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
|
||||
|
||||
[[package]]
|
||||
name = "pest"
|
||||
version = "2.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c022f1e7b65d6a24c0dbbd5fb344c66881bc01f3e5ae74a1c8100f2f985d98a4"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"thiserror",
|
||||
"ucd-trie",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pest_derive"
|
||||
version = "2.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "35513f630d46400a977c4cb58f78e1bfbe01434316e60c37d27b9ad6139c66d8"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"pest_generator",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pest_generator"
|
||||
version = "2.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc9fc1b9e7057baba189b5c626e2d6f40681ae5b6eb064dc7c7834101ec8123a"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"pest_meta",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.29",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pest_meta"
|
||||
version = "2.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1df74e9e7ec4053ceb980e7c0c8bd3594e977fde1af91daba9c928e8e8c6708d"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"pest",
|
||||
"sha2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.13"
|
||||
@@ -1094,6 +1274,16 @@ version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||
|
||||
[[package]]
|
||||
name = "prettyplease"
|
||||
version = "0.2.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c64d9ba0963cdcea2e1b2230fbae2bab30eb25a174be395c41e764bfb65dd62"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"syn 2.0.29",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.66"
|
||||
@@ -1465,6 +1655,17 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.10.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-registry"
|
||||
version = "1.4.1"
|
||||
@@ -1711,6 +1912,18 @@ version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
|
||||
|
||||
[[package]]
|
||||
name = "ucd-trie"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-bidi"
|
||||
version = "0.3.13"
|
||||
@@ -1738,6 +1951,12 @@ version = "1.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
|
||||
|
||||
[[package]]
|
||||
name = "unindent"
|
||||
version = "0.1.11"
|
||||
@@ -1767,6 +1986,12 @@ version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.4.0"
|
||||
|
||||
@@ -23,6 +23,9 @@ hex = "0.4.3"
|
||||
itertools = "0.11.0"
|
||||
lazy_static = "1.4.0"
|
||||
thiserror = "1.0.41"
|
||||
bytes = "1.5.0"
|
||||
pdl-derive = "0.2.0"
|
||||
pdl-runtime = "0.2.0"
|
||||
|
||||
# Dev tools
|
||||
file-header = { version = "0.1.2", optional = true }
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
use bumble::{
|
||||
adv::CommonDataType,
|
||||
wrapper::{
|
||||
core::AdvertisementDataUnit, device::Device, hci::AddressType, transport::Transport,
|
||||
core::AdvertisementDataUnit, device::Device, hci::packets::AddressType,
|
||||
transport::Transport,
|
||||
},
|
||||
};
|
||||
use clap::Parser as _;
|
||||
@@ -69,9 +70,7 @@ async fn main() -> PyResult<()> {
|
||||
let mut seen_adv_cache = seen_adv_clone.lock().unwrap();
|
||||
let expiry_duration = time::Duration::from_secs(cli.dedup_expiry_secs);
|
||||
|
||||
let advs_from_addr = seen_adv_cache
|
||||
.entry(addr_bytes)
|
||||
.or_insert_with(collections::HashMap::new);
|
||||
let advs_from_addr = seen_adv_cache.entry(addr_bytes).or_default();
|
||||
// we expect cache hits to be the norm, so we do a separate lookup to avoid cloning
|
||||
// on every lookup with entry()
|
||||
let show = if let Some(prev) = advs_from_addr.get_mut(&data_units) {
|
||||
@@ -102,7 +101,9 @@ async fn main() -> PyResult<()> {
|
||||
};
|
||||
|
||||
let (type_style, qualifier) = match adv.address()?.address_type()? {
|
||||
AddressType::PublicIdentity | AddressType::PublicDevice => (Style::new().cyan(), ""),
|
||||
AddressType::PublicIdentityAddress | AddressType::PublicDeviceAddress => {
|
||||
(Style::new().cyan(), "")
|
||||
}
|
||||
_ => {
|
||||
if addr.is_static()? {
|
||||
(Style::new().green(), "(static)")
|
||||
|
||||
@@ -12,9 +12,26 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use bumble::wrapper::{drivers::rtk::DriverInfo, transport::Transport};
|
||||
use bumble::wrapper::{
|
||||
controller::Controller,
|
||||
device::Device,
|
||||
drivers::rtk::DriverInfo,
|
||||
hci::{
|
||||
packets::{
|
||||
AddressType, ErrorCode, ReadLocalVersionInformationBuilder,
|
||||
ReadLocalVersionInformationComplete,
|
||||
},
|
||||
Address, Error,
|
||||
},
|
||||
host::Host,
|
||||
link::Link,
|
||||
transport::Transport,
|
||||
};
|
||||
use nix::sys::stat::Mode;
|
||||
use pyo3::PyResult;
|
||||
use pyo3::{
|
||||
exceptions::PyException,
|
||||
{PyErr, PyResult},
|
||||
};
|
||||
|
||||
#[pyo3_asyncio::tokio::test]
|
||||
async fn fifo_transport_can_open() -> PyResult<()> {
|
||||
@@ -35,3 +52,26 @@ async fn realtek_driver_info_all_drivers() -> PyResult<()> {
|
||||
assert_eq!(12, DriverInfo::all_drivers()?.len());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[pyo3_asyncio::tokio::test]
|
||||
async fn hci_command_wrapper_has_correct_methods() -> PyResult<()> {
|
||||
let address = Address::new("F0:F1:F2:F3:F4:F5", &AddressType::RandomDeviceAddress)?;
|
||||
let link = Link::new_local_link()?;
|
||||
let controller = Controller::new("C1", None, None, Some(link), Some(address.clone())).await?;
|
||||
let host = Host::new(controller.clone().into(), controller.into()).await?;
|
||||
let device = Device::new(None, Some(address), None, Some(host), None)?;
|
||||
|
||||
device.power_on().await?;
|
||||
|
||||
// Send some simple command. A successful response means [HciCommandWrapper] has the minimum
|
||||
// required interface for the Python code to think its an [HCI_Command] object.
|
||||
let command = ReadLocalVersionInformationBuilder {};
|
||||
let event: ReadLocalVersionInformationComplete = device
|
||||
.send_command(&command.into(), true)
|
||||
.await?
|
||||
.try_into()
|
||||
.map_err(|e: Error| PyErr::new::<PyException, _>(e.to_string()))?;
|
||||
|
||||
assert_eq!(ErrorCode::Success, event.get_status());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -179,7 +179,7 @@ pub(crate) fn parse(firmware_path: &path::Path) -> PyResult<()> {
|
||||
pub(crate) async fn info(transport: &str, force: bool) -> PyResult<()> {
|
||||
let transport = Transport::open(transport).await?;
|
||||
|
||||
let mut host = Host::new(transport.source()?, transport.sink()?)?;
|
||||
let mut host = Host::new(transport.source()?, transport.sink()?).await?;
|
||||
host.reset(DriverFactory::None).await?;
|
||||
|
||||
if !force && !Driver::check(&host).await? {
|
||||
@@ -203,7 +203,7 @@ pub(crate) async fn info(transport: &str, force: bool) -> PyResult<()> {
|
||||
pub(crate) async fn load(transport: &str, force: bool) -> PyResult<()> {
|
||||
let transport = Transport::open(transport).await?;
|
||||
|
||||
let mut host = Host::new(transport.source()?, transport.sink()?)?;
|
||||
let mut host = Host::new(transport.source()?, transport.sink()?).await?;
|
||||
host.reset(DriverFactory::None).await?;
|
||||
|
||||
match Driver::for_host(&host, force).await? {
|
||||
@@ -219,7 +219,7 @@ pub(crate) async fn load(transport: &str, force: bool) -> PyResult<()> {
|
||||
pub(crate) async fn drop(transport: &str) -> PyResult<()> {
|
||||
let transport = Transport::open(transport).await?;
|
||||
|
||||
let mut host = Host::new(transport.source()?, transport.sink()?)?;
|
||||
let mut host = Host::new(transport.source()?, transport.sink()?).await?;
|
||||
host.reset(DriverFactory::None).await?;
|
||||
|
||||
Driver::drop_firmware(&mut host).await?;
|
||||
|
||||
@@ -21,8 +21,7 @@
|
||||
/// TCP client to connect.
|
||||
/// When the L2CAP CoC channel is closed, the TCP connection is closed as well.
|
||||
use crate::cli::l2cap::{
|
||||
proxy_l2cap_rx_to_tcp_tx, proxy_tcp_rx_to_l2cap_tx, run_future_with_current_task_locals,
|
||||
BridgeData,
|
||||
inject_py_event_loop, proxy_l2cap_rx_to_tcp_tx, proxy_tcp_rx_to_l2cap_tx, BridgeData,
|
||||
};
|
||||
use bumble::wrapper::{
|
||||
device::{Connection, Device},
|
||||
@@ -85,11 +84,12 @@ pub async fn start(args: &Args, device: &mut Device) -> PyResult<()> {
|
||||
let mtu = args.mtu;
|
||||
let mps = args.mps;
|
||||
let ble_connection = Arc::new(Mutex::new(ble_connection));
|
||||
// Ensure Python event loop is available to l2cap `disconnect`
|
||||
let _ = run_future_with_current_task_locals(async move {
|
||||
// spawn thread to handle incoming tcp connections
|
||||
tokio::spawn(inject_py_event_loop(async move {
|
||||
while let Ok((tcp_stream, addr)) = listener.accept().await {
|
||||
let ble_connection = ble_connection.clone();
|
||||
let _ = run_future_with_current_task_locals(proxy_data_between_tcp_and_l2cap(
|
||||
// spawn thread to handle this specific tcp connection
|
||||
if let Ok(future) = inject_py_event_loop(proxy_data_between_tcp_and_l2cap(
|
||||
ble_connection,
|
||||
tcp_stream,
|
||||
addr,
|
||||
@@ -97,10 +97,11 @@ pub async fn start(args: &Args, device: &mut Device) -> PyResult<()> {
|
||||
max_credits,
|
||||
mtu,
|
||||
mps,
|
||||
));
|
||||
)) {
|
||||
tokio::spawn(future);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
});
|
||||
})?);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ use crate::L2cap;
|
||||
use anyhow::anyhow;
|
||||
use bumble::wrapper::{device::Device, l2cap::LeConnectionOrientedChannel, transport::Transport};
|
||||
use owo_colors::{colors::css::Orange, OwoColorize};
|
||||
use pyo3::{PyObject, PyResult, Python};
|
||||
use pyo3::{PyResult, Python};
|
||||
use std::{future::Future, path::PathBuf, sync::Arc};
|
||||
use tokio::{
|
||||
io::{AsyncReadExt, AsyncWriteExt},
|
||||
@@ -170,21 +170,12 @@ async fn proxy_tcp_rx_to_l2cap_tx(
|
||||
}
|
||||
}
|
||||
|
||||
/// Copies the current thread's TaskLocals into a Python "awaitable" and encapsulates it in a Rust
|
||||
/// future, running it as a Python Task.
|
||||
/// `TaskLocals` stores the current event loop, and allows the user to copy the current Python
|
||||
/// context if necessary. In this case, the python event loop is used when calling `disconnect` on
|
||||
/// an l2cap connection, or else the call will fail.
|
||||
pub fn run_future_with_current_task_locals<F>(
|
||||
fut: F,
|
||||
) -> PyResult<impl Future<Output = PyResult<PyObject>> + Send>
|
||||
/// Copies the current thread's Python even loop (contained in `TaskLocals`) into the given future.
|
||||
/// Useful when sending work to another thread that calls Python code which calls `get_running_loop()`.
|
||||
pub fn inject_py_event_loop<F, R>(fut: F) -> PyResult<impl Future<Output = R>>
|
||||
where
|
||||
F: Future<Output = PyResult<()>> + Send + 'static,
|
||||
F: Future<Output = R> + Send + 'static,
|
||||
{
|
||||
Python::with_gil(|py| {
|
||||
let locals = pyo3_asyncio::tokio::get_current_locals(py)?;
|
||||
let future = pyo3_asyncio::tokio::scope(locals.clone(), fut);
|
||||
pyo3_asyncio::tokio::future_into_py_with_locals(py, locals, future)
|
||||
.and_then(pyo3_asyncio::tokio::into_future)
|
||||
})
|
||||
let locals = Python::with_gil(pyo3_asyncio::tokio::get_current_locals)?;
|
||||
Ok(pyo3_asyncio::tokio::scope(locals, fut))
|
||||
}
|
||||
|
||||
@@ -19,10 +19,7 @@
|
||||
/// When the L2CAP CoC channel is closed, the bridge disconnects the TCP socket
|
||||
/// and waits for a new L2CAP CoC channel to be connected.
|
||||
/// When the TCP connection is closed by the TCP server, the L2CAP connection is closed as well.
|
||||
use crate::cli::l2cap::{
|
||||
proxy_l2cap_rx_to_tcp_tx, proxy_tcp_rx_to_l2cap_tx, run_future_with_current_task_locals,
|
||||
BridgeData,
|
||||
};
|
||||
use crate::cli::l2cap::{proxy_l2cap_rx_to_tcp_tx, proxy_tcp_rx_to_l2cap_tx, BridgeData};
|
||||
use bumble::wrapper::{device::Device, hci::HciConstant, l2cap::LeConnectionOrientedChannel};
|
||||
use futures::executor::block_on;
|
||||
use owo_colors::OwoColorize;
|
||||
@@ -49,19 +46,19 @@ pub async fn start(args: &Args, device: &mut Device) -> PyResult<()> {
|
||||
let port = args.tcp_port;
|
||||
device.register_l2cap_channel_server(
|
||||
args.psm,
|
||||
move |_py, l2cap_channel| {
|
||||
move |py, l2cap_channel| {
|
||||
let channel_info = l2cap_channel
|
||||
.debug_string()
|
||||
.unwrap_or_else(|e| format!("failed to get l2cap channel info ({e})"));
|
||||
println!("{} {channel_info}", "*** L2CAP channel:".cyan());
|
||||
|
||||
let host = host.clone();
|
||||
// Ensure Python event loop is available to l2cap `disconnect`
|
||||
let _ = run_future_with_current_task_locals(proxy_data_between_l2cap_and_tcp(
|
||||
l2cap_channel,
|
||||
host,
|
||||
port,
|
||||
));
|
||||
// Handles setting up a tokio runtime that runs this future to completion while also
|
||||
// containing the necessary context vars.
|
||||
pyo3_asyncio::tokio::future_into_py(
|
||||
py,
|
||||
proxy_data_between_l2cap_and_tcp(l2cap_channel, host, port),
|
||||
)?;
|
||||
Ok(())
|
||||
},
|
||||
args.max_credits,
|
||||
|
||||
@@ -143,10 +143,7 @@ pub(crate) fn probe(verbose: bool) -> anyhow::Result<()> {
|
||||
);
|
||||
if let Some(s) = serial {
|
||||
println!("{:26}{}", " Serial:".green(), s);
|
||||
device_serials_by_id
|
||||
.entry(device_id)
|
||||
.or_insert(HashSet::new())
|
||||
.insert(s);
|
||||
device_serials_by_id.entry(device_id).or_default().insert(s);
|
||||
}
|
||||
if let Some(m) = mfg {
|
||||
println!("{:26}{}", " Manufacturer:".green(), m);
|
||||
@@ -314,7 +311,7 @@ impl ClassInfo {
|
||||
self.protocol,
|
||||
self.protocol_name()
|
||||
.map(|s| format!(" [{}]", s))
|
||||
.unwrap_or_else(String::new)
|
||||
.unwrap_or_default()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
161
rust/src/internal/hci/mod.rs
Normal file
@@ -0,0 +1,161 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// 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.
|
||||
|
||||
pub use pdl_runtime::{Error, Packet};
|
||||
|
||||
use crate::internal::hci::packets::{Acl, Command, Event, Sco};
|
||||
use pdl_derive::pdl;
|
||||
|
||||
#[allow(missing_docs, warnings, clippy::all)]
|
||||
#[pdl("src/internal/hci/packets.pdl")]
|
||||
pub mod packets {}
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
/// HCI Packet type, prepended to the packet.
|
||||
/// Rootcanal's PDL declaration excludes this from ser/deser and instead is implemented in code.
|
||||
/// To maintain the ability to easily use future versions of their packet PDL, packet type is
|
||||
/// implemented here.
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub(crate) enum PacketType {
|
||||
Command = 0x01,
|
||||
Acl = 0x02,
|
||||
Sco = 0x03,
|
||||
Event = 0x04,
|
||||
}
|
||||
|
||||
impl TryFrom<u8> for PacketType {
|
||||
type Error = PacketTypeParseError;
|
||||
|
||||
fn try_from(value: u8) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
0x01 => Ok(PacketType::Command),
|
||||
0x02 => Ok(PacketType::Acl),
|
||||
0x03 => Ok(PacketType::Sco),
|
||||
0x04 => Ok(PacketType::Event),
|
||||
_ => Err(PacketTypeParseError::InvalidPacketType { value }),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PacketType> for u8 {
|
||||
fn from(packet_type: PacketType) -> Self {
|
||||
match packet_type {
|
||||
PacketType::Command => 0x01,
|
||||
PacketType::Acl => 0x02,
|
||||
PacketType::Sco => 0x03,
|
||||
PacketType::Event => 0x04,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Allows for smoother interoperability between a [Packet] and a bytes representation of it that
|
||||
/// includes its type as a header
|
||||
pub(crate) trait WithPacketType<T: Packet> {
|
||||
/// Converts the [Packet] into bytes, prefixed with its type
|
||||
fn to_vec_with_packet_type(self) -> Vec<u8>;
|
||||
|
||||
/// Parses a [Packet] out of bytes that are prefixed with the packet's type
|
||||
fn parse_with_packet_type(bytes: &[u8]) -> Result<T, PacketTypeParseError>;
|
||||
}
|
||||
|
||||
/// Errors that may arise when parsing a packet that is prefixed with its type
|
||||
#[derive(Debug, PartialEq, thiserror::Error)]
|
||||
pub(crate) enum PacketTypeParseError {
|
||||
#[error("The slice being parsed was empty")]
|
||||
EmptySlice,
|
||||
#[error("Packet type ({value:#X}) is invalid")]
|
||||
InvalidPacketType { value: u8 },
|
||||
#[error("Expected packet type: {expected:?}, but got: {actual:?}")]
|
||||
PacketTypeMismatch {
|
||||
expected: PacketType,
|
||||
actual: PacketType,
|
||||
},
|
||||
#[error("Failed to parse packet after header: {error}")]
|
||||
PacketParse { error: Error },
|
||||
}
|
||||
|
||||
impl From<Error> for PacketTypeParseError {
|
||||
fn from(error: Error) -> Self {
|
||||
Self::PacketParse { error }
|
||||
}
|
||||
}
|
||||
|
||||
impl WithPacketType<Self> for Command {
|
||||
fn to_vec_with_packet_type(self) -> Vec<u8> {
|
||||
prepend_packet_type(PacketType::Command, self.to_vec())
|
||||
}
|
||||
|
||||
fn parse_with_packet_type(bytes: &[u8]) -> Result<Self, PacketTypeParseError> {
|
||||
parse_with_expected_packet_type(Command::parse, PacketType::Command, bytes)
|
||||
}
|
||||
}
|
||||
|
||||
impl WithPacketType<Self> for Acl {
|
||||
fn to_vec_with_packet_type(self) -> Vec<u8> {
|
||||
prepend_packet_type(PacketType::Acl, self.to_vec())
|
||||
}
|
||||
|
||||
fn parse_with_packet_type(bytes: &[u8]) -> Result<Self, PacketTypeParseError> {
|
||||
parse_with_expected_packet_type(Acl::parse, PacketType::Acl, bytes)
|
||||
}
|
||||
}
|
||||
|
||||
impl WithPacketType<Self> for Sco {
|
||||
fn to_vec_with_packet_type(self) -> Vec<u8> {
|
||||
prepend_packet_type(PacketType::Sco, self.to_vec())
|
||||
}
|
||||
|
||||
fn parse_with_packet_type(bytes: &[u8]) -> Result<Self, PacketTypeParseError> {
|
||||
parse_with_expected_packet_type(Sco::parse, PacketType::Sco, bytes)
|
||||
}
|
||||
}
|
||||
|
||||
impl WithPacketType<Self> for Event {
|
||||
fn to_vec_with_packet_type(self) -> Vec<u8> {
|
||||
prepend_packet_type(PacketType::Event, self.to_vec())
|
||||
}
|
||||
|
||||
fn parse_with_packet_type(bytes: &[u8]) -> Result<Self, PacketTypeParseError> {
|
||||
parse_with_expected_packet_type(Event::parse, PacketType::Event, bytes)
|
||||
}
|
||||
}
|
||||
|
||||
fn prepend_packet_type(packet_type: PacketType, mut packet_bytes: Vec<u8>) -> Vec<u8> {
|
||||
packet_bytes.insert(0, packet_type.into());
|
||||
packet_bytes
|
||||
}
|
||||
|
||||
fn parse_with_expected_packet_type<T: Packet, F, E>(
|
||||
parser: F,
|
||||
expected_packet_type: PacketType,
|
||||
bytes: &[u8],
|
||||
) -> Result<T, PacketTypeParseError>
|
||||
where
|
||||
F: Fn(&[u8]) -> Result<T, E>,
|
||||
PacketTypeParseError: From<E>,
|
||||
{
|
||||
let (first_byte, packet_bytes) = bytes
|
||||
.split_first()
|
||||
.ok_or(PacketTypeParseError::EmptySlice)?;
|
||||
let actual_packet_type = PacketType::try_from(*first_byte)?;
|
||||
if actual_packet_type == expected_packet_type {
|
||||
Ok(parser(packet_bytes)?)
|
||||
} else {
|
||||
Err(PacketTypeParseError::PacketTypeMismatch {
|
||||
expected: expected_packet_type,
|
||||
actual: actual_packet_type,
|
||||
})
|
||||
}
|
||||
}
|
||||
6253
rust/src/internal/hci/packets.pdl
Normal file
94
rust/src/internal/hci/tests.rs
Normal file
@@ -0,0 +1,94 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// 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.
|
||||
|
||||
use crate::internal::hci::{
|
||||
packets::{Event, EventBuilder, EventCode, Sco},
|
||||
parse_with_expected_packet_type, prepend_packet_type, Error, Packet, PacketType,
|
||||
PacketTypeParseError, WithPacketType,
|
||||
};
|
||||
use bytes::Bytes;
|
||||
|
||||
#[test]
|
||||
fn prepends_packet_type() {
|
||||
let packet_type = PacketType::Event;
|
||||
let packet_bytes = vec![0x00, 0x00, 0x00, 0x00];
|
||||
let actual = prepend_packet_type(packet_type, packet_bytes);
|
||||
assert_eq!(vec![0x04, 0x00, 0x00, 0x00, 0x00], actual);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_empty_slice_should_error() {
|
||||
let actual = parse_with_expected_packet_type(FakePacket::parse, PacketType::Event, &[]);
|
||||
assert_eq!(Err(PacketTypeParseError::EmptySlice), actual);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_invalid_packet_type_should_error() {
|
||||
let actual = parse_with_expected_packet_type(FakePacket::parse, PacketType::Event, &[0xFF]);
|
||||
assert_eq!(
|
||||
Err(PacketTypeParseError::InvalidPacketType { value: 0xFF }),
|
||||
actual
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_mismatched_packet_type_should_error() {
|
||||
let actual = parse_with_expected_packet_type(FakePacket::parse, PacketType::Acl, &[0x01]);
|
||||
assert_eq!(
|
||||
Err(PacketTypeParseError::PacketTypeMismatch {
|
||||
expected: PacketType::Acl,
|
||||
actual: PacketType::Command
|
||||
}),
|
||||
actual
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_invalid_packet_should_error() {
|
||||
let actual = parse_with_expected_packet_type(Sco::parse, PacketType::Sco, &[0x03]);
|
||||
assert!(actual.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_packet_roundtrip_with_type() {
|
||||
let event_packet = EventBuilder {
|
||||
event_code: EventCode::InquiryComplete,
|
||||
payload: None,
|
||||
}
|
||||
.build();
|
||||
let event_packet_bytes = event_packet.clone().to_vec_with_packet_type();
|
||||
let actual =
|
||||
parse_with_expected_packet_type(Event::parse, PacketType::Event, &event_packet_bytes)
|
||||
.unwrap();
|
||||
assert_eq!(event_packet, actual);
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
struct FakePacket;
|
||||
|
||||
impl FakePacket {
|
||||
fn parse(_bytes: &[u8]) -> Result<Self, Error> {
|
||||
Ok(Self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Packet for FakePacket {
|
||||
fn to_bytes(self) -> Bytes {
|
||||
Bytes::new()
|
||||
}
|
||||
|
||||
fn to_vec(self) -> Vec<u8> {
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
@@ -18,3 +18,4 @@
|
||||
//! to discover.
|
||||
|
||||
pub(crate) mod drivers;
|
||||
pub(crate) mod hci;
|
||||
|
||||
34
rust/src/wrapper/common.rs
Normal file
@@ -0,0 +1,34 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// 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.
|
||||
|
||||
//! Shared resources found under bumble's common.py
|
||||
use pyo3::{PyObject, Python, ToPyObject};
|
||||
|
||||
/// Represents the sink for some transport mechanism
|
||||
pub struct TransportSink(pub(crate) PyObject);
|
||||
|
||||
impl ToPyObject for TransportSink {
|
||||
fn to_object(&self, _py: Python<'_>) -> PyObject {
|
||||
self.0.clone()
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents the source for some transport mechanism
|
||||
pub struct TransportSource(pub(crate) PyObject);
|
||||
|
||||
impl ToPyObject for TransportSource {
|
||||
fn to_object(&self, _py: Python<'_>) -> PyObject {
|
||||
self.0.clone()
|
||||
}
|
||||
}
|
||||
66
rust/src/wrapper/controller.rs
Normal file
@@ -0,0 +1,66 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// 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.
|
||||
|
||||
//! Controller components
|
||||
use crate::wrapper::{
|
||||
common::{TransportSink, TransportSource},
|
||||
hci::Address,
|
||||
link::Link,
|
||||
wrap_python_async, PyDictExt,
|
||||
};
|
||||
use pyo3::{
|
||||
intern,
|
||||
types::{PyDict, PyModule},
|
||||
PyObject, PyResult, Python,
|
||||
};
|
||||
use pyo3_asyncio::tokio::into_future;
|
||||
|
||||
/// A controller that can send and receive HCI frames via some link
|
||||
#[derive(Clone)]
|
||||
pub struct Controller(pub(crate) PyObject);
|
||||
|
||||
impl Controller {
|
||||
/// Creates a new [Controller] object. When optional arguments are not specified, the Python
|
||||
/// module specifies the defaults. Must be called from a thread with a Python event loop, which
|
||||
/// should be true on `tokio::main` and `async_std::main`.
|
||||
///
|
||||
/// For more info, see https://awestlake87.github.io/pyo3-asyncio/master/doc/pyo3_asyncio/#event-loop-references-and-contextvars.
|
||||
pub async fn new(
|
||||
name: &str,
|
||||
host_source: Option<TransportSource>,
|
||||
host_sink: Option<TransportSink>,
|
||||
link: Option<Link>,
|
||||
public_address: Option<Address>,
|
||||
) -> PyResult<Self> {
|
||||
Python::with_gil(|py| {
|
||||
let controller_ctr = PyModule::import(py, intern!(py, "bumble.controller"))?
|
||||
.getattr(intern!(py, "Controller"))?;
|
||||
|
||||
let kwargs = PyDict::new(py);
|
||||
kwargs.set_item("name", name)?;
|
||||
kwargs.set_opt_item("host_source", host_source)?;
|
||||
kwargs.set_opt_item("host_sink", host_sink)?;
|
||||
kwargs.set_opt_item("link", link)?;
|
||||
kwargs.set_opt_item("public_address", public_address)?;
|
||||
|
||||
// Controller constructor (`__init__`) is not (and can't be) marked async, but calls
|
||||
// `get_running_loop`, and thus needs wrapped in an async function.
|
||||
wrap_python_async(py, controller_ctr)?
|
||||
.call((), Some(kwargs))
|
||||
.and_then(into_future)
|
||||
})?
|
||||
.await
|
||||
.map(Self)
|
||||
}
|
||||
}
|
||||
@@ -14,12 +14,16 @@
|
||||
|
||||
//! Devices and connections to them
|
||||
|
||||
use crate::internal::hci::WithPacketType;
|
||||
use crate::{
|
||||
adv::AdvertisementDataBuilder,
|
||||
wrapper::{
|
||||
core::AdvertisingData,
|
||||
gatt_client::{ProfileServiceProxy, ServiceProxy},
|
||||
hci::{Address, HciErrorCode},
|
||||
hci::{
|
||||
packets::{Command, ErrorCode, Event},
|
||||
Address, HciCommandWrapper,
|
||||
},
|
||||
host::Host,
|
||||
l2cap::LeConnectionOrientedChannel,
|
||||
transport::{Sink, Source},
|
||||
@@ -27,18 +31,73 @@ use crate::{
|
||||
},
|
||||
};
|
||||
use pyo3::{
|
||||
exceptions::PyException,
|
||||
intern,
|
||||
types::{PyDict, PyModule},
|
||||
IntoPy, PyObject, PyResult, Python, ToPyObject,
|
||||
IntoPy, PyErr, PyObject, PyResult, Python, ToPyObject,
|
||||
};
|
||||
use pyo3_asyncio::tokio::into_future;
|
||||
use std::path;
|
||||
|
||||
/// Represents the various properties of some device
|
||||
pub struct DeviceConfiguration(PyObject);
|
||||
|
||||
impl DeviceConfiguration {
|
||||
/// Creates a new configuration, letting the internal Python object set all the defaults
|
||||
pub fn new() -> PyResult<DeviceConfiguration> {
|
||||
Python::with_gil(|py| {
|
||||
PyModule::import(py, intern!(py, "bumble.device"))?
|
||||
.getattr(intern!(py, "DeviceConfiguration"))?
|
||||
.call0()
|
||||
.map(|any| Self(any.into()))
|
||||
})
|
||||
}
|
||||
|
||||
/// Creates a new configuration from the specified file
|
||||
pub fn load_from_file(&mut self, device_config: &path::Path) -> PyResult<()> {
|
||||
Python::with_gil(|py| {
|
||||
self.0
|
||||
.call_method1(py, intern!(py, "load_from_file"), (device_config,))
|
||||
})
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
impl ToPyObject for DeviceConfiguration {
|
||||
fn to_object(&self, _py: Python<'_>) -> PyObject {
|
||||
self.0.clone()
|
||||
}
|
||||
}
|
||||
|
||||
/// A device that can send/receive HCI frames.
|
||||
#[derive(Clone)]
|
||||
pub struct Device(PyObject);
|
||||
|
||||
impl Device {
|
||||
/// Creates a Device. When optional arguments are not specified, the Python object specifies the
|
||||
/// defaults.
|
||||
pub fn new(
|
||||
name: Option<&str>,
|
||||
address: Option<Address>,
|
||||
config: Option<DeviceConfiguration>,
|
||||
host: Option<Host>,
|
||||
generic_access_service: Option<bool>,
|
||||
) -> PyResult<Self> {
|
||||
Python::with_gil(|py| {
|
||||
let kwargs = PyDict::new(py);
|
||||
kwargs.set_opt_item("name", name)?;
|
||||
kwargs.set_opt_item("address", address)?;
|
||||
kwargs.set_opt_item("config", config)?;
|
||||
kwargs.set_opt_item("host", host)?;
|
||||
kwargs.set_opt_item("generic_access_service", generic_access_service)?;
|
||||
|
||||
PyModule::import(py, intern!(py, "bumble.device"))?
|
||||
.getattr(intern!(py, "Device"))?
|
||||
.call((), Some(kwargs))
|
||||
.map(|any| Self(any.into()))
|
||||
})
|
||||
}
|
||||
|
||||
/// Create a Device per the provided file configured to communicate with a controller through an HCI source/sink
|
||||
pub fn from_config_file_with_hci(
|
||||
device_config: &path::Path,
|
||||
@@ -66,6 +125,29 @@ impl Device {
|
||||
})
|
||||
}
|
||||
|
||||
/// Sends an HCI command on this Device, returning the command's event result.
|
||||
pub async fn send_command(&self, command: &Command, check_result: bool) -> PyResult<Event> {
|
||||
Python::with_gil(|py| {
|
||||
self.0
|
||||
.call_method1(
|
||||
py,
|
||||
intern!(py, "send_command"),
|
||||
(HciCommandWrapper(command.clone()), check_result),
|
||||
)
|
||||
.and_then(|coroutine| into_future(coroutine.as_ref(py)))
|
||||
})?
|
||||
.await
|
||||
.and_then(|event| {
|
||||
Python::with_gil(|py| {
|
||||
let py_bytes = event.call_method0(py, intern!(py, "__bytes__"))?;
|
||||
let bytes: &[u8] = py_bytes.extract(py)?;
|
||||
let event = Event::parse_with_packet_type(bytes)
|
||||
.map_err(|e| PyErr::new::<PyException, _>(e.to_string()))?;
|
||||
Ok(event)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/// Turn the device on
|
||||
pub async fn power_on(&self) -> PyResult<()> {
|
||||
Python::with_gil(|py| {
|
||||
@@ -236,7 +318,7 @@ impl Connection {
|
||||
kwargs.set_opt_item("mps", mps)?;
|
||||
self.0
|
||||
.call_method(py, intern!(py, "open_l2cap_channel"), (), Some(kwargs))
|
||||
.and_then(|coroutine| pyo3_asyncio::tokio::into_future(coroutine.as_ref(py)))
|
||||
.and_then(|coroutine| into_future(coroutine.as_ref(py)))
|
||||
})?
|
||||
.await
|
||||
.map(LeConnectionOrientedChannel::from)
|
||||
@@ -244,13 +326,13 @@ impl Connection {
|
||||
|
||||
/// Disconnect from device with provided reason. When optional arguments are not specified, the
|
||||
/// Python module specifies the defaults.
|
||||
pub async fn disconnect(&mut self, reason: Option<HciErrorCode>) -> PyResult<()> {
|
||||
pub async fn disconnect(&mut self, reason: Option<ErrorCode>) -> PyResult<()> {
|
||||
Python::with_gil(|py| {
|
||||
let kwargs = PyDict::new(py);
|
||||
kwargs.set_opt_item("reason", reason)?;
|
||||
self.0
|
||||
.call_method(py, intern!(py, "disconnect"), (), Some(kwargs))
|
||||
.and_then(|coroutine| pyo3_asyncio::tokio::into_future(coroutine.as_ref(py)))
|
||||
.and_then(|coroutine| into_future(coroutine.as_ref(py)))
|
||||
})?
|
||||
.await
|
||||
.map(|_| ())
|
||||
@@ -259,7 +341,7 @@ impl Connection {
|
||||
/// Register a callback to be called on disconnection.
|
||||
pub fn on_disconnection(
|
||||
&mut self,
|
||||
callback: impl Fn(Python, HciErrorCode) -> PyResult<()> + Send + 'static,
|
||||
callback: impl Fn(Python, ErrorCode) -> PyResult<()> + Send + 'static,
|
||||
) -> PyResult<()> {
|
||||
let boxed = ClosureCallback::new(move |py, args, _kwargs| {
|
||||
callback(py, args.get_item(0)?.extract()?)
|
||||
|
||||
@@ -14,84 +14,62 @@
|
||||
|
||||
//! HCI
|
||||
|
||||
pub use crate::internal::hci::{packets, Error, Packet};
|
||||
|
||||
use crate::{
|
||||
internal::hci::WithPacketType,
|
||||
wrapper::hci::packets::{AddressType, Command, ErrorCode},
|
||||
};
|
||||
use itertools::Itertools as _;
|
||||
use pyo3::{
|
||||
exceptions::PyException, intern, types::PyModule, FromPyObject, PyAny, PyErr, PyObject,
|
||||
PyResult, Python, ToPyObject,
|
||||
exceptions::PyException,
|
||||
intern, pyclass, pymethods,
|
||||
types::{PyBytes, PyModule},
|
||||
FromPyObject, IntoPy, PyAny, PyErr, PyObject, PyResult, Python, ToPyObject,
|
||||
};
|
||||
|
||||
/// HCI error code.
|
||||
pub struct HciErrorCode(u8);
|
||||
|
||||
impl<'source> FromPyObject<'source> for HciErrorCode {
|
||||
fn extract(ob: &'source PyAny) -> PyResult<Self> {
|
||||
Ok(HciErrorCode(ob.extract()?))
|
||||
}
|
||||
}
|
||||
|
||||
impl ToPyObject for HciErrorCode {
|
||||
fn to_object(&self, py: Python<'_>) -> PyObject {
|
||||
self.0.to_object(py)
|
||||
}
|
||||
}
|
||||
|
||||
/// Provides helpers for interacting with HCI
|
||||
pub struct HciConstant;
|
||||
|
||||
impl HciConstant {
|
||||
/// Human-readable error name
|
||||
pub fn error_name(status: HciErrorCode) -> PyResult<String> {
|
||||
pub fn error_name(status: ErrorCode) -> PyResult<String> {
|
||||
Python::with_gil(|py| {
|
||||
PyModule::import(py, intern!(py, "bumble.hci"))?
|
||||
.getattr(intern!(py, "HCI_Constant"))?
|
||||
.call_method1(intern!(py, "error_name"), (status.0,))?
|
||||
.call_method1(intern!(py, "error_name"), (status.to_object(py),))?
|
||||
.extract()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// A Bluetooth address
|
||||
#[derive(Clone)]
|
||||
pub struct Address(pub(crate) PyObject);
|
||||
|
||||
impl Address {
|
||||
/// Creates a new [Address] object
|
||||
pub fn new(address: &str, address_type: &AddressType) -> PyResult<Self> {
|
||||
Python::with_gil(|py| {
|
||||
PyModule::import(py, intern!(py, "bumble.device"))?
|
||||
.getattr(intern!(py, "Address"))?
|
||||
.call1((address, address_type.to_object(py)))
|
||||
.map(|any| Self(any.into()))
|
||||
})
|
||||
}
|
||||
|
||||
/// The type of address
|
||||
pub fn address_type(&self) -> PyResult<AddressType> {
|
||||
Python::with_gil(|py| {
|
||||
let addr_type = self
|
||||
.0
|
||||
self.0
|
||||
.getattr(py, intern!(py, "address_type"))?
|
||||
.extract::<u32>(py)?;
|
||||
|
||||
let module = PyModule::import(py, intern!(py, "bumble.hci"))?;
|
||||
let klass = module.getattr(intern!(py, "Address"))?;
|
||||
|
||||
if addr_type
|
||||
== klass
|
||||
.getattr(intern!(py, "PUBLIC_DEVICE_ADDRESS"))?
|
||||
.extract::<u32>()?
|
||||
{
|
||||
Ok(AddressType::PublicDevice)
|
||||
} else if addr_type
|
||||
== klass
|
||||
.getattr(intern!(py, "RANDOM_DEVICE_ADDRESS"))?
|
||||
.extract::<u32>()?
|
||||
{
|
||||
Ok(AddressType::RandomDevice)
|
||||
} else if addr_type
|
||||
== klass
|
||||
.getattr(intern!(py, "PUBLIC_IDENTITY_ADDRESS"))?
|
||||
.extract::<u32>()?
|
||||
{
|
||||
Ok(AddressType::PublicIdentity)
|
||||
} else if addr_type
|
||||
== klass
|
||||
.getattr(intern!(py, "RANDOM_IDENTITY_ADDRESS"))?
|
||||
.extract::<u32>()?
|
||||
{
|
||||
Ok(AddressType::RandomIdentity)
|
||||
} else {
|
||||
Err(PyErr::new::<PyException, _>("Invalid address type"))
|
||||
}
|
||||
.extract::<u8>(py)?
|
||||
.try_into()
|
||||
.map_err(|addr_type| {
|
||||
PyErr::new::<PyException, _>(format!(
|
||||
"Failed to convert {addr_type} to AddressType"
|
||||
))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -134,12 +112,45 @@ impl Address {
|
||||
}
|
||||
}
|
||||
|
||||
/// BT address types
|
||||
#[allow(missing_docs)]
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
pub enum AddressType {
|
||||
PublicDevice,
|
||||
RandomDevice,
|
||||
PublicIdentity,
|
||||
RandomIdentity,
|
||||
impl ToPyObject for Address {
|
||||
fn to_object(&self, _py: Python<'_>) -> PyObject {
|
||||
self.0.clone()
|
||||
}
|
||||
}
|
||||
|
||||
/// Implements minimum necessary interface to be treated as bumble's [HCI_Command].
|
||||
/// While pyo3's macros do not support generics, this could probably be refactored to allow multiple
|
||||
/// implementations of the HCI_Command methods in the future, if needed.
|
||||
#[pyclass]
|
||||
pub(crate) struct HciCommandWrapper(pub(crate) Command);
|
||||
|
||||
#[pymethods]
|
||||
impl HciCommandWrapper {
|
||||
fn __bytes__(&self, py: Python) -> PyResult<PyObject> {
|
||||
let bytes = PyBytes::new(py, &self.0.clone().to_vec_with_packet_type());
|
||||
Ok(bytes.into_py(py))
|
||||
}
|
||||
|
||||
#[getter]
|
||||
fn op_code(&self) -> u16 {
|
||||
self.0.get_op_code().into()
|
||||
}
|
||||
}
|
||||
|
||||
impl ToPyObject for AddressType {
|
||||
fn to_object(&self, py: Python<'_>) -> PyObject {
|
||||
u8::from(self).to_object(py)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'source> FromPyObject<'source> for ErrorCode {
|
||||
fn extract(ob: &'source PyAny) -> PyResult<Self> {
|
||||
ob.extract()
|
||||
}
|
||||
}
|
||||
|
||||
impl ToPyObject for ErrorCode {
|
||||
fn to_object(&self, py: Python<'_>) -> PyObject {
|
||||
u8::from(self).to_object(py)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,8 +14,12 @@
|
||||
|
||||
//! Host-side types
|
||||
|
||||
use crate::wrapper::transport::{Sink, Source};
|
||||
use pyo3::{intern, prelude::PyModule, types::PyDict, PyObject, PyResult, Python};
|
||||
use crate::wrapper::{
|
||||
transport::{Sink, Source},
|
||||
wrap_python_async,
|
||||
};
|
||||
use pyo3::{intern, prelude::PyModule, types::PyDict, PyObject, PyResult, Python, ToPyObject};
|
||||
use pyo3_asyncio::tokio::into_future;
|
||||
|
||||
/// Host HCI commands
|
||||
pub struct Host {
|
||||
@@ -29,13 +33,23 @@ impl Host {
|
||||
}
|
||||
|
||||
/// Create a new Host
|
||||
pub fn new(source: Source, sink: Sink) -> PyResult<Self> {
|
||||
pub async fn new(source: Source, sink: Sink) -> PyResult<Self> {
|
||||
Python::with_gil(|py| {
|
||||
PyModule::import(py, intern!(py, "bumble.host"))?
|
||||
.getattr(intern!(py, "Host"))?
|
||||
.call((source.0, sink.0), None)
|
||||
.map(|any| Self { obj: any.into() })
|
||||
})
|
||||
let host_ctr =
|
||||
PyModule::import(py, intern!(py, "bumble.host"))?.getattr(intern!(py, "Host"))?;
|
||||
|
||||
let kwargs = PyDict::new(py);
|
||||
kwargs.set_item("controller_source", source.0)?;
|
||||
kwargs.set_item("controller_sink", sink.0)?;
|
||||
|
||||
// Needed for Python 3.8-3.9, in which the Semaphore object, when constructed, calls
|
||||
// `get_event_loop`.
|
||||
wrap_python_async(py, host_ctr)?
|
||||
.call((), Some(kwargs))
|
||||
.and_then(into_future)
|
||||
})?
|
||||
.await
|
||||
.map(|any| Self { obj: any })
|
||||
}
|
||||
|
||||
/// Send a reset command and perform other reset tasks.
|
||||
@@ -61,6 +75,12 @@ impl Host {
|
||||
}
|
||||
}
|
||||
|
||||
impl ToPyObject for Host {
|
||||
fn to_object(&self, _py: Python<'_>) -> PyObject {
|
||||
self.obj.clone()
|
||||
}
|
||||
}
|
||||
|
||||
/// Driver factory to use when initializing a host
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum DriverFactory {
|
||||
|
||||