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