• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "daemon_unity.h"
16 #include <sys/mount.h>
17 
18 namespace Hdc {
HdcDaemonUnity(HTaskInfo hTaskInfo)19 HdcDaemonUnity::HdcDaemonUnity(HTaskInfo hTaskInfo)
20     : HdcTaskBase(hTaskInfo)
21 {
22     currentDataCommand = CMD_KERNEL_ECHO_RAW;  // Default output to shelldata
23 }
24 
~HdcDaemonUnity()25 HdcDaemonUnity::~HdcDaemonUnity()
26 {
27     WRITE_LOG(LOG_DEBUG, "HdcDaemonUnity::~HdcDaemonUnity finish");
28 }
29 
StopTask()30 void HdcDaemonUnity::StopTask()
31 {
32     // Remove jpid tracker when stopping task
33     RemoveJdwpTracker();
34     asyncCommand.DoRelease();
35 }
36 
ReadyForRelease()37 bool HdcDaemonUnity::ReadyForRelease()
38 {
39     if (!HdcTaskBase::ReadyForRelease() || !asyncCommand.ReadyForRelease()) {
40         return false;
41     }
42     return true;
43 }
44 
AsyncCmdOut(bool finish,int64_t exitStatus,const string result)45 bool HdcDaemonUnity::AsyncCmdOut(bool finish, int64_t exitStatus, const string result)
46 {
47 #ifdef UNIT_TEST
48     Base::WriteBinFile((UT_TMP_PATH + "/execute.result").c_str(), (uint8_t *)result.c_str(), result.size(),
49                        countUt++ == 0);
50 #endif
51     bool ret = false;
52     bool wantFinish = false;
53     do {
54         if (finish) {
55             wantFinish = true;
56             ret = true;
57             --refCount;
58             break;
59         }
60         if (!SendToAnother(currentDataCommand, (uint8_t *)result.c_str(), result.size())) {
61             break;
62         }
63         ret = true;
64     } while (false);
65     if (wantFinish) {
66         TaskFinish();
67     }
68     return ret;
69 }
70 
ExecuteShell(const char * shellCommand)71 int HdcDaemonUnity::ExecuteShell(const char *shellCommand)
72 {
73     do {
74         AsyncCmd::CmdResultCallback funcResultOutput;
75         funcResultOutput = std::bind(&HdcDaemonUnity::AsyncCmdOut, this, std::placeholders::_1, std::placeholders::_2,
76                                      std::placeholders::_3);
77         if (!asyncCommand.Initial(loopTask, funcResultOutput)) {
78             break;
79         }
80         asyncCommand.ExecuteCommand(shellCommand);
81         ++refCount;
82         return RET_SUCCESS;
83     } while (false);
84 
85     TaskFinish();
86     WRITE_LOG(LOG_DEBUG, "Shell failed finish");
87     return -1;
88 }
89 
FindMountDeviceByPath(const char * toQuery,char * dev)90 bool HdcDaemonUnity::FindMountDeviceByPath(const char *toQuery, char *dev)
91 {
92     int fd;
93     int res;
94     char *token = nullptr;
95     const char delims[] = "\n";
96     char buf[BUF_SIZE_DEFAULT2];
97 
98     fd = open("/proc/mounts", O_RDONLY | O_CLOEXEC);
99     if (fd < 0) {
100         return false;
101     }
102     read(fd, buf, sizeof(buf) - 1);
103     close(fd);
104     buf[sizeof(buf) - 1] = '\0';
105     token = strtok(buf, delims);
106 
107     while (token) {
108         char dir[BUF_SIZE_SMALL] = "";
109         int freq;
110         int passnno;
111         // clang-format off
112         res = sscanf_s(token, "%255s %255s %*s %*s %d %d\n", dev, BUF_SIZE_SMALL - 1,
113                        dir, BUF_SIZE_SMALL - 1, &freq, &passnno);
114         // clang-format on
115         dev[BUF_SIZE_SMALL - 1] = '\0';
116         dir[BUF_SIZE_SMALL - 1] = '\0';
117         if (res == 4 && (strcmp(toQuery, dir) == 0)) {  // 4 : The correct number of parameters
118             return true;
119         }
120         token = strtok(nullptr, delims);
121     }
122     return false;
123 }
124 
RemountPartition(const char * dir)125 bool HdcDaemonUnity::RemountPartition(const char *dir)
126 {
127     int fd;
128     int off = 0;
129     char dev[BUF_SIZE_SMALL] = "";
130 
131     if (!FindMountDeviceByPath(dir, dev) || strlen(dev) < 4) {  // 4 : file count
132         WRITE_LOG(LOG_DEBUG, "FindMountDeviceByPath failed");
133         return false;
134     }
135 
136     if ((fd = open(dev, O_RDONLY | O_CLOEXEC)) < 0) {
137         WRITE_LOG(LOG_DEBUG, "Open device:%s failed, error:%d", dev, errno);
138         return false;
139     }
140     ioctl(fd, BLKROSET, &off);
141     close(fd);
142 
143     if (mount(dev, dir, "none", MS_REMOUNT, nullptr) < 0) {
144         WRITE_LOG(LOG_DEBUG, "Mount device failed");
145         return false;
146     }
147     return true;
148 }
149 
RemountDevice()150 bool HdcDaemonUnity::RemountDevice()
151 {
152     if (getuid() != 0) {
153         LogMsg(MSG_FAIL, "Opearte need running as root");
154         return false;
155     }
156     struct stat info;
157     if (!lstat("/vendor", &info) && (info.st_mode & S_IFMT) == S_IFDIR) {
158         // has vendor
159         if (!RemountPartition("/vendor")) {
160             LogMsg(MSG_FAIL, "Mount failed");
161             return false;
162         }
163     }
164     if (!lstat("/data", &info) && (info.st_mode & S_IFMT) == S_IFDIR) {
165         if (!RemountPartition("/data")) {
166             return false;
167         }
168     }
169     LogMsg(MSG_OK, "Mount finish");
170     return true;
171 }
172 
RebootDevice(const string & cmd)173 bool HdcDaemonUnity::RebootDevice(const string &cmd)
174 {
175     sync();
176     return SystemDepend::RebootDevice(cmd);
177 }
178 
SetDeviceRunMode(void * daemonIn,const char * cmd)179 bool HdcDaemonUnity::SetDeviceRunMode(void *daemonIn, const char *cmd)
180 {
181     HdcDaemon *daemon = (HdcDaemon *)daemonIn;
182     WRITE_LOG(LOG_DEBUG, "Set run mode:%s", cmd);
183     if (!strcmp(CMDSTR_TMODE_USB.c_str(), cmd)) {
184         SystemDepend::SetDevItem("persist.hdc.mode", CMDSTR_TMODE_USB.c_str());
185     } else if (!strncmp("port", cmd, strlen("port"))) {
186         SystemDepend::SetDevItem("persist.hdc.mode", CMDSTR_TMODE_TCP.c_str());
187         if (!strncmp("port ", cmd, strlen("port "))) {
188             const char *port = cmd + 5;
189             SystemDepend::SetDevItem("persist.hdc.port", port);
190         }
191     } else {
192         LogMsg(MSG_FAIL, "Unknow command");
193         return false;
194     }
195     // shutdown
196     daemon->PostStopInstanceMessage(true);
197     LogMsg(MSG_OK, "Set device run mode successful.");
198     return true;
199 }
200 
GetHiLog(const char * cmd)201 inline bool HdcDaemonUnity::GetHiLog(const char *cmd)
202 {
203     string cmdDo = "hilog";
204     if (cmd && !strcmp((char *)cmd, "v")) {
205         cmdDo += " -v long";
206     }
207     ExecuteShell(cmdDo.c_str());
208     return true;
209 }
210 
ListJdwpProcess(void * daemonIn)211 inline bool HdcDaemonUnity::ListJdwpProcess(void *daemonIn)
212 {
213     HdcDaemon *daemon = (HdcDaemon *)daemonIn;
214     string result = ((HdcJdwp *)daemon->clsJdwp)->GetProcessList();
215     if (!result.size()) {
216         result = EMPTY_ECHO;
217     } else {
218         result.erase(result.end() - 1);  // remove tail \n
219     }
220     LogMsg(MSG_OK, result.c_str());
221     return true;
222 }
223 
TrackJdwpProcess(void * daemonIn)224 inline bool HdcDaemonUnity::TrackJdwpProcess(void *daemonIn)
225 {
226     HdcDaemon *daemon = static_cast<HdcDaemon *>(daemonIn);
227     if (!((static_cast<HdcJdwp *>(daemon->clsJdwp))->CreateJdwpTracker(taskInfo))) {
228         string result = MESSAGE_FAIL;
229         LogMsg(MSG_OK, result.c_str());
230         return false;
231     }
232     return true;
233 }
234 
RemoveJdwpTracker()235 inline void HdcDaemonUnity::RemoveJdwpTracker()
236 {
237     HdcDaemon *daemon = static_cast<HdcDaemon *>(taskInfo->ownerSessionClass);
238     (static_cast<HdcJdwp *>(daemon->clsJdwp))->RemoveJdwpTracker(taskInfo);
239 }
240 
CommandDispatch(const uint16_t command,uint8_t * payload,const int payloadSize)241 bool HdcDaemonUnity::CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize)
242 {
243     bool ret = true;
244     HdcDaemon *daemon = (HdcDaemon *)taskInfo->ownerSessionClass;
245     // Both are not executed, do not need to be detected 'childReady'
246     string strPayload = string((char *)payload, payloadSize);
247 #ifdef HDC_DEBUG
248     WRITE_LOG(LOG_DEBUG, "CommandDispatch command:%d", command);
249 #endif // HDC_DEBUG
250     switch (command) {
251         case CMD_UNITY_EXECUTE: {
252             ExecuteShell((char *)strPayload.c_str());
253             break;
254         }
255         case CMD_UNITY_REMOUNT: {
256             ret = false;
257             RemountDevice();
258             break;
259         }
260         case CMD_UNITY_REBOOT: {
261             ret = false;
262             RebootDevice(strPayload);
263             break;
264         }
265         case CMD_UNITY_RUNMODE: {
266             ret = false;
267             SetDeviceRunMode(daemon, strPayload.c_str());
268             break;
269         }
270         case CMD_UNITY_HILOG: {
271             GetHiLog(strPayload.c_str());
272             break;
273         }
274         case CMD_UNITY_ROOTRUN: {
275             ret = false;
276 #ifdef HDC_DEBUG
277             if (payloadSize != 0 && !strcmp((char *)strPayload.c_str(), "r")) {
278                 SystemDepend::SetDevItem("persist.hdc.root", "0");
279             } else {
280                 SystemDepend::SetDevItem("persist.hdc.root", "1");
281             }
282 #endif // HDC_DEBUG
283             daemon->PostStopInstanceMessage(true);
284             break;
285         }
286         case CMD_UNITY_TERMINATE: {
287             daemon->PostStopInstanceMessage(!strcmp((char *)strPayload.c_str(), "1"));
288             break;
289         }
290         case CMD_UNITY_BUGREPORT_INIT: {
291             currentDataCommand = CMD_UNITY_BUGREPORT_DATA;
292             ExecuteShell((char *)CMDSTR_BUGREPORT.c_str());
293             break;
294         }
295         case CMD_JDWP_LIST: {
296             ret = false;
297             ListJdwpProcess(daemon);
298             break;
299         }
300         case CMD_JDWP_TRACK: {
301             if (!TrackJdwpProcess(daemon)) {
302                 ret = false;
303             }
304             break;
305         }
306         default:
307             break;
308     }
309 #ifdef HDC_DEBUG
310     WRITE_LOG(LOG_DEBUG, "CommandDispatch command:%d finish.", command);
311 #endif // HDC_LOCAL_DEBUG
312     return ret;
313 };
314 }  // namespace Hdc
315