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

mm-radio: Mobile data initial bring-up #18

Draft
wants to merge 10 commits into
base: main
Choose a base branch
from
61 changes: 33 additions & 28 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* Copyright (C) 2023 The GloDroid Project
*/

#![warn(clippy::unwrap_used, clippy::expect_used)]
#![feature(async_closure)]
#![feature(try_blocks)]

Expand All @@ -21,6 +22,7 @@ use android_hardware_radio_config::aidl::android::hardware::radio::config::IRadi
use android_logger::LogId;
use async_std::task::block_on;
use log::{error, info};
use utils::error::Error;

fn main() {
// Initialize android logging.
Expand All @@ -45,42 +47,45 @@ fn main() {
error!("{}", panic_info);
}));

// Android use different path for dbus socket, set it via env variable.
if std::env::var("DBUS_SYSTEM_BUS_ADDRESS").is_err() {
std::env::set_var(
"DBUS_SYSTEM_BUS_ADDRESS",
"unix:path=/mnt/var/run/dbus/system_bus_socket",
);
}
let result: Result<(), Error> = try {
// Android use different path for dbus socket, set it via env variable.
if std::env::var("DBUS_SYSTEM_BUS_ADDRESS").is_err() {
std::env::set_var(
"DBUS_SYSTEM_BUS_ADDRESS",
"unix:path=/mnt/var/run/dbus/system_bus_socket",
);
}

info!("mm-radio is starting.");
info!("mm-radio is starting.");

let connection = block_on(zbus::Connection::system()).unwrap();
let rhm = create_radio_hal_manager(&connection).unwrap();
let connection = block_on(zbus::Connection::system())?;
let rhm = create_radio_hal_manager(&connection)?;

radio_hal_manager::add_binder_service!(RadioConfig::default(), RadioConfig, "default").unwrap();
const MAX_SLOT: usize = 3;
const FIRST_SLOT: usize = 1;
let mut slots_registered = 0;
for slot in FIRST_SLOT..MAX_SLOT {
if register_frontend_element(&rhm, format!("slot{slot}").as_str()).is_err() {
break;
radio_hal_manager::add_binder_service!(RadioConfig::default(), RadioConfig, "default")?;
const MAX_SLOT: usize = 3;
const FIRST_SLOT: usize = 1;
let mut slots_registered = 0;
for slot in FIRST_SLOT..MAX_SLOT {
if register_frontend_element(&rhm, format!("slot{slot}").as_str()).is_err() {
break;
}
slots_registered += 1;
}
slots_registered += 1;
}

if slots_registered == 0 {
panic!("Failed to register any slot, please check your manifest");
}
if slots_registered == 0 {
panic!("Failed to register any slot, please check your manifest");
}

info!("Registered {} slots for modems", slots_registered);
info!("Registered {} slots for modems", slots_registered);

bind_modems(&rhm);
bind_modems(&rhm)?;

info!("Successfully registered mm-radio service.");
info!("Successfully registered mm-radio service.");

info!("Joining thread pool now.");
binder::ProcessState::join_thread_pool();
info!("Joining thread pool now.");
binder::ProcessState::join_thread_pool();

panic!("Should not reach here.");
panic!("Should not reach here.");
};
result.unwrap_or_else(|e| e.log());
}
9 changes: 9 additions & 0 deletions src/mm_zbus/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,12 @@ pub(crate) mod mm_sms_state {
pub(crate) const SENDING: u32 = 4;
pub(crate) const SENT: u32 = 5;
}

pub(crate) mod mm_bearer_ip_family {
pub(crate) const NONE: u32 = 0;
pub(crate) const IPV4: u32 = 1 << 0;
pub(crate) const IPV6: u32 = 1 << 1;
pub(crate) const IPV4V6: u32 = 1 << 2;
pub(crate) const NON_IP: u32 = 1 << 3;
pub(crate) const ANY: u32 = 0xFFFFFFF7;
}
126 changes: 112 additions & 14 deletions src/radio/radio_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,26 @@
* Copyright (C) 2023 The GloDroid Project
*/

use crate::mm_zbus::consts::mm_bearer_ip_family;
use crate::mm_zbus::mm_bearer_proxy::BearerProxy;
use crate::mm_zbus::mm_modem_proxy::ModemProxy;
use crate::mm_zbus::mm_simple_proxy::SimpleProxy;
use crate::utils::error::Error;
use crate::utils::iradio::{
declare_async_iradio, entry_check, not_implemented, okay, shared, sharedmut,
declare_async_iradio, entry_check, not_implemented, okay, resp_err, shared, sharedmut,
};
use android_hardware_radio::aidl::android::hardware::radio::AccessNetwork::AccessNetwork;
use android_hardware_radio_data::aidl::android::hardware::radio::data::DataRequestReason::DataRequestReason as DRR;
use android_hardware_radio_data::aidl::android::hardware::radio::data::{
DataProfileInfo::*, DataThrottlingAction::*, IRadioData::*, IRadioDataIndication::*,
IRadioDataResponse::*, KeepaliveRequest::*, LinkAddress::*, SliceInfo::*,
DataCallFailCause::*, DataProfileInfo::*, DataThrottlingAction::*, IRadioData::*,
IRadioDataIndication::*, IRadioDataResponse::*, KeepaliveRequest::*, LinkAddress::*,
PdpProtocolType::*, SetupDataCallResult::*, SliceInfo::*,
};
use async_std::sync::RwLock;
use async_std::task::block_on;
use binder::{BinderFeatures, Strong};
use log::info;
use std::collections::HashMap;
use std::sync::Arc;
use zbus::export::async_trait::async_trait;

Expand All @@ -29,6 +35,7 @@ pub struct RadioDataShared {
indication: Option<binder::Strong<dyn IRadioDataIndication>>,

modem_proxy: Option<ModemProxy<'static>>,
simple_proxy: Option<SimpleProxy<'static>>,
}

#[derive(Default)]
Expand All @@ -37,36 +44,46 @@ pub struct RadioData {
}

impl RadioDataShared {
pub fn bind(shared_in: &Arc<RwLock<RadioDataShared>>, modem_proxy: &ModemProxy<'static>) {
pub(crate) fn bind(
shared_in: &Arc<RwLock<RadioDataShared>>,
modem_proxy: &ModemProxy<'static>,
) -> Result<(), Error> {
/* Setup shared structure */
{
let mut shared = block_on(shared_in.write());
shared.modem_proxy = Some(modem_proxy.clone());
let conn = modem_proxy.connection();
let path = modem_proxy.path().to_string();
shared.simple_proxy = Some(block_on(SimpleProxy::builder(conn).path(path)?.build())?);
shared.modem_bound = true;
}
Self::notify_framework(shared_in);
Self::notify_framework(shared_in)?;
Ok(())
}

pub fn unbind(shared_in: &Arc<RwLock<RadioDataShared>>) {
pub(crate) fn unbind(shared_in: &Arc<RwLock<RadioDataShared>>) -> Result<(), Error> {
{
let mut shared = block_on(shared_in.write());
shared.modem_proxy = None;
shared.simple_proxy = None;
shared.modem_bound = false;
}
Self::notify_framework(shared_in);
Self::notify_framework(shared_in)?;
Ok(())
}

fn is_initialized(&self) -> bool {
self.response.is_some() && self.indication.is_some() && self.modem_bound
}

fn notify_framework(shared_in: &Arc<RwLock<RadioDataShared>>) {
fn notify_framework(shared_in: &Arc<RwLock<RadioDataShared>>) -> Result<(), Error> {
let shared = block_on(shared_in.read());
if !shared.is_initialized() {
return;
return Ok(());
}
let ind = shared.indication.as_ref().unwrap();
ind.dataCallListChanged(Default::default(), Default::default()).unwrap();
let ind = shared.indication.as_ref().ok_or(Error::noneopt())?;
ind.dataCallListChanged(Default::default(), Default::default())?;
Ok(())
}
}

Expand Down Expand Up @@ -130,7 +147,7 @@ impl IRadioDataAsyncServer for RadioData {
&self,
serial: i32,
_access_network: AccessNetwork,
_data_profile_info: &DataProfileInfo,
data_profile_info: &DataProfileInfo,
_roaming_allowed: bool,
_reason: DRR,
_addresses: &[LinkAddress],
Expand All @@ -140,7 +157,88 @@ impl IRadioDataAsyncServer for RadioData {
_match_all_rule_allowed: bool,
) -> binder::Result<()> {
entry_check!(&self, serial, setupDataCallResponse, &Default::default());
okay!(&self, serial, setupDataCallResponse, &Default::default())
info!("setupDataCall: {:?}", data_profile_info);
let result: Result<SetupDataCallResult, Error> = try {
let shared = shared!(&self);
let mut props = HashMap::new();
props.insert("apn", data_profile_info.apn.clone().into());
props.insert("user", data_profile_info.user.clone().into());
props.insert("password", data_profile_info.password.clone().into());
let ip_family = match data_profile_info.protocol {
PdpProtocolType::IPV4V6 => mm_bearer_ip_family::IPV4V6,
PdpProtocolType::IP => mm_bearer_ip_family::IPV4,
PdpProtocolType::IPV6 => mm_bearer_ip_family::IPV6,
PdpProtocolType::NON_IP => mm_bearer_ip_family::NON_IP,
_ => mm_bearer_ip_family::ANY,
};
props.insert("ip-type", ip_family.into());
let result = shared.simple_proxy.as_ref().ok_or(Error::noneopt())?.connect(props).await;
if result.is_err() {
error!("setupDataCall error: {:?}", result);
return resp_err!(
&self,
serial,
RadioError::INTERNAL_ERR,
setupDataCallResponse,
&Default::default()
);
}

let path = result?;
let conn = shared.simple_proxy.as_ref().ok_or(Error::noneopt())?.connection();
let bearer_proxy = BearerProxy::builder(conn).path(path)?.build().await?;

let connected = bearer_proxy.connected().await?;
info!("setupDataCall connected: {connected}");

let ipv4 = bearer_proxy.ip4_config().await?;
info!("setupDataCall ipv4: {:?}", ipv4);
let addrv4 = LinkAddress {
address: ipv4.get("address").ok_or(Error::noneopt())?.to_owned().try_into()?,
..Default::default()
};

let mut dnses: Vec<String> = Vec::new();
for i in 1..=2 {
if let Some(opt) = ipv4.get(&format!("dns{i}")) {
dnses.push(opt.to_owned().try_into()?);
}
}

let mtu_v6: Option<i32> = try {
let ipv6 = bearer_proxy.ip6_config().await.ok()?;
TryInto::<u32>::try_into(ipv6.get("mtu")?).ok()? as i32
};

let mtu_v6 = mtu_v6.unwrap_or(1500);

SetupDataCallResult {
cid: 1,
active: DATA_CONNECTION_STATUS_ACTIVE,
r#type: data_profile_info.protocol,
ifname: bearer_proxy.interface().await?,
addresses: vec![addrv4],
dnses,
gateways: vec![ipv4
.get("gateway")
.ok_or(Error::noneopt())?
.to_owned()
.try_into()?],
pcscf: vec![],
mtuV4: TryInto::<u32>::try_into(ipv4.get("mtu").ok_or(Error::noneopt())?)? as i32,
mtuV6: mtu_v6,
pduSessionId: 0,
cause: DataCallFailCause::NONE,
defaultQos: Default::default(),
handoverFailureMode: HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_SETUP_NORMAL,
qosSessions: vec![],
sliceInfo: None,
suggestedRetryTime: 0,
trafficDescriptors: vec![],
}
};
let result = result?;
okay!(&self, serial, setupDataCallResponse, &result)
}

async fn startHandover(&self, serial: i32, _call_id: i32) -> binder::Result<()> {
Expand Down Expand Up @@ -172,7 +270,7 @@ impl IRadioDataAsyncServer for RadioData {
shared.indication = Some(radio_indication.clone());
}

RadioDataShared::notify_framework(&self.shared);
RadioDataShared::notify_framework(&self.shared)?;

Ok(())
}
Expand Down
Loading