// // Copyright (C) 2020 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. #pragma once #include #include #include "host/commands/modem_simulator/data_service.h" #include "host/commands/modem_simulator/misc_service.h" #include "host/commands/modem_simulator/modem_service.h" #include "host/commands/modem_simulator/network_service_constants.h" #include "host/commands/modem_simulator/sim_service.h" namespace cuttlefish { class NetworkService : public ModemService, public std::enable_shared_from_this { public: NetworkService(int32_t service_id_, ChannelMonitor* channel_monitor, ThreadLooper* thread_looper); ~NetworkService() = default; NetworkService(const NetworkService &) = delete; NetworkService &operator=(const NetworkService &) = delete; void SetupDependency(MiscService* misc, SimService* sim, DataService* data); void HandleRadioPowerReq(const Client& client); void HandleRadioPower(const Client& client, std::string& command); void HandleSignalStrength(const Client& client); void HandleQueryNetworkSelectionMode(const Client& client); void HandleRequestOperator(const Client& client); void HandleQueryAvailableNetwork(const Client& client); void HandleSetNetworkSelectionMode(const Client& client, std::string& command); void HandleVoiceNetworkRegistration(const Client& client, std::string& command); void HandleDataNetworkRegistration(const Client& client, std::string& command); void HandleGetPreferredNetworkType(const Client& client); void HandleQuerySupportedTechs(const Client& client); void HandleSetPreferredNetworkType(const Client& client, std::string& command); void HandleNetworkRegistration(cuttlefish::SharedFD client, std::string& command); void HandleReceiveRemoteVoiceDataReg(const Client& client, std::string& command); void HandleReceiveRemoteCTEC(const Client& client, std::string& command); void HandleReceiveRemoteSignal(const Client& client, std::string& command); void OnSimStatusChanged(SimService::SimStatus sim_status); void OnVoiceRegisterStateChanged(); void OnDataRegisterStateChanged(); void OnSignalStrengthChanged(); enum RegistrationState { NET_REGISTRATION_UNREGISTERED = 0, NET_REGISTRATION_HOME = 1, NET_REGISTRATION_SEARCHING = 2, NET_REGISTRATION_DENIED = 3, NET_REGISTRATION_UNKNOWN = 4, NET_REGISTRATION_ROAMING = 5, NET_REGISTRATION_EMERGENCY = 8 }; RegistrationState GetVoiceRegistrationState() const; bool isRadioOff() const { return radio_state_ == RADIO_STATE_OFF; } private: void InitializeServiceState(); std::vector InitializeCommandHandlers(); void InitializeNetworkOperator(); void InitializeSimOperator(); bool WakeupFromSleep(); bool IsHasNetwork(); void UpdateRegisterState(RegistrationState state); void AdjustSignalStrengthValue(int& value, const std::pair& range); MiscService* misc_service_ = nullptr; SimService* sim_service_ = nullptr; DataService* data_service_ = nullptr; enum RadioState : int32_t { RADIO_STATE_OFF, RADIO_STATE_ON, }; RadioState radio_state_; /* Operator */ struct NetworkOperator { enum OperatorState { OPER_STATE_UNKNOWN = 0, OPER_STATE_AVAILABLE = 1, OPER_STATE_CURRENT = 2, OPER_STATE_FORBIDDEN = 3 }; std::string numeric; std::string long_name; std::string short_name; OperatorState operator_state; NetworkOperator() {} NetworkOperator(const std::string& number, const std::string& ln, const std::string& sn, OperatorState state) : numeric(number), long_name(ln), short_name(sn), operator_state(state) {} }; enum OperatorSelectionMode { OPER_SELECTION_AUTOMATIC = 0, OPER_SELECTION_MANUAL, OPER_SELECTION_DEREGISTRATION, OPER_SELECTION_SET_FORMAT, OPER_SELECTION_MANUAL_AUTOMATIC }; std::vector operator_list_; std::string current_operator_numeric_ = ""; OperatorSelectionMode oper_selection_mode_; /* SignalStrength */ struct SignalStrength { int gsm_rssi; /* Valid values are (0-31, 99) as defined in TS 27.007 8.5 */ int gsm_ber; /* bit error rate (0-7, 99) as defined in TS 27.007 8.5 */ int cdma_dbm; /* Valid values are positive integers. This value is the actual RSSI value * multiplied by -1. Example: If the actual RSSI is -75, then this response * value will be 75. */ int cdma_ecio; /* Valid values are positive integers. This value is the actual Ec/Io multiplied * by -10. Example: If the actual Ec/Io is -12.5 dB, then this response value * will be 125. */ int evdo_dbm; /* Refer cdma_dbm */ int evdo_ecio; /* Refer cdma_ecio */ int evdo_snr; /* Valid values are 0-8. 8 is the highest signal to noise ratio. */ int lte_rssi; /* Refer gsm_rssi */ int lte_rsrp; /* The current Reference Signal Receive Power in dBm multiplied by -1. * Range: 44 to 140 dBm * INT_MAX: 0x7FFFFFFF denotes invalid value. * Reference: 3GPP TS 36.133 9.1.4 */ int lte_rsrq; /* The current Reference Signal Receive Quality in dB multiplied by -1. * Range: 20 to 3 dB. * INT_MAX: 0x7FFFFFFF denotes invalid value. * Reference: 3GPP TS 36.133 9.1.7 */ int lte_rssnr; /* The current reference signal signal-to-noise ratio in 0.1 dB units. * Range: -200 to +300 (-200 = -20.0 dB, +300 = 30dB). * INT_MAX : 0x7FFFFFFF denotes invalid value. * Reference: 3GPP TS 36.101 8.1.1 */ int lte_cqi; /* The current Channel Quality Indicator. * Range: 0 to 15. * INT_MAX : 0x7FFFFFFF denotes invalid value. * Reference: 3GPP TS 36.101 9.2, 9.3, A.4 */ int lte_ta; /* timing advance in micro seconds for a one way trip from cell to device. * Approximate distance can be calculated using 300m/us * timingAdvance. * Range: 0 to 0x7FFFFFFE * INT_MAX : 0x7FFFFFFF denotes invalid value. * Reference: 3GPP 36.321 section 6.1.3.5 */ int tdscdma_rscp; /* P-CCPCH RSCP as defined in TS 25.225 5.1.1 * Valid values are (0-96, 255) as defined in TS 27.007 8.69 * INT_MAX denotes that the value is invalid/unreported. */ int wcdma_rssi; /* Refer gsm_rssi */ int wcdma_ber; /* Refer gsm_ber */ int32_t nr_ss_rsrp; /* SS reference signal received power, multiplied by -1. * Reference: 3GPP TS 38.215. * Range [44, 140], INT_MAX means invalid/unreported. */ int32_t nr_ss_rsrq; /* SS reference signal received quality, multiplied by -1. * Reference: 3GPP TS 38.215. * Range [3, 20], INT_MAX means invalid/unreported. */ int32_t nr_ss_sinr; /* SS signal-to-noise and interference ratio. * Reference: 3GPP TS 38.215 section 5.1.*, 3GPP TS 38.133 section 10.1.16.1. * Range [-23, 40], INT_MAX means invalid/unreported. */ int32_t nr_csi_rsrp; /* CSI reference signal received power, multiplied by -1. * Reference: 3GPP TS 38.215. * Range [44, 140], INT_MAX means invalid/unreported. */ int32_t nr_csi_rsrq; /* CSI reference signal received quality, multiplied by -1. * Reference: 3GPP TS 38.215. * Range [3, 20], INT_MAX means invalid/unreported. */ int32_t nr_csi_sinr; /* CSI signal-to-noise and interference ratio. * Reference: 3GPP TS 138.215 section 5.1.*, 3GPP TS 38.133 section 10.1.16.1. * Range [-23, 40], INT_MAX means invalid/unreported. */ SignalStrength() : gsm_rssi(kRssiUnknownValue), gsm_ber(kBerUnknownValue), cdma_dbm(kDbmUnknownValue), cdma_ecio(kEcioUnknownValue), evdo_dbm(kDbmUnknownValue), evdo_ecio(kEcioUnknownValue), evdo_snr(kSnrUnknownValue), lte_rssi(kRssiUnknownValue), lte_rsrp(INT_MAX), lte_rsrq(INT_MAX), lte_rssnr(INT_MAX), lte_cqi(INT_MAX), lte_ta(INT_MAX), tdscdma_rscp(INT_MAX), wcdma_rssi(kRssiUnknownValue), wcdma_ber(kBerUnknownValue), nr_ss_rsrp(INT_MAX), nr_ss_rsrq(INT_MAX), nr_ss_sinr(INT_MAX), nr_csi_rsrp(INT_MAX), nr_csi_rsrq(INT_MAX), nr_csi_sinr(INT_MAX) {} }; // There's no such thing as a percentage for signal strength in the real // world, as for example for battery usage, this percent value is used to pick // a value within the corresponding signal strength values range for emulation // purposes only. int signal_strength_percent_{80}; static int GetValueInRange(const std::pair& range, int percent); static std::string BuildCSQCommandResponse( const SignalStrength& signal_strength); SignalStrength GetCurrentSignalStrength(); /* Data / voice Registration State */ struct NetworkRegistrationStatus { enum RegistrationUnsolMode { REGISTRATION_UNSOL_DISABLED = 0, REGISTRATION_UNSOL_ENABLED = 1, REGISTRATION_UNSOL_ENABLED_FULL = 2 }; enum AccessTechnoloy { ACESS_TECH_GSM = 0, ACESS_TECH_GSM_COMPACT = 1, ACESS_TECH_UTRAN = 2, ACESS_TECH_EGPRS = 3, ACESS_TECH_HSDPA = 4, ACESS_TECH_HSUPA = 5, ACESS_TECH_HSPA = 6, ACESS_TECH_EUTRAN = 7, ACESS_TECH_EC_GSM_IoT = 8, ACESS_TECH_E_UTRAN = 9, ACESS_TECH_E_UTRA = 10, ACESS_TECH_NR = 11, ACESS_TECH_NG_RAN = 12, ACESS_TECH_E_UTRA_NR = 13 }; NetworkRegistrationStatus() : unsol_mode(REGISTRATION_UNSOL_ENABLED_FULL), registration_state(NET_REGISTRATION_UNREGISTERED), network_type(ACESS_TECH_EUTRAN) {} RegistrationUnsolMode unsol_mode; RegistrationState registration_state; AccessTechnoloy network_type; }; NetworkRegistrationStatus voice_registration_status_; NetworkRegistrationStatus data_registration_status_; enum ModemTechnology { M_MODEM_TECH_GSM = 1 << 0, M_MODEM_TECH_WCDMA = 1 << 1, M_MODEM_TECH_CDMA = 1 << 2, M_MODEM_TECH_EVDO = 1 << 3, M_MODEM_TECH_TDSCDMA= 1 << 4, M_MODEM_TECH_LTE = 1 << 5, M_MODEM_TECH_NR = 1 << 6, }; ModemTechnology current_network_mode_; int preferred_network_mode_; int modem_radio_capability_; NetworkRegistrationStatus::AccessTechnoloy getNetworkTypeFromTech(ModemTechnology modemTech); int getModemTechFromPrefer(int preferred_mask); ModemTechnology getTechFromNetworkType(NetworkRegistrationStatus::AccessTechnoloy act); std::atomic first_signal_strength_request_; // For time update std::atomic android_last_signal_time_; class KeepSignalStrengthChangingLoop { public: KeepSignalStrengthChangingLoop(NetworkService& network_service); void Start(); private: void UpdateSignalStrengthCallback(); NetworkService& network_service_; std::atomic_flag loop_started_; }; KeepSignalStrengthChangingLoop keep_signal_strength_changing_loop_; void HandleIdentifierDisclosure(const std::string& command); void HandleSecurityAlgorithmUpdate(const std::string& command); }; } // namespace cuttlefish