package ca.canuckcoding.adb; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class AdbCommand extends Thread { private final int FILE_MODE = 0664; private AdbDevice device; private AdbSocket socket; private String actionCode; private StringBuffer command; private String response; private int exitCode; private File stdoutRedirect; private File stdinRedirect; private IOException ioException; private AdbException adbException; public AdbCommand(AdbDevice nd, String action, String path, String[] params) throws IOException { device = nd; socket = new AdbSocket(device.getHost(), device.getPort()); actionCode = action; command = new StringBuffer(); boolean sync = isSync(); if(!sync) { command.append(action); command.append(":"); } command.append(formatArg(path)); for(int i=0; i<params.length; i++) { command.append(" "); command.append(formatArg(params[i])); } if(actionCode.equalsIgnoreCase("SEND")) { command.append(","); command.append(Integer.toString(FILE_MODE)); } else if(!sync) { command.append(" ; echo $?"); } exitCode = 0; stdoutRedirect = null; stdinRedirect = null; ioException = null; adbException = null; } private boolean isSync() { return actionCode.equalsIgnoreCase("RECV") || actionCode.equalsIgnoreCase("SEND"); } private String formatArg(String s) { return s.replace("\\", "\\\\").replace("\"", "\\\"").replace(" ", "\\ "); } public void stdoutFile(File redirect) { stdoutRedirect = redirect; } public void stdinFile(File input) { stdinRedirect = input; } @Override public void run() { try { if(socket.sendCommand("host:transport:" + device.getId())) { boolean okay = false; if(!isSync()) { okay = socket.sendCommand(command.toString()); } else { okay = socket.sendSyncAction(actionCode, command.toString()); } if(okay) { if(stdinRedirect!=null) { writeFileToOutputStream(stdinRedirect); } else if(stdoutRedirect!=null) { writeInputStreamToFile(stdoutRedirect); } else { response = collectResponse(); } } else { adbException = new AdbException("Adb command failure"); } } else { adbException = new AdbException("Adb failure: unable to connect to device"); } } catch(IOException e) { System.err.println(e.getMessage()); ioException = e; exitCode = -1; } } private void writeInputStreamToFile(File f) throws IOException { FileOutputStream fos = new FileOutputStream(f); byte data[] = new byte[1024 * 64]; int n = socket.readChunk(data); while(n>0) { fos.write(data, 0, n); n = socket.readChunk(data); } fos.flush(); fos.close(); } private void writeFileToOutputStream(File f) throws IOException { FileInputStream fis = new FileInputStream(f); byte[] data = new byte[1024*64]; int n = fis.read(data); while(n>0) { socket.writeChunk(data, 0, n); n = fis.read(data); } socket.sendStatus("DONE", (int)f.lastModified()); socket.flush(); fis.close(); } private String collectResponse() throws IOException { String result = ""; String line = socket.readline(); while(line!=null) { result += line; line = socket.readline(); if(line!=null) { result += "\n"; } } if(!isSync()) { int last = result.lastIndexOf("\n"); if(last>0) { try { exitCode = Integer.parseInt(result.substring(last).trim()); result = result.substring(0, last); } catch(Exception e) { exitCode = -1; } } else { try { exitCode = Integer.parseInt(result.trim()); result = ""; } catch(Exception e) { exitCode = -1; } } } return result; } public int waitFor() throws InterruptedException, IOException, AdbException { join(); socket.flush(); socket.close(); if(ioException!=null) { throw ioException; } if(adbException!=null) { throw adbException; } return exitCode; } public String getResponse() { return response; } public int getExitCode() { return exitCode; } }