Java tutorial
/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package com.mozilla.SUTAgentAndroid.service; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintWriter; import java.io.RandomAccessFile; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.Socket; import java.net.SocketException; import java.net.UnknownHostException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.StringTokenizer; import java.util.TimeZone; import java.util.zip.Adler32; import java.util.zip.CheckedInputStream; import java.util.zip.CheckedOutputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; import org.apache.commons.net.ftp.FTP; import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.net.ftp.FTPFile; import org.apache.commons.net.ftp.FTPReply; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import com.mozilla.SUTAgentAndroid.R; import com.mozilla.SUTAgentAndroid.SUTAgentAndroid; import android.app.Activity; import android.app.ActivityManager; import android.app.AlarmManager; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.ActivityNotFoundException; import android.content.ComponentName; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; import android.content.ContextWrapper; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ServiceInfo; import android.content.pm.PackageManager.NameNotFoundException; import android.database.Cursor; import android.net.Uri; import android.os.Build; import android.os.Debug; import android.os.Environment; import android.os.StatFs; import android.os.SystemClock; import android.text.TextUtils; import android.util.DisplayMetrics; import android.util.Log; import android.view.Surface; import android.view.WindowManager; public class DoCommand { String lineSep = System.getProperty("line.separator"); Process pProc; OutputStream sutIn; InputStream sutErr; InputStream sutOut; AlertLooperThread alrt = null; ContextWrapper contextWrapper = null; String currentDir = "/"; String sErrorPrefix = "##AGENT-WARNING## "; boolean bTraceOn = false; String ffxProvider = "org.mozilla.ffxcp"; String fenProvider = "org.mozilla.fencp"; private static final int DEFAULT_STARTPRG_TIMEOUT_SECONDS = 300; public final String prgVersion = "SUTAgentAndroid Version 1.20"; public enum Command { RUN("run"), EXEC("exec"), EXECSU("execsu"), EXECCWD("execcwd"), EXECCWDSU("execcwdsu"), EXECEXT( "execext"), ENVRUN("envrun"), KILL("kill"), PS("ps"), DEVINFO("info"), OS("os"), ID("id"), UPTIME( "uptime"), UPTIMEMILLIS("uptimemillis"), SUTUPTIMEMILLIS("sutuptimemillis"), SETTIME( "settime"), SYSTIME("systime"), SCREEN("screen"), ROTATION("rotation"), MEMORY( "memory"), POWER("power"), PROCESS("process"), SUTUSERINFO( "sutuserinfo"), TEMPERATURE("temperature"), GETAPPROOT( "getapproot"), TESTROOT("testroot"), ALRT("alrt"), DISK( "disk"), CP("cp"), TIME("time"), HASH("hash"), CD( "cd"), CAT("cat"), CWD("cwd"), MV( "mv"), PUSH("push"), PULL( "pull"), RM("rm"), PRUNE( "rmdr"), MKDR( "mkdr"), DIRWRITABLE( "dirw"), ISDIR( "isdir"), DEAD( "dead"), MEMS( "mems"), LS( "ls"), TMPD( "tmpd"), PING( "ping"), REBT( "rebt"), UNZP( "unzp"), ZIP( "zip"), CLOK( "clok"), STAT( "stat"), QUIT( "quit"), EXIT( "exit"), HELP( "help"), FTPG( "ftpg"), FTPP( "ftpp"), INST( "inst"), UPDT( "updt"), UNINST( "uninst"), UNINSTALL( "uninstall"), TEST( "test"), DBG( "dbg"), TRACE( "trace"), VER( "ver"), TZGET( "tzget"), TZSET( "tzset"), ADB( "adb"), CHMOD( "chmod"), TOPACTIVITY( "activity"), UNKNOWN( "unknown"); private final String theCmd; Command(String theCmd) { this.theCmd = theCmd; } public String theCmd() { return theCmd; } public static Command getCmd(String sCmd) { Command retCmd = UNKNOWN; for (Command cmd : Command.values()) { if (cmd.theCmd().equalsIgnoreCase(sCmd)) { retCmd = cmd; break; } } return (retCmd); } } public DoCommand(ContextWrapper service) { this.contextWrapper = service; } public String processCommand(String theCmdLine, PrintWriter out, BufferedInputStream in, OutputStream cmdOut) { String strReturn = ""; Command cCmd = null; Command cSubCmd = null; if (bTraceOn) ((ASMozStub) this.contextWrapper).SendToDataChannel(theCmdLine); String[] Argv = parseCmdLine2(theCmdLine); int Argc = Argv.length; cCmd = Command.getCmd(Argv[0]); switch (cCmd) { case TRACE: if (Argc == 2) bTraceOn = (Argv[1].equalsIgnoreCase("on") ? true : false); else strReturn = sErrorPrefix + "Wrong number of arguments for trace command!"; break; case VER: strReturn = prgVersion; break; case CLOK: strReturn = GetClok(); break; case TZGET: strReturn = GetTimeZone(); break; case TZSET: if (Argc == 2) strReturn = SetTimeZone(Argv[1]); else strReturn = sErrorPrefix + "Wrong number of arguments for settz command!"; break; case UPDT: if (Argc >= 2) strReturn = StrtUpdtOMatic(Argv[1], Argv[2], (Argc > 3 ? Argv[3] : null), (Argc > 4 ? Argv[4] : null)); else strReturn = sErrorPrefix + "Wrong number of arguments for updt command!"; break; case SETTIME: strReturn = SetSystemTime(Argv[1], (Argc > 2 ? Argv[2] : null), cmdOut); break; case CWD: try { strReturn = new java.io.File(currentDir).getCanonicalPath(); } catch (IOException e) { e.printStackTrace(); } break; case CD: if (Argc == 2) strReturn = changeDir(Argv[1]); else strReturn = sErrorPrefix + "Wrong number of arguments for cd command!"; break; case LS: strReturn = PrintDir(((Argc > 1) ? Argv[1] : currentDir)); break; case GETAPPROOT: if (Argc == 2) strReturn = GetAppRoot(Argv[1]); else strReturn = sErrorPrefix + "Wrong number of arguments for getapproot command!"; break; case ISDIR: if (Argc == 2) strReturn = isDirectory(Argv[1]); else strReturn = sErrorPrefix + "Wrong number of arguments for isdir command!"; break; case TESTROOT: strReturn = GetTestRoot(); break; case DEAD: if (Argc == 2) strReturn = (IsProcessDead(Argv[1]) ? (Argv[1] + " is hung or unresponsive") : (Argv[1] + " is ok")); else strReturn = sErrorPrefix + "Wrong number of arguments for dead command!"; break; case PS: strReturn = GetProcessInfo(); break; case PULL: if (Argc >= 2) { long lOff = 0; long lLen = -1; if (Argc > 2) { try { lOff = Long.parseLong(Argv[2].trim()); } catch (NumberFormatException nfe) { lOff = 0; System.out.println("NumberFormatException: " + nfe.getMessage()); } } if (Argc == 4) { try { lLen = Long.parseLong(Argv[3].trim()); } catch (NumberFormatException nfe) { lLen = -1; System.out.println("NumberFormatException: " + nfe.getMessage()); } } strReturn = Pull(Argv[1], lOff, lLen, cmdOut); } else { strReturn = sErrorPrefix + "Wrong number of arguments for pull command!"; } break; case PUSH: if (Argc == 3) { long lArg = 0; try { lArg = Long.parseLong(Argv[2].trim()); } catch (NumberFormatException nfe) { System.out.println("NumberFormatException: " + nfe.getMessage()); } strReturn = Push(Argv[1], in, lArg); } else strReturn = sErrorPrefix + "Wrong number of arguments for push command!"; break; case INST: if (Argc >= 2) strReturn = InstallApp(Argv[1], cmdOut); else strReturn = sErrorPrefix + "Wrong number of arguments for inst command!"; break; case UNINST: if (Argc >= 2) strReturn = UnInstallApp(Argv[1], cmdOut, true); else strReturn = sErrorPrefix + "Wrong number of arguments for uninst command!"; break; case UNINSTALL: if (Argc >= 2) strReturn = UnInstallApp(Argv[1], cmdOut, false); else strReturn = sErrorPrefix + "Wrong number of arguments for uninstall command!"; break; case ALRT: if (Argc > 1) { if (Argv[1].contentEquals("on")) { String sTitle = "Agent Alert"; String sMsg = "The Agent Alert System has been activated!"; if (Argc == 3) { sTitle = Argv[2]; sMsg = ""; } else if (Argc == 4) { sTitle = Argv[2]; sMsg = Argv[3]; } StartAlert(sTitle, sMsg); } else { StopAlert(); } } else { strReturn = sErrorPrefix + "Wrong number of arguments for alrt command!"; } break; case REBT: if (Argc >= 1) strReturn = RunReboot(cmdOut, (Argc > 1 ? Argv[1] : null), (Argc > 2 ? Argv[2] : null)); else strReturn = sErrorPrefix + "Wrong number of arguments for rebt command!"; // RunReboot(cmdOut); break; case TMPD: strReturn = GetTmpDir(); break; case DEVINFO: if (Argc == 1) { strReturn += SUTAgentAndroid.sUniqueID; strReturn += "\n"; strReturn += GetOSInfo(); strReturn += "\n"; strReturn += GetSystemTime(); strReturn += "\n"; strReturn += GetUptime(); strReturn += "\n"; strReturn += GetUptimeMillis(); strReturn += "\n"; strReturn += GetSutUptimeMillis(); strReturn += "\n"; strReturn += GetScreenInfo(); strReturn += "\n"; strReturn += GetRotationInfo(); strReturn += "\n"; strReturn += GetMemoryInfo(); strReturn += "\n"; strReturn += GetPowerInfo(); strReturn += "\n"; strReturn += GetTemperatureInfo(); strReturn += "\n"; strReturn += GetProcessInfo(); strReturn += "\n"; strReturn += GetSutUserInfo(); strReturn += "\n"; strReturn += GetDiskInfo("/data"); strReturn += "\n"; strReturn += GetDiskInfo("/system"); strReturn += "\n"; strReturn += GetDiskInfo("/mnt/sdcard"); } else { cSubCmd = Command.getCmd(Argv[1]); switch (cSubCmd) { case ID: strReturn = SUTAgentAndroid.sUniqueID; break; case SCREEN: strReturn = GetScreenInfo(); break; case ROTATION: strReturn = GetRotationInfo(); break; case PROCESS: strReturn = GetProcessInfo(); break; case OS: strReturn = GetOSInfo(); break; case SYSTIME: strReturn = GetSystemTime(); break; case UPTIME: strReturn = GetUptime(); break; case UPTIMEMILLIS: strReturn = GetUptimeMillis(); break; case SUTUPTIMEMILLIS: strReturn = GetSutUptimeMillis(); break; case MEMORY: strReturn = GetMemoryInfo(); break; case POWER: strReturn += GetPowerInfo(); break; case SUTUSERINFO: strReturn += GetSutUserInfo(); break; case TEMPERATURE: strReturn += GetTemperatureInfo(); break; case DISK: strReturn += "\n"; strReturn += GetDiskInfo("/data"); strReturn += "\n"; strReturn += GetDiskInfo("/system"); strReturn += "\n"; strReturn += GetDiskInfo("/mnt/sdcard"); break; default: break; } } break; case STAT: if (Argc == 2) strReturn = StatProcess(Argv[1]); else strReturn = sErrorPrefix + "Wrong number of arguments for ping command!"; break; case PING: if (Argc == 2) strReturn = SendPing(Argv[1], cmdOut); else strReturn = sErrorPrefix + "Wrong number of arguments for ping command!"; break; case HASH: if (Argc == 2) strReturn = HashFile(Argv[1]); else strReturn = sErrorPrefix + "Wrong number of arguments for hash command!"; break; case PRUNE: if (Argc == 2) strReturn = PruneDir(Argv[1]); else strReturn = sErrorPrefix + "Wrong number of arguments for prune command!"; break; case FTPG: if (Argc == 4) strReturn = FTPGetFile(Argv[1], Argv[2], Argv[3], cmdOut); else strReturn = sErrorPrefix + "Wrong number of arguments for ftpg command!"; break; case CAT: if (Argc == 2) strReturn = Cat(Argv[1], cmdOut); else strReturn = sErrorPrefix + "Wrong number of arguments for cat command!"; break; case DIRWRITABLE: if (Argc == 2) strReturn = IsDirWritable(Argv[1]); else strReturn = sErrorPrefix + "Wrong number of arguments for dirwritable command!"; break; case TIME: if (Argc == 2) strReturn = PrintFileTimestamp(Argv[1]); else strReturn = sErrorPrefix + "Wrong number of arguments for time command!"; break; case MKDR: if (Argc == 2) strReturn = MakeDir(Argv[1]); else strReturn = sErrorPrefix + "Wrong number of arguments for mkdr command!"; break; case RM: if (Argc == 2) strReturn = RemoveFile(Argv[1]); else strReturn = sErrorPrefix + "Wrong number of arguments for rm command!"; break; case MV: if (Argc == 3) strReturn = Move(Argv[1], Argv[2]); else strReturn = sErrorPrefix + "Wrong number of arguments for mv command!"; break; case CP: if (Argc == 3) strReturn = CopyFile(Argv[1], Argv[2]); else strReturn = sErrorPrefix + "Wrong number of arguments for cp command!"; break; case QUIT: case EXIT: strReturn = Argv[0]; break; case DBG: Debug.waitForDebugger(); strReturn = "waitForDebugger on"; break; case ADB: if (Argc == 2) { if (Argv[1].contains("ip") || Argv[1].contains("usb")) { strReturn = SetADB(Argv[1]); } else { strReturn = sErrorPrefix + "Unrecognized argument for adb command!"; } } else { strReturn = sErrorPrefix + "Wrong number of arguments for adb command!"; } break; case TEST: long lFreeMemory = Runtime.getRuntime().freeMemory(); long lTotMemory = Runtime.getRuntime().totalMemory(); long lMaxMemory = Runtime.getRuntime().maxMemory(); if (lFreeMemory > 0) { strReturn = "Max memory: " + lMaxMemory + "\nTotal Memory: " + lTotMemory + "\nFree memory: " + lFreeMemory; break; } ContentResolver cr = contextWrapper.getContentResolver(); Uri ffxFiles = null; if (Argv[1].contains("fennec")) { ffxFiles = Uri.parse("content://" + fenProvider + "/dir"); } else if (Argv[1].contains("firefox")) { ffxFiles = Uri.parse("content://" + ffxProvider + "/dir"); } // Uri ffxFiles = Uri.parse("content://org.mozilla.fencp/file"); String[] columns = new String[] { "_id", "isdir", "filename", "length" }; // String[] columns = new String[] { // "_id", // "chunk" // }; Cursor myCursor = cr.query(ffxFiles, columns, // Which columns to return (Argc > 1 ? Argv[1] : null), // Which rows to return (all rows) null, // Selection arguments (none) null); // Put the results in ascending order by name /* if (myCursor != null) { int nRows = myCursor.getCount(); String [] colNames = myCursor.getColumnNames(); int nID = 0; int nBytesRecvd = 0; for (int lcv = 0; lcv < nRows; lcv++) { if (myCursor.moveToPosition(lcv)) { nID = myCursor.getInt(0); byte [] buf = myCursor.getBlob(1); if (buf != null) { nBytesRecvd += buf.length; strReturn += new String(buf); buf = null; } } } strReturn += "[eof - " + nBytesRecvd + "]"; myCursor.close(); } */ if (myCursor != null) { int nRows = myCursor.getCount(); int nID = 0; String sFileName = ""; long lFileSize = 0; boolean bIsDir = false; for (int lcv = 0; lcv < nRows; lcv++) { if (myCursor.moveToPosition(lcv)) { nID = myCursor.getInt(0); bIsDir = (myCursor.getInt(1) == 1 ? true : false); sFileName = myCursor.getString(2); lFileSize = myCursor.getLong(3); strReturn += "" + nID + "\t" + (bIsDir ? "<dir> " : " ") + sFileName + "\t" + lFileSize + "\n"; } } myCursor.close(); } break; case EXEC: case ENVRUN: if (Argc >= 2) { String[] theArgs = new String[Argc - 1]; for (int lcv = 1; lcv < Argc; lcv++) { theArgs[lcv - 1] = Argv[lcv]; } strReturn = StartPrg2(theArgs, cmdOut, null, false, DEFAULT_STARTPRG_TIMEOUT_SECONDS); } else { strReturn = sErrorPrefix + "Wrong number of arguments for " + Argv[0] + " command!"; } break; case EXECSU: if (Argc >= 2) { String[] theArgs = new String[Argc - 1]; for (int lcv = 1; lcv < Argc; lcv++) { theArgs[lcv - 1] = Argv[lcv]; } strReturn = StartPrg2(theArgs, cmdOut, null, true, DEFAULT_STARTPRG_TIMEOUT_SECONDS); } else { strReturn = sErrorPrefix + "Wrong number of arguments for " + Argv[0] + " command!"; } break; case EXECCWD: if (Argc >= 3) { String[] theArgs = new String[Argc - 2]; for (int lcv = 2; lcv < Argc; lcv++) { theArgs[lcv - 2] = Argv[lcv]; } strReturn = StartPrg2(theArgs, cmdOut, Argv[1], false, DEFAULT_STARTPRG_TIMEOUT_SECONDS); } else { strReturn = sErrorPrefix + "Wrong number of arguments for " + Argv[0] + " command!"; } break; case EXECCWDSU: if (Argc >= 3) { String[] theArgs = new String[Argc - 2]; for (int lcv = 2; lcv < Argc; lcv++) { theArgs[lcv - 2] = Argv[lcv]; } strReturn = StartPrg2(theArgs, cmdOut, Argv[1], true, DEFAULT_STARTPRG_TIMEOUT_SECONDS); } else { strReturn = sErrorPrefix + "Wrong number of arguments for " + Argv[0] + " command!"; } break; case RUN: if (Argc >= 2) { String[] theArgs = new String[Argc - 1]; for (int lcv = 1; lcv < Argc; lcv++) { theArgs[lcv - 1] = Argv[lcv]; } if (Argv[1].contains("/") || Argv[1].contains("\\") || !Argv[1].contains(".")) strReturn = StartPrg(theArgs, cmdOut, false, DEFAULT_STARTPRG_TIMEOUT_SECONDS); else strReturn = StartJavaPrg(theArgs, null); } else { strReturn = sErrorPrefix + "Wrong number of arguments for " + Argv[0] + " command!"; } break; case EXECEXT: // An "extended" exec command with format: // execext [su] [cwd=<path>] [t=<timeout in seconds>] arg1 ... if (Argc >= 2) { boolean su = false; String cwd = null; int timeout = DEFAULT_STARTPRG_TIMEOUT_SECONDS; int extra; for (extra = 1; extra < Argc; extra++) { if (Argv[extra].equals("su")) { su = true; } else if (Argv[extra].startsWith("cwd=")) { cwd = Argv[extra].substring(4); } else if (Argv[extra].startsWith("t=")) { timeout = Integer.parseInt(Argv[extra].substring(2)); if (timeout < 1 || timeout > 4 * 60 * 60) { Log.e("SUTAgentAndroid", "invalid execext timeout " + Argv[extra].substring(2) + "; using default instead"); timeout = DEFAULT_STARTPRG_TIMEOUT_SECONDS; } } else { break; } } if (extra < Argc) { String[] theArgs = new String[Argc - extra]; for (int lcv = extra; lcv < Argc; lcv++) { theArgs[lcv - extra] = Argv[lcv]; } strReturn = StartPrg2(theArgs, cmdOut, cwd, su, timeout); } else { strReturn = sErrorPrefix + "No regular arguments for " + Argv[0] + " command!"; } } else { strReturn = sErrorPrefix + "Wrong number of arguments for " + Argv[0] + " command!"; } break; case KILL: if (Argc == 2) strReturn = KillProcess(Argv[1], cmdOut); else strReturn = sErrorPrefix + "Wrong number of arguments for kill command!"; break; case DISK: strReturn = GetDiskInfo((Argc == 2 ? Argv[1] : "/")); break; case UNZP: strReturn = Unzip(Argv[1], (Argc == 3 ? Argv[2] : "")); break; case ZIP: strReturn = Zip(Argv[1], (Argc == 3 ? Argv[2] : "")); break; case CHMOD: if (Argc == 2) strReturn = ChmodDir(Argv[1]); else strReturn = sErrorPrefix + "Wrong number of arguments for chmod command!"; break; case TOPACTIVITY: strReturn = TopActivity(); break; case HELP: strReturn = PrintUsage(); break; default: strReturn = sErrorPrefix + "[" + Argv[0] + "] command"; if (Argc > 1) { strReturn += " with arg(s) ="; for (int lcv = 1; lcv < Argc; lcv++) { strReturn += " [" + Argv[lcv] + "]"; } } strReturn += " is currently not implemented."; break; } return (strReturn); } private void SendNotification(String tickerText, String expandedText) { NotificationManager notificationManager = (NotificationManager) contextWrapper .getSystemService(Context.NOTIFICATION_SERVICE); int icon = R.drawable.ateamlogo; long when = System.currentTimeMillis(); Notification notification = new Notification(icon, tickerText, when); notification.flags |= (Notification.FLAG_INSISTENT | Notification.FLAG_AUTO_CANCEL); notification.defaults |= Notification.DEFAULT_SOUND; notification.defaults |= Notification.DEFAULT_VIBRATE; notification.defaults |= Notification.DEFAULT_LIGHTS; Context context = contextWrapper.getApplicationContext(); // Intent to launch an activity when the extended text is clicked Intent intent2 = new Intent(contextWrapper, SUTAgentAndroid.class); PendingIntent launchIntent = PendingIntent.getActivity(context, 0, intent2, 0); notification.setLatestEventInfo(context, tickerText, expandedText, launchIntent); notificationManager.notify(1959, notification); } private void CancelNotification() { NotificationManager notificationManager = (NotificationManager) contextWrapper .getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.cancel(1959); } public void StartAlert(String sTitle, String sMsg) { // start the alert message SendNotification(sTitle, sMsg); } public void StopAlert() { CancelNotification(); } public String[] parseCmdLine2(String theCmdLine) { String cmdString; String workingString; String workingString2; String workingString3; List<String> lst = new ArrayList<String>(); int nLength = 0; int nFirstSpace = -1; // Null cmd line if (theCmdLine == null) { String[] theArgs = new String[1]; theArgs[0] = new String(""); return (theArgs); } else { nLength = theCmdLine.length(); nFirstSpace = theCmdLine.indexOf(' '); } if (nFirstSpace == -1) { String[] theArgs = new String[1]; theArgs[0] = new String(theCmdLine); return (theArgs); } // Get the command cmdString = new String(theCmdLine.substring(0, nFirstSpace)); lst.add(cmdString); // Jump past the command and trim workingString = (theCmdLine.substring(nFirstSpace + 1, nLength)).trim(); while ((nLength = workingString.length()) > 0) { int nEnd = 0; int nStart = 0; // if we have a quote if (workingString.startsWith("\"") || workingString.startsWith("'")) { char quoteChar = '"'; if (workingString.startsWith("\'")) quoteChar = '\''; // point to the first non quote char nStart = 1; // find the matching quote nEnd = workingString.indexOf(quoteChar, nStart); char prevChar; while (nEnd != -1) { // check to see if the quotation mark has been escaped prevChar = workingString.charAt(nEnd - 1); if (prevChar == '\\') { // if escaped, point past this quotation mark and find the next nEnd++; if (nEnd < nLength) nEnd = workingString.indexOf(quoteChar, nEnd); else nEnd = -1; } else break; } // there isn't one if (nEnd == -1) { // point at the quote nStart = 0; // so find the next space nEnd = workingString.indexOf(' ', nStart); // there isn't one of those either if (nEnd == -1) nEnd = nLength; // Just grab the rest of the cmdline } } else // no quote so find the next space { nEnd = workingString.indexOf(' ', nStart); // there isn't one of those if (nEnd == -1) nEnd = nLength; // Just grab the rest of the cmdline } // get the substring workingString2 = workingString.substring(nStart, nEnd); // if we have escaped quotes, convert them into standard ones while (workingString2.contains("\\\"") || workingString2.contains("\\'")) { workingString2 = workingString2.replace("\\\"", "\""); workingString2 = workingString2.replace("\\'", "'"); } // add it to the list lst.add(new String(workingString2)); // if we are dealing with a quote if (nStart > 0) nEnd++; // point past the end one // jump past the substring and trim it workingString = (workingString.substring(nEnd)).trim(); } // ok we're done package up the results int nItems = lst.size(); String[] theArgs = new String[nItems]; for (int lcv = 0; lcv < nItems; lcv++) { theArgs[lcv] = lst.get(lcv); } return (theArgs); } public String[] parseCmdLine(String theCmdLine) { String cmdString; String workingString; String workingString2; List<String> lst = new ArrayList<String>(); int nLength = 0; int nFirstSpace = -1; // Null cmd line if (theCmdLine == null) { String[] theArgs = new String[1]; theArgs[0] = new String(""); return (theArgs); } else { nLength = theCmdLine.length(); nFirstSpace = theCmdLine.indexOf(' '); } if (nFirstSpace == -1) { String[] theArgs = new String[1]; theArgs[0] = new String(theCmdLine); return (theArgs); } // Get the command cmdString = new String(theCmdLine.substring(0, nFirstSpace)); lst.add(cmdString); // Jump past the command and trim workingString = (theCmdLine.substring(nFirstSpace + 1, nLength)).trim(); while ((nLength = workingString.length()) > 0) { int nEnd = 0; int nStart = 0; // if we have a quote if (workingString.startsWith("\"")) { // point to the first non quote char nStart = 1; // find the matching quote nEnd = workingString.indexOf('"', nStart); // there isn't one if (nEnd == -1) { // point at the quote nStart = 0; // so find the next space nEnd = workingString.indexOf(' ', nStart); // there isn't one of those either if (nEnd == -1) nEnd = nLength; // Just grab the rest of the cmdline } else { nStart = 0; nEnd++; } } else // no quote so find the next space { nEnd = workingString.indexOf(' ', nStart); // there isn't one of those if (nEnd == -1) nEnd = nLength; // Just grab the rest of the cmdline } // get the substring workingString2 = workingString.substring(nStart, nEnd); // add it to the list lst.add(new String(workingString2)); // jump past the substring and trim it workingString = (workingString.substring(nEnd)).trim(); } int nItems = lst.size(); String[] theArgs = new String[nItems]; for (int lcv = 0; lcv < nItems; lcv++) { theArgs[lcv] = lst.get(lcv); } return (theArgs); } public String fixFileName(String fileName) { String sRet = ""; String sTmpFileName = ""; sRet = fileName.replace('\\', '/'); if (sRet.startsWith("/")) sTmpFileName = sRet; else sTmpFileName = currentDir + "/" + sRet; sRet = sTmpFileName.replace('\\', '/'); sTmpFileName = sRet; sRet = sTmpFileName.replace("//", "/"); return (sRet); } public String AddFilesToZip(ZipOutputStream out, String baseDir, String relDir) { final int BUFFER = 2048; String sRet = ""; String curDir = ""; String relFN = ""; BufferedInputStream origin = null; byte data[] = new byte[BUFFER]; if (relDir.length() > 0) curDir = baseDir + "/" + relDir; else curDir = baseDir; File f = new File(curDir); if (f.isFile()) { try { relFN = ((relDir.length() > 0) ? relDir + "/" + f.getName() : f.getName()); System.out.println("Adding: " + relFN); sRet += "Adding: " + relFN + lineSep; FileInputStream fi = new FileInputStream(curDir); origin = new BufferedInputStream(fi, BUFFER); ZipEntry entry = new ZipEntry(relFN); out.putNextEntry(entry); int count; while ((count = origin.read(data, 0, BUFFER)) != -1) { out.write(data, 0, count); } origin.close(); } catch (Exception e) { e.printStackTrace(); } return (sRet); } String files[] = f.list(); if (files != null) { try { for (int i = 0; i < files.length; i++) { f = new File(curDir + "/" + files[i]); if (f.isDirectory()) { if (relDir.length() > 0) sRet += AddFilesToZip(out, baseDir, relDir + "/" + files[i]); else sRet += AddFilesToZip(out, baseDir, files[i]); } else { relFN = ((relDir.length() > 0) ? relDir + "/" + files[i] : files[i]); System.out.println("Adding: " + relFN); sRet += "Adding: " + relFN + lineSep; FileInputStream fi = new FileInputStream(curDir + "/" + files[i]); origin = new BufferedInputStream(fi, BUFFER); ZipEntry entry = new ZipEntry(relFN); out.putNextEntry(entry); int count; while ((count = origin.read(data, 0, BUFFER)) != -1) { out.write(data, 0, count); } origin.close(); } } } catch (Exception e) { e.printStackTrace(); } } return (sRet); } public String Zip(String zipFileName, String srcName) { String fixedZipFileName = fixFileName(zipFileName); String fixedSrcName = fixFileName(srcName); String sRet = ""; try { FileOutputStream dest = new FileOutputStream(fixedZipFileName); CheckedOutputStream checksum = new CheckedOutputStream(dest, new Adler32()); ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(checksum)); out.setMethod(ZipOutputStream.DEFLATED); sRet += AddFilesToZip(out, fixedSrcName, ""); out.close(); System.out.println("checksum: " + checksum.getChecksum().getValue()); sRet += "checksum: " + checksum.getChecksum().getValue(); } catch (Exception e) { e.printStackTrace(); } return (sRet); } public String Unzip(String zipFileName, String dstDirectory) { String sRet = ""; String fixedZipFileName = fixFileName(zipFileName); String fixedDstDirectory = fixFileName(dstDirectory); String dstFileName = ""; int nNumExtracted = 0; boolean bRet = false; try { final int BUFFER = 2048; BufferedOutputStream dest = null; ZipFile zipFile = new ZipFile(fixedZipFileName); int nNumEntries = zipFile.size(); zipFile.close(); FileInputStream fis = new FileInputStream(fixedZipFileName); CheckedInputStream checksum = new CheckedInputStream(fis, new Adler32()); ZipInputStream zis = new ZipInputStream(new BufferedInputStream(checksum)); ZipEntry entry; byte[] data = new byte[BUFFER]; while ((entry = zis.getNextEntry()) != null) { System.out.println("Extracting: " + entry); int count; if (fixedDstDirectory.length() > 0) dstFileName = fixedDstDirectory + entry.getName(); else dstFileName = entry.getName(); String tmpDir = dstFileName.substring(0, dstFileName.lastIndexOf('/')); File tmpFile = new File(tmpDir); if (!tmpFile.exists()) { bRet = tmpFile.mkdirs(); } else bRet = true; if (bRet) { // if we aren't just creating a directory if (dstFileName.lastIndexOf('/') != (dstFileName.length() - 1)) { // write out the file FileOutputStream fos = new FileOutputStream(dstFileName); dest = new BufferedOutputStream(fos, BUFFER); while ((count = zis.read(data, 0, BUFFER)) != -1) { dest.write(data, 0, count); } dest.flush(); dest.close(); dest = null; fos.close(); fos = null; } nNumExtracted++; } else sRet += " - failed" + lineSep; } data = null; zis.close(); System.out.println("Checksum: " + checksum.getChecksum().getValue()); sRet += "Checksum: " + checksum.getChecksum().getValue(); sRet += lineSep + nNumExtracted + " of " + nNumEntries + " successfully extracted"; } catch (Exception e) { e.printStackTrace(); } return (sRet); } public String StatProcess(String string) { String sRet = ""; ActivityManager aMgr = (ActivityManager) contextWrapper.getSystemService(Activity.ACTIVITY_SERVICE); int[] nPids = new int[1]; nPids[0] = Integer.parseInt(string); android.os.Debug.MemoryInfo[] mi = aMgr.getProcessMemoryInfo(nPids); sRet = "Dalvik Private Dirty pages " + mi[0].dalvikPrivateDirty + " kb\n"; sRet += "Dalvik Proportional Set Size " + mi[0].dalvikPss + " kb\n"; sRet += "Dalvik Shared Dirty pages " + mi[0].dalvikSharedDirty + " kb\n\n"; sRet += "Native Private Dirty pages heap " + mi[0].nativePrivateDirty + " kb\n"; sRet += "Native Proportional Set Size heap " + mi[0].nativePss + " kb\n"; sRet += "Native Shared Dirty pages heap " + mi[0].nativeSharedDirty + " kb\n\n"; sRet += "Other Private Dirty pages " + mi[0].otherPrivateDirty + " kb\n"; sRet += "Other Proportional Set Size " + mi[0].otherPss + " kb\n"; sRet += "Other Shared Dirty pages " + mi[0].otherSharedDirty + " kb\n\n"; sRet += "Total Private Dirty Memory " + mi[0].getTotalPrivateDirty() + " kb\n"; sRet += "Total Proportional Set Size Memory " + mi[0].getTotalPss() + " kb\n"; sRet += "Total Shared Dirty Memory " + mi[0].getTotalSharedDirty() + " kb"; return (sRet); } public void FixDataLocalPermissions() { String chmodResult; File localDir = new java.io.File("/data/local"); if (!localDir.canWrite()) { chmodResult = ChmodDir("/data/local"); Log.i("SUTAgentAndroid", "Changed permissions on /data/local to make it writable: " + chmodResult); } File tmpDir = new java.io.File("/data/local/tmp"); if (tmpDir.exists() && !tmpDir.isDirectory()) { if (!tmpDir.delete()) { Log.e("SUTAgentAndroid", "Could not delete file /data/local/tmp"); } } if (!tmpDir.exists() && !tmpDir.mkdirs()) { Log.e("SUTAgentAndroid", "Could not create directory /data/local/tmp"); } chmodResult = ChmodDir("/data/local/tmp"); Log.i("SUTAgentAndroid", "Changed permissions on /data/local/tmp to make it writable: " + chmodResult); } private Boolean _SetTestRoot(String testroot) { String isWritable = IsDirWritable(testroot); if (isWritable.contains(sErrorPrefix) || isWritable.contains("is not writable")) { Log.w("SUTAgentAndroid", isWritable); Log.w("SUTAgentAndroid", "Unable to set device root to " + testroot); return false; } Log.i("SUTAgentAndroid", "Set device root to " + testroot); SUTAgentAndroid.sTestRoot = testroot; return true; } public void SetTestRoot(String testroot) { Boolean success = false; if (!testroot.equals("")) { // Device specified the required testroot. success = _SetTestRoot(testroot); if (!success) { Log.e("SUTAgentAndroid", "Unable to set device root to " + testroot); } } else { // Detect the testroot. // Attempt external storage. success = _SetTestRoot(Environment.getExternalStorageDirectory().getAbsolutePath()); if (!success) { Log.e("SUTAgentAndroid", "Cannot access world writeable test root"); } } } public String GetTestRoot() { if (SUTAgentAndroid.sTestRoot.equals("")) { SetTestRoot(""); } return SUTAgentAndroid.sTestRoot; } public String GetAppRoot(String AppName) { String sRet = sErrorPrefix + " internal error [no context]"; Context ctx = contextWrapper.getApplicationContext(); if (ctx != null) { try { Context appCtx = ctx.createPackageContext(AppName, 0); ContextWrapper appCtxW = new ContextWrapper(appCtx); sRet = appCtxW.getApplicationInfo().dataDir; appCtxW = null; appCtx = null; ctx = null; System.gc(); } catch (NameNotFoundException e) { e.printStackTrace(); } } return (sRet); } public String isDirectory(String sDir) { String sRet = sErrorPrefix + sDir + " does not exist"; String tmpDir = fixFileName(sDir); int nFiles = 0; if (tmpDir.contains("org.mozilla.fennec") || tmpDir.contains("org.mozilla.firefox")) { ContentResolver cr = contextWrapper.getContentResolver(); Uri ffxFiles = Uri .parse("content://" + (tmpDir.contains("fennec") ? fenProvider : ffxProvider) + "/dir"); String[] columns = new String[] { "_id", "isdir", "filename", "length" }; Cursor myCursor = cr.query(ffxFiles, columns, // Which columns to return tmpDir, // Which rows to return (all rows) null, // Selection arguments (none) null); // Order clause (none) if (myCursor != null) { nFiles = myCursor.getCount(); // If no entries the dir is empty if (nFiles > 0) { if (myCursor.moveToPosition(0)) { sRet = ((myCursor.getLong(myCursor.getColumnIndex("isdir")) == 1) ? "TRUE" : "FALSE"); } } myCursor.close(); } } else { File tmpFile = new java.io.File(tmpDir); if (tmpFile.exists()) { sRet = (tmpFile.isDirectory() ? "TRUE" : "FALSE"); } else { try { pProc = Runtime.getRuntime().exec(this.getSuArgs("ls -l " + sDir)); RedirOutputThread outThrd = new RedirOutputThread(pProc, null); outThrd.start(); outThrd.joinAndStopRedirect(5000); sRet = outThrd.strOutput; if (!sRet.contains("No such file or directory") && sRet.startsWith("l")) sRet = "FALSE"; } catch (IOException e) { sRet = e.getMessage(); e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } } return (sRet); } public String changeDir(String newDir) { String tmpDir = fixFileName(newDir); String sRet = sErrorPrefix + "Couldn't change directory to " + tmpDir; int nFiles = 0; if (tmpDir.contains("org.mozilla.fennec") || tmpDir.contains("org.mozilla.firefox")) { ContentResolver cr = contextWrapper.getContentResolver(); Uri ffxFiles = Uri .parse("content://" + (tmpDir.contains("fennec") ? fenProvider : ffxProvider) + "/dir"); String[] columns = new String[] { "_id", "isdir", "filename" }; Cursor myCursor = cr.query(ffxFiles, columns, // Which columns to return tmpDir, // Which rows to return (all rows) null, // Selection arguments (none) null); // Order clause (none) if (myCursor != null) { nFiles = myCursor.getCount(); if (nFiles > 0) { if (myCursor.moveToPosition(0)) { if (myCursor.getLong(myCursor.getColumnIndex("isdir")) == 1) { currentDir = myCursor.getString(myCursor.getColumnIndex("filename")); sRet = ""; } } } else { sRet = sErrorPrefix + tmpDir + " is not a valid directory"; } myCursor.close(); } } else { File tmpFile = new java.io.File(tmpDir); if (tmpFile.exists()) { try { if (tmpFile.isDirectory()) { currentDir = tmpFile.getCanonicalPath(); sRet = ""; } else sRet = sErrorPrefix + tmpDir + " is not a valid directory"; } catch (IOException e) { e.printStackTrace(); } } } return (sRet); } static final String HEXES = "0123456789abcdef"; public static String getHex(byte[] raw) { if (raw == null) { return null; } final StringBuilder hex = new StringBuilder(2 * raw.length); for (final byte b : raw) { hex.append(HEXES.charAt((b & 0xF0) >> 4)).append(HEXES.charAt((b & 0x0F))); } return hex.toString(); } public String HashFile(String fileName) { String sTmpFileName = fixFileName(fileName); String sRet = sErrorPrefix + "Couldn't calculate hash for file " + sTmpFileName; byte[] buffer = new byte[4096]; int nRead = 0; long lTotalRead = 0; MessageDigest digest = null; try { digest = java.security.MessageDigest.getInstance("MD5"); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } if (sTmpFileName.contains("org.mozilla.fennec") || sTmpFileName.contains("org.mozilla.firefox")) { ContentResolver cr = contextWrapper.getContentResolver(); Uri ffxFiles = null; ffxFiles = Uri .parse("content://" + (sTmpFileName.contains("fennec") ? fenProvider : ffxProvider) + "/file"); String[] columns = new String[] { "_id", "chunk" }; Cursor myCursor = cr.query(ffxFiles, columns, // Which columns to return sTmpFileName, // Which rows to return (all rows) null, // Selection arguments (none) null); // Order clause (none) if (myCursor != null) { int nRows = myCursor.getCount(); int nBytesRecvd = 0; for (int lcv = 0; lcv < nRows; lcv++) { if (myCursor.moveToPosition(lcv)) { byte[] buf = myCursor.getBlob(1); if (buf != null) { nBytesRecvd += buf.length; digest.update(buf, 0, buf.length); lTotalRead += nRead; buf = null; } } } myCursor.close(); byte[] hash = digest.digest(); sRet = getHex(hash); } } else { try { FileInputStream srcFile = new FileInputStream(sTmpFileName); while ((nRead = srcFile.read(buffer)) != -1) { digest.update(buffer, 0, nRead); lTotalRead += nRead; } srcFile.close(); byte[] hash = digest.digest(); sRet = getHex(hash); } catch (FileNotFoundException e) { sRet += " file not found"; } catch (IOException e) { sRet += " io exception"; e.printStackTrace(); } } return (sRet); } public String RemoveFile(String fileName) { String sTmpFileName = fixFileName(fileName); String sRet = sErrorPrefix + "Couldn't delete file " + sTmpFileName; if (sTmpFileName.contains("org.mozilla.fennec") || sTmpFileName.contains("org.mozilla.firefox")) { ContentResolver cr = contextWrapper.getContentResolver(); Uri ffxFiles = Uri .parse("content://" + (sTmpFileName.contains("fennec") ? fenProvider : ffxProvider) + "/file"); if (cr.delete(ffxFiles, sTmpFileName, null) == 1) { sRet = "deleted " + sTmpFileName; } } else { File f = new File(sTmpFileName); if (f.delete()) sRet = "deleted " + sTmpFileName; } return (sRet); } public String PruneDir(String sDir) { String sRet = ""; int nFiles = 0; String sSubDir = null; String sTmpDir = fixFileName(sDir); if (sTmpDir.contains("org.mozilla.fennec") || sTmpDir.contains("org.mozilla.firefox")) { ContentResolver cr = contextWrapper.getContentResolver(); Uri ffxFiles = Uri .parse("content://" + (sTmpDir.contains("fennec") ? fenProvider : ffxProvider) + "/dir"); if (cr.delete(ffxFiles, sTmpDir, null) > 0) { sRet = "deleted " + sTmpDir; } } else { File dir = new File(sTmpDir); if (dir.isDirectory()) { sRet = "Deleting file(s) from " + sTmpDir; File[] files = dir.listFiles(); if (files != null) { if ((nFiles = files.length) > 0) { for (int lcv = 0; lcv < nFiles; lcv++) { if (files[lcv].isDirectory()) { sSubDir = files[lcv].getAbsolutePath(); sRet += "\n" + PruneDir(sSubDir); } else { if (files[lcv].delete()) { sRet += "\n\tDeleted " + files[lcv].getName(); } else { sRet += "\n\tUnable to delete " + files[lcv].getName(); } } } } else sRet += "\n\t<empty>"; } if (dir.delete()) { sRet += "\nDeleting directory " + sTmpDir; } else { sRet += "\nUnable to delete directory " + sTmpDir; } } else { sRet += sErrorPrefix + sTmpDir + " is not a directory"; } } return (sRet); } public String PrintDir(String sDir) { String sRet = ""; int nFiles = 0; String sTmpDir = fixFileName(sDir); if (sTmpDir.contains("org.mozilla.fennec") || sTmpDir.contains("org.mozilla.firefox")) { ContentResolver cr = contextWrapper.getContentResolver(); Uri ffxFiles = null; ffxFiles = Uri.parse("content://" + (sTmpDir.contains("fennec") ? fenProvider : ffxProvider) + "/dir"); String[] columns = new String[] { "_id", "isdir", "filename", "length" }; Cursor myCursor = cr.query(ffxFiles, columns, // Which columns to return sTmpDir, // Which rows to return (all rows) null, // Selection arguments (none) null); // Order clause (none) if (myCursor != null) { nFiles = myCursor.getCount(); // If only one entry and the index is -1 this is not a directory int nNdx = myCursor.getColumnIndex("_id"); // If no entries the dir is empty if (nFiles == 1) { sRet = "<empty>"; } else { // Show the entries for (int lcv = 1; lcv < nFiles; lcv++) { if (myCursor.moveToPosition(lcv)) { if ((lcv == 0) && (myCursor.getLong(nNdx) == -1)) { sRet = sErrorPrefix + sTmpDir + " is not a directory"; } else { sRet += myCursor.getString(2); if (lcv < (nFiles - 1)) sRet += "\n"; } } } } myCursor.close(); } } else { File dir = new File(sTmpDir); if (dir.isDirectory()) { File[] files = dir.listFiles(); if (files != null) { if ((nFiles = files.length) > 0) { for (int lcv = 0; lcv < nFiles; lcv++) { sRet += files[lcv].getName(); if (lcv < (nFiles - 1)) { sRet += "\n"; } } } else { sRet = "<empty>"; } } } else { sRet = sErrorPrefix + sTmpDir + " is not a directory"; } } return (sRet); } public String Move(String sTmpSrcFileName, String sTmpDstFileName) { String sRet = sErrorPrefix + "Could not move " + sTmpSrcFileName + " to " + sTmpDstFileName; String sTmp = CopyFile(sTmpSrcFileName, sTmpDstFileName); if (sTmp.contains(" copied to ")) { sTmp = RemoveFile(sTmpSrcFileName); if (sTmp.startsWith("deleted ")) { sRet = sTmpSrcFileName + " moved to " + sTmpDstFileName; } } return (sRet); } public String CopyFile(String sTmpSrcFileName, String sTmpDstFileName) { String sRet = sErrorPrefix + "Could not copy " + sTmpSrcFileName + " to " + sTmpDstFileName; ContentValues cv = null; File destFile = null; Uri ffxSrcFiles = null; Uri ffxDstFiles = null; FileInputStream srcFile = null; FileOutputStream dstFile = null; byte[] buffer = new byte[4096]; int nRead = 0; long lTotalRead = 0; long lTotalWritten = 0; ContentResolver crIn = null; ContentResolver crOut = null; if (sTmpSrcFileName.contains("org.mozilla.fennec") || sTmpSrcFileName.contains("org.mozilla.firefox")) { ffxSrcFiles = Uri.parse( "content://" + (sTmpSrcFileName.contains("fennec") ? fenProvider : ffxProvider) + "/file"); crIn = contextWrapper.getContentResolver(); } else { try { srcFile = new FileInputStream(sTmpSrcFileName); } catch (FileNotFoundException e) { e.printStackTrace(); } } if (sTmpDstFileName.contains("org.mozilla.fennec") || sTmpDstFileName.contains("org.mozilla.firefox")) { ffxDstFiles = Uri.parse( "content://" + (sTmpDstFileName.contains("fennec") ? fenProvider : ffxProvider) + "/file"); crOut = contextWrapper.getContentResolver(); cv = new ContentValues(); } else { try { dstFile = new FileOutputStream(sTmpDstFileName); } catch (FileNotFoundException e) { e.printStackTrace(); } } if (srcFile != null) { try { while ((nRead = srcFile.read(buffer)) != -1) { lTotalRead += nRead; if (dstFile != null) { dstFile.write(buffer, 0, nRead); dstFile.flush(); } else { cv.put("length", nRead); cv.put("chunk", buffer); if (crOut.update(ffxDstFiles, cv, sTmpDstFileName, null) == 0) break; lTotalWritten += nRead; } } srcFile.close(); if (dstFile != null) { dstFile.flush(); dstFile.close(); destFile = new File(sTmpDstFileName); lTotalWritten = destFile.length(); } if (lTotalWritten == lTotalRead) { sRet = sTmpSrcFileName + " copied to " + sTmpDstFileName; } else { sRet = sErrorPrefix + "Failed to copy " + sTmpSrcFileName + " [length = " + lTotalWritten + "] to " + sTmpDstFileName + " [length = " + lTotalRead + "]"; } } catch (IOException e) { e.printStackTrace(); } } else { String[] columns = new String[] { "_id", "chunk", "length" }; Cursor myCursor = crIn.query(ffxSrcFiles, columns, // Which columns to return sTmpSrcFileName, // Which rows to return (all rows) null, // Selection arguments (none) null); // Order clause (none) if (myCursor != null) { int nRows = myCursor.getCount(); byte[] buf = null; for (int lcv = 0; lcv < nRows; lcv++) { if (myCursor.moveToPosition(lcv)) { buf = myCursor.getBlob(myCursor.getColumnIndex("chunk")); if (buf != null) { nRead = buf.length; try { lTotalRead += nRead; if (dstFile != null) { dstFile.write(buffer, 0, nRead); dstFile.flush(); } else { cv.put("length", nRead); cv.put("chunk", buffer); if (crOut.update(ffxDstFiles, cv, sTmpDstFileName, null) == 0) break; lTotalWritten += nRead; } } catch (IOException e) { e.printStackTrace(); } buf = null; } } } if (nRows == -1) { sRet = sErrorPrefix + sTmpSrcFileName + ",-1\nNo such file or directory"; } else { myCursor.close(); if (dstFile != null) { try { dstFile.flush(); dstFile.close(); destFile = new File(sTmpDstFileName); lTotalWritten = destFile.length(); } catch (IOException e) { e.printStackTrace(); } } if (lTotalWritten == lTotalRead) { sRet = sTmpSrcFileName + " copied to " + sTmpDstFileName; } else { sRet = sErrorPrefix + "Failed to copy " + sTmpSrcFileName + " [length = " + lTotalWritten + "] to " + sTmpDstFileName + " [length = " + lTotalRead + "]"; } } } else { sRet = sErrorPrefix + sTmpSrcFileName + ",-1\nUnable to access file (internal error)"; } } return (sRet); } public String IsDirWritable(String sDir) { String sTmpDir = fixFileName(sDir); String sRet = sErrorPrefix + "[" + sTmpDir + "] is not a directory"; if (sTmpDir.contains("org.mozilla.fennec") || sTmpDir.contains("org.mozilla.firefox")) { ContentResolver cr = contextWrapper.getContentResolver(); Uri ffxFiles = null; ffxFiles = Uri.parse("content://" + (sTmpDir.contains("fennec") ? fenProvider : ffxProvider) + "/dir"); String[] columns = new String[] { "_id", "isdir", "filename", "length", "writable" }; Cursor myCursor = cr.query(ffxFiles, columns, // Which columns to return sTmpDir, // Which rows to return (all rows) null, // Selection arguments (none) null); // Order clause (none) if (myCursor != null) { if (myCursor.getCount() > 0) { if (myCursor.moveToPosition(0)) { if (myCursor.getLong(myCursor.getColumnIndex("isdir")) == 1) { sRet = "[" + sTmpDir + "] " + ((myCursor.getLong(myCursor.getColumnIndex("writable")) == 1) ? "is" : "is not") + " writable"; } } } } } else { File dir = new File(sTmpDir); if (dir.isDirectory()) { sRet = "[" + sTmpDir + "] " + (dir.canWrite() ? "is" : "is not") + " writable"; } else { sRet = sErrorPrefix + "[" + sTmpDir + "] is not a directory"; } } return (sRet); } public String Push(String fileName, BufferedInputStream bufIn, long lSize) { byte[] buffer = new byte[8192]; int nRead = 0; long lRead = 0; String sTmpFileName = fixFileName(fileName); FileOutputStream dstFile = null; ContentResolver cr = null; ContentValues cv = null; Uri ffxFiles = null; String sRet = sErrorPrefix + "Push failed!"; try { if (sTmpFileName.contains("org.mozilla.fennec") || sTmpFileName.contains("org.mozilla.firefox")) { cr = contextWrapper.getContentResolver(); ffxFiles = Uri.parse( "content://" + (sTmpFileName.contains("fennec") ? fenProvider : ffxProvider) + "/file"); cv = new ContentValues(); } else { dstFile = new FileOutputStream(sTmpFileName, false); } while ((nRead != -1) && (lRead < lSize)) { nRead = bufIn.read(buffer); if (nRead != -1) { if (dstFile != null) { dstFile.write(buffer, 0, nRead); dstFile.flush(); } else { cv.put("offset", lRead); cv.put("length", nRead); cv.put("chunk", buffer); cr.update(ffxFiles, cv, sTmpFileName, null); } lRead += nRead; } } if (dstFile != null) { dstFile.flush(); dstFile.close(); } if (lRead == lSize) { sRet = HashFile(sTmpFileName); } } catch (IOException e) { e.printStackTrace(); } buffer = null; return (sRet); } public String FTPGetFile(String sServer, String sSrcFileName, String sDstFileName, OutputStream out) { byte[] buffer = new byte[4096]; int nRead = 0; long lTotalRead = 0; String sRet = sErrorPrefix + "FTP Get failed for " + sSrcFileName; String strRet = ""; int reply = 0; FileOutputStream outStream = null; String sTmpDstFileName = fixFileName(sDstFileName); FTPClient ftp = new FTPClient(); try { ftp.connect(sServer); reply = ftp.getReplyCode(); if (FTPReply.isPositiveCompletion(reply)) { ftp.login("anonymous", "b@t.com"); reply = ftp.getReplyCode(); if (FTPReply.isPositiveCompletion(reply)) { ftp.enterLocalPassiveMode(); if (ftp.setFileType(FTP.BINARY_FILE_TYPE)) { File dstFile = new File(sTmpDstFileName); outStream = new FileOutputStream(dstFile); FTPFile[] ftpFiles = ftp.listFiles(sSrcFileName); if (ftpFiles.length > 0) { long lFtpSize = ftpFiles[0].getSize(); if (lFtpSize <= 0) lFtpSize = 1; InputStream ftpIn = ftp.retrieveFileStream(sSrcFileName); while ((nRead = ftpIn.read(buffer)) != -1) { lTotalRead += nRead; outStream.write(buffer, 0, nRead); strRet = "\r" + lTotalRead + " of " + lFtpSize + " bytes received " + ((lTotalRead * 100) / lFtpSize) + "% completed"; out.write(strRet.getBytes()); out.flush(); } ftpIn.close(); @SuppressWarnings("unused") boolean bRet = ftp.completePendingCommand(); outStream.flush(); outStream.close(); strRet = ftp.getReplyString(); reply = ftp.getReplyCode(); } else { strRet = sRet; } } ftp.logout(); ftp.disconnect(); sRet = "\n" + strRet; } else { ftp.disconnect(); System.err.println("FTP server refused login."); } } else { ftp.disconnect(); System.err.println("FTP server refused connection."); } } catch (SocketException e) { sRet = e.getMessage(); strRet = ftp.getReplyString(); reply = ftp.getReplyCode(); sRet += "\n" + strRet; e.printStackTrace(); } catch (IOException e) { sRet = e.getMessage(); strRet = ftp.getReplyString(); reply = ftp.getReplyCode(); sRet += "\n" + strRet; e.printStackTrace(); } return (sRet); } public String Pull(String fileName, long lOffset, long lLength, OutputStream out) { String sTmpFileName = fixFileName(fileName); String sRet = sErrorPrefix + "Could not read the file " + sTmpFileName; byte[] buffer = new byte[4096]; int nRead = 0; long lSent = 0; if (sTmpFileName.contains("org.mozilla.fennec") || sTmpFileName.contains("org.mozilla.firefox")) { ContentResolver cr = contextWrapper.getContentResolver(); Uri ffxFiles = null; ffxFiles = Uri .parse("content://" + (sTmpFileName.contains("fennec") ? fenProvider : ffxProvider) + "/file"); String[] columns = new String[] { "_id", "chunk", "length" }; String[] args = new String[2]; args[0] = Long.toString(lOffset); args[1] = Long.toString(lLength); Cursor myCursor = cr.query(ffxFiles, columns, // Which columns to return sTmpFileName, // Which rows to return (all rows) args, // Selection arguments (none) null); // Order clause (none) if (myCursor != null) { int nRows = myCursor.getCount(); long lFileLength = 0; for (int lcv = 0; lcv < nRows; lcv++) { if (myCursor.moveToPosition(lcv)) { if (lcv == 0) { lFileLength = myCursor.getLong(2); String sTmp = sTmpFileName + "," + lFileLength + "\n"; try { out.write(sTmp.getBytes()); } catch (IOException e) { e.printStackTrace(); break; } } if (lLength != 0) { byte[] buf = myCursor.getBlob(1); if (buf != null) { nRead = buf.length; try { if ((lSent + nRead) <= lFileLength) { out.write(buf, 0, nRead); lSent += nRead; } else { nRead = (int) (lFileLength - lSent); out.write(buf, 0, nRead); Log.d("pull warning", "more bytes read than expected"); break; } } catch (IOException e) { e.printStackTrace(); sRet = sErrorPrefix + "Could not write to out " + sTmpFileName; } buf = null; } } } } if (nRows == 0) { String sTmp = sTmpFileName + "," + lFileLength + "\n"; try { out.write(sTmp.getBytes()); } catch (IOException e) { e.printStackTrace(); } } if (nRows == -1) { sRet = sErrorPrefix + sTmpFileName + ",-1\nNo such file or directory"; } else { myCursor.close(); sRet = ""; } } else { sRet = sErrorPrefix + sTmpFileName + ",-1\nUnable to access file (internal error)"; } } else { try { File f = new File(sTmpFileName); long lFileLength = f.length(); FileInputStream fin = new FileInputStream(f); if (lFileLength == 0) { while ((nRead = fin.read(buffer)) != -1) { lFileLength += nRead; } fin.close(); fin = new FileInputStream(f); } // lLength == -1 return everything between lOffset and eof // lLength == 0 return file length // lLength > 0 return lLength bytes if (lLength == -1) { lFileLength = lFileLength - lOffset; } else if (lLength == 0) { // just return the file length } else { lFileLength = ((lLength <= (lFileLength - lOffset)) ? lLength : (lFileLength - lOffset)); } String sTmp = sTmpFileName + "," + lFileLength + "\n"; out.write(sTmp.getBytes()); if (lLength != 0) { if (lOffset > 0) { fin.skip(lOffset); } while ((nRead = fin.read(buffer)) != -1) { if ((lSent + nRead) <= lFileLength) { out.write(buffer, 0, nRead); lSent += nRead; } else { nRead = (int) (lFileLength - lSent); out.write(buffer, 0, nRead); if (lLength != -1) Log.d("pull warning", "more bytes read than sent"); break; } } } fin.close(); out.flush(); sRet = ""; } catch (FileNotFoundException e) { sRet = sErrorPrefix + sTmpFileName + ",-1\nNo such file or directory"; } catch (IOException e) { sRet = e.toString(); } } return (sRet); } public String Cat(String fileName, OutputStream out) { String sTmpFileName = fixFileName(fileName); String sRet = sErrorPrefix + "Could not read the file " + sTmpFileName; byte[] buffer = new byte[4096]; int nRead = 0; if (sTmpFileName.contains("org.mozilla.fennec") || sTmpFileName.contains("org.mozilla.firefox")) { ContentResolver cr = contextWrapper.getContentResolver(); Uri ffxFiles = null; ffxFiles = Uri .parse("content://" + (sTmpFileName.contains("fennec") ? fenProvider : ffxProvider) + "/file"); String[] columns = new String[] { "_id", "chunk" }; Cursor myCursor = cr.query(ffxFiles, columns, // Which columns to return sTmpFileName, // Which rows to return (all rows) null, // Selection arguments (none) null); // Order clause (none) if (myCursor != null) { int nRows = myCursor.getCount(); int nBytesRecvd = 0; for (int lcv = 0; lcv < nRows; lcv++) { if (myCursor.moveToPosition(lcv)) { byte[] buf = myCursor.getBlob(1); if (buf != null) { nBytesRecvd += buf.length; try { out.write(buf); sRet = ""; } catch (IOException e) { e.printStackTrace(); sRet = sErrorPrefix + "Could not write to out " + sTmpFileName; } buf = null; } } } if (nRows == 0) { sRet = ""; } myCursor.close(); } } else { try { FileInputStream fin = new FileInputStream(sTmpFileName); while ((nRead = fin.read(buffer)) != -1) { out.write(buffer, 0, nRead); } fin.close(); out.flush(); sRet = ""; } catch (FileNotFoundException e) { sRet = sErrorPrefix + sTmpFileName + " No such file or directory"; } catch (IOException e) { sRet = e.toString(); } } return (sRet); } public String MakeDir(String sDir) { String sTmpDir = fixFileName(sDir); String sRet = sErrorPrefix + "Could not create the directory " + sTmpDir; if (sTmpDir.contains("org.mozilla.fennec") || sTmpDir.contains("org.mozilla.firefox")) { ContentResolver cr = contextWrapper.getContentResolver(); Uri ffxFiles = Uri .parse("content://" + (sTmpDir.contains("fennec") ? fenProvider : ffxProvider) + "/dir"); ContentValues cv = new ContentValues(); if (cr.update(ffxFiles, cv, sTmpDir, null) == 1) { sRet = sDir + " successfully created"; } } else { File dir = new File(sTmpDir); if (dir.mkdirs()) { sRet = sDir + " successfully created"; } } return (sRet); } // move this to SUTAgentAndroid.java public String GetScreenInfo() { String sRet = ""; DisplayMetrics metrics = new DisplayMetrics(); WindowManager wMgr = (WindowManager) contextWrapper.getSystemService(Context.WINDOW_SERVICE); wMgr.getDefaultDisplay().getMetrics(metrics); sRet = "X:" + metrics.widthPixels + " Y:" + metrics.heightPixels; return (sRet); } // move this to SUTAgentAndroid.java public int[] GetScreenXY() { int[] nRetXY = new int[2]; DisplayMetrics metrics = new DisplayMetrics(); WindowManager wMgr = (WindowManager) contextWrapper.getSystemService(Context.WINDOW_SERVICE); wMgr.getDefaultDisplay().getMetrics(metrics); nRetXY[0] = metrics.widthPixels; nRetXY[1] = metrics.heightPixels; return (nRetXY); } public String GetRotationInfo() { WindowManager wMgr = (WindowManager) contextWrapper.getSystemService(Context.WINDOW_SERVICE); int nRotationDegrees = 0; // default switch (wMgr.getDefaultDisplay().getRotation()) { case Surface.ROTATION_90: nRotationDegrees = 90; break; case Surface.ROTATION_180: nRotationDegrees = 180; break; case Surface.ROTATION_270: nRotationDegrees = 270; break; } return "ROTATION:" + nRotationDegrees; } public String SetADB(String sWhat) { String sRet = ""; String sTmp = ""; String sCmd; if (sWhat.contains("ip")) { sCmd = "setprop service.adb.tcp.port 5555"; } else { sCmd = "setprop service.adb.tcp.port -1"; } try { pProc = Runtime.getRuntime().exec(this.getSuArgs(sCmd)); RedirOutputThread outThrd = new RedirOutputThread(pProc, null); outThrd.start(); outThrd.joinAndStopRedirect(5000); sTmp = outThrd.strOutput; Log.e("ADB", sTmp); if (outThrd.nExitCode == 0) { pProc = Runtime.getRuntime().exec(this.getSuArgs("stop adbd")); outThrd = new RedirOutputThread(pProc, null); outThrd.start(); outThrd.joinAndStopRedirect(5000); sTmp = outThrd.strOutput; Log.e("ADB", sTmp); if (outThrd.nExitCode == 0) { pProc = Runtime.getRuntime().exec(this.getSuArgs("start adbd")); outThrd = new RedirOutputThread(pProc, null); outThrd.start(); outThrd.joinAndStopRedirect(5000); sTmp = outThrd.strOutput; Log.e("ADB", sTmp); if (outThrd.nExitCode == 0) { sRet = "Successfully set adb to " + sWhat + "\n"; } else { sRet = sErrorPrefix + "Failed to start adbd\n"; } } else { sRet = sErrorPrefix + "Failed to stop adbd\n"; } } else { sRet = sErrorPrefix + "Failed to setprop service.adb.tcp.port 5555\n"; } } catch (IOException e) { sRet = e.getMessage(); e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } return (sRet); } public String KillProcess(String sProcName, OutputStream out) { String sRet = sErrorPrefix + "Unable to kill " + sProcName + "\n"; ActivityManager aMgr = (ActivityManager) contextWrapper.getSystemService(Activity.ACTIVITY_SERVICE); List<ActivityManager.RunningAppProcessInfo> lProcesses = aMgr.getRunningAppProcesses(); int lcv = 0; String sFoundProcName = ""; int nProcs = 0; boolean bFoundAppProcess = false; if (lProcesses != null) nProcs = lProcesses.size(); for (lcv = 0; lcv < nProcs; lcv++) { if (lProcesses.get(lcv).processName.contains(sProcName)) { sFoundProcName = lProcesses.get(lcv).processName; bFoundAppProcess = true; try { pProc = Runtime.getRuntime().exec(this.getSuArgs("kill " + lProcesses.get(lcv).pid)); RedirOutputThread outThrd = new RedirOutputThread(pProc, null); outThrd.start(); outThrd.joinAndStopRedirect(15000); String sTmp = outThrd.strOutput; Log.e("KILLPROCESS", sTmp); } catch (IOException e) { sRet = e.getMessage(); e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } } if (bFoundAppProcess) { // Give the messages a chance to be processed try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } sRet = "Successfully killed " + sProcName + "\n"; lProcesses = aMgr.getRunningAppProcesses(); nProcs = 0; if (lProcesses != null) nProcs = lProcesses.size(); for (lcv = 0; lcv < nProcs; lcv++) { if (lProcesses.get(lcv).processName.contains(sProcName)) { sRet = sErrorPrefix + "Unable to kill " + sProcName + " (couldn't kill " + sFoundProcName + ")\n"; break; } } } else { // To kill processes other than Java applications - processes // like xpcshell - a different strategy is necessary: use ps // to find the process' PID. try { pProc = Runtime.getRuntime().exec("ps"); RedirOutputThread outThrd = new RedirOutputThread(pProc, null); outThrd.start(); outThrd.joinAndStopRedirect(10000); String sTmp = outThrd.strOutput; StringTokenizer stokLines = new StringTokenizer(sTmp, "\n"); while (stokLines.hasMoreTokens()) { String sLine = stokLines.nextToken(); StringTokenizer stokColumns = new StringTokenizer(sLine, " \t\n"); stokColumns.nextToken(); String sPid = stokColumns.nextToken(); stokColumns.nextToken(); stokColumns.nextToken(); stokColumns.nextToken(); stokColumns.nextToken(); stokColumns.nextToken(); stokColumns.nextToken(); String sName = null; if (stokColumns.hasMoreTokens()) { sName = stokColumns.nextToken(); if (sName.contains(sProcName)) { NewKillProc(sPid, out); sRet = "Successfully killed " + sName + "\n"; } } } } catch (Exception e) { e.printStackTrace(); } } return (sRet); } public boolean IsProcessDead(String sProcName) { boolean bRet = false; ActivityManager aMgr = (ActivityManager) contextWrapper.getSystemService(Activity.ACTIVITY_SERVICE); List<ActivityManager.ProcessErrorStateInfo> lProcesses = aMgr.getProcessesInErrorState(); int lcv = 0; if (lProcesses != null) { for (lcv = 0; lcv < lProcesses.size(); lcv++) { if (lProcesses.get(lcv).processName.contentEquals(sProcName) && lProcesses.get(lcv).condition != ActivityManager.ProcessErrorStateInfo.NO_ERROR) { bRet = true; break; } } } return (bRet); } public String GetProcessInfo() { String sRet = ""; ActivityManager aMgr = (ActivityManager) contextWrapper.getSystemService(Activity.ACTIVITY_SERVICE); List<ActivityManager.RunningAppProcessInfo> lProcesses = aMgr.getRunningAppProcesses(); int nProcs = 0; int lcv = 0; String strProcName = ""; int nPID = 0; int nUser = 0; if (lProcesses != null) nProcs = lProcesses.size(); for (lcv = 0; lcv < nProcs; lcv++) { strProcName = lProcesses.get(lcv).processName; nPID = lProcesses.get(lcv).pid; nUser = lProcesses.get(lcv).uid; sRet += nUser + "\t" + nPID + "\t" + strProcName; if (lcv < (nProcs - 1)) sRet += "\n"; } return (sRet); } public String GetOSInfo() { String sRet = ""; sRet = Build.DISPLAY; return (sRet); } public String GetPowerInfo() { String sRet = ""; sRet = "Power status:\n AC power " + SUTAgentAndroid.sACStatus + "\n"; sRet += " Battery charge " + SUTAgentAndroid.sPowerStatus + "\n"; sRet += " Remaining charge: " + SUTAgentAndroid.nChargeLevel + "%\n"; sRet += " Battery Temperature: " + (((float) (SUTAgentAndroid.nBatteryTemp)) / 10) + " (c)\n"; return (sRet); } public String GetSutUserInfo() { String sRet = ""; try { // based on patch in https://bugzilla.mozilla.org/show_bug.cgi?id=811763 Context context = contextWrapper.getApplicationContext(); Object userManager = context.getSystemService("user"); if (userManager != null) { // if userManager is non-null that means we're running on 4.2+ and so the rest of this // should just work Object userHandle = android.os.Process.class.getMethod("myUserHandle", (Class[]) null).invoke(null); Object userSerial = userManager.getClass() .getMethod("getSerialNumberForUser", userHandle.getClass()).invoke(userManager, userHandle); sRet += "User Serial:" + userSerial.toString(); } } catch (Exception e) { // Guard against any unexpected failures e.printStackTrace(); } return sRet; } public String GetTemperatureInfo() { String sTempVal = "unknown"; String sDeviceFile = "/sys/bus/platform/devices/temp_sensor_hwmon.0/temp1_input"; try { pProc = Runtime.getRuntime().exec(this.getSuArgs("cat " + sDeviceFile)); RedirOutputThread outThrd = new RedirOutputThread(pProc, null); outThrd.start(); outThrd.joinAndStopRedirect(5000); String output = outThrd.strOutput; // this only works on pandas (with the temperature sensors turned // on), other platforms we just get a file not found error... we'll // just return "unknown" for that case try { sTempVal = String.valueOf(Integer.parseInt(output.trim()) / 1000.0); } catch (NumberFormatException e) { // not parsed! probably not a panda } } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } return "Temperature: " + sTempVal; } public String GetDiskInfo(String sPath) { String sRet = ""; StatFs statFS = new StatFs(sPath); long nBlockCount = statFS.getBlockCount(); long nBlockSize = statFS.getBlockSize(); long nBlocksAvail = statFS.getAvailableBlocks(); // Free is often the same as Available, but can include reserved // blocks that are not available to normal applications. // long nBlocksFree = statFS.getFreeBlocks(); sRet = sPath + ": " + (nBlockCount * nBlockSize) + " total, " + (nBlocksAvail * nBlockSize) + " available"; return (sRet); } public String GetMemoryInfo() { String sRet = "PA:" + GetMemoryConfig() + ", FREE: " + GetMemoryUsage(); return (sRet); } public long GetMemoryConfig() { ActivityManager aMgr = (ActivityManager) contextWrapper.getSystemService(Activity.ACTIVITY_SERVICE); ActivityManager.MemoryInfo outInfo = new ActivityManager.MemoryInfo(); aMgr.getMemoryInfo(outInfo); long lMem = outInfo.availMem; return (lMem); } public long GetMemoryUsage() { String load = ""; try { RandomAccessFile reader = new RandomAccessFile("/proc/meminfo", "r"); load = reader.readLine(); // Read in the MemTotal load = reader.readLine(); // Read in the MemFree } catch (IOException ex) { return (0); } String[] toks = load.split(" "); int i = 1; for (i = 1; i < toks.length; i++) { String val = toks[i].trim(); if (!val.equals("")) { break; } } if (i <= toks.length) { long lMem = Long.parseLong(toks[i].trim()); return (lMem * 1024); } return (0); } public String UpdateCallBack(String sFileName) { String sRet = sErrorPrefix + "No file specified"; String sIP = ""; String sPort = ""; int nEnd = 0; int nStart = 0; if ((sFileName == null) || (sFileName.length() == 0)) return (sRet); Context ctx = contextWrapper.getApplicationContext(); try { FileInputStream fis = ctx.openFileInput(sFileName); int nBytes = fis.available(); if (nBytes > 0) { byte[] buffer = new byte[nBytes + 1]; int nRead = fis.read(buffer, 0, nBytes); fis.close(); ctx.deleteFile(sFileName); if (nRead > 0) { String sBuffer = new String(buffer); nEnd = sBuffer.indexOf(','); if (nEnd > 0) { sIP = (sBuffer.substring(0, nEnd)).trim(); nStart = nEnd + 1; nEnd = sBuffer.indexOf('\r', nStart); if (nEnd > 0) { sPort = (sBuffer.substring(nStart, nEnd)).trim(); Thread.sleep(5000); sRet = RegisterTheDevice(sIP, sPort, sBuffer.substring(nEnd + 1)); } } } } } catch (FileNotFoundException e) { sRet = sErrorPrefix + "Nothing to do"; } catch (IOException e) { sRet = sErrorPrefix + "Couldn't send info to " + sIP + ":" + sPort; } catch (InterruptedException e) { e.printStackTrace(); } return (sRet); } public String RegisterTheDevice(String sSrvr, String sPort, String sData) { String sRet = ""; String line = ""; // Debug.waitForDebugger(); if (sSrvr != null && sPort != null && sData != null) { try { int nPort = Integer.parseInt(sPort); Socket socket = new Socket(sSrvr, nPort); PrintWriter out = new PrintWriter(socket.getOutputStream(), false); BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); out.println(sData); if (out.checkError() == false) { socket.setSoTimeout(30000); while (socket.isInputShutdown() == false) { line = in.readLine(); if (line != null) { line = line.toLowerCase(); sRet += line; // ok means we're done if (line.contains("ok")) break; } else { // end of stream reached break; } } } out.close(); in.close(); socket.close(); } catch (NumberFormatException e) { sRet += "reg NumberFormatException thrown [" + e.getLocalizedMessage() + "]"; e.printStackTrace(); } catch (UnknownHostException e) { sRet += "reg UnknownHostException thrown [" + e.getLocalizedMessage() + "]"; e.printStackTrace(); } catch (IOException e) { sRet += "reg IOException thrown [" + e.getLocalizedMessage() + "]"; e.printStackTrace(); } } return (sRet); } public String GetInternetData(String sHost, String sPort, String sURL) { String sRet = ""; String sNewURL = ""; HttpClient httpClient = new DefaultHttpClient(); try { sNewURL = "http://" + sHost + ((sPort.length() > 0) ? (":" + sPort) : "") + sURL; HttpGet request = new HttpGet(sNewURL); HttpResponse response = httpClient.execute(request); int status = response.getStatusLine().getStatusCode(); // we assume that the response body contains the error message if (status != HttpStatus.SC_OK) { ByteArrayOutputStream ostream = new ByteArrayOutputStream(); response.getEntity().writeTo(ostream); Log.e("HTTP CLIENT", ostream.toString()); } else { InputStream content = response.getEntity().getContent(); byte[] data = new byte[2048]; int nRead = content.read(data); sRet = new String(data, 0, nRead); content.close(); // this will also close the connection } } catch (IllegalArgumentException e) { sRet = e.getLocalizedMessage(); e.printStackTrace(); } catch (ClientProtocolException e) { sRet = e.getLocalizedMessage(); e.printStackTrace(); } catch (IOException e) { sRet = e.getLocalizedMessage(); e.printStackTrace(); } return (sRet); } public String GetTimeZone() { String sRet = ""; TimeZone tz; tz = TimeZone.getDefault(); Date now = new Date(); sRet = tz.getDisplayName(tz.inDaylightTime(now), TimeZone.LONG); return (sRet); } public String SetTimeZone(String sTimeZone) { String sRet = "Unable to set timezone to " + sTimeZone; TimeZone tz = null; AlarmManager amgr = null; if ((sTimeZone.length() > 0) && (sTimeZone.startsWith("GMT"))) { amgr = (AlarmManager) contextWrapper.getSystemService(Context.ALARM_SERVICE); if (amgr != null) amgr.setTimeZone(sTimeZone); } else { String[] zoneNames = TimeZone.getAvailableIDs(); int nNumMatches = zoneNames.length; int lcv = 0; for (lcv = 0; lcv < nNumMatches; lcv++) { if (zoneNames[lcv].equalsIgnoreCase(sTimeZone)) break; } if (lcv < nNumMatches) { amgr = (AlarmManager) contextWrapper.getSystemService(Context.ALARM_SERVICE); if (amgr != null) amgr.setTimeZone(zoneNames[lcv]); } } if (amgr != null) { tz = TimeZone.getDefault(); Date now = new Date(); sRet = tz.getDisplayName(tz.inDaylightTime(now), TimeZone.LONG); } return (sRet); } public String GetSystemTime() { String sRet = ""; Calendar cal = Calendar.getInstance(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss:SSS"); sRet = sdf.format(cal.getTime()); return (sRet); } public String SetSystemTime(String sDate, String sTime, OutputStream out) { String sRet = ""; String sM = ""; String sMillis = ""; if (((sDate != null) && (sTime != null)) && (sDate.contains("/") || sDate.contains(".")) && (sTime.contains(":"))) { int year = Integer.parseInt(sDate.substring(0, 4)); int month = Integer.parseInt(sDate.substring(5, 7)); int day = Integer.parseInt(sDate.substring(8, 10)); int hour = Integer.parseInt(sTime.substring(0, 2)); int mins = Integer.parseInt(sTime.substring(3, 5)); int secs = Integer.parseInt(sTime.substring(6, 8)); Calendar cal = new GregorianCalendar(TimeZone.getDefault()); cal.set(year, month - 1, day, hour, mins, secs); long lMillisecs = cal.getTime().getTime(); sM = Long.toString(lMillisecs); sMillis = sM.substring(0, sM.length() - 3) + "." + sM.substring(sM.length() - 3); } else { sRet += "Invalid argument(s)"; } // if we have an argument if (sMillis.length() > 0) { try { pProc = Runtime.getRuntime().exec(this.getSuArgs("date -u " + sMillis)); RedirOutputThread outThrd = new RedirOutputThread(pProc, null); outThrd.start(); outThrd.joinAndStopRedirect(10000); sRet += GetSystemTime(); } catch (IOException e) { sRet = e.getMessage(); e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } return (sRet); } public String GetClok() { long lMillisecs = System.currentTimeMillis(); String sRet = ""; if (lMillisecs > 0) sRet = Long.toString(lMillisecs); return (sRet); } public String GetUptime() { String sRet = ""; long lHold = 0; long lUptime = SystemClock.elapsedRealtime(); int nDays = 0; int nHours = 0; int nMinutes = 0; int nSecs = 0; int nMilliseconds = 0; if (lUptime > 0) { nDays = (int) (lUptime / (24L * 60L * 60L * 1000L)); lHold = lUptime % (24L * 60L * 60L * 1000L); nHours = (int) (lHold / (60L * 60L * 1000L)); lHold %= 60L * 60L * 1000L; nMinutes = (int) (lHold / (60L * 1000L)); lHold %= 60L * 1000L; nSecs = (int) (lHold / 1000L); nMilliseconds = (int) (lHold % 1000); sRet = "" + nDays + " days " + nHours + " hours " + nMinutes + " minutes " + nSecs + " seconds " + nMilliseconds + " ms"; } return (sRet); } public String GetUptimeMillis() { return Long.toString(SystemClock.uptimeMillis()); } public String GetSutUptimeMillis() { long now = System.currentTimeMillis(); return "SUTagent running for " + Long.toString(now - SUTAgentAndroid.nCreateTimeMillis) + " ms"; } public String NewKillProc(String sProcId, OutputStream out) { String sRet = ""; try { pProc = Runtime.getRuntime().exec("kill " + sProcId); RedirOutputThread outThrd = new RedirOutputThread(pProc, out); outThrd.start(); outThrd.joinAndStopRedirect(5000); } catch (IOException e) { sRet = e.getMessage(); e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } return (sRet); } public String SendPing(String sIPAddr, OutputStream out) { String sRet = ""; String[] theArgs = new String[4]; theArgs[0] = "ping"; theArgs[1] = "-c"; theArgs[2] = "3"; theArgs[3] = sIPAddr; try { pProc = Runtime.getRuntime().exec(theArgs); RedirOutputThread outThrd = new RedirOutputThread(pProc, out); outThrd.start(); outThrd.joinAndStopRedirect(5000); if (out == null) sRet = outThrd.strOutput; } catch (IOException e) { sRet = e.getMessage(); e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } return (sRet); } public String GetTmpDir() { String sRet = ""; Context ctx = contextWrapper.getApplicationContext(); File dir = ctx.getFilesDir(); ctx = null; try { sRet = dir.getCanonicalPath(); } catch (IOException e) { e.printStackTrace(); } return (sRet); } public String PrintFileTimestamp(String sFile) { String sRet = ""; String sTmpFileName = fixFileName(sFile); long lModified = -1; if (sTmpFileName.contains("org.mozilla.fennec") || sTmpFileName.contains("org.mozilla.firefox")) { ContentResolver cr = contextWrapper.getContentResolver(); Uri ffxFiles = Uri .parse("content://" + (sTmpFileName.contains("fennec") ? fenProvider : ffxProvider) + "/dir"); String[] columns = new String[] { "_id", "isdir", "filename", "length", "ts" }; Cursor myCursor = cr.query(ffxFiles, columns, // Which columns to return sTmpFileName, // Which rows to return (all rows) null, // Selection arguments (none) null); // Order clause (none) if (myCursor != null) { if (myCursor.getCount() > 0) { if (myCursor.moveToPosition(0)) { lModified = myCursor.getLong(myCursor.getColumnIndex("ts")); } } myCursor.close(); } } else { File theFile = new File(sTmpFileName); if (theFile.exists()) { lModified = theFile.lastModified(); } } if (lModified != -1) { Date dtModified = new Date(lModified); SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss:SSS"); sRet = "Last modified: " + sdf.format(dtModified); } else { sRet = sErrorPrefix + "[" + sTmpFileName + "] doesn't exist"; } return (sRet); } public String GetIniData(String sSection, String sKey, String sFile) { String sRet = ""; String sComp = ""; String sLine = ""; boolean bFound = false; BufferedReader in = null; String sTmpFileName = fixFileName(sFile); try { in = new BufferedReader(new FileReader(sTmpFileName)); sComp = "[" + sSection + "]"; while ((sLine = in.readLine()) != null) { if (sLine.equalsIgnoreCase(sComp)) { bFound = true; break; } } if (bFound) { sComp = (sKey + " =").toLowerCase(); while ((sLine = in.readLine()) != null) { if (sLine.toLowerCase().contains(sComp)) { String[] temp = null; temp = sLine.split("="); if (temp != null) { if (temp.length > 1) sRet = temp[1].trim(); } break; } } } in.close(); } catch (FileNotFoundException e) { sComp = e.toString(); } catch (IOException e) { sComp = e.toString(); } return (sRet); } public String RunReboot(OutputStream out, String sCallBackIP, String sCallBackPort) { String sRet = ""; Context ctx = contextWrapper.getApplicationContext(); try { if ((sCallBackIP != null) && (sCallBackPort != null) && (sCallBackIP.length() > 0) && (sCallBackPort.length() > 0)) { FileOutputStream fos = ctx.openFileOutput("update.info", Context.MODE_WORLD_READABLE | Context.MODE_WORLD_WRITEABLE); String sBuffer = sCallBackIP + "," + sCallBackPort + "\rSystem rebooted\r"; fos.write(sBuffer.getBytes()); fos.flush(); fos.close(); fos = null; } } catch (FileNotFoundException e) { sRet = sErrorPrefix + "Callback file creation error [rebt] call failed " + e.getMessage(); e.printStackTrace(); } catch (IOException e) { sRet = sErrorPrefix + "Callback file error [rebt] call failed " + e.getMessage(); e.printStackTrace(); } try { // Tell all of the data channels we are rebooting ((ASMozStub) this.contextWrapper).SendToDataChannel("Rebooting ..."); pProc = Runtime.getRuntime().exec(this.getSuArgs("reboot")); RedirOutputThread outThrd = new RedirOutputThread(pProc, out); outThrd.start(); outThrd.joinAndStopRedirect(10000); } catch (IOException e) { sRet = e.getMessage(); e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } return (sRet); } private String[] getSuArgs(String cmdString) { String[] theArgs = new String[3]; theArgs[0] = "su"; theArgs[1] = "-c"; // as a security measure, ICS and later resets LD_LIBRARY_PATH. reset // it here when executing the command theArgs[2] = "LD_LIBRARY_PATH=/vendor/lib:/system/lib " + cmdString; return theArgs; } public String UnInstallApp(String sApp, OutputStream out, boolean reboot) { String sRet = ""; try { if (reboot == true) { pProc = Runtime.getRuntime().exec(this.getSuArgs("pm uninstall " + sApp + ";reboot;exit")); } else { pProc = Runtime.getRuntime().exec(this.getSuArgs("pm uninstall " + sApp + ";exit")); } RedirOutputThread outThrd = new RedirOutputThread(pProc, out); outThrd.start(); try { outThrd.joinAndStopRedirect(60000); int nRet = pProc.exitValue(); sRet = "\nuninst complete [" + nRet + "]"; } catch (IllegalThreadStateException itse) { itse.printStackTrace(); sRet = "\nuninst command timed out"; } } catch (IOException e) { sRet = e.getMessage(); e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } return (sRet); } public String InstallApp(String sApp, OutputStream out) { String sRet = ""; File srcFile = new File(sApp); try { // on android 4.2 and above, we want to pass the "-d" argument to pm so that version // downgrades are allowed... (option unsupported in earlier versions) String sPmCmd; if (android.os.Build.VERSION.SDK_INT >= 17) { // JELLY_BEAN_MR1 sPmCmd = "pm install -r -d " + sApp + " Cleanup;exit"; } else { sPmCmd = "pm install -r " + sApp + " Cleanup;exit"; } pProc = Runtime.getRuntime().exec(this.getSuArgs(sPmCmd)); RedirOutputThread outThrd3 = new RedirOutputThread(pProc, out); outThrd3.start(); try { outThrd3.joinAndStopRedirect(60000); int nRet3 = pProc.exitValue(); if (nRet3 == 0) { sRet = "\ninstallation complete [0]\n"; } else { sRet = "\nFailure pm install [" + nRet3 + "]\n"; } } catch (IllegalThreadStateException itse) { itse.printStackTrace(); sRet = "\nFailure pm install command timed out\n"; } try { out.write(sRet.getBytes()); out.flush(); } catch (IOException e1) { e1.printStackTrace(); } } catch (IOException e) { sRet = e.getMessage(); e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } return (sRet); } public String StrtUpdtOMatic(String sPkgName, String sPkgFileName, String sCallBackIP, String sCallBackPort) { String sRet = ""; Context ctx = contextWrapper.getApplicationContext(); PackageManager pm = ctx.getPackageManager(); Intent prgIntent = new Intent(); prgIntent.setPackage("com.mozilla.watcher"); try { PackageInfo pi = pm.getPackageInfo("com.mozilla.watcher", PackageManager.GET_SERVICES | PackageManager.GET_INTENT_FILTERS); ServiceInfo[] si = pi.services; for (int i = 0; i < si.length; i++) { ServiceInfo s = si[i]; if (s.name.length() > 0) { prgIntent.setClassName(s.packageName, s.name); break; } } } catch (NameNotFoundException e) { e.printStackTrace(); sRet = sErrorPrefix + "watcher is not properly installed"; return (sRet); } prgIntent.putExtra("command", "updt"); prgIntent.putExtra("pkgName", sPkgName); prgIntent.putExtra("pkgFile", sPkgFileName); prgIntent.putExtra("reboot", true); try { if ((sCallBackIP != null) && (sCallBackPort != null) && (sCallBackIP.length() > 0) && (sCallBackPort.length() > 0)) { FileOutputStream fos = ctx.openFileOutput("update.info", Context.MODE_WORLD_READABLE | Context.MODE_WORLD_WRITEABLE); String sBuffer = sCallBackIP + "," + sCallBackPort + "\rupdate started " + sPkgName + " " + sPkgFileName + "\r"; fos.write(sBuffer.getBytes()); fos.flush(); fos.close(); fos = null; prgIntent.putExtra("outFile", ctx.getFilesDir() + "/update.info"); } else { if (prgIntent.hasExtra("outFile")) { System.out.println("outFile extra unset from intent"); prgIntent.removeExtra("outFile"); } } ComponentName cn = contextWrapper.startService(prgIntent); if (cn != null) sRet = "exit"; else sRet = sErrorPrefix + "Unable to use watcher service"; } catch (ActivityNotFoundException anf) { sRet = sErrorPrefix + "Activity Not Found Exception [updt] call failed"; anf.printStackTrace(); } catch (FileNotFoundException e) { sRet = sErrorPrefix + "File creation error [updt] call failed"; e.printStackTrace(); } catch (IOException e) { sRet = sErrorPrefix + "File error [updt] call failed"; e.printStackTrace(); } ctx = null; return (sRet); } public String StartJavaPrg(String[] sArgs, Intent preIntent) { String sRet = ""; String sArgList = ""; String sUrl = ""; // String sRedirFileName = ""; Intent prgIntent = null; Context ctx = contextWrapper.getApplicationContext(); PackageManager pm = ctx.getPackageManager(); if (preIntent == null) prgIntent = new Intent(); else prgIntent = preIntent; prgIntent.setPackage(sArgs[0]); prgIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // Get the main activity for this package try { final ComponentName c = pm.getLaunchIntentForPackage(sArgs[0]).getComponent(); prgIntent.setClassName(c.getPackageName(), c.getClassName()); } catch (Exception e) { e.printStackTrace(); return "Unable to find main activity for package: " + sArgs[0]; } if (sArgs.length > 1) { if (sArgs[0].contains("android.browser")) prgIntent.setAction(Intent.ACTION_VIEW); else prgIntent.setAction(Intent.ACTION_MAIN); if (sArgs[0].contains("fennec") || sArgs[0].contains("firefox")) { sArgList = ""; sUrl = ""; for (int lcv = 1; lcv < sArgs.length; lcv++) { if (sArgs[lcv].contains("://")) { prgIntent.setAction(Intent.ACTION_VIEW); sUrl = sArgs[lcv]; } else { if (sArgs[lcv].equals(">")) { lcv++; if (lcv < sArgs.length) lcv++; // sRedirFileName = sArgs[lcv++]; } else sArgList += " " + sArgs[lcv]; } } if (sArgList.length() > 0) prgIntent.putExtra("args", sArgList.trim()); if (sUrl.length() > 0) prgIntent.setData(Uri.parse(sUrl.trim())); } else { for (int lcv = 1; lcv < sArgs.length; lcv++) sArgList += " " + sArgs[lcv]; prgIntent.setData(Uri.parse(sArgList.trim())); } } else { prgIntent.setAction(Intent.ACTION_MAIN); } try { contextWrapper.startActivity(prgIntent); FindProcThread findProcThrd = new FindProcThread(contextWrapper, sArgs[0]); findProcThrd.start(); findProcThrd.join(7000); if (!findProcThrd.bFoundIt && !findProcThrd.bStillRunning) { sRet = "Unable to start " + sArgs[0] + ""; } } catch (ActivityNotFoundException anf) { anf.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } ctx = null; return (sRet); } public String StartPrg(String[] progArray, OutputStream out, boolean startAsRoot, int timeoutSeconds) { String sRet = ""; int lcv = 0; try { if (startAsRoot) { // we need to requote the program string here, in case // there's spaces or other characters which need quoting // before being passed to su List<String> quotedProgList = new ArrayList<String>(); for (String arg : progArray) { String quotedArg = arg; quotedArg = quotedArg.replace("\"", "\\\""); quotedArg = quotedArg.replace("\'", "\\\'"); if (quotedArg.contains(" ")) { quotedArg = "\"" + quotedArg + "\""; } quotedProgList.add(quotedArg); } pProc = Runtime.getRuntime().exec(this.getSuArgs(TextUtils.join(" ", quotedProgList))); } else { pProc = Runtime.getRuntime().exec(progArray); } RedirOutputThread outThrd = new RedirOutputThread(pProc, out); outThrd.start(); try { outThrd.join(timeoutSeconds * 1000); int nRetCode = pProc.exitValue(); sRet = "return code [" + nRetCode + "]"; } catch (IllegalThreadStateException itse) { } outThrd.stopRedirect(); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); sRet = "Timed out!"; } return (sRet); } public String StartPrg2(String[] progArray, OutputStream out, String cwd, boolean startAsRoot, int timeoutSeconds) { String sRet = ""; int nArraySize = 0; int nArgs = progArray.length - 1; // 1st arg is the environment string int lcv = 0; int temp = 0; String sEnvString = progArray[0]; if (!sEnvString.contains("=") && (sEnvString.length() > 0)) { if (sEnvString.contains("/") || sEnvString.contains("\\") || !sEnvString.contains(".")) sRet = StartPrg(progArray, out, startAsRoot, timeoutSeconds); else sRet = StartJavaPrg(progArray, null); return (sRet); } // Set up command line args stripping off the environment string String[] theArgs = new String[nArgs]; for (lcv = 0; lcv < nArgs; lcv++) { theArgs[lcv] = progArray[lcv + 1]; } try { String[] envStrings = sEnvString.split(","); Map<String, String> newEnv = new HashMap<String, String>(); for (lcv = 0; lcv < envStrings.length; lcv++) { temp = envStrings[lcv].indexOf("="); if (temp > 0) { newEnv.put(envStrings[lcv].substring(0, temp), envStrings[lcv].substring(temp + 1, envStrings[lcv].length())); } } Map<String, String> sysEnv = System.getenv(); nArraySize = sysEnv.size(); for (Map.Entry<String, String> entry : newEnv.entrySet()) { if (!sysEnv.containsKey(entry.getKey())) { nArraySize++; } } String[] envArray = new String[nArraySize]; int i = 0; int offset; String sKey = ""; String sValue = ""; for (Map.Entry<String, String> entry : sysEnv.entrySet()) { sKey = entry.getKey(); if (newEnv.containsKey(sKey)) { sValue = newEnv.get(sKey); if ((offset = sValue.indexOf("$" + sKey)) != -1) { envArray[i++] = sKey + "=" + sValue.substring(0, offset) + entry.getValue() + sValue.substring(offset + sKey.length() + 1); } else envArray[i++] = sKey + "=" + sValue; newEnv.remove(sKey); } else envArray[i++] = entry.getKey() + "=" + entry.getValue(); } for (Map.Entry<String, String> entry : newEnv.entrySet()) { envArray[i++] = entry.getKey() + "=" + entry.getValue(); } if (theArgs[0].contains("/") || theArgs[0].contains("\\") || !theArgs[0].contains(".")) { if (cwd != null) { File f = new File(cwd); pProc = Runtime.getRuntime().exec(theArgs, envArray, f); } else { pProc = Runtime.getRuntime().exec(theArgs, envArray); } RedirOutputThread outThrd = new RedirOutputThread(pProc, out); outThrd.start(); try { outThrd.join(timeoutSeconds * 1000); int nRetCode = pProc.exitValue(); sRet = "return code [" + nRetCode + "]"; } catch (IllegalThreadStateException itse) { } outThrd.stopRedirect(); } else { Intent preIntent = new Intent(); for (lcv = 0; lcv < envArray.length; lcv++) { preIntent.putExtra("env" + lcv, envArray[lcv]); } sRet = StartJavaPrg(theArgs, preIntent); } } catch (UnsupportedOperationException e) { if (e != null) e.printStackTrace(); } catch (ClassCastException e) { if (e != null) e.printStackTrace(); } catch (IllegalArgumentException e) { if (e != null) e.printStackTrace(); } catch (NullPointerException e) { if (e != null) e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); sRet = "Timed out!"; } return (sRet); } public String ChmodDir(String sDir) { String sRet = ""; int nFiles = 0; String sSubDir = null; String sTmpDir = fixFileName(sDir); File dir = new File(sTmpDir); if (dir.isDirectory()) { sRet = "Changing permissions for " + sTmpDir; File[] files = dir.listFiles(); if (files != null) { if ((nFiles = files.length) > 0) { for (int lcv = 0; lcv < nFiles; lcv++) { if (files[lcv].isDirectory()) { sSubDir = files[lcv].getAbsolutePath(); sRet += "\n" + ChmodDir(sSubDir); } else { // set the new file's permissions to rwxrwxrwx, if possible try { Process pProc = Runtime.getRuntime() .exec(this.getSuArgs("chmod 777 " + files[lcv])); RedirOutputThread outThrd = new RedirOutputThread(pProc, null); outThrd.start(); outThrd.joinAndStopRedirect(5000); sRet += "\n\tchmod " + files[lcv].getName() + " ok"; } catch (InterruptedException e) { sRet += "\n\ttimeout waiting for chmod " + files[lcv].getName(); } catch (IOException e) { sRet += "\n\tunable to chmod " + files[lcv].getName(); } } } } else sRet += "\n\t<empty>"; } } // set the new directory's (or file's) permissions to rwxrwxrwx, if possible try { Process pProc = Runtime.getRuntime().exec(this.getSuArgs("chmod 777 " + sTmpDir)); RedirOutputThread outThrd = new RedirOutputThread(pProc, null); outThrd.start(); outThrd.joinAndStopRedirect(5000); sRet += "\n\tchmod " + sTmpDir + " ok"; } catch (InterruptedException e) { sRet += "\n\ttimeout waiting for chmod " + sTmpDir; } catch (IOException e) { sRet += "\n\tunable to chmod " + sTmpDir; } return (sRet); } public String TopActivity() { String sRet = ""; ActivityManager aMgr = (ActivityManager) contextWrapper.getSystemService(Activity.ACTIVITY_SERVICE); List<ActivityManager.RunningTaskInfo> taskInfo = null; ComponentName componentInfo = null; if (aMgr != null) { taskInfo = aMgr.getRunningTasks(1); } if (taskInfo != null) { // topActivity: "The activity component at the top of the history stack of the task. // This is what the user is currently doing." componentInfo = taskInfo.get(0).topActivity; } if (componentInfo != null) { sRet = componentInfo.getPackageName(); } return (sRet); } private String PrintUsage() { String sRet = "run [cmdline] - start program no wait\n" + "exec [env pairs] [cmdline] - start program no wait optionally pass env\n" + " key=value pairs (comma separated)\n" + "execcwd <dir> [env pairs] [cmdline] - start program from specified directory\n" + "execsu [env pairs] [cmdline] - start program as privileged user\n" + "execcwdsu <dir> [env pairs] [cmdline] - start program from specified directory as privileged user\n" + "execext [su] [cwd=<dir>] [t=<timeout>] [env pairs] [cmdline] - start program with extended options\n" + "kill [program name] - kill program no path\n" + "killall - kill all processes started\n" + "ps - list of running processes\n" + "info - list of device info\n" + " [os] - os version for device\n" + " [id] - unique identifier for device\n" + " [uptime] - uptime for device\n" + " [uptimemillis] - uptime for device in milliseconds\n" + " [sutuptimemillis] - uptime for SUT in milliseconds\n" + " [systime] - current system time\n" + " [screen] - width, height and bits per pixel for device\n" + " [memory] - physical, free, available, storage memory\n" + " for device\n" + " [processes] - list of running processes see 'ps'\n" + "alrt [on/off] - start or stop sysalert behavior\n" + "disk [arg] - prints disk space info\n" + "cp file1 file2 - copy file1 to file2\n" + "time file - timestamp for file\n" + "hash file - generate hash for file\n" + "cd directory - change cwd\n" + "cat file - cat file\n" + "cwd - display cwd\n" + "mv file1 file2 - move file1 to file2\n" + "push filename - push file to device\n" + "rm file - delete file\n" + "rmdr directory - delete directory even if not empty\n" + "mkdr directory - create directory\n" + "dirw directory - tests whether the directory is writable\n" + "isdir directory - test whether the directory exists\n" + "chmod directory|file - change permissions of directory and contents (or file) to 777\n" + "stat processid - stat process\n" + "dead processid - print whether the process is alive or hung\n" + "mems - dump memory stats\n" + "ls - print directory\n" + "tmpd - print temp directory\n" + "ping [hostname/ipaddr] - ping a network device\n" + "unzp zipfile destdir - unzip the zipfile into the destination dir\n" + "zip zipfile src - zip the source file/dir into zipfile\n" + "rebt - reboot device\n" + "inst /path/filename.apk - install the referenced apk file\n" + "uninst packagename - uninstall the referenced package and reboot\n" + "uninstall packagename - uninstall the referenced package without a reboot\n" + "updt pkgname pkgfile - unpdate the referenced package\n" + "clok - the current device time expressed as the" + " number of millisecs since epoch\n" + "settime date time - sets the device date and time\n" + " (YYYY/MM/DD HH:MM:SS)\n" + "tzset timezone - sets the device timezone format is\n" + " GMTxhh:mm x = +/- or a recognized Olsen string\n" + "tzget - returns the current timezone set on the device\n" + "rebt - reboot device\n" + "adb ip|usb - set adb to use tcp/ip on port 5555 or usb\n" + "activity - print package name of top (foreground) activity\n" + "quit - disconnect SUTAgent\n" + "exit - close SUTAgent\n" + "ver - SUTAgent version\n" + "help - you're reading it"; return (sRet); } }