package org.linaro.iasenov.benchmarkframework; import android.annotation.SuppressLint; import android.app.Activity; import android.app.AlertDialog; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.graphics.Color; import android.graphics.Typeface; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.text.Html; import android.text.method.ScrollingMovementMethod; import android.util.DisplayMetrics; import android.util.Log; import android.util.TypedValue; import android.view.Gravity; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.view.WindowManager; import android.widget.AbsListView; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.BaseAdapter; import android.widget.Button; import android.widget.CheckBox; import android.widget.GridView; import android.widget.ListView; import android.widget.NumberPicker; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; import java.io.BufferedWriter; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.lang.reflect.Method; import java.math.BigInteger; import java.security.SecureRandom; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; public class MainActivity extends AppCompatActivity implements View.OnClickListener { private static String TAG = "BenchmarkFramework"; private Button mStartButton; private Button mStartAutoButton; private Button mChartButton; private Button mInfo; private Button mShowHideDispay; private TextView mDisplayDetails; private static TextView mToolbarRepeatIndicator; public ProgressDialog progressDialog; private String mSelectedTest = ""; private String mSelectedClassTest = ""; public static String autoTestFileNameIdentifier = "Default"; private String mTestResult = ""; private String mAllTestsResult = ""; public static String PACKAGE_NAME; private List mAllTests; private ArrayList selectedClassTests; private static String KEY_REPEAT_NUMBER = "repeat-number"; private static String KEY_FILE_FORMAT = "file-format"; public static boolean IS_SHELL_CONTROL = false; public static String LOG_PATH = ""; public static String EXECUTABLE_PATH = ""; public static String SAVE_DATA_PATH = ""; public static String TEMP_PATH = ""; public static String mRepeatNumber=""; public static String fileFormatFromSettings = ""; private int nextTestIndex; private int allTestsCount; private int numberOfCheckedTests = 0; public int endTestCounter; private boolean isAuto = false; private boolean isSelected = false; public boolean isTempLogFileNeeded = false; public boolean isCanceled = false; private Context mContext; public static Activity mActivity; private static int pixWide; private static int pixHigh; private static int testDone = 0; private Typeface tf = Typeface.create("monospace", 0); public File autoTestFile; //file for auto saving tests results(when isAuto); private TaskCanceler taskCanceler; private Handler handler = new Handler(); public static long elapsedTotalTime = 0; public static String runningTests = ""; public static int APP_UID; public static String mStep; public static String mFrom; public static String mSelectedTxt; public static String GRAPHICS_ELAPSED_TIME = "graphics_elapsed_time"; public static String GRAPHICS_ROUND = "graphics_round"; public static Map mapTimes = new HashMap(); //************************* private int count; private boolean[] testselection; private MyAdapter mGridViewAdapter; int pixMin; public GridView mListViewGrid; public static final Lock LOCK = new Lock(); final String[] classNameTestItems = {"Test1", "Test2", "Test3", "Test4", "Test5", "Test6", "Test7", "Test8", "Test9", "Test10", "Test11", "Test12", "Test13", "Test14", "Test15", "Test16", "Test17", "Test18", "Test19", "Test20", "Test21", "Test22", "Test23", "Test24", "Test25", "Test26", "Test27", "Test28", "Test29", "Test30", "Test31", "Test32", "Test33", "Test34", "Test35", "Test36", "Test37", "Test38", "Test39", "Test40", "Test41", "Test42", "Test43", "Test44", "Test45", "Test46"}; //********************************************************************************************** @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //Prevent screen off cause this will interrupt the some of tests running in own activity(GPU tests) getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); mContext = getApplicationContext(); mActivity = this; APP_UID = android.os.Process.myUid(); PACKAGE_NAME = getApplicationContext().getPackageName(); mStartButton = (Button) findViewById(R.id.startButton); mStartButton.setOnClickListener(this); //*************************************************** SharedPreferences prefs = getPreferences(MODE_PRIVATE); //Load repeat number tests from preferences mRepeatNumber = prefs.getString(KEY_REPEAT_NUMBER,"1"); //Load file format from preferences fileFormatFromSettings = prefs.getString(KEY_FILE_FORMAT,"html"); // Find the toolbar view inside the activity layout Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); // Sets the Toolbar to act as the ActionBar for this Activity window. // Make sure the toolbar exists in the activity and is not null setSupportActionBar(toolbar); getSupportActionBar().setTitle(" Benchmark Framework"); //getSupportActionBar().setSubtitle(" Linaro Open source benchmarks"); getSupportActionBar().setIcon(R.drawable.lmg_logo_toolbar); mToolbarRepeatIndicator = (TextView) findViewById(R.id.toolbar_repeat_indicator); mToolbarRepeatIndicator.setText(" "+mRepeatNumber+" "); mStartAutoButton = (Button) findViewById(R.id.startAutoButton); mStartAutoButton.setOnClickListener(this); mChartButton = (Button) findViewById(R.id.chartButton); mChartButton.setOnClickListener(this); mInfo = (Button) findViewById(R.id.infoButton); mInfo.setOnClickListener(this); mShowHideDispay = (Button) findViewById(R.id.showHideDisplay); mShowHideDispay.setOnClickListener(this); mDisplayDetails = (TextView) findViewById(R.id.displayDetails); DisplayMetrics metrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(metrics); mDisplayDetails.setTypeface(tf); pixHigh = metrics.heightPixels; pixWide = metrics.widthPixels; testDone = 0; pixMin = pixWide; if (pixHigh < pixMin) pixMin = pixHigh; mDisplayDetails.setTextSize(TypedValue.COMPLEX_UNIT_PX, getPixels(pixMin)); mDisplayDetails.setTextColor(Color.rgb(102, 255, 51)); mDisplayDetails.setBackgroundColor(Color.BLACK); mDisplayDetails.setMovementMethod(new ScrollingMovementMethod()); //show listview with saved results files and give option to read them mDisplayDetails.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { // TODO Auto-generated method stub Intent i = new Intent(mActivity, Results.class); //Intent i = new Intent(mActivity, Chart.class); startActivity(i); return true; } }); LOG_PATH = getFilesDir() + "/logss" + "/tmpLog.txt"; EXECUTABLE_PATH = getFilesDir() + "/executable_file"; SAVE_DATA_PATH = getFilesDir() + "/download"; TEMP_PATH = EXECUTABLE_PATH + "/temp"; final String[] displayNames = {"MemSpeed", "RandMem", "Linaro-Libc-Bench", "Linaro-StringBench", "Linaro-Harness", "Linaro-Dhrystone", "Iozone", "Bonnie++", "Algorithm(ART)", "BMsGame(ART)", "Caffeine(ART)", "Jit-out(ART)", "Math(ART)", "Micro(ART)", "Stanford(ART)", "DrawArc(GPU)", "DrawCircle2(GPU)", "DrawImage(GPU)", "DrawRect(GPU)", "DrawText(GPU)", "DrawCircle(GPU)", "Kubench(GPU)", "Nehe08(GPU)", "Nehe16(GPU)", "TeapotES(GPU)", "Tiotester", "Himeno", "Stream", "FS-Mark", "Bork", "SciMark", "Smallpt", "Tscp", "Hint", "Fhourstones", "Monte-Carlo", "Bonds", "Repo", "N-queens", "SysBench", "BinaryTrees", "MallocBench", "StressBench", "TuXBencH", "Later", "LinPack"}; //*******************GridView******************* this.count = displayNames.length; this.testselection = new boolean[count]; mListViewGrid = (GridView) findViewById(R.id.listGrid); mGridViewAdapter = new MyAdapter(displayNames); mListViewGrid.setAdapter(mGridViewAdapter); //********************************************** IS_SHELL_CONTROL = false; //Check if shell control is used for tests //This fix issue with NullPointer on mListViewGrid(invoke isShellControl() when mListViewGrid layout is already inflate) mListViewGrid.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @SuppressLint("NewApi") @Override public void onGlobalLayout() { //At this point the layout is complete and the //dimensions of myView and any child views are known. Log.i(TAG, "onGlobalLayout"); mListViewGrid.getViewTreeObserver().removeOnGlobalLayoutListener(this); isShellControl(); } }); //isShellControl(); } //********************************************************************************************** //********************************************************************************************** @Override public void onResume() { super.onResume(); // put your code here... } //********************************************************************************************** @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch(requestCode) { case (100) : { if (resultCode == Activity.RESULT_OK) { // TODO Extract the data returned from the child Activity. BaseBenchmark.elapsedFromActivityTest = data.getLongExtra(MainActivity. GRAPHICS_ELAPSED_TIME,0); BaseBenchmark.mRound = data.getIntExtra(MainActivity.GRAPHICS_ROUND,0); Log.i(TAG,"elapsed from activity test:" + BaseBenchmark.elapsedFromActivityTest); synchronized (MainActivity.LOCK) { MainActivity.LOCK.setCondition(true); MainActivity.LOCK.notifyAll(); } } if (resultCode == Activity.RESULT_CANCELED) { Log.i(TAG,"RESULT_CANCELED"); //Need to set isCanceled flag here isCanceled = true; //Simulate click on calcel button progressDialog.show(); progressDialog.getButton(DialogInterface.BUTTON_NEGATIVE).performClick(); synchronized (MainActivity.LOCK) { MainActivity.LOCK.setCondition(true); MainActivity.LOCK.notifyAll(); } } break; } } } //********************************************************************************************** //Load benchmarks libraries when benchmark test is integrated as (*.so) //********************************************************************************************** static { System.loadLibrary("memspeedlib"); System.loadLibrary("randmemlib"); //System.loadLibrary("cbench"); //System.loadLibrary("stringbench"); //System.loadLibrary("harness"); } //********************************************************************************************** @Override public void onClick(View v) { Log.i(TAG, "numberOfCheckedTests: " + numberOfCheckedTests); if (v.getId() == R.id.startButton && numberOfCheckedTests > 0) { isAuto = false; isSelected = true; //This check will be removed in future if (mSelectedClassTest.equals("Test4")) { isTempLogFileNeeded = true; } else { isTempLogFileNeeded = false; } runTests(Integer.parseInt(mRepeatNumber)); } else if (v.getId() == R.id.startButton && numberOfCheckedTests == 0) { Toast.makeText(v.getContext(), "Please select test...", Toast.LENGTH_SHORT).show(); } else if (v.getId() == R.id.chartButton && testDone == 1) { //saveUIResultToFile(); Intent i = new Intent(mActivity, Chart.class); startActivity(i); } else if (v.getId() == R.id.chartButton && testDone == 0) { Toast.makeText(v.getContext(), "No charts to show", Toast.LENGTH_SHORT).show(); } else if (v.getId() == R.id.startAutoButton) { isAuto = true; isSelected = false; runTests(Integer.parseInt(mRepeatNumber)); } else if (v.getId() == R.id.infoButton) { String info = "[RUN TEST]: Run selected tests

" + "[RUN AUTO]: Run all tests in row and save results to file automatically

" + "[CHART]: Create chart for executed tests

" + "[Settings]:
- Allow to control tests repeatability" + "

- Clear Data" + "

- File format"+ "

- Device info"; createAlertDialog("Help", info, false); } else if(v.getId() == R.id.showHideDisplay){ //Log.i(TAG,"showHideDisplay"); if(mDisplayDetails.getVisibility() == View.GONE){ //Log.i(TAG,"set visible"); mDisplayDetails.setVisibility(View.VISIBLE); ((Button)v).setText("HIDE DISPLAY"); }else{ mDisplayDetails.setVisibility(View.GONE); ((Button)v).setText("SHOW DISPLAY"); //Log.i(TAG, "set gone"); } } } //********************************************************************************************** @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } //********************************************************************************************** @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { //showTestRepeatNumber(); Intent i = new Intent(this, SettingsActivity.class); startActivity(i); return true; } return super.onOptionsItemSelected(item); } private void displayResult(String result) { mDisplayDetails.setText(result); } //********************************************************************************************** //********************************************************************************************** public static Activity getActivity(){ return mActivity; } //********************************************************************************************** //********************************************************************************************** //Show info about repeat indicator textview in toolbar //********************************************************************************************** public void onRepeatIndicatorClick(View v){ int x = (int)v.getX(); int y = (int)v.getY(); Context context = mContext; CharSequence message = "Repeat indicator"; int duration = Toast.LENGTH_SHORT; final Toast toastTop = Toast.makeText(context, message, duration); toastTop.setGravity(Gravity.TOP | Gravity.LEFT, x,y); toastTop.show(); } //********************************************************************************************** //Calculate best text size depends on pixels //********************************************************************************************** public int getPixels(int pixMin) { int correction = 0; int pixels = 11+correction; if (pixMin < 401) { pixels = 12+correction; } else if (pixMin < 451) { pixels = 14+correction; } else if (pixMin < 501) { pixels = 15+correction; } else if (pixMin < 551) { pixels = 16+correction; } else if (pixMin < 601) { pixels = 18+correction; } else if (pixMin < 651) { pixels = 20+correction; } else if (pixMin < 721) { pixels = 22+correction; } else if (pixMin < 751) { pixels = 23+correction; } else if (pixMin < 801) { pixels = 24+correction; } else if (pixMin < 851) { pixels = 26+correction; } else if (pixMin < 901) { pixels = 28+correction; } else if (pixMin < 951) { pixels = 30+correction; } else { pixels = 32+correction; } return pixels; } //********************************************************************************************** //Save "mDisplayDetails" text to file //********************************************************************************************** public void saveUIResultToFile() { File dir = new File(getFilesDir() + "/download"); dir.mkdirs(); File file = new File(dir, "testUIData.txt"); try { FileOutputStream f = new FileOutputStream(file); PrintWriter pw = new PrintWriter(f); pw.println(mDisplayDetails.getText().toString()); pw.flush(); pw.close(); f.close(); Log.i("IVO", getFilesDir() + " FilePath: " + file.getAbsolutePath()); Toast.makeText(mContext, "Result was saved to file: " + file.getAbsolutePath(), Toast.LENGTH_LONG).show(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } //********************************************************************************************** //Save results from Auto tests to text file with random name every time //********************************************************************************************** public void saveAutoTestResultToFile() { File dir = new File(getFilesDir() + "/download"); dir.mkdirs(); if(fileFormatFromSettings.equals("txt")) { autoTestFile = new File(dir, "testLogcatData_" + autoTestFileNameIdentifier + ".txt"); }else if(fileFormatFromSettings.equals("html")){ autoTestFile = new File(dir, "testLogcatData_" + autoTestFileNameIdentifier + ".html"); } try { FileOutputStream f = new FileOutputStream(autoTestFile, true);//apppend=true PrintWriter pw = new PrintWriter(f); if(fileFormatFromSettings.equals("txt")) { pw.println(mTestResult/*mDisplayDetails.getText().toString()*/); }else if(fileFormatFromSettings.equals("html")){ pw.println(HtmlUtil.resultHtmlString); HtmlUtil.clear(); } pw.flush(); pw.close(); f.close(); Log.i(TAG, getFilesDir() + " FilePath: " + autoTestFile.getAbsolutePath()); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } //********************************************************************************************** //Run tests //********************************************************************************************** public void runTests(int timesToRun) { nextTestIndex = 0; allTestsCount = 0; elapsedTotalTime = 0; mAllTests = new ArrayList(); selectedClassTests = new ArrayList(); mAllTestsResult = ""; selectedClassTests.clear(); mAllTests.clear(); //Clear chart data mapTimes.clear(); //HTML BEGIN //Clear html string if(fileFormatFromSettings.equals("html")) { HtmlUtil.clear(); } //HTML END runningTests = ""; //reset cancel flag isCanceled = false; //Create taskCanceler taskCanceler = new TaskCanceler(); mDisplayDetails.scrollTo(0, 0); //Show to async task when real end has come endTestCounter = timesToRun; if (isAuto) { for (int i = 0; i < mListViewGrid.getCount(); i++) { mAllTests.add((mGridViewAdapter.getTextByPosition(i)).toString()); } } if (isSelected) { for (int i = 0; i < mListViewGrid.getCount(); i++) { if (testselection[i]) { mAllTests.add((mGridViewAdapter.getTextByPosition(i))); selectedClassTests.add(classNameTestItems[i]); } } } allTestsCount = mAllTests.size(); if (isAuto) Log.i(TAG, "autoTest:" + allTestsCount); if (isSelected) Log.i(TAG, "Number of selected tests:" + allTestsCount); Log.i(TAG, "Repeat tests:" + timesToRun); if (mAllTests.size() > 0) { SecureRandom random = new SecureRandom(); autoTestFileNameIdentifier = new BigInteger(11, random).toString(32); for(int counter = 0; counter < timesToRun; counter++) { //Clear test index on each repeat nextTestIndex = 0; for (int i = 0; i < allTestsCount; i++) { isTempLogFileNeeded = false;//make it false for now if (nextTestIndex < allTestsCount) { if (isAuto) { mSelectedTest = mAllTests.get(nextTestIndex); mSelectedClassTest = classNameTestItems[nextTestIndex]; } if (isSelected) { mSelectedTest = mAllTests.get(nextTestIndex).toString(); mSelectedClassTest = selectedClassTests.get(nextTestIndex).toString(); } String localSelectedTest = mSelectedTest; String localSelectedClassTest = mSelectedClassTest; //Add to summery string if(counter == 0) { //Add test only once to summary runningTests = runningTests + "," + localSelectedClassTest; } AsyncTaskRunner runner = new AsyncTaskRunner(localSelectedTest, localSelectedClassTest, counter+1, timesToRun); //Prepeare it for cancel situation taskCanceler.addAsyncTask(runner); //runner.execute(mSelectedTest); runner.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, localSelectedTest); //} nextTestIndex++; } } } } } //********************************************************************************************** //Can Use this method when benchmark test take a lot of time and logcat dev/log/main ring buffer is overloaded //Reads only app logs //********************************************************************************************** public Process writeLogcatToFile() { Log.i(TAG, "writeLogcatToFile"); Process process = null; try { Runtime.getRuntime().exec(new String[]{"logcat", "-c"}); File dir = new File(getFilesDir() + "/logss"); dir.mkdirs(); File tempLogFile = new File(dir, "tmpLog.txt"); tempLogFile.delete(); tempLogFile = new File(dir, "tmpLog.txt"); process = Runtime.getRuntime().exec("logcat -f " + tempLogFile.getAbsolutePath()); } catch (Exception e1) { e1.printStackTrace(); } return process; } //********************************************************************************************** public void createAlertDialog(String title, String message, boolean isPositive) { AlertDialog alertDialog = new AlertDialog.Builder(MainActivity.this).create(); alertDialog.setTitle(title); alertDialog.setMessage(Html.fromHtml(message)); alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "OK", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); if(isPositive) { alertDialog.setButton(AlertDialog.BUTTON_POSITIVE, "OPEN", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { Intent intent = new Intent(Intent.ACTION_VIEW); Uri internal = Uri.parse("content://org.linaro.iasenov.benchmarkframework/" + autoTestFile.getAbsolutePath()); intent.setDataAndType(internal, "text/plain"); startActivity(intent); dialog.dismiss(); } }); } alertDialog.show(); } //Delete all files from dir //********************************************************************************************** public static void clearDirFiles(File dir) throws IOException { if (dir.isDirectory()) { for (File c : dir.listFiles()) { c.delete(); Log.i(TAG,"Delete:"+c.getAbsolutePath()); } }else{ Log.i(TAG, "clearDataFiles: " + dir.getAbsolutePath() + " not exist or not a directory"); } } //********************************************************************************************** //Show dialog with confirm issue when settings for clear data are clicked //********************************************************************************************** public static void clearDataDialog(Activity mActivity) { AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder( mActivity); final File dir_save_data = new File(SAVE_DATA_PATH); // set dialog message alertDialogBuilder .setCancelable(false) .setPositiveButton("OK", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { //Delete all data in SAVE_DATA_PATH if (dir_save_data.exists()) { try { clearDirFiles(dir_save_data); } catch (IOException e) { e.printStackTrace(); } } } }) .setNegativeButton("Cancel", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }); //mActivity.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(dir_save_data))); // create alert dialog AlertDialog alertDialog = alertDialogBuilder.create(); alertDialog.setTitle(Html.fromHtml("Clear data")); alertDialog.setMessage("Once deleted data will not be restored!\n\nAre you sure?"); // show it alertDialog.show(); } //********************************************************************************************** //Update used file format chosen from Settings //********************************************************************************************** public static void updateFileFormat(String newValue){ fileFormatFromSettings = newValue; SharedPreferences prefs = mActivity.getPreferences(MODE_PRIVATE); final SharedPreferences.Editor editor = mActivity.getPreferences(MODE_PRIVATE).edit(); editor.putString(KEY_FILE_FORMAT, newValue); editor.apply(); } //********************************************************************************************** //Show dialog with test repeat number when settings are clicked //********************************************************************************************** public static void repeatNumberDialog(Activity ac) { // get prompts.xml view LayoutInflater li = LayoutInflater.from(ac); View promptsView = li.inflate(R.layout.prompts, null); AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder( ac); // set prompts.xml to alertdialog builder alertDialogBuilder.setView(promptsView); //Important: use shared preferences of main activity (not ac) to get repeat number properly!!! SharedPreferences prefs = mActivity.getPreferences(MODE_PRIVATE); final SharedPreferences.Editor editor = mActivity.getPreferences(MODE_PRIVATE).edit(); mRepeatNumber = prefs.getString(KEY_REPEAT_NUMBER,"1"); final NumberPicker np = (NumberPicker) promptsView.findViewById(R.id.numberPicker1); np.setMinValue(1); np.setMaxValue(99); np.setWrapSelectorWheel(false); np.setValue(Integer.parseInt(mRepeatNumber)); // set dialog message alertDialogBuilder .setCancelable(false) .setPositiveButton("OK", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { // get user input and set it to result // edit text //result.setText(userInput.getText()); if (!mRepeatNumber.equals(np.getValue())) {//if user input not the same as from preferences mRepeatNumber = Integer.toString(np.getValue()); editor.putString(KEY_REPEAT_NUMBER, Integer.toString(np.getValue())); editor.apply(); mToolbarRepeatIndicator.setText(" "+mRepeatNumber+" ");//change text in toolbar textview } } }) .setNegativeButton("Cancel", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }); // create alert dialog AlertDialog alertDialog = alertDialogBuilder.create(); // show it alertDialog.show(); //Window window = alertDialog.getWindow(); //window.setLayout(500, 500); } //********************************************************************************************** //Check adb shell params //********************************************************************************************** public boolean isShellParamsCorrect(String... params) { //Check tests are correct boolean isShellTestFind = false; String testsFromShell[] = params[0].split(":"); String repeatShellTests = params[1]; //******************Check is tests ok******************* for (String selected : testsFromShell) { for (String className : classNameTestItems) { if (className.equals(selected)) { //Found it! isShellTestFind = true; } } if(isShellTestFind){ //if test is found isShellTestFind = false; }else { //Set test as finished and put some info about the error writeToSocketFile("isFinished", "1"); writeToSocketFile("info", "Error: [persist.sys.tests] is not set or is set in a wrong way. Please check the script and fix it!"); return false; } } //******************Check is repeat number ok******************* if(repeatShellTests.length() == 0) { //Set test as finished and put some info about the error writeToSocketFile("isFinished", "1"); writeToSocketFile("info", "Error: [persist.sys.repeat] is not set..."); return false; }else if(repeatShellTests.length() > 0) { // Is a number if(!isNumeric(repeatShellTests)) { writeToSocketFile("isFinished", "1"); writeToSocketFile("info", "Error: [persist.sys.repeat] is not numeric string..."); return false; } if(repeatShellTests.equals("0")) { writeToSocketFile("isFinished", "1"); writeToSocketFile("info", "Error: [persist.sys.repeat] is less than 1"); return false; } } return true; } //********************************************************************************************** //Run tests in shell control //********************************************************************************************** public boolean isShellControl() { //Log.i(TAG, "isShellControl"); boolean res = false; String control = Util.getProperty("persist.sys.control"); String testsToBeRun = Util.getProperty("persist.sys.tests"); String repeatShellTests = Util.getProperty("persist.sys.repeat"); res = control.equals("shell"); if (res) { //clear isFinished.txt writeToSocketFile("isFinished", "0"); writeToSocketFile("info", ""); //Let's check the shell parameters if(!isShellParamsCorrect(testsToBeRun, repeatShellTests)){ return false; } String testsFromShell[] = testsToBeRun.split(":"); //if property is not set by the adb shell set it to 1 if(repeatShellTests.length() == 0) { repeatShellTests = "1"; } Log.i(TAG, "control:" + control); Log.i(TAG, "testToBeRun:" + testsToBeRun); Log.i(TAG, "repeatShellTests:" + repeatShellTests); int mActivePosition = 0; //Do not need to remove checks in shell mode so commented!!! /* for (String className : classNameTestItems) { mGridViewAdapter.removeCheckAtPosition(mActivePosition, mListViewGrid); mActivePosition++; } */ mActivePosition = 0; mGridViewAdapter.notifyDataSetChanged(); for (String className : classNameTestItems) { for (String selected : testsFromShell) { if (className.equals(selected)) { //Click on the current test testselection[mActivePosition] = true; //mGridViewAdapter.performItemClick(mActivePosition, mListViewGrid); } } mActivePosition++; } isAuto = false; isSelected = true; IS_SHELL_CONTROL = true; runTests(Integer.parseInt(repeatShellTests)); } return res; } //********************************************************************************************** //Check if string contains only digits //********************************************************************************************** public static boolean isNumeric(String str) { for (char c : str.toCharArray()) { if (!Character.isDigit(c)) return false; } return true; } //********************************************************************************************** //Create and write to file used by adb shell //********************************************************************************************** public Boolean writeToSocketFile(String fname, String fcontent) { try { File dir = new File(getFilesDir() + "/socket"); dir.mkdirs(); String fpath = getFilesDir() + "/socket/" + fname + ".txt"; File file = new File(fpath); // If file does not exists, then create it if (!file.exists()) { file.createNewFile(); } FileWriter fw = new FileWriter(file.getAbsoluteFile()); BufferedWriter bw = new BufferedWriter(fw); bw.write(fcontent); bw.close(); Log.i("TAG", "Sucess"); return true; } catch (IOException e) { e.printStackTrace(); return false; } } //********************************************************************************************** //Get device information with html tags //********************************************************************************************** public static String getInfosAboutDeviceHTML(Activity a) { String s = ""; try { PackageInfo pInfo = a.getPackageManager().getPackageInfo( a.getPackageName(), PackageManager.GET_META_DATA); s += "APP Package Name: " + a.getPackageName()+""; s += "

APP Version Name: " + pInfo.versionName+""; s += "

APP Version Code: " + pInfo.versionCode+""; } catch (PackageManager.NameNotFoundException e) { } s += "

OS Version: " + System.getProperty("os.version") + " (" + android.os.Build.VERSION.INCREMENTAL + ")"+""; s += "

OS API Level: " + android.os.Build.VERSION.SDK+""; s += "

Device: " + android.os.Build.DEVICE+""; s += "

Model (and Product): " + android.os.Build.MODEL + " (" + android.os.Build.PRODUCT + ")"+""; // TODO add application version! // more from // http://developer.android.com/reference/android/os/Build.html : s += "

Manufacturer: " + android.os.Build.MANUFACTURER+""; s += "

Other TAGS: " + android.os.Build.TAGS+""; s += "

screenWidth: " + a.getWindow().getWindowManager().getDefaultDisplay() .getWidth()+""; s += "

screenHeigth: " + a.getWindow().getWindowManager().getDefaultDisplay() .getHeight()+""; s += "

Keyboard available: " + (a.getResources().getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS)+""; s += "

Trackball available: " + (a.getResources().getConfiguration().navigation == Configuration.NAVIGATION_TRACKBALL)+""; s += "

SD Card state: " + Environment.getExternalStorageState()+""; Properties p = System.getProperties(); Enumeration keys = p.keys(); String key = ""; while (keys.hasMoreElements()) { key = (String) keys.nextElement(); s += "

- " + key + " = " + (String) p.get(key)+""; } return s; } //********************************************************************************************** //class TaskCanceler used for cancelling started tasks //********************************************************************************************** public class TaskCanceler implements Runnable{ private List tasks; public TaskCanceler(){ tasks = new ArrayList(); } private void addAsyncTask(AsyncTask task){ tasks.add(task); } @Override public void run() { for(AsyncTask at : tasks) { if (at.getStatus() == AsyncTask.Status.RUNNING || at.getStatus() == AsyncTask.Status.PENDING) at.cancel(true); } } } //********************************************************************************************** //Async task for background test processing //********************************************************************************************** public class AsyncTaskRunner extends AsyncTask { private String resp; //ProgressDialog progressDialog; String selectedTest; String selectedClassTest; int stepN; int repeatN; public AsyncTaskRunner(String test, String classTest, int step, int repeat) { super(); selectedTest = test; selectedClassTest = classTest; stepN = step; repeatN = repeat; } //********************************************************************************************** @Override protected String doInBackground(String... params) { //Log.i(TAG,"isCanceled " + isCanceled); //if tests are canceled just return if(isCanceled) return ""; //In BaseBenchmark clear() method will try "STEP_FROM" replacement again to be sure it will be done on one of both replace places mStep = Integer.toString(stepN); mFrom = Integer.toString(repeatN); mSelectedTxt = selectedTest; publishProgress(selectedTest, selectedClassTest, Integer.toString(stepN), Integer.toString(repeatN)); try { testDone = 0; Class thisClass = Class.forName(PACKAGE_NAME + "." + selectedClassTest); Object iClass = thisClass.newInstance(); Method thisMethod = thisClass.getMethod("startBenchmark", Integer.TYPE); mTestResult = (String) (thisMethod.invoke(iClass, 1)); mAllTestsResult = mAllTestsResult + "\n\n" + mTestResult; //Save test result saveAutoTestResultToFile(); testDone = 1; //progressDialog.dismiss(); } catch (Exception e) { e.printStackTrace(); resp = e.getMessage(); //Get what we can from the output if(fileFormatFromSettings.equals("html")) { HtmlUtil.addTemplateExecute(); HtmlUtil.replaceHtmlTag("EXECUTE", ""); HtmlUtil.addTemplateParagraph(); HtmlUtil.replaceHtmlTag("BODY", Interceptor.outputTxt); Interceptor.clear(); HtmlUtil.addTemplateEnd(); } mTestResult = Interceptor.outputTxt; mAllTestsResult = mAllTestsResult + "\n\n" + mTestResult; //Let's call GC System.gc(); } return selectedClassTest; } //********************************************************************************************** @Override protected void onPostExecute(String result) { //Decrement numberOfCheckedTests(need that because test is auto checked previously) if(isAuto){ //numberOfCheckedTests--; } progressDialog.dismiss(); //displayResult(mTestResult); //UI display Log.i(TAG, mTestResult); //adb logcat display String endTest = ""; if (isAuto) { endTest = classNameTestItems[allTestsCount - 1]; } else { endTest = selectedClassTests.get(allTestsCount - 1).toString(); } //decrease the counter if endTest if (result.equals(endTest)) { endTestCounter--; } if (result.equals(endTest) && endTestCounter == 0 && !isCanceled) { //if last one is finished and counter is 0 and is not Canceled //Get total time at the end double totalTime = (double) (elapsedTotalTime) / 1000; //Inform shell that tests are done writeToSocketFile("isFinished", "1"); //Set some info to shell about test status...where results are saved if(autoTestFile!=null) { writeToSocketFile("info", "Save result to: " + autoTestFile.getAbsolutePath()); } displayResult(mAllTestsResult);//UI display if(fileFormatFromSettings.equals("html")){ HtmlUtil.addTemplateSummary(); HtmlUtil.replaceHtmlTag("TOTAL_TIME", String.format("%5.4f", totalTime) + " seconds"); if(!IS_SHELL_CONTROL) { HtmlUtil.replaceHtmlTag("REPEAT", mRepeatNumber + " time(s)"); }else{ HtmlUtil.replaceHtmlTag("REPEAT", mFrom + " time(s)"); } HtmlUtil.replaceHtmlTag("TESTS", runningTests.substring(1)); saveAutoTestResultToFile(); } String filepath = "" + autoTestFile.getAbsolutePath() + ""; createAlertDialog("File with results created", filepath, true); } } //********************************************************************************************** @Override protected void onPreExecute() { //Decrement numberOfCheckedTests(need that because test is auto checked previously) if(isAuto){ //numberOfCheckedTests = 0; } Log.i(TAG, "selectedTest:" + selectedTest); mDisplayDetails.setText(selectedTest + " is running please wait..."); } //********************************************************************************************** @Override protected void onCancelled(String result) { // Runs on UI thread after cancel() is invoked // and doInBackground() has finished/returned //Log.i(TAG,"Cancel"); //delete file with resutls if(autoTestFile !=null) { autoTestFile.delete(); Log.i(TAG, "onCancelled: File: " + autoTestFile.getAbsolutePath() + " was deleted"); autoTestFile = null; } //HTML BEGIN //Clear html string if(fileFormatFromSettings.equals("html")) { HtmlUtil.clear(); } //HTML END testDone = 0; // dismiss the progress dialog progressDialog.dismiss(); } //********************************************************************************************** @Override protected void onProgressUpdate(String... text) { mDisplayDetails.setText(text[0] + " is running please wait..."); final String txt = text[0]; String extraText = ""; if (text[1].equals(("Test4"))) //set some extra text for this test to inform user for longer wait. { extraText = "\n\nNote: This test can take more than 30 min. so be patient..."; } progressDialog = new ProgressDialog(MainActivity.this); progressDialog.setTitle("Step " + text[2] + " From " + text[3]); progressDialog.setMessage(text[0] + " is running please wait..." + extraText); progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); progressDialog.setCanceledOnTouchOutside(false); //Set test step in html file //if(fileFormatFromSettings.equals("html")){ // HtmlUtil.replaceHtmlTag("STEP_FROM", "Step " + text[2] + "("+text[3]+")"); //} // Put a cancel button in progress dialog //TODO: Set Cancel button for cancelling the test progressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "Cancel", new DialogInterface.OnClickListener() { // Set a click listener for progress dialog cancel button @Override public void onClick(DialogInterface dialog, int which) { //call stop benchmark method try { Class thisClass = Class.forName(PACKAGE_NAME + "." + selectedClassTest); Object iClass = thisClass.newInstance(); Method thisMethod = thisClass.getMethod("stopBenchmark"); thisMethod.invoke(iClass); } catch (Exception e) { e.printStackTrace(); } //Cancel all async tasks waiting in the queue //handler.postDelayed(taskCanceler,0); taskCanceler.run(); mDisplayDetails.setText(txt + " is canceled...\n\nWarning: File with results is deleted!!!"); // Tell the system about cancellation isCanceled = true; // dismiss the progress dialog //progressDialog.dismiss(); } }); String testNumber = selectedClassTest.replace("Test", ""); if(!(Integer.parseInt(testNumber) >=16 && Integer.parseInt(testNumber) <=25)) { //Dont show progress dialog for test with own PD progressDialog.show(); } if (isAuto) { int mActivePosition = 0; //Do remove all checks here for (String className : classNameTestItems) { //mGridViewAdapter.removeCheckAtPosition(mActivePosition, mListViewGrid); if(testselection[mActivePosition] == true){ testselection[mActivePosition] = false; numberOfCheckedTests--; } mActivePosition++; } mActivePosition = 0; mGridViewAdapter.notifyDataSetChanged(); //Do auto click here for (String className : classNameTestItems) { if (className.equals(text[1])) { //Click on the current test testselection[mActivePosition] = true; numberOfCheckedTests++; //mGridViewAdapter.performItemClick(mActivePosition,mListViewGrid); } mActivePosition++; } } } //********************************************************************************************** }//AsyncTaskRunner //********************************************************************************************** //********************************************************************************************** //Custom Adapter for GridView //********************************************************************************************** public class MyAdapter extends BaseAdapter { private LayoutInflater mInflater; String testsList[]; public MyAdapter(String testsList[]) { mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); this.testsList = testsList; } public int getCount() { return count; } public Object getItem(int position) { return position; } public long getItemId(int position) { return position; } public String getTextByPosition(int pos) { return testsList[pos]; } public View getView(int position, View convertView, ViewGroup parent) { //Log.i(TAG,"getView_position:" +position); ViewHolder holder; if (convertView == null) { //Log.i(TAG,"getView_position_null:" +position); holder = new ViewHolder(); convertView = mInflater.inflate( R.layout.listview, null); holder.textview = (TextView) convertView.findViewById(R.id.itemText); holder.checkbox = (CheckBox) convertView.findViewById(R.id.itemCheckBox); convertView.setTag(holder); } else { //Log.i(TAG,"getView_position_not_null:" +position); holder = (ViewHolder) convertView.getTag(); } holder.checkbox.setId(position); holder.textview.setId(position); holder.textview.setText(testsList[position]); holder.textview.setTextSize(getPixels(pixMin)); holder.checkbox.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { // TODO Auto-generated method stub CheckBox cb = (CheckBox) v; int id = cb.getId(); if (testselection[id]) { cb.setChecked(false); testselection[id] = false; numberOfCheckedTests--; //Log.i(TAG, "uncheck"); } else { cb.setChecked(true); testselection[id] = true; numberOfCheckedTests++; //Log.i(TAG, "check"); } } }); holder.checkbox.setChecked(testselection[position]); holder.id = position; return convertView; } public void removeCheckAtPosition(int i, GridView gr) { //It is needed to check the max index used in getView method(because max index can be smaller than count of gridview elements) //So catch is used to prevent from crash when i is greater than max index used in getView try { //Log.i(TAG, "position:" + i); ViewGroup gridChild = (ViewGroup) gr.getChildAt(i); int childSize = gridChild.getChildCount(); for (int k = 0; k < childSize; k++) { if (gridChild.getChildAt(k) instanceof CheckBox) { CheckBox cb = (CheckBox) gridChild.getChildAt(k); //Log.i(TAG,""+i); if (testselection[i]) { cb.setChecked(false); testselection[i] = false; numberOfCheckedTests--; //Log.i(TAG, "uncheck"); } } } }catch(Exception e){ Log.i(TAG, "(Expected error):removeCheckAtPosition:" + e.toString()); } } public void performItemClick(int position, GridView gr){ ViewGroup gridChild = (ViewGroup) gr.getChildAt(position); int childSize = gridChild.getChildCount(); for(int k = 0; k < childSize; k++) { if(gridChild.getChildAt(k) instanceof CheckBox ) { CheckBox cb = (CheckBox)gridChild.getChildAt(k); cb.setChecked(true); testselection[position] = true; numberOfCheckedTests++; } } } //********************************************************************************************** }//MyAdapter //********************************************************************************************** class ViewHolder { TextView textview; CheckBox checkbox; int id; //********************************************************************************************** }//ViewHolder //********************************************************************************************** //Use object of this class for synchronization public static class Lock { private boolean condition; public boolean conditionMet() { return condition; } public void setCondition(boolean condition) { this.condition = condition; } } //********************************************************************************************** }//MainActivity //**********************************************************************************************