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