Skip to content

Commit

Permalink
Rename FOC dir to foc
Browse files Browse the repository at this point in the history
  • Loading branch information
InvictusRMC committed Feb 23, 2024
1 parent 745c2ab commit d89ea66
Show file tree
Hide file tree
Showing 13 changed files with 1,902 additions and 0 deletions.

Large diffs are not rendered by default.

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
)
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();
}
}
Loading

0 comments on commit d89ea66

Please sign in to comment.