aboutsummaryrefslogtreecommitdiff
path: root/host/commands/modem_simulator/network_service.h
blob: fd22fa7290fbab8ee2ab313cb9d07d3e04e29afe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
//
// 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 <atomic>
#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 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<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);

  std::atomic<bool> first_signal_strength_request_;  // For time update
  std::atomic<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_;

  void HandleIdentifierDisclosure(const std::string& command);
  void HandleSecurityAlgorithmUpdate(const std::string& command);
};

}  // namespace cuttlefish