• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (C) 2020 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 
16 #include "host/commands/modem_simulator/nvram_config.h"
17 
18 #include <android-base/logging.h>
19 #include <json/json.h>
20 
21 #include <fstream>
22 #include <mutex>
23 #include <sstream>
24 
25 #include "common/libs/utils/files.h"
26 #include "host/commands/modem_simulator/device_config.h"
27 
28 namespace cuttlefish {
29 
30 const char* kInstances            = "instances";
31 const char* kNetworkSelectionMode = "network_selection_mode";
32 const char* kOperatorNumeric      = "operator_numeric";
33 const char* kModemTechnoloy       = "modem_technoloy";
34 const char* kPreferredNetworkMode = "preferred_network_mode";
35 const char* kEmergencyMode        = "emergency_mode";
36 const char* kSimType              = "sim_type";
37 
38 const int   kDefaultNetworkSelectionMode  = 0;     // AUTOMATIC
39 const std::string kDefaultOperatorNumeric = "";
40 const int   kDefaultModemTechnoloy        = 0x10;  // LTE
41 const int   kDefaultPreferredNetworkMode  = 0x13;  // LTE | WCDMA | GSM
42 const bool  kDefaultEmergencyMode         = false;
43 
44 /**
45  * Creates the (initially empty) config object and populates it with values from
46  * the config file "modem_nvram.json" located in the cuttlefish instance path,
47  * or uses the default value if the config file not exists,
48  * Returns nullptr if there was an error loading from file
49  */
BuildConfigImpl(size_t num_instances,int sim_type)50 NvramConfig* NvramConfig::BuildConfigImpl(size_t num_instances, int sim_type) {
51   auto nvram_config_path =
52       cuttlefish::modem::DeviceConfig::PerInstancePath("modem_nvram.json");
53 
54   auto ret = new NvramConfig(num_instances, sim_type);
55   if (ret) {
56     if (!cuttlefish::FileExists(nvram_config_path) ||
57         !cuttlefish::FileHasContent(nvram_config_path.c_str())) {
58       ret->InitDefaultNvramConfig();
59     } else {
60       auto loaded = ret->LoadFromFile(nvram_config_path.c_str());
61       if (!loaded) {
62         delete ret;
63         return nullptr;
64       }
65     }
66   }
67   return ret;
68 }
69 
70 std::unique_ptr<NvramConfig> NvramConfig::s_nvram_config;
71 
InitNvramConfigService(size_t num_instances,int sim_type)72 void NvramConfig::InitNvramConfigService(size_t num_instances, int sim_type) {
73   static std::once_flag once_flag;
74 
75   std::call_once(once_flag, [num_instances, sim_type]() {
76     NvramConfig::s_nvram_config.reset(BuildConfigImpl(num_instances, sim_type));
77   });
78 }
79 
Get()80 /* static */ const NvramConfig* NvramConfig::Get() {
81   return s_nvram_config.get();
82 }
83 
SaveToFile()84 void NvramConfig::SaveToFile() {
85   auto nvram_config = Get();
86   auto nvram_config_file = nvram_config->ConfigFileLocation();
87   nvram_config->SaveToFile(nvram_config_file);
88 }
89 
NvramConfig(size_t num_instances,int sim_type)90 NvramConfig::NvramConfig(size_t num_instances, int sim_type)
91     : total_instances_(num_instances),
92       sim_type_(sim_type),
93       dictionary_(new Json::Value()) {}
94 // Can't use '= default' on the header because the compiler complains of
95 // Json::Value being an incomplete type
96 NvramConfig::~NvramConfig() = default;
97 
98 NvramConfig::NvramConfig(NvramConfig&&) = default;
99 NvramConfig& NvramConfig::operator=(NvramConfig&&) = default;
100 
ForInstance(int num) const101 NvramConfig::InstanceSpecific NvramConfig::ForInstance(int num) const {
102   return InstanceSpecific(this, std::to_string(num));
103 }
104 
ConfigFileLocation() const105 std::string NvramConfig::ConfigFileLocation() const {
106   return cuttlefish::AbsolutePath(
107       cuttlefish::modem::DeviceConfig::PerInstancePath("modem_nvram.json"));
108 }
109 
LoadFromFile(const char * file)110 bool NvramConfig::LoadFromFile(const char* file) {
111   auto real_file_path = cuttlefish::AbsolutePath(file);
112   if (real_file_path.empty()) {
113     LOG(ERROR) << "Could not get real path for file " << file;
114     return false;
115   }
116 
117   Json::CharReaderBuilder builder;
118   std::ifstream ifs = modem::DeviceConfig::open_ifstream_crossplat(real_file_path.c_str());
119   std::string errorMessage;
120   if (!Json::parseFromStream(builder, ifs, dictionary_.get(), &errorMessage)) {
121     LOG(ERROR) << "Could not read config file " << file << ": "
122                << errorMessage;
123     return false;
124   }
125   return true;
126 }
127 
SaveToFile(const std::string & file) const128 bool NvramConfig::SaveToFile(const std::string& file) const {
129   std::ofstream ofs = modem::DeviceConfig::open_ofstream_crossplat(file.c_str());
130   if (!ofs.is_open()) {
131     LOG(ERROR) << "Unable to write to file " << file;
132     return false;
133   }
134   ofs << *dictionary_;
135   return !ofs.fail();
136 }
137 
InitDefaultNvramConfig()138 void NvramConfig::InitDefaultNvramConfig() {
139   for (size_t num = 0; num < total_instances_; num++) {
140     auto instance = ForInstance(num);
141     instance.set_modem_technoloy(kDefaultModemTechnoloy);
142     instance.set_network_selection_mode(kDefaultNetworkSelectionMode);
143     instance.set_preferred_network_mode(kDefaultPreferredNetworkMode);
144     instance.set_emergency_mode(kDefaultEmergencyMode);
145   }
146 }
147 
Dictionary() const148 const Json::Value* NvramConfig::InstanceSpecific::Dictionary() const {
149   return &(*config_->dictionary_)[kInstances][id_];
150 }
151 
Dictionary()152 Json::Value* NvramConfig::InstanceSpecific::Dictionary() {
153   return &(*config_->dictionary_)[kInstances][id_];
154 }
155 
network_selection_mode() const156 int NvramConfig::InstanceSpecific::network_selection_mode() const {
157   return (*Dictionary())[kNetworkSelectionMode].asInt();
158 }
159 
set_network_selection_mode(int mode)160 void NvramConfig::InstanceSpecific::set_network_selection_mode(int mode) {
161   (*Dictionary())[kNetworkSelectionMode] = mode;
162 }
163 
operator_numeric() const164 std::string NvramConfig::InstanceSpecific::operator_numeric() const {
165   return (*Dictionary())[kOperatorNumeric].asString();
166 }
167 
set_operator_numeric(std::string & operator_numeric)168 void NvramConfig::InstanceSpecific::set_operator_numeric(std::string& operator_numeric) {
169   (*Dictionary())[kOperatorNumeric] = operator_numeric;
170 }
171 
modem_technoloy() const172 int NvramConfig::InstanceSpecific::modem_technoloy() const {
173   return (*Dictionary())[kModemTechnoloy].asInt();
174 }
175 
set_modem_technoloy(int technoloy)176 void NvramConfig::InstanceSpecific::set_modem_technoloy(int technoloy) {
177   (*Dictionary())[kModemTechnoloy] = technoloy;
178 }
179 
preferred_network_mode() const180 int NvramConfig::InstanceSpecific::preferred_network_mode() const {
181   return (*Dictionary())[kPreferredNetworkMode].asInt();
182 }
183 
set_preferred_network_mode(int mode)184 void NvramConfig::InstanceSpecific::set_preferred_network_mode(int mode) {
185   (*Dictionary())[kPreferredNetworkMode] = mode;
186 }
187 
emergency_mode() const188 bool NvramConfig::InstanceSpecific::emergency_mode() const {
189   return (*Dictionary())[kEmergencyMode].asBool();
190 }
191 
set_emergency_mode(bool mode)192 void NvramConfig::InstanceSpecific::set_emergency_mode(bool mode) {
193   (*Dictionary())[kEmergencyMode] = mode;
194 }
195 
sim_type() const196 int NvramConfig::sim_type() const {
197   return sim_type_;
198 }
199 
200 }  // namespace cuttlefish
201