diff --git a/src/mm_zbus/consts.rs b/src/mm_zbus/consts.rs index 1ce339a..7029565 100644 --- a/src/mm_zbus/consts.rs +++ b/src/mm_zbus/consts.rs @@ -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; +} diff --git a/src/radio/radio_data.rs b/src/radio/radio_data.rs index 32ef9b7..cc77ec6 100644 --- a/src/radio/radio_data.rs +++ b/src/radio/radio_data.rs @@ -5,21 +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; @@ -30,6 +35,7 @@ pub struct RadioDataShared { indication: Option>, modem_proxy: Option>, + simple_proxy: Option>, } #[derive(Default)] @@ -46,6 +52,9 @@ impl RadioDataShared { { 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)?; @@ -56,6 +65,7 @@ impl RadioDataShared { { 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)?; @@ -137,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], @@ -147,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 = 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 = 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 = try { + let ipv6 = bearer_proxy.ip6_config().await.ok()?; + TryInto::::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::::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<()> { diff --git a/src/radio/radio_messaging.rs b/src/radio/radio_messaging.rs index a62a2e9..a0b6c9e 100644 --- a/src/radio/radio_messaging.rs +++ b/src/radio/radio_messaging.rs @@ -135,8 +135,9 @@ impl RadioMessagingShared { pub(crate) fn unbind(shared_in: &Arc>) -> Result<(), Error> { let mut shared = block_on(shared_in.write()); - shared.modem_bound = false; shared.modem_proxy = None; + shared.messaging_proxy = None; + shared.modem_bound = false; Ok(()) } diff --git a/src/radio/radio_modem.rs b/src/radio/radio_modem.rs index 0196d75..ae16b87 100644 --- a/src/radio/radio_modem.rs +++ b/src/radio/radio_modem.rs @@ -111,7 +111,7 @@ impl RadioModemShared { } let ind = self.indication.as_ref().ok_or(Error::noneopt())?; let state = self.modem_proxy.as_ref().ok_or(Error::noneopt())?.state().await?; - let enabled = state == mm_modem_state::ENABLED || state == mm_modem_state::REGISTERED; + let enabled = state > mm_modem_state::ENABLED; ind.radioStateChanged( RadioIndicationType::UNSOLICITED, if enabled { RadioState::ON } else { RadioState::OFF }, diff --git a/src/radio/radio_network.rs b/src/radio/radio_network.rs index 80cdf68..2b9579d 100644 --- a/src/radio/radio_network.rs +++ b/src/radio/radio_network.rs @@ -205,7 +205,17 @@ impl IRadioNetworkAsyncServer for RadioNetwork { async fn getDataRegistrationState(&self, serial: i32) -> binder::Result<()> { entry_check!(&self, serial, getDataRegistrationStateResponse, &def()); - okay!(&self, serial, getDataRegistrationStateResponse, &def()) + let rsr = RegStateResult { + regState: RegState::REG_HOME, + rat: RadioTechnology::LTE, + cellIdentity: CellIdentity::Lte(get_fake_cell_identity_lte()), + registeredPlmn: "25501".to_string(), + accessTechnologySpecificInfo: AccessTechnologySpecificInfo::EutranInfo( + Default::default(), + ), + ..Default::default() + }; + okay!(&self, serial, getDataRegistrationStateResponse, &rsr) } async fn getImsRegistrationState(&self, serial: i32) -> binder::Result<()> {