Java tutorial
/* * Copyright 2012 AT&T * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.att.android.arodatacollector.utils; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.lang.reflect.Field; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; import java.util.Calendar; import java.util.Date; import java.util.Enumeration; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpParams; import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.os.Environment; import android.os.StatFs; import android.provider.Settings; /** * Contains utility methods that are used by the ARO Data Collector. * */ public class AROCollectorUtils { private static final String COLLECTOR = "collector"; private static final String USER = "USER"; private static final String TCPDUMP = "tcpdump"; /** Logging string for the ARO Collector Utils class. */ public static final String TAG = "AROCollectorUtils"; /** used for exiting the activity when the analyzer timeout happens */ public static final String ANALYZER_TIMEOUT_SHUTDOWN_INTENT = "arodatacollector.timeout.SHUTDOWN"; public static final String ANALYZER_CLOSE_CMD_INTENT = "arodatacollector.home.activity.close"; /** used to close the old instance when a new one is launched from the analyzer*/ public static final String ANALYZER_LAUNCH_CLEANUP_INTENT = "arodatacollector.launch.cleanup"; /** Empty String */ public static String EMPTY_STRING = ""; /** Not Applicable */ public static String NOT_APPLICABLE = "NA"; /** * Gets the ARO Data Collector time stamp * * @return The time stamp value in seconds. */ public double getDataCollectorEventTimeStamp() { return getSystemTimeinSeconds(); } /** * Gets the system time value(in seconds). * * @return The system time stamp value(in seconds ). */ public double getSystemTimeinSeconds() { return (double) System.currentTimeMillis() / 1000; } /** * Deletes the specified trace directory from the device. * * @param path * The trace directory path to be deleted. * * @return A boolean value that is "true" if the trace folder was deleted * successfully, and "false" if it was not. */ public boolean deleteDirectory(File path) { if (path.exists()) { final File[] files = path.listFiles(); for (int i = 0; i < files.length; i++) { if (files[i].isDirectory()) { deleteDirectory(files[i]); } else { files[i].delete(); } } } return (path.delete()); } /** * Indicates whether or not there are special characters in the specified * trace folder name. * * @param tracefolername * The trace folder name. * * @return A boolean value that is "true" if the trace folder name contains * a special character and "false" if it does not. */ public boolean isContainsSpecialCharacterorSpace(String tracefolername) { boolean isContainsSC = false; if (tracefolername != null && !tracefolername.equals("")) { // Pattern to include alphanumeric with "-" final Matcher m = Pattern.compile("[^a-zA-Z0-9[-]]").matcher(tracefolername); if (m.find()) { isContainsSC = true; } else { isContainsSC = false; } } return isContainsSC; } /** * Returns a value that indicates whether or not the flight mode is turned * on. * * @param context * The application context. * @return A boolean value that is "true" if the flight mode is ON and * "false" if it is not. */ public boolean isAirplaneModeOn(Context context) { return Settings.System.getInt(context.getContentResolver(), Settings.System.AIRPLANE_MODE_ON, 0) != 0; } /** * Retrieves the value of the specified field from an instance of the specified class using * reflection. * * @param mClass * The name of the class. * @param mInstance * The object containing the value to be retrieved. * @param fieldName * The name of the field to be retrieved. * @return The value of the specified field from the specified class. */ public final String getSpecifiedFieldValues(Class<?> mClass, Object mInstance, String fieldName) { String fieldValue = ""; if (mClass == null || mInstance == null || fieldName == null) return fieldValue; try { final Field field = mClass.getDeclaredField(fieldName); if (field != null) { field.setAccessible(true); fieldValue = field.get(mInstance).toString(); } } catch (NoSuchFieldException exp) { fieldValue = ""; AROLogger.e(TAG, "Exception in getSpecifiedFieldValues NoSuchFieldException" + exp); } catch (IllegalAccessException ile) { fieldValue = ""; AROLogger.e(TAG, "Exception in getSpecifiedFieldValues IllegalAccessException" + ile); } return fieldValue; } /** * Returns a value indicating whether or not the device SD card is mounted. * * @return A boolean value that is "true" if the SD card is mounted, and * "false" if it is not. */ public boolean checkSDCardMounted() { final String state = Environment.getExternalStorageState(); if (state.equals(Environment.MEDIA_REMOVED) || !state.equals(Environment.MEDIA_MOUNTED) || state.equals(Environment.MEDIA_MOUNTED_READ_ONLY)) { return true; } else { return false; } } /** * Executes the specified linux command on the device shell. * * @param shellCommand * A linux native shell command. * * @return The output from the linux native shell command. */ public String runCommand(String shellCommand) { String stdout; String sRet = ""; String stderr; try { final Process m_process = Runtime.getRuntime().exec(shellCommand); final StringBuilder sbread = new StringBuilder(); final Thread tout = new Thread(new Runnable() { public void run() { BufferedReader bufferedReader = new BufferedReader( new InputStreamReader(m_process.getInputStream()), 8192); String ls_1 = null; try { while ((ls_1 = bufferedReader.readLine()) != null) { sbread.append(ls_1).append("\n"); } } catch (IOException e) { AROLogger.e(TAG, "IOException in runCommand" + e); } finally { try { bufferedReader.close(); } catch (IOException e) { AROLogger.e(TAG, "Exception in runCommand bufferedReader.close()" + e); } } } }); tout.start(); final StringBuilder sberr = new StringBuilder(); final Thread terr = new Thread(new Runnable() { public void run() { final BufferedReader bufferedReader = new BufferedReader( new InputStreamReader(m_process.getErrorStream()), 8192); String ls_1 = null; try { while ((ls_1 = bufferedReader.readLine()) != null) { sberr.append(ls_1).append("\n"); } } catch (IOException e) { AROLogger.e(TAG, "Exception in runCommand" + e); } finally { try { bufferedReader.close(); } catch (IOException e) { AROLogger.e(TAG, "Exception in runCommand bufferedReader.close()" + e); } } } }); terr.start(); while (tout.isAlive()) { Thread.sleep(50); } if (terr.isAlive()) terr.interrupt(); stdout = sbread.toString(); stderr = sberr.toString(); sRet = stdout + stderr; } catch (java.io.IOException ee) { AROLogger.e(TAG, "Exception in runCommand" + ee); return null; } catch (InterruptedException ie) { AROLogger.e(TAG, "Exception in runCommand" + ie); return null; } return sRet; } /** * find the process info * @param processName * @return * @throws IOException * @throws InterruptedException */ public static String executePS(String processName) throws IOException, InterruptedException { AROLogger.d(TAG, "entered ps..."); final Process process = Runtime.getRuntime().exec("ps " + processName); final InputStreamReader inputStream = new InputStreamReader(process.getInputStream()); final BufferedReader reader = new BufferedReader(inputStream); try { String line = null; int read; final char[] buffer = new char[4096]; final StringBuffer output = new StringBuffer(); while ((read = reader.read(buffer)) > 0) { output.append(buffer, 0, read); } // Waits for the command to finish. process.waitFor(); //no need to destroy the process since waitFor() will wait until all subprocesses exit line = output.toString(); return line; } finally { try { reader.close(); inputStream.close(); reader.close(); } catch (Exception e) { AROLogger.e(TAG, "Exception caught while closing resources in executePS. Error msg=" + e.getMessage()); AROLogger.e(TAG, "execution will be allowed to continue"); } AROLogger.d(TAG, "exiting ps..."); } } /** * Gets the process ID for the specified process name. * * @param processName * The name of the process. * * @return The process ID. * @throws java.io.IOException * @throws java.lang.InterruptedException * @throws java.lang.IndexOutOfBoundsException */ public int getProcessID(String processName) throws IOException, InterruptedException { String line = null; int pid = 0; // default line = executePS(processName); String[] rows = line.split("\\n"); if (AROLogger.logVerbose) { for (int rowNum = 0; rowNum < rows.length; rowNum++) { AROLogger.v(TAG, "values row " + rowNum + ": " + ">>>" + rows[rowNum] + "<<<"); } } if (rows[0].startsWith(USER)) { AROLogger.v(TAG, "PID should be in 2nd column in single row retrieved"); for (int rowNum = 1; rowNum < rows.length; rowNum++) { final String row = rows[rowNum]; final String[] values_item = row.split("\\s+"); if (AROLogger.logVerbose) { for (int itemNum = 0; itemNum < values_item.length; itemNum++) { AROLogger.v(TAG, "item " + itemNum + ": " + ">>>" + values_item[itemNum] + "<<<"); } } // expects second column is PID // for (int itemNum = 1; itemNum < values_item.length; // itemNum++) { int itemNum = 1; // second column contains PID if (values_item[itemNum].length() > 0) { String temp = null; temp = values_item[itemNum]; try { pid = Integer.valueOf(temp); } catch (NumberFormatException nfe) { AROLogger.e(TAG, nfe.getClass().getName() + " thrown trying to parse PID"); // will allow to return default PID of 0 } // also check process code status itemNum = 7; // eighth column contains process state code; // do not want Z if (values_item[itemNum].equals("Z")) { continue;// look in next row } AROLogger.d(TAG, "header column: " + itemNum + ">>PID returned: " + pid); } // } return pid; } AROLogger.d(TAG, "exiting if USER block with PID (without finding one): " + pid); } else { AROLogger.d(TAG, "entered else-issuing ps command by itself"); line = executePS(""); rows = line.split("\\n"); if (rows != null && (rows.length > 1)) { int column_num = -1; // default for (int itemNumPS = 0; itemNumPS < rows.length; itemNumPS++) { final String row = rows[itemNumPS]; if (AROLogger.logVerbose) { AROLogger.v(TAG, "row " + itemNumPS + ": " + ">>>" + row + "<<<"); } final String[] value_item = row.split("\\s+"); // assumption on ps // command: // processname // is last row, // so even split // by space will // return // correct item // expect 1st row to return column header names; find column // with "PID" if (itemNumPS == 0) { AROLogger.d(TAG, "header row..."); for (int headerItemNum = 0; headerItemNum < value_item.length; headerItemNum++) { if (AROLogger.logVerbose) { AROLogger.v(TAG, "header item " + headerItemNum + "=" + value_item[headerItemNum]); } if (value_item[headerItemNum].equalsIgnoreCase("PID")) { column_num = headerItemNum; break; } } } else { AROLogger.v(TAG, "rows of processes..."); for (int processRowNum = 0; processRowNum < value_item.length; processRowNum++) { if (value_item[processRowNum].contains(processName)) { pid = Integer.valueOf(value_item[column_num]); // returns 1st match AROLogger.v(TAG, "for process " + processName + " found PID: " + pid); return pid; } } } } } else { // pid is still equal to 0; nothing else to do but log AROLogger.d(TAG, "values.length: " + rows.length + "-PID: " + pid); } } AROLogger.d(TAG, "exiting getProcessID()-returning PID: " + pid); return pid; } /** * Gets the default ARO trace folder name in the HH:MM:SS:DD:MM:YY format. * * @return The default ARO trace folder name. */ public String getDefaultTraceFolderName() { final Date systemDate = new Date(); final Calendar now = Calendar.getInstance(); final int currenthours = systemDate.getHours(); final int currentminutes = systemDate.getMinutes(); final int currentseconds = systemDate.getSeconds(); final int currentdate = now.get(Calendar.DATE); // java calendar int currentmonth = now.get(Calendar.MONTH); // As Jan is defined as 0 in currentmonth = currentmonth + 1; if (currentmonth >= 13) // As Jan is defined as 0 in java calendar currentmonth = 1; String currentMonth = Integer.toString(currentmonth); String currentDate = Integer.toString(currentdate); String currentHours = Integer.toString(currenthours); String currentMinutes = Integer.toString(currentminutes); String currentSeconds = Integer.toString(currentseconds - 1); if (currentmonth < 10) { currentMonth = ""; currentMonth = "0" + currentmonth; } if (currentdate < 10) { currentDate = ""; currentDate = "0" + currentdate; } if (currenthours < 10) { currentHours = ""; currentHours = "0" + currenthours; } if (currentminutes < 10) { currentMinutes = ""; currentMinutes = "0" + currentminutes; } if (currentseconds < 10) { currentSeconds = ""; currentSeconds = "0" + currentseconds; } final String folderName = now.get(Calendar.YEAR) + "-" + currentMonth + "-" + currentDate + "-" + currentHours + "-" + currentMinutes + "-" + currentSeconds; return folderName; } /** * Retrieves overall information about the specified application package * * @param pm * The package manager instance. * @param name * The package name. * * @return Returns information about the package or null if the package * could not be successfully parsed. */ public static PackageInfo getPackageInfo(PackageManager pm, String name) { PackageInfo ret = null; try { ret = pm.getPackageInfo(name, PackageManager.GET_ACTIVITIES); } catch (NameNotFoundException e) { AROLogger.e(TAG, "Exception in getPackageInfo" + e); } return ret; } /** * Reverts the specified source string. * * @param from * The source string. * @return The reverted string. */ public static String revert(String from) { if (from == null || from.length() <= 1) return from; final int len = from.length(); final StringBuilder sb = new StringBuilder(len); for (int i = 1; i <= len; i++) { sb.append(from.charAt(len - i)); } return sb.toString(); } /** * Parses the integer value of the specified object. * * @param s * The source object. * @return An integer value parsed from the specified object. */ public static int parseInt(Object s) { return parseInt(s == null ? null : s.toString(), 0); } /** * Parses the integer value of the specified string. * * @param s * The string value to parse. * @param iDefault * A default integer value. * * @return An integer value parsed from the specified string. */ public static int parseInt(String s, int iDefault) { return (int) parseLong(s, iDefault); } /** * Parses the long value of the specified string. * * @param s * The string value to parse. * @param iDefault * A default long value. * @return A long value parsed from the specified string. */ public static long parseLong(String s, long iDefault) { if (s == null || s.equals("")) return iDefault; try { s = s.trim().replaceAll(",", ""); final int l = s.indexOf('.'); if (l > 0) s = s.substring(0, l); return Long.parseLong(s); } catch (RuntimeException e) { return iDefault; } } /** * Returns the IP Address of the device during the trace cycle when it is * connected to the network. * * @return The IP Address of the device. * * @throws java.net.SocketException */ public String getLocalIpAddress() throws SocketException { for (final Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en .hasMoreElements();) { final NetworkInterface intf = en.nextElement(); for (final Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr .hasMoreElements();) { final InetAddress inetAddress = enumIpAddr.nextElement(); if (!inetAddress.isLoopbackAddress()) { return inetAddress.getHostAddress(); } } } return null; } /** * Deletes the specified trace folder. * * @param tracefoldername * The name of the trace folder to be deleted. * @return A boolean value that is "true" if the trace folder was * successfully deleted and "false" if it was not. */ public boolean deleteTraceFolder(File tracefoldername) { if (tracefoldername.isDirectory()) { final String[] children = tracefoldername.list(); for (int i = 0; i < children.length; i++) { if (!deleteTraceFolder(new File(tracefoldername, children[i]))) { return false; } } } // The directory is now empty so delete it return tracefoldername.delete(); } /** * Returns the amount of available memory left on the device SD Card (in * bytes). */ public long checkSDCardMemoryAvailable() { final StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getPath()); final long bytesAvailable = (long) stat.getBlockSize() * (long) stat.getAvailableBlocks(); final long kbsAvailable = bytesAvailable / 1024; // float megAvailable = (long) (bytesAvailable / (1024.f * 1024.f)); return kbsAvailable; } /** * Opens the http connection to http://www.google.com/, and enables the * network data packet. * * @throws java.io.IOException * @throws ClientProtocolException */ public void OpenHttpConnection() throws ClientProtocolException, IOException { final String strUrl = "http://www.google.com"; final int timeoutConnection = 15000; final int timeoutSocket = 15000; InputStream in = null; BufferedReader reader = null; InputStreamReader inputstreamReader = null; HttpClient client = null; HttpResponse response = null; HttpParams httpParameters = new BasicHttpParams(); HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection); HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket); client = new DefaultHttpClient(httpParameters); HttpPost post = new HttpPost(strUrl); try { // add headers post.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8"); post.addHeader("Cache-Control", "no-cache"); post.addHeader("Pragma", "no-cache"); response = client.execute(post); in = response.getEntity().getContent(); inputstreamReader = new InputStreamReader(in); reader = new BufferedReader(inputstreamReader); final StringBuilder builder = new StringBuilder(); String line = null; while ((line = reader.readLine()) != null) { builder.append(line + "\n"); } } finally { if (inputstreamReader != null) { inputstreamReader.close(); } if (in != null) { in.close(); } if (reader != null) { reader.close(); } if (client != null) { client.getConnectionManager().shutdown(); } httpParameters = null; post = null; client = null; response = null; } } /** * Returns a value indicating whether tcpdump is running on the * native shell. * * @return A boolean value that is "true" if tcpdump is running on the * native shell, and is "false" otherwise. */ public static boolean isTcpDumpRunning() { boolean isAroTcpDumpRunning = false; try { String line = null; int pid = 0; // default line = executePS(TCPDUMP); String[] rows = line.split("\\n"); if (AROLogger.logVerbose) { for (int rowNum = 0; rowNum < rows.length; rowNum++) { AROLogger.v(TAG, "values row " + rowNum + ": " + ">>>" + rows[rowNum] + "<<<"); } } if (rows[0].startsWith(USER)) { AROLogger.v(TAG, "PID should be in 2nd column in single row retrieved"); for (int rowNum = 1; rowNum < rows.length; rowNum++) { final String row = rows[rowNum]; final String[] columns = row.split("\\s+"); if (AROLogger.logVerbose) { for (int itemNum = 0; itemNum < columns.length; itemNum++) { AROLogger.v(TAG, "item " + itemNum + ": " + ">>>" + columns[itemNum] + "<<<"); } } int pNameIndex = columns.length - 1; //process name is the last column String pName = columns[pNameIndex]; if (pName != null && pName.contains(COLLECTOR)) { isAroTcpDumpRunning = true; break; } } if (AROLogger.logDebug) { AROLogger.d(TAG, "exiting if USER block with PID (without finding one): " + pid); } } if (AROLogger.logDebug) { AROLogger.d(TAG, "isTcpDumpRunning: " + isAroTcpDumpRunning); } } catch (IOException e) { AROLogger.e(TAG, e.getClass().getName() + " thrown by pstcpdump()"); } catch (InterruptedException e) { AROLogger.e(TAG, e.getClass().getName() + " thrown by pstcpdump()"); } return isAroTcpDumpRunning; } }