-
Notifications
You must be signed in to change notification settings - Fork 64
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
745c2ab
commit d89ea66
Showing
13 changed files
with
1,902 additions
and
0 deletions.
There are no files selected for viewing
616 changes: 616 additions & 0 deletions
616
freedomOfComputing/src/main/java/nl/tudelft/trustchain/foc/AppGossiper.kt
Large diffs are not rendered by default.
Oops, something went wrong.
13 changes: 13 additions & 0 deletions
13
freedomOfComputing/src/main/java/nl/tudelft/trustchain/foc/EvaDownload.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package nl.tudelft.trustchain.foc | ||
|
||
import nl.tudelft.ipv8.Peer | ||
|
||
data class EvaDownload( | ||
var activeDownload: Boolean = false, | ||
var lastRequest: Long? = null, | ||
var magnetInfoHash: String = "", | ||
var peer: Peer? = null, | ||
var retryAttempts: Int = 0, | ||
var fileName: String = "", | ||
var attemptUUID: String? = null | ||
) |
180 changes: 180 additions & 0 deletions
180
freedomOfComputing/src/main/java/nl/tudelft/trustchain/foc/ExecutionActivity.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,180 @@ | ||
package nl.tudelft.trustchain.foc; | ||
|
||
import android.annotation.SuppressLint; | ||
import android.content.Context; | ||
import android.os.Build; | ||
import android.os.Bundle; | ||
import android.os.Parcel; | ||
import android.os.Parcelable; | ||
import android.util.Log; | ||
import android.view.View; | ||
import android.widget.LinearLayout; | ||
import android.widget.Toast; | ||
import androidx.annotation.RequiresApi; | ||
import androidx.appcompat.app.AppCompatActivity; | ||
import androidx.fragment.app.Fragment; | ||
import androidx.fragment.app.FragmentManager; | ||
import androidx.fragment.app.FragmentTransaction; | ||
import dalvik.system.DexClassLoader; | ||
import dalvik.system.DexFile; | ||
import java.io.File; | ||
import java.io.FileOutputStream; | ||
import java.io.IOException; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.nio.file.Paths; | ||
import java.util.Enumeration; | ||
import java.util.Objects; | ||
import nl.tudelft.trustchain.foc.databinding.ActivityExecutionBinding; | ||
|
||
import static nl.tudelft.trustchain.foc.util.ExtensionUtils.DATA_DOT_EXTENSION; | ||
import static nl.tudelft.trustchain.foc.util.ExtensionUtils.DEX_EXTENSION; | ||
|
||
public class ExecutionActivity extends AppCompatActivity { | ||
|
||
private ActivityExecutionBinding binding; | ||
private Fragment mainFragment; | ||
private FragmentManager manager; | ||
private String apkName; | ||
private final static String FILE_NAME = "fileName"; | ||
|
||
/** | ||
* Stores the current state of the dynamically loaded code. | ||
*/ | ||
private void storeState() { | ||
// Store state next to apk | ||
String fileName = this.apkName + DATA_DOT_EXTENSION; | ||
try { | ||
FileOutputStream stream = new FileOutputStream(fileName); | ||
Parcel p = Parcel.obtain(); | ||
Objects.requireNonNull(manager.saveFragmentInstanceState(mainFragment)).writeToParcel(p, 0); | ||
byte[] bytes = p.marshall(); | ||
stream.write(bytes); | ||
stream.close(); | ||
p.recycle(); | ||
} catch (IOException e) { | ||
this.printToast(e.toString()); | ||
} | ||
} | ||
|
||
/** | ||
* Retrieves the state of the dynamically loaded code (including any performed UI actions) | ||
* | ||
* @return the latest known state of the dynamically loaded code or null if it does not exist | ||
*/ | ||
private Fragment.SavedState getState() { | ||
// states are stored in the same directories as apks themselves (in the app specific files) | ||
String fileName = this.apkName + DATA_DOT_EXTENSION; | ||
try { | ||
Path path = Paths.get(fileName); | ||
byte[] data = Files.readAllBytes(path); | ||
Parcel parcel = Parcel.obtain(); | ||
parcel.unmarshall(data, 0, data.length); | ||
parcel.setDataPosition(0); | ||
Parcelable.Creator<Fragment.SavedState> classLoader = Fragment.SavedState.CREATOR; | ||
return classLoader.createFromParcel(parcel); | ||
} catch (IOException e) { | ||
return null; | ||
} | ||
} | ||
|
||
/** | ||
* This method is called by Android indicating that the user no longer interacts with the app and | ||
* that the state should be saved. | ||
*/ | ||
@Override | ||
public void onPause() { | ||
super.onPause(); | ||
this.storeState(); | ||
} | ||
|
||
/** | ||
* Performs all required initials actions when loading the dynamic code: | ||
* - Retrieve filename of APK from MainActivityFOC | ||
* - Dynamically load code of the APK using the DexClassLoader | ||
* - Restore the state of the dynamically loaded code, if any | ||
* - Load the dynamic code on a view on the users screen. | ||
* | ||
* @param savedInstanceState Default Android savedInstanceState | ||
*/ | ||
@SuppressLint({"ResourceType"}) | ||
@Override | ||
protected void onCreate(Bundle savedInstanceState) { | ||
super.onCreate(savedInstanceState); | ||
|
||
Bundle extras = this.getIntent().getExtras(); | ||
if (extras.containsKey(FILE_NAME)) { | ||
this.apkName = this.getIntent().getStringExtra(FILE_NAME); | ||
assert this.apkName != null; | ||
} else { | ||
this.printToast("No APK name supplied"); | ||
return; | ||
} | ||
|
||
binding = ActivityExecutionBinding.inflate(getLayoutInflater()); | ||
View view = binding.getRoot(); | ||
setContentView(view); | ||
Context context = getApplicationContext(); | ||
|
||
//uncomment if you want to read from the actual phone storage (needs "write" permission) | ||
final String apkPath = this.apkName; | ||
String activeApp = this.apkName.substring(this.apkName.lastIndexOf("/") + 1, this.apkName.lastIndexOf(".")); | ||
|
||
final ClassLoader classLoader = new DexClassLoader(apkPath, context.getCacheDir().getAbsolutePath(), null, this.getClass().getClassLoader()); | ||
|
||
try { | ||
String mainFragmentClass = getMainFragmentClass(apkPath); | ||
Class<?> fragmentClass = classLoader.loadClass((mainFragmentClass != null) ? mainFragmentClass : "com.execmodule." + activeApp + ".MainFragment"); | ||
this.mainFragment = (Fragment) fragmentClass.newInstance(); | ||
Fragment.SavedState state = this.getState(); | ||
if (state != null) { | ||
this.mainFragment.setInitialSavedState(state); | ||
} | ||
|
||
LinearLayout tmpLayout = new LinearLayout(context); | ||
tmpLayout.setId(1); | ||
|
||
this.manager = getSupportFragmentManager(); | ||
FragmentTransaction transaction = this.manager.beginTransaction(); | ||
transaction.add(tmpLayout.getId(), this.mainFragment, "mainFragment"); | ||
transaction.commit(); | ||
|
||
binding.llcontainer.addView(tmpLayout); | ||
} catch (Exception e) { | ||
this.printToast(e.toString()); | ||
Log.i("personal", "Something went wrong"); | ||
} | ||
} | ||
|
||
/** | ||
* Retrieves the main fragment class from the specified APK. | ||
* This class can be in any package. The only requirement is the main fragment should be called exactly 'MainFragment' | ||
* <p> | ||
* Deprecation suppression required to use DexFile, which we use to loop through all classes. | ||
* | ||
* @param path to the APK. | ||
* @return the exact location of the main fragment class | ||
*/ | ||
@SuppressWarnings("deprecation") | ||
private String getMainFragmentClass(String path) { | ||
try { | ||
DexFile dx = DexFile.loadDex(path, File.createTempFile("opt", DEX_EXTENSION, | ||
getCacheDir()).getPath(), 0); | ||
for (Enumeration<String> classNames = dx.entries(); classNames.hasMoreElements(); ) { | ||
String className = classNames.nextElement(); | ||
if (className.contains("MainFragment") && !className.contains("$")) | ||
return className; | ||
} | ||
} catch (IOException e) { | ||
Log.w("personal", "Error opening " + path, e); | ||
} | ||
return null; | ||
} | ||
|
||
/** | ||
* Display a short message on the screen (mainly for debugging purposes). | ||
*/ | ||
private void printToast(String s) { | ||
Toast.makeText(this.getApplicationContext(), s, Toast.LENGTH_LONG).show(); | ||
} | ||
} |
Oops, something went wrong.