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