package com.ericsson.uecontrol.gui; import android.app.ActionBar; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.preference.PreferenceManager; import android.support.v4.app.FragmentActivity; import android.view.Menu; import android.view.MenuItem; import android.view.WindowManager; import android.widget.Toast; import com.ericsson.uecontrol.R; import com.ericsson.uecontrol.core.UeControlExecutor; import com.ericsson.uecontrol.core.UeControlExecutor.ExecutionListener; import com.ericsson.uecontrol.core.behaviour.UeBehaviourSleep; import com.ericsson.uecontrol.core.behaviour.UeBehaviourSurfing; import com.ericsson.uecontrol.core.util.ThroughputCalculator; import com.ericsson.uecontrol.gui.fragments.BehaviourListFragment; import com.ericsson.uecontrol.gui.fragments.ExecNotification; import com.ericsson.uecontrol.gui.fragments.FileBrowserDialog; import com.ericsson.uecontrol.gui.fragments.FileBrowserDialog.OnFileSelectionListener; import com.ericsson.uecontrol.gui.fragments.StatusFragment; import org.apache.log4j.Level; import org.apache.log4j.Logger; import java.io.File; import de.mindpipe.android.logging.log4j.LogConfigurator; public class MainActivity extends FragmentActivity implements OnSharedPreferenceChangeListener, OnFileSelectionListener, ExecutionListener { private static final Logger log = Logger.getLogger(MainActivity.class); public static final String DEFAULT_LOG_PATH = "/sdcard/uecontrol/"; public static final String BEHAVIOUR_SAVE_FILE = "behaviour_list.json"; /* Fragments */ private StatusFragment statusFragment; private BehaviourListFragment behaviourListFragment; private MenuItem action_execute; private MenuItem action_mark; private boolean backButtonPressed = false; /* Static Data */ private static UeControlExecutor executor; private static int uid; private static Activity context; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Set static fields and preferences SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); PreferenceManager.setDefaultValues(this, R.xml.preferences, false); prefs.registerOnSharedPreferenceChangeListener(this); uid = getApplicationInfo().uid; context = this; // Setup Debugging setupDebugLogging(); // Setup Executor if(executor == null) { log.info("Creating new instance of executor"); executor = new UeControlExecutor(); executor.setDeviceBasedThroughput(Boolean.parseBoolean(prefs.getString("throughput_type", "false"))); executor.setThroughputFrequency(Float.parseFloat(prefs.getString("throughput_average_freq", "" + ThroughputCalculator.UPDATES_PER_SEC))); File input = new File(this.getFilesDir(), BEHAVIOUR_SAVE_FILE); if (input.exists()) { try { log.debug("Reading saved state"); executor.read(input.getAbsolutePath()); } catch (Exception e) { Toast.makeText(this, "Unable to load saved state", Toast.LENGTH_SHORT).show(); log.error(null, e); } } else { log.debug("No saved state found, creating default behaviours"); executor.addBehaviour(new UeBehaviourSleep()); executor.addBehaviour(new UeBehaviourSurfing()); executor.addBehaviour(new UeBehaviourSleep(4000)); } } else { log.info("Using existing executor"); } // Setup Main GUI setContentView(R.layout.activity_main); statusFragment = (StatusFragment) getFragmentManager().findFragmentById(R.id.status_fragment); behaviourListFragment = (BehaviourListFragment) getFragmentManager().findFragmentById(R.id.behaviour_list_fragment); executor.setThroughputListener(statusFragment.getThroughputListener()); executor.setExecutionListener(this); updateExecutionState(); } public void setupDebugLogging(){ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); String path = prefs.getString("logging_path", DEFAULT_LOG_PATH); if(!path.endsWith("/")) path += File.separator; LogConfigurator logConfigurator = new LogConfigurator(); logConfigurator.setFileName(path + "uecontrol.log"); if(prefs.getBoolean("debug", false)) logConfigurator.setRootLevel(Level.DEBUG); else logConfigurator.setRootLevel(Level.WARN); // Set log level of a specific logger logConfigurator.setLevel("org.apache", Level.ERROR); logConfigurator.configure(); } public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { log.debug("Preference changed: "+key); if(key.equals("debug")) { if (sharedPreferences.getBoolean("debug", false)) { Logger.getRootLogger().setLevel(Level.DEBUG); log.info("Enabling debug logging."); } else { log.info("Disabling debug logging."); Logger.getRootLogger().setLevel(Level.WARN); } } else if(key.equals("throughput_type")){ log.info("Device Throughput set to: "+sharedPreferences.getString("throughput_type", "false")); if(executor != null) executor.setDeviceBasedThroughput(Boolean.parseBoolean(sharedPreferences.getString("throughput_type", "false"))); } else if(key.equals("throughput_average_freq")){ float frequency = Float.parseFloat(sharedPreferences.getString("throughput_average_freq", ""+ThroughputCalculator.UPDATES_PER_SEC)); log.info("Device Throughput Frequency set to: "+frequency); if(executor != null) executor.setThroughputFrequency(frequency); if(statusFragment != null) { statusFragment.reset(); statusFragment.updateGraphLength(); } } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Only show items in the action bar relevant to this screen // if the drawer is not showing. Otherwise, let the drawer // decide what to show in the action bar. getMenuInflater().inflate(R.menu.main, menu); ActionBar actionBar = getActionBar(); actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); actionBar.setDisplayShowTitleEnabled(true); action_execute = (MenuItem) menu.findItem(R.id.action_execute); action_mark = (MenuItem) menu.findItem(R.id.action_mark); updateExecutionState(); 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(); if (id == R.id.action_execute) { if(executor.isRunning()) { executor.terminate(); } else { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); if(prefs.getBoolean("logging", false)) executor.setLogPath(prefs.getString("logging_path", Environment.getExternalStorageDirectory().getAbsolutePath()+"/uecontrol/")); else executor.setLogPath(null); executor.execute(); } updateExecutionState(); return true; } else if (id == R.id.action_mark) { if (executor.getCsvLogger() != null) { executor.getCsvLogger().addComment("--- Mark ---"); Toast.makeText(this, "Mark added to log", Toast.LENGTH_SHORT).show(); } } else if (id == R.id.action_reset) { if(executor != null) { executor.terminate(); executor.reset(); } if(statusFragment != null) statusFragment.reset(); if(behaviourListFragment != null) behaviourListFragment.onResume(); updateExecutionState(); } else if (id == R.id.action_edit) { if(!executor.isRunning()) { Intent intent = new Intent(this, EditActivity.class); startActivity(intent); } else Toast.makeText(this, "Stop execution to edit behaviours", Toast.LENGTH_SHORT).show(); return true; } else if (id == R.id.action_import) { FileBrowserDialog browser = FileBrowserDialog.newInstance( "/sdcard", FileBrowserDialog.BrowserMode.SELECT_FILE); browser.show(this.getFragmentManager(), "import"); } else if (id == R.id.action_export) { FileBrowserDialog browser = FileBrowserDialog.newInstance( "/sdcard", FileBrowserDialog.BrowserMode.NEW_FILE); browser.show(this.getFragmentManager(), "export"); } else if (id == R.id.action_settings) { startActivity(new Intent(this, SettingsActivity.class)); return true; } return super.onOptionsItemSelected(item); } public void onFileSelection(String tag, File file){ try { if(tag.equals("import")) { executor.read(file.getAbsolutePath()); if(behaviourListFragment != null) behaviourListFragment.onResume(); } else if(tag.equals("export")) { executor.save(file.getAbsolutePath()); } } catch (Exception e) { String msg = "Unable to import from file"; if(tag.equals("export")) msg = "Unable to export to file"; log.error(msg+": "+file.getAbsolutePath(), e); Toast.makeText(this, msg, Toast.LENGTH_SHORT).show(); } } private void updateExecutionState(){ if(action_execute != null) { if (executor.isRunning()) executionStarted(); else executionStopped(); } } public void executionStarted(){ if(action_execute == null) return; this.runOnUiThread(new Runnable() { @Override public void run() { action_execute.setTitle(R.string.action_stop); ExecNotification.create(); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(MainActivity.this); if(action_mark != null && prefs.getBoolean("logging", false)) action_mark.setEnabled(true); if(prefs.getBoolean("screen_on", false)) getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); } }); } public void executionStopped(){ if(action_execute == null) return; this.runOnUiThread(new Runnable() { @Override public void run() { action_execute.setTitle(R.string.action_run); ExecNotification.dismiss(); action_mark.setEnabled(false); getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); } }); } @Override public void onBackPressed() { if (backButtonPressed) { // Close the App super.onBackPressed(); return; } this.backButtonPressed = true; Toast.makeText(this, "Press BACK again to Exit", Toast.LENGTH_SHORT).show(); new Handler().postDelayed(new Runnable() { @Override public void run() { backButtonPressed = false; } }, 2000); } @Override protected void onDestroy() { if(executor != null && isFinishing()){ executor.terminateNonBlock(); executor.reset(); executor = null; } super.onDestroy(); } public static UeControlExecutor getExecutor() { return executor; } public static int getUID(){ return uid; } public static Activity getContext(){return context;} }