Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

remote hci android app #312

Merged
merged 3 commits into from
Oct 17, 2023
Merged

remote hci android app #312

merged 3 commits into from
Oct 17, 2023

Conversation

barbibulle
Copy link
Collaborator

A simple kotlin+java HCI proxy app that can be built as a simple user app without checking out the AOSP tree.

Copy link
Contributor

@uael uael left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lgtm! Also added @DeltaEvo and @SilverBzH since they have way more expertise on this than me 😄

@benquike
Copy link
Contributor

benquike commented Oct 9, 2023

FYI, I tried running bumble-pair and starting pairing from Android, it was stuck at the following step:

DEBUG:bumble.host:### CONTROLLER -> HOST: HCI_IO_CAPABILITY_REQUEST_EVENT:
  bd_addr: 58:24:29:DB:A1:AC/P
DEBUG:bumble.host:### HOST -> CONTROLLER: HCI_IO_CAPABILITY_REQUEST_REPLY_COMMAND:
  bd_addr:                     58:24:29:DB:A1:AC/P
  io_capability:               HCI_DISPLAY_YES_NO_IO_CAPABILITY
  oob_data_present:            0
  authentication_requirements: HCI_MITM_REQUIRED_GENERAL_BONDING_AUTHENTICATION_REQUIREMENTS
DEBUG:bumble.host:### CONTROLLER -> HOST: HCI_SIMPLE_PAIRING_COMPLETE_EVENT:
  status:  HCI_LMP_OR_LL_RESPONSE_TIMEOUT_ERROR
  bd_addr: 58:24:29:DB:A1:AC/P
DEBUG:bumble.host:simple pairing complete for 58:24:29:DB:A1:AC/P: status=HCI_LMP_OR_LL_RESPONSE_TIMEOUT_ERROR
DEBUG:bumble.host:### CONTROLLER -> HOST: HCI_DISCONNECTION_COMPLETE_EVENT:
  status:            HCI_SUCCESS
  connection_handle: 11
  reason:            HCI_LMP_OR_LL_RESPONSE_TIMEOUT_ERROR
DEBUG:bumble.host:### DISCONNECTION: [0x000B] 58:24:29:DB:A1:AC/P reason=34
DEBUG:bumble.device:*** Disconnection: [0x000B] 58:24:29:DB:A1:AC/P as PERIPHERAL, reason=3

The packets were sent over from the other device, I guess some packets are discarded.

@benquike
Copy link
Contributor

Have you considered writing this in a command line app? Why is a GUI app is needed

@zxzxwu
Copy link
Collaborator

zxzxwu commented Oct 11, 2023

I am quite surprised this can work...
From an automation perspective, it's better to be an instrumentation(so the lifecycle can be more stable), but it can be a good start here.

@barbibulle
Copy link
Collaborator Author

Have you considered writing this in a command line app? Why is a GUI app is needed

You’re right that the UI isn’t essential here. But I wanted a Java-only app for simplicity (easier to debug, more people are familiar with it on Android), and I don’t know of a way to write an Android Java app that can be purely a CLI app with no activity. Plus, writing Kotlin and Java is much nicer than C++.

@barbibulle
Copy link
Collaborator Author

I am quite surprised this can work... From an automation perspective, it's better to be an instrumentation(so the lifecycle can be more stable), but it can be a good start here.

You’re right. I wanted to start with something simple that most users could try out easily for themselves and send feedback/contribute, but it should evolve over time to offer more options for automation, including with things like a Mobly RPC interface.

@barbibulle
Copy link
Collaborator Author

FYI, I tried running bumble-pair and starting pairing from Android, it was stuck at the following step:

DEBUG:bumble.host:### CONTROLLER -> HOST: HCI_IO_CAPABILITY_REQUEST_EVENT:
  bd_addr: 58:24:29:DB:A1:AC/P
DEBUG:bumble.host:### HOST -> CONTROLLER: HCI_IO_CAPABILITY_REQUEST_REPLY_COMMAND:
  bd_addr:                     58:24:29:DB:A1:AC/P
  io_capability:               HCI_DISPLAY_YES_NO_IO_CAPABILITY
  oob_data_present:            0
  authentication_requirements: HCI_MITM_REQUIRED_GENERAL_BONDING_AUTHENTICATION_REQUIREMENTS
DEBUG:bumble.host:### CONTROLLER -> HOST: HCI_SIMPLE_PAIRING_COMPLETE_EVENT:
  status:  HCI_LMP_OR_LL_RESPONSE_TIMEOUT_ERROR
  bd_addr: 58:24:29:DB:A1:AC/P
DEBUG:bumble.host:simple pairing complete for 58:24:29:DB:A1:AC/P: status=HCI_LMP_OR_LL_RESPONSE_TIMEOUT_ERROR
DEBUG:bumble.host:### CONTROLLER -> HOST: HCI_DISCONNECTION_COMPLETE_EVENT:
  status:            HCI_SUCCESS
  connection_handle: 11
  reason:            HCI_LMP_OR_LL_RESPONSE_TIMEOUT_ERROR
DEBUG:bumble.host:### DISCONNECTION: [0x000B] 58:24:29:DB:A1:AC/P reason=34
DEBUG:bumble.device:*** Disconnection: [0x000B] 58:24:29:DB:A1:AC/P as PERIPHERAL, reason=3

The packets were sent over from the other device, I guess some packets are discarded.

The issue is fixed now in the latest commit.

@zxzxwu
Copy link
Collaborator

zxzxwu commented Oct 11, 2023

Can we have a workflow for this? Like building, and running some simple tests with Android Emulator.

@barbibulle
Copy link
Collaborator Author

Can we have a workflow for this? Like building, and running some simple tests with Android Emulator.

Yes, that would be great. I didn't have time to look into it yet (many steps, involving downloading SDKs, etc, there are GH actions available for it but they need to be investigated). It will also require running the emulator with SELinux disabled. I propose doing that as a future PR.

Copy link
Collaborator

@zxzxwu zxzxwu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

Comment on lines 42 to 46
mListener.onMessage("Waiting for connection on port " + mPort);
try (
ServerSocket serverSocket = new ServerSocket(mPort);
Socket clientSocket = serverSocket.accept()
) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In case user select port 0 (allocate by the system)

Suggested change
mListener.onMessage("Waiting for connection on port " + mPort);
try (
ServerSocket serverSocket = new ServerSocket(mPort);
Socket clientSocket = serverSocket.accept()
) {
try (
ServerSocket serverSocket = new ServerSocket(mPort);
mListener.onMessage("Waiting for connection on port " + serverSocket.getLocalPort());
Socket clientSocket = serverSocket.accept()
) {

@benquike
Copy link
Contributor

and I don’t know of a way to write an Android Java app that can be purely a CLI app with no activity. Plus, writing Kotlin and Java is much nicer than C++.

I mean a simple cmd program with no UI. I think for this purpose, GUI seems to be an overhaul, which makes it even harder to control (if we consider using it in some automate workflow). Also, if we have a cmd program, it is always easy to wrap it in a GUI app.

@zxzxwu
Copy link
Collaborator

zxzxwu commented Oct 11, 2023

and I don’t know of a way to write an Android Java app that can be purely a CLI app with no activity. Plus, writing Kotlin and Java is much nicer than C++.

I mean a simple cmd program with no UI. I think for this purpose, GUI seems to be an overhaul, which makes it even harder to control (if we consider using it in some automate workflow). Also, if we have a cmd program, it is always easy to wrap it in a GUI app.

I don't think there is any way to create CLI program in Android besides NDK. A proper way to achieve that is through instrumentation, which allows launching over adb shell am instrument -w <instrumentation> example. However, if GUI doesn't take any input and not considering background kill, there is no much difference between these two.

@barbibulle
Copy link
Collaborator Author

and I don’t know of a way to write an Android Java app that can be purely a CLI app with no activity. Plus, writing Kotlin and Java is much nicer than C++.

I mean a simple cmd program with no UI. I think for this purpose, GUI seems to be an overhaul, which makes it even harder to control (if we consider using it in some automate workflow). Also, if we have a cmd program, it is always easy to wrap it in a GUI app.

For sure, a UI-less mode would be useful as well. That's why I separated the UI (MainActivity.kt) from the proxy implementation (HciProxy.java) with a simple HciProxy class that can be instantiated by just passing a port number and a listener. So we could easily add a ui-less host that just uses the HciProxy class. Another option I'm considering going forward is to make the HciProxy into a service (currently it just runs in a regular thread, for convenience).

@benquike
Copy link
Contributor

benquike commented Oct 11, 2023

I don't think there is any way to create CLI program in Android besides NDK. A proper way to achieve that is through instrumentation, which allows launching over adb shell am instrument -w <instrumentation> example. However, if GUI doesn't take any input and not considering background kill, there is no much difference between these two.

Yes, NDK is the android native toolchain.

Actually there are some key differences. In addition to the difference in taking user inputs, other differences I have experienced include: when the screen is turned off, or some other app is brought to foreground, the app is is not working anymore. I think there are other ways to avoid this though.

@uael
Copy link
Contributor

uael commented Oct 11, 2023

Should we go for instrumentation then ? Could be cool if we can simplify the app and reduce the amount of code 👀

@barbibulle
Copy link
Collaborator Author

I don't think there is any way to create CLI program in Android besides NDK. A proper way to achieve that is through instrumentation, which allows launching over adb shell am instrument -w <instrumentation> example. However, if GUI doesn't take any input and not considering background kill, there is no much difference between these two.

Yes, NDK is the android native toolchain.

Actually there are some key differences. In addition to the difference in taking user inputs, other differences I have experienced include: when the screen is turned off, or some other app is brought to foreground, the app is is not working anymore. I think there are other ways to avoid this though.

For running in the background while other apps are in front, running as a background service rather than just a thread started from the main activity will do that. I intend to implement that in a separate PR.

@barbibulle
Copy link
Collaborator Author

Should we go for instrumentation then ? Could be cool if we can simplify the app and reduce the amount of code 👀

Would just starting the activity from am start like am start -n com.github.google.bumble.remotehci/.MainActivity --ez autostart true --ei port 9995 be enough for now. That works well.
I'm not familiar enough with am instrument, what advantages would it have in this case vs starting the activity or service?

@uael
Copy link
Contributor

uael commented Oct 13, 2023

Should we go for instrumentation then ? Could be cool if we can simplify the app and reduce the amount of code 👀

Would just starting the activity from am start like am start -n com.github.google.bumble.remotehci/.MainActivity --ez autostart true --ei port 9995 be enough for now. That works well.
I'm not familiar enough with am instrument, what advantages would it have in this case vs starting the activity or service?

It can reduce the amount of files required in bumble sources, but apart from this I don't know

@barbibulle barbibulle merged commit 88392ef into main Oct 17, 2023
51 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants