diff --git a/_gitignore.txt b/_gitignore.txt new file mode 100644 index 0000000..2b75303 --- /dev/null +++ b/_gitignore.txt @@ -0,0 +1,13 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild diff --git a/app/_gitignore.txt b/app/_gitignore.txt new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/app/_gitignore.txt @@ -0,0 +1 @@ +/build diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..8839a6c --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,31 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 28 + defaultConfig { + applicationId "com.guilhermed.offloadingfibonaccibench" + minSdkVersion 19 + targetSdkVersion 28 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation 'com.android.support:appcompat-v7:28.0.0' + implementation 'com.android.support.constraint:constraint-layout:1.1.3' + implementation 'com.mcxiaoke.volley:library:1.0.19' + implementation 'com.cloudbees:endpoints:0.8' + implementation 'eu.hgross:blaubot-android:2+' + testImplementation 'junit:junit:4.12' + androidTestImplementation 'com.android.support.test:runner:1.0.2' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' +} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/app/src/androidTest/java/com/guilhermed/offloadingfibonaccibench/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/guilhermed/offloadingfibonaccibench/ExampleInstrumentedTest.java new file mode 100644 index 0000000..4f7855a --- /dev/null +++ b/app/src/androidTest/java/com/guilhermed/offloadingfibonaccibench/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.guilhermed.offloadingfibonaccibench; + +import android.content.Context; +import android.support.test.InstrumentationRegistry; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getTargetContext(); + + assertEquals("com.guilhermed.offloadingfibonacci", appContext.getPackageName()); + } +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..af1d372 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/AMOk/Actuator.java b/app/src/main/java/AMOk/Actuator.java new file mode 100644 index 0000000..083b28f --- /dev/null +++ b/app/src/main/java/AMOk/Actuator.java @@ -0,0 +1,17 @@ +package AMOk; + +import Offload.Dataset; + +public class Actuator { + private KnowledgeBase kBase; + private Dataset dataset; + + public Actuator() { + kBase = KnowledgeBase.getInstance(); + dataset = Dataset.getInstance(); + } + + public void act(){ + dataset.setShouldOffload(kBase.getShouldOffload()); + } +} \ No newline at end of file diff --git a/app/src/main/java/AMOk/Analyser.java b/app/src/main/java/AMOk/Analyser.java new file mode 100644 index 0000000..e3d9c63 --- /dev/null +++ b/app/src/main/java/AMOk/Analyser.java @@ -0,0 +1,39 @@ +package AMOk; + +import android.util.Log; + +import Offload.Dataset; + +public class Analyser { + + public void analyse(){ + KnowledgeBase kBase = KnowledgeBase.getInstance(); + + final String toastText = "fileSizeValue[0,1]: "+ Math.min((double)KnowledgeBase.getInstance().getFileSize()/(double)30,(double)1) + + "\nMemoValue[0,1]: "+ (double)KnowledgeBase.getInstance().getHeapUsed()/(double)KnowledgeBase.getInstance().getHeapSize() + + "\nBattery[0,1]:" + (double)KnowledgeBase.getInstance().getBatteryPct(); + Log.d("Analyser data:",toastText); + + /** Specialist defined parameters due to application requests*/ + double batteryWeight = 0.5; + double memoWeight = 0.3; + double sizeWeight = 0.2; + + + double memo = memoWeight*((double)kBase.getHeapUsed()/(double)kBase.getHeapSize()); + + /** Using 30KB as size reference*/ + double size = sizeWeight* Math.min((double)kBase.getFileSize()/(double)30,(double)1); + + double battery; + + if(kBase.isCharging()) + battery = batteryWeight; + else + battery = batteryWeight*(double)kBase.getBatteryPct(); + + double coef = size + battery + memo; + + kBase.setCoefficient(coef); + } +} \ No newline at end of file diff --git a/app/src/main/java/AMOk/Executor.java b/app/src/main/java/AMOk/Executor.java new file mode 100644 index 0000000..f867e17 --- /dev/null +++ b/app/src/main/java/AMOk/Executor.java @@ -0,0 +1,9 @@ +package AMOk; + +public class Executor { + + public void execute(){ + Actuator mActuator = new Actuator(); + mActuator.act(); + } +} \ No newline at end of file diff --git a/app/src/main/java/AMOk/FrameworkMain.java b/app/src/main/java/AMOk/FrameworkMain.java new file mode 100644 index 0000000..bcb87aa --- /dev/null +++ b/app/src/main/java/AMOk/FrameworkMain.java @@ -0,0 +1,22 @@ +package AMOk; + +public class FrameworkMain { + private Monitor mMonitor; + private Analyser mAnalyser; + private Planner mPlanner; + private Executor mExecutor; + + public FrameworkMain(){ + mMonitor = new Monitor(); + mAnalyser = new Analyser(); + mPlanner = new Planner(); + mExecutor = new Executor(); + } + + public void run(){ + mMonitor.monitor(); + mAnalyser.analyse(); + mPlanner.plan(); + mExecutor.execute(); + } +} \ No newline at end of file diff --git a/app/src/main/java/AMOk/KnowledgeBase.java b/app/src/main/java/AMOk/KnowledgeBase.java new file mode 100644 index 0000000..ebe0640 --- /dev/null +++ b/app/src/main/java/AMOk/KnowledgeBase.java @@ -0,0 +1,183 @@ +package AMOk; + +import Offload.Dataset; + +public class KnowledgeBase { + + private static KnowledgeBase instance = null; + protected KnowledgeBase (){} + public static KnowledgeBase getInstance(){ + if(instance == null){ + instance = new KnowledgeBase(); + } + return instance; + } + + private boolean isCharging = false; + private String charginMethod = ""; + private float batteryPct = 0; + + private boolean isConnected = false; + private String connectionType = ""; + + private long heapSize, heapUsed, heapFree; + + private float cpuUser,cpuSystem,cpuIdle,cpuWait; + + private long localTime, remoteTime; + + private long fileSize; + + private double coefficient; + + private boolean shouldOffload; + + public long getLocalTime() { + return localTime; + } + + public void setLocalTime(long localTime) { + this.localTime = localTime; + } + + public long getRemoteTime() { + return remoteTime; + } + + public void setRemoteTime(long remoteTime) { + this.remoteTime = remoteTime; + + } + + public float getCpuUser() { + return cpuUser; + } + + public void setCpuUser(float cpuUser) { + this.cpuUser = cpuUser; + + } + + public float getCpuSystem() { + return cpuSystem; + } + + public void setCpuSystem(float cpuSystem) { + this.cpuSystem = cpuSystem; + + } + + public float getCpuIdle() { + return cpuIdle; + } + + public void setCpuIdle(float cpuIdle) { + this.cpuIdle = cpuIdle; + + } + + public float getCpuWait() { + return cpuWait; + } + + public void setCpuWait(float cpuWait) { + this.cpuWait = cpuWait; + + } + + public long getHeapSize() { + return heapSize; + } + + public void setHeapSize(long heapSize) { + this.heapSize = heapSize; + + } + + public long getHeapUsed() { + return heapUsed; + } + + public void setHeapUsed(long heapUsed) { + this.heapUsed = heapUsed; + + } + + public long getHeapFree() { + return heapFree; + } + + public void setHeapFree(long headFree) { + this.heapFree = headFree; + + } + + public boolean isConnected() { + return isConnected; + } + + public void setConnected(boolean connected) { + isConnected = connected; + + } + + public String getConnectionType() { + return connectionType; + } + + public void setConnectionType(String connectionType) { + this.connectionType = connectionType; + + } + + public boolean isCharging() { + return isCharging; + } + + public void setCharging(boolean charging) { + isCharging = charging; + + } + + public String getCharginMethod() { + return charginMethod; + } + + public void setCharginMethod(String charginMethod) { + this.charginMethod = charginMethod; + + } + + public float getBatteryPct() { + return batteryPct; + } + + public void setBatteryPct(float batteryPct) { + this.batteryPct = batteryPct; + + } + + public long getFileSize() { + return fileSize; + } + + public void setFileSize(long fileSize) { + this.fileSize= fileSize; + } + + public double getCoefficient() { + return coefficient; + } + + public void setCoefficient(double coefficient) { + this.coefficient= coefficient; + } + + public boolean getShouldOffload() { + return shouldOffload; + } + + public void setShouldOffload(boolean shouldOffload) { + this.shouldOffload = shouldOffload; + } +} \ No newline at end of file diff --git a/app/src/main/java/AMOk/Monitor.java b/app/src/main/java/AMOk/Monitor.java new file mode 100644 index 0000000..1b74e53 --- /dev/null +++ b/app/src/main/java/AMOk/Monitor.java @@ -0,0 +1,9 @@ +package AMOk; + +public class Monitor { + + public void monitor(){ + Sensor mSensor = new Sensor(); + mSensor.sense(); + } +} \ No newline at end of file diff --git a/app/src/main/java/AMOk/Planner.java b/app/src/main/java/AMOk/Planner.java new file mode 100644 index 0000000..9d685d1 --- /dev/null +++ b/app/src/main/java/AMOk/Planner.java @@ -0,0 +1,37 @@ +package AMOk; + +import android.util.Log; +import Offload.Dataset; + +/** + * Created by Vitor Bertozzi on 8/9/18. + * + */ +public class Planner { + public double threshold; + + public Planner() { + threshold = 0.5; + } + + public void plan(){ + KnowledgeBase kBase= KnowledgeBase.getInstance(); + Boolean isConnected = kBase.isConnected(); + + Double coefficient = kBase.getCoefficient(); + + Log.d("Planner data:","Coefficient: "+ String.valueOf(coefficient)); + + /** If not connected, auto-deny offloading*/ + if (!isConnected){ + kBase.setShouldOffload(false); + } + + if (coefficient>threshold) { + kBase.setShouldOffload(true); + } + else{ + kBase.setShouldOffload(false); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/AMOk/Sensor.java b/app/src/main/java/AMOk/Sensor.java new file mode 100644 index 0000000..0ca0f95 --- /dev/null +++ b/app/src/main/java/AMOk/Sensor.java @@ -0,0 +1,27 @@ +package AMOk; + +import Offload.Dataset; + +public class Sensor { + + private KnowledgeBase kBase; + private Dataset dataset; + + public Sensor() { + kBase = KnowledgeBase.getInstance(); + dataset = Dataset.getInstance(); + } + + public void sense(){ + kBase.setBatteryPct(dataset.getBatteryPct()); + kBase.setCharging(dataset.isCharging()); + + kBase.setConnected(dataset.isConnected()); + + kBase.setHeapFree(dataset.getHeapFree()); + kBase.setHeapUsed(dataset.getHeapUsed()); + kBase.setHeapSize(dataset.getHeapSize()); + + kBase.setFileSize(dataset.getFileSize()); + } +} \ No newline at end of file diff --git a/app/src/main/java/Offload/Dataset.java b/app/src/main/java/Offload/Dataset.java new file mode 100644 index 0000000..1912ce4 --- /dev/null +++ b/app/src/main/java/Offload/Dataset.java @@ -0,0 +1,209 @@ +package Offload; + +import java.util.Observable; + +/** + * Created by pedrocandido on 10/5/17. + */ + +public class Dataset extends Observable { + + private static Dataset instance = null; + protected Dataset(){} + public static Dataset getInstance(){ + if(instance == null){ + instance = new Dataset(); + } + return instance; + } + + private boolean isCharging = false; + private String charginMethod = ""; + private float batteryPct = 0; + + private boolean isConnected = false; + private String connectionType = ""; + + private long heapSize, heapUsed, heapFree; + + private float cpuUser,cpuSystem,cpuIdle,cpuWait; + + private long localTime, remoteTime; + + private long fileSize; + + private long batteryNanoWatt = 0; + + private boolean shouldOffload; + + + public long getLocalTime() { + return localTime; + } + + public void setLocalTime(long localTime) { + this.localTime = localTime; + setChanged(); + notifyObservers(); + } + + public long getRemoteTime() { + return remoteTime; + } + + public void setRemoteTime(long remoteTime) { + this.remoteTime = remoteTime; + setChanged(); + notifyObservers(); + } + + public float getCpuUser() { + return cpuUser; + } + + public void setCpuUser(float cpuUser) { + this.cpuUser = cpuUser; + setChanged(); + notifyObservers(); + } + + public float getCpuSystem() { + return cpuSystem; + } + + public void setCpuSystem(float cpuSystem) { + this.cpuSystem = cpuSystem; + setChanged(); + notifyObservers(); + } + + public float getCpuIdle() { + return cpuIdle; + } + + public void setCpuIdle(float cpuIdle) { + this.cpuIdle = cpuIdle; + setChanged(); + notifyObservers(); + } + + public float getCpuWait() { + return cpuWait; + } + + public void setCpuWait(float cpuWait) { + this.cpuWait = cpuWait; + setChanged(); + notifyObservers(); + } + + public long getHeapSize() { + return heapSize; + } + + public void setHeapSize(long heapSize) { + this.heapSize = heapSize; + setChanged(); + notifyObservers(); + } + + public long getHeapUsed() { + return heapUsed; + } + + public void setHeapUsed(long heapUsed) { + this.heapUsed = heapUsed; + setChanged(); + notifyObservers(); + } + + public long getHeapFree() { + return heapFree; + } + + public void setHeapFree(long headFree) { + this.heapFree = headFree; + setChanged(); + notifyObservers(); + } + + public boolean isConnected() { + return isConnected; + } + + public void setConnected(boolean connected) { + isConnected = connected; + setChanged(); + notifyObservers(); + } + + public String getConnectionType() { + return connectionType; + } + + public void setConnectionType(String connectionType) { + this.connectionType = connectionType; + setChanged(); + notifyObservers(); + } + + public boolean isCharging() { + return isCharging; + } + + public void setCharging(boolean charging) { + isCharging = charging; + setChanged(); + notifyObservers(); + } + + public String getCharginMethod() { + return charginMethod; + } + + public void setCharginMethod(String charginMethod) { + this.charginMethod = charginMethod; + setChanged(); + notifyObservers(); + } + + public float getBatteryPct() { + return batteryPct; + } + + public void setBatteryPct(float batteryPct) { + this.batteryPct = batteryPct; + setChanged(); + notifyObservers(); + } + + public long getBatteryNanoWatt() { + return batteryNanoWatt; + } + + public void setBatteryNanoWatt(long batteryNanoWatt) { + this.batteryNanoWatt = batteryNanoWatt; + setChanged(); + notifyObservers(); + } + + public long getFileSize() { + return fileSize; + } + + public void setFileSize(long fileSize) { + this.fileSize= fileSize; + setChanged(); + notifyObservers(); + } + + public boolean getShouldOffload() { + return shouldOffload; + } + + public void setShouldOffload(boolean shouldOffload) { + this.shouldOffload= shouldOffload; + setChanged(); + notifyObservers(); + } +} \ No newline at end of file diff --git a/app/src/main/java/Offload/Monitor.java b/app/src/main/java/Offload/Monitor.java new file mode 100644 index 0000000..90a3020 --- /dev/null +++ b/app/src/main/java/Offload/Monitor.java @@ -0,0 +1,128 @@ +package Offload; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.os.BatteryManager; + +import java.io.IOException; +import java.io.RandomAccessFile; + +public class Monitor extends BroadcastReceiver { + + @Override + public void onReceive(Context context, Intent intent) { + + monitorBatery(context,intent); + monitorInternet(context); + monitorCPU(); + monitorMemory(); + + } + + /** + * + * @param context + * @param intent + * + * Get bettery information from the system intent. + * Monitor when battery status change and when batery level change + */ + public void monitorBatery(Context context, Intent intent){ + if(intent!=null) { + int batteryStatus = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1); + if (batteryStatus != -1) { + Dataset.getInstance().setCharging(batteryStatus == BatteryManager.BATTERY_STATUS_CHARGING || + batteryStatus == BatteryManager.BATTERY_STATUS_FULL); + } + + int chargePlug = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1); + if (chargePlug != -1) { + switch (chargePlug) { + case BatteryManager.BATTERY_PLUGGED_AC: + Dataset.getInstance().setCharginMethod("AC"); + break; + case BatteryManager.BATTERY_PLUGGED_USB: + Dataset.getInstance().setCharginMethod("USB"); + break; + case BatteryManager.BATTERY_PLUGGED_WIRELESS: + Dataset.getInstance().setCharginMethod("Wireless"); + break; + default: + break; + } + } + int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1); + int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1); + if (level != -1 && scale != -1) { + Dataset.getInstance().setBatteryPct(level / (float) scale); + } + + long levelNanoWatt = intent.getLongExtra(String.valueOf(BatteryManager.BATTERY_PROPERTY_ENERGY_COUNTER), -1); + if (levelNanoWatt != -1) { + Dataset.getInstance().setBatteryNanoWatt(levelNanoWatt); + } + } + } + + /** + * + * @param context + * + * Monitor connectivity from android syatem service + */ + public void monitorInternet(Context context){ + ConnectivityManager cm = + (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE); + + NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); + if(activeNetwork != null) { + Dataset.getInstance().setConnected(activeNetwork != null && activeNetwork.isConnectedOrConnecting()); + Dataset.getInstance().setConnectionType(activeNetwork.getTypeName() + " " + activeNetwork.getSubtypeName()); + } + } + + /** + * Monitor cpu by reading first line of linux file /proc/stats + */ + public void monitorCPU(){ + try { + RandomAccessFile reader = new RandomAccessFile("/proc/stat", "r"); + String load = reader.readLine(); + + String[] toks = load.split(" +"); // Split on one or more spaces + + float user = Float.parseFloat(toks[1]) + Float.parseFloat(toks[2]); + float system = Float.parseFloat(toks[3]); + float idle = Float.parseFloat(toks[4]); + float wait = Float.parseFloat(toks[5]) + Float.parseFloat(toks[6]) + Float.parseFloat(toks[7]); + + float total = user + system + idle + wait; + + Dataset.getInstance().setCpuUser(user/total); + Dataset.getInstance().setCpuSystem(system/total); + Dataset.getInstance().setCpuWait(wait/total); + Dataset.getInstance().setCpuIdle(idle/total); + + } catch (IOException ex) { + ex.printStackTrace(); + } + } + + /** + * Monitor available memory by using Java's Runtime class + */ + public void monitorMemory(){ + final Runtime runtime = Runtime.getRuntime(); + final long usedMemInMB=(runtime.totalMemory() - runtime.freeMemory()) / 1048576L; + final long maxHeapSizeInMB=runtime.maxMemory() / 1048576L; + final long availHeapSizeInMB = maxHeapSizeInMB - usedMemInMB; + + Dataset.getInstance().setHeapSize(maxHeapSizeInMB); + Dataset.getInstance().setHeapFree(availHeapSizeInMB); + Dataset.getInstance().setHeapUsed(usedMemInMB); + } + +} diff --git a/app/src/main/java/com/guilhermed/offloadingfibonaccibench/AppMonitor.java b/app/src/main/java/com/guilhermed/offloadingfibonaccibench/AppMonitor.java new file mode 100644 index 0000000..bf9f253 --- /dev/null +++ b/app/src/main/java/com/guilhermed/offloadingfibonaccibench/AppMonitor.java @@ -0,0 +1,130 @@ +package com.guilhermed.offloadingfibonaccibench; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.os.BatteryManager; + +import java.io.IOException; +import java.io.RandomAccessFile; + +import Offload.Dataset; + +public class AppMonitor extends BroadcastReceiver { + + @Override + public void onReceive(Context context, Intent intent) { + + monitorBatery(context,intent); + monitorInternet(context); + //monitorCPU(); + monitorMemory(); + + } + + /** + * + * @param context + * @param intent + * + * Get battery information from the system intent. + * Monitor when battery status change and when batery level change + */ + public void monitorBatery(Context context, Intent intent){ + if(intent!=null) { + int batteryStatus = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1); + if (batteryStatus != -1) { + Dataset.getInstance().setCharging(batteryStatus == BatteryManager.BATTERY_STATUS_CHARGING || + batteryStatus == BatteryManager.BATTERY_STATUS_FULL); + } + + int chargePlug = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1); + if (chargePlug != -1) { + switch (chargePlug) { + case BatteryManager.BATTERY_PLUGGED_AC: + Dataset.getInstance().setCharginMethod("AC"); + break; + case BatteryManager.BATTERY_PLUGGED_USB: + Dataset.getInstance().setCharginMethod("USB"); + break; + case BatteryManager.BATTERY_PLUGGED_WIRELESS: + Dataset.getInstance().setCharginMethod("Wireless"); + break; + default: + break; + } + } + int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1); + int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1); + int nanoWattHoursCounter = intent.getIntExtra(Integer.toString(BatteryManager.BATTERY_PROPERTY_ENERGY_COUNTER), -1); + /*if (level != -1 && scale != -1) { + Dataset.getInstance().setBatteryPct(level / (float) scale); + }*/ + + if (nanoWattHoursCounter != -1) { + Dataset.getInstance().setBatteryPct(nanoWattHoursCounter); + } + } + } + + /** + * + * @param context + * + * Monitor connectivity from android system service + */ + public void monitorInternet(Context context){ + ConnectivityManager cm = + (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE); + + NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); + if(activeNetwork != null) { + Dataset.getInstance().setConnected(activeNetwork != null && activeNetwork.isConnectedOrConnecting()); + Dataset.getInstance().setConnectionType(activeNetwork.getTypeName() + " " + activeNetwork.getSubtypeName()); + } + } + + /** + * Monitor cpu by reading first line of linux file /proc/stats + */ + public void monitorCPU(){ + try { + RandomAccessFile reader = new RandomAccessFile("/proc/stat", "r"); //ONSERTAR + String load = reader.readLine(); + + String[] toks = load.split(" +"); // Split on one or more spaces + + float user = Float.parseFloat(toks[1]) + Float.parseFloat(toks[2]); + float system = Float.parseFloat(toks[3]); + float idle = Float.parseFloat(toks[4]); + float wait = Float.parseFloat(toks[5]) + Float.parseFloat(toks[6]) + Float.parseFloat(toks[7]); + + float total = user + system + idle + wait; + + Dataset.getInstance().setCpuUser(user/total); + Dataset.getInstance().setCpuSystem(system/total); + Dataset.getInstance().setCpuWait(wait/total); + Dataset.getInstance().setCpuIdle(idle/total); + + } catch (IOException ex) { + ex.printStackTrace(); + } + } + + /** + * Monitor available memory by using Java's Runtime class + */ + public void monitorMemory(){ + final Runtime runtime = Runtime.getRuntime(); + final long usedMemInMB=(runtime.totalMemory() - runtime.freeMemory()) / 1048576L; + final long maxHeapSizeInMB=runtime.maxMemory() / 1048576L; + final long availHeapSizeInMB = maxHeapSizeInMB - usedMemInMB; + + Dataset.getInstance().setHeapSize(maxHeapSizeInMB); + Dataset.getInstance().setHeapFree(availHeapSizeInMB); + Dataset.getInstance().setHeapUsed(usedMemInMB); + } + +} diff --git a/app/src/main/java/com/guilhermed/offloadingfibonaccibench/MainActivity.java b/app/src/main/java/com/guilhermed/offloadingfibonaccibench/MainActivity.java new file mode 100644 index 0000000..9c00da6 --- /dev/null +++ b/app/src/main/java/com/guilhermed/offloadingfibonaccibench/MainActivity.java @@ -0,0 +1,697 @@ +package com.guilhermed.offloadingfibonaccibench; + +import android.annotation.SuppressLint; +import android.app.ActivityManager; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.ServiceConnection; +import android.net.TrafficStats; +import android.os.BatteryManager; +import android.os.CountDownTimer; +import android.os.Environment; +import android.os.IBinder; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; +import android.widget.Toast; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Observable; +import java.util.Observer; +import java.util.UUID; + +import AMOk.*; +import Offload.Monitor; +import eu.hgross.blaubot.android.BlaubotAndroid; +import eu.hgross.blaubot.android.BlaubotAndroidFactory; +import eu.hgross.blaubot.core.Blaubot; +import eu.hgross.blaubot.core.LifecycleListenerAdapter; + +import static java.lang.Thread.sleep; + +import Offload.*; + +public class MainActivity extends AppCompatActivity implements ServiceCallbacks, Observer { + private static final UUID APP_UUID = UUID.fromString("DE292C5B-34FB-4738-8C7E-D0291389DEC8"); + + private Blaubot mBlaubot; + //private DebugView mDebugView; + private Midd midd; + + private static final int STOP = 0; + private static final int GO = 1; + + private TextView outputPos; + private TextView outputResult; + private EditText inputPosition; + private Button buttonCalculate; + + private long outputValue; + + private int waiter = 0; + + private boolean bounded; + + // variable for testing without going through decision algorithm. true = always offload, false = never offload + private boolean offload = true; + + //private Middleware mid; + private FrameworkMain framework; + + private Monitor mMonitor; + private Planner planner; + //private Extractor extractor; + + private long startTime; + private long diffTime; + + private int currBatteryPct; + private long currBatteryNanoWatt; + private long startBattery; + private long diffBattery; + + private long startBatteryNanoWatt; + private long diffBatteryNanoWatt; + + private Long rxBytesStart = Long.valueOf(0); + private Long txBytesStart = Long.valueOf(0); + + private Long rxBytesDiff; + private Long txBytesDiff; + + private final int[] numbers = new int[]{5, 10, 15, 20, 25, 30, 35, 40, 45}; + private int fiboCount; + + static { + eu.hgross.blaubot.util.Log.LOG_LEVEL = eu.hgross.blaubot.util.Log.LogLevel.DEBUG; + } + + private int UID; + + @SuppressLint("LongLogTag") + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + fiboCount = 0; + + UID = android.os.Process.myUid(); + + setContentView(R.layout.activity_main); + + //startOffloadingMechanism(); + startOffloadingFramework(); + + mBlaubot = BlaubotAndroidFactory.createEthernetBlaubot(APP_UUID); +// mDebugView.registerBlaubotInstance(mBlaubot); + + mBlaubot.addLifecycleListener(new LifecycleListenerAdapter() { + @Override + public void onConnected() { + Log.d("MAINACTIVITY", "CONNECTED"); + } + + @Override + public void onDisconnected() { + Log.d("MAINACTIVITY", "DISCONNECTED"); + } + + }); + + startMyService(); + + outputPos = (TextView) findViewById(R.id.idPosValue); + outputResult = (TextView) findViewById(R.id.idResultValue); + inputPosition = (EditText) findViewById(R.id.idInput); + buttonCalculate = (Button) findViewById(R.id.idButton); + + String storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES).getAbsolutePath(); + String header = "Fibonacci Number;Time Spent;Current Battery Percentage;Battery Spent;Bytes Received;Bytes Transmitted\n"; + String filePath = storageDir + "/benchmarks_values_fibo.txt"; + + File file = new File(filePath); + try { + file.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + + try { + FileOutputStream stream = new FileOutputStream(filePath, false); + OutputStreamWriter osw = new OutputStreamWriter(stream); + osw.write(header); + osw.flush(); + osw.close(); + stream.close(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + + buttonCalculate.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + setBenchmarkStart(); + /*for (int i = 25; i < 30; i++) { + startTime = System.currentTimeMillis(); + startBattery = Math.round(Dataset.getInstance().getBatteryPct()*100); + calcFibonacci(i); + diffBattery = Math.round(Dataset.getInstance().getBatteryPct()*100) - startBattery; + diffTime = System.currentTimeMillis() - startTime; + Log.d("TESTING TIME ELAPSED " + Integer.toString(i), Long.toString(diffTime)); + Toast.makeText(MainActivity.this, "TESTING TIME ELAPSED " + Integer.toString(i) + Long.toString(diffTime), Toast.LENGTH_SHORT).show(); + Log.d("TESTING BATTERY USAGE % " + Integer.toString(i), Long.toString(diffBattery)); + Toast.makeText(MainActivity.this, "TESTING BATTERY USAGE % " + Integer.toString(i) + Long.toString(diffBattery), Toast.LENGTH_SHORT).show(); + }*/ + + final String inputText = inputPosition.getText().toString(); + + inputPosition.setText(String.valueOf(numbers[fiboCount])); + + //offload = Dataset.getInstance().getShouldOffload(); + + if (!offload) { + outputPos.setText("" + String.valueOf(numbers[fiboCount])); + + if (midd == null) { + Log.d("SERVICE READY?", "NOT READY"); + } + + + runOnUiThread(new Runnable() { + public void run() { + midd.inputBenchmarkStartingMessageToMid("started"); + outputValue = calcFibonacci(numbers[fiboCount]-1); + + + outputResult.setText("" + outputValue); + + midd.midPublish(String.valueOf(numbers[fiboCount]) + ";" + String.valueOf(outputValue)); + + setBenchmarkValues(); + + fiboCount++; + } + }); + + } + if (offload) { + //int inputValue = Integer.parseInt(inputText); + outputPos.setText("" + String.valueOf(numbers[fiboCount])); + + runOnUiThread(new Runnable() { + public void run() { + if (midd == null) { + Log.d("SERVICE READY?", "NOT READY"); + } + //midd.registerBlaubot(mBlaubot, (short) 1); + + midd.inputBenchmarkStartingMessageToMid("started"); + + midd.inputToMid(String.valueOf(numbers[fiboCount])); + fiboCount++; + +// startTime = System.currentTimeMillis(); +// startBattery = getBatteryPct(); +// startBatteryNanoWatt = getBatteryNanoWatt(); +// rxBytesStart = getUidRxBytes(UID); +// txBytesStart = getUidTxBytes(UID); + } + }); + } + } + }); + +// final CountDownTimer cdt = new CountDownTimer(30000 * 8 + 1, 30000) { +// public void onTick(long millisUntilFinished) { +// buttonCalculate.performClick(); +// } +// public void onFinish() { +// } +// }; +// +// new CountDownTimer(10000, 10000) { +// public void onTick(long millisUntilFinished) { +// buttonCalculate.performClick(); +// } +// public void onFinish() { +// cdt.start(); +// } +// }.start(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + + stopMyService(); + } + + @Override + protected void onPause() { + super.onPause(); + if (mBlaubot instanceof BlaubotAndroid) { + final BlaubotAndroid blaubotAndroid = (BlaubotAndroid) mBlaubot; + blaubotAndroid.unregisterReceivers(this); + blaubotAndroid.onResume(this); + } + } + + @Override + protected void onResume() { + mBlaubot.startBlaubot(); + + if (mBlaubot instanceof BlaubotAndroid) { + final BlaubotAndroid blaubotAndroid = (BlaubotAndroid) mBlaubot; + blaubotAndroid.setContext(this); + blaubotAndroid.registerReceivers(this); + blaubotAndroid.onResume(this); + } + super.onResume(); + } + + @Override + protected void onStop() { + mBlaubot.stopBlaubot(); + + if (bounded) { + midd.setCallbacks(null); + unbindService(mConnection); + bounded = false; + } + //stopMyService(); + super.onStop(); + } + + @Override + public void onBackPressed() { + super.onBackPressed(); + } + + @Override + protected void onNewIntent(Intent intent) { + if (mBlaubot instanceof BlaubotAndroid) { + final BlaubotAndroid blaubotAndroid = (BlaubotAndroid) mBlaubot; + blaubotAndroid.onNewIntent(intent); + } + super.onNewIntent(intent); + } + + public long calcFibonacci(int n) { + if (n <= 0) + return 0; + if (n == 1) + return 1; + return (calcFibonacci(n - 1) + calcFibonacci(n - 2)); + } + + /*public void send(final String inputValue) { + Log.d("Service running?", Boolean.toString(isMyServiceRunning(Middleware.class))); + + /*for (InetAddress i : getLocalInetAddress()) { + Log.d("IP: ", i.getCanonicalHostName()); + Log.d("IP: ", i.getHostName()); + Log.d("IP: ", i.getHostAddress()); + Log.d("IP: ", i.getAddress().toString()); + } + + String server_url = "http://192.168.0.9:8080/FibonacciServer/FibonacciServlet"; + final RequestQueue requestQueue = Volley.newRequestQueue(MainActivity.this); + + StringRequest stringRequest = new StringRequest(Request.Method.POST, server_url, + new Response.Listener() { + @Override + public void onResponse(String response) { + Log.d("Resposta do servidor: ", response); + setResult(response); + + //setWaiter(GO); + + requestQueue.stop(); + } + }, new Response.ErrorListener() { + @Override + public void onErrorResponse(VolleyError error) { + Log.d("Erro no servidor: ", error.toString()); + + setResult(error.toString()); + + requestQueue.stop(); + } + }) { + @Override + protected Map getParams() { + Map params = new HashMap(); + params.put("fiboString", inputValue); + + return params; + } + }; + + stringRequest.setRetryPolicy(new DefaultRetryPolicy( + 30000, // before was 30000 + 0, // before was 10000 + 30000)); // before was 30000 + requestQueue.add(stringRequest); + }*/ + + public String getResult() { return outputResult.getText().toString(); } + public void setResult(final String response) { + + runOnUiThread(new Runnable() { + + @Override + public void run() { + outputResult.setText(response); + } + }); + } + + public String getOutputPos() { return outputPos.getText().toString(); } + public void setOutputPos(final String response) { + runOnUiThread(new Runnable() { + + @Override + public void run() { + + outputPos.setText(response); + } + }); + } + + @SuppressLint("LongLogTag") + @Override + public void setBenchmarkValues() { + + diffTime = System.currentTimeMillis() - startTime; + //currBatteryPct = Dataset.getInstance().getBatteryPct()*100; + currBatteryPct = getBatteryPct(); + diffBattery = getBatteryPct() - startBattery; + rxBytesDiff = getUidRxBytes(UID) - rxBytesStart; + txBytesDiff = getUidTxBytes(UID) - txBytesStart; + + Log.d("BENCH TESTING TIME ELAPSED", Long.toString(diffTime)); + Log.d("BENCH CURRENT BATTERY PERCENTAGE", String.valueOf(currBatteryPct)); + Log.d("BENCH TESTING BATTERY USAGE %", Long.toString(diffBattery)); + Log.d("BENCH BYTES RECEIVED", Long.toString(rxBytesDiff)); + Log.d("BENCH BYTES SENT", Long.toString(txBytesDiff)); + + String storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES).getAbsolutePath(); + + String filePathBenchmark = storageDir + "/benchmarks_values_fibo.txt"; + + String strNumber = String.valueOf(numbers[fiboCount])+";"; + String strDiffTime = Long.toString(diffTime)+";"; + String strCurrBatteryPct = String.valueOf(currBatteryPct)+";"; + String strDiffBatteryPct = Long.toString(diffBattery)+";"; + String strRxBytesDiff = Long.toString(rxBytesDiff)+";"; + // using '\n' as line break because it's faster and the code is only going to be tested on Android + String strTxBytesDiff = Long.toString(txBytesDiff)+"\n"; + + String strBenchmark = strNumber + strDiffTime + strCurrBatteryPct + strDiffBatteryPct + strRxBytesDiff + strTxBytesDiff; + + File file = new File(filePathBenchmark); + if (!file.exists()) { + try { + file.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + try { + FileOutputStream stream = new FileOutputStream(filePathBenchmark, true); + OutputStreamWriter osw = new OutputStreamWriter(stream); + osw.write(strBenchmark); + osw.flush(); + osw.close(); + stream.close(); + + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + + runOnUiThread(new Runnable() { + public void run() { + Toast.makeText(MainActivity.this, "Calculation Done!", Toast.LENGTH_LONG).show(); + } + }); + } + + @Override + public void setBenchmarkStart() { + startTime = System.currentTimeMillis(); + startBattery = getBatteryPct(); + rxBytesStart = getUidRxBytes(UID); + txBytesStart = getUidTxBytes(UID); + } + + public int getWaiter() { + return waiter; + } + public void setWaiter(int waiter) { + this.waiter = waiter; + } + + private boolean isMyServiceRunning(Class serviceClass) { + ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); + for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) { + if (serviceClass.getName().equals(service.service.getClassName())) { + return true; + } + } + return false; + } + + public int startMyService() { + Intent serviceIntent = new Intent(this, Midd.class); + + if (!isMyServiceRunning(Midd.class)) { + bindService(serviceIntent, mConnection, BIND_AUTO_CREATE); + return 1; + } + return 0; + } + + public int stopMyService() { + Intent serviceIntent = new Intent(this, Midd.class); + + if (!isMyServiceRunning(Midd.class)) { + if (bounded) { + midd.setCallbacks(null); + unbindService(mConnection); + bounded = false; + } + + return 1; + } + + return 0; + } + + ServiceConnection mConnection = new ServiceConnection() { + @Override + public void onServiceDisconnected(ComponentName name) { + Toast.makeText(MainActivity.this, "Service is disconnected!", Toast.LENGTH_LONG).show(); + bounded = false; + midd = null; + } + + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + Toast.makeText(MainActivity.this, "Service is connected!", Toast.LENGTH_LONG).show(); + bounded = true; + Midd.LocalBinder mLocalBinder = (Midd.LocalBinder)service; + midd = mLocalBinder.getMiddlewareInstance(); + midd.setCallbacks(MainActivity.this); + midd.registerBlaubot(mBlaubot, (short) 1); + } + }; + + /// OLD OFFLOADING MECHANISM + /*private static startOffloadingMechanism() { + Monitor mMonitor = new Monitor(); + Timer timer = new Timer(); + + final Extractor extractor = new Extractor(this); + Dataset.getInstance().addObserver(this); + + if(mMonitor != null) { + registerReceiver(mMonitor, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); + registerReceiver(mMonitor, new IntentFilter(Intent.ACTION_POWER_DISCONNECTED)); + registerReceiver(mMonitor, new IntentFilter(Intent.ACTION_POWER_CONNECTED)); + + final IntentFilter filters = new IntentFilter(); + filters.addAction("android.net.wifi.WIFI_STATE_CHANGED"); + filters.addAction("android.net.wifi.STATE_CHANGE"); + registerReceiver(mMonitor, filters); + + timer.schedule(new TimerTask() { + @Override + public void run() { + MainActivity.this.runOnUiThread(new Runnable() { + @Override + public void run() { + mMonitor.onReceive(getApplicationContext(),null); + } + }); + } + },500,500); + + final boolean shouldExecuteLocally = Decider.shouldExecuteLocally(); + + if (shouldExecuteLocally) { + Log.d("Offloading Status: ", "Classifying locally..."); + } else { + Log.d("Offloading Status: ","Classifying Remotely..."); + } + } + }*/ + + public void startOffloadingFramework() { + mMonitor = new Offload.Monitor(); + planner = new Planner(); + + //extractor = new Extractor(this); + //final long tamanho = extractor.getFileSize(); + //Dataset.getInstance().setFileSize(tamanho); + + Dataset.getInstance().addObserver(this); + + framework = new FrameworkMain(); + + framework.run(); + } + + public static InetAddress[] getLocalInetAddress() { + ArrayList addresses = new ArrayList(); + try { + Enumeration en = NetworkInterface.getNetworkInterfaces(); + while( en.hasMoreElements()) { + NetworkInterface intf = en.nextElement(); + for (Enumeration enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) { + InetAddress inetAddress = enumIpAddr.nextElement(); + if (!inetAddress.isLoopbackAddress()) { + addresses.add(inetAddress); + } + } + } + } catch (SocketException ex) { + String LOG_TAG = null; + System.out.println(LOG_TAG + " : " + ex.toString()); + } + return addresses.toArray(new InetAddress[0]); + } + + @Override + public void update(Observable observable, Object o) { + /*bateryLevel.setText(String.valueOf(Math.round(Dataset.getInstance().getBatteryPct()*100))+"%"); + baterySource.setText(Dataset.getInstance().isCharging() ? "Status: Carregando via " + Dataset.getInstance().getCharginMethod() : "Status: Não está carregando"); + internetStatus.setText(Dataset.getInstance().isConnected() ? "Conectado" : "Offline"); + internetSource.setText("Via "+Dataset.getInstance().getConnectionType()); + + memoryHeap.setText("Tamanho total do HEAP: "+Dataset.getInstance().getHeapSize()+"MB"); + heapUsing.setText("Usando no HEAP: "+Dataset.getInstance().getHeapUsed()+"MB"); + heapFree.setText("Disponível no HEAP: "+Dataset.getInstance().getHeapFree()+"MB"); + + cpuUser.setText("User: "+String.valueOf(Math.round(Dataset.getInstance().getCpuUser()*100))+"%"); + cpuSystem.setText("System: "+String.valueOf(Math.round(Dataset.getInstance().getCpuSystem()*100))+"%"); + cpuWait.setText("IO: "+String.valueOf(Math.round(Dataset.getInstance().getCpuWait()*100))+"%"); + cpuIdle.setText("Idle: "+String.valueOf(Math.round(Dataset.getInstance().getCpuIdle()*100))+"%"); + + runtimeOffline.setText("Tempo da última execução offine: "+String.valueOf(Math.round(Dataset.getInstance().getLocalTime()/1000.0))+"s"); + runtimeOnline.setText("Tempo da última execução online: "+String.valueOf(Math.round(Dataset.getInstance().getRemoteTime()/1000.0))+"s");*/ + } + + + /** + * Read UID Rx Bytes + * + * @param uid + * @return rxBytes + */ + public Long getUidRxBytes(int uid) { + BufferedReader reader; + Long rxBytes = 0L; + try { + reader = new BufferedReader(new FileReader("/proc/uid_stat/" + uid + + "/tcp_rcv")); + rxBytes = Long.parseLong(reader.readLine()); + reader.close(); + } + catch (FileNotFoundException e) { + rxBytes = TrafficStats.getUidRxBytes(uid); + //e.printStackTrace(); + } + catch (IOException e) { + e.printStackTrace(); + } + return rxBytes; + } + + /** + * Read UID Tx Bytes + * + * @param uid + * @return txBytes + */ + public Long getUidTxBytes(int uid) { + BufferedReader reader; + Long txBytes = 0L; + try { + reader = new BufferedReader(new FileReader("/proc/uid_stat/" + uid + + "/tcp_snd")); + txBytes = Long.parseLong(reader.readLine()); + reader.close(); + } + catch (FileNotFoundException e) { + txBytes = TrafficStats.getUidTxBytes(uid); + //e.printStackTrace(); + } + catch (IOException e) { + e.printStackTrace(); + } + return txBytes; + } + + public int getBatteryPct() { + IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); + Intent batteryStatus = registerReceiver(null, ifilter); + + int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1); + int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1); + + float batteryPct = level / (float)scale; + + return level; + } + + public long getBatteryNanoWatt() { + IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); + Intent batteryStatus = registerReceiver(null, ifilter); + + long nanoWatt = batteryStatus.getLongExtra(Integer.toString(BatteryManager.BATTERY_PROPERTY_ENERGY_COUNTER), -1); + + return nanoWatt; + } +} diff --git a/app/src/main/java/com/guilhermed/offloadingfibonaccibench/Midd.java b/app/src/main/java/com/guilhermed/offloadingfibonaccibench/Midd.java new file mode 100644 index 0000000..d8cd6bd --- /dev/null +++ b/app/src/main/java/com/guilhermed/offloadingfibonaccibench/Midd.java @@ -0,0 +1,352 @@ +package com.guilhermed.offloadingfibonaccibench; + +import android.app.Service; +import android.content.Intent; +import android.os.Binder; +import android.os.Environment; +import android.os.Handler; +import android.os.IBinder; +import android.util.Log; +import android.widget.Toast; + +import com.android.volley.DefaultRetryPolicy; +import com.android.volley.Request; +import com.android.volley.RequestQueue; +import com.android.volley.Response; +import com.android.volley.VolleyError; +import com.android.volley.toolbox.StringRequest; +import com.android.volley.toolbox.Volley; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import eu.hgross.blaubot.core.Blaubot; +import eu.hgross.blaubot.core.IBlaubotDevice; +import eu.hgross.blaubot.core.ILifecycleListener; +import eu.hgross.blaubot.core.statemachine.IBlaubotConnectionStateMachineListener; +import eu.hgross.blaubot.core.statemachine.states.IBlaubotState; +import eu.hgross.blaubot.messaging.BlaubotMessage; +import eu.hgross.blaubot.messaging.IBlaubotChannel; +import eu.hgross.blaubot.messaging.IBlaubotMessageListener; + +public class Midd extends Service implements ILifecycleListener, IBlaubotConnectionStateMachineListener { + private final String TAG = "MIDDD"; + + private IBlaubotChannel channel; + private Blaubot mBlaubot; + + private String valueFromActivity; + private ServiceCallbacks serviceCallbacks; + + //Declaring the handler + private Handler handler; + //Declaring your implementation of Runnable + private Runner runner; + + private int ackCounter; + + IBinder mBinder = new LocalBinder(); + + public void onCreate() { + super.onCreate(); + + ackCounter = 0; + + //debugView = (DebugView) findViewById(R.id.debugView); + + Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show(); + handler = new Handler(); + runner = new Runner(); + } + + public void onNewIntent(Intent intent) { + Log.d("MESSAGE IN8", "Hello world!"); + } + + @Override + public void onDestroy() { + //Log.d("MESSAGE IN9", "Hello world!"); + handler.removeCallbacks(runner); + Toast.makeText(this, "Service Destroyed", Toast.LENGTH_LONG).show(); + stopSelf(); + super.onDestroy(); + } + + @Override + public IBinder onBind(Intent intent) { + return mBinder; + } + + public class LocalBinder extends Binder { + public Midd getMiddlewareInstance() { + return Midd.this; + } + } + + public class Runner implements Runnable { + @Override + public void run() { + Log.d("AndroidClarified", "Running"); + handler.postDelayed(this, 1000 * 5); + } + } + + public void setCallbacks(ServiceCallbacks callbacks) { + serviceCallbacks = callbacks; + } + + // Send messages to all subscribers of this channel + public void publish (String message) { + //channel.clearMessageQueue(); + channel.publish(message.getBytes()); + Log.d("MESSAGE OUT", message); + } + + public void publishFile (String filePath) { + File file = new File(filePath); + int size = (int) file.length(); + byte[] bytes = new byte[size]; + try { + BufferedInputStream buf = new BufferedInputStream(new FileInputStream(file)); + buf.read(bytes, 0, bytes.length); + buf.close(); + } catch (FileNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + channel.publish(bytes, true); + Log.d("MESSAGE OUT", filePath); + } + + public void inputBenchmarkStartingMessageToMid(String message) { + publish(message); + } + + public void inputToMid(String input) { + valueFromActivity = input; + //publish(valueFromActivity); + send(valueFromActivity); + } + + public void inputFilePathToMid(String filePath) { + publishFile(filePath); + //send(valueFromActivity); + } + + public void midPublish(String input) { + valueFromActivity = input; + publish(valueFromActivity); + } + + public void send(final String inputValue) { + //Log.d("Service running?", Boolean.toString(isMyServiceRunning(Middleware.class))); + + String server_url = "http://192.168.0.9:8080/FibonacciServer/FibonacciServlet"; + final RequestQueue requestQueue = Volley.newRequestQueue(Midd.this); + Log.d("TRACKING", "TRACKING"); + + StringRequest stringRequest = new StringRequest(Request.Method.POST, server_url, + new Response.Listener() { + @Override + public void onResponse(String response) { + Log.d("Resposta do servidor: ", response); + + if (serviceCallbacks != null) { + serviceCallbacks.setResult(response); + serviceCallbacks.setBenchmarkValues(); + } + + publish(valueFromActivity + ";" + response); + + requestQueue.stop(); + } + }, new Response.ErrorListener() { + @Override + public void onErrorResponse(VolleyError error) { + Log.d("Erro no servidor: ", error.toString()); + + if (serviceCallbacks != null) { + serviceCallbacks.setResult(error.toString()); + } + + requestQueue.stop(); + } + }) { + @Override + protected Map getParams() { + Map params = new HashMap(); + params.put("fiboString", inputValue); + + return params; + } + }; + + stringRequest.setRetryPolicy(new DefaultRetryPolicy( + 30000, // before was 30000 + 1000, // before was 10000 + 30000)); // before was 30000 + requestQueue.add(stringRequest); + } + + private IBlaubotMessageListener mMessageListener = new IBlaubotMessageListener() { + @Override + public void onMessage(BlaubotMessage blaubotMessage) { + //String msg = new String(blaubotMessage.getPayload()); + Log.d("MESSAGE RECEIVED", "HAHAHAHAH"); + + if (blaubotMessage != null) { + String message = new String(blaubotMessage.getPayload()); + + if (message.equalsIgnoreCase("started")) { + serviceCallbacks.setBenchmarkStart(); + Log.d("MESSAGE RECEIVED", message); + } else if (message.equalsIgnoreCase("ack")) { + Log.d("ACK RECEIVED", message); + ackCounter++; + + if (ackCounter == 1) { + ackCounter = 0; + serviceCallbacks.setBenchmarkValues(); + } + } else { + String resp = new String(blaubotMessage.getPayload()); + + Log.d("PAYLOAD RECEIVED", resp); + + String[] inputAndOutput = resp.split(";"); + + if (serviceCallbacks != null) { + Log.d("MESSAGE IN FROM NET: ", blaubotMessage.toString()); + serviceCallbacks.setResult(inputAndOutput[1]); + serviceCallbacks.setOutputPos(inputAndOutput[0]); + } + + /*String storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES).getAbsolutePath(); + + Log.d("PATHH", storageDir); + + String filePath = storageDir + "/midd_test_4096KB_result.txt"; + Log.d("PATH + FILENAME", filePath); + + byte[] fileContentInBytes = blaubotMessage.getPayload(); + + File file = new File(filePath); + if (!file.exists()) { + try { + file.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + try { + FileOutputStream stream = new FileOutputStream(filePath); + stream.write(fileContentInBytes); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + }*/ + publish("ack"); + serviceCallbacks.setBenchmarkValues(); + } + } else { + Log.d("ATTENTION: ", "blaubotMessage is null"); + } + } + }; + + private void registerMessageChannel(IBlaubotChannel blaubotChannel) { + channel = blaubotChannel; + channel.subscribe(mMessageListener); + } + + private void unregisterChannels() { + if (channel != null) { + channel.removeMessageListener(mMessageListener); + } + } + + public void registerBlaubot(Blaubot blaubot, short messageChannelId) { + if (mBlaubot != null) { + unregisterBlaubot(); + } + + mBlaubot = blaubot; + mBlaubot.addLifecycleListener(this); + mBlaubot.getConnectionStateMachine().addConnectionStateMachineListener(this); + + // Create a channel for each of our messages + channel = mBlaubot.createChannel(messageChannelId); + channel.getChannelConfig().setTransmitIfNoSubscribers(true); + channel.getChannelConfig().setTransmitReflexiveMessages(true); + + // register them with the chatroom + registerMessageChannel(channel); + } + + public void unregisterBlaubot() { + unregisterChannels(); + if (mBlaubot != null) { + mBlaubot.removeLifecycleListener(this); + mBlaubot.getConnectionStateMachine().removeConnectionStateMachineListener(this); + mBlaubot = null; + } + } + + @Override + public void onConnected() { + Log.d(TAG, "CONNECTED"); + } + + @Override + public void onDisconnected() { + Log.d(TAG, "DISCONNECTED"); + } + + @Override + public void onDeviceJoined(IBlaubotDevice blaubotDevice) { + Log.d(TAG, "JOINED"); + } + + @Override + public void onDeviceLeft(IBlaubotDevice blaubotDevice) { + Log.d(TAG, "LEFT"); + } + + @Override + public void onPrinceDeviceChanged(IBlaubotDevice oldPrince, IBlaubotDevice newPrince) { + Log.d(TAG, "PRINCE CHANGED"); + } + + @Override + public void onKingDeviceChanged(IBlaubotDevice oldKing, IBlaubotDevice newKing) { + Log.d(TAG, "KING CHANGED"); + } + + @Override + public void onStateChanged(IBlaubotState oldState, IBlaubotState newState) { + Log.d(TAG, "STATE CHANGED"); + channel.clearMessageQueue(); + } + + @Override + public void onStateMachineStopped() { + Log.d(TAG, "STATE MACHINE STOPPED"); + } + + @Override + public void onStateMachineStarted() { + Log.d(TAG, "STATE MACHINE STARTED"); + } +} diff --git a/app/src/main/java/com/guilhermed/offloadingfibonaccibench/ServiceCallbacks.java b/app/src/main/java/com/guilhermed/offloadingfibonaccibench/ServiceCallbacks.java new file mode 100644 index 0000000..92a13cf --- /dev/null +++ b/app/src/main/java/com/guilhermed/offloadingfibonaccibench/ServiceCallbacks.java @@ -0,0 +1,13 @@ +package com.guilhermed.offloadingfibonaccibench; + +public interface ServiceCallbacks { + + public String getResult(); + public void setResult(String response); + + public String getOutputPos(); + public void setOutputPos(String response); + + public void setBenchmarkValues(); + public void setBenchmarkStart(); +} diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..1f6bb29 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..0d025f9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4139e47 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,123 @@ + + + + + + + + + + + +