diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 740c2ee9..5236833d 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -2,25 +2,83 @@ name: Android CI on: push: - branches: [ "main" ] + branches: [ 'main', 'rel/**' ] + tags: + - '*' pull_request: - branches: [ "main" ] + branches: [ 'main' ] + jobs: build: - runs-on: ubuntu-latest - + environment: ngni-omnt steps: - - uses: actions/checkout@v3 - - name: set up JDK 11 - uses: actions/setup-java@v3 - with: - java-version: '11' - distribution: 'temurin' - cache: gradle - - - name: Grant execute permission for gradlew - run: chmod +x gradlew - - name: Build with Gradle - run: ./gradlew build + - name: Checkout Branch ${{ github.ref }} + uses: actions/checkout@v4 + - name: Get Latest iPerf + run: | + wget -O jniLibs.zip https://github.com/omnt/iperf/releases/latest/download/jniLibs + unzip jniLibs.zip -d app/src/main + rm jniLibs.zip + + - name: Decode Keystore and Create key.properties + env: + ENCODED_STRING: ${{ secrets.KEYSTORE }} + RELEASE_KEYSTORE_PASSWORD: ${{ secrets.STOREPASSWORD }} + RELEASE_KEYSTORE_ALIAS: ${{ secrets.KEYALIAS }} + RELEASE_KEY_PASSWORD: ${{ secrets.KEYPASSWORD }} + run: | + echo -n "$ENCODED_STRING" | base64 -d > app/OpenMobileNetworkToolkit-key.jks + mkdir android + touch android/key.properties + echo "storePassword=$RELEASE_KEYSTORE_PASSWORD" > android/key.properties + echo "keyPassword=$RELEASE_KEY_PASSWORD" >> android/key.properties + echo "keyAlias=$RELEASE_KEYSTORE_ALIAS" >> android/key.properties + echo "storeFile=OpenMobileNetworkToolkit-key.jks" >> android/key.properties + + - name: Setup Java + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: 17 + cache: gradle + + - name: Build Release APK + env: + ENCODED_STRING: ${{ secrets.KEYSTORE }} + RELEASE_KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PW }} + RELEASE_KEYSTORE_ALIAS: ${{ secrets.KEYSTORE_ALIAS }} + RELEASE_KEY_PASSWORD: ${{ secrets.KEY_PW }} + run: ./gradlew assembleRelease --stacktrace + + - name: Build Release APK + env: + ENCODED_STRING: ${{ secrets.KEYSTORE }} + RELEASE_KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PW }} + RELEASE_KEYSTORE_ALIAS: ${{ secrets.KEYSTORE_ALIAS }} + RELEASE_KEY_PASSWORD: ${{ secrets.KEY_PW }} + run: ./gradlew assembleDebug --stacktrace + + - name: Generate SPDX + env: + ENCODED_STRING: ${{ secrets.KEYSTORE }} + RELEASE_KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PW }} + RELEASE_KEYSTORE_ALIAS: ${{ secrets.KEYSTORE_ALIAS }} + RELEASE_KEY_PASSWORD: ${{ secrets.KEY_PW }} + run: ./gradlew app:spdxSbomForRelease + + - name: Get release file apk path + id: releaseApk + run: | + echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT + mkdir upload + mv app/build/outputs/apk/debug/app-debug.apk ./upload/omnt-debug.apk + mv app/build/outputs/apk/release/app-release.apk ./upload/omnt-release.apk + mv app/build/spdx/release.spdx.json ./upload/release.spdx.json + + - name: Upload All Artifacts + uses: actions/upload-artifact@v4 + with: + name: omnt-${{ steps.releaseApk.outputs.sha_short }} + path: ./upload \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..28d0b407 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,27 @@ +# OpenMobileNetworkToolkit Changelog +## Release [0.3] + +### Added +- Github Action Workflow for APK Debug/Relase Build and SPDX File [PR 13](https://github.com/omnt/OpenMobileNetworkToolkit/pull/13) +- Documentation [PR 13](https://github.com/omnt/OpenMobileNetworkToolkit/pull/13) +- CHANGELOG.md [PR 13](https://github.com/omnt/OpenMobileNetworkToolkit/pull/13) + +### Changed +- Fix possible [InfluxDB Bug](https://github.com/influxdata/influxdb-client-java/issues/731) +- iPerf3 GUI [PR 14](https://github.com/omnt/OpenMobileNetworkToolkit/pull/14) +- Fix Ping Bug, where button is enabled but now Ping is running after app restart [PR 14](https://github.com/omnt/OpenMobileNetworkToolkit/pull/14) +- Update Ping Fragment, now uses the Metric class to display [PR 14](https://github.com/omnt/OpenMobileNetworkToolkit/pull/14) +- +### Breaking Changes +- see [PR 14](https://github.com/omnt/OpenMobileNetworkToolkit/pull/14) + +## Release [0.2] +### Changed +- Improved 4G support. Now all cell parameters of 4G networks should be logged and displayed correctly +- Improved 2G same as 4G +- Logging status indicator in the actionbar +- Filter for Carrier Settings Readout +- Carrier Settings Apply button moved to Settings +- InfluxDB Cloud is now also supported to be used as logging target. This means we can log to Influx 1.x 2.x and 3.x +- [PR 7](https://github.com/omnt/OpenMobileNetworkToolkit/pull/7) +- [Release 0.2](https://github.com/omnt/OpenMobileNetworkToolkit/releases/tag/0.2 diff --git a/README.md b/README.md index 28929480..cf9cc6e8 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,11 @@ Also, OMNT provides access to different "secret" settings in Android phones. The current state of the app can be described as "research software", it fits our needs but does not aim to be complete or bug free. Use the app at your own risk. If you find it useful for your research, please cite the app in publications. + +* [Quick Start HowTo](docs/quick-start.md) +* [User Manual](docs/OpenMobileNetworkToolkit.md) +* [Signing HowTo](docs/signing.md) + ## Why use this app * As apps like OMNT can can access a lot of private information. It is important for users to be able to make sure that those data is not @@ -46,75 +51,9 @@ The following permissions are requested: If the app can't gain Carrier Privileges, some values can't be accessed and some features are disabled. See below. -### Carrier Permissions -Carrier specific settings can only be accessed by apps running with so-called carrier privileges. This was added in android 6 and is mostly relevant -for 4G and 5G networks. (https://source.android.com/devices/tech/config/carrier) - -Carrier or researcher who are able (admin key to the SIM card is required) to program their own sim cards can store a fingerprint of an signing certificate in an access rule applet (ARA-M) on the SIM card. -An app signed with this certificate will get carrier privileges granted by android. (https://source.android.com/devices/tech/config/uicc) - -E.g. the [ARAM-Applet by Bertrand Martel](https://github.com/bertrandmartel/aram-applet) for JavaCard based SIM cards can be used. -Some SIM cards like the cards from [Sysmocom](http://shop.sysmocom.de/products/sysmoISIM-SJA2) already come with the applet pre installed. -To install the applet to a SIM card [GlobalPlatformPro by Martin Paljak](https://github.com/martinpaljak/GlobalPlatformPro) can be used. -Pre-compiled versions of ARA-M and GP can be found in the [CoIMS_Wiki repository by Supreeth Herle](https://github.com/herlesupreeth/CoIMS_Wiki). - -To provision the fingerprint to the applet, either (pySim)[https://github.com/osmocom/pysim] or GP can be used. - -With pySim it can be done by entering the following commands into pySim-shell: - -start pySim shell with an PSCD attached reader -``` -python3 pySim-shell.py -p0 -a -or if you have a csv file with ICCID and admin pin: -python3 pySim-shell.py -p0 --csv card_data.csv -``` - -Provision the fingerprint. Note that instead of a fingerprint also a valid android App ID can be used. -If you have a SIM Card with the ARA-M applet from sysmocom you can skip the 'verify_adm' part as the applet is not write protected. -```shell -verify_adm -select ADF.ARA-M -aram_delete_all -aram_store_ref_ar_do --aid ffffffffffff --device-app-id E849B63A7B96E571F788FC5845C4AA3C520D18E8 --android-permissions 0000000000000001 -``` -(this assumes the credentials to access the card are stored in the pySim format.) - -### Signing the app -This can be done with android studio. - -To generated a signed apk: -``` -Go to 'build' -> 'Generate signed Bundle/APK' -You will be ask to generate a new key or import an existing one. -Click through the dialogs until you end up with a signed APK -``` - -To sign the debug apks used for development -``` -Go to 'file' -> Project Structure -> Modules -Select the 'app', select the 'Signing config' tab. -create a new signing config referencing you key file -``` - -You can also manually re-sign the downloaded .apk file using apksigner https://developer.android.com/tools/apksigner . -```shell -apksigner sign --ks my.keystore OpenMobileNetworkToolkit.apk -``` -where my.keystore is your java keystore. ## SPDX-SBOM -The SPDX formatted Software Bill Of Material is a machine readable list of all software components used in the app. -To generate a new file run +The SPDX formatted ```Software Bill Of Material``` is a machine readable list of all software components used in the app. To generate a new file run ```shell ./gradlew app:spdxSbomForRelease -``` - -## iPerf3 -iPerf3 has been compiled with a [jni](https://developer.android.com/training/articles/perf-jni) interface to enable OMNT to call it using the specified parameters. -To see how to integrate iPerf3 into your app, look at [iPerf3 Repo](https://github.com/omnt/iperf) - -![iPerf3](screenshots/iperf3.png) - -## Network Slicing - -This function is still under development and requires support from the core network. +``` \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 496d1c14..8f016df5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -8,7 +8,7 @@ plugins { id 'com.android.application' id 'androidx.navigation.safeargs' - id("org.spdx.sbom") version "0.7.0" + id("org.spdx.sbom") version "0.8.0" } def keystoreProperties = new Properties() @@ -24,6 +24,14 @@ if (keystorePropertiesFile.exists()) { keystoreProperties['storePassword'] = "omnt2024" } +def getGitHash = { -> + def stdout = new ByteArrayOutputStream() + exec { + commandLine "git", "rev-parse", "--short", "HEAD" + standardOutput = stdout + } + return stdout.toString().trim() +} android { signingConfigs { @@ -33,16 +41,23 @@ android { storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null storePassword keystoreProperties['storePassword'] } + release{ + keyAlias keystoreProperties['keyAlias'] + keyPassword keystoreProperties['keyPassword'] + storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null + storePassword keystoreProperties['storePassword'] + } } + compileSdk 34 defaultConfig { applicationId "de.fraunhofer.fokus.OpenMobileNetworkToolkit" - //targetSdkPreview "VanillaIceCream" minSdk 31 targetSdk 34 - versionCode 2 - versionName "0.2" + versionCode 3 + versionName "0.3" + resValue("string", "git_hash", getGitHash()) testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" signingConfig signingConfigs.debug @@ -72,13 +87,13 @@ android { } buildFeatures { viewBinding true + buildConfig = true } namespace 'de.fraunhofer.fokus.OpenMobileNetworkToolkit' ndkVersion '25.2.9519653' lint { abortOnError false } - buildToolsVersion '34.0.0' } spdxSbom { @@ -87,7 +102,7 @@ spdxSbom { configurations = ['releaseRuntimeClasspath'] scm { uri.set("https://github.com/omnt/OpenMobileNetworkToolkit") - revision.set("0.2") + revision.set("0.3") } document { name.set("OpenMobileNetworkToolkit") @@ -106,13 +121,13 @@ dependencies { implementation "androidx.room:room-runtime:$room_version" annotationProcessor "androidx.room:room-compiler:$room_version" - implementation 'androidx.appcompat:appcompat:1.6.1' + implementation 'androidx.appcompat:appcompat:1.7.0' implementation 'com.google.guava:guava:33.1.0-jre' - implementation 'androidx.concurrent:concurrent-futures:1.1.0' + implementation 'androidx.concurrent:concurrent-futures:1.2.0' implementation 'androidx.activity:activity:1.9.0' - implementation 'androidx.fragment:fragment:1.7.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.11.0' + implementation 'androidx.fragment:fragment:1.8.0' + 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' @@ -123,10 +138,10 @@ dependencies { implementation 'androidx.preference:preference-ktx:1.2.1' implementation 'androidx.recyclerview:recyclerview:1.3.2' implementation 'androidx.recyclerview:recyclerview-selection:1.1.0' - implementation 'com.influxdb:influxdb-client-java:7.0.0' - implementation 'com.google.android.gms:play-services-location:21.2.0' + implementation 'com.influxdb:influxdb-client-java:7.1.0' + implementation 'com.google.android.gms:play-services-location:21.3.0' implementation 'com.github.anastr:speedviewlib:1.6.1' - implementation "androidx.viewpager2:viewpager2:1.0.0" + implementation "androidx.viewpager2:viewpager2:1.1.0" } configurations.implementation { diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index e3d3247e..9c325e21 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -20,12 +20,12 @@ # hide the original source file name. #-renamesourcefileattribute SourceFile --dontskipnonpubliclibraryclasses -dontobfuscate --forceprocessing -optimizationpasses 5 -keep class * extends android.app.Activity +-keep class com.influxdb.** + -assumenosideeffects class android.util.Log { public static *** d(...); public static *** v(...); diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ce5b6c8c..fc7bc1e5 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -62,6 +62,8 @@ + diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/AboutFragment.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/AboutFragment.java index d4261432..549853d3 100644 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/AboutFragment.java +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/AboutFragment.java @@ -33,8 +33,10 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat super.onViewCreated(view, savedInstanceState); TextView about_text = requireView().findViewById(R.id.about_text_box); about_text.setAutoLinkMask(Linkify.WEB_URLS); + about_text.setTextIsSelectable(true); about_text.append(getString(R.string.appinfo)); about_text.append("\n\n"); + about_text.append("https://omnt.app\n"); about_text.append("https://github.com/omnt/OpenMobileNetworkToolkit"); about_text.append("\n\nThird party software used in this app: \n \n"); about_text.append( @@ -42,5 +44,11 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat about_text.append("\n\n"); about_text.append( "iPerf3 is licensed under a BSD style license. \nhttps://github.com/esnet/iperf"); + + about_text.append("\n\n"); + about_text.append("Version Code: " + BuildConfig.VERSION_CODE + "\nVersion Name: " + BuildConfig.VERSION_NAME + "\n"); + about_text.append("Build Type: " + BuildConfig.BUILD_TYPE + "\n"); + about_text.append("GitHash: " + getString(R.string.git_hash) + "\n"); + about_text.append("SigningHash sha256: " + GlobalVars.getInstance().getSigning_hash() + "\n"); } } diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/DataProvider/DataProvider.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/DataProvider/DataProvider.java index 857923ab..17177cc0 100644 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/DataProvider/DataProvider.java +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/DataProvider/DataProvider.java @@ -95,7 +95,6 @@ public class DataProvider extends PhoneStateListener implements LocationListener private List nii = new ArrayList<>(); private ArrayList ssi = new ArrayList<>(); private SliceInformation si = new SliceInformation(); - private PingInformation pi = new PingInformation(); // Time stamp, should be updated on each update of internal data caches private long ts = System.currentTimeMillis(); private LocationCallback locationCallback; diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/DataProvider/PingInformation.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/DataProvider/PingInformation.java deleted file mode 100644 index 00cb64eb..00000000 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/DataProvider/PingInformation.java +++ /dev/null @@ -1,18 +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.DataProvider; - -public class PingInformation { - private Double unixTimestamp; - private int icmpSeq; - private int ttl; - private double rtt; - - private String host; -} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/GlobalVars.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/GlobalVars.java index bf8ddb95..e21b6443 100644 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/GlobalVars.java +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/GlobalVars.java @@ -35,6 +35,7 @@ public class GlobalVars { public static String CQI = "CQI"; public static String EvoDbm = "EvoDbm"; private static GlobalVars instance; + ImageView log_status; private DataProvider dp; private boolean feature_telephony; private boolean carrier_permissions; @@ -45,6 +46,26 @@ public class GlobalVars { private boolean feature_admin; private boolean feature_work_profile; private boolean permission_phone_state; + private String signing_hash; + private boolean permission_fine_location; + + private GlobalVars() { + } + + public static synchronized GlobalVars getInstance() { + if (instance == null) { + instance = new GlobalVars(); + } + return instance; + } + + public String getSigning_hash() { + return signing_hash; + } + + public void setSigning_hash(String signing_hash) { + this.signing_hash = signing_hash; + } public ImageView getLog_status() { return log_status; @@ -54,16 +75,6 @@ public void setLog_status(ImageView log_status) { this.log_status = log_status; } - ImageView log_status; - private GlobalVars(){} - - public static synchronized GlobalVars getInstance(){ - if(instance==null){ - instance=new GlobalVars(); - } - return instance; - } - public DataProvider get_dp() { return dp; } @@ -152,6 +163,4 @@ public void setPermission_fine_location(boolean permission_fine_location) { this.permission_fine_location = permission_fine_location; } - private boolean permission_fine_location; - } diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/HomeFragment.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/HomeFragment.java index f0a5622b..b9094891 100644 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/HomeFragment.java +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/HomeFragment.java @@ -123,6 +123,7 @@ public View onCreateView( md = MessageDigest.getInstance("SHA256"); md.update(signature.toByteArray()); String hash = new String(Base64.encode(md.digest(), 0)); + gv.setSigning_hash(hash); Log.d(TAG, "Signature: " + toHexString(md.digest())); } } catch (PackageManager.NameNotFoundException e1) { 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 new file mode 100644 index 00000000..b5402cd5 --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Intervals.java @@ -0,0 +1,19 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3; + +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Interval; +import java.util.ArrayList; + +public class Intervals { + private ArrayList intervals;; + + public Intervals(){ + this.intervals = new ArrayList<>(); + } + public void addInterval(Interval interval){ + intervals.add(interval); + } + public ArrayList getIntervalArrayList(){ + return intervals; + } + +} 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 index 55cfdbef..a68251df 100644 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3Fragment.java +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3Fragment.java @@ -83,7 +83,7 @@ public class Iperf3Fragment extends Fragment { private final String IPERF3CPORT = "iperf3cport"; private CheckBox iperf3BiDir; private CheckBox iperf3Reverse; - private CheckBox iperf3Json; + private CheckBox iperf3OneOff; private EditText iperf3EtIp; private EditText iperf3EtPort; @@ -169,7 +169,6 @@ public void onChanged(String s) { iperf3Reverse.setChecked(iperf3RunResult.input.iperf3Reverse); iperf3BiDir.setChecked(iperf3RunResult.input.iperf3BiDir); - iperf3Json.setChecked(iperf3RunResult.input.iperf3Json); iperf3OneOff.setChecked(iperf3RunResult.input.iperf3OneOff); protocolSpinner.setSelection(iperf3RunResult.input.iperf3IdxProtocol); iperf3ModeSpinner.setSelection(iperf3RunResult.input.iperf3IdxMode); @@ -304,12 +303,10 @@ public void afterTextChanged(Editable s) { iperf3BiDir = v.findViewById(R.id.iperf_bidir); iperf3Reverse = v.findViewById(R.id.iperf3_reverse); - iperf3Json = v.findViewById(R.id.iperf3_json); iperf3OneOff = v.findViewById(R.id.iperf3_one_off); saveCheckboxInputToSharedPreferences(iperf3BiDir, IPERF3BIDIR); saveCheckboxInputToSharedPreferences(iperf3Reverse, IPERF3REVERSE); - saveCheckboxInputToSharedPreferences(iperf3Json, IPERF3JSON); saveCheckboxInputToSharedPreferences(iperf3OneOff, IPERF3ONEOFF); protocolSpinner = v.findViewById(R.id.iperf3_protocol_spinner); @@ -352,7 +349,6 @@ public void onFragmentResult(@NonNull String requestKey, iperf3Reverse.setChecked(iperf3RunResult.input.iperf3Reverse); iperf3BiDir.setChecked(iperf3RunResult.input.iperf3BiDir); - iperf3Json.setChecked(iperf3RunResult.input.iperf3Json); iperf3OneOff.setChecked(iperf3RunResult.input.iperf3OneOff); protocolSpinner.setSelection(iperf3RunResult.input.iperf3IdxProtocol); iperf3ModeSpinner.setSelection(iperf3RunResult.input.iperf3IdxMode); @@ -375,7 +371,6 @@ public void onFragmentResult(@NonNull String requestKey, iperf3BiDir.setChecked(savedInstanceState.getBoolean(IPERF3BIDIR)); iperf3Reverse.setChecked(savedInstanceState.getBoolean(IPERF3REVERSE)); - iperf3Json.setChecked(savedInstanceState.getBoolean(IPERF3JSON)); iperf3OneOff.setChecked(savedInstanceState.getBoolean(IPERF3ONEOFF)); protocolSpinner.setSelection(savedInstanceState.getInt(IPERF3IDXPROTOCOL)); iperf3ModeSpinner.setSelection(savedInstanceState.getInt(IPERF3IDXMODE)); @@ -391,7 +386,6 @@ public void onFragmentResult(@NonNull String requestKey, iperf3BiDir.setChecked(preferences.getBoolean(IPERF3BIDIR, false)); iperf3Reverse.setChecked(preferences.getBoolean(IPERF3REVERSE, false)); - iperf3Json.setChecked(preferences.getBoolean(IPERF3JSON, false)); iperf3OneOff.setChecked(preferences.getBoolean(IPERF3ONEOFF, false)); protocolSpinner.setSelection(preferences.getInt(IPERF3IDXPROTOCOL, 0)); iperf3ModeSpinner.setSelection(preferences.getInt(IPERF3IDXMODE, 0)); @@ -630,7 +624,7 @@ private String parseInput() { input.iperf3BiDir = false; input.iperf3Reverse = false; input.iperf3OneOff = false; - input.iperf3Json = false; + input.iperf3Json = true; if (!isModeSpinnerClient()) { stb.add("-s"); @@ -648,10 +642,11 @@ private String parseInput() { stb.add("--one-off"); input.iperf3OneOff = true; } - if (iperf3Json.isChecked()) { - stb.add("--json"); - input.iperf3Json = true; - } + stb.add("--json-stream"); + + stb.add("--connect-timeout"); + stb.add("500"); + String joined = String.join(" ", stb); @@ -682,7 +677,6 @@ private void writeToSP() { editor.putBoolean(IPERF3BIDIR, iperf3BiDir.isChecked()); editor.putBoolean(IPERF3REVERSE, iperf3Reverse.isChecked()); - editor.putBoolean(IPERF3JSON, iperf3Json.isChecked()); editor.putBoolean(IPERF3ONEOFF, iperf3OneOff.isChecked()); editor.apply(); } diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3LogFragment.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3LogFragment.java index 2dc8b13e..41d05e2e 100644 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3LogFragment.java +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3LogFragment.java @@ -29,11 +29,19 @@ 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.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; import java.io.FileReader; -import java.io.IOException; import de.fraunhofer.fokus.OpenMobileNetworkToolkit.R; @@ -53,8 +61,14 @@ public class Iperf3LogFragment extends Fragment { private TextView iperf3OutputViewer; private LinearLayout parameterLL; private Context ct; + private LinearLayout metricLL; + private Metric defaultReverseThroughput; + private Metric defaultThroughput; + private Metric defaultRTT; + private Metric defaultJITTER; + private Metric PACKET_LOSS; + public Iperf3LogFragment() { - // Required empty public constructor } @@ -76,6 +90,7 @@ public void run() { runIconView.setImageDrawable(runIcon); uploadIcon = Iperf3Utils.getDrawableUpload(ct, iperf3RunResult.result, iperf3RunResult.uploaded); uploadIconView.setImageDrawable(uploadIcon); + BufferedReader br = null; StringBuilder text = new StringBuilder(); @@ -87,34 +102,71 @@ public void run() { return; } String line; - try { - while ((line = br.readLine()) != null) { - text.append(line); - text.append('\n'); - } - br.close(); - iperf3OutputViewer.setText(text.toString()); - } catch (IOException e) { - logHandler.removeCallbacks(logUpdate); - Log.d(TAG, "onCreateView: failed"); - return; - } + Iperf3Parser iperf3Parser = new Iperf3Parser(iperf3RunResult.input.iperf3rawIperf3file); + iperf3Parser.addPropertyChangeListener(new PropertyChangeListener() { + + private void parseSum(Sum sum, Metric throughput){ + SUM_TYPE sumType = sum.getSumType(); + throughput.update(sum.getBits_per_second()); + switch (sumType){ + case UDP_DL: + defaultJITTER.update(((UDP_DL_SUM)sum).getJitter_ms()); + PACKET_LOSS.update((double) ((UDP_DL_SUM) sum).getLost_percent()); + case TCP_DL: + if(throughput.getDirectionName().getText().equals("Throughput")){ + throughput.getDirectionName().setText("Downlink Mbit/s"); + } + break; + case UDP_UL: + case TCP_UL: + if(throughput.getDirectionName().getText().equals("Throughput")){ + throughput.getDirectionName().setText("Uplink Mbit/s"); + } + break; + } + } + public void propertyChange(PropertyChangeEvent evt) { + + switch (evt.getPropertyName()){ + case "interval": + Interval interval = (Interval) evt.getNewValue(); + parseSum(interval.getSum(), defaultThroughput); + if(interval.getSumBidirReverse() != null) parseSum(interval.getSumBidirReverse(), + defaultReverseThroughput); + break; + case "start": + break; + case "end": + break; + case "error": + Error error = (Error) evt.getNewValue(); + TextView errorView = new TextView(ct); + errorView.setText(error.getError()); + errorView.setTextColor(ct.getColor(R.color.crimson)); + errorView.setPadding(10, 10, 10, 10); + errorView.setTextSize(20); + metricLL.addView(errorView); + break; + } + } + }); + iperf3Parser.parse(); if (iperf3RunResult.result != -100) { logHandler.removeCallbacks(logUpdate); return; } - - - setFields(iperf3RunResult); logHandler.removeCallbacks(logUpdate); logHandler.postDelayed(this, 1000); } }; + + + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -249,8 +301,49 @@ public void onClick(View v) { 1, 10, 1, TypedValue.COMPLEX_UNIT_SP); iperf3OutputViewer.setTextIsSelectable(true); - scrollView.addView(iperf3OutputViewer); - secondRow.addView(scrollView); + + metricLL = new LinearLayout(ct); + metricLL.setOrientation(LinearLayout.VERTICAL); + metricLL.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); + + + + defaultThroughput = new Metric(METRIC_TYPE.THROUGHPUT, ct); + defaultReverseThroughput = new Metric(METRIC_TYPE.THROUGHPUT, ct); + + 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")); + }; + } + + mainLL.addView(metricLL); + + + mainLL.addView(secondRow); if(iperf3RunResult.input.iperf3rawIperf3file == null){ 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 new file mode 100644 index 00000000..f3499a34 --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3Parser.java @@ -0,0 +1,90 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3; + +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 java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.util.Observable; +import java.util.Observer; +import org.json.JSONObject; + + +public class Iperf3Parser { + + private String pathToFile; + private File file; + private BufferedReader br = null; + private PropertyChangeSupport support; + private Start start; + private Intervals intervals = new Intervals(); + Iperf3Parser(String pathToFile) { + 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); + } + + 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); + break; + default: + System.out.println("Unknown event"); + break; + } + } + } catch (Exception e) { + System.out.println("Error reading file"); + } + } + + public Intervals getIntervals() { + return intervals; + } + public Start getStart() { + return start; + } + public void addPropertyChangeListener(PropertyChangeListener pcl) { + support.addPropertyChangeListener(pcl); + } + + public void removePropertyChangeListener(PropertyChangeListener pcl) { + support.removePropertyChangeListener(pcl); + } + + +} 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 464a39cd..dfc37e1e 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 @@ -204,6 +204,7 @@ private LinearLayout thirdRow(LinearLayout ll){ Iperf3Utils.getLayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 0.1F)); return ll; } + public ViewHolder(View itemView) { super(itemView); Log.d(TAG, "ViewHolder: " + itemView); @@ -221,7 +222,6 @@ public ViewHolder(View itemView) { linearLayout.addView(firstRow(new LinearLayout(context))); linearLayout.addView(secondRow(new LinearLayout(context))); linearLayout.addView(thirdRow(new LinearLayout(context))); - itemView.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3ToLineProtocolWorker.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3ToLineProtocolWorker.java index 7f057f57..3056c8da 100644 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3ToLineProtocolWorker.java +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3ToLineProtocolWorker.java @@ -21,14 +21,15 @@ import androidx.work.WorkerParameters; import com.google.common.base.Splitter; -import com.google.gson.Gson; import com.influxdb.client.domain.WritePrecision; import com.influxdb.client.write.Point; -import java.io.BufferedReader; +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.FileReader; import java.io.IOException; import java.util.Collections; import java.util.HashMap; @@ -39,9 +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; -import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Root; -import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Stream; public class Iperf3ToLineProtocolWorker extends Worker { private static final String TAG = "Iperf3UploadWorker"; @@ -146,61 +144,80 @@ public Map getTagsMap() { public Result doWork() { setup(); Data output = new Data.Builder().putBoolean("iperf3_upload", false).build(); - BufferedReader br = null; - try { - br = new BufferedReader(new FileReader(rawIperf3file)); - } catch (FileNotFoundException | NullPointerException e) { - e.printStackTrace(); - return Result.failure(output); - } - Root iperf3AsJson = new Gson().fromJson(br, Root.class); - long timestamp = iperf3AsJson.start.timestamp.timesecs*1000; + + Iperf3Parser iperf3Parser = new Iperf3Parser(rawIperf3file); + iperf3Parser.parse(); + + + long timestamp = Integer.toUnsignedLong( iperf3Parser.getStart().getTimestamp().getTimesecs())*1000; Log.d(TAG, "doWork: "+timestamp); String role = "server"; - if(iperf3AsJson.start.connectingTo != null){ + if(iperf3Parser.getStart().getConnecting_to() != null){ role = "client"; } LinkedList points = new LinkedList(); - for (Interval interval: iperf3AsJson.intervals) { - long tmpTimestamp = timestamp + (long) (interval.sum.end * 1000); - int intervalIdx = iperf3AsJson.intervals.indexOf(interval); - for (Stream stream: interval.streams){ + for (Interval interval: iperf3Parser.getIntervals().getIntervalArrayList()) { + long tmpTimestamp = timestamp + (long) (interval.getSum().getEnd() * 1000); + int intervalIdx = iperf3Parser.getIntervals().getIntervalArrayList().indexOf(interval); + for (Stream stream: interval.getStreams().getStreamArrayList()){ Point point = new Point("Iperf3"); point.addTag("run_uid", runID); point.addTag("bidir", String.valueOf(biDir)); - point.addTag("sender", String.valueOf(stream.sender)); + point.addTag("sender", String.valueOf(stream.getSender())); point.addTag("role", role); - point.addTag("socket", String.valueOf(stream.socket)); + point.addTag("socket", String.valueOf(stream.getSocket())); point.addTag("protocol", protocol); point.addTag("interval", intervalIperf); - point.addTag("version", iperf3AsJson.start.version); + point.addTag("version", iperf3Parser.getStart().getVersion()); point.addTag("reversed", String.valueOf(rev)); point.addTag("oneOff", String.valueOf(oneOff)); - point.addTag("connectingToHost", iperf3AsJson.start.connectingTo.host); - point.addTag("connectingToPort", String.valueOf(iperf3AsJson.start.connectingTo.port)); + point.addTag("connectingToHost", iperf3Parser + .getStart() + .getConnecting_to() + .getHost()); + point.addTag("connectingToPort", String.valueOf(iperf3Parser + .getStart() + .getConnecting_to() + .getPort())); point.addTag("bandwidth", bandwidth); point.addTag("duration", duration); point.addTag("bytesToTransmit", bytes); - point.addTag("streams", String.valueOf(interval.streams.size())); - point.addTag("streamIdx", String.valueOf(interval.streams.indexOf(stream))); + point.addTag("streams", String.valueOf(interval.getStreams().size())); + point.addTag("streamIdx", String.valueOf(interval.getStreams().getStreamArrayList().indexOf(stream))); point.addTag("intervalIdx", String.valueOf(intervalIdx)); - point.addField("bits_per_second", stream.bitsPerSecond); - point.addField("seconds", stream.seconds); - point.addField("bytes", stream.bytes); - - if(stream.rtt != 0) point.addField("rtt", stream.rtt); - if(stream.rttvar != 0) point.addField("rttvar", stream.rttvar); - if(stream.jitterMs != 0) point.addField("jitter_ms", stream.jitterMs); - if(protocol.equals("UDP") && rev){ - point.addField("lost_packets", stream.lostPackets); - point.addField("lost_percent", stream.lostPercent); + point.addField("bits_per_second", stream.getBits_per_second()); + point.addField("seconds", stream.getSeconds()); + point.addField("bytes", stream.getBytes()); + + + switch (stream.getStreamType()){ + case TCP_DL: + break; + case TCP_UL: + TCP_UL_STREAM tcp_ul_stream = (TCP_UL_STREAM) stream; + point.addField("snd_cwnd", tcp_ul_stream.getSnd_cwnd()); + point.addField("retransmits", tcp_ul_stream.getRetransmits()); + point.addField("snd_wnd", tcp_ul_stream.getSnd_wnd()); + point.addField("rtt", tcp_ul_stream.getRtt()); + point.addField("rttvar", tcp_ul_stream.getRttvar()); + point.addField("pmtu", tcp_ul_stream.getPmtu()); + break; + case UDP_DL: + UDP_DL_STREAM udp_dl_stream = (UDP_DL_STREAM) stream; + point.addField("jitter_ms", udp_dl_stream.getJitter_ms()); + point.addField("lost_packets", udp_dl_stream.getLost_packets()); + point.addField("packets", udp_dl_stream.getPackets()); + point.addField("lost_percent", udp_dl_stream.getLost_percent()); + break; + case UDP_UL: + break; + case UNKNOWN: + break; } - point.addField("retransmits", stream.retransmits); - point.time(tmpTimestamp, WritePrecision.MS); points.add(point); diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Connected.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Connected.java deleted file mode 100644 index d0f22178..00000000 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Connected.java +++ /dev/null @@ -1,32 +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.JSON; - -import com.google.gson.annotations.Expose; -import com.google.gson.annotations.SerializedName; - -public class Connected { - - @SerializedName("socket") - @Expose - public int socket; - @SerializedName("local_host") - @Expose - public String localHost; - @SerializedName("local_port") - @Expose - public int localPort; - @SerializedName("remote_host") - @Expose - public String remoteHost; - @SerializedName("remote_port") - @Expose - public int remotePort; - -} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/ConnectingTo.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/ConnectingTo.java deleted file mode 100644 index 76189230..00000000 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/ConnectingTo.java +++ /dev/null @@ -1,24 +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.JSON; - - -import com.google.gson.annotations.Expose; -import com.google.gson.annotations.SerializedName; - -public class ConnectingTo { - - @SerializedName("host") - @Expose - public String host; - @SerializedName("port") - @Expose - public int port; - -} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/CpuUtilizationPercent.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/CpuUtilizationPercent.java deleted file mode 100644 index 4c100394..00000000 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/CpuUtilizationPercent.java +++ /dev/null @@ -1,35 +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.JSON; - -import com.google.gson.annotations.Expose; -import com.google.gson.annotations.SerializedName; - -public class CpuUtilizationPercent { - - @SerializedName("host_total") - @Expose - public float hostTotal; - @SerializedName("host_user") - @Expose - public float hostUser; - @SerializedName("host_system") - @Expose - public float hostSystem; - @SerializedName("remote_total") - @Expose - public float remoteTotal; - @SerializedName("remote_user") - @Expose - public float remoteUser; - @SerializedName("remote_system") - @Expose - public float remoteSystem; - -} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/End.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/End.java deleted file mode 100644 index 1f6bd544..00000000 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/End.java +++ /dev/null @@ -1,40 +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.JSON; - -import com.google.gson.annotations.Expose; -import com.google.gson.annotations.SerializedName; - -import java.util.List; - -public class End { - - @SerializedName("streams") - @Expose - public List streams; - @SerializedName("sum") - @Expose - public Sum sum; - @SerializedName("sum_sent") - @Expose - public SumSent sumSent; - @SerializedName("sum_received") - @Expose - public SumReceived sumReceived; - @SerializedName("cpu_utilization_percent") - @Expose - public CpuUtilizationPercent cpuUtilizationPercent; - @SerializedName("sender_tcp_congestion") - @Expose - public String senderTcpCongestion; - @SerializedName("receiver_tcp_congestion") - @Expose - public String receiverTcpCongestion; - -} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Error.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Error.java new file mode 100644 index 00000000..e1444cab --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Error.java @@ -0,0 +1,28 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON; + +import org.json.JSONException; +import org.json.JSONObject; + +public class Error { + private String error; + + public Error() { + } + + public String getError() { + return error; + } + + public void setError(String error) { + this.error = error; + } + + public void parse(String data) throws JSONException { + this.error = data; + } + + public String toString() { + return "Error: " + error; + } + +} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval.java deleted file mode 100644 index d4ed5933..00000000 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval.java +++ /dev/null @@ -1,25 +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.JSON; - -import com.google.gson.annotations.Expose; -import com.google.gson.annotations.SerializedName; - -import java.util.List; - -public class Interval { - - @SerializedName("streams") - @Expose - public List streams = null; - @SerializedName("sum") - @Expose - public Sum sum; - -} 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 new file mode 100644 index 00000000..4d1caf6b --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Interval.java @@ -0,0 +1,79 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval; + +import static de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.SUM_TYPE.*; + +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; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams.Streams; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.TCP.TCP_BIDIR_SUM; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.TCP.TCP_DL_SUM; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.TCP.TCP_SUM; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.TCP.TCP_UL_SUM; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.UDP.UDP_BIDIR_SUM; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.UDP.UDP_DL_SUM; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.UDP.UDP_SUM; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.UDP.UDP_UL_SUM; +import org.json.JSONException; +import org.json.JSONObject; + +public class Interval { + private Streams streams; + private Sum sum; + public Sum sumBidirReverse; + + public Interval(){ + streams = new Streams(); + } + + private SUM_TYPE getSumType(JSONObject data) throws JSONException { + boolean sender = data.getBoolean("sender"); + if(sender){ + if(data.has("retransmits")) return SUM_TYPE.TCP_UL; + if(data.has("packets")) return SUM_TYPE.UDP_UL; + } + if(data.has("jitter_ms")) return SUM_TYPE.UDP_DL; + return SUM_TYPE.TCP_DL; + } + + public Sum identifySum(JSONObject data) throws JSONException { + Sum identifiedSum = null; + switch (getSumType(data)){ + case TCP_DL: + identifiedSum = new TCP_DL_SUM(); + ((TCP_DL_SUM) identifiedSum).parse(data); + break; + case TCP_UL: + identifiedSum = new TCP_UL_SUM(); + ((TCP_UL_SUM) identifiedSum).parse(data); + break; + case UDP_DL: + identifiedSum = new UDP_DL_SUM(); + ((UDP_DL_SUM) identifiedSum).parse(data); + break; + case UDP_UL: + identifiedSum = new UDP_UL_SUM(); + ((UDP_UL_SUM) identifiedSum).parse(data); + break; + } + return identifiedSum; + } + + public void parse(JSONObject data) throws JSONException { + streams.parse(data.getJSONArray("streams")); + sum = identifySum(data.getJSONObject("sum")); + if(data.has("sum_bidir_reverse")){ + sumBidirReverse = identifySum(data.getJSONObject("sum_bidir_reverse")); + } + } + + public Streams getStreams() { + return streams; + } + public Sum getSum() { + return sum; + } + public Sum getSumBidirReverse() { + return sumBidirReverse; + } +} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Streams/STREAM_TYPE.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Streams/STREAM_TYPE.java new file mode 100644 index 00000000..f5a50a29 --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Streams/STREAM_TYPE.java @@ -0,0 +1,9 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams; + +public enum STREAM_TYPE { + TCP_UL, + TCP_DL, + UDP_UL, + UDP_DL, + UNKNOWN +} 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 new file mode 100644 index 00000000..9ec8dba1 --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Streams/Stream.java @@ -0,0 +1,64 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams; + +import org.json.JSONException; +import org.json.JSONObject; + +public class Stream { + private int socket; + private int start; + private double end; + private double seconds; + private long bytes; + private double bits_per_second; + private boolean omitted; + private boolean sender; + + private STREAM_TYPE streamType; + + public Stream(){ + } + public void parse(JSONObject data) throws JSONException { + this.socket = data.getInt("socket"); + this.start = data.getInt("start"); + this.end = data.getDouble("end"); + this.seconds = data.getDouble("seconds"); + this.bytes = data.getLong("bytes"); + this.bits_per_second = data.getDouble("bits_per_second"); + this.omitted = data.getBoolean("omitted"); + this.sender = data.getBoolean("sender"); + } + + public int getSocket() { + return socket; + } + public int getStart() { + return start; + } + public double getEnd() { + return end; + } + public double getSeconds() { + return seconds; + } + public long getBytes() { + return bytes; + } + public double getBits_per_second() { + return bits_per_second; + } + public boolean getOmitted() { + return omitted; + } + public boolean getSender() { + return sender; + } + + public STREAM_TYPE getStreamType() { + return streamType; + } + + public void setStreamType( + STREAM_TYPE streamType) { + this.streamType = streamType; + } +} 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 new file mode 100644 index 00000000..b00cbc4c --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Streams/Streams.java @@ -0,0 +1,74 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams; + +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; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams.UDP.UDP_UL_STREAM; +import java.util.ArrayList; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +public class Streams { + private ArrayList streams; + public Streams(){ + this.streams = new ArrayList<>(); + } + + private STREAM_TYPE identifyStream(JSONObject data) throws JSONException { + boolean sender = data.getBoolean("sender"); + if(sender){ + if(data.has("retransmits")) return STREAM_TYPE.TCP_UL; + if(data.has("packets")) return STREAM_TYPE.UDP_UL; + } + if(data.has("jitter_ms")) return STREAM_TYPE.UDP_DL; + return STREAM_TYPE.TCP_DL; + } + + private Stream parseStream(JSONObject data) throws JSONException{ + STREAM_TYPE type = identifyStream(data); + Stream stream = null; + switch (type) { + case TCP_UL: + stream = new TCP_UL_STREAM(); + break; + case TCP_DL: + stream = new TCP_DL_STREAM(); + break; + case UDP_UL: + stream = new UDP_UL_STREAM(); + break; + case UDP_DL: + stream = new UDP_DL_STREAM(); + break; + case UNKNOWN: + return stream; + } + stream.parse(data); + return stream; + } + + public void parse(JSONArray streams) throws JSONException { + for (int i = 0; i < streams.length(); i++) { + JSONObject streamJSONObject = streams.getJSONObject(i); + Stream stream = parseStream(streamJSONObject); + if(stream == null){ + System.out.println("Stream is null!"); + continue; + } + addStream(stream); + } + } + public int size(){ + return streams.size(); + } + public ArrayList getStreamArrayList() { + return streams; + } + public void addStream(Stream stream){ + streams.add(stream); + } + public Stream getStream(int i) { + return streams.get(i); + } +} 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 new file mode 100644 index 00000000..93e27705 --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Streams/TCP/TCP_DL_STREAM.java @@ -0,0 +1,16 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams.TCP; + +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams.STREAM_TYPE; + +import org.json.JSONException; +import org.json.JSONObject; + +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/Streams/TCP/TCP_STREAM.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Streams/TCP/TCP_STREAM.java new file mode 100644 index 00000000..3b3e663b --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Streams/TCP/TCP_STREAM.java @@ -0,0 +1,14 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams.TCP; + +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams.Stream; +import org.json.JSONException; +import org.json.JSONObject; + +public class TCP_STREAM extends Stream { + public TCP_STREAM(){ + super(); + } + public void parse(JSONObject data) throws JSONException { + super.parse(data); + } +} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Streams/TCP/TCP_UL_STREAM.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Streams/TCP/TCP_UL_STREAM.java new file mode 100644 index 00000000..a305776d --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Streams/TCP/TCP_UL_STREAM.java @@ -0,0 +1,53 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams.TCP; + +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams.STREAM_TYPE; +import org.json.JSONException; +import org.json.JSONObject; + +public class TCP_UL_STREAM extends TCP_STREAM { + private int retransmits; + private int snd_cwnd; + private int snd_wnd; + private int rtt; + private int rttvar; + private int pmtu; + + public TCP_UL_STREAM(){ + super(); + } + public void parse(JSONObject data) throws JSONException { + super.parse(data); + this.retransmits = data.getInt("retransmits"); + this.snd_cwnd = data.getInt("snd_cwnd"); + this.snd_wnd = data.getInt("snd_wnd"); + this.rtt = data.getInt("rtt"); + this.rttvar = data.getInt("rttvar"); + this.pmtu = data.getInt("pmtu"); + this.setStreamType(STREAM_TYPE.TCP_UL); + } + + public int getRetransmits() { + return retransmits; + } + + public int getSnd_cwnd() { + return snd_cwnd; + } + + public int getSnd_wnd() { + return snd_wnd; + } + + public int getRtt() { + return rtt; + } + + public int getRttvar() { + return rttvar; + } + + public int getPmtu() { + return pmtu; + } + +} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Streams/UDP/UDP_DL_STREAM.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Streams/UDP/UDP_DL_STREAM.java new file mode 100644 index 00000000..af7b68ac --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Streams/UDP/UDP_DL_STREAM.java @@ -0,0 +1,36 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams.UDP; + +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams.STREAM_TYPE; +import org.json.JSONException; +import org.json.JSONObject; + +public class UDP_DL_STREAM extends UDP_STREAM { + private double jitter_ms; + private int lost_packets; + private int packets; + private double lost_percent; + public UDP_DL_STREAM(){ + super(); + } + public void parse(JSONObject data) throws JSONException { + super.parse(data); + this.jitter_ms = data.getDouble("jitter_ms"); + this.lost_packets = data.getInt("lost_packets"); + this.packets = data.getInt("packets"); + this.lost_percent = data.getDouble("lost_percent"); + this.setStreamType(STREAM_TYPE.UDP_DL); + } + public double getJitter_ms() { + return jitter_ms; + } + public int getLost_packets() { + return lost_packets; + } + public int getPackets() { + return packets; + } + public double getLost_percent() { + return lost_percent; + } + +} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Streams/UDP/UDP_STREAM.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Streams/UDP/UDP_STREAM.java new file mode 100644 index 00000000..acf8e17f --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Streams/UDP/UDP_STREAM.java @@ -0,0 +1,15 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams.UDP; + +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams.Stream; +import org.json.JSONException; +import org.json.JSONObject; + +public class UDP_STREAM extends Stream { + public int packets; + public UDP_STREAM(){ + super(); + } + public void parse(JSONObject data) throws JSONException { + super.parse(data); + } +} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Streams/UDP/UDP_UL_STREAM.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Streams/UDP/UDP_UL_STREAM.java new file mode 100644 index 00000000..99fdda02 --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Streams/UDP/UDP_UL_STREAM.java @@ -0,0 +1,15 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams.UDP; + +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams.STREAM_TYPE; +import org.json.JSONException; +import org.json.JSONObject; + +public class UDP_UL_STREAM extends UDP_STREAM { + public UDP_UL_STREAM(){ + super(); + } + public void parse(JSONObject data) throws JSONException { + super.parse(data); + this.setStreamType(STREAM_TYPE.UDP_UL); + } +} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Sum/SUM_TYPE.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Sum/SUM_TYPE.java new file mode 100644 index 00000000..538bbd08 --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Sum/SUM_TYPE.java @@ -0,0 +1,11 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum; + +public enum SUM_TYPE { + TCP_UL, + TCP_DL, + TCP_BIDIR, + UDP_UL, + UDP_DL, + UDP_BIDIR, + UNKNOWN +} 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 new file mode 100644 index 00000000..c8f56f68 --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Sum/Sum.java @@ -0,0 +1,54 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum; + +import org.json.JSONException; +import org.json.JSONObject; + +public class Sum { + private int start; + private float end; + private float seconds; + private long bytes; + private double bits_per_second; + private boolean omitted; + private boolean sender; + private SUM_TYPE sumType; + public Sum(){ + } + public void parse(JSONObject data) throws JSONException { + this.start = data.getInt("start"); + this.end = (float) data.getDouble("end"); + this.seconds = (float) data.getDouble("seconds"); + this.bytes = data.getLong("bytes"); + this.bits_per_second = data.getDouble("bits_per_second"); + this.omitted = data.getBoolean("omitted"); + this.sender = data.getBoolean("sender"); + } + public int getStart() { + return start; + } + public float getEnd() { + return end; + } + public float getSeconds() { + return seconds; + } + public long getBytes() { + return bytes; + } + public double getBits_per_second() { + return bits_per_second; + } + public boolean getOmitted() { + return omitted; + } + public boolean getSender() { + return sender; + } + public SUM_TYPE getSumType() { + return sumType; + } + public void setSumType(SUM_TYPE sumType) { + this.sumType = sumType; + } + +} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Sum/TCP/TCP_BIDIR_SUM.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Sum/TCP/TCP_BIDIR_SUM.java new file mode 100644 index 00000000..2165f579 --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Sum/TCP/TCP_BIDIR_SUM.java @@ -0,0 +1,24 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.TCP; + +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.SUM_TYPE; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.Sum; +import org.json.JSONException; +import org.json.JSONObject; + +public class TCP_BIDIR_SUM extends TCP_SUM{ + Sum bidirReverse; + SUM_TYPE sumType; + public TCP_BIDIR_SUM() { + super(); + this.sumType = SUM_TYPE.TCP_BIDIR; + } + public void parse(JSONObject data) throws JSONException { + super.parse(data.getJSONObject("sum")); + this.bidirReverse.parse(data.getJSONObject("sum_bidir_reverse")); + + } + + public SUM_TYPE getSumType() { + return sumType; + } +} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Sum/TCP/TCP_DL_SUM.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Sum/TCP/TCP_DL_SUM.java new file mode 100644 index 00000000..d664ea55 --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Sum/TCP/TCP_DL_SUM.java @@ -0,0 +1,17 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.TCP; + +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.SUM_TYPE; +import org.json.JSONException; +import org.json.JSONObject; + +public class TCP_DL_SUM extends TCP_SUM{ + public TCP_DL_SUM() { + super(); + this.setSumType(SUM_TYPE.TCP_DL); + } + + @Override + public void parse(JSONObject data) throws JSONException { + super.parse(data); + } +} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Sum/TCP/TCP_SUM.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Sum/TCP/TCP_SUM.java new file mode 100644 index 00000000..27833aea --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Sum/TCP/TCP_SUM.java @@ -0,0 +1,15 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.TCP; + +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.Sum; +import org.json.JSONException; +import org.json.JSONObject; + +public class TCP_SUM extends Sum { + public TCP_SUM() { + super(); + } + public void parse(JSONObject data) throws JSONException { + super.parse(data); + + } +} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Sum/TCP/TCP_UL_SUM.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Sum/TCP/TCP_UL_SUM.java new file mode 100644 index 00000000..e8f84261 --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Sum/TCP/TCP_UL_SUM.java @@ -0,0 +1,18 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.TCP; + +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.SUM_TYPE; +import org.json.JSONException; +import org.json.JSONObject; + +public class TCP_UL_SUM extends TCP_SUM{ + public int retransmits; + public TCP_UL_SUM() { + super(); + this.setSumType(SUM_TYPE.TCP_UL); + } + public void parse(JSONObject data) throws JSONException { + super.parse(data); + this.retransmits = data.getInt("retransmits"); + + } +} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Sum/UDP/UDP_BIDIR_SUM.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Sum/UDP/UDP_BIDIR_SUM.java new file mode 100644 index 00000000..284a35aa --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Sum/UDP/UDP_BIDIR_SUM.java @@ -0,0 +1,25 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.UDP; + +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.SUM_TYPE; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.Sum; +import org.json.JSONException; +import org.json.JSONObject; + +public class UDP_BIDIR_SUM extends UDP_SUM{ + + Sum bidirReverse; + SUM_TYPE sumType; + public UDP_BIDIR_SUM() { + super(); + sumType = SUM_TYPE.UDP_BIDIR; + } + public void parse(JSONObject data) throws JSONException { + super.parse(data.getJSONObject("sum")); + this.bidirReverse.parse(data.getJSONObject("sum_bidir_reverse")); + + } + + public SUM_TYPE getSumType() { + return sumType; + } +} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Sum/UDP/UDP_DL_SUM.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Sum/UDP/UDP_DL_SUM.java new file mode 100644 index 00000000..041a39e1 --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Sum/UDP/UDP_DL_SUM.java @@ -0,0 +1,37 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.UDP; + +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.SUM_TYPE; +import org.json.JSONException; +import org.json.JSONObject; + +public class UDP_DL_SUM extends UDP_SUM{ + private double jitter_ms; + private int lost_packets; + private double lost_percent; + public UDP_DL_SUM() { + super(); + this.setSumType(SUM_TYPE.UDP_DL); + } + + @Override + public void parse(JSONObject data) throws JSONException { + super.parse(data); + this.jitter_ms = data.getDouble("jitter_ms"); + this.lost_packets = data.getInt("lost_packets"); + this.lost_percent = data.getDouble("lost_percent"); + + } + + public double getJitter_ms() { + return jitter_ms; + } + + public int getLost_packets() { + return lost_packets; + } + + public double getLost_percent() { + return lost_percent; + } + +} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Sum/UDP/UDP_SUM.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Sum/UDP/UDP_SUM.java new file mode 100644 index 00000000..02a4abe0 --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Sum/UDP/UDP_SUM.java @@ -0,0 +1,6 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.UDP; + +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.Sum; + +public class UDP_SUM extends Sum { +} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Sum/UDP/UDP_UL_SUM.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Sum/UDP/UDP_UL_SUM.java new file mode 100644 index 00000000..a73bab2c --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Sum/UDP/UDP_UL_SUM.java @@ -0,0 +1,17 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.UDP; + +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.SUM_TYPE; +import org.json.JSONException; +import org.json.JSONObject; + +public class UDP_UL_SUM extends UDP_SUM{ + private int packets; + public UDP_UL_SUM() { + super(); + this.setSumType(SUM_TYPE.UDP_UL); + } + public void parse(JSONObject data) throws JSONException { + super.parse(data); + this.packets = data.getInt("packets"); + } +} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Receiver.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Receiver.java deleted file mode 100644 index 87eba891..00000000 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Receiver.java +++ /dev/null @@ -1,39 +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.JSON; - - -import com.google.gson.annotations.Expose; -import com.google.gson.annotations.SerializedName; - -public class Receiver { - - @SerializedName("socket") - @Expose - public int socket; - @SerializedName("start") - @Expose - public int start; - @SerializedName("end") - @Expose - public float end; - @SerializedName("seconds") - @Expose - public float seconds; - @SerializedName("bytes") - @Expose - public long bytes; - @SerializedName("bits_per_second") - @Expose - public float bitsPerSecond; - @SerializedName("sender") - @Expose - public boolean sender; - -} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Root.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Root.java deleted file mode 100644 index f615b5fc..00000000 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Root.java +++ /dev/null @@ -1,28 +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.JSON; - -import com.google.gson.annotations.Expose; -import com.google.gson.annotations.SerializedName; - -import java.util.List; - -public class Root { - - @SerializedName("start") - @Expose - public Start start; - @SerializedName("intervals") - @Expose - public List intervals = null; - @SerializedName("end") - @Expose - public End end; - -} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Sender.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Sender.java deleted file mode 100644 index 93a9d870..00000000 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Sender.java +++ /dev/null @@ -1,57 +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.JSON; - - -import com.google.gson.annotations.Expose; -import com.google.gson.annotations.SerializedName; - -public class Sender { - - @SerializedName("socket") - @Expose - public int socket; - @SerializedName("start") - @Expose - public int start; - @SerializedName("end") - @Expose - public float end; - @SerializedName("seconds") - @Expose - public float seconds; - @SerializedName("bytes") - @Expose - public long bytes; - @SerializedName("bits_per_second") - @Expose - public float bitsPerSecond; - @SerializedName("retransmits") - @Expose - public int retransmits; - @SerializedName("max_snd_cwnd") - @Expose - public int maxSndCwnd; - @SerializedName("max_snd_wnd") - @Expose - public int maxSndWnd; - @SerializedName("max_rtt") - @Expose - public int maxRtt; - @SerializedName("min_rtt") - @Expose - public int minRtt; - @SerializedName("mean_rtt") - @Expose - public int meanRtt; - @SerializedName("sender") - @Expose - public boolean sender; - -} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Start.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Start.java deleted file mode 100644 index 1f2a29b4..00000000 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Start.java +++ /dev/null @@ -1,55 +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.JSON; - -import com.google.gson.annotations.Expose; -import com.google.gson.annotations.SerializedName; - -import java.util.List; - -public class Start { - - @SerializedName("connected") - @Expose - public List connected = null; - @SerializedName("version") - @Expose - public String version; - @SerializedName("system_info") - @Expose - public String systemInfo; - @SerializedName("timestamp") - @Expose - public Timestamp timestamp; - @SerializedName("connecting_to") - @Expose - public ConnectingTo connectingTo; - @SerializedName("cookie") - @Expose - public String cookie; - @SerializedName("tcp_mss_default") - @Expose - public int tcpMssDefault; - @SerializedName("target_bitrate") - @Expose - public int targetBitrate; - @SerializedName("sock_bufsize") - @Expose - public int sockBufsize; - @SerializedName("sndbuf_actual") - @Expose - public int sndbufActual; - @SerializedName("rcvbuf_actual") - @Expose - public int rcvbufActual; - @SerializedName("test_start") - @Expose - public TestStart testStart; - -} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Stream.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Stream.java deleted file mode 100644 index 0ff3d252..00000000 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Stream.java +++ /dev/null @@ -1,74 +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.JSON; - -import com.google.gson.annotations.Expose; -import com.google.gson.annotations.SerializedName; - -public class Stream { - - @SerializedName("socket") - @Expose - public int socket; - @SerializedName("start") - @Expose - public float start; - @SerializedName("end") - @Expose - public float end; - @SerializedName("seconds") - @Expose - public float seconds; - @SerializedName("bytes") - @Expose - public long bytes; - @SerializedName("bits_per_second") - @Expose - public float bitsPerSecond; - @SerializedName("retransmits") - @Expose - public int retransmits; - @SerializedName("snd_cwnd") - @Expose - public int sndCwnd; - @SerializedName("packets") - @Expose - public int packets; - @SerializedName("jitter_ms") - @Expose - public float jitterMs; - @SerializedName("lost_packets") - @Expose - public int lostPackets; - @SerializedName("lost_percent") - @Expose - public float lostPercent; - @SerializedName("snd_wnd") - @Expose - public int sndWnd; - @SerializedName("rtt") - @Expose - public int rtt; - @SerializedName("rttvar") - @Expose - public int rttvar; - @SerializedName("pmtu") - @Expose - public int outOfOrder; - @SerializedName("out_of_order") - @Expose - public int pmtu; - @SerializedName("omitted") - @Expose - public boolean omitted; - @SerializedName("sender") - @Expose - public boolean sender; - -} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Stream__1.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Stream__1.java deleted file mode 100644 index 7add7207..00000000 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Stream__1.java +++ /dev/null @@ -1,21 +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.JSON; - - -import com.google.gson.annotations.Expose; -import com.google.gson.annotations.SerializedName; - -public class Stream__1 { - - @SerializedName("udp") - @Expose - public Stream udp; - -} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Sum.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Sum.java deleted file mode 100644 index 07ef6675..00000000 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Sum.java +++ /dev/null @@ -1,54 +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.JSON; - -import com.google.gson.annotations.Expose; -import com.google.gson.annotations.SerializedName; - -public class Sum { - - @SerializedName("start") - @Expose - public float start; - @SerializedName("end") - @Expose - public float end; - @SerializedName("seconds") - @Expose - public float seconds; - @SerializedName("bytes") - @Expose - public double bytes; - @SerializedName("bits_per_second") - @Expose - public float bitsPerSecond; - @SerializedName("retransmits") - @Expose - public int retransmits; - @SerializedName("omitted") - @Expose - public boolean omitted; - @SerializedName("sender") - @Expose - public boolean sender; - - @SerializedName("packets") - @Expose - public int packets; - @SerializedName("jitter_ms") - @Expose - public float jitterMs; - @SerializedName("lost_packets") - @Expose - public int lostPackets; - @SerializedName("lost_percent") - @Expose - public float lostPercent; - -} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/SumReceived.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/SumReceived.java deleted file mode 100644 index e8c8372b..00000000 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/SumReceived.java +++ /dev/null @@ -1,47 +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.JSON; - - -import com.google.gson.annotations.Expose; -import com.google.gson.annotations.SerializedName; - -public class SumReceived { - - @SerializedName("start") - @Expose - public int start; - @SerializedName("end") - @Expose - public float end; - @SerializedName("seconds") - @Expose - public float seconds; - @SerializedName("bytes") - @Expose - public long bytes; - @SerializedName("bits_per_second") - @Expose - public float bitsPerSecond; - @SerializedName("sender") - @Expose - public boolean sender; - @SerializedName("packets") - @Expose - public int packets; - @SerializedName("jitter_ms") - @Expose - public float jitterMs; - @SerializedName("lost_packets") - @Expose - public int lostPackets; - @SerializedName("lost_percent") - @Expose - public float lostPercent; -} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/SumSent.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/SumSent.java deleted file mode 100644 index a83c7641..00000000 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/SumSent.java +++ /dev/null @@ -1,50 +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.JSON; - - -import com.google.gson.annotations.Expose; -import com.google.gson.annotations.SerializedName; - -public class SumSent { - - @SerializedName("start") - @Expose - public int start; - @SerializedName("end") - @Expose - public float end; - @SerializedName("seconds") - @Expose - public float seconds; - @SerializedName("bytes") - @Expose - public long bytes; - @SerializedName("bits_per_second") - @Expose - public float bitsPerSecond; - @SerializedName("retransmits") - @Expose - public int retransmits; - @SerializedName("sender") - @Expose - public boolean sender; - @SerializedName("packets") - @Expose - public int packets; - @SerializedName("jitter_ms") - @Expose - public float jitterMs; - @SerializedName("lost_packets") - @Expose - public int lostPackets; - @SerializedName("lost_percent") - @Expose - public float lostPercent; -} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/TestStart.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/TestStart.java deleted file mode 100644 index 99fecc99..00000000 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/TestStart.java +++ /dev/null @@ -1,48 +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.JSON; - - -import com.google.gson.annotations.Expose; -import com.google.gson.annotations.SerializedName; - -public class TestStart { - - @SerializedName("protocol") - @Expose - public String protocol; - @SerializedName("num_streams") - @Expose - public int numStreams; - @SerializedName("blksize") - @Expose - public int blksize; - @SerializedName("omit") - @Expose - public int omit; - @SerializedName("duration") - @Expose - public int duration; - @SerializedName("bytes") - @Expose - public int bytes; - @SerializedName("blocks") - @Expose - public int blocks; - @SerializedName("reverse") - @Expose - public int reverse; - @SerializedName("tos") - @Expose - public int tos; - @SerializedName("target_bitrate") - @Expose - public int targetBitrate; - -} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Timestamp.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Timestamp.java deleted file mode 100644 index bdebf702..00000000 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Timestamp.java +++ /dev/null @@ -1,24 +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.JSON; - - -import com.google.gson.annotations.Expose; -import com.google.gson.annotations.SerializedName; - -public class Timestamp { - - @SerializedName("time") - @Expose - public String time; - @SerializedName("timesecs") - @Expose - public long timesecs; - -} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Udp.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Udp.java deleted file mode 100644 index e2ab4a90..00000000 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Udp.java +++ /dev/null @@ -1,51 +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.JSON; - -import com.google.gson.annotations.Expose; -import com.google.gson.annotations.SerializedName; - -public class Udp { - @SerializedName("socket") - @Expose - public int socket; - @SerializedName("start") - @Expose - public int start; - @SerializedName("end") - @Expose - public float end; - @SerializedName("seconds") - @Expose - public float seconds; - @SerializedName("bytes") - @Expose - public long bytes; - @SerializedName("bits_per_second") - @Expose - public float bitsPerSecond; - @SerializedName("packets") - @Expose - public int packets; - @SerializedName("jitter_ms") - @Expose - public float jitterMs; - @SerializedName("lost_packets") - @Expose - public int lostPackets; - @SerializedName("lost_percent") - @Expose - public float lostPercent; - @SerializedName("out_of_order") - @Expose - public int outOfOrder; - @SerializedName("sender") - @Expose - public boolean sender; -} \ No newline at end of file diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/start/Connected.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/start/Connected.java new file mode 100644 index 00000000..33f29b15 --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/start/Connected.java @@ -0,0 +1,21 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.start; + +import org.json.JSONException; +import org.json.JSONObject; + +public class Connected { + public int socket; + public String local_host; + public int local_port; + public String remote_host; + public int remote_port; + + public void parse(JSONObject data) throws JSONException { + this.socket = data.getInt("socket"); + this.local_host = data.getString("local_host"); + this.local_port = data.getInt("local_port"); + this.remote_host = data.getString("remote_host"); + this.remote_port = data.getInt("remote_port"); + + } +} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/start/ConnectingTo.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/start/ConnectingTo.java new file mode 100644 index 00000000..6ffdb23d --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/start/ConnectingTo.java @@ -0,0 +1,21 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.start; + +import org.json.JSONException; +import org.json.JSONObject; + +public class ConnectingTo{ + private String host; + private int port; + + public void parse(JSONObject data) throws JSONException { + this.host = data.getString("host"); + this.port = data.getInt("port"); + } + + public String getHost() { + return host; + } + public int getPort() { + return port; + } +} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/start/Start.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/start/Start.java new file mode 100644 index 00000000..30cea994 --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/start/Start.java @@ -0,0 +1,88 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.start; + +import java.util.ArrayList; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +public class Start{ + private ArrayList connected = new ArrayList(); + private String version; + private String system_info; + private Timestamp timestamp; + private ConnectingTo connecting_to; + private String cookie; + private int tcp_mss_default; + private int target_bitrate; + private int fq_rate; + private int sock_bufsize; + private int sndbuf_actual; + private int rcvbuf_actual; + private TestStart test_start; + + public Start(){ + } + public void parseStart(JSONObject data) throws JSONException { + JSONArray connected = data.getJSONArray("connected"); + for (int i = 0; i < connected.length(); i++) { + Connected connectedObj = new Connected(); + connectedObj.parse(connected.getJSONObject(i)); + this.connected.add(connectedObj); + } + this.version = data.getString("version"); + this.system_info = data.getString("system_info"); + this.timestamp = new Timestamp(); + this.timestamp.parse(data.getJSONObject("timestamp")); + this.connecting_to = new ConnectingTo(); + this.connecting_to.parse(data.getJSONObject("connecting_to")); + this.cookie = data.getString("cookie"); + if(data.has("tcp_mss_default")) this.tcp_mss_default = data.getInt("tcp_mss_default"); + this.target_bitrate = data.getInt("target_bitrate"); + this.fq_rate = data.getInt("fq_rate"); + this.sock_bufsize = data.getInt("sock_bufsize"); + this.sndbuf_actual = data.getInt("sndbuf_actual"); + this.rcvbuf_actual = data.getInt("rcvbuf_actual"); + this.test_start = new TestStart(); + this.test_start.parse(data.getJSONObject("test_start")); + } + public ArrayList getConnected() { + return connected; + } + public String getVersion() { + return version; + } + public String getSystem_info() { + return system_info; + } + public Timestamp getTimestamp() { + return timestamp; + } + public ConnectingTo getConnecting_to() { + return connecting_to; + } + public String getCookie() { + return cookie; + } + public int getTcp_mss_default() { + return tcp_mss_default; + } + public int getTarget_bitrate() { + return target_bitrate; + } + public int getFq_rate() { + return fq_rate; + } + public int getSock_bufsize() { + return sock_bufsize; + } + public int getSndbuf_actual() { + return sndbuf_actual; + } + public int getRcvbuf_actual() { + return rcvbuf_actual; + } + public TestStart getTest_start() { + return test_start; + } + +} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/start/TestStart.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/start/TestStart.java new file mode 100644 index 00000000..d6d190b9 --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/start/TestStart.java @@ -0,0 +1,36 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.start; + +import org.json.JSONException; +import org.json.JSONObject; + +public class TestStart{ + public String protocol; + public int num_streams; + public int blksize; + public int omit; + public int duration; + public int bytes; + public int blocks; + public int reverse; + public int tos; + public int target_bitrate; + public boolean bidir; + public int fqrate; + public int interval; + + public void parse(JSONObject data) throws JSONException { + this.protocol = data.getString("protocol"); + this.num_streams = data.getInt("num_streams"); + this.blksize = data.getInt("blksize"); + this.omit = data.getInt("omit"); + this.duration = data.getInt("duration"); + this.bytes = data.getInt("bytes"); + this.blocks = data.getInt("blocks"); + this.reverse = data.getInt("reverse"); + this.tos = data.getInt("tos"); + this.target_bitrate = data.getInt("target_bitrate"); + this.bidir = 1 == data.getInt("bidir"); + this.fqrate = data.getInt("fqrate"); + this.interval = data.getInt("interval"); + } +} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/start/Timestamp.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/start/Timestamp.java new file mode 100644 index 00000000..27d25598 --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/start/Timestamp.java @@ -0,0 +1,20 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.start; + +import org.json.JSONException; +import org.json.JSONObject; + +public class Timestamp{ + private String time; + private int timesecs; + + public void parse(JSONObject data) throws JSONException { + this.time = data.getString("time"); + this.timesecs = data.getInt("timesecs"); + } + public String getTime() { + return time; + } + public int getTimesecs() { + return timesecs; + } +} 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 74e9b64e..75a4dfaa 100644 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/LoggingService.java +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/LoggingService.java @@ -25,16 +25,12 @@ import android.os.Looper; import android.telephony.TelephonyManager; import android.util.Log; +import android.widget.ImageView; import android.widget.Toast; import androidx.annotation.Nullable; import androidx.core.app.NotificationCompat; -import androidx.lifecycle.Observer; import androidx.preference.PreferenceManager; -import androidx.work.Data; -import androidx.work.OneTimeWorkRequest; -import androidx.work.WorkInfo; -import androidx.work.WorkManager; import com.influxdb.client.domain.WritePrecision; import com.influxdb.client.write.Point; @@ -46,20 +42,16 @@ import java.nio.file.Files; import java.nio.file.Paths; import java.util.ArrayList; -import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Objects; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import de.fraunhofer.fokus.OpenMobileNetworkToolkit.DataProvider.CellInformation; import de.fraunhofer.fokus.OpenMobileNetworkToolkit.DataProvider.DataProvider; import de.fraunhofer.fokus.OpenMobileNetworkToolkit.InfluxDB2x.InfluxdbConnection; import de.fraunhofer.fokus.OpenMobileNetworkToolkit.InfluxDB2x.InfluxdbConnections; -import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Ping.PingWorker; public class LoggingService extends Service { private static final String TAG = "Logging_Service"; @@ -81,15 +73,9 @@ public class LoggingService extends Service { private Handler localFileHandler; private List logFilePoints; private FileOutputStream stream; - private FileOutputStream ping_stream; private int interval; private Context context; - private Handler pingLogging; - private String pingInput; - private WorkManager wm; - GlobalVars gv; - private ArrayList pingWRs; // Handle local on-device logging to logfile private final Runnable localFileUpdate = new Runnable() { @Override @@ -231,19 +217,6 @@ public int onStartCommand(Intent intent, int flags, int startId) { tm = GlobalVars.getInstance().getTm(); cp = gv.isCarrier_permissions(); } - wm = WorkManager.getInstance(context); - if(intent != null) { - if (intent.getBooleanExtra("ping", false)) { - if (intent.getBooleanExtra("ping_stop", false)) { - stopPing(); - } else { - pingInput = intent.getStringExtra("input"); - pingWRs = new ArrayList<>(); - setupPing(); - } - return START_STICKY; - } - } // create intent for notifications Intent notificationIntent = new Intent(this, MainActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_IMMUTABLE); @@ -513,7 +486,10 @@ private void setupRemoteInfluxDB() { Objects.requireNonNull(ic).open_write_api(); remoteInfluxHandler = new Handler(Objects.requireNonNull(Looper.myLooper())); remoteInfluxHandler.post(RemoteInfluxUpdate); - gv.getLog_status().setColorFilter(Color.argb(255, 255, 0, 0)); + ImageView log_status = gv.getLog_status(); + if (log_status != null) { + gv.getLog_status().setColorFilter(Color.argb(255, 255, 0, 0)); + } } /** @@ -541,151 +517,6 @@ private void stopRemoteInfluxDB() { gv.getLog_status().setColorFilter(Color.argb(255, 192, 192, 192)); } - private long unixTimestampWithMicrosToMillis(double timestampWithMicros) { - long seconds = (long) timestampWithMicros; - long microseconds = (long) ((timestampWithMicros - seconds) * 1e6); - return seconds * 1000 + microseconds / 1000; - } - - private void setupPing(){ - Log.d(TAG, "setupLocalFile"); - - // build log file path - String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).getAbsolutePath() + "/omnt/ping/"; - try { - Files.createDirectories(Paths.get(path)); - } catch (IOException e) { - throw new RuntimeException(e); - } - - // create the log file - SimpleDateFormat formatter = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss", Locale.US); - Date now = new Date(); - String filename = path + formatter.format(now) + ".txt"; - Log.d(TAG, "logfile: " + filename); - File logfile = new File(filename); - try { - logfile.createNewFile(); - } catch (IOException e) { - throw new RuntimeException(e); - } - - // get an output stream - try { - ping_stream = new FileOutputStream(logfile); - } catch (FileNotFoundException e) { - Toast.makeText(context, "logfile not created", Toast.LENGTH_SHORT).show(); - e.printStackTrace(); - } - - pingLogging = new Handler(Objects.requireNonNull(Looper.myLooper())); - pingLogging.post(pingUpdate); - } - - private final Runnable pingUpdate = new Runnable() { - @Override - public void run() { - - Data data = new Data.Builder() - .putString("input", pingInput) - .build(); - OneTimeWorkRequest pingWR = - new OneTimeWorkRequest.Builder(PingWorker.class) - .setInputData(data) - .addTag("Ping").build(); - pingWRs.add(pingWR); - - wm.beginWith(pingWR).enqueue(); - Observer observer = new Observer() { - @Override - public void onChanged(Object o) { - WorkInfo workInfo = (WorkInfo) o; - WorkInfo.State state = workInfo.getState(); - Log.d(TAG, "onChanged: "+state.toString()); - if(state == WorkInfo.State.RUNNING) { - String line = workInfo.getProgress().getString("ping_line"); - if(line == null) return; - Pattern pattern = Pattern.compile("\\[(\\d+\\.\\d+)\\] (\\d+ bytes from (\\S+|\\d+\\.\\d+\\.\\d+\\.\\d+)): icmp_seq=(\\d+) ttl=(\\d+) time=([\\d.]+) ms"); - Matcher matcher = pattern.matcher(line); - Intent intent = new Intent("ping"); - - if(matcher.find()){ - long unixTimestamp = unixTimestampWithMicrosToMillis(Double.parseDouble(matcher.group(1))); - int icmpSeq = Integer.parseInt(matcher.group(4)); - int ttl = Integer.parseInt(matcher.group(5)); - String host = matcher.group(3); - double rtt = Double.parseDouble(matcher.group(6)); - intent.putExtra("ping_running", true); - intent.putExtra("ping_rtt", rtt); - - // Create an InfluxDB point with the Unix timestamp - Point point = Point.measurement("Ping") - .time(unixTimestamp, WritePrecision.MS) - .addTags(dp.getTagsMap()) - .addTag("toHost", host) - .addField("icmp_seq", icmpSeq) - .addField("ttl", ttl) - .addField("rtt", rtt); - try { - ping_stream.write((point.toLineProtocol() + "\n").getBytes()); - } catch (IOException e) { - e.printStackTrace(); - } - - if (sp.getBoolean("enable_influx", false) && ic != null) { - try { - ic.writePoints(Arrays.asList(point)); - } catch (IOException e) { - e.printStackTrace(); - } - } - - Log.d(TAG, "doWork: Point:"+point.toLineProtocol()); - - } - intent.putExtra("ping_line", line); - sendBroadcast(intent); - - return; - } - if(state == WorkInfo.State.ENQUEUED) return; - if(state == WorkInfo.State.CANCELLED) { - try { - ping_stream.close(); - } catch (IOException e) { - e.printStackTrace(); - } - return; - }; - if(state == WorkInfo.State.FAILED) { - pingLogging.postDelayed(pingUpdate, 1000); - return; - } - - wm.getWorkInfoByIdLiveData(pingWR.getId()).removeObserver(this); - pingLogging.postDelayed(pingUpdate, 1000); - } - }; - wm.getWorkInfoByIdLiveData(pingWR.getId()).observeForever(observer); - } - }; - - private void stopPing(){ - if(pingLogging != null) pingLogging.removeCallbacks(pingUpdate); - try { - if (ping_stream != null) ping_stream.close(); - } catch (IOException e) { - throw new RuntimeException(e); - } - - wm.cancelAllWorkByTag("Ping"); - Intent intent = new Intent("ping_rtt"); - intent.putExtra("ping_rtt", 0.0); - intent.putExtra("ping_running", false); - sendBroadcast(intent); - pingWRs = new ArrayList<>(); - } - @Nullable @Override public IBinder onBind(Intent intent) { diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Metric/METRIC_TYPE.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Metric/METRIC_TYPE.java new file mode 100644 index 00000000..7b0ffb8d --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Metric/METRIC_TYPE.java @@ -0,0 +1,10 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Metric; + +public enum METRIC_TYPE { + THROUGHPUT, + RTT, + JITTER, + PACKET_LOSS, + PING_RTT, + PING_PACKET_LOSS, + } diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Metric/Metric.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Metric/Metric.java new file mode 100644 index 00000000..b8507f50 --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Metric/Metric.java @@ -0,0 +1,238 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Metric; + +import android.content.Context; +import android.graphics.Typeface; +import android.graphics.drawable.GradientDrawable; +import android.view.Gravity; +import android.widget.LinearLayout; +import android.widget.TextView; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.R; +import java.util.ArrayList; +import java.util.Locale; + +public class Metric { + private LinearLayout mean; + private LinearLayout median; + private LinearLayout max; + private LinearLayout min; + private LinearLayout last; + private TextView directionName; + private ArrayList meanList = new ArrayList<>(); + private double maxValueSum = Double.MIN_VALUE; + private double minValueSum = Double.MAX_VALUE; + private METRIC_TYPE metricType; + private Context ct; + private LinearLayout mainLL; + + public Metric(METRIC_TYPE metricType, Context ct){ + this.metricType = metricType; + this.ct = ct; + } + + private LinearLayout createTile(String key) { + LinearLayout ll = new LinearLayout(ct); + + GradientDrawable gd = new GradientDrawable(); + gd.setColor(ct.getColor(R.color.cardview_dark_background)); + gd.setCornerRadius(10); + gd.setStroke(2, 0xFF000000); + ll.setBackground(gd); + ll.setMinimumHeight(ll.getWidth()); + ll.setGravity(Gravity.CENTER); + + ll.setOrientation(LinearLayout.VERTICAL); + LinearLayout.LayoutParams foo = new LinearLayout.LayoutParams(200, 150); + foo.weight = 1; + foo.setMargins(10, 10, 10, 10); + ll.setLayoutParams(foo); + TextView keyView = new TextView(ct); + keyView.setGravity(Gravity.CENTER); + LinearLayout.LayoutParams keyViewLayoutParams = new LinearLayout.LayoutParams(200, 50); + keyViewLayoutParams.setMargins(0, 0, 0, 10); + keyView.setLayoutParams(keyViewLayoutParams); + keyView.setTypeface(null, Typeface.BOLD); + + keyView.setText(key); + ll.addView(keyView); + TextView valueView = new TextView(ct); + valueView.setGravity(Gravity.CENTER); + LinearLayout.LayoutParams valueViewLayoutParams = new LinearLayout.LayoutParams(200, 50); + valueViewLayoutParams.setMargins(0, 0, 0, 0); + valueView.setLayoutParams(valueViewLayoutParams); + ll.addView(valueView); + return ll; + } + + private LinearLayout createLL(String key) { + LinearLayout ll = null; + switch (key) { + case "mean": + mean = createTile(key); + ll = mean; + break; + case "median": + median = createTile(key); + ll = median; + break; + case "max": + max = createTile(key); + ll = max; + break; + case "min": + min = createTile(key); + ll = min; + break; + case "last": + last = createTile(key); + ll = last; + break; + } + return ll; + } + private String getFormatedString(double value){ + switch (this.metricType){ + case THROUGHPUT: + return String.format(Locale.getDefault(), "%.2f", value/1e+6); + case RTT: + case PACKET_LOSS: + case JITTER: + case PING_RTT: + case PING_PACKET_LOSS: + return String.format(Locale.getDefault(), "%.2f", value); + } + return Double.toString(value); + } + public LinearLayout createMainLL(String direction) { + mainLL = new LinearLayout(ct); + LinearLayout.LayoutParams foo1 = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT + ); + mainLL.setOrientation(LinearLayout.VERTICAL); + mainLL.setLayoutParams(foo1); + + directionName = new TextView(ct); + directionName.setText(direction); + mainLL.addView(directionName); + + LinearLayout cardViewResult = new LinearLayout(ct); + LinearLayout.LayoutParams cardParams = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT + ); + cardViewResult.setOrientation(LinearLayout.HORIZONTAL); + cardViewResult.setLayoutParams(cardParams); + + cardViewResult.addView(createLL("mean")); + cardViewResult.addView(createLL("median")); + cardViewResult.addView(createLL("max")); + cardViewResult.addView(createLL("min")); + cardViewResult.addView(createLL("last")); + mainLL.addView(cardViewResult); + return mainLL; + } + + public double calcMean(){ + return meanList.stream().mapToDouble(a -> a).sum()/meanList.size(); + } + + public double calcMedian(){ + this.getMeanList().sort(Double::compareTo); + return meanList.get(Math.round(meanList.size()/2)); + } + + public double calcMax(){ + return meanList.stream().mapToDouble(a -> a).max().getAsDouble(); + } + + public double calcMin(){ + return meanList.stream().mapToDouble(a -> a).min().getAsDouble(); + } + public void update(Double value){ + this.meanList.add(value); + + ((TextView)mean.getChildAt(1)).setText(String.format(" %s", getFormatedString(calcMean()))); + ((TextView)median.getChildAt(1)).setText(String.format(" %s", getFormatedString(calcMedian()))); + ((TextView)max.getChildAt(1)).setText(String.format(" %s", getFormatedString(calcMax()))); + ((TextView)min.getChildAt(1)).setText(String.format(" %s", getFormatedString(calcMin()))); + ((TextView)last.getChildAt(1)).setText(String.format(" %s", getFormatedString(value))); + } + + public ArrayList getMeanList() { + return meanList; + } + public void setMaxValueSum(double maxValueSum) { + this.maxValueSum = maxValueSum; + } + public void setMinValueSum(double minValueSum) { + this.minValueSum = minValueSum; + } + public double getMaxValueSum() { + return maxValueSum; + } + public double getMinValueSum() { + return minValueSum; + } + + public void setMeanList(ArrayList meanList) { + this.meanList = meanList; + } + + public LinearLayout getMean() { + return mean; + } + + public void setMean(LinearLayout mean) { + this.mean = mean; + } + + public LinearLayout getMedian() { + return median; + } + + public void setMedian(LinearLayout median) { + this.median = median; + } + + public LinearLayout getMax() { + return max; + } + + public void setMax(LinearLayout max) { + this.max = max; + } + + public LinearLayout getMin() { + return min; + } + + public void setMin(LinearLayout min) { + this.min = min; + } + + public LinearLayout getLast() { + return last; + } + + public void setLast(LinearLayout last) { + this.last = last; + } + + + public TextView getDirectionName() { + return directionName; + } + + public void setDirectionName(TextView directionName) { + this.directionName = directionName; + } + + public void resetMetric(){ + meanList.clear(); + this.maxValueSum = Double.MIN_VALUE; + this.minValueSum = Double.MAX_VALUE; + } + public void setVisibility(int visibility){ + mainLL.setVisibility(visibility); + } + } diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingFragment.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingFragment.java index 6b8af0cf..037950c2 100644 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingFragment.java +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingFragment.java @@ -9,18 +9,13 @@ package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Ping; 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.graphics.Color; import android.os.Bundle; import android.os.Handler; import android.text.Editable; import android.text.TextWatcher; -import android.text.method.ScrollingMovementMethod; import android.util.Log; import android.view.LayoutInflater; import android.view.View; @@ -28,19 +23,19 @@ import android.widget.CompoundButton; import android.widget.EditText; import android.widget.LinearLayout; -import android.widget.ScrollView; import android.widget.Switch; -import android.widget.TextView; import androidx.fragment.app.Fragment; -import androidx.work.WorkManager; - -import com.github.anastr.speedviewlib.TubeSpeedometer; -import com.github.anastr.speedviewlib.components.Style; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Metric.METRIC_TYPE; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Metric.Metric; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Ping.PingInformations.PacketLossLine; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Ping.PingInformations.PingInformation; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Ping.PingInformations.RTTLine; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import java.io.FileOutputStream; -import de.fraunhofer.fokus.OpenMobileNetworkToolkit.LoggingService; import de.fraunhofer.fokus.OpenMobileNetworkToolkit.R; public class PingFragment extends Fragment { @@ -52,9 +47,10 @@ public class PingFragment extends Fragment { private FileOutputStream stream; private EditText input; private Context ct; - private TextView pingViewer; - private ScrollView scrollView; private SharedPreferences sp; + private Metric rttMetric; + private Metric packetLossMetric; + public PingFragment() { } @SuppressLint("UnspecifiedRegisterReceiverFlag") @@ -62,21 +58,33 @@ public PingFragment() { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } - private void setupPing(){ + + private void startPingService(){ input.setEnabled(false); - pingViewer.setText(""); - Intent pingStart = new Intent(ct, LoggingService.class); - pingStart.putExtra("input", input.getText().toString()); - pingStart.putExtra("ping", true); + Intent pingStart = new Intent(ct, PingService.class); ct.startService(pingStart); + rttMetric.resetMetric(); + PingParser pingParser = PingParser.getInstance(null); + pingParser.addPropertyChangeListener(new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + PingInformation pi = (PingInformation) evt.getNewValue(); + switch (pi.getLineType()){ + case RTT: + rttMetric.update( ((RTTLine)pi).getRtt()); + break; + case PACKET_LOSS: + packetLossMetric.update(((PacketLossLine)pi).getPacketLoss()); + //packetLossMetric.setVisibility(View.VISIBLE); + break; + } + } + }); } - private void stopPing(){ + private void stopPingService(){ input.setEnabled(true); - Intent pingStart = new Intent(ct, LoggingService.class); - pingStart.putExtra("ping", true); - pingStart.putExtra("ping_stop", true); - pingStart.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - ct.startService(pingStart); + Intent pingStart = new Intent(ct, PingService.class); + ct.stopService(pingStart); } @@ -117,39 +125,32 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, input.setText(sp.getString("ping_input", "-w 5 8.8.8.8")); ct = requireContext(); - pingViewer = horizontalLL1.findViewById(R.id.ping_viewer); - scrollView = horizontalLL1.findViewById(R.id.ping_scrollviewer); saveTextInputToSharedPreferences(input, "ping_input"); - aSwitch.setChecked(sp.getBoolean("switch", false)); + aSwitch.setChecked(PingService.isRunning()); aSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton compoundButton, boolean b) { Log.d(TAG, "onCheckedChanged: "+b); - if(b) setupPing(); - else stopPing(); - sp.edit().putBoolean("switch", b).apply(); + if(b) startPingService(); + else stopPingService(); } }); - BroadcastReceiver receiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - double rtt = intent.getExtras().getDouble("ping_rtt"); - boolean ping_running = intent.getExtras().getBoolean("ping_running"); - handleInput(ping_running); - String pingLine = intent.getExtras().getString("ping_line"); - pingViewer.append(pingLine+"\n"); - scrollView.fullScroll(View.FOCUS_DOWN); - } - }; - requireActivity().registerReceiver(receiver, new IntentFilter("ping"), Context.RECEIVER_EXPORTED); - - - pingViewer.setMovementMethod(new ScrollingMovementMethod()); + rttMetric = new Metric(METRIC_TYPE.PING_RTT, ct); + packetLossMetric = new Metric(METRIC_TYPE.PING_PACKET_LOSS, ct); + LinearLayout metricsLL = new LinearLayout(ct); + metricsLL.setOrientation(LinearLayout.VERTICAL); + LinearLayout.LayoutParams foo1 = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT + ); + metricsLL.setLayoutParams(foo1); + metricsLL.addView(rttMetric.createMainLL("RTT [ms]")); + metricsLL.addView(packetLossMetric.createMainLL("Packet Loss [%]")); + + horizontalLL1.addView(metricsLL); + //packetLossMetric.setVisibility(View.INVISIBLE); return v; } - - - } \ No newline at end of file diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingInformations/LINEType.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingInformations/LINEType.java new file mode 100644 index 00000000..c3580dd7 --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingInformations/LINEType.java @@ -0,0 +1,7 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Ping.PingInformations; + +public enum LINEType { + RTT, + PACKET_LOSS, + UNREACHABLE, TIMEOUT, UNKNOWN +} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingInformations/PacketLossLine.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingInformations/PacketLossLine.java new file mode 100644 index 00000000..33bbc2d7 --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingInformations/PacketLossLine.java @@ -0,0 +1,41 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Ping.PingInformations; + +import com.influxdb.client.write.Point; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class PacketLossLine extends PingInformation{ + private double packetLoss; + private long packetsTransmitted; + private long packetsReceived; + Pattern pattern = Pattern.compile("(\\d+)\\s+packets\\s+transmitted.*?(\\d+)\\s+received.*?(\\d+%)\\s+packet\\s+loss.*?time\\s+(\\d+ms)"); + Matcher matcher; + public PacketLossLine(String line) { + super(line); + this.setLineType(LINEType.PACKET_LOSS); + } + public void parse(){ + matcher = pattern.matcher(this.getLine()); + if(matcher.find()){ + packetsTransmitted = Long.parseLong(matcher.group(1)); + packetsReceived = Long.parseLong(matcher.group(2)); + packetLoss = Double.parseDouble(matcher.group(3).replace("%", "")); + } + } + public long getPacketsReceived() { + return packetsReceived; + } + public long getPacketsTransmitted() { + return packetsTransmitted; + } + public double getPacketLoss() { + return packetLoss; + } + + public Point getPoint(){ + return super.getPoint() + .addField("packets_transmitted", this.getPacketsTransmitted()) + .addField("packets_received", this.getPacketsReceived()) + .addField("packet_loss", this.getPacketLoss()); + } +} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingInformations/PingInformation.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingInformations/PingInformation.java new file mode 100644 index 00000000..3b0f53fc --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingInformations/PingInformation.java @@ -0,0 +1,61 @@ +/* + * 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.Ping.PingInformations; + +import com.influxdb.client.domain.WritePrecision; +import com.influxdb.client.write.Point; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.DataProvider.DataProvider; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class PingInformation { + private String line; + private LINEType lineType; + private Double unixTimestamp; + private DataProvider dp; + public PingInformation(String line) { + this.line = line; + } + + private double unixTimestampWithMicrosToMillis(double timestampWithMicros) { + long seconds = (long) timestampWithMicros; + long microseconds = (long) ((timestampWithMicros - seconds) * 1e6); + return seconds * 1000 + microseconds / 1000; + } + + private void parseUnixTimestamp(){ + Pattern pattern = Pattern.compile("\\[\\d+\\.\\d+\\]"); + Matcher matcher = pattern.matcher(line); + if (matcher.find()) { + String unixTimestampString = matcher.group(0).replace("[", "").replace("]", ""); + unixTimestamp = unixTimestampWithMicrosToMillis(Double.parseDouble(unixTimestampString)); + } + } + public void parse() { + parseUnixTimestamp(); + } + public void setLineType(LINEType lineType) { + this.lineType = lineType; + } + public LINEType getLineType() { + return lineType; + } + public String getLine() { + return line; + } + public Double getUnixTimestamp() { + return unixTimestamp; + } + + public Point getPoint(){ + Point point = new Point("Ping"); + point.time(this.getUnixTimestamp(), WritePrecision.MS); + return point; + } +} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingInformations/RTTLine.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingInformations/RTTLine.java new file mode 100644 index 00000000..f162caf3 --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingInformations/RTTLine.java @@ -0,0 +1,55 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Ping.PingInformations; + +import com.influxdb.client.domain.WritePrecision; +import com.influxdb.client.write.Point; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class RTTLine extends PingInformation{ + public static Pattern pattern = Pattern.compile( + "\\[(\\d+\\.\\d+)\\] (\\d+ bytes from (\\S+|\\d+\\.\\d+\\.\\d+\\.\\d+)): icmp_seq=(\\d+) ttl=(\\d+) time=([\\d.]+) ms"); + private int icmpSeq; + private int ttl; + private double rtt; + private String host; + + public RTTLine(String line) { + super(line); + super.setLineType(LINEType.RTT); + } + + public void parse(){ + super.parse(); + Matcher matcher = pattern.matcher(this.getLine()); + if (matcher.find()) { + icmpSeq = Integer.parseInt(matcher.group(4)); + ttl = Integer.parseInt(matcher.group(5)); + host = matcher.group(3); + rtt = Double.parseDouble(matcher.group(6)); + } + } + + public double getRtt() { + return rtt; + } + + public int getIcmpSeq() { + return icmpSeq; + } + + public int getTtl() { + return ttl; + } + + public String getHost() { + return host; + } + + public Point getPoint(){ + return super.getPoint() + .addTag("toHost", this.getHost()) + .addField("icmp_seq", this.getIcmpSeq()) + .addField("ttl", this.getTtl()) + .addField("rtt", this.getRtt()); + } +} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingParser.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingParser.java new file mode 100644 index 00000000..31a6f863 --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingParser.java @@ -0,0 +1,93 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Ping; + +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Ping.PingInformations.LINEType; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Ping.PingInformations.PacketLossLine; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Ping.PingInformations.PingInformation; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Ping.PingInformations.RTTLine; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.io.BufferedReader; +import java.io.IOException; +import java.util.ArrayList; + +public class PingParser { + private static PingParser instance = null; + private BufferedReader br; + private ArrayList lines; + + private PropertyChangeSupport support; + private PropertyChangeListener listener; + private PingParser(BufferedReader br) { + this.br = br; + this.lines = new ArrayList<>(); + support = new PropertyChangeSupport(this); + } + + public static PingParser getInstance(BufferedReader br){ + if (instance == null) instance = new PingParser(br); + if(br != null); instance.setBr(br); + return instance; + } + private LINEType getLineType(String line){ + if (line.contains("bytes from")) { + return LINEType.RTT; + } else if (line.contains("Unreachable")) { + return LINEType.UNREACHABLE; + } else if (line.contains("Request timeout")) { + return LINEType.TIMEOUT; + } else if (line.contains("packets transmitted")){ + return LINEType.PACKET_LOSS; + } else { + return LINEType.UNKNOWN; + } + } + public void parse(){ + String line; + try { + while((line = this.br.readLine()) != null){ + PingInformation pi = null; + switch (getLineType(line)){ + case RTT: + pi = new RTTLine(line); + case UNREACHABLE: + //TDODO + break; + case TIMEOUT: + //TODO + break; + case PACKET_LOSS: + pi = new PacketLossLine(line); + break; + case UNKNOWN: + break; + } + if(pi == null) continue; + pi.parse(); + this.lines.add(pi); + support.firePropertyChange("ping", null, pi); + } + } catch (IOException e){ + + } + } + + public void addPropertyChangeListener(PropertyChangeListener listener){ + support.addPropertyChangeListener(listener); + } + public void setListener(PropertyChangeListener listener){ + this.listener = listener; + } + public PropertyChangeListener getListener(){ + return this.listener; + } + public void removePropertyChangeListener(PropertyChangeListener listener){ + support.removePropertyChangeListener(listener); + } + + public void setBr(BufferedReader br){ + this.br = br; + } + + +} + diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingService.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingService.java new file mode 100644 index 00000000..3db18077 --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingService.java @@ -0,0 +1,266 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Ping; + +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.pm.PackageManager; +import android.graphics.Color; +import android.icu.text.SimpleDateFormat; +import android.os.Build; +import android.os.Environment; +import android.os.Handler; +import android.os.IBinder; +import android.os.Looper; +import android.util.Log; +import android.widget.Toast; +import androidx.annotation.Nullable; +import androidx.core.app.NotificationCompat; +import androidx.lifecycle.Observer; +import androidx.preference.Preference; +import androidx.preference.PreferenceManager; +import androidx.work.Data; +import androidx.work.OneTimeWorkRequest; +import androidx.work.WorkInfo; +import androidx.work.WorkManager; +import com.influxdb.client.domain.WritePrecision; +import com.influxdb.client.write.Point; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.DataProvider.DataProvider; +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.MainActivity; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Ping.PingInformations.PingInformation; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.R; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.HashMap; +import java.util.Locale; +import java.util.Objects; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class PingService extends Service { + private static final String TAG = "PingService"; + private FileOutputStream ping_stream; + private Handler pingLogging; + private String pingInput; + private WorkManager wm; + private Context context; + private ArrayList pingWRs; + private SharedPreferences pingSP; + private SharedPreferences defaultSP; + NotificationCompat.Builder builder; + DataProvider dp; + InfluxdbConnection influx; + private static boolean isRunning = false; + private static PingParser pingParser; + private Process pingProcess; + private String pingCommand; + private Runtime runtime = Runtime.getRuntime(); + private PropertyChangeListener propertyChangeListener; + HashMap parsedCommand = new HashMap<>(); + + @Nullable + @Override + public IBinder onBind(Intent intent) { + return null; + } + @Override + public void onDestroy() { + Log.d(TAG, "onDestroy: Stop logging service"); + stopPing(); + } + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + Log.d(TAG, "onStartCommand: Start logging service"); + GlobalVars gv = GlobalVars.getInstance(); + // setup class variables + dp = gv.get_dp(); + context = getApplicationContext(); + pingSP = context.getSharedPreferences("Ping", Context.MODE_PRIVATE); + defaultSP = PreferenceManager.getDefaultSharedPreferences(context); + if(defaultSP.getBoolean("enable_influx", false)) influx = InfluxdbConnections.getRicInstance(context); + wm = WorkManager.getInstance(context); + if(intent == null) return START_NOT_STICKY; + pingInput = intent.getStringExtra("input"); + pingWRs = new ArrayList<>(); + setupPing(); + isRunning = true; + return START_STICKY; + } + + + private void setupPing(){ + Log.d(TAG, "starting Ping Service..."); + + String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).getAbsolutePath() + "/omnt/ping/"; + try { + Files.createDirectories(Paths.get(path)); + } catch (IOException e) { + Toast.makeText(context, "could not create /omnt/ping Dir!", Toast.LENGTH_SHORT).show(); + pingSP.edit().putBoolean("ping", false).apply(); + Log.d(TAG, "setupPing: could not create /omnt/ping Dir!"); + return; + } + + // create the log file + SimpleDateFormat formatter = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss", Locale.US); + Date now = new Date(); + String filename = path + formatter.format(now) + ".txt"; + Log.d(TAG, "logfile: " + filename); + File logfile = new File(filename); + try { + logfile.createNewFile(); + } catch (IOException e) { + Toast.makeText(context, "could not create logfile "+filename, Toast.LENGTH_SHORT).show(); + Log.d(TAG, "setupPing: could not create logfile"); + pingSP.edit().putBoolean("ping", false).apply(); + return; + } + + // get an output stream + try { + ping_stream = new FileOutputStream(logfile); + } catch (FileNotFoundException e) { + Toast.makeText(context, "could not create output stream", Toast.LENGTH_SHORT).show(); + Log.d(TAG, "setupPing: could not create output stream"); + pingSP.edit().putBoolean("ping", false).apply(); + return; + } + pingSP.edit().putBoolean("ping", true).apply(); + pingLogging = new Handler(Objects.requireNonNull(Looper.myLooper())); + PingParser pingParser = PingParser.getInstance(null); + propertyChangeListener = pingParser.getListener(); + if(propertyChangeListener != null){ + pingParser.removePropertyChangeListener(propertyChangeListener); + } + propertyChangeListener = new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + PingInformation pi = (PingInformation) evt.getNewValue(); + + Point point = pi.getPoint(); + point.addTags(dp.getTagsMap()); + Log.d(TAG, "propertyChange: "+point.toLineProtocol()); + try { + ping_stream.write((point.toLineProtocol() + "\n").getBytes()); + } catch (IOException e) { + e.printStackTrace(); + } + + if (defaultSP.getBoolean("enable_influx", false) && influx.getWriteApi() != null) { + try { + influx.writePoints(Arrays.asList(point)); + } catch (IOException e) { + e.printStackTrace(); + } + } + + } + }; + + pingParser.addPropertyChangeListener(propertyChangeListener); + pingParser.setListener(propertyChangeListener); + pingLogging.post(pingUpdate); + } + public void parsePingCommand() { + + String[] commandParts = pingCommand.split("\\s+"); + + String previousPart = null; + for (String part : commandParts) { + switch (part) { + case "ping": + parsedCommand.put("command", part); + break; + case "-w": + if (previousPart != null) { + parsedCommand.put("timeout", previousPart); + } + break; + default: + parsedCommand.put("target", part); + break; + } + previousPart = part; + } + } + + private final Runnable pingUpdate = new Runnable() { + @Override + public void run() { + Data data = new Data.Builder() + .putString("input", pingSP.getString("ping_input", "8.8.8.8")) + .build(); + OneTimeWorkRequest pingWR = + new OneTimeWorkRequest.Builder(PingWorker.class) + .setInputData(data) + .addTag("Ping").build(); + pingWRs.add(pingWR); + + wm.beginWith(pingWR).enqueue(); + Observer observer = new Observer() { + @Override + public void onChanged(Object o) { + WorkInfo workInfo = (WorkInfo) o; + WorkInfo.State state = workInfo.getState(); + switch (state){ + case RUNNING: + case ENQUEUED: + return; + case CANCELLED: + try { + ping_stream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + pingLogging.removeCallbacks(pingUpdate); + return; + } + + wm.getWorkInfoByIdLiveData(pingWR.getId()).removeObserver(this); + pingLogging.postDelayed(pingUpdate, 200); + } + }; + wm.getWorkInfoByIdLiveData(pingWR.getId()).observeForever(observer); + } + }; + + private void stopPing(){ + + if (pingLogging != null )pingLogging.removeCallbacks(pingUpdate); + try { + if (ping_stream != null) ping_stream.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + + for (OneTimeWorkRequest wr : pingWRs){ + wm.cancelWorkById(wr.getId()); + + } + + pingSP.edit().putBoolean("ping", false).apply(); + pingWRs = new ArrayList<>(); + } + public static boolean isRunning() { + return isRunning; + } + + +} + diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingWorker.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingWorker.java index 507a40c5..df2062af 100644 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingWorker.java +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingWorker.java @@ -11,6 +11,7 @@ import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE; import android.app.Notification; +import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.graphics.Color; @@ -24,7 +25,11 @@ import androidx.work.Worker; import androidx.work.WorkerParameters; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Ping.PingInformations.PingInformation; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Ping.PingInformations.RTTLine; import de.fraunhofer.fokus.OpenMobileNetworkToolkit.R; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; @@ -51,6 +56,9 @@ public class PingWorker extends Worker { private String timeRegex = "\\btime=([0-9]+\\.[0-9]+)\\s+ms\\b"; private Pattern pattern = Pattern.compile(timeRegex); private String line = null; + private double rtt; + private NotificationManager notificationManager; + public void parsePingCommand() { @@ -93,9 +101,6 @@ private ForegroundInfo createForegroundInfo(@NonNull String progress) { PendingIntent intent = WorkManager.getInstance(ct) .createCancelPendingIntent(getId()); - - - notification = notificationBuilder .setContentTitle("Ping "+ parsedCommand.get("target")) .setContentText(progress) @@ -113,19 +118,14 @@ private ForegroundInfo createForegroundInfo(@NonNull String progress) { Runnable updateNotification = new Runnable() { @Override public void run() { - Matcher matcher = pattern.matcher(line); - if(matcher.find()){ - double rtt = Double.parseDouble(matcher.group(1)); + if(notification != null){ + notificationBuilder.setContentText(rtt+" ms"); + notificationManager.notify(notificationID, notificationBuilder.build()); + } else { setForegroundAsync(createForegroundInfo(rtt+" ms")); } } }; - Runnable sendBroadcast = new Runnable() { - @Override - public void run() { - setProgressAsync(new Data.Builder().putString("ping_line", line).build()); - } - }; @NonNull @Override @@ -133,6 +133,7 @@ public Result doWork() { lines = new ArrayList<>(); Data data = null; notificationBuilder = new NotificationCompat.Builder(ct, channelId); + notificationManager = ct.getSystemService(NotificationManager.class); try { StringBuilder stringBuilder = new StringBuilder(); @@ -148,29 +149,37 @@ public Result doWork() { new BufferedReader(new InputStreamReader(pingProcess.getInputStream())); - while((line = outputReader.readLine()) != null){ - lines.add(line); - updateNotification.run(); - sendBroadcast.run(); - } - data = new Data.Builder().putStringArray("output", lines.toArray(new String[0])) - .build(); + PingParser pingParser = PingParser.getInstance(outputReader); + + pingParser.addPropertyChangeListener(new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + PingInformation pi = (PingInformation) evt.getNewValue(); + switch(pi.getLineType()){ + case PACKET_LOSS: + break; + case RTT: + rtt = ((RTTLine)pi).getRtt(); + break; + + } + updateNotification.run(); + } + }); + pingParser.parse(); + int result = pingProcess.waitFor(); if(isStopped()){ Log.d(TAG, "doWork: got cancelled because Worker got stopped!"); - return Result.success(data); + return Result.success(); } - int result = pingProcess.waitFor(); Log.d(TAG, "doWork: result " + result); if (result != 0) { return Result.failure(); } - data = new Data.Builder().putStringArray("output", lines.toArray(new String[0])) - .build(); - } catch (IOException e) { e.printStackTrace(); System.out.printf(e.toString()); @@ -178,6 +187,6 @@ public Result doWork() { throw new RuntimeException(e); } - return Result.success(data); + return Result.success(); } } diff --git a/app/src/main/res/layout/fragment_iperf3_input.xml b/app/src/main/res/layout/fragment_iperf3_input.xml index bd98c3c9..61fa0ff7 100644 --- a/app/src/main/res/layout/fragment_iperf3_input.xml +++ b/app/src/main/res/layout/fragment_iperf3_input.xml @@ -150,20 +150,6 @@ app:layout_constraintStart_toStartOf="@+id/guideline210" app:layout_constraintTop_toTopOf="parent" /> - - Huawei Project Mediatek IMS iPerf3 - Send! + Send -c 172.17.0.1 OpenMobileNetworkToolkit logging This app is provided by NGNI a department of Fraunhofer FOKUS. \n\nhttps://www.fokus.fraunhofer.de/go/ngni \n\nThis software is licensed under BSD 3-Clause Clear License https://spdx.org/licenses/BSD-3-Clause-Clear.html \n\nAuthors: \n\nPeter Hasse \nMohsin Nisar \nJohann Hackler diff --git a/build.gradle b/build.gradle index daec1cce..0273d8d5 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.3.2' + classpath 'com.android.tools.build:gradle:8.4.2' def nav_version = "2.5.3" classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version" classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.21' diff --git a/docs/OpenMobileNetworkToolkit.md b/docs/OpenMobileNetworkToolkit.md new file mode 100644 index 00000000..b264a192 --- /dev/null +++ b/docs/OpenMobileNetworkToolkit.md @@ -0,0 +1,22 @@ +# OpenMobileNetworkToolkit User Guide + +* [Quick Start Guide](./quick-start.md) +* [Installation](installation.md) +* [SIM Card Setup for Carrier Permissions](./carrier-permissions.md) +* [Android Tweaks](android_tweaks.md) +* OMNT Usage + * [Home](./home.md) + * [iPerf3](./iperf3.md) + * [Ping](./ping.md) + * [Special Codes](./special_codes.md) + * [Subscriptions](./subscriptions.md) + * [Carrier Settings](./carrier_settings.md) + * [Slicing](./slicing.md) + * [InfluxDB](./influxdb.md) + * [Workprofile](./workprofile.md) + * [Settings](settings/settings.md) + * [Logging](settings/logging.md) + * [Mobile Network](settings/mobile_network.md) + * [Set subscription](settings/set_subscrption.md) + * [Reboot Modem](settings/reboot_modem.md) + \ No newline at end of file diff --git a/docs/android_tweaks.md b/docs/android_tweaks.md new file mode 100644 index 00000000..55555313 --- /dev/null +++ b/docs/android_tweaks.md @@ -0,0 +1,13 @@ +# Android Tweaks + +While OMNT should work without changes on the phone settings needed there are some options useful to set for better measurement results. + +## Developer Settings +The following settings can be found in the android developer settings menu. On Vanilla Android devices they are enabled by going to ```Settings -> About the phone``` and pressing there multiple times ```Build number```. If this is not working on your device a quick web search with your phone name and ```developer settings``` should help. After enabling the developer settings they are usually accessible via ```Settings -> System -> Developer Options```. +* USB debugging: Install and debug apps via ADB +* Mobile data always active: Allows to gather mobile network information even if connected to WiFi +* Force full GNSS measurements: might improve GNSS accuracy while logging + +Depending on your phone there might be more useful options (or less) + +[Home](OpenMobileNetworkToolkit.md) \ No newline at end of file diff --git a/docs/build.md b/docs/build.md new file mode 100644 index 00000000..10a638d5 --- /dev/null +++ b/docs/build.md @@ -0,0 +1,3 @@ +# Building OMNT + +[Home](OpenMobileNetworkToolkit.md) \ No newline at end of file diff --git a/docs/carrier-permissions.md b/docs/carrier-permissions.md new file mode 100644 index 00000000..14bd3e12 --- /dev/null +++ b/docs/carrier-permissions.md @@ -0,0 +1,35 @@ +# SIM UICC configuration for Carrier Permissions +Carrier specific settings can only be accessed by apps running with so-called carrier privileges. This was added in android 6 and is mostly relevant for 4G and 5G networks. (https://source.android.com/devices/tech/config/carrier). These permissions also allow OMNT to talk to APIs restricted to system apps (apps that are shipped with your phone usually not removable). OMNT works with out these permissions but some features will be disabled. + +Carrier or researcher who are able (admin key to the SIM card is required) to program their own sim cards can store a fingerprint of an signing certificate in an access rule applet (ARA-M) on the SIM card. +An app signed with this certificate will get carrier privileges granted by Android. (https://source.android.com/devices/tech/config/uicc) + +E.g. the [ARAM-Applet by Bertrand Martel](https://github.com/bertrandmartel/aram-applet) for JavaCard based SIM cards can be used. +Some SIM cards like the cards from [Sysmocom](http://shop.sysmocom.de/products/sysmoISIM-SJA2) already come with the applet pre installed. +To install the applet to a SIM card [GlobalPlatformPro by Martin Paljak](https://github.com/martinpaljak/GlobalPlatformPro) can be used. +Pre-compiled versions of ARA-M and GP can be found in the [CoIMS_Wiki repository by Supreeth Herle](https://github.com/herlesupreeth/CoIMS_Wiki). + +To provision the fingerprint to the applet, either [pySim](https://github.com/osmocom/pysim) or GP can be used. + +With pySim it can be done by entering the following commands into pySim-shell: + +start pySim shell with an PCSCD attached reader +```shell +python3 pySim-shell.py -p0 -a +``` +or if you have a csv file with ICCID and admin pin: +```shell +python3 pySim-shell.py -p0 --csv card_data.csv +``` + +Provision the fingerprint. Note that instead of a fingerprint also a valid android App ID can be used. +If you have a SIM Card with the ARA-M applet from sysmocom you can skip the ```verify_adm``` part as the applet is not write protected. +```shell +verify_adm +select ADF.ARA-M +aram_delete_all +aram_store_ref_ar_do --aid ffffffffffff --device-app-id E849B63A7B96E571F788FC5845C4AA3C520D18E8 --android-permissions 0000000000000001 +``` +This assumes the credentials to access the card are stored in the pySim format. + +[Home](OpenMobileNetworkToolkit.md) \ No newline at end of file diff --git a/docs/carrier_settings.md b/docs/carrier_settings.md new file mode 100644 index 00000000..6561e867 --- /dev/null +++ b/docs/carrier_settings.md @@ -0,0 +1,5 @@ +# Carrier Settings View + +This view allows to read out and filter the current settings used by the phone for the currently used subscription. Those settings tell the phone how to behave in the specific network. This list of settings displayed here can be very long and differs from phone to phone. To alter the most relevant settings please see [Settings -> Mobile Network](settings/mobile_network.md). + +[Home](OpenMobileNetworkToolkit.md) \ No newline at end of file diff --git a/docs/home.md b/docs/home.md new file mode 100644 index 00000000..8cb4c6fb --- /dev/null +++ b/docs/home.md @@ -0,0 +1,33 @@ +# Home Screen + +When starting the OMNT or touching the OMNT logo in the top left corner the home screen is displayed. +Here are all information the OMNT can collect displayed. Different cards grouped the data into categories. +The data displayed is updates on load and swipe down. This way the data of the time of refresh can be analyzed. +The same grouping is applied to the data send to the InfluxDB. + +## Cell Information +This card displays information from the Android [CellInfo API](https://developer.android.com/reference/android/telephony/CellInfo). The cell information are on the cell the phone is camping on or registered to. If neighbor cells are present / announced and display of neighbor cells is enabled in the settings they are displayed to. Information on neighbor cells are usually limited. + +## Signal Strength Information +This card displays information from the Android [Signal Strength API](https://developer.android.com/reference/android/telephony/SignalStrength). Signal information have less properties then the Cell info API but on some devices they seem to be more accurate / more often updated. + +## Network Information +This card presents the current network state of the phone. This includes the current mobile network registration as well as the default route, currently used access network and DNS. + + +## Device Information +This card displays information on the phone it self. This information only change on e.g. firmware updates. It is often helpful to e.g. compare base band versions between to phones to spot the cause for different behavior. + +## Device Features +This card displays the availability of some relevant APIs on the phone. + +## APP Permissions +This card displays the permissions granted to the OMNT. + +## Network Interfaces +This card lists all network interfaces of the UE and there current IP addresses. + +## Location +This card shows the current location information provided to OMNT by Android. + +[Home](OpenMobileNetworkToolkit.md) \ No newline at end of file diff --git a/docs/images/iPerf3_run_upload.gif b/docs/images/iPerf3_run_upload.gif new file mode 100644 index 00000000..ffd0f95e Binary files /dev/null and b/docs/images/iPerf3_run_upload.gif differ diff --git a/docs/images/iPerf3_run_view.gif b/docs/images/iPerf3_run_view.gif new file mode 100644 index 00000000..95609484 Binary files /dev/null and b/docs/images/iPerf3_run_view.gif differ diff --git a/docs/images/influx_settings_credentials.png b/docs/images/influx_settings_credentials.png new file mode 100644 index 00000000..2984af5b Binary files /dev/null and b/docs/images/influx_settings_credentials.png differ diff --git a/docs/images/influx_settings_options.png b/docs/images/influx_settings_options.png new file mode 100644 index 00000000..e9a3cbf7 Binary files /dev/null and b/docs/images/influx_settings_options.png differ diff --git a/docs/images/iperf3.png b/docs/images/iperf3.png new file mode 100644 index 00000000..b5f2a8a0 Binary files /dev/null and b/docs/images/iperf3.png differ diff --git a/docs/images/pending_upload.png b/docs/images/pending_upload.png new file mode 100644 index 00000000..37082fce Binary files /dev/null and b/docs/images/pending_upload.png differ diff --git a/docs/images/upload_fail.png b/docs/images/upload_fail.png new file mode 100644 index 00000000..53118eb1 Binary files /dev/null and b/docs/images/upload_fail.png differ diff --git a/docs/images/upload_success.png b/docs/images/upload_success.png new file mode 100644 index 00000000..700b9227 Binary files /dev/null and b/docs/images/upload_success.png differ diff --git a/docs/influxdb.md b/docs/influxdb.md new file mode 100644 index 00000000..68fe06b1 --- /dev/null +++ b/docs/influxdb.md @@ -0,0 +1,7 @@ +# InfluxDB View + +This view allows the configuration of a locally (on the phone) running InfluxDB instance. This is currently still under development and should no be considered stable. + +Configuration of logging and remote InfluxDB hosts can be found in [Settings -> Logging](settings/logging.md) + +[Home](OpenMobileNetworkToolkit.md) \ No newline at end of file diff --git a/docs/installation.md b/docs/installation.md new file mode 100644 index 00000000..f88185da --- /dev/null +++ b/docs/installation.md @@ -0,0 +1,3 @@ +# Installation + +[Home](OpenMobileNetworkToolkit.md) \ No newline at end of file diff --git a/docs/iperf3.md b/docs/iperf3.md new file mode 100644 index 00000000..ca951c2a --- /dev/null +++ b/docs/iperf3.md @@ -0,0 +1,30 @@ +## iPerf3 +iPerf3 has been compiled with a [JNI](https://developer.android.com/training/articles/perf-jni) interface to enable OMNT to call it using the specified parameters. +To see how to integrate iPerf3 into your app, look at [iPerf3 Repo](https://github.com/omnt/iperf) + +| Description | iPerf3 run is pending to upload | iPerf3 run failed to upload | iPerf3 run successfully uploaded | iPerf3 run is running | iPerf3 run is done | iPerf3 run has an error | +|------------------------------------------------------------------------|-------------------------------------------------------------------------------|--------------------------------------------------------------------------|-----------------------------------------------------------------------------|--------------------------------------------------------------------------|----------------------------------------------------------------------|------------------------------------------------------------------------------------------------------| +| Image |
|
|
|
|
|
| + + +### Usage +To use iPerf3 it is pretty simple. +You can type into the GUI the server IP and port, the duration of the test, and the bandwidth. +You can also choose the protocol you want to use, TCP or UDP. +![iPerf3](images/iperf3.png) + +### Results +The results of the iPerf3 test are displayed in the GUI. +![iPerf3_results](images/iPerf3_run_view.gif) + +### Local Logging +The local results of each iPerf3 run are logged in `/sdcard0/Documents/omnt/iperf3RawLogs/`. +Each log gets converted into a https://docs.influxdata.com/influxdb/cloud/reference/syntax/line-protocol/ file, which is saved at `/sdcard0/Documents/omnt/iperf3LP/`. + +### Upload to Remote InfluxDB +If the Influx parameters are set correctly (refer to [Logging -> Remote Logging](settings/logging.md)), the results of the iPerf3 test will be uploaded to the InfluxDB. +InfluxDB Remote Logging needs to be enabled. +If the upload to InfluxDB fails, the logs can be uploaded manually. +![iPerf3_run_upload.gif](images/iPerf3_run_upload.gif) + +[Home](OpenMobileNetworkToolkit.md) \ No newline at end of file diff --git a/docs/ping.md b/docs/ping.md new file mode 100644 index 00000000..dfc63043 --- /dev/null +++ b/docs/ping.md @@ -0,0 +1,7 @@ +# Ping, ICMP View +[ICMP](https://en.wikipedia.org/wiki/Internet_Control_Message_Protocol) allows a high level analysis of the current network conditions. The input field allows to enter the target IP address as well as options of the ICMP command. If logging is enabled the results of the ICMP test are pushed to the InfluxDB and can be viewed in the dashboards. The most relevant KPIs gathered here are: +* packet loss +* RTT round trip time +* jitter + +[Home](OpenMobileNetworkToolkit.md) \ No newline at end of file diff --git a/docs/quick-start.md b/docs/quick-start.md new file mode 100644 index 00000000..3558fe4a --- /dev/null +++ b/docs/quick-start.md @@ -0,0 +1,75 @@ +# Quick start guide + +This guide aims to bring you quickly to a working setup with InfluxDB and Grafana by using the cloud accounts. You will be able to store your measurements in an InfluxDB instance and visualize the data with our example dashboard in Grafana. This guide further assumes you have an Android phone with a compatible Android Version and you either already know how to build OMNT yourself or a release APK. + +Note: If you run your own Grafana / InfluxDB you can jump ahead to [Setup OMNT](#setup-omnt). +If you want to setup Grafana and InfluxDB yourself checkout: +* https://docs.influxdata.com/influxdb/v1/introduction/install/ +* https://grafana.com/docs/grafana/latest/setup-grafana/installation/ + +# Accounts +This guide assumes you will use the free cloud accounts of InfluxDB and Grafana. If you don't have accounts for both services: + + * https://cloud2.influxdata.com/signup + * https://grafana.com/products/cloud/ + +both services can be used for free to get a first impression, more advanced usage will require a paid subscription or a private / on prem instance. + +# Installation +The simplest way to install the app is by downloading it on the phone, if ADB is at hand installing via adb more convenient. + + adb install release.apk + +or use android studio to build and install OMNT. Follow [build](build.md) for more information on building the app. + +# Setup InfluxDB +Log into your influxDB account and hover over the top symbol in the right menu bar (below the influx logo), in now visible menu select ```buckets```. Click on the ```Create bucket``` button in the top right of the screen. You can name the bucket what ever you want e.g. ```omnt```. + +Next click on the ```api token``` tab and create an API token. Again naming is up to you. +For simplicity create an ```all access``` token. +Make sure to copy the token somewhere you find it later, it will not be shown again. + +On the top of the window you see you organization, most likely something like ```dev```, write this down to. + +The last information you need from influx is the url to your instance. It depends on the cloud zone you choose and will look e.g. like this ```https://eu-central-1-1.aws.cloud2.influxdata.com/``` + +# Setup Grafana +Log into your Grafana account and add a new data source by selecting ```Connections``` and than ```add new data source```. Now choose ```InfluxDB``` and click on ```add data source```. +Name the data source what ever you like. As our sample dashboards using Flux as query language select ```flux``` from the dropdown menu. If you later develop you own dashboards you can also use InfluxQL or SQL on the same data. + +Scroll down to ```InfluxDB Details``` and enter the information written down during the InfluxDB setup. +Click on ```Save & Test``` + +Now you can import the sample dashboards provided at https://github.com/omnt/Dashboards . + +# Setup OMNT +## InfluxDB Settings +Now its time to open OMNT and configure its logging component. Touch the three dots in the right top corner to open the app menu. Select ```Settings``` and open the ```Logging``` setting page. + + + +Fist scroll down to ```Remote logging``` here we configure the credentials for remote InfluxDB. +1) Toggle the ```InfluxDB log``` switch. +2) Copy the url you saved before to ```Influxdb instance URL/IP``` option. +3) Copy the organization id to the ```InfluxDB Organization``` option. +4) Copy the token to the ```Influx Token``` +5) Copy the bucket id to ```InfluxDB bucket``` + +## Logging Content +Here we configure what data should be written to the database. Note that this also affects the log file. +* User Fake location: This will prevent you real location showing up in your logs. Mostly useful for developers. +* Measurement Name: This name will be used to identifier your measurement later on. +* Tags: This should at least have ```device=YourDevice``` as a tag. Further tags can be added comma separated. +* Log network information: log data displayed in the network information card on the home screen +* Log signal data: log data displayed in the signal info card on the home screen +* Log cell information: log data displayed in the cell information card on the home screen +* Log neighbor cells: include neighbor cells in the log +* Log throughput data: log interface throughput statistics +* Log battery information: include current battery and charging state in the log +* Log IP addresses: Include current IP addresses in the log + +If everything is set up you can now scroll up to the top of the logging settings and enable the logging system. If your phone has a internet connection the logging logo will tun green when data is successfully transmitted to the database. + +You should now see the device and measurement selectable in the dashboards and graphs ans maps filling with data points. + +[Home](OpenMobileNetworkToolkit.md) \ No newline at end of file diff --git a/docs/settings/logging.md b/docs/settings/logging.md new file mode 100644 index 00000000..bf665c1b --- /dev/null +++ b/docs/settings/logging.md @@ -0,0 +1,36 @@ +# Logging Settings + +## Logging Service +* Enable: Start / Stop the logging component of OMNT. This effects all data logging targets, iPerf and Ping measurements and the Notification bar. +* Start on boot: Start OMNT and its logging component on device boot. +* Interval: Logging interval in milliseconds +* Enable Notification Update: Show current cell information in the notification area of android. This will wake up the screen and my raise power consumption. + +## Local Logging +* InfluxDB log: This is work in progress and should allow the usage of a on device database +* Log file: Measurements a written to a file on the phones internal memory. + +## Remote Logging +This section configured the remote logging function to an InfluxDB. This has been tested with on-prem InfluxDB 2.x installation +as well with InfluxDB 3.x cloud. + +* InfluxDb Log: Enable the logging to remote database +* InfluxDB instance URL / IP: Address of the database e.g. ```https://example.com/influxd:443``` +* Influx Organization: Either ID or Name of the Org to which the bucket and token belongs +* Influx Token: The InfluxDB API token to be used +* Influx Bucket: Name or ID of the bucket to be used + +## Logging Content +Here the content of what data should be logged is configured. Note that this also affects all logging targets. +* User Fake location: This will replace the GNSS location with a static one. Mostly useful for developers. +* Measurement Name: This name will be used to identifier the measurement later on. +* Tags: This should at least have ```device=YourDevice``` as a tag. Further tags can be added comma separated. +* Log network information: log data displayed in the network information card on the home screen +* Log signal data: log data displayed in the signal info card on the home screen +* Log cell information: log data displayed in the cell information card on the home screen +* Log neighbor cells: include neighbor cells in the log +* Log throughput data: log interface throughput statistics +* Log battery information: include current battery and charging state in the log +* Log IP addresses: Include current IP addresses in the log + +[Settings](settings.md) | [Home](../OpenMobileNetworkToolkit.md) \ No newline at end of file diff --git a/docs/settings/mobile_network.md b/docs/settings/mobile_network.md new file mode 100644 index 00000000..3ca86858 --- /dev/null +++ b/docs/settings/mobile_network.md @@ -0,0 +1,20 @@ +# Mobile Network +This section of the OMNT settings combines the mobile network related settings. OMNT needs carrier permissions to apply those settings. +Note that not all devices will silently ignore some of the settings. + +## Radio Settings +* Select Access Network Type: Limit the network types the modem will use a specific technology. +* Set PLMN: Force the modem to only attach to a specific PLMN and ignore other available cells. +* Persist until reboot: Make sure the setting will be applied after e.g. a SIM change until the next reboot + +## Carrier Settings +While there are a lot more carrier settings part of a phone configuration not all relevant or even accessible. This section allows to configure the profile +applied for the selected subscription. OMNT will try to restore them after each network change event which mostly happens on SIM change, modem reboot and similar. +This section reflects the settings desired to be applied and not necessary the current state. To look at the current state please use the [Carrier Settings](../carrier_settings.md) View from the menu. + +* Apply carrier settings now: This button will request the phone to apply the settings configured below to be applied. + +The different settings are grouped by the android API level on which they where introduced and will be disabled if the phones runs an older version. +Details on the different settings can be found [here](https://developer.android.com/reference/android/telephony/CarrierConfigManager) + +[Settings](settings.md) | [Home](../OpenMobileNetworkToolkit.md) \ No newline at end of file diff --git a/docs/settings/reboot_modem.md b/docs/settings/reboot_modem.md new file mode 100644 index 00000000..eb84c3d4 --- /dev/null +++ b/docs/settings/reboot_modem.md @@ -0,0 +1,10 @@ +# Reboot Modem + +[Home](../OpenMobileNetworkToolkit.md) + +The ```reboot modem``` button, carrier permissions required, triggers a reboot of the modem / base band of the phone. +This usually affects all subscriptions / SIM cards / mobile network connection. + +Usually this is faster then toggling airplane mode and might also be a more deep reboot. + +[Settings](settings.md) | [Home](../OpenMobileNetworkToolkit.md) \ No newline at end of file diff --git a/docs/settings/set_subscrption.md b/docs/settings/set_subscrption.md new file mode 100644 index 00000000..d68a5e22 --- /dev/null +++ b/docs/settings/set_subscrption.md @@ -0,0 +1,9 @@ +# Set Subscription +OMNT needs to attach it self to a so called Telephony Manager. Each Telephony Manager instance is tied to an active subscription (SIM card). +Device with support for multiple subscriptions e.g. eUICCs and UICCs allow the usage of multiple subscriptions at the same time. Default OMNT will try to use the +first active one which is most of the time the subscription configured for calls in the Android settings. +By setting a different subscription e.g. a SIM card with carrier permissions enabling hashes deployed can be selected while connecting with a second subscription to a +mobile network. Some feature will be disabled / not work for subscription without the permissions. + + +[Settings](settings.md) | [Home](../OpenMobileNetworkToolkit.md) \ No newline at end of file diff --git a/docs/settings/settings.md b/docs/settings/settings.md new file mode 100644 index 00000000..d2ff0d82 --- /dev/null +++ b/docs/settings/settings.md @@ -0,0 +1,13 @@ +# Settings +OMNT has a lot of settings which allow a customization of the app behavior and its features. This settings are grouped by topic. Some settings will be disabled depending on the permissions granted to OMNT. + +## Home Screen Settings +* Show Neighbor Cells: Display the current neighbor cells on the home screen or not + +## APP Settings +* [Logging](logging.md): Configuration of the logging system of OMNT +* [Mobile Network](mobile_network.md): Configure Carrier Settings an Mobile Network related options +* [Set Subscription](set_subscrption.md): Choose the subscription to use +* [Reboot Modem](reboot_modem.md): Reboot the modem of the phone + +[Home](../OpenMobileNetworkToolkit.md) \ No newline at end of file diff --git a/docs/signing.md b/docs/signing.md new file mode 100644 index 00000000..b23c5bf6 --- /dev/null +++ b/docs/signing.md @@ -0,0 +1,23 @@ +# Signing the app +This can be done with android studio. + +To generated a signed apk: + +1) Go to ```build``` -> ```Generate signed Bundle/APK``` +2) You will be ask to generate a new key or import an existing one +3) Click through the dialogs until you end up with a signed APK + +To sign the debug apks used for development + +1) Go to ```file``` -> Project Structure -> Modules +2) Select the ```app``` +3) select the ```Signing config``` tab. +4) create a new signing config referencing you key file + +You can also manually re-sign the downloaded .apk file using [apksigner](https://developer.android.com/tools/). +```shell +apksigner sign --ks my.keystore OpenMobileNetworkToolkit.apk +``` +where my.keystore is your java keystore. + +[Home](OpenMobileNetworkToolkit.md) \ No newline at end of file diff --git a/docs/slicing.md b/docs/slicing.md new file mode 100644 index 00000000..0d7ad1cf --- /dev/null +++ b/docs/slicing.md @@ -0,0 +1,5 @@ +# Network Slicing + +This function is still under development and requires support from the core network. + +[Home](OpenMobileNetworkToolkit.md) \ No newline at end of file diff --git a/docs/special_codes.md b/docs/special_codes.md new file mode 100644 index 00000000..c70cd8e6 --- /dev/null +++ b/docs/special_codes.md @@ -0,0 +1,5 @@ +# Special Codes View + +This view, if carrier permissions are granted, allows to send so called Secret or Special Codes via the dialer API. Those codes are mostly vendor specific or even device specific and either enable hidden features or open developer menus. If carrier permissions are not granted those codes can also be entered into the system dialer. Some vendors e.g. Samsung don't allow this in there custom dialer but its usually possible to install the google dialer from play store and make this the default dialer. + +[Home](OpenMobileNetworkToolkit.md) \ No newline at end of file diff --git a/docs/subscriptions.md b/docs/subscriptions.md new file mode 100644 index 00000000..cad4fe3f --- /dev/null +++ b/docs/subscriptions.md @@ -0,0 +1,4 @@ +# Subscriptions View +Subscriptions are profiles provided bei UICCs and eUICCS "SIMCARDs / eSIMprofiles" to the phone / base band to connect to mobile networks. This View displays information on currently enable subscriptions. + +[Home](OpenMobileNetworkToolkit.md) \ No newline at end of file diff --git a/docs/workprofile.md b/docs/workprofile.md new file mode 100644 index 00000000..76f01ee6 --- /dev/null +++ b/docs/workprofile.md @@ -0,0 +1,4 @@ +# Workprofile View +[Android Workprofile](https://support.google.com/work/android/answer/6191949?hl=en) allows to separate Apps into two different spaces. This view allows to create such an work profile on the phone. The reasons this is in OMNT is that a work profile is necessary on Android to use network slicing. But it might come handy for other use cases to. + +[Home](OpenMobileNetworkToolkit.md) \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index dd069f72..928f96bc 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -9,7 +9,7 @@ #Thu Oct 12 12:17:46 CEST 2023 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip r= zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/screenshots/iperf3.png b/screenshots/iperf3.png deleted file mode 100644 index 7f62e36a..00000000 Binary files a/screenshots/iperf3.png and /dev/null differ