diff --git a/app/build.gradle b/app/build.gradle index c67a9ce0..c78cb18a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -81,6 +81,7 @@ android { signingConfig signingConfigs.debug } } + compileOptions { sourceCompatibility JavaVersion.VERSION_11 targetCompatibility JavaVersion.VERSION_11 @@ -99,6 +100,8 @@ android { lint { abortOnError false } + + } spdxSbom { @@ -122,6 +125,7 @@ spdxSbom { dependencies { implementation 'androidx.preference:preference:1.2.1' implementation 'androidx.work:work-runtime:2.9.0' + implementation 'com.google.android.material:material:1.12.0' def room_version = "2.6.1" implementation "androidx.room:room-runtime:$room_version" @@ -129,10 +133,9 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.7.0' implementation 'com.google.guava:guava:33.2.1-jre' implementation 'androidx.concurrent:concurrent-futures:1.2.0' - implementation 'androidx.activity:activity:1.9.0' - implementation 'androidx.fragment:fragment:1.8.1' + implementation 'androidx.activity:activity:1.9.1' + implementation 'androidx.fragment:fragment:1.8.2' implementation 'androidx.appcompat:appcompat:1.7.0' - implementation 'com.google.android.material:material:1.12.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'androidx.navigation:navigation-fragment:2.7.7' implementation 'androidx.navigation:navigation-ui:2.7.7' diff --git a/app/schemas/de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Iperf3ResultsDataBase/3.json b/app/schemas/de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Iperf3ResultsDataBase/3.json index 59a986b4..92b88f80 100644 --- a/app/schemas/de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Iperf3ResultsDataBase/3.json +++ b/app/schemas/de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Iperf3ResultsDataBase/3.json @@ -2,11 +2,11 @@ "formatVersion": 1, "database": { "version": 3, - "identityHash": "3d98e37212367d9d5ef195be31a59c58", + "identityHash": "12fc36c505cf323268351cd8ce794593", "entities": [ { "tableName": "iperf3_result_database", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uid` TEXT NOT NULL, `result` INTEGER NOT NULL, `uploaded` INTEGER NOT NULL, `timestamp` INTEGER NOT NULL, `input` TEXT, PRIMARY KEY(`uid`))", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uid` TEXT NOT NULL, `result` INTEGER NOT NULL, `uploaded` INTEGER NOT NULL, `timestamp` INTEGER NOT NULL, `input` TEXT, `intervals` TEXT, PRIMARY KEY(`uid`))", "fields": [ { "fieldPath": "uid", @@ -37,13 +37,19 @@ "columnName": "input", "affinity": "TEXT", "notNull": false + }, + { + "fieldPath": "intervals", + "columnName": "intervals", + "affinity": "TEXT", + "notNull": false } ], "primaryKey": { + "autoGenerate": false, "columnNames": [ "uid" - ], - "autoGenerate": false + ] }, "indices": [], "foreignKeys": [] @@ -52,7 +58,7 @@ "views": [], "setupQueries": [ "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", - "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '3d98e37212367d9d5ef195be31a59c58')" + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '12fc36c505cf323268351cd8ce794593')" ] } } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 6a7f0749..861218a2 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -63,14 +63,21 @@ - - + + + + + + fromString(String value) { + Type listType = new TypeToken>() {}.getType(); + return new Gson().fromJson(value, listType); + } + + @TypeConverter + public static String fromArrayList(ArrayList list) { + Gson gson = new Gson(); + return gson.toJson(list); + } +} \ No newline at end of file diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3InputConverter.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Database/Converter/Iperf3InputConverter.java similarity index 61% rename from app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3InputConverter.java rename to app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Database/Converter/Iperf3InputConverter.java index 61c014c5..979f4b8f 100644 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3InputConverter.java +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Database/Converter/Iperf3InputConverter.java @@ -6,22 +6,24 @@ * SPDX-License-Identifier: BSD-3-Clause-Clear */ -package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3; +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.Converter; import androidx.room.ProvidedTypeConverter; import androidx.room.TypeConverter; import com.google.gson.Gson; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Iperf3Input; + @ProvidedTypeConverter public class Iperf3InputConverter { @TypeConverter - public Iperf3Fragment.Iperf3Input StringToIperf3Input(String string) { - return new Gson().fromJson(string, Iperf3Fragment.Iperf3Input.class); + public Iperf3Input StringToIperf3Input(String string) { + return new Gson().fromJson(string, Iperf3Input.class); } @TypeConverter - public String Iperf3InputToString(Iperf3Fragment.Iperf3Input example) { + public String Iperf3InputToString(Iperf3Input example) { return new Gson().toJson(example); } } diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Database/Iperf3ResultsDataBase.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Database/Iperf3ResultsDataBase.java new file mode 100644 index 00000000..3916d063 --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Database/Iperf3ResultsDataBase.java @@ -0,0 +1,32 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database; + +import android.content.Context; +import androidx.room.Database; +import androidx.room.Room; +import androidx.room.RoomDatabase; +import androidx.room.TypeConverters; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.Converter.IntervalsConverter; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.Converter.Iperf3InputConverter; + +@Database(entities = {Iperf3RunResult.class}, version = 1, exportSchema = false) +@TypeConverters({IntervalsConverter.class}) +public abstract class Iperf3ResultsDataBase extends RoomDatabase { + private static volatile Iperf3ResultsDataBase INSTANCE; + + public abstract Iperf3RunResultDao iperf3RunResultDao(); + + public static Iperf3ResultsDataBase getDatabase(final Context context) { + if (INSTANCE == null) { + synchronized (Iperf3ResultsDataBase.class) { + if (INSTANCE == null) { + INSTANCE = Room.databaseBuilder(context.getApplicationContext(), + Iperf3ResultsDataBase.class, "iperf3_database") + .addTypeConverter(new Iperf3InputConverter()) + .allowMainThreadQueries() + .build(); + } + } + } + return INSTANCE; + } +} \ No newline at end of file diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3RunResult.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Database/Iperf3RunResult.java similarity index 65% rename from app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3RunResult.java rename to app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Database/Iperf3RunResult.java index 1a7f9854..94113a12 100644 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3RunResult.java +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Database/Iperf3RunResult.java @@ -6,7 +6,7 @@ * SPDX-License-Identifier: BSD-3-Clause-Clear */ -package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3; +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database; import androidx.annotation.NonNull; import androidx.room.ColumnInfo; @@ -15,6 +15,12 @@ import androidx.room.TypeConverters; import java.sql.Timestamp; +import java.util.ArrayList; + +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.Converter.IntervalsConverter; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.Converter.Iperf3InputConverter; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Iperf3Input; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Interval; @Entity(tableName = "iperf3_result_database") public class Iperf3RunResult { @@ -33,9 +39,13 @@ public class Iperf3RunResult { @ColumnInfo(name = "input") @TypeConverters({Iperf3InputConverter.class}) - public Iperf3Fragment.Iperf3Input input; + public Iperf3Input input; + + @ColumnInfo(name = "intervals") + @TypeConverters({IntervalsConverter.class}) + public ArrayList intervals; - public Iperf3RunResult(String uid, int result, boolean upload, Iperf3Fragment.Iperf3Input input, + public Iperf3RunResult(String uid, int result, boolean upload, Iperf3Input input, Timestamp timestamp) { this.uid = uid; this.result = result; diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3RunResultDao.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Database/Iperf3RunResultDao.java similarity index 66% rename from app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3RunResultDao.java rename to app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Database/Iperf3RunResultDao.java index 158823aa..0295ba74 100644 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3RunResultDao.java +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Database/Iperf3RunResultDao.java @@ -6,7 +6,7 @@ * SPDX-License-Identifier: BSD-3-Clause-Clear */ -package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3; +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database; import androidx.lifecycle.LiveData; import androidx.room.Dao; @@ -14,10 +14,16 @@ import androidx.room.Insert; import androidx.room.OnConflictStrategy; import androidx.room.Query; +import androidx.room.TypeConverters; import androidx.room.Update; +import java.util.ArrayList; import java.util.List; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.Converter.IntervalsConverter; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Intervals; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Interval; + @Dao public interface Iperf3RunResultDao { @Query("SELECT * FROM iperf3_result_database") @@ -44,6 +50,15 @@ public interface Iperf3RunResultDao { @Query("UPDATE iperf3_result_database SET uploaded=:uploaded WHERE uid=:uid") void updateUpload(String uid, boolean uploaded); + @Query("SELECT intervals FROM iperf3_result_database WHERE uid=:uid") + LiveData getIntervals(String uid); + + @Query("UPDATE iperf3_result_database SET intervals=:intervals WHERE uid=:uid") + void updateIntervals(String uid, ArrayList intervals); + + @Query("SELECT * FROM iperf3_result_database WHERE uid=:uid") + LiveData getLiveRunResult(String uid); + @Update void update(Iperf3RunResult iperf3RunResult); diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Fragments/Input/Iperf3CardAdapter.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Fragments/Input/Iperf3CardAdapter.java new file mode 100644 index 00000000..e2ee1d07 --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Fragments/Input/Iperf3CardAdapter.java @@ -0,0 +1,48 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Fragments.Input; + +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentActivity; +import androidx.viewpager2.adapter.FragmentStateAdapter; + +import java.util.ArrayList; + +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Fragments.Iperf3Fragment; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Fragments.Output.Iperf3ListFragment; + +public class Iperf3CardAdapter extends FragmentStateAdapter { + + + private ArrayList fragmentList = new ArrayList<>(); + + public Iperf3CardAdapter(@NonNull FragmentActivity fragmentActivity) { + super(fragmentActivity); + + this.addFragment(Iperf3CardFragment.newInstance(0)); + this.fragmentList.add(Iperf3ListFragment.newInstance()); + } + + public void addFragment(Iperf3CardFragment fragment) { + int fragmentPosition = Math.max(fragmentList.size() - 1, 0); + fragmentList.add(fragmentPosition, fragment); + notifyItemInserted(fragmentList.size() - 2); + } + + public ArrayList getFragments() { + ArrayList fragments = new ArrayList<>(); + for (Fragment fragment : fragmentList) { + if(fragment instanceof Iperf3CardFragment) fragments.add((Iperf3CardFragment) fragment); + } + return fragments; + } + @NonNull + @Override + public Fragment createFragment(int position) { + return fragmentList.get(position); + } + + @Override + public int getItemCount() { + return fragmentList.size(); + } +} \ No newline at end of file diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Fragments/Input/Iperf3CardFragment.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Fragments/Input/Iperf3CardFragment.java new file mode 100644 index 00000000..48163a4f --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Fragments/Input/Iperf3CardFragment.java @@ -0,0 +1,342 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Fragments.Input; + +import android.content.Context; +import android.content.Intent; +import android.graphics.Color; +import android.os.Bundle; +import android.text.Editable; +import android.text.TextWatcher; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ProgressBar; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + +import com.google.android.material.button.MaterialButton; +import com.google.android.material.button.MaterialButtonToggleGroup; +import com.google.android.material.textfield.TextInputEditText; +import com.google.android.material.textview.MaterialTextView; + + +import java.sql.Timestamp; +import java.util.UUID; +import java.util.function.Consumer; + +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Iperf3Input; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Iperf3Service; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Preferences.SPType; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Preferences.SharedPreferencesGrouper; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.R; + +public class Iperf3CardFragment extends Fragment { + + private static final String ARG_POSITION = "position"; + private ProgressBar progressBar; + private Iperf3Input iperf3Input; + private Context ct; + private MaterialButton sendBtn; + private View view; + //todo start iperf3 as a service + private TextInputEditText ip; + private TextInputEditText port; + private TextInputEditText bandwidth; + private TextInputEditText duration; + private TextInputEditText interval; + private TextInputEditText bytes; + private TextInputEditText streams; + private TextInputEditText cport; + + + private MaterialButtonToggleGroup mode; + private MaterialButtonToggleGroup protocol; + private MaterialButtonToggleGroup direction; + + private MaterialButton modeClient; + private MaterialButton modeServer; + private MaterialButton protocolTCP; + private MaterialButton protocolUDP; + private MaterialButton directionUp; + private MaterialButton directionDown; + private MaterialButton directonBidir; + + private SharedPreferencesGrouper spg; + private String TAG = "Iperf3CardFragment"; + + + public static Iperf3CardFragment newInstance(int position) { + Iperf3CardFragment fragment = new Iperf3CardFragment(); + Bundle args = new Bundle(); + args.putInt(ARG_POSITION, position); + fragment.setArguments(args); + return fragment; + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + this.ct = requireContext(); + } + + /** + * Create a text watcher + * @param consumer + * @param name + * @return + */ + private TextWatcher createTextWatcher(Consumer consumer, String name) { + return new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { + + } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { + consumer.accept(charSequence.toString()); + spg.getSharedPreference(SPType.iperf3_sp).edit().putString(name, charSequence.toString()).apply(); + } + + @Override + public void afterTextChanged(Editable editable) { + } + }; + } + + /** + * Set up the text watchers + */ + private void setupTextWatchers() { + ip.addTextChangedListener(createTextWatcher(iperf3Input::setIp, Iperf3Input.IPERF3IP)); + port.addTextChangedListener(createTextWatcher(iperf3Input::setPort, Iperf3Input.IPERF3PORT)); + bandwidth.addTextChangedListener(createTextWatcher(iperf3Input::setBandwidth, Iperf3Input.IPERF3BANDWIDTH)); + duration.addTextChangedListener(createTextWatcher(iperf3Input::setDuration, Iperf3Input.IPERF3DURATION)); + interval.addTextChangedListener(createTextWatcher(iperf3Input::setInterval, Iperf3Input.IPERF3INTERVAL)); + bytes.addTextChangedListener(createTextWatcher(iperf3Input::setBytes, Iperf3Input.IPERF3BYTES)); + streams.addTextChangedListener(createTextWatcher(iperf3Input::setStreams, Iperf3Input.IPERF3STREAMS)); + cport.addTextChangedListener(createTextWatcher(iperf3Input::setCport, Iperf3Input.IPERF3CPORT)); + } + + /** + * Set the text from the shared preferences + * @param editText + * @param key + */ + private void setTextFromSharedPreferences(TextInputEditText editText, String key) { + if (spg.getSharedPreference(SPType.iperf3_sp).contains(key)) { + editText.setText(spg.getSharedPreference(SPType.iperf3_sp).getString(key, "")); + } + } + + /** + * Set the texts from the shared preferences + */ + private void setTextsFromSharedPreferences(){ + setTextFromSharedPreferences(ip, Iperf3Input.IPERF3IP); + setTextFromSharedPreferences(port, Iperf3Input.IPERF3PORT); + setTextFromSharedPreferences(bandwidth, Iperf3Input.IPERF3BANDWIDTH); + setTextFromSharedPreferences(duration, Iperf3Input.IPERF3DURATION); + setTextFromSharedPreferences(interval, Iperf3Input.IPERF3INTERVAL); + setTextFromSharedPreferences(bytes, Iperf3Input.IPERF3BYTES); + setTextFromSharedPreferences(streams, Iperf3Input.IPERF3STREAMS); + setTextFromSharedPreferences(cport, Iperf3Input.IPERF3CPORT); + } + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + view = inflater.inflate(R.layout.fragment_iperf3_card, container, false); + // Initialize the TextView + progressBar = view.findViewById(R.id.iperf3_progress); + progressBar.setVisibility(View.INVISIBLE); + iperf3Input = new Iperf3Input(); + sendBtn = view.findViewById(R.id.iperf3_send); + spg = SharedPreferencesGrouper.getInstance(ct); + sendBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(ct, Iperf3Service.class); + if(!iperf3Input.isValid()){ + Toast.makeText(ct, "Please give at least an IP!", Toast.LENGTH_SHORT).show(); + return; + } + iperf3Input.setUuid(UUID.randomUUID().toString()); + iperf3Input.setTimestamp(new Timestamp(System.currentTimeMillis())); + intent.putExtra("input", iperf3Input); + + ct.startService(intent); + + } + }); + + + ip = view.findViewById(R.id.iperf3_ip); + port = view.findViewById(R.id.iperf3_port); + bandwidth = view.findViewById(R.id.iperf3_bandwidth); + duration = view.findViewById(R.id.iperf3_duration); + interval = view.findViewById(R.id.iperf3_interval); + bytes = view.findViewById(R.id.iperf3_bytes); + streams = view.findViewById(R.id.iperf3_streams); + cport = view.findViewById(R.id.iperf3_cport); + + + mode = view.findViewById(R.id.iperf3_mode_toggle_group); + protocol = view.findViewById(R.id.iperf3_protocol_toggle_group); + direction = view.findViewById(R.id.iperf3_direction_toggle_group); + + modeClient = view.findViewById(R.id.iperf3_client_button); + modeServer = view.findViewById(R.id.iperf3_server_button); + + protocolTCP = view.findViewById(R.id.iperf3_tcp_button); + protocolUDP = view.findViewById(R.id.iperf3_udp_button); + + directionDown = view.findViewById(R.id.iperf3_download_button); + directionUp = view.findViewById(R.id.iperf3_upload_button); + directonBidir = view.findViewById(R.id.iperf3_bidir_button); + + setupTextWatchers(); + setTextsFromSharedPreferences(); + + try { + switch (Iperf3Input.Iperf3Mode.valueOf(spg.getSharedPreference(SPType.iperf3_sp).getString(Iperf3Input.IPERF3MODE, ""))){ + case CLIENT: + updateModeState(modeClient, modeServer, Iperf3Input.Iperf3Mode.CLIENT); + break; + case SERVER: + updateModeState(modeServer, modeClient, Iperf3Input.Iperf3Mode.SERVER); + break; + case UNDEFINED: + default: + modeClient.setBackgroundColor(Color.TRANSPARENT); + modeServer.setBackgroundColor(Color.TRANSPARENT); + spg.getSharedPreference(SPType.iperf3_sp).edit().putString(Iperf3Input.IPERF3MODE, Iperf3Input.Iperf3Mode.UNDEFINED.toString()).apply(); + break; + } + } catch (IllegalArgumentException e) { + Log.e(TAG, "onCreateView: ", e); + } + try { + switch (Iperf3Input.Iperf3Protocol.valueOf(spg.getSharedPreference(SPType.iperf3_sp).getString(Iperf3Input.IPERF3PROTOCOL, ""))){ + case TCP: + updateProtocolState(protocolTCP, protocolUDP, Iperf3Input.Iperf3Protocol.TCP); + break; + case UDP: + updateProtocolState(protocolUDP, protocolTCP, Iperf3Input.Iperf3Protocol.UDP); + break; + case UNDEFINED: + default: + protocolTCP.setBackgroundColor(Color.TRANSPARENT); + protocolUDP.setBackgroundColor(Color.TRANSPARENT); + spg.getSharedPreference(SPType.iperf3_sp).edit().putString(Iperf3Input.IPERF3PROTOCOL, Iperf3Input.Iperf3Protocol.UNDEFINED.toString()).apply(); + break; + } + } catch (IllegalArgumentException e) { + Log.e(TAG, "onCreateView: ", e); + } + try { + switch (Iperf3Input.Iperf3Direction.valueOf(spg.getSharedPreference(SPType.iperf3_sp).getString(Iperf3Input.IPERF3DIRECTION, ""))) { + case UP: + updateDirectionState(directionUp, directionDown, directonBidir, Iperf3Input.Iperf3Direction.UP); + break; + case DOWN: + updateDirectionState(directionDown, directionUp, directonBidir, Iperf3Input.Iperf3Direction.DOWN); + break; + case BIDIR: + updateDirectionState(directonBidir, directionUp, directionDown, Iperf3Input.Iperf3Direction.BIDIR); + break; + case UNDEFINED: + default: + directionUp.setBackgroundColor(Color.TRANSPARENT); + directionDown.setBackgroundColor(Color.TRANSPARENT); + directonBidir.setBackgroundColor(Color.TRANSPARENT); + break; + } + } catch (IllegalArgumentException e) { + Log.e(TAG, "onCreateView: ", e); + } + + mode.addOnButtonCheckedListener(new MaterialButtonToggleGroup.OnButtonCheckedListener() { + @Override + public void onButtonChecked(MaterialButtonToggleGroup group, int checkedId, boolean isChecked) { + if (isChecked) { + switch (checkedId) { + case R.id.iperf3_client_button: + updateModeState(modeClient, modeServer, Iperf3Input.Iperf3Mode.CLIENT); + break; + case R.id.iperf3_server_button: + updateModeState(modeServer, modeClient, Iperf3Input.Iperf3Mode.SERVER); + break; + } + } + } + }); + protocol.addOnButtonCheckedListener(new MaterialButtonToggleGroup.OnButtonCheckedListener() { + @Override + public void onButtonChecked(MaterialButtonToggleGroup group, int checkedId, boolean isChecked) { + if (isChecked) { + switch (checkedId) { + case R.id.iperf3_tcp_button: + updateProtocolState(protocolTCP, protocolUDP, Iperf3Input.Iperf3Protocol.TCP); + break; + case R.id.iperf3_udp_button: + updateProtocolState(protocolUDP, protocolTCP, Iperf3Input.Iperf3Protocol.UDP); + break; + } + } + } + }); + direction.addOnButtonCheckedListener(new MaterialButtonToggleGroup.OnButtonCheckedListener() { + @Override + public void onButtonChecked(MaterialButtonToggleGroup group, int checkedId, boolean isChecked) { + if (isChecked) { + switch (checkedId) { + case R.id.iperf3_upload_button: + updateDirectionState(directionUp, directionDown, directonBidir, Iperf3Input.Iperf3Direction.UP); + break; + case R.id.iperf3_download_button: + updateDirectionState(directionDown, directionUp, directonBidir, Iperf3Input.Iperf3Direction.DOWN); + break; + case R.id.iperf3_bidir_button: + updateDirectionState(directonBidir, directionUp, directionDown, Iperf3Input.Iperf3Direction.BIDIR); + break; + } + } + } + }); + + return view; + } + + @Override + public void onResume() { + super.onResume(); + view.requestLayout(); + } + + + + private void updateModeState(MaterialButton activeButton, MaterialButton inactiveButton, Iperf3Input.Iperf3Mode protocol) { + activeButton.setBackgroundColor(getResources().getColor(R.color.purple_500, null)); + inactiveButton.setBackgroundColor(Color.TRANSPARENT); + iperf3Input.setMode(protocol); + spg.getSharedPreference(SPType.iperf3_sp).edit().putString(Iperf3Input.IPERF3MODE, protocol.toString()).apply(); + } + + private void updateProtocolState(MaterialButton activeButton, MaterialButton inactiveButton, Iperf3Input.Iperf3Protocol protocol) { + activeButton.setBackgroundColor(getResources().getColor(R.color.purple_500, null)); + inactiveButton.setBackgroundColor(Color.TRANSPARENT); + iperf3Input.setProtocol(protocol); + spg.getSharedPreference(SPType.iperf3_sp).edit().putString(Iperf3Input.IPERF3PROTOCOL, protocol.toString()).apply(); + } + + private void updateDirectionState(MaterialButton activeButton, MaterialButton inactiveButton1, MaterialButton inactiveButton2, Iperf3Input.Iperf3Direction direction) { + activeButton.setBackgroundColor(getResources().getColor(R.color.purple_500, null)); + inactiveButton1.setBackgroundColor(Color.TRANSPARENT); + inactiveButton2.setBackgroundColor(Color.TRANSPARENT); + iperf3Input.setDirection(direction); + spg.getSharedPreference(SPType.iperf3_sp).edit().putString(Iperf3Input.IPERF3DIRECTION, direction.toString()).apply(); + } +} \ No newline at end of file diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Fragments/Iperf3Fragment.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Fragments/Iperf3Fragment.java new file mode 100644 index 00000000..74eba88e --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Fragments/Iperf3Fragment.java @@ -0,0 +1,55 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Fragments; + +import android.content.Context; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.viewpager2.widget.ViewPager2; + +import com.google.android.material.button.MaterialButton; + +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Fragments.Input.Iperf3CardAdapter; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Fragments.Input.Iperf3CardFragment; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.R; + +public class Iperf3Fragment extends Fragment{ + private static final String TAG = "iperf3InputFragment"; + + private View v; + private Context ct; + private MaterialButton sendBtn; + private ViewPager2 viewPager; + private Iperf3CardAdapter adapter; + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup parent, @Nullable Bundle savedInstanceState) { + ct = requireContext(); + v = inflater.inflate(R.layout.fragment_iperf3_input, parent, false); + viewPager = v.findViewById(R.id.iperf3_viewpager); + //linearLayout = v.findViewById(R.id.iperf3_plan); + adapter = new Iperf3CardAdapter(getActivity()); + + viewPager.setAdapter(adapter); + + viewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() { + @Override + public void onPageSelected(int position) { + super.onPageSelected(position); + adapter.notifyDataSetChanged(); + v.requestLayout(); + } + }); + + + return v; + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + } +} \ No newline at end of file diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3ListFragment.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Fragments/Output/Iperf3ListFragment.java similarity index 68% rename from app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3ListFragment.java rename to app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Fragments/Output/Iperf3ListFragment.java index 6ae30a5d..2c5ce49a 100644 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3ListFragment.java +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Fragments/Output/Iperf3ListFragment.java @@ -8,9 +8,10 @@ //from https://codeburst.io/android-swipe-menu-with-recyclerview-8f28a235ff28 -package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3; +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Fragments.Output; import android.annotation.SuppressLint; +import android.content.Context; import android.graphics.Canvas; import android.os.Bundle; import android.os.Handler; @@ -21,6 +22,7 @@ import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; +import androidx.lifecycle.Observer; import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -31,7 +33,13 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton; import java.util.ArrayList; +import java.util.List; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Iperf3RecyclerViewAdapter; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.Iperf3ResultsDataBase; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.Iperf3RunResult; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.Iperf3RunResultDao; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Worker.Iperf3ToLineProtocolWorker; import de.fraunhofer.fokus.OpenMobileNetworkToolkit.R; import de.fraunhofer.fokus.OpenMobileNetworkToolkit.SwipeController; import de.fraunhofer.fokus.OpenMobileNetworkToolkit.SwipeControllerActions; @@ -45,6 +53,30 @@ public class Iperf3ListFragment extends Fragment { private LinearLayoutManager linearLayoutManager; private FloatingActionButton uploadBtn; private Iperf3ResultsDataBase db; + private Context context; + + + + public static Iperf3ListFragment newInstance() { + Iperf3ListFragment fragment = new Iperf3ListFragment(); + Bundle args = new Bundle(); + fragment.setArguments(args); + return fragment; + } + + + + private void observeDatabaseChanges() { + if(db == null) return; + db.iperf3RunResultDao().getAll().observe(getViewLifecycleOwner(), new Observer>() { + @Override + public void onChanged(@Nullable List runResults) { + updateIperf3ListAdapter(); + } + }); + } + + @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -52,53 +84,57 @@ public void onCreate(@Nullable Bundle savedInstanceState) { @SuppressLint("NotifyDataSetChanged") public void updateIperf3ListAdapter() { - if (this.adapter != null) { - this.adapter.notifyDataSetChanged(); - } + if (this.adapter != null) this.adapter.notifyDataSetChanged(); } @SuppressLint("ClickableViewAccessibility") public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.fragment_iperf3_list, parent, false); - ArrayList uids = this.getArguments().getStringArrayList("iperf3List"); + this.context = requireContext(); + recyclerView = v.findViewById(R.id.runners_list); uploadBtn = v.findViewById(R.id.iperf3_upload_button); + db = Iperf3ResultsDataBase.getDatabase(this.context); + + observeDatabaseChanges(); + + linearLayoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false); + this.adapter = new Iperf3RecyclerViewAdapter(getActivity(), + new ArrayList(db.iperf3RunResultDao().getIDs()), + uploadBtn); + + recyclerView.setLayoutManager(linearLayoutManager); - adapter = new Iperf3RecyclerViewAdapter(getActivity(), uids, uploadBtn); recyclerView.setAdapter(adapter); - db = Iperf3ResultsDataBase.getDatabase(requireContext()); - swipeController = new SwipeController(new SwipeControllerActions() { @SuppressLint("NotifyDataSetChanged") @Override public void onRightClicked(int position) { WorkManager iperf3WM = WorkManager.getInstance(getContext()); - String uid = uids.get(position); + String uid = new ArrayList(db.iperf3RunResultDao().getIDs()).get(position); iperf3WM.cancelAllWorkByTag(uid); Iperf3RunResultDao iperf3RunResultDao = Iperf3ResultsDataBase.getDatabase(requireContext()).iperf3RunResultDao(); Iperf3RunResult runResult = iperf3RunResultDao.getRunResult(uid); - Data.Builder iperf3Data = new Data.Builder(); - iperf3Data.putString("rawIperf3file", runResult.input.iperf3rawIperf3file); - iperf3Data.putString("iperf3LineProtocolFile", runResult.input.iperf3LineProtocolFile); - iperf3Data.putString("measurementName", runResult.input.measurementName); - iperf3Data.putString("ip", runResult.input.iperf3IP); - iperf3Data.putString("port", runResult.input.iperf3Port); - iperf3Data.putString("bandwidth", runResult.input.iperf3Bandwidth); - iperf3Data.putString("duration", runResult.input.iperf3Duration); - iperf3Data.putString("interval", runResult.input.iperf3Interval); - iperf3Data.putString("bytes", runResult.input.iperf3Bytes); - iperf3Data.putString("protocol", Iperf3Utils.getProtocolString(runResult.input.iperf3IdxProtocol)); - iperf3Data.putBoolean("rev", runResult.input.iperf3Reverse); - iperf3Data.putBoolean("biDir", runResult.input.iperf3BiDir); - iperf3Data.putBoolean("oneOff", runResult.input.iperf3OneOff); - iperf3Data.putString("client", Iperf3Utils.getModeString(runResult.input.iperf3IdxMode)); - iperf3Data.putString("timestamp", runResult.input.timestamp.toString()); + iperf3Data.putString("rawIperf3file", runResult.input.getRawFile()); + iperf3Data.putString("iperf3LineProtocolFile", runResult.input.getLineProtocolFile()); + iperf3Data.putString("measurementName", runResult.input.getMeasurementName()); + iperf3Data.putString("ip", runResult.input.getIp()); + iperf3Data.putString("port", runResult.input.getPort()); + iperf3Data.putString("bandwidth", runResult.input.getBandwidth()); + iperf3Data.putString("duration", runResult.input.getDuration()); + iperf3Data.putString("interval", runResult.input.getInterval()); + iperf3Data.putString("bytes", runResult.input.getBytes()); + iperf3Data.putString("protocol", runResult.input.getProtocol().toString()); + iperf3Data.putString("direction", runResult.input.getDirection().toString()); + iperf3Data.putBoolean("oneOff", runResult.input.isOneOff()); + iperf3Data.putString("mode", runResult.input.getMode().toString()); + iperf3Data.putString("timestamp", runResult.input.getTimestamp().toString()); OneTimeWorkRequest iperf3LP = new OneTimeWorkRequest @@ -121,13 +157,12 @@ public void run() { @Override public void onLeftClicked(int position) { Bundle input = new Bundle(); - input.putString("uid", uids.get(position)); + input.putString("uid", new ArrayList(db.iperf3RunResultDao().getIDs()).get(position)); getActivity().getSupportFragmentManager().setFragmentResult("input", input); getActivity().getSupportFragmentManager().popBackStack(); } }); - ItemTouchHelper itemTouchhelper = new ItemTouchHelper(swipeController); itemTouchhelper.attachToRecyclerView(recyclerView); @@ -137,6 +172,8 @@ public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { swipeController.onDraw(c); } }); + + return v; } diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3LogFragment.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Fragments/Output/Iperf3LogFragment.java similarity index 68% rename from app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3LogFragment.java rename to app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Fragments/Output/Iperf3LogFragment.java index d6364041..d12a81c1 100644 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3LogFragment.java +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Fragments/Output/Iperf3LogFragment.java @@ -6,7 +6,7 @@ * SPDX-License-Identifier: BSD-3-Clause-Clear */ -package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3; +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Fragments.Output; import android.content.Context; import android.graphics.drawable.Drawable; @@ -19,6 +19,7 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.FrameLayout; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.LinearLayout; @@ -29,15 +30,13 @@ import androidx.core.widget.TextViewCompat; import androidx.fragment.app.Fragment; -import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Error; -import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Interval; -import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.SUM_TYPE; -import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.Sum; -import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.UDP.UDP_DL_SUM; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Iperf3Input; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.Iperf3ResultsDataBase; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.Iperf3RunResult; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Iperf3Utils; import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Metric.METRIC_TYPE; import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Metric.Metric; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; + import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; @@ -67,6 +66,7 @@ public class Iperf3LogFragment extends Fragment { private Metric defaultRTT; private Metric defaultJITTER; private Metric PACKET_LOSS; + private Context context; public Iperf3LogFragment() { } @@ -76,6 +76,7 @@ public Iperf3LogFragment() { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.db = Iperf3ResultsDataBase.getDatabase(getActivity().getApplicationContext()); + this.context = requireContext(); } private void setFields(Iperf3RunResult iperf3RunResult) { @@ -97,13 +98,13 @@ public void run() { try { br = new BufferedReader(new FileReader(file)); } catch (FileNotFoundException e) { - iperf3OutputViewer.setText(String.format("no iPerf3 file found, with following path: \n %s", iperf3RunResult.input.iperf3rawIperf3file)); + iperf3OutputViewer.setText(String.format("no iPerf3 file found, with following path: \n %s", iperf3RunResult.input.getRawFile())); logHandler.removeCallbacks(logUpdate); return; } String line; - - Iperf3Parser iperf3Parser = new Iperf3Parser(iperf3RunResult.input.iperf3rawIperf3file); + /* + Iperf3Parser iperf3Parser = new Iperf3Parser(iperf3RunResult.input.getRawFile()); iperf3Parser.addPropertyChangeListener(new PropertyChangeListener() { private void parseSum(Sum sum, Metric throughput){ @@ -153,7 +154,7 @@ public void propertyChange(PropertyChangeEvent evt) { } }); - iperf3Parser.parse(); + iperf3Parser.parse();*/ if (iperf3RunResult.result != -100) { logHandler.removeCallbacks(logUpdate); return; @@ -164,8 +165,59 @@ public void propertyChange(PropertyChangeEvent evt) { } }; + private TextView createTextView(Context ct, String text, float weight) { + TextView textView = new TextView(ct); + textView.setText(text); + LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT); + layoutParams.weight = weight; + textView.setLayoutParams(layoutParams); + return textView; + } + private LinearLayout getTextView(String name, String value) { + if(value == null) return null; + if(value.equals("")) return null; + LinearLayout mainLL = new LinearLayout(context); + mainLL.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); + mainLL.setOrientation(LinearLayout.HORIZONTAL); + + TextView parameterName = createTextView(context, name, 0.25F); + TextView parameterValue = createTextView(context, value, 0.75F); + + mainLL.addView(parameterName); + mainLL.addView(parameterValue); + return mainLL; + } + + private void addTextView(LinearLayout ll, String name, String value) { + LinearLayout mainLL = getTextView(name, value); + if(mainLL != null) ll.addView(mainLL); + } + + public LinearLayout getInputAsLinearLayoutKeyValue(Iperf3Input input) { + LinearLayout main = new LinearLayout(context); + main.setOrientation(LinearLayout.VERTICAL); + LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( + 0, + FrameLayout.LayoutParams.WRAP_CONTENT); + layoutParams.weight = 8f; + main.setLayoutParams(layoutParams); + + addTextView(main, Iperf3Input.IPERF3IP.replace("iperf3", ""), input.getIp()); + addTextView(main, Iperf3Input.IPERF3PORT.replace("iperf3", ""), input.getPort()); + addTextView(main, Iperf3Input.IPERF3PROTOCOL.replace("iperf3Idx", ""), input.getProtocol().toString()); + addTextView(main, Iperf3Input.IPERF3MODE.replace("iperf3Idx", ""), input.getMode().toPrettyPrint()); + addTextView(main, Iperf3Input.IPERF3DIRECTION.replace("iperf3", ""), input.getDirection().toPrettyPrint()); + addTextView(main, Iperf3Input.IPERF3BANDWIDTH.replace("iperf3", ""), input.getBandwidth()); + addTextView(main, Iperf3Input.IPERF3DURATION.replace("iperf3", ""), input.getDuration()); + addTextView(main, Iperf3Input.IPERF3UUID.replace("iperf3", ""), input.getUuid()); + addTextView(main, Iperf3Input.IPERF3STREAMS.replace("iperf3", ""), input.getStreams()); + addTextView(main, Iperf3Input.IPERF3TIMESTAMP.replace("iperf3", ""), input.getTimestamp().toString()); + + return main; + } + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, @@ -186,8 +238,8 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, mainLL.setLayoutParams(layoutParams); LinearLayout.LayoutParams foo = new LinearLayout.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT); + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT); foo.setMargins(30, 10, 0, 0); firstRow.setLayoutParams(foo); @@ -215,26 +267,19 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, uploadIconView.setLayoutParams(uploadIconViewLayout); - parameterLL = iperf3RunResult.input.getInputAsLinearLayoutKeyValue(new LinearLayout(ct), ct); - - - - firstRow.addView(parameterLL); - LinearLayout headerWrapper = new LinearLayout(ct); LinearLayout.LayoutParams headerWrapperLayout = new LinearLayout.LayoutParams( - ViewGroup.LayoutParams.WRAP_CONTENT, - ViewGroup.LayoutParams.WRAP_CONTENT); + LinearLayout.LayoutParams.WRAP_CONTENT, + LinearLayout.LayoutParams.WRAP_CONTENT); headerWrapper.setLayoutParams(headerWrapperLayout); headerWrapper.setOrientation(LinearLayout.VERTICAL); CardView cardView = new CardView(ct); - LinearLayout.LayoutParams cardViewLayout = Iperf3Utils.getLayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT, - 0); + CardView.LayoutParams cardViewLayout = new CardView.LayoutParams( + CardView.LayoutParams.MATCH_PARENT, + CardView.LayoutParams.WRAP_CONTENT); headerWrapper.setPadding(30, 30, 30, 30); cardView.setLayoutParams(cardViewLayout); cardView.setRadius(10); @@ -254,6 +299,9 @@ public void onClick(View v) { header.setLayoutParams(headerLayout); header.setOrientation(LinearLayout.HORIZONTAL); + firstRow.addView(getInputAsLinearLayoutKeyValue(iperf3RunResult.input)); + + TextView headerName = new TextView(ct); headerName.setText("iPerf3 run"); LinearLayout.LayoutParams headerNameLayout = new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT); @@ -313,31 +361,44 @@ public void onClick(View v) { metricLL.addView(defaultThroughput.createMainLL("Throughput")); - if(iperf3RunResult.input.iperf3BiDir) { - metricLL.addView(defaultReverseThroughput.createMainLL("Throughput")); - if(iperf3RunResult.input.iperf3IdxProtocol == 0) { - //defaultRTT = new Metric(METRIC_TYPE.RTT); - //metricLL.addView(defaultRTT.createOneDirection("RTT")); - } - if(iperf3RunResult.input.iperf3IdxProtocol == 1) { - defaultJITTER = new Metric(METRIC_TYPE.JITTER, ct); - metricLL.addView(defaultJITTER.createMainLL("Jitter ms")); - PACKET_LOSS = new Metric(METRIC_TYPE.PACKET_LOSS, ct); - metricLL.addView(PACKET_LOSS.createMainLL("Packet Loss %")); - } - } - if(iperf3RunResult.input.iperf3Reverse) { - if(iperf3RunResult.input.iperf3IdxProtocol == 1) { - defaultJITTER = new Metric(METRIC_TYPE.JITTER, ct); - metricLL.addView(defaultJITTER.createMainLL("Jitter ms")); - PACKET_LOSS = new Metric(METRIC_TYPE.JITTER, ct); - metricLL.addView(PACKET_LOSS.createMainLL("Packet Loss %")); - } - } else if(!iperf3RunResult.input.iperf3BiDir) { - if(iperf3RunResult.input.iperf3IdxProtocol == 0) { - //defaultRTT = new Metric(METRIC_TYPE.RTT); - //metricLL.addView(defaultRTT.createOneDirection("RTT ms")); - } + + + switch (iperf3RunResult.input.getDirection()){ + case UP: + defaultThroughput.getDirectionName().setText("Uplink Mbit/s"); + //display RTT when available - https://github.com/esnet/iperf/issues/1724 + break; + case DOWN: + defaultThroughput.getDirectionName().setText("Downlink Mbit/s"); + switch (iperf3RunResult.input.getProtocol()){ + case TCP: + break; + case UDP: + defaultJITTER = new Metric(METRIC_TYPE.JITTER, ct); + metricLL.addView(defaultJITTER.createMainLL("Jitter ms")); + PACKET_LOSS = new Metric(METRIC_TYPE.PACKET_LOSS, ct); + metricLL.addView(PACKET_LOSS.createMainLL("Packet Loss %")); + break; + } + break; + case BIDIR: + metricLL.addView(defaultReverseThroughput.createMainLL("Throughput")); + switch (iperf3RunResult.input.getProtocol()){ + case TCP: + defaultThroughput.getDirectionName().setText("Downlink Mbit/s"); + defaultReverseThroughput.getDirectionName().setText("Uplink Mbit/s"); + break; + case UDP: + defaultThroughput.getDirectionName().setText("Downlink Mbit/s"); + defaultReverseThroughput.getDirectionName().setText("Uplink Mbit/s"); + defaultJITTER = new Metric(METRIC_TYPE.JITTER, ct); + metricLL.addView(defaultJITTER.createMainLL("Jitter ms")); + PACKET_LOSS = new Metric(METRIC_TYPE.PACKET_LOSS, ct); + metricLL.addView(PACKET_LOSS.createMainLL("Packet Loss %")); + break; + } + + break; } mainLL.addView(metricLL); @@ -346,11 +407,11 @@ public void onClick(View v) { mainLL.addView(secondRow); - if(iperf3RunResult.input.iperf3rawIperf3file == null){ + if(iperf3RunResult.input.getRawFile() == null){ iperf3OutputViewer.setText("iPerf3 file path empty!"); return v; } - file = new File(iperf3RunResult.input.iperf3rawIperf3file); + file = new File(iperf3RunResult.input.getRawFile()); logHandler = new Handler(Looper.myLooper()); @@ -358,6 +419,12 @@ public void onClick(View v) { return v; } + @Override + public void onResume() { + super.onResume(); + v.requestLayout(); + } + public void onPause() { super.onPause(); if(logHandler != null) logHandler.removeCallbacks(logUpdate); diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Intervals.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Intervals.java index 08635896..a2c18fd4 100644 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Intervals.java +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Intervals.java @@ -1,11 +1,17 @@ package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3; +import androidx.room.TypeConverters; import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Interval; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.Converter.IntervalsConverter; import java.util.ArrayList; public class Intervals { - private final ArrayList intervals; + @TypeConverters({IntervalsConverter.class}) + private ArrayList intervals; + public Intervals(ArrayList intervals){ + this.intervals = intervals; + } public Intervals(){ this.intervals = new ArrayList<>(); } @@ -16,4 +22,7 @@ public ArrayList getIntervalArrayList(){ return intervals; } -} + public void setIntervals(ArrayList intervals){ + this.intervals = intervals; + } +} \ No newline at end of file diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3Executor.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3Executor.java new file mode 100644 index 00000000..db77b0fa --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3Executor.java @@ -0,0 +1,119 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3; + +import static android.app.PendingIntent.getActivity; + +import android.content.Context; +import android.util.Log; + +import androidx.work.Data; +import androidx.work.OneTimeWorkRequest; +import androidx.work.WorkInfo; +import androidx.work.WorkManager; + +import java.util.UUID; + +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Worker.Iperf3ExecuterWorker; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Worker.Iperf3ToLineProtocolWorker; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Worker.Iperf3UploadWorker; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.Iperf3ResultsDataBase; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.Iperf3RunResult; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.Iperf3RunResultDao; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Preferences.SPType; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Preferences.SharedPreferencesGrouper; + +public class Iperf3Executor { + private static final String TAG = "Iperf3Executor"; + private WorkManager workManager; + private Context context; + private Iperf3Input iperf3Input; + private Data.Builder dataBuilder; + private Iperf3RunResultDao iperf3RunResultDao; + private SharedPreferencesGrouper spg; + private OneTimeWorkRequest iperf3WR; + private OneTimeWorkRequest iperf3LP; + private OneTimeWorkRequest iperf3UP; + + + public Iperf3Executor(Context context, Iperf3Input iperf3Input) { + this.context = context; + spg = SharedPreferencesGrouper.getInstance(context); + workManager = WorkManager.getInstance(context); + iperf3RunResultDao = Iperf3ResultsDataBase.getDatabase(context).iperf3RunResultDao(); + this.iperf3Input = iperf3Input; + this.dataBuilder = this.iperf3Input.getInputAsDataBuilder(); + + + iperf3WR = new OneTimeWorkRequest + .Builder(Iperf3ExecuterWorker.class) + .setInputData(this.dataBuilder.build()) + .addTag("iperf3Run") + .addTag(iperf3Input.getUuid()) + .build(); + iperf3LP = new OneTimeWorkRequest + .Builder(Iperf3ToLineProtocolWorker.class) + .setInputData(this.dataBuilder.build()) + .build(); + iperf3UP = new OneTimeWorkRequest + .Builder(Iperf3UploadWorker.class) + .setInputData(this.dataBuilder.build()) + .addTag("iperf3") + .build(); + iperf3RunResultDao.insert(new Iperf3RunResult(this.iperf3Input.getUuid(), + -100, + false, + this.iperf3Input, + this.iperf3Input.getTimestamp())); + + + + + workManager.getWorkInfoByIdLiveData(iperf3WR.getId()).observeForever(workInfo -> { + int iperf3_result; + iperf3_result = workInfo.getOutputData().getInt("iperf3_result", -100); + if (workInfo.getState().equals(WorkInfo.State.CANCELLED)) { + iperf3_result = -1; + } + iperf3RunResultDao.updateResult(this.iperf3Input.getUuid(), iperf3_result); + Log.d(TAG, "onChanged: iperf3_result: " + iperf3_result); + /*if (iperf3_result == -100) { + progressIndicator.setVisibility(LinearProgressIndicator.VISIBLE); + if (!isModeSpinnerClient()) { + progressbarHandler.postDelayed(progressbarUpdate, SHOW_PROGRESSBAR); + } + } else if (iperf3_result != 0) { + progressIndicator.setIndicatorColor(failedColors); + progressbarHandler.postDelayed(progressbarUpdate, SHOW_PROGRESSBAR); + + } else { + progressIndicator.setIndicatorColor(succesColors); + progressbarHandler.postDelayed(progressbarUpdate, SHOW_PROGRESSBAR); + }*/ + }); + + workManager.getWorkInfoByIdLiveData(iperf3UP.getId()).observeForever(workInfo -> { + boolean iperf3_upload; + iperf3_upload = workInfo.getOutputData().getBoolean("iperf3_upload", false); + Log.d(TAG, "onChanged: iperf3_upload: " + iperf3_upload); + iperf3RunResultDao.updateUpload(this.iperf3Input.getUuid(), iperf3_upload); + }); + + } + + public UUID getUuid() { + return this.iperf3WR.getId(); + } + + public void start() { + if (spg.getSharedPreference(SPType.logging_sp).getBoolean("enable_influx", false)) { + workManager.beginWith(iperf3WR).then(iperf3LP).then(iperf3UP).enqueue(); + } else { + workManager.beginWith(iperf3WR).then(iperf3LP).enqueue(); + } + + } + + public void stop(){ + workManager.cancelAllWorkByTag(this.iperf3Input.getUuid()); + } + +} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3Fragment.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3Fragment.java deleted file mode 100644 index ff16e37c..00000000 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3Fragment.java +++ /dev/null @@ -1,857 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2023 Peter Hasse - * SPDX-FileCopyrightText: 2023 Johann Hackler - * SPDX-FileCopyrightText: 2023 Fraunhofer FOKUS - * - * SPDX-License-Identifier: BSD-3-Clause-Clear - */ - -package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3; - -import android.content.Context; -import android.content.SharedPreferences; -import android.os.Bundle; -import android.os.Environment; -import android.os.Handler; -import android.os.Looper; -import android.system.ErrnoException; -import android.system.Os; -import android.text.Editable; -import android.text.TextWatcher; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.Button; -import android.widget.CheckBox; -import android.widget.EditText; -import android.widget.LinearLayout; -import android.widget.Spinner; -import android.widget.TextView; -import android.widget.Toast; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentResultListener; -import androidx.lifecycle.MutableLiveData; -import androidx.lifecycle.Observer; -import androidx.navigation.NavController; -import androidx.navigation.fragment.NavHostFragment; -import androidx.work.Data; -import androidx.work.OneTimeWorkRequest; -import androidx.work.WorkInfo; -import androidx.work.WorkManager; - -import com.google.android.material.progressindicator.LinearProgressIndicator; -import com.google.common.util.concurrent.ListenableFuture; - -import java.io.File; -import java.io.IOException; -import java.lang.reflect.Field; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.sql.Timestamp; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.LinkedList; -import java.util.List; -import java.util.UUID; - -import de.fraunhofer.fokus.OpenMobileNetworkToolkit.R; -import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Preferences.SPType; -import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Preferences.SharedPreferencesGrouper; - -public class Iperf3Fragment extends Fragment { - private static final String TAG = "iperf3InputFragment"; - private final int SHOW_PROGRESSBAR = 3000; - private final String IPERF3IP = "iperf3IP"; - private final String IPERF3PORT = "iperf3Port"; - private final String IPERF3BANDWIDTH = "iperf3Bandwidth"; - private final String IPERF3DURATION = "iperf3Duration"; - private final String IPERF3INTERVAL = "iperf3Interval"; - private final String IPERF3BYTES = "iperf3Bytes"; - private final String IPERF3STREAMS = "iperf3Streams"; - private final String IPERF3BIDIR = "iperf3BiDir"; - private final String IPERF3REVERSE = "iperf3Reverse"; - private final String IPERF3JSON = "iperf3Json"; - private final String IPERF3ONEOFF = "iperf3OneOff"; - private final String IPERF3IDXPROTOCOL = "iperf3IdxProtocol"; - private final String IPERF3IDXMODE = "iperf3IdxMode"; - private final String IPERF3CPORT = "iperf3cport"; - private CheckBox iperf3BiDir; - private CheckBox iperf3Reverse; - - private CheckBox iperf3OneOff; - private EditText iperf3EtIp; - private EditText iperf3EtPort; - private EditText iperf3EtBandwidth; - private EditText iperf3EtDuration; - private EditText iperf3EtInterval; - private EditText iperf3EtBytes; - private EditText iperf3EtStreams; - private EditText iperf3Cport; - private Button sendBtn; - private Button instancesBtn; - private Spinner protocolSpinner; - private Spinner iperf3ModeSpinner; - private Iperf3RunResultDao iperf3RunResultDao; - private LinearProgressIndicator progressIndicator; - private int[] failedColors; - private int[] runningColors; - private int[] succesColors; - private LinkedList editTexts; - private String rawIperf3file; - private String logFileDir; - private String logFileName; - private View v; - private SharedPreferencesGrouper spg; - private Iperf3Input input; - private WorkManager iperf3WM; - private Iperf3ResultsDataBase db; - private ArrayList uids; - private Context ct; - private final Runnable progressbarUpdate = new Runnable() { - @Override - public void run() { - progressIndicator.setVisibility(LinearProgressIndicator.INVISIBLE); - progressIndicator.setIndicatorColor(runningColors); - } - }; - - @Override - public void onPause() { - super.onPause(); - } - - @Override - public void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - this.input = new Iperf3Input(); - this.db = Iperf3ResultsDataBase.getDatabase(getActivity().getApplicationContext()); - this.uids = new ArrayList<>(this.db.iperf3RunResultDao().getIDs()); - this.iperf3WM = WorkManager.getInstance(getActivity().getApplicationContext()); - this.logFileDir = - Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS) - .getAbsolutePath() + "/omnt/iperf3RawLogs/"; - this.iperf3RunResultDao = db.iperf3RunResultDao(); - File iperf3Path = new File(this.logFileDir); - if (!iperf3Path.exists()) { - iperf3Path.mkdir(); - } - this.ct = requireContext(); - this.spg = SharedPreferencesGrouper.getInstance(this.ct); - } - - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - - - NavController navController = NavHostFragment.findNavController(this); - MutableLiveData liveData = navController.getCurrentBackStackEntry() - .getSavedStateHandle() - .getLiveData("uid"); - - - - liveData.observe(getViewLifecycleOwner(), new Observer() { - @Override - public void onChanged(String s) { - Iperf3RunResult iperf3RunResult = db.iperf3RunResultDao().getRunResult(s); - - iperf3EtIp.setText(iperf3RunResult.input.iperf3IP); - iperf3EtPort.setText(iperf3RunResult.input.iperf3Port); - iperf3EtBandwidth.setText(iperf3RunResult.input.iperf3Bandwidth); - iperf3EtDuration.setText(iperf3RunResult.input.iperf3Duration); - iperf3EtInterval.setText(iperf3RunResult.input.iperf3Interval); - iperf3EtBytes.setText(iperf3RunResult.input.iperf3Bytes); - iperf3Cport.setText(iperf3RunResult.input.iperf3Cport); - - iperf3Reverse.setChecked(iperf3RunResult.input.iperf3Reverse); - iperf3BiDir.setChecked(iperf3RunResult.input.iperf3BiDir); - iperf3OneOff.setChecked(iperf3RunResult.input.iperf3OneOff); - protocolSpinner.setSelection(iperf3RunResult.input.iperf3IdxProtocol); - iperf3ModeSpinner.setSelection(iperf3RunResult.input.iperf3IdxMode); - - - } - }); - } - - - private void saveTextInputToSharedPreferences(EditText field, String name) { - field.addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { - - } - - @Override - public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { - spg.getSharedPreference(SPType.iperf3_sp).edit().putString(name, field.getText().toString()).apply(); - } - - @Override - public void afterTextChanged(Editable editable) { - - } - }); - - } - - - - private void saveCheckboxInputToSharedPreferences(CheckBox box, String name) { - box.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - spg.getSharedPreference(SPType.iperf3_sp).edit().putBoolean(name, box.isChecked()).apply(); - } - }); - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) { - v = inflater.inflate(R.layout.fragment_iperf3_input, parent, false); - iperf3EtIp = v.findViewById(R.id.iperf3_ip); - iperf3EtPort = v.findViewById(R.id.iperf3_port); - iperf3EtBandwidth = v.findViewById(R.id.iperf3_bandwidth); - iperf3EtDuration = v.findViewById(R.id.iperf3_duration); - - - - - iperf3EtInterval = v.findViewById(R.id.iperf3_interval); - iperf3EtBytes = v.findViewById(R.id.iperf3_bytes); - iperf3EtStreams = v.findViewById(R.id.iperf3_streams); - iperf3Cport = v.findViewById(R.id.iperf3_cport); - progressIndicator = v.findViewById(R.id.iperf3_progress); - - iperf3EtDuration.addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - iperf3EtBytes.setEnabled(s.length() <= 0); - } - - @Override - public void afterTextChanged(Editable s) { - - } - }); - - - iperf3EtBytes.addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - iperf3EtDuration.setEnabled(s.length() <= 0); - } - - @Override - public void afterTextChanged(Editable s) { - - } - }); - - saveTextInputToSharedPreferences(iperf3EtIp, IPERF3IP); - saveTextInputToSharedPreferences(iperf3EtPort, IPERF3PORT); - saveTextInputToSharedPreferences(iperf3EtBandwidth, IPERF3BANDWIDTH); - saveTextInputToSharedPreferences(iperf3EtDuration, IPERF3DURATION); - saveTextInputToSharedPreferences(iperf3EtInterval, IPERF3INTERVAL); - saveTextInputToSharedPreferences(iperf3EtBytes, IPERF3BYTES); - saveTextInputToSharedPreferences(iperf3EtStreams, IPERF3STREAMS); - saveTextInputToSharedPreferences(iperf3Cport, IPERF3CPORT); - - failedColors = new int[] {getContext().getColor(R.color.crimson), - getContext().getColor(R.color.crimson), getContext().getColor(R.color.crimson)}; - runningColors = new int[] {getContext().getColor(R.color.purple_500), - getContext().getColor(R.color.crimson), getContext().getColor(R.color.forestgreen)}; - succesColors = new int[] {getContext().getColor(R.color.forestgreen), - getContext().getColor(R.color.forestgreen), getContext().getColor(R.color.forestgreen)}; - - progressIndicator.setIndicatorColor(runningColors); - progressIndicator.setIndeterminateAnimationType( - LinearProgressIndicator.INDETERMINATE_ANIMATION_TYPE_CONTIGUOUS); - progressIndicator.setVisibility(LinearProgressIndicator.INVISIBLE); - - editTexts = new LinkedList<>(); - editTexts.add(iperf3EtIp); - editTexts.add(iperf3EtPort); - editTexts.add(iperf3EtBandwidth); - editTexts.add(iperf3EtDuration); - editTexts.add(iperf3EtInterval); - editTexts.add(iperf3EtBytes); - editTexts.add(iperf3EtStreams); - editTexts.add(iperf3Cport); - sendBtn = v.findViewById(R.id.iperf3_send); - instancesBtn = v.findViewById(R.id.iperf3_instances_button); - - sendBtn.setOnClickListener(this::executeIperfCommand); - instancesBtn.setOnClickListener(this::showInstances); - - iperf3BiDir = v.findViewById(R.id.iperf_bidir); - iperf3Reverse = v.findViewById(R.id.iperf3_reverse); - iperf3OneOff = v.findViewById(R.id.iperf3_one_off); - - saveCheckboxInputToSharedPreferences(iperf3BiDir, IPERF3BIDIR); - saveCheckboxInputToSharedPreferences(iperf3Reverse, IPERF3REVERSE); - saveCheckboxInputToSharedPreferences(iperf3OneOff, IPERF3ONEOFF); - - protocolSpinner = v.findViewById(R.id.iperf3_protocol_spinner); - ArrayAdapter adapter = - ArrayAdapter.createFromResource(getContext(), R.array.iperf_protocol, - R.layout.support_simple_spinner_dropdown_item); - adapter.setDropDownViewResource(R.layout.support_simple_spinner_dropdown_item); - protocolSpinner.setAdapter(adapter); - - iperf3ModeSpinner = v.findViewById(R.id.iperf3_mode_spinner); - ArrayAdapter mode_adapter = - ArrayAdapter.createFromResource(getContext(), R.array.iperf_mode, - R.layout.support_simple_spinner_dropdown_item); - adapter.setDropDownViewResource(R.layout.support_simple_spinner_dropdown_item); - iperf3ModeSpinner.setAdapter(mode_adapter); - - - getActivity().getSupportFragmentManager() - .setFragmentResultListener("input", getViewLifecycleOwner(), - new FragmentResultListener() { - @Override - public void onFragmentResult(@NonNull String requestKey, - @NonNull Bundle result) { - - Iperf3RunResult iperf3RunResult = - db.iperf3RunResultDao().getRunResult(result.getString("uid")); - String logFileName = iperf3RunResult.input.iperf3LogFileName.split("_")[0]; - if (logFileName.equals("iperf3")) { - logFileName = ""; - } - - iperf3EtIp.setText(iperf3RunResult.input.iperf3IP); - iperf3EtPort.setText(iperf3RunResult.input.iperf3Port); - iperf3EtBandwidth.setText(iperf3RunResult.input.iperf3Bandwidth); - iperf3EtDuration.setText(iperf3RunResult.input.iperf3Duration); - iperf3EtInterval.setText(iperf3RunResult.input.iperf3Interval); - iperf3EtBytes.setText(iperf3RunResult.input.iperf3Bytes); - iperf3EtStreams.setText(iperf3RunResult.input.streams); - iperf3Cport.setText(iperf3RunResult.input.iperf3Cport); - - iperf3Reverse.setChecked(iperf3RunResult.input.iperf3Reverse); - iperf3BiDir.setChecked(iperf3RunResult.input.iperf3BiDir); - iperf3OneOff.setChecked(iperf3RunResult.input.iperf3OneOff); - protocolSpinner.setSelection(iperf3RunResult.input.iperf3IdxProtocol); - iperf3ModeSpinner.setSelection(iperf3RunResult.input.iperf3IdxMode); - - writeToSP(); - } - }); - iperf3EtIp.setText(spg.getSharedPreference(SPType.iperf3_sp).getString(IPERF3IP, null)); - iperf3EtPort.setText(spg.getSharedPreference(SPType.iperf3_sp).getString(IPERF3PORT, null)); - iperf3EtBandwidth.setText(spg.getSharedPreference(SPType.iperf3_sp).getString(IPERF3BANDWIDTH, null)); - iperf3EtDuration.setText(spg.getSharedPreference(SPType.iperf3_sp).getString(IPERF3DURATION, null)); - iperf3EtInterval.setText(spg.getSharedPreference(SPType.iperf3_sp).getString(IPERF3INTERVAL, null)); - iperf3EtBytes.setText(spg.getSharedPreference(SPType.iperf3_sp).getString(IPERF3BYTES, null)); - iperf3EtStreams.setText(spg.getSharedPreference(SPType.iperf3_sp).getString(IPERF3STREAMS, null)); - iperf3Cport.setText(spg.getSharedPreference(SPType.iperf3_sp).getString(IPERF3CPORT, null)); - - iperf3BiDir.setChecked(spg.getSharedPreference(SPType.iperf3_sp).getBoolean(IPERF3BIDIR, false)); - iperf3Reverse.setChecked(spg.getSharedPreference(SPType.iperf3_sp).getBoolean(IPERF3REVERSE, false)); - iperf3OneOff.setChecked(spg.getSharedPreference(SPType.iperf3_sp).getBoolean(IPERF3ONEOFF, false)); - protocolSpinner.setSelection(spg.getSharedPreference(SPType.iperf3_sp).getInt(IPERF3IDXPROTOCOL, 0)); - iperf3ModeSpinner.setSelection(spg.getSharedPreference(SPType.iperf3_sp).getInt(IPERF3IDXMODE, 0)); - - - try { - Os.setenv("TMPDIR", String.valueOf(getActivity().getCacheDir()), true); - } catch (ErrnoException e) { - Log.d(TAG,e.toString()); - } - return v; - } - - public void showInstances(View view) { - Bundle bundle = new Bundle(); - bundle.putStringArrayList("iperf3List", uids); - - NavController navController; - - NavHostFragment navHostFragment = - (NavHostFragment) getActivity().getSupportFragmentManager() - .findFragmentById(R.id.fragmentContainerView); - navController = navHostFragment.getNavController(); - - navController.navigate(R.id.runners_list, bundle); - } - - private boolean isModeSpinnerClient() { - String status = iperf3ModeSpinner.getSelectedItem().toString(); - return status.equals("Client"); - } - - public void executeIperfCommand(View view) { - String[] command = parseInput().split(" "); - - String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).getAbsolutePath() + "/omnt/iperf3LP/"; - - if(input.iperf3Json){ - try { - Files.createDirectories(Paths.get(path)); - } catch (IOException e) { - Toast.makeText(requireContext(),"Could not create Dir files!", Toast.LENGTH_SHORT).show(); - } - } - - // create the log file; - - String iperf3WorkerID = input.uuid; - - input.iperf3LineProtocolFile = path + iperf3WorkerID + ".txt"; - Data.Builder iperf3Data = new Data.Builder(); - iperf3Data.putStringArray("commands", command); - iperf3Data.putString("iperf3WorkerID", iperf3WorkerID); - iperf3Data.putString("rawIperf3file", rawIperf3file); - iperf3Data.putString("iperf3LineProtocolFile", input.iperf3LineProtocolFile); - iperf3Data.putString("measurementName", input.measurementName); - iperf3Data.putString("ip", input.iperf3IP); - iperf3Data.putString("port", input.iperf3Port); - iperf3Data.putString("bandwidth", input.iperf3Bandwidth); - iperf3Data.putString("duration", input.iperf3Duration); - iperf3Data.putString("interval", input.iperf3Interval); - iperf3Data.putString("bytes", input.iperf3Bytes); - iperf3Data.putString("protocol", protocolSpinner.getSelectedItem().toString()); - iperf3Data.putBoolean("rev", input.iperf3Reverse); - iperf3Data.putBoolean("biDir", input.iperf3BiDir); - iperf3Data.putBoolean("oneOff", input.iperf3OneOff); - iperf3Data.putString("client", iperf3ModeSpinner.getSelectedItem().toString()); - iperf3Data.putString("timestamp", input.timestamp.toString()); - iperf3Data.putString("protocol", protocolSpinner.getSelectedItem().toString()); - iperf3Data.putString("cport", input.iperf3Cport); - - ListenableFuture> status = iperf3WM.getWorkInfosByTag("iperf3Run"); - -/* try { - for (WorkInfo workInfo : status.get()) { - if (workInfo.getState().equals(WorkInfo.State.RUNNING)) { - Toast.makeText(getContext(), "iperf3 Test is running!", Toast.LENGTH_SHORT) - .show(); - return; - } - } - } catch (ExecutionException | InterruptedException e) { - Log.d(TAG,e.toString()); -; - }*/ - - uids.add(0, iperf3WorkerID); - iperf3Data.putInt("notificationID", uids.size()); - - - OneTimeWorkRequest iperf3WR = - new OneTimeWorkRequest - .Builder(Iperf3Worker.class) - .setInputData(iperf3Data.build()) - .addTag("iperf3Run") - .addTag(iperf3WorkerID) - .build(); - OneTimeWorkRequest iperf3LP = - new OneTimeWorkRequest - .Builder(Iperf3ToLineProtocolWorker.class) - .setInputData(iperf3Data.build()) - .build(); - OneTimeWorkRequest iperf3UP = - new OneTimeWorkRequest - .Builder(Iperf3UploadWorker.class) - .setInputData(iperf3Data.build()) - .addTag("iperf3") - .build(); - - iperf3RunResultDao.insert( - new Iperf3RunResult(iperf3WorkerID, -100, false, input, input.timestamp)); - - - - if (spg.getSharedPreference(SPType.logging_sp).getBoolean("enable_influx", false) && input.iperf3Json) { - iperf3WM.beginWith(iperf3WR).then(iperf3LP).then(iperf3UP).enqueue(); - } else if(input.iperf3Json) { - iperf3WM.beginWith(iperf3WR).then(iperf3LP).enqueue(); - } else { - iperf3WM.beginWith(iperf3WR).enqueue(); - } - - - - Handler progressbarHandler = new Handler(Looper.myLooper()); - - iperf3WM.getWorkInfoByIdLiveData(iperf3WR.getId()).observeForever(workInfo -> { - int iperf3_result; - iperf3_result = workInfo.getOutputData().getInt("iperf3_result", -100); - if (workInfo.getState().equals(WorkInfo.State.CANCELLED)) { - iperf3_result = -1; - } - iperf3RunResultDao.updateResult(iperf3WorkerID, iperf3_result); - Log.d(TAG, "onChanged: iperf3_result: " + iperf3_result); - if (iperf3_result == -100) { - progressIndicator.setVisibility(LinearProgressIndicator.VISIBLE); - if (!isModeSpinnerClient()) { - progressbarHandler.postDelayed(progressbarUpdate, SHOW_PROGRESSBAR); - } - } else if (iperf3_result != 0) { - progressIndicator.setIndicatorColor(failedColors); - progressbarHandler.postDelayed(progressbarUpdate, SHOW_PROGRESSBAR); - - } else { - progressIndicator.setIndicatorColor(succesColors); - progressbarHandler.postDelayed(progressbarUpdate, SHOW_PROGRESSBAR); - } - - }); - iperf3WM.getWorkInfoByIdLiveData(iperf3UP.getId()).observeForever(workInfo -> { - boolean iperf3_upload; - iperf3_upload = workInfo.getOutputData().getBoolean("iperf3_upload", false); - Log.d(TAG, "onChanged: iperf3_upload: " + iperf3_upload); - iperf3RunResultDao.updateUpload(iperf3WorkerID, iperf3_upload); - }); - - - } - - private String getKeyFromId(String s, String value) { - String key = ""; - switch (s) { - case "iperf3_logfile": - key = "--logfile"; - input.measurementName = value; - break; - case "iperf3_streams": - key = "-P"; - input.streams = value; - break; - case "iperf3_ip": - key = "-c"; - input.iperf3IP = value; - break; - case "iperf3_port": - key = "-p"; - input.iperf3Port = value; - break; - case "iperf3_bandwidth": - key = "-b"; - input.iperf3Bandwidth = value; - break; - case "iperf3_duration": - key = "-t"; - input.iperf3Duration = value; - break; - case "iperf3_interval": - key = "-i"; - input.iperf3Interval = value; - break; - case "iperf3_bytes": - key = "-n"; - input.iperf3Bytes = value; - break; - case "iperf3_cport": - key = "--cport"; - input.iperf3Cport = value; - break; - } - return key; - } - - private String parseInput() { - List stb = new LinkedList<>(); - for (EditText et : editTexts) { - String value = et.getText().toString(); - if (!value.equals("")) { - String s = getResources().getResourceEntryName(et.getId()); - String key = getKeyFromId(s, value); - if (s.equals("iperf3_bandwidth")) { - value += "M"; - } - stb.add(key); - stb.add(value); - } - } - - String protocol = protocolSpinner.getSelectedItem().toString(); - if (!protocol.equals("TCP")) { - stb.add("--" + protocol.toLowerCase()); - } - input.iperf3IdxProtocol = protocolSpinner.getSelectedItemPosition(); - - input.timestamp = new Timestamp(System.currentTimeMillis()); - String iperf3TS = input.timestamp.toString().replace(" ", "_").replace(":", "_"); - - input.uuid = UUID.randomUUID().toString(); - - input.measurementName = "Iperf3"; - this.logFileName = String.format("iperf3_%s_%s.json", iperf3TS, input.uuid); - - input.iperf3LogFileName = this.logFileName; - this.rawIperf3file = this.logFileDir + this.logFileName; - input.iperf3rawIperf3file = this.rawIperf3file; - - stb.add("--logfile"); - stb.add(this.rawIperf3file); - - input.iperf3BiDir = false; - input.iperf3Reverse = false; - input.iperf3OneOff = false; - input.iperf3Json = true; - - if (!isModeSpinnerClient()) { - stb.add("-s"); - input.iperf3IdxMode = iperf3ModeSpinner.getSelectedItemPosition(); - } - if (iperf3BiDir.isChecked()) { - stb.add("--bidir"); - input.iperf3BiDir = true; - } - if (iperf3Reverse.isChecked()) { - stb.add("--reverse"); - input.iperf3Reverse = true; - } - if (iperf3OneOff.isChecked()) { - stb.add("--one-off"); - input.iperf3OneOff = true; - } - stb.add("--json-stream"); - - stb.add("--connect-timeout"); - stb.add("500"); - - - String joined = String.join(" ", stb); - - Log.d(TAG, "parseInput: joined command " + joined); - input.iperf3Command = joined; - - - return joined; - } - - @Override - public void onSaveInstanceState(@NonNull Bundle outState) { - super.onSaveInstanceState(outState); - } - - private void writeToSP() { - SharedPreferences.Editor editor = spg.getSharedPreference(SPType.iperf3_sp).edit(); - editor.putInt(IPERF3IDXPROTOCOL, protocolSpinner.getSelectedItemPosition()); - editor.putInt(IPERF3IDXMODE, iperf3ModeSpinner.getSelectedItemPosition()); - editor.putString(IPERF3IP, iperf3EtIp.getText().toString()); - editor.putString(IPERF3PORT, iperf3EtPort.getText().toString()); - editor.putString(IPERF3BANDWIDTH, iperf3EtBandwidth.getText().toString()); - editor.putString(IPERF3DURATION, iperf3EtDuration.getText().toString()); - editor.putString(IPERF3INTERVAL, iperf3EtInterval.getText().toString()); - editor.putString(IPERF3BYTES, iperf3EtBytes.getText().toString()); - editor.putString(IPERF3STREAMS, iperf3EtStreams.getText().toString()); - editor.putString(IPERF3CPORT, iperf3Cport.getText().toString()); - - editor.putBoolean(IPERF3BIDIR, iperf3BiDir.isChecked()); - editor.putBoolean(IPERF3REVERSE, iperf3Reverse.isChecked()); - editor.putBoolean(IPERF3ONEOFF, iperf3OneOff.isChecked()); - editor.apply(); - } - - @Override - public void onDestroy() { - super.onDestroy(); - if(this.isResumed()) - writeToSP(); - } - - - - public static class Iperf3Input { - public boolean iperf3BiDir; - public boolean iperf3Reverse; - public boolean iperf3Json; - public boolean iperf3OneOff; - public int iperf3IdxMode; - public int iperf3IdxProtocol; - public String uuid; - public String iperf3Command; - public String iperf3rawIperf3file; - public String iperf3LogFileName; - public String measurementName; - public String iperf3IP; - public String iperf3Port; - public String iperf3Bandwidth; - public String iperf3LineProtocolFile; - public String iperf3Duration; - public String iperf3Interval; - public String iperf3Bytes; - public Timestamp timestamp; - public String streams; - public String iperf3Cport; - private List getFields(){ - List fields = Arrays.asList(Iperf3Input.class.getDeclaredFields()); - fields.sort((o1, o2) -> { - return o1.toGenericString().compareTo(o2.toGenericString()); - }); - return fields; - } - private LinearLayout getTextView(String name, String value, Context ct){ - LinearLayout mainLL = new LinearLayout(ct); - mainLL.setOrientation(LinearLayout.HORIZONTAL); - - - LinearLayout.LayoutParams parameterLayoutName = new LinearLayout.LayoutParams( - 0, - ViewGroup.LayoutParams.WRAP_CONTENT); - parameterLayoutName.weight = 1F; - TextView parameterName = new TextView(ct); - parameterName.setTextIsSelectable(true); - parameterName.setText(String.format("%s", name)); - parameterName.setLayoutParams(parameterLayoutName); - TextView parameterValue = new TextView(ct); - parameterValue.setTextIsSelectable(true); - parameterValue.setText(String.format("%s", value)); - LinearLayout.LayoutParams parameterLayoutValue = new LinearLayout.LayoutParams( - 0, - ViewGroup.LayoutParams.WRAP_CONTENT); - parameterLayoutValue.weight = 3F; - parameterValue.setLayoutParams(parameterLayoutValue); - - mainLL.addView(parameterName); - mainLL.addView(parameterValue); - return mainLL; - } - private LinearLayout getTextViewValue(String key, String value, Context ct){ - LinearLayout mainLL = new LinearLayout(ct); - mainLL.setOrientation(LinearLayout.HORIZONTAL); - mainLL.setFocusable(false); - mainLL.setFocusedByDefault(false); - - TextView parameterValue = new TextView(ct); - - parameterValue.setTextIsSelectable(true); - parameterValue.setText(String.format("%s", value)); - LinearLayout.LayoutParams parameterLayoutValue = new LinearLayout.LayoutParams( - 0, - ViewGroup.LayoutParams.WRAP_CONTENT); - parameterValue.setPadding(5, 5, 5, 5); - parameterLayoutValue.setMargins(0, 0, 10, 10); - parameterLayoutValue.weight = 1F; - parameterValue.setLayoutParams(parameterLayoutValue); - - mainLL.addView(parameterValue); - return mainLL; - } - public LinearLayout getInputAsLinearLayoutKeyValue(LinearLayout mainLL, Context ct){ - mainLL.setOrientation(LinearLayout.VERTICAL); - LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( - 0, - ViewGroup.LayoutParams.WRAP_CONTENT); - layoutParams.weight = 8F; - mainLL.setLayoutParams(layoutParams); - String[] protocol = - ct.getResources().getStringArray(R.array.iperf_protocol); - String[] mode = ct.getResources().getStringArray(R.array.iperf_mode); - for(Field parameter: getFields()){ - try { - Object parameterValueObj = parameter.get(this); - if(parameterValueObj == null){ - continue; - } - - String parameterName = parameter.getName().replace("iperf3", ""); - if(parameterName.equals("measurementName") - || parameterName.equals("rawIperf3file") - || parameterName.equals("LogFileName") - || parameterName.equals("Command") - || parameterName.equals("LineProtocolFile")) continue; - - String parameterValue = parameter.get(this).toString(); - if(parameterValue.equals("false")){ - continue; - } - if(parameterName.equals("IdxProtocol")){ - parameterName = "Protocol"; - parameterValue = protocol[Integer.parseInt(parameterValue)]; - } - - if(parameterName.equals("IdxMode")){ - parameterName = "Mode"; - parameterValue = mode[Integer.parseInt(parameterValue)]; - } - mainLL.addView(getTextView( - parameterName, - parameterValue, - ct)); - - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - } - return mainLL; - } - - public LinearLayout getInputAsLinearLayoutValue(LinearLayout mainLL, Context ct){ - mainLL.setOrientation(LinearLayout.HORIZONTAL); - LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( - 0, - ViewGroup.LayoutParams.WRAP_CONTENT); - layoutParams.weight = 10F; - mainLL.setLayoutParams(layoutParams); - String[] protocol = - ct.getResources().getStringArray(R.array.iperf_protocol); - String[] mode = ct.getResources().getStringArray(R.array.iperf_mode); - for(Field parameter: getFields()){ - try { - Object parameterValueObj = parameter.get(this); - if(parameterValueObj == null){ - continue; - } - - String parameterName = parameter.getName().replace("iperf3", ""); - if(parameterName.equals("measurementName") - || parameterName.equals("rawIperf3file") - || parameterName.equals("LogFileName") - || parameterName.equals("Command") - || parameterName.equals("LineProtocolFile") - || parameterName.equals("timestamp") - || parameterName.equals("uuid")) continue; - - String parameterValue = parameter.get(this).toString(); - if(parameterValue.equals("false")){ - continue; - } - if(parameterName.equals("IdxProtocol")){ - parameterName = "Protocol"; - parameterValue = protocol[Integer.parseInt(parameterValue)]; - } - - if(parameterName.equals("IdxMode")){ - parameterName = "Mode"; - parameterValue = mode[Integer.parseInt(parameterValue)]; - } - - if(parameterValue.equals("true")){ - parameterValue = parameterName; - } - - mainLL.addView(getTextViewValue( - parameterName, - parameterValue, - ct)); - - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - } - return mainLL; - } - } -} \ No newline at end of file diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3Input.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3Input.java new file mode 100644 index 00000000..bfef1ea8 --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3Input.java @@ -0,0 +1,449 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3; + +import android.os.Environment; +import android.os.Parcel; +import android.os.Parcelable; +import android.widget.LinearLayout; + +import androidx.annotation.NonNull; +import androidx.work.Data; + + +import org.checkerframework.checker.units.qual.A; + +import java.lang.reflect.Field; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.StringJoiner; +import java.util.UUID; + + +public class Iperf3Input implements Parcelable { + public static final String[] EXCLUDED_FIELDS = { + "measurementName", "rawFile", "logFileName", "command", "lineProtocolFile", + "context", "timestamp", "uuid", "cardView", "main", "EXCLUDED_FIELDS" + }; + + + public static final String rootPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).getAbsolutePath(); + public static final String jsonDirPath = rootPath+"/omnt/iperf3/json/"; + public static final String lineProtocolDirPath = rootPath+"/omnt/iperf3/lineprotocol/"; + + public static final String IPERF3IP = "iperf3IP"; + public static final String IPERF3PORT = "iperf3Port"; + public static final String IPERF3BANDWIDTH = "iperf3Bandwidth"; + public static final String IPERF3DURATION = "iperf3Duration"; + public static final String IPERF3INTERVAL = "iperf3Interval"; + public static final String IPERF3BYTES = "iperf3Bytes"; + public static final String IPERF3STREAMS = "iperf3Streams"; + public static final String IPERF3DIRECTION = "iperf3Direction"; + public static final String IPERF3ONEOFF = "iperf3OneOff"; + public static final String IPERF3PROTOCOL = "iperf3IdxProtocol"; + public static final String IPERF3MODE = "iperf3IdxMode"; + public static final String IPERF3CPORT = "iperf3cport"; + public static final String IPERF3UUID = "iperf3UUID"; + public static final String IPERF3TIMESTAMP = "iperf3Timestamp"; + + + protected Iperf3Input(Parcel in) { + isJson = in.readBoolean(); + isOneOff = in.readBoolean(); + mode = Iperf3Mode.valueOf(in.readString()); + protocol = Iperf3Protocol.valueOf(in.readString()); + direction = Iperf3Direction.valueOf(in.readString()); + rawFile = in.readString(); + ip = in.readString(); + port = in.readString(); + bandwidth = in.readString(); + duration = in.readString(); + interval = in.readString(); + bytes = in.readString(); + streams = in.readString(); + cport = in.readString(); + uuid = in.readString(); + logFileName = in.readString(); + measurementName = in.readString(); + lineProtocolFile = in.readString(); + timestamp = (Timestamp) in.readSerializable(); + } + + public static final Creator CREATOR = new Creator<>() { + @Override + public Iperf3Input createFromParcel(Parcel in) { + return new Iperf3Input(in); + } + + @Override + public Iperf3Input[] newArray(int size) { + return new Iperf3Input[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel parcel, int i) { + parcel.writeBoolean(isJson); + parcel.writeBoolean(isOneOff); + parcel.writeString(mode.toString()); + parcel.writeString(protocol.toString()); + parcel.writeString(direction.toString()); + parcel.writeString(rawFile); + parcel.writeString(ip); + parcel.writeString(port); + parcel.writeString(bandwidth); + parcel.writeString(duration); + parcel.writeString(interval); + parcel.writeString(bytes); + parcel.writeString(streams); + parcel.writeString(cport); + parcel.writeString(uuid); + parcel.writeString(logFileName); + parcel.writeString(measurementName); + parcel.writeString(lineProtocolFile); + parcel.writeSerializable(timestamp); + } + + public boolean isValid(){ + return !ip.isEmpty(); + } + + public enum Iperf3Mode { + CLIENT, + SERVER, + UNDEFINED; + public String toPrettyPrint() { + return this.name().substring(0, 1).toUpperCase() + this.name().toLowerCase().substring(1); + } + } + + public enum Iperf3Protocol { + TCP, + UDP, + UNDEFINED + } + + public enum Iperf3Direction { + UP, + DOWN, + BIDIR, + UNDEFINED; + public String toPrettyPrint() { + return this.name().toLowerCase(); + } + } + + private boolean isJson; + private boolean isOneOff; + private Iperf3Mode mode = Iperf3Mode.UNDEFINED; + private Iperf3Protocol protocol = Iperf3Protocol.UNDEFINED; + private Iperf3Direction direction = Iperf3Direction.UNDEFINED; + private String rawFile; + private String ip; + private String port; + private String bandwidth; + private String duration; + private String interval; + private String bytes; + private String streams; + private String cport; + + private String uuid; + private String logFileName; + private String measurementName; + private String lineProtocolFile; + private Timestamp timestamp; + + + public Iperf3Input() { + this.isJson = false; + this.isOneOff = false; + //if(uuid == null) this.uuid = UUID.randomUUID().toString(); + this.uuid = ""; + this.rawFile = jsonDirPath+this.uuid+".json";; + this.logFileName = ""; + this.measurementName = ""; + this.ip = ""; + this.port = ""; + this.bandwidth = ""; + this.lineProtocolFile = lineProtocolDirPath+this.uuid+".txt"; + this.duration = ""; + this.interval = ""; + this.bytes = ""; + this.timestamp = new Timestamp(System.currentTimeMillis()); + this.streams = ""; + this.cport = ""; + } + + public void setMode(Iperf3Mode mode) { + this.mode = mode; + } + + public void setJson(boolean json) { + this.isJson = json; + } + + public void setOneOff(boolean oneOff) { + this.isOneOff = oneOff; + } + + public void setDirection(Iperf3Direction direction) { + this.direction = direction; + } + + public void setProtocol(Iperf3Protocol protocol) { + this.protocol = protocol; + } + + public Iperf3Direction getDirection() { + return direction; + } + + + public Iperf3Protocol getProtocol() { + return protocol; + } + + public Iperf3Mode getMode() { + return mode; + } + + + public void setUuid(String uuid) { + this.uuid = uuid; + this.rawFile = jsonDirPath+this.uuid+".json"; + this.lineProtocolFile = lineProtocolDirPath+this.uuid+".txt"; + } + + + public void setRawFile(String rawFile) { + this.rawFile = rawFile; + } + + public void setLogFileName(String logFileName) { + this.logFileName = logFileName; + } + + public void setMeasurementName(String measurementName) { + this.measurementName = measurementName; + } + + public void setIp(String ip) { + this.ip = ip; + } + + public void setPort(String port) { + this.port = port; + } + + public void setBandwidth(String bandwidth) { + this.bandwidth = bandwidth; + } + + public void setLineProtocolFile(String lineProtocolFile) { + this.lineProtocolFile = lineProtocolFile; + } + + public void setDuration(String duration) { + this.duration = duration; + } + + public void setInterval(String interval) { + this.interval = interval; + } + + public void setBytes(String bytes) { + this.bytes = bytes; + } + + public void setTimestamp(Timestamp timestamp) { + this.timestamp = timestamp; + } + + public void setStreams(String streams) { + this.streams = streams; + } + + public void setCport(String cport) { + this.cport = cport; + } + + + public boolean isJson() { + return isJson; + } + + public boolean isOneOff() { + return isOneOff; + } + + public String getUuid() { + return uuid; + } + + public String getRawFile() { + return rawFile; + } + + public String getLogFileName() { + return logFileName; + } + + public String getMeasurementName() { + return measurementName; + } + + public String getIp() { + return ip; + } + + public String getPort() { + return port; + } + + public String getBandwidth() { + return bandwidth; + } + + public String getLineProtocolFile() { + return lineProtocolFile; + } + + public String getDuration() { + return duration; + } + + public String getInterval() { + return interval; + } + + public String getBytes() { + return bytes; + } + + public Timestamp getTimestamp() { + return timestamp; + } + + public String getStreams() { + return streams; + } + + public String getCport() { + return cport; + } + + public List getFields() { + List fields = Arrays.asList(Iperf3Input.class.getDeclaredFields()); + fields.sort((o1, o2) -> o1.toGenericString().compareTo(o2.toGenericString())); + return fields; + } + + + public Data.Builder getInputAsDataBuilder() { + Data.Builder data = new Data.Builder(); + for (Field parameter : getFields()) { + try { + Object parameterValueObj = parameter.get(this); + if (parameterValueObj == null) { + continue; + } + + String parameterName = parameter.getName().replace("iperf3", ""); + if (Arrays.asList(EXCLUDED_FIELDS).contains(parameterName)) continue; + + String parameterValue = parameter.get(this).toString(); + if (parameterValue.equals("false") || parameterValue.isEmpty()) { + continue; + } + + data.putString(parameterName, parameterValue); + + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + data.putStringArray("command", getInputAsCommand()); + data.putString("uuid", uuid); + return data; + } + + public String[] getInputAsCommand(){ + ArrayList command = new ArrayList<>(); + //command.add("iperf3"); + switch (mode) { + case CLIENT: + command.add("-c"); + if(!ip.isEmpty()) command.add(ip); + break; + case SERVER: + command.add("-s"); + break; + } + if(port != null && !port.isEmpty()){ + command.add("-p"); + command.add(port); + } + if(bandwidth != null && !bandwidth.isEmpty()){ + command.add("-b"); + command.add(bandwidth); + } + if(duration != null && !duration.isEmpty()){ + command.add("-t"); + command.add(duration); + } + if(interval != null && !interval.isEmpty()){ + command.add("-i"); + command.add(interval); + } + if(bytes != null && !bytes.isEmpty()){ + command.add("-n"); + command.add(bytes); + } + if(streams != null && !streams.isEmpty()){ + command.add("-P"); + command.add(streams); + } + if(cport != null && !cport.isEmpty()){ + command.add("-B"); + command.add(cport); + } + + switch (direction){ + case DOWN: + command.add("--reverse"); + break; + case BIDIR: + command.add("--bidir"); + break; + case UP: + break; + } + + switch (protocol){ + case UDP: + command.add("-u"); + break; + case TCP: + break; + } + + command.add("--logfile"); + command.add(rawFile); + command.add("--json-stream"); + command.add("--connect-timeout"); + command.add("500"); + return command.toArray(new String[0]); + } + + + + + + +} \ No newline at end of file diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3LibLoader.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3LibLoader.java index c8d20e25..96075272 100644 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3LibLoader.java +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3LibLoader.java @@ -27,7 +27,7 @@ public class Iperf3LibLoader { "iperf3.17.1" ); - protected static synchronized void load() { + public static synchronized void load() { if (done) { return; } diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3Parser.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3Parser.java index 781ade6b..4487fcdc 100644 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3Parser.java +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3Parser.java @@ -1,5 +1,12 @@ package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3; +import android.content.Context; +import android.os.FileObserver; +import android.util.Log; + +import androidx.annotation.Nullable; + +import org.json.JSONException; import org.json.JSONObject; import java.beans.PropertyChangeListener; @@ -8,68 +15,110 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; +import java.io.IOException; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.Converter.IntervalsConverter; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.Iperf3RunResult; import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Error; import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Interval; import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.start.Start; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.Iperf3ResultsDataBase; public class Iperf3Parser { - + private static final String TAG = "Iperf3Parser"; private final String pathToFile; private final File file; private BufferedReader br = null; private PropertyChangeSupport support; private Start start; private final Intervals intervals = new Intervals(); - Iperf3Parser(String pathToFile) { + private Iperf3ResultsDataBase db; + private Context context; + private Iperf3Input iperf3Input; + private FileObserver fileObserver; + public Iperf3Parser(Context context, String pathToFile, Iperf3Input iperf3Input) { + this.context = context; this.pathToFile = pathToFile; this.file = new File(this.pathToFile); - try { - br = new BufferedReader(new FileReader(file)); - } catch (FileNotFoundException ex) { - System.out.println("File not found"); - return; - } this.support = new PropertyChangeSupport(this); + this.db = Iperf3ResultsDataBase.getDatabase(this.context); + this.iperf3Input = iperf3Input; + this.fileObserver = null; } + + public void parse(){ - String line; - try { - while ((line = br.readLine()) != null) { - JSONObject obj = new JSONObject(line); - String event = obj.getString("event"); - switch (event) { - case "start": - start = new Start(); - JSONObject startData = obj.getJSONObject("data"); - start.parseStart(startData); - break; - case "interval": - Interval interval = new Interval(); - JSONObject intervalData = obj.getJSONObject("data"); - interval.parse(intervalData); - support.firePropertyChange("interval", null, interval); - intervals.addInterval(interval); - break; - case "end": - System.out.println("End"); - break; - case "error": - Error error = new Error(); - String errorString = obj.getString("data"); - error.parse(errorString); - support.firePropertyChange("error", null, error); + Log.i(TAG, "Parsing file"); + + + fileObserver = new FileObserver(new File(pathToFile), + FileObserver.ALL_EVENTS) { + @Override + public void onEvent(int i, @Nullable String s) { + switch (i){ + case FileObserver.CREATE: + Log.i(TAG, "onEvent: File created by iPerf3"); break; - default: - System.out.println("Unknown event"); + case FileObserver.MODIFY: + Log.i(TAG, "onEvent: File modified by iPerf3"); + + try { + br = new BufferedReader(new FileReader(file)); + } catch (FileNotFoundException e) { + Log.e(TAG, "onEvent: File not found!"); + } + String line; + try { + while ((line = br.readLine()) != null) { + JSONObject obj = new JSONObject(line); + String event = obj.getString("event"); + switch (event) { + case "start": + start = new Start(); + JSONObject startData = obj.getJSONObject("data"); + start.parseStart(startData); + break; + case "interval": + Interval interval = new Interval(); + JSONObject intervalData = obj.getJSONObject("data"); + interval.parse(intervalData); + support.firePropertyChange("interval", null, interval); + intervals.addInterval(interval); + db.iperf3RunResultDao().updateIntervals(iperf3Input.getUuid(), intervals.getIntervalArrayList()); + Log.d(TAG, "parse: interval added to db for "+iperf3Input.getUuid()); + break; + case "end": + System.out.println("End"); + break; + case "error": + Error error = new Error(); + String errorString = obj.getString("data"); + error.parse(errorString); + support.firePropertyChange("error", null, error); + break; + default:; + System.out.println("Unknown event"); + break; + } + } + } catch (JSONException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } + + this.stopWatching(); + break; } } - } catch (Exception e) { - System.out.println("Error reading file"); - } + }; + fileObserver.startWatching(); + + + } public Intervals getIntervals() { diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3RecyclerViewAdapter.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3RecyclerViewAdapter.java index 0ab33dce..1c6694db 100644 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3RecyclerViewAdapter.java +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3RecyclerViewAdapter.java @@ -9,7 +9,10 @@ package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3; import android.annotation.SuppressLint; +import android.content.BroadcastReceiver; import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.res.Configuration; import android.os.Bundle; @@ -23,21 +26,30 @@ import android.widget.Toast; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.cardview.widget.CardView; import androidx.core.content.ContextCompat; import androidx.fragment.app.FragmentActivity; -import androidx.preference.PreferenceManager; +import androidx.lifecycle.LiveData; +import androidx.lifecycle.Observer; import androidx.recyclerview.widget.RecyclerView; import androidx.work.Data; import androidx.work.OneTimeWorkRequest; import androidx.work.WorkManager; import com.google.android.material.floatingactionbutton.FloatingActionButton; +import com.google.android.material.progressindicator.LinearProgressIndicator; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Fragments.Output.Iperf3LogFragment; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Interval; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Worker.Iperf3UploadWorker; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.Iperf3ResultsDataBase; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.Iperf3RunResult; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.Iperf3RunResultDao; import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Preferences.SPType; import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Preferences.SharedPreferencesGrouper; import de.fraunhofer.fokus.OpenMobileNetworkToolkit.R; @@ -46,18 +58,20 @@ public class Iperf3RecyclerViewAdapter extends RecyclerView.Adapter { private final String TAG = "Iperf3RecyclerViewAdapter"; private final Iperf3ResultsDataBase db; - private final ArrayList uids; + private ArrayList uids; private Context context; - private final FragmentActivity c; + private FragmentActivity c; private final HashMap selectedRuns; private final HashMap selectedCardViews; private final FloatingActionButton uploadBtn; + private BroadcastReceiver receiver; public Iperf3RecyclerViewAdapter(FragmentActivity c, ArrayList uids, FloatingActionButton uploadBtn) { this.c = c; + if(uids == null) uids = new ArrayList<>(); this.uids = uids; - this.db = Iperf3ResultsDataBase.getDatabase(context); + this.db = Iperf3ResultsDataBase.getDatabase(this.c.getApplicationContext()); this.selectedRuns = new HashMap<>(); this.selectedCardViews = new HashMap<>(); this.uploadBtn = uploadBtn; @@ -83,7 +97,7 @@ public void onClick(View view) { Iperf3RunResult runResult = iperf3RunResultDao.getRunResult(uid); Data.Builder data = new Data.Builder(); - data.putString("iperf3LineProtocolFile", runResult.input.iperf3LineProtocolFile); + data.putString("iperf3LineProtocolFile", runResult.input.getLineProtocolFile()); OneTimeWorkRequest iperf3UP = new OneTimeWorkRequest.Builder(Iperf3UploadWorker.class) .setInputData(data.build()) @@ -109,6 +123,19 @@ public void onClick(View view) { } }); + for(String uid: uids){ + LiveData liveData = db.iperf3RunResultDao().getIntervals(uid); + Observer observer = new Observer() { + @Override + public void onChanged(Intervals intervals) { + notifyDataSetChanged(); + } + }; + liveData.observe(c, observer); + } + + + } @@ -131,6 +158,52 @@ public boolean isNightMode(Context context) { return nightModeFlags == Configuration.UI_MODE_NIGHT_YES; } + private TextView createTextView(Context ct, String text, float weight) { + TextView textView = new TextView(ct); + textView.setText(text); + LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT); + layoutParams.weight = weight; + textView.setLayoutParams(layoutParams); + return textView; + } + + private LinearLayout getTextViewValue(String key, String value, Context ct) { + LinearLayout mainLL = new LinearLayout(ct); + mainLL.setOrientation(LinearLayout.HORIZONTAL); + mainLL.setFocusable(false); + mainLL.setFocusedByDefault(false); + + TextView parameterValue = createTextView(ct, value, 1F); + parameterValue.setTextIsSelectable(true); + parameterValue.setPadding(5, 5, 5, 5); + LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) parameterValue.getLayoutParams(); + layoutParams.setMargins(0, 0, 10, 10); + + mainLL.addView(parameterValue); + return mainLL; + } + + public LinearLayout getInputAsLinearLayoutValue(LinearLayout mainLL, Context ct, Iperf3Input input) { + mainLL.setOrientation(LinearLayout.HORIZONTAL); + LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( + 0, + ViewGroup.LayoutParams.WRAP_CONTENT); + layoutParams.weight = 10F; + mainLL.setLayoutParams(layoutParams); + + mainLL.addView(getTextViewValue(Iperf3Input.IPERF3IP.replace("iperf3", ""), input.getIp(), ct)); + mainLL.addView(getTextViewValue(Iperf3Input.IPERF3PORT.replace("iperf3", ""), input.getPort(), ct)); + mainLL.addView(getTextViewValue(Iperf3Input.IPERF3PROTOCOL.replace("iperf3", ""), input.getProtocol().toString(), ct)); + mainLL.addView(getTextViewValue(Iperf3Input.IPERF3MODE.replace("iperf3", ""), input.getMode().toPrettyPrint(), ct)); + mainLL.addView(getTextViewValue(Iperf3Input.IPERF3DIRECTION.replace("iperf3", ""), input.getDirection().toPrettyPrint(), ct)); + mainLL.addView(getTextViewValue(Iperf3Input.IPERF3BANDWIDTH.replace("iperf3", ""), input.getBandwidth(), ct)); + mainLL.addView(getTextViewValue(Iperf3Input.IPERF3DURATION.replace("iperf3", ""), input.getDuration(), ct)); + + + return mainLL; + } + + @Override public void onBindViewHolder(@NonNull ViewHolder holder, int position) { holder.iPerf3Parameters.removeAllViews(); @@ -149,12 +222,29 @@ public void onBindViewHolder(@NonNull ViewHolder holder, int position) { } holder.measurement.setText("iPerf3"); - holder.timestamp.setText(test.input.timestamp.toString()); + holder.timestamp.setText(test.input.getTimestamp().toString()); holder.runIcon.setImageDrawable(Iperf3Utils.getDrawableResult(context, test.result)); holder.uploadIcon.setImageDrawable(Iperf3Utils.getDrawableUpload(context, test.result, test.uploaded)); - holder.iPerf3Parameters = test.input.getInputAsLinearLayoutValue(holder.iPerf3Parameters, context); + holder.iPerf3Parameters = getInputAsLinearLayoutValue(holder.iPerf3Parameters, context, test.input); + IntentFilter filter = new IntentFilter(context.getPackageName() + ".broadcast.iperf3.INTERVAL"); + + + + Iperf3RunResult iperf3RunResult = db.iperf3RunResultDao().getRunResult(this.uids.get(position)); + String duration = iperf3RunResult.input.getDuration(); + if(duration == null || duration.equals("")) duration = "10"; + int progress = 0; + try { + progress = (int) iperf3RunResult.intervals.get(iperf3RunResult.intervals.size()-1).getSum().getEnd(); + } catch (Exception e) {} + holder.linearProgressIndicator.setMax(Integer.parseInt(duration)); + holder.linearProgressIndicator.setProgress(progress); + + + this.c.registerReceiver(holder.broadcastReceiver, filter, Context.RECEIVER_NOT_EXPORTED); } + private Iperf3RunResult getItemByPosition(int position) { return this.db.iperf3RunResultDao().getRunResult(this.uids.get(position)); } @@ -172,6 +262,13 @@ public class ViewHolder extends RecyclerView.ViewHolder { public ImageView uploadIcon; private final LinearLayout linearLayout; private LinearLayout iPerf3Parameters; + private String uid; + private LinearProgressIndicator linearProgressIndicator; + private BroadcastReceiver broadcastReceiver; + + public LinearLayout getLinearLayout() { + return linearLayout; + } private LinearLayout firstRow(LinearLayout ll){ measurement.setLayoutParams( @@ -206,9 +303,19 @@ private LinearLayout thirdRow(LinearLayout ll){ return ll; } + + private LinearLayout fourthRow(LinearLayout ll){ + ll.setOrientation(LinearLayout.HORIZONTAL); + linearProgressIndicator = new LinearProgressIndicator(context); + linearProgressIndicator.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 40)); + ll.addView(linearProgressIndicator); + + + return ll; + } + public ViewHolder(View itemView) { super(itemView); - Log.d(TAG, "ViewHolder: " + itemView); measurement = new TextView(context); timestamp = new TextView(context); iperf3State = new TextView(context); @@ -223,6 +330,8 @@ public ViewHolder(View itemView) { linearLayout.addView(firstRow(new LinearLayout(context))); linearLayout.addView(secondRow(new LinearLayout(context))); linearLayout.addView(thirdRow(new LinearLayout(context))); + linearLayout.addView(fourthRow(new LinearLayout(context))); + itemView.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { @@ -265,13 +374,15 @@ public void onClick(View v) { bundle.putString("uid", uid); Iperf3LogFragment test = new Iperf3LogFragment(); test.setArguments(bundle); + c.getSupportFragmentManager().beginTransaction() .replace(R.id.fragmentContainerView, test, "iperf3LogFragment") .addToBackStack("findThisFragment").commit(); } }); - + int itemPos = getLayoutPosition(); + if(uids.contains(itemPos)) uid = uids.get(getLayoutPosition()); } } diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3ResultsDataBase.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3ResultsDataBase.java deleted file mode 100644 index d9b01a29..00000000 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3ResultsDataBase.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2023 Peter Hasse - * SPDX-FileCopyrightText: 2023 Johann Hackler - * SPDX-FileCopyrightText: 2023 Fraunhofer FOKUS - * - * SPDX-License-Identifier: BSD-3-Clause-Clear - */ - -package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3; - -import android.content.Context; - -import androidx.room.Database; -import androidx.room.Room; -import androidx.room.RoomDatabase; - -@Database( - entities = {Iperf3RunResult.class}, - version = 3 -) -public abstract class Iperf3ResultsDataBase extends RoomDatabase { - private static volatile Iperf3ResultsDataBase INSTANCE; - - static Iperf3ResultsDataBase getDatabase(final Context context) { - if (INSTANCE == null) { - synchronized (Iperf3ResultsDataBase.class) { - if (INSTANCE == null) { - - INSTANCE = Room.databaseBuilder(context.getApplicationContext(), - Iperf3ResultsDataBase.class, "iperf3_result_database") - .addTypeConverter(new Iperf3InputConverter()) - .allowMainThreadQueries() - .build(); - } - } - } - return INSTANCE; - } - - public abstract Iperf3RunResultDao iperf3RunResultDao(); -} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3Service.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3Service.java new file mode 100644 index 00000000..a1a2d0da --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3Service.java @@ -0,0 +1,115 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3; + +import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE; + +import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.app.Service; +import android.content.Intent; +import android.os.Build; +import android.os.FileObserver; +import android.os.IBinder; +import android.util.Log; +import android.widget.Toast; + +import androidx.annotation.Nullable; +import androidx.core.app.NotificationCompat; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.HashMap; + +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.R; + +public class Iperf3Service extends Service { + public final static int FOREGROUND_SERVICE_TYPE = FOREGROUND_SERVICE_TYPE_SPECIAL_USE; + public final static int NOTIFICATION_ID = 1002; + private static final String CHANNEL_ID = "Iperf3ServiceChannel"; + private static final String TAG = "Iperf3Service"; + private ArrayList parsing = new ArrayList<>(); + private FileObserver fileObserver; + + @Override + public void onCreate() { + super.onCreate(); + createNotificationChannel(); + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + if(intent == null){ + Toast.makeText(getApplicationContext(),"No intent!", Toast.LENGTH_SHORT).show(); + return START_NOT_STICKY; + } + Iperf3Input iperf3Input = intent.getParcelableExtra("input"); + + if(iperf3Input == null){ + Toast.makeText(getApplicationContext(),"No input data!", Toast.LENGTH_SHORT).show(); + return START_NOT_STICKY; + } + Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID) + .setContentTitle("iPerf3 Service") + .setContentText("no active test") + .setSmallIcon(R.drawable.outline_speed_24) + .build(); + + + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) { + startForeground(NOTIFICATION_ID, notification); + } else { + startForeground(NOTIFICATION_ID, notification, FOREGROUND_SERVICE_TYPE_SPECIAL_USE); + } + try{ + Files.createDirectories(Paths.get(Iperf3Input.jsonDirPath)); + Files.createDirectories(Paths.get(Iperf3Input.lineProtocolDirPath)); + } catch (IOException e){ + Toast.makeText(getApplicationContext(),"Could not create Dir files!", Toast.LENGTH_SHORT).show(); + } + + Iperf3Executor iperf3Executor = new Iperf3Executor(getApplicationContext(), iperf3Input); + iperf3Executor.start(); + + fileObserver = new FileObserver(new File(Iperf3Input.jsonDirPath), + FileObserver.ALL_EVENTS) { + @Override + public void onEvent(int i, @Nullable String s) { + Log.i(TAG, "onEvent: " + i + " " + s); + switch (i){ + case FileObserver.MODIFY: + Log.i(TAG, "onEvent: File modified by iPerf3"); + Iperf3Parser iperf3Parser = new Iperf3Parser(getApplicationContext(), iperf3Input.getRawFile(), iperf3Input); + iperf3Parser.parse(); + break; + } + } + }; + fileObserver.startWatching(); + + return START_STICKY; + } + + @Nullable + @Override + public IBinder onBind(Intent intent) { + return null; + } + + private void createNotificationChannel() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + NotificationChannel serviceChannel = new NotificationChannel( + CHANNEL_ID, + "Iperf3 Service Channel", + NotificationManager.IMPORTANCE_HIGH + ); + + NotificationManager manager = getSystemService(NotificationManager.class); + if (manager != null) { + manager.createNotificationChannel(serviceChannel); + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Interval.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Interval.java index 47d51b1a..26309c9b 100644 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Interval.java +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Interval.java @@ -2,6 +2,11 @@ import static de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.SUM_TYPE.*; +import android.os.Parcel; +import android.os.Parcelable; + +import androidx.annotation.NonNull; + import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams.STREAM_TYPE; import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.SUM_TYPE; import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.Sum; @@ -17,7 +22,7 @@ import org.json.JSONException; import org.json.JSONObject; -public class Interval { +public class Interval implements Parcelable{ private final Streams streams; private Sum sum; public Sum sumBidirReverse; @@ -26,6 +31,24 @@ public Interval(){ streams = new Streams(); } + protected Interval(Parcel in) { + streams = in.readParcelable(Streams.class.getClassLoader()); + sum = in.readParcelable(Sum.class.getClassLoader()); + sumBidirReverse = in.readParcelable(Sum.class.getClassLoader()); + } + + public static final Creator CREATOR = new Creator() { + @Override + public Interval createFromParcel(Parcel in) { + return new Interval(in); + } + + @Override + public Interval[] newArray(int size) { + return new Interval[size]; + } + }; + private SUM_TYPE getSumType(JSONObject data) throws JSONException { boolean sender = data.getBoolean("sender"); if(sender){ @@ -76,4 +99,16 @@ public Sum getSum() { public Sum getSumBidirReverse() { return sumBidirReverse; } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel parcel, int i) { + parcel.writeParcelable(streams, i); + parcel.writeParcelable(sum, i); + parcel.writeParcelable(sumBidirReverse, i); + } } diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Streams/Stream.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Streams/Stream.java index 9ec8dba1..dfcd48c2 100644 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Streams/Stream.java +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Streams/Stream.java @@ -1,9 +1,14 @@ package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams; +import android.os.Parcel; +import android.os.Parcelable; + +import androidx.annotation.NonNull; + import org.json.JSONException; import org.json.JSONObject; -public class Stream { +public class Stream implements Parcelable { private int socket; private int start; private double end; @@ -17,6 +22,30 @@ public class Stream { public Stream(){ } + + protected Stream(Parcel in) { + socket = in.readInt(); + start = in.readInt(); + end = in.readDouble(); + seconds = in.readDouble(); + bytes = in.readLong(); + bits_per_second = in.readDouble(); + omitted = in.readBoolean(); + sender = in.readBoolean(); + } + + public static final Creator CREATOR = new Creator() { + @Override + public Stream createFromParcel(Parcel in) { + return new Stream(in); + } + + @Override + public Stream[] newArray(int size) { + return new Stream[size]; + } + }; + public void parse(JSONObject data) throws JSONException { this.socket = data.getInt("socket"); this.start = data.getInt("start"); @@ -61,4 +90,21 @@ public void setStreamType( STREAM_TYPE streamType) { this.streamType = streamType; } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel parcel, int i) { + parcel.writeInt(socket); + parcel.writeInt(start); + parcel.writeDouble(end); + parcel.writeDouble(seconds); + parcel.writeLong(bytes); + parcel.writeDouble(bits_per_second); + parcel.writeBoolean(omitted); + parcel.writeBoolean(sender); + } } diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Streams/Streams.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Streams/Streams.java index 4a07cf84..3660a470 100644 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Streams/Streams.java +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Streams/Streams.java @@ -1,5 +1,10 @@ package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams; +import android.os.Parcel; +import android.os.Parcelable; + +import androidx.annotation.NonNull; + import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams.TCP.TCP_DL_STREAM; import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams.TCP.TCP_UL_STREAM; import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams.UDP.UDP_DL_STREAM; @@ -9,12 +14,28 @@ import org.json.JSONException; import org.json.JSONObject; -public class Streams { +public class Streams implements Parcelable { private final ArrayList streams; public Streams(){ this.streams = new ArrayList<>(); } + protected Streams(Parcel in) { + streams = in.createTypedArrayList(Stream.CREATOR); + } + + public static final Creator CREATOR = new Creator() { + @Override + public Streams createFromParcel(Parcel in) { + return new Streams(in); + } + + @Override + public Streams[] newArray(int size) { + return new Streams[size]; + } + }; + private STREAM_TYPE identifyStream(JSONObject data) throws JSONException { boolean sender = data.getBoolean("sender"); if(sender){ @@ -71,4 +92,14 @@ public void addStream(Stream stream){ public Stream getStream(int i) { return streams.get(i); } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel parcel, int i) { + parcel.writeTypedList(streams); + } } diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Streams/TCP/TCP_DL_STREAM.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Streams/TCP/TCP_DL_STREAM.java index 93e27705..328c3e1c 100644 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Streams/TCP/TCP_DL_STREAM.java +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Streams/TCP/TCP_DL_STREAM.java @@ -1,5 +1,7 @@ package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams.TCP; +import android.annotation.SuppressLint; + import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams.STREAM_TYPE; import org.json.JSONException; @@ -9,6 +11,7 @@ public class TCP_DL_STREAM extends TCP_STREAM { public TCP_DL_STREAM(){ super(); } + public void parse(JSONObject data) throws JSONException { super.parse(data); this.setStreamType(STREAM_TYPE.TCP_DL); diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Sum/Sum.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Sum/Sum.java index c8f56f68..e99a96a1 100644 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Sum/Sum.java +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Sum/Sum.java @@ -1,9 +1,14 @@ package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum; +import android.os.Parcel; +import android.os.Parcelable; + +import androidx.annotation.NonNull; + import org.json.JSONException; import org.json.JSONObject; -public class Sum { +public class Sum implements Parcelable { private int start; private float end; private float seconds; @@ -14,6 +19,30 @@ public class Sum { private SUM_TYPE sumType; public Sum(){ } + + protected Sum(Parcel in) { + start = in.readInt(); + end = in.readFloat(); + seconds = in.readFloat(); + bytes = in.readLong(); + bits_per_second = in.readDouble(); + omitted = in.readBoolean(); + sender = in.readBoolean(); + sumType = SUM_TYPE.values()[in.readInt()]; + } + + public static final Creator CREATOR = new Creator() { + @Override + public Sum createFromParcel(Parcel in) { + return new Sum(in); + } + + @Override + public Sum[] newArray(int size) { + return new Sum[size]; + } + }; + public void parse(JSONObject data) throws JSONException { this.start = data.getInt("start"); this.end = (float) data.getDouble("end"); @@ -51,4 +80,21 @@ public void setSumType(SUM_TYPE sumType) { this.sumType = sumType; } + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel parcel, int i) { + parcel.writeInt(this.start); + parcel.writeFloat(this.end); + parcel.writeFloat(this.seconds); + parcel.writeLong(this.bytes); + parcel.writeDouble(this.bits_per_second); + parcel.writeBoolean(this.omitted); + parcel.writeBoolean(this.sender); + parcel.writeInt(this.sumType.ordinal()); + + } } diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3Worker.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Worker/Iperf3ExecuterWorker.java similarity index 62% rename from app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3Worker.java rename to app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Worker/Iperf3ExecuterWorker.java index 1a228178..4e17605b 100644 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3Worker.java +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Worker/Iperf3ExecuterWorker.java @@ -6,34 +6,29 @@ * SPDX-License-Identifier: BSD-3-Clause-Clear */ -package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3; +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Worker; -import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC; -import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION; import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE; import android.app.Notification; import android.app.PendingIntent; import android.content.Context; import android.graphics.Color; -import android.os.Build; import android.util.Log; -import android.widget.TextView; import androidx.annotation.NonNull; -import androidx.annotation.RequiresApi; import androidx.core.app.NotificationCompat; -import androidx.room.util.StringUtil; import androidx.work.Data; import androidx.work.ForegroundInfo; import androidx.work.WorkManager; import androidx.work.Worker; import androidx.work.WorkerParameters; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Iperf3Input; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Iperf3LibLoader; import de.fraunhofer.fokus.OpenMobileNetworkToolkit.R; -import java.util.Locale; -public class Iperf3Worker extends Worker { +public class Iperf3ExecuterWorker extends Worker { private static final String TAG = "iperf3Worker"; static { @@ -41,27 +36,21 @@ public class Iperf3Worker extends Worker { } private final String[] cmd; - private final String iperf3WorkerID; - private final String measurementName; - private final String timestamp; - private final int notificationID; - private final String client; - private final String protocol; - private String serverPort; - private final String ip; + private final String uuid; private final int FOREGROUND_SERVICE_TYPE = FOREGROUND_SERVICE_TYPE_SPECIAL_USE; - - public Iperf3Worker(@NonNull Context context, @NonNull WorkerParameters workerParams) { + private final int notificationID = 1002; + private String ip; + private String port; + private String protocol; + private Iperf3Input.Iperf3Mode mode; + public Iperf3ExecuterWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) { super(context, workerParams); - cmd = getInputData().getStringArray("commands"); - measurementName = getInputData().getString("measurementName"); - iperf3WorkerID = getInputData().getString("iperf3WorkerID"); - timestamp = getInputData().getString("timestamp"); - notificationID = 100; - client = getInputData().getString("client"); + cmd = getInputData().getStringArray("command"); + uuid = getInputData().getString("uuid"); ip = getInputData().getString("ip"); - serverPort = getInputData().getString("port"); + port = getInputData().getString("port"); protocol = getInputData().getString("protocol"); + mode = Iperf3Input.Iperf3Mode.valueOf(getInputData().getString("mode")); } @@ -76,7 +65,7 @@ private ForegroundInfo createForegroundInfo(@NonNull String progress) { PendingIntent intent = WorkManager.getInstance(context) .createCancelPendingIntent(getId()); Notification notification = new NotificationCompat.Builder(context, id) - .setContentTitle("iPerf3 "+ client.substring(0, 1).toUpperCase() + client.substring(1).toLowerCase()) + //.setContentTitle("iPerf3 "+ client.substring(0, 1).toUpperCase() + client.substring(1).toLowerCase()) .setContentText(progress) .setOngoing(true) .setColor(Color.WHITE) @@ -96,10 +85,11 @@ public void onStopped() { @NonNull @Override public Result doWork() { - if (serverPort == null) serverPort = "5201"; - String progress = String.format("Connected to %s:%s with %s", ip, serverPort, protocol); - if (client.equals("server")) { - progress = String.format("Running on %s:%s", ip, serverPort); + Log.i(TAG, "doWork: called!"); + if (port == null) port = "5201"; + String progress = String.format("Connecting to %s:%s with %s", ip, port, protocol); + if (mode.equals(Iperf3Input.Iperf3Mode.SERVER)) { + progress = String.format("Running on %s:%s", ip, port); } setForegroundAsync(createForegroundInfo(progress)); @@ -111,7 +101,7 @@ public Result doWork() { Data.Builder output = new Data.Builder() .putInt("iperf3_result", result) - .putString("iperf3WorkerID", iperf3WorkerID); + .putString("iperf3WorkerID", uuid); if (result == 0) { return Result.success(output.build()); } diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3ToLineProtocolWorker.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Worker/Iperf3ToLineProtocolWorker.java similarity index 95% rename from app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3ToLineProtocolWorker.java rename to app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Worker/Iperf3ToLineProtocolWorker.java index 86cf58fc..0fe6a59c 100644 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3ToLineProtocolWorker.java +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Worker/Iperf3ToLineProtocolWorker.java @@ -6,7 +6,7 @@ * SPDX-License-Identifier: BSD-3-Clause-Clear */ -package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3; +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Worker; import android.content.Context; import android.os.Build; @@ -22,6 +22,12 @@ import com.influxdb.client.domain.WritePrecision; import com.influxdb.client.write.Point; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Iperf3Input; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Iperf3Parser; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Interval; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams.Stream; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams.TCP.TCP_UL_STREAM; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams.UDP.UDP_DL_STREAM; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; @@ -34,10 +40,6 @@ import de.fraunhofer.fokus.OpenMobileNetworkToolkit.GlobalVars; import de.fraunhofer.fokus.OpenMobileNetworkToolkit.InfluxDB2x.InfluxdbConnection; import de.fraunhofer.fokus.OpenMobileNetworkToolkit.InfluxDB2x.InfluxdbConnections; -import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Interval; -import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams.Stream; -import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams.TCP.TCP_UL_STREAM; -import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams.UDP.UDP_DL_STREAM; import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Preferences.SPType; import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Preferences.SharedPreferencesGrouper; @@ -57,7 +59,7 @@ public class Iperf3ToLineProtocolWorker extends Worker { private final String protocol; private final String iperf3LineProtocolFile; - private final DeviceInformation di = GlobalVars.getInstance().get_dp().getDeviceInformation(); + private final DeviceInformation di; private final boolean rev; private final boolean biDir; @@ -68,6 +70,7 @@ public class Iperf3ToLineProtocolWorker extends Worker { public Iperf3ToLineProtocolWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) { super(context, workerParams); rawIperf3file = getInputData().getString("rawIperf3file"); + di = GlobalVars.getInstance().get_dp().getDeviceInformation(); ip = getInputData().getString("ip"); measurementName = getInputData().getString("measurementName"); @@ -145,7 +148,7 @@ public Result doWork() { setup(); Data output = new Data.Builder().putBoolean("iperf3_upload", false).build(); - Iperf3Parser iperf3Parser = new Iperf3Parser(rawIperf3file); + Iperf3Parser iperf3Parser = new Iperf3Parser(getApplicationContext(), rawIperf3file, new Iperf3Input()); iperf3Parser.parse(); @@ -238,7 +241,7 @@ public Result doWork() { iperf3Stream = new FileOutputStream(iperf3LineProtocolFile, true); } catch (FileNotFoundException e) { Toast.makeText(getApplicationContext(), "logfile not created", Toast.LENGTH_SHORT).show(); - Log.d(TAG,e.toString()); + e.printStackTrace(); } if(iperf3Stream == null){ diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3UploadWorker.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Worker/Iperf3UploadWorker.java similarity index 97% rename from app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3UploadWorker.java rename to app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Worker/Iperf3UploadWorker.java index b3ff8d43..5f15b1a7 100644 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3UploadWorker.java +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Worker/Iperf3UploadWorker.java @@ -6,7 +6,7 @@ * SPDX-License-Identifier: BSD-3-Clause-Clear */ -package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3; +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Worker; import android.content.Context; import android.util.Log; diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/LoggingService.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/LoggingService.java index 69b96766..bd41bef7 100644 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/LoggingService.java +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/LoggingService.java @@ -296,6 +296,10 @@ public void onDestroy() { private ArrayList getPoints() { long time = System.currentTimeMillis(); + if(dp == null) { + Log.e(TAG, "getPoints: Dataprovider is null!"); + return new ArrayList<>(); + } Map tags_map = dp.getTagsMap(); ArrayList logPoints = new ArrayList<>(); diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/MainActivity.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/MainActivity.java index 6b48c36d..eb1ae1f7 100644 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/MainActivity.java +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/MainActivity.java @@ -47,6 +47,7 @@ import androidx.navigation.fragment.NavHostFragment; import androidx.preference.Preference; import androidx.preference.PreferenceFragmentCompat; +import androidx.work.WorkManager; import java.security.MessageDigest; import java.util.ArrayList; @@ -105,7 +106,7 @@ protected void onCreate(Bundle savedInstanceState) { spg = SharedPreferencesGrouper.getInstance(getApplicationContext()); pm = getPackageManager(); feature_telephony = pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY); - + WorkManager.getInstance(context).cancelAllWork(); // populate global vars we use in other parts of the app. gv.setPm(pm); gv.setPermission_phone_state(ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED); @@ -478,4 +479,5 @@ public boolean onPreferenceStartFragment(@NonNull PreferenceFragmentCompat calle } return true; } + } \ No newline at end of file diff --git a/app/src/main/res/drawable/dashed_outline.xml b/app/src/main/res/drawable/dashed_outline.xml new file mode 100644 index 00000000..9e66ce6e --- /dev/null +++ b/app/src/main/res/drawable/dashed_outline.xml @@ -0,0 +1,10 @@ + + + + + + diff --git a/app/src/main/res/drawable/grid_shape.xml b/app/src/main/res/drawable/grid_shape.xml new file mode 100644 index 00000000..0406b401 --- /dev/null +++ b/app/src/main/res/drawable/grid_shape.xml @@ -0,0 +1,13 @@ + + + + + + + diff --git a/app/src/main/res/layout/fragment_iperf3_card.xml b/app/src/main/res/layout/fragment_iperf3_card.xml new file mode 100644 index 00000000..983fca3f --- /dev/null +++ b/app/src/main/res/layout/fragment_iperf3_card.xml @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_iperf3_card_add.xml b/app/src/main/res/layout/fragment_iperf3_card_add.xml new file mode 100644 index 00000000..447d8699 --- /dev/null +++ b/app/src/main/res/layout/fragment_iperf3_card_add.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_iperf3_input.xml b/app/src/main/res/layout/fragment_iperf3_input.xml index 61fa0ff7..ad4b1185 100644 --- a/app/src/main/res/layout/fragment_iperf3_input.xml +++ b/app/src/main/res/layout/fragment_iperf3_input.xml @@ -7,287 +7,20 @@ ~ SPDX-License-Identifier: BSD-3-Clause-Clear --> - + android:orientation="vertical"> - + + + - - - - - - - - - - - - - - - - - -