/* * Copyright (C) 2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ use crate::daemon_lib::mount; use crate::daemon_lib::task_manager; use crate::common::jdwp::DisplayType; use crate::common::jdwp::Jdwp; use crate::daemon_lib::sys_para::*; use crate::utils::hdc_log::*; use crate::common::hdctransfer; use crate::config::{self, HdcCommand, MessageLevel}; use libc::sync; extern "C" { fn Restart(); } async fn hdc_restart() { crate::info!("Mode changed, hdc daemon restart!"); unsafe { Restart(); } } async fn echo_client(session_id: u32, channel_id: u32, message: &str, level: MessageLevel) { hdctransfer::echo_client(session_id, channel_id, message, level).await; } async fn echo_device_mode_result(session_id: u32, channel_id: u32, result: bool, message: &str) { if result { echo_client( session_id, channel_id, "Set device run mode successful.", MessageLevel::Ok, ) .await; } else { let msg = format!("Set device run mode failed: {}", message); echo_client(session_id, channel_id, msg.as_str(), MessageLevel::Fail).await; } task_finish(session_id, channel_id).await; } async fn echo_reboot_result(session_id: u32, channel_id: u32, result: bool, message: &str) { if result { echo_client( session_id, channel_id, "Reboot successful.", MessageLevel::Ok, ) .await; } else { let msg = format!("Reboot failed: {}", message); echo_client(session_id, channel_id, msg.as_str(), MessageLevel::Fail).await; } task_finish(session_id, channel_id).await; } async fn echo_root_run_mode_result(session_id: u32, channel_id: u32, result: bool, message: &str) { if result { let msg = format!("Set {} run mode successful.", message); echo_client(session_id, channel_id, msg.as_str(), MessageLevel::Ok).await; } else { let msg = format!("Set {} run mode failed.", message); echo_client(session_id, channel_id, msg.as_str(), MessageLevel::Fail).await; } task_finish(session_id, channel_id).await; } async fn set_root_run_enable(session_id: u32, channel_id: u32, root: bool) { let root_flag = if root { "0" } else { "1" }; let mode_msg = if root { "sh" } else { "root" }; let result = set_dev_item(config::ENV_ROOT_RUN_MODE, root_flag); echo_root_run_mode_result(session_id, channel_id, result, mode_msg).await; crate::info!( "set_root_run_enable: session_id: {}, channel_id: {}, root: {}, result: {}", session_id, channel_id, root, result ); if result { crate::info!("set_root_run root:{root} free_all_session"); task_manager::free_all_sessiones().await; std::process::exit(0); } } async fn set_root_run(session_id: u32, channel_id: u32, _payload: &[u8]) { let (ret, debug_able) = get_dev_item(config::ENV_DEBUGGABLE, "_"); if !ret || debug_able.trim() != "1" { crate::info!("get debuggable failed"); echo_client( session_id, channel_id, "Cannot set root run mode in undebuggable version.", MessageLevel::Fail, ) .await; task_finish(session_id, channel_id).await; return; } if _payload.is_empty() { set_root_run_enable(session_id, channel_id, false).await; } else if _payload == [b'r'] { set_root_run_enable(session_id, channel_id, true).await; } else { echo_root_run_mode_result(session_id, channel_id, false, "Unknown command").await; } } async fn reboot_device(session_id: u32, channel_id: u32, _payload: &[u8]) { unsafe { sync(); }; let param = match String::from_utf8(_payload.to_vec()) { Ok(param) => param, Err(_) => String::from("Unknown"), }; let mut cmd = String::from("reboot"); if !param.is_empty() { cmd.push(','); cmd.push_str(param.as_str()); } let cmd = cmd.trim(); let result = set_dev_item(config::ENV_STARTUP, cmd); echo_reboot_result(session_id, channel_id, result, cmd).await; } async fn remount_device(session_id: u32, channel_id: u32) { unsafe { if libc::getuid() != 0 { echo_client( session_id, channel_id, "Operate need running as root", MessageLevel::Fail, ) .await; task_finish(session_id, channel_id).await; return; } } let ret = mount::remount_device(); if ret { echo_client(session_id, channel_id, "Mount finish", MessageLevel::Ok).await; } else { echo_client(session_id, channel_id, "Mount failed", MessageLevel::Fail).await; } task_finish(session_id, channel_id).await; } async fn set_device_mode(session_id: u32, channel_id: u32, _payload: &[u8]) { let param = match String::from_utf8(_payload.to_vec()) { Ok(param) => param, Err(_) => String::from("Unknown"), }; match param.as_str() { config::MODE_USB => { let result = set_dev_item(config::ENV_HDC_MODE, config::MODE_USB); echo_device_mode_result(session_id, channel_id, result, config::MODE_USB).await; if result { crate::info!("tmode usb free_all_session"); task_manager::free_all_sessiones().await; hdc_restart().await } } str if str.starts_with(config::PREFIX_PORT) => { let result = set_dev_item(config::ENV_HDC_MODE, config::MODE_TCP); if !result { echo_device_mode_result(session_id, channel_id, result, config::MODE_TCP).await; return; } let port = &str[config::PREFIX_PORT.len()..]; let port = port.trim_end_matches(|c: char| c.is_ascii_control() || c.is_ascii_whitespace()); let result = set_dev_item(config::ENV_HOST_PORT, port); echo_device_mode_result(session_id, channel_id, result, config::ENV_HOST_PORT).await; if result { crate::info!("tmode port:{port} free_all_session"); task_manager::free_all_sessiones().await; hdc_restart().await } } _ => { echo_device_mode_result(session_id, channel_id, false, "Unknown command").await; } } } async fn do_jdwp_list(session_id: u32, channel_id: u32) { crate::debug!("do_jdwp_list, session_id {session_id}, channel_id {channel_id}"); let jdwp = Jdwp::get_instance().clone(); let process_list = jdwp.get_process_list().await; if process_list.is_empty() { echo_client(session_id, channel_id, "[Empty]", MessageLevel::Ok).await; } else { echo_client( session_id, channel_id, process_list.as_str(), MessageLevel::Ok, ) .await; } task_finish(session_id, channel_id).await; } async fn do_jdwp_track(session_id: u32, channel_id: u32, payload: &[u8]) { // 0:AllApp 1:DebugApp 2:ReleaseApp 3:AllAppWithType let mut display = DisplayType::DebugApp; if !payload.is_empty() && payload[0] == b'p' { display = DisplayType::AllApp; } else if !payload.is_empty() && payload[0] == b'a' { display = DisplayType::AllAppWithType; } let jdwp = Jdwp::get_instance().clone(); jdwp.add_tracker(channel_id, session_id, display) .await; } pub async fn command_dispatch( session_id: u32, channel_id: u32, _command: HdcCommand, _payload: &[u8], _payload_size: u16, ) -> bool { crate::info!("DaemonUnityTask: command:{:?}", _command); match _command { HdcCommand::UnityReboot => reboot_device(session_id, channel_id, _payload).await, HdcCommand::UnityRunmode => set_device_mode(session_id, channel_id, _payload).await, HdcCommand::UnityRootrun => set_root_run(session_id, channel_id, _payload).await, HdcCommand::JdwpList => do_jdwp_list(session_id, channel_id).await, HdcCommand::JdwpTrack => do_jdwp_track(session_id, channel_id, _payload).await, HdcCommand::UnityRemount => remount_device(session_id, channel_id).await, _ => { crate::error!("other command, {:?}", _command); } } true } async fn task_finish(session_id: u32, channel_id: u32) { hdctransfer::transfer_task_finish(channel_id, session_id).await; }