• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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 use super::mount;
16 use crate::jdwp::Jdwp;
17 use crate::transfer;
18 use hdc::common::hdctransfer;
19 use hdc::config::TaskMessage;
20 use hdc::config::{self, HdcCommand};
21 use hdc::utils::execute_shell_cmd;
22 use libc::sync;
23 
24 extern "C" {
Restart()25     fn Restart();
26 }
27 
hdc_restart()28 async fn hdc_restart() {
29     unsafe {
30         Restart();
31     }
32 }
33 
echo_client(session_id: u32, channel_id: u32, message: &str)34 async fn echo_client(session_id: u32, channel_id: u32, message: &str) {
35     let echo_message = TaskMessage {
36         channel_id,
37         command: HdcCommand::KernelEchoRaw,
38         payload: message.as_bytes().to_vec(),
39     };
40     transfer::put(session_id, echo_message).await;
41 }
42 
echo_device_mode_result(session_id: u32, channel_id: u32, result: bool, message: Vec<u8>)43 async fn echo_device_mode_result(session_id: u32, channel_id: u32, result: bool, message: Vec<u8>) {
44     if result {
45         echo_client(session_id, channel_id, "Set device run mode successful.").await;
46     } else {
47         let msg = format!(
48             "Set device run mode failed: {}",
49             String::from_utf8(message).unwrap()
50         );
51         echo_client(session_id, channel_id, msg.as_str()).await;
52     }
53     task_finish(session_id, channel_id).await;
54 }
55 
echo_reboot_result(session_id: u32, channel_id: u32, result: bool, message: Vec<u8>)56 async fn echo_reboot_result(session_id: u32, channel_id: u32, result: bool, message: Vec<u8>) {
57     if result {
58         echo_client(session_id, channel_id, "Reboot successful.").await;
59     } else {
60         let msg = format!("Reboot failed: {}", String::from_utf8(message).unwrap());
61         echo_client(session_id, channel_id, msg.as_str()).await;
62     }
63     task_finish(session_id, channel_id).await;
64 }
65 
echo_root_run_mode_result( session_id: u32, channel_id: u32, result: bool, message: Vec<u8>, )66 async fn echo_root_run_mode_result(
67     session_id: u32,
68     channel_id: u32,
69     result: bool,
70     message: Vec<u8>,
71 ) {
72     if result {
73         echo_client(session_id, channel_id, "Set root run mode successful.").await;
74     } else {
75         let msg = format!(
76             "Set root run mode failed: {}",
77             String::from_utf8(message).unwrap()
78         );
79         echo_client(session_id, channel_id, msg.as_str()).await;
80     }
81     task_finish(session_id, channel_id).await;
82 }
83 
set_root_run_enable(session_id: u32, channel_id: u32, force: bool)84 async fn set_root_run_enable(session_id: u32, channel_id: u32, force: bool) {
85     let arg = if force { "0" } else { "1" };
86     let shell_command = format!(
87         "{} {} {}",
88         config::SHELL_PARAM_SET,
89         config::ENV_ROOT_RUN_MODE,
90         arg
91     );
92     let (result, message) = execute_shell_cmd(shell_command);
93     echo_root_run_mode_result(session_id, channel_id, result, message).await;
94     if result {
95         hdc_restart().await;
96     }
97 }
98 
set_root_run(session_id: u32, channel_id: u32, _payload: &[u8])99 async fn set_root_run(session_id: u32, channel_id: u32, _payload: &[u8]) {
100     let shell_command = format!("{} {}", config::SHELL_PARAM_GET, config::ENV_DEBUGGABLE,);
101     let (result, message) = execute_shell_cmd(shell_command);
102     if !result || message[0] != b'1' {
103         return;
104     }
105 
106     if _payload.is_empty() {
107         set_root_run_enable(session_id, channel_id, false).await;
108     } else if _payload == [b'r'] {
109         set_root_run_enable(session_id, channel_id, true).await;
110     } else {
111         echo_root_run_mode_result(
112             session_id,
113             channel_id,
114             false,
115             String::from("Unknown command").as_bytes().to_vec(),
116         )
117         .await;
118     }
119 }
120 
reboot_device(session_id: u32, channel_id: u32, _payload: &[u8])121 async fn reboot_device(session_id: u32, channel_id: u32, _payload: &[u8]) {
122     mount::remount_device();
123     unsafe {
124         sync();
125     };
126 
127     let param = String::from_utf8(_payload.to_vec()).unwrap();
128     let mut cmd = String::from("reboot");
129     if !param.is_empty() {
130         cmd.push(',');
131         cmd.push_str(param.as_str());
132     }
133 
134     let shell_command = format!(
135         "{} {} {}",
136         config::SHELL_PARAM_SET,
137         config::ENV_STARTUP,
138         cmd
139     );
140     let (result, message) = execute_shell_cmd(shell_command);
141     echo_reboot_result(session_id, channel_id, result, message).await;
142 }
143 
remount_device(session_id: u32, channel_id: u32)144 async fn remount_device(session_id: u32, channel_id: u32) {
145     let ret = mount::remount_device();
146     if ret {
147         echo_client(session_id, channel_id, "Remount successful.").await;
148     } else {
149         echo_client(session_id, channel_id, "Remount failed.").await;
150     }
151     task_finish(session_id, channel_id).await;
152 }
153 
set_device_mode(session_id: u32, channel_id: u32, _payload: &[u8])154 async fn set_device_mode(session_id: u32, channel_id: u32, _payload: &[u8]) {
155     let param = String::from_utf8(_payload.to_vec()).unwrap();
156     match param.as_str() {
157         config::MODE_USB => {
158             let shell_command = format!(
159                 "{} {} {}",
160                 config::SHELL_PARAM_SET,
161                 config::ENV_HDC_MODE,
162                 config::MODE_USB
163             );
164             let (result, message) = execute_shell_cmd(shell_command);
165             echo_device_mode_result(session_id, channel_id, result, message).await;
166             if result {
167                 hdc_restart().await
168             }
169         }
170         str if str.starts_with(config::PREFIX_PORT) => {
171             let shell_command = format!(
172                 "{} {} {}",
173                 config::SHELL_PARAM_SET,
174                 config::ENV_HDC_MODE,
175                 config::MODE_TCP
176             );
177             let (ret, msg) = execute_shell_cmd(shell_command);
178             if !ret {
179                 echo_device_mode_result(session_id, channel_id, ret, msg).await;
180                 return;
181             }
182 
183             let port = &str[config::PREFIX_PORT.len()..];
184             let port =
185                 port.trim_end_matches(|c: char| c.is_ascii_control() || c.is_ascii_whitespace());
186             let set_port_command = format!(
187                 "{} {} {}",
188                 config::SHELL_PARAM_SET,
189                 config::ENV_HOST_PORT,
190                 port
191             );
192             let (result, message) = execute_shell_cmd(set_port_command);
193             echo_device_mode_result(session_id, channel_id, result, message).await;
194             if result {
195                 hdc_restart().await
196             }
197         }
198         _ => {
199             echo_device_mode_result(
200                 session_id,
201                 channel_id,
202                 false,
203                 String::from("Unknown command").as_bytes().to_vec(),
204             )
205             .await;
206         }
207     }
208 }
209 
do_jdwp_list(session_id: u32, channel_id: u32)210 async fn do_jdwp_list(session_id: u32, channel_id: u32) {
211     println!("do_jdwp_list");
212     let jdwp = Jdwp::get_instance().clone();
213     let process_list = jdwp.get_process_list().await;
214     if process_list.is_empty() {
215         echo_client(session_id, channel_id, "[Empty]").await;
216     } else {
217         echo_client(session_id, channel_id, process_list.as_str()).await;
218     }
219     task_finish(session_id, channel_id).await;
220 }
221 
do_jdwp_track(session_id: u32, channel_id: u32, payload: &[u8])222 async fn do_jdwp_track(session_id: u32, channel_id: u32, payload: &[u8]) {
223     let mut debug_or_release = true;
224     if !payload.is_empty() && payload[0] == b'p' {
225         debug_or_release = false;
226     }
227     println!("do_jdwp_track");
228     let jdwp = Jdwp::get_instance().clone();
229     jdwp.add_tracker(channel_id, session_id, debug_or_release)
230         .await;
231 }
232 
command_dispatch( session_id: u32, channel_id: u32, _command: HdcCommand, _payload: &[u8], _payload_size: u16, ) -> bool233 pub async fn command_dispatch(
234     session_id: u32,
235     channel_id: u32,
236     _command: HdcCommand,
237     _payload: &[u8],
238     _payload_size: u16,
239 ) -> bool {
240     println!("DaemonUnityTask: command:{:#?}", _command);
241     match _command {
242         HdcCommand::UnityReboot => {
243             reboot_device(session_id, channel_id, _payload).await;
244         }
245         HdcCommand::UnityRunmode => {
246             set_device_mode(session_id, channel_id, _payload).await;
247         }
248         HdcCommand::UnityRootrun => {
249             set_root_run(session_id, channel_id, _payload).await;
250         }
251         HdcCommand::JdwpList => {
252             do_jdwp_list(session_id, channel_id).await;
253         }
254         HdcCommand::JdwpTrack => {
255             do_jdwp_track(session_id, channel_id, _payload).await;
256         }
257         HdcCommand::UnityRemount => {
258             remount_device(session_id, channel_id).await;
259         }
260         _ => {
261             println!("other command");
262         }
263     }
264     true
265 }
266 
task_finish(session_id: u32, channel_id: u32)267 async fn task_finish(session_id: u32, channel_id: u32) {
268     hdctransfer::transfer_task_finish(channel_id, session_id).await;
269 }
270