blob: 59d0d67e8d99d6c7ffc0b3f3223b9f93ef999ee7 [file] [log] [blame]
/* 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 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();
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 notification = new Notification.Builder(context)
.setContentTitle(tickerText)
.setContentText(expandedText)
.setSmallIcon(icon)
.setWhen(when)
.setContentIntent(launchIntent)
.build();
notification.flags |= (Notification.FLAG_INSISTENT | Notification.FLAG_AUTO_CANCEL);
notification.defaults |= Notification.DEFAULT_SOUND;
notification.defaults |= Notification.DEFAULT_VIBRATE;
notification.defaults |= Notification.DEFAULT_LIGHTS;
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 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);
}
}