• 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/misc_service.h"
17 
18 #include <ctime>
19 #include <fstream>
20 #include <iomanip>
21 
22 namespace cuttlefish {
23 
MiscService(int32_t service_id,ChannelMonitor * channel_monitor,ThreadLooper * thread_looper)24 MiscService::MiscService(int32_t service_id, ChannelMonitor* channel_monitor,
25                          ThreadLooper* thread_looper)
26     : ModemService(service_id, this->InitializeCommandHandlers(),
27                    channel_monitor, thread_looper) {
28   ParseTimeZone();
29 }
30 
ParseTimeZone()31 void MiscService::ParseTimeZone() {
32 #if defined(__linux__)
33   constexpr char TIMEZONE_FILENAME[] = "/etc/timezone";
34   std::ifstream ifs(TIMEZONE_FILENAME);
35   if (ifs.is_open()) {
36     std::string line;
37     if (std::getline(ifs, line)) {
38       FixTimeZone(line);
39       timezone_ = line;
40     }
41   }
42 #endif
43 }
44 
FixTimeZone(std::string & line)45 void MiscService::FixTimeZone(std::string& line) {
46   auto slashpos = line.find("/");
47   // "/" will be treated as separator, change it !
48   if (slashpos != std::string::npos) {
49     line.replace(slashpos, 1, "!");
50   }
51 }
52 
SetTimeZone(std::string timezone)53 void MiscService::SetTimeZone(std::string timezone) {
54   FixTimeZone(timezone);
55   timezone_ = timezone;
56 }
57 
InitializeCommandHandlers()58 std::vector<CommandHandler> MiscService::InitializeCommandHandlers() {
59   std::vector<CommandHandler> command_handlers = {
60       /* initializeCallback */
61       CommandHandler("E0Q0V1",
62                      [this](const Client& client) {
63                        this->HandleCommandDefaultSupported(client);
64                      }),
65       CommandHandler("S0=0",
66                      [this](const Client& client) {
67                        this->HandleCommandDefaultSupported(client);
68                      }),
69       CommandHandler("+CMEE=1",
70                      [this](const Client& client) {
71                        this->HandleCommandDefaultSupported(client);
72                      }),
73       CommandHandler("+CMOD=0",
74                      [this](const Client& client) {
75                        this->HandleCommandDefaultSupported(client);
76                      }),
77       CommandHandler("+CSSN=0,1",
78                      [this](const Client& client) {
79                        this->HandleCommandDefaultSupported(client);
80                      }),
81       CommandHandler("+COLP=0",
82                      [this](const Client& client) {
83                        this->HandleCommandDefaultSupported(client);
84                      }),
85       CommandHandler("+CSCS=\"HEX\"",
86                      [this](const Client& client) {
87                        this->HandleCommandDefaultSupported(client);
88                      }),
89       CommandHandler("+CMGF=0",
90                      [this](const Client& client) {
91                        this->HandleCommandDefaultSupported(client);
92                      }),
93 
94       CommandHandler("+CGSN",
95                      [this](const Client& client, std::string& cmd) {
96                        this->HandleGetIMEI(client, cmd);
97                      }),
98   };
99   return (command_handlers);
100 }
101 
HandleGetIMEI(const Client & client,std::string & command)102 void MiscService::HandleGetIMEI(const Client& client, std::string& command) {
103   const std::string identityGsmImei = "867400022047199";
104   const std::string identityGsmSvn = "01";
105   const std::string information = "modem simulator";
106 
107   std::vector<std::string> responses;
108 
109   if (command == "AT+CGSN") {
110     responses.push_back(identityGsmImei);
111   } else {
112     CommandParser cmd(command);
113     cmd.SkipPrefix();
114     int snt = cmd.GetNextInt();
115     switch (snt) {
116       case 0:  // SN: IMEI and more information provided by manufacturers
117         responses.push_back(identityGsmImei + information);
118         break;
119       case 1:  // IMEI
120         responses.push_back(identityGsmImei);
121         break;
122       case 2:  // IMEI and software version number
123         responses.push_back(identityGsmImei + identityGsmSvn);
124         break;
125       case 3:  // Software version number
126         responses.push_back(identityGsmSvn);
127         break;
128       default:  // Default IMEI
129         responses.push_back(identityGsmImei);
130         break;
131     }
132   }
133 
134   responses.push_back("OK");
135   client.SendCommandResponse(responses);
136 }
137 
TimeUpdate()138 void MiscService::TimeUpdate() {
139   auto now = std::time(0);
140 
141   auto local_time = *std::localtime(&now);
142   auto gm_time = *std::gmtime(&now);
143 
144   auto t_local_time = std::mktime(&local_time);
145   auto t_gm_time = std::mktime(&gm_time);
146 
147   // Timezone offset is in number of quarter-hours
148   auto tzdiff = (int)std::difftime(t_local_time, t_gm_time) / (15 * 60);
149 
150   std::stringstream ss;
151   ss << "%CTZV: \"" << std::setfill('0') << std::setw(2)
152      << local_time.tm_year % 100 << "/" << std::setfill('0') << std::setw(2)
153      << local_time.tm_mon + 1 << "/" << std::setfill('0') << std::setw(2)
154      << local_time.tm_mday << "," << std::setfill('0') << std::setw(2)
155      << local_time.tm_hour << ":" << std::setfill('0') << std::setw(2)
156      << local_time.tm_min << ":" << std::setfill('0') << std::setw(2)
157      << local_time.tm_sec << (tzdiff >= 0 ? '+' : '-')
158      << (tzdiff >= 0 ? tzdiff : -tzdiff) << ":" << local_time.tm_isdst;
159   if (!timezone_.empty()) {
160     ss << ":" << timezone_;
161   }
162   ss << "\"";
163 
164   SendUnsolicitedCommand(ss.str());
165 }
166 
167 }  // namespace cuttlefish
168