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" { Restartnull26 fn Restart(); 27 } 28 29 async fn hdc_restart() { 30 crate::info!("Mode changed, hdc daemon restart!"); 31 unsafe { 32 Restart(); 33 } 34 } 35 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 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 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 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 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 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 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 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 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 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 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 239 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 261 async fn task_finish(session_id: u32, channel_id: u32) { 262 hdctransfer::transfer_task_finish(channel_id, session_id).await; 263 } 264