| // |
| // 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 <ctime> |
| |
| #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<NetworkService> { |
| 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<CommandHandler> InitializeCommandHandlers(); |
| void InitializeNetworkOperator(); |
| void InitializeSimOperator(); |
| |
| bool WakeupFromSleep(); |
| bool IsHasNetwork(); |
| void UpdateRegisterState(RegistrationState state); |
| void AdjustSignalStrengthValue(int& value, const std::pair<int, int>& 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<NetworkOperator> 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 percentange 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<int, int>& 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); |
| |
| bool first_signal_strength_request_; // For time update |
| time_t 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_; |
| }; |
| |
| } // namespace cuttlefish |