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 <iomanip>
20 
21 namespace cuttlefish {
22 
MiscService(int32_t service_id,ChannelMonitor * channel_monitor,ThreadLooper * thread_looper)23 MiscService::MiscService(int32_t service_id, ChannelMonitor* channel_monitor,
24                          ThreadLooper* thread_looper)
25     : ModemService(service_id, this->InitializeCommandHandlers(),
26                    channel_monitor, thread_looper) {}
27 
InitializeCommandHandlers()28 std::vector<CommandHandler> MiscService::InitializeCommandHandlers() {
29   std::vector<CommandHandler> command_handlers = {
30       /* initializeCallback */
31       CommandHandler("E0Q0V1",
32                      [this](const Client& client) {
33                        this->HandleCommandDefaultSupported(client);
34                      }),
35       CommandHandler("S0=0",
36                      [this](const Client& client) {
37                        this->HandleCommandDefaultSupported(client);
38                      }),
39       CommandHandler("+CMEE=1",
40                      [this](const Client& client) {
41                        this->HandleCommandDefaultSupported(client);
42                      }),
43       CommandHandler("+CMOD=0",
44                      [this](const Client& client) {
45                        this->HandleCommandDefaultSupported(client);
46                      }),
47       CommandHandler("+CSSN=0,1",
48                      [this](const Client& client) {
49                        this->HandleCommandDefaultSupported(client);
50                      }),
51       CommandHandler("+COLP=0",
52                      [this](const Client& client) {
53                        this->HandleCommandDefaultSupported(client);
54                      }),
55       CommandHandler("+CSCS=\"HEX\"",
56                      [this](const Client& client) {
57                        this->HandleCommandDefaultSupported(client);
58                      }),
59       CommandHandler("+CMGF=0",
60                      [this](const Client& client) {
61                        this->HandleCommandDefaultSupported(client);
62                      }),
63 
64       CommandHandler("+CGSN",
65                      [this](const Client& client, std::string& cmd) {
66                        this->HandleGetIMEI(client, cmd);
67                      }),
68   };
69   return (command_handlers);
70 }
71 
HandleGetIMEI(const Client & client,std::string & command)72 void MiscService::HandleGetIMEI(const Client& client, std::string& command) {
73   const std::string identityGsmImei = "12345678902468";
74   const std::string identityGsmSvn = "01";
75   const std::string information = "modem simulator";
76 
77   std::vector<std::string> responses;
78 
79   if (command == "AT+CGSN") {
80     responses.push_back(identityGsmImei);
81   } else {
82     CommandParser cmd(command);
83     cmd.SkipPrefix();
84     int snt = cmd.GetNextInt();
85     switch (snt) {
86       case 0:  // SN: IMEI and more information provided by manufacturers
87         responses.push_back(identityGsmImei + information);
88         break;
89       case 1:  // IMEI
90         responses.push_back(identityGsmImei);
91         break;
92       case 2:  // IMEI and software version number
93         responses.push_back(identityGsmImei + identityGsmSvn);
94         break;
95       case 3:  // Software version number
96         responses.push_back(identityGsmSvn);
97         break;
98       default:  // Default IMEI
99         responses.push_back(identityGsmImei);
100         break;
101     }
102   }
103 
104   responses.push_back("OK");
105   client.SendCommandResponse(responses);
106 }
107 
TimeUpdate()108 void MiscService::TimeUpdate() {
109   auto now = std::time(0);
110 
111   auto local_time = *std::localtime(&now);
112   auto gm_time = *std::gmtime(&now);
113 
114   auto t_local_time = std::mktime(&local_time);
115   auto t_gm_time = std::mktime(&gm_time);
116 
117   auto tzdiff = (int)std::difftime(t_local_time, t_gm_time) / (60 * 60);
118 
119   std::stringstream ss;
120   ss << "%CTZV: \"" << std::setfill('0') << std::setw(2) << local_time.tm_year % 100 << "/"
121                     << std::setfill('0') << std::setw(2) << local_time.tm_mon + 1 << "/"
122                     << std::setfill('0') << std::setw(2) << local_time.tm_mday << ","
123                     << std::setfill('0') << std::setw(2) << local_time.tm_hour << ":"
124                     << std::setfill('0') << std::setw(2) << local_time.tm_min << ":"
125                     << std::setfill('0') << std::setw(2) << local_time.tm_sec
126                     << (tzdiff >= 0 ? '+' : '-')
127                     << (tzdiff >= 0 ? tzdiff : -tzdiff) << ":"
128                     << local_time.tm_isdst << "\"";
129 
130   SendUnsolicitedCommand(ss.str());
131 }
132 
133 }  // namespace cuttlefish
134