class AndroidSupplyTool implements ApplicationListener<ContextRefreshedEvent> {
    private static File sasBinary = new File("plugins" + File.separator + "sonic-android-supply");
    private static 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) {
        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";
        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)});
            }
            GlobalProcessMap.getMap().put(processName, ps);
            sasJSON.put("port", port);
        } catch (Exception 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)});
            }
            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();
        }
    }

    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);
            ps.children().forEach(ProcessHandle::destroy);
            ps.destroy();
        }
    }

    public static void startPerfmon(String udId, String pkg, Session session, LogUtil logUtil, int interval) {<FILL_FUNCTION_BODY>}
}

        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);
        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();
        }
        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;
                }
                log.info(s);
            }
            try {
                stdInputErr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                err.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            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) {
                }
            }
            try {
                stdInput.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                inputStreamReader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            log.info("perfmon print thread shutdown.");
        });
        pro.start();
        String processName = String.format("process-%s-perfmon", udId);
        GlobalProcessMap.getMap().put(processName, ps);
    
<no_super_class>