Skip to content

Commit

Permalink
feat: integrate adb port forwarding (#2451)
Browse files Browse the repository at this point in the history
  • Loading branch information
E1int authored Nov 8, 2024
1 parent ddd0b9c commit 55313e0
Show file tree
Hide file tree
Showing 20 changed files with 874 additions and 75 deletions.
100 changes: 64 additions & 36 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ authors = ["alvr-org"]
license = "MIT"

[workspace.dependencies]
alvr_adb = { path = "alvr/adb" }
alvr_audio = { path = "alvr/audio" }
alvr_client_core = { path = "alvr/client_core" }
alvr_common = { path = "alvr/common" }
Expand Down
16 changes: 16 additions & 0 deletions alvr/adb/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "alvr_adb"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
authors.workspace = true
license.workspace = true

[dependencies]
alvr_common.workspace = true
alvr_filesystem.workspace = true
alvr_server_io.workspace = true

anyhow = "1"
ureq = "2.10"
zip = "2"
33 changes: 33 additions & 0 deletions alvr/adb/src/connection_state.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// https://cs.android.com/android/platform/superproject/main/+/7dbe542b9a93fb3cee6c528e16e2d02a26da7cc0:packages/modules/adb/adb.h;l=104-122
#[derive(Debug)]
pub enum ConnectionState {
Authorizing,
Bootloader,
Connecting,
Detached,
Device,
Host,
NoPermissions, // https://cs.android.com/android/platform/superproject/main/+/main:system/core/diagnose_usb/diagnose_usb.cpp;l=83-90
Offline,
Recovery,
Rescue,
Sideload,
Unauthorized,
}

pub fn parse(value: &str) -> Option<ConnectionState> {
match value {
"authorizing" => Some(ConnectionState::Authorizing),
"bootloader" => Some(ConnectionState::Bootloader),
"connecting" => Some(ConnectionState::Connecting),
"detached" => Some(ConnectionState::Detached),
"device" => Some(ConnectionState::Device),
"host" => Some(ConnectionState::Host),
"offline" => Some(ConnectionState::Offline),
"recovery" => Some(ConnectionState::Recovery),
"rescue" => Some(ConnectionState::Rescue),
"sideload" => Some(ConnectionState::Sideload),
"unauthorized" => Some(ConnectionState::Unauthorized),
_ => None,
}
}
68 changes: 68 additions & 0 deletions alvr/adb/src/device.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use crate::{
connection_state::{self, ConnectionState},
transport_type::{self, TransportType},
};

// https://cs.android.com/android/platform/superproject/main/+/7dbe542b9a93fb3cee6c528e16e2d02a26da7cc0:packages/modules/adb/transport.cpp;l=1409
// The serial number is printed with a "%-22s" format, meaning that it's a left-aligned space-padded string of 22 characters.
const SERIAL_NUMBER_COLUMN_LENGTH: usize = 22;

// https://cs.android.com/android/platform/superproject/main/+/7dbe542b9a93fb3cee6c528e16e2d02a26da7cc0:packages/modules/adb/transport.cpp;l=1398
#[derive(Debug)]
pub struct Device {
pub connection_state: Option<ConnectionState>,
pub device: Option<String>,
pub model: Option<String>,
pub product: Option<String>,
pub serial: Option<String>,
pub transport_type: Option<TransportType>,
}

pub fn parse(line: &str) -> Option<Device> {
if line.len() < SERIAL_NUMBER_COLUMN_LENGTH {
return None;
}
let (left, right) = line.split_at(SERIAL_NUMBER_COLUMN_LENGTH);
let serial = left
.contains("(no serial number)")
.then(|| left.trim().to_owned());
let mut remaining = right.trim();

let connection_state = if remaining.starts_with("no permissions") {
// Since the current user's name can be printed in the error message,
// we are gambling that there's not a "]" in it.
if let Some((_, right)) = remaining.split_once(']') {
remaining = right;
Some(ConnectionState::NoPermissions)
} else {
None
}
} else if let Some((left, right)) = remaining.split_once(' ') {
remaining = right;
connection_state::parse(left)
} else {
None
};

let mut slices = remaining.split_whitespace();
let product = slices.next().and_then(parse_pair);
let model = slices.next().and_then(parse_pair);
let device = slices.next().and_then(parse_pair);
let transport_type = slices.next().and_then(transport_type::parse);

Some(Device {
connection_state,
device,
model,
product,
serial,
transport_type,
})
}

fn parse_pair(pair: &str) -> Option<String> {
let mut slice = pair.split(':');
let _key = slice.next();

slice.next().map(|value| value.to_string())
}
Loading

0 comments on commit 55313e0

Please sign in to comment.