Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: 整理代码并解决调用远程ADB持续发送命令会被阻塞的问题 #462

Merged
merged 2 commits into from
Sep 3, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
215 changes: 104 additions & 111 deletions src/main/java/org/cloud/sonic/agent/bridge/android/AndroidSupplyTool.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,161 +35,154 @@
import java.io.IOException;
import java.io.InputStreamReader;

import static org.cloud.sonic.agent.tools.BytesTool.sendText;

@Slf4j
@Component
public class AndroidSupplyTool implements ApplicationListener<ContextRefreshedEvent> {
private static File sasBinary = new File("plugins" + File.separator + "sonic-android-supply");
private static String sas = sasBinary.getAbsolutePath();
private static final File sasBinary = new File("plugins" + File.separator + "sonic-android-supply");
private static final String sas = sasBinary.getAbsolutePath();

@Override
public void onApplicationEvent(@NonNull ContextRefreshedEvent event) {
log.info("Enable sonic-android-supply Module");
}

public static void startShare(String udId, Session session) {
executeShare(udId, session, PortTool.getPort());
}

public static void startShare(String udId, int port) {
executeShare(udId, null, port);
}

private static void executeShare(String udId, Session session, int port) {
JSONObject sasJSON = new JSONObject();
sasJSON.put("msg", "sas");
sasJSON.put("isEnable", true);
stopShare(udId);
String processName = String.format("process-%s-sas", udId);
String commandLine = "%s share -s %s --translate-port %d";
String commandLine = String.format("%s share -s %s --translate-port %d", sas, udId, port);
try {
String system = System.getProperty("os.name").toLowerCase();
Process ps = null;
int port = PortTool.getPort();
if (system.contains("win")) {
ps = Runtime.getRuntime().exec(new String[]{"cmd", "/c", String.format(commandLine, sas, udId, port)});
} else if (system.contains("linux") || system.contains("mac")) {
ps = Runtime.getRuntime().exec(new String[]{"sh", "-c", String.format(commandLine, sas, udId, port)});
}
Process ps = executeCommand(commandLine);
GlobalProcessMap.getMap().put(processName, ps);
sasJSON.put("port", port);
} catch (Exception e) {
} catch (IOException e) {
log.error("Error starting Android share", e);
sasJSON.put("port", 0);
e.printStackTrace();
} finally {
BytesTool.sendText(session, sasJSON.toJSONString());
}
}

public static void startShare(String udId, int port) {
stopShare(udId);
String processName = String.format("process-%s-sas", udId);
String commandLine = "%s share -s %s --translate-port %d";
try {
String system = System.getProperty("os.name").toLowerCase();
Process ps = null;
if (system.contains("win")) {
ps = Runtime.getRuntime().exec(new String[]{"cmd", "/c", String.format(commandLine, sas, udId, port)});
} else if (system.contains("linux") || system.contains("mac")) {
ps = Runtime.getRuntime().exec(new String[]{"sh", "-c", String.format(commandLine, sas, udId, port)});
if (session != null) {
BytesTool.sendText(session, sasJSON.toJSONString());
}
GlobalProcessMap.getMap().put(processName, ps);
} catch (Exception e) {
e.printStackTrace();
}
}

public static void stopShare(String udId) {
String processName = String.format("process-%s-sas", udId);
if (GlobalProcessMap.getMap().get(processName) != null) {
Process ps = GlobalProcessMap.getMap().get(processName);
ps.children().forEach(ProcessHandle::destroy);
ps.destroy();
}
terminateProcess(String.format("process-%s-sas", udId));
}

public static void stopPerfmon(String udId) {
String processName = String.format("process-%s-perfmon", udId);
if (GlobalProcessMap.getMap().get(processName) != null) {
Process ps = GlobalProcessMap.getMap().get(processName);
terminateProcess(String.format("process-%s-perfmon", udId));
}

private static void terminateProcess(String processName) {
Process ps = GlobalProcessMap.getMap().get(processName);
if (ps != null) {
ps.children().forEach(ProcessHandle::destroy);
ps.destroy();
GlobalProcessMap.getMap().remove(processName);
}
}

public static void startPerfmon(String udId, String pkg, Session session, LogUtil logUtil, int interval) {
stopPerfmon(udId);
Process ps = null;
String commandLine = "%s perfmon -s %s -r %d %s -j --sys-cpu --sys-mem --sys-network";
String system = System.getProperty("os.name").toLowerCase();
String tail = pkg.length() == 0 ? "" : (" --proc-cpu --proc-fps --proc-mem --proc-threads -p " + pkg);
String processName = String.format("process-%s-perfmon", udId);
String commandLine = String.format("%s perfmon -s %s -r %d %s -j --sys-cpu --sys-mem --sys-network", sas, udId, interval, pkg.isEmpty() ? "" : "--proc-cpu --proc-fps --proc-mem --proc-threads -p " + pkg);
try {
if (system.contains("win")) {
ps = Runtime.getRuntime().exec(new String[]{"cmd", "/c", String.format(commandLine, sas, udId, interval, tail)});
} else if (system.contains("linux") || system.contains("mac")) {
ps = Runtime.getRuntime().exec(new String[]{"sh", "-c", String.format(commandLine, sas, udId, interval, tail)});
}
} catch (Exception e) {
e.printStackTrace();
Process ps = executeCommand(commandLine);
GlobalProcessMap.getMap().put(processName, ps);
handlePerfmonOutput(ps, session, logUtil);
} catch (IOException e) {
log.error("Error starting performance monitor", e);
}
InputStreamReader inputStreamReader = new InputStreamReader(ps.getInputStream());
BufferedReader stdInput = new BufferedReader(inputStreamReader);
InputStreamReader err = new InputStreamReader(ps.getErrorStream());
BufferedReader stdInputErr = new BufferedReader(err);
Thread psErr = new Thread(() -> {
String s;
while (true) {
try {
if ((s = stdInputErr.readLine()) == null) break;
} catch (IOException e) {
log.info(e.getMessage());
break;
}

private static Process executeCommand(String command) throws IOException {
String system = System.getProperty("os.name").toLowerCase();
Process process;

if (system.contains("win")) {
process = Runtime.getRuntime().exec(new String[]{"cmd", "/c", command});
} else if (system.contains("linux") || system.contains("mac")) {
process = Runtime.getRuntime().exec(new String[]{"sh", "-c", command});
} else {
throw new RuntimeException("Unsupported operating system: " + system);
}

// 打印输出和错误流
printProcessOutput(process);

return process;
}

private static void printProcessOutput(Process process) {
// 创建线程打印标准输出
new Thread(() -> {
try (BufferedReader stdInput = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
String line;
while ((line = stdInput.readLine()) != null) {
log.info("Output: " + line);
}
log.info(s);
}
try {
stdInputErr.close();
} catch (IOException e) {
e.printStackTrace();
log.error("Error reading standard output", e);
}
try {
err.close();
}).start();

// 创建线程打印错误输出
new Thread(() -> {
try (BufferedReader stdError = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {
String line;
while ((line = stdError.readLine()) != null) {
log.error("Error: " + line);
}
} catch (IOException e) {
e.printStackTrace();
log.error("Error reading error output", e);
}
log.info("perfmon print thread shutdown.");
});
psErr.start();
Thread pro = new Thread(() -> {
String s;
while (true) {
try {
if ((s = stdInput.readLine()) == null) break;
} catch (IOException e) {
log.info(e.getMessage());
break;
}
try {
JSONObject perf = JSON.parseObject(s);
if (session != null) {
JSONObject perfDetail = new JSONObject();
perfDetail.put("msg", "perfDetail");
perfDetail.put("detail", perf);
sendText(session, perfDetail.toJSONString());
}
if (logUtil != null) {
logUtil.sendPerLog(perf.toJSONString());
}
} catch (Exception ignored) {
}
}).start();
}

private static void handlePerfmonOutput(Process ps, Session session, LogUtil logUtil) throws IOException {
try (BufferedReader stdInput = new BufferedReader(new InputStreamReader(ps.getInputStream()));
BufferedReader stdInputErr = new BufferedReader(new InputStreamReader(ps.getErrorStream()))) {
Thread errThread = new Thread(() -> logErrorStream(stdInputErr));
errThread.start();
String line;
while ((line = stdInput.readLine()) != null) {
processPerfmonLine(line, session, logUtil);
}
try {
stdInput.close();
} catch (IOException e) {
e.printStackTrace();
}
}

private static void logErrorStream(BufferedReader stdInputErr) {
try {
stdInputErr.lines().forEach(log::info);
} catch (Exception e) {
log.error("Error reading error stream", e);
}
}

private static void processPerfmonLine(String line, Session session, LogUtil logUtil) {
try {
JSONObject perf = JSON.parseObject(line);
if (session != null) {
JSONObject perfDetail = new JSONObject();
perfDetail.put("msg", "perfDetail");
perfDetail.put("detail", perf);
BytesTool.sendText(session, perfDetail.toJSONString());
}
try {
inputStreamReader.close();
} catch (IOException e) {
e.printStackTrace();
if (logUtil != null) {
logUtil.sendPerLog(perf.toJSONString());
}
log.info("perfmon print thread shutdown.");
});
pro.start();
String processName = String.format("process-%s-perfmon", udId);
GlobalProcessMap.getMap().put(processName, ps);
} catch (Exception e) {
log.error("Error processing performance monitor line", e);
}
}
}
Loading