Commit fadb253a authored by akwizgran's avatar akwizgran

Show results in a dialog when the test finishes.

parent bac7e341
......@@ -15,6 +15,7 @@ import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.ViewModelProvider;
import static android.widget.Toast.LENGTH_SHORT;
import static org.briarproject.interferometer.MainViewModel.CONSUMED;
import static org.briarproject.interferometer.MainViewModel.ConnectionState.DISCONNECTED;
import static org.briarproject.interferometer.MainViewModel.ConnectionState.DOWNLOADING;
import static org.briarproject.interferometer.MainViewModel.ConnectionState.UPLOADING;
......@@ -25,6 +26,7 @@ import static org.briarproject.interferometer.MainViewModel.TestPhase.BT_ENABLED
import static org.briarproject.interferometer.MainViewModel.TestPhase.CONNECTIONS;
import static org.briarproject.interferometer.MainViewModel.TestPhase.DISCOVERY;
import static org.briarproject.interferometer.MainViewModel.TestPhase.READY;
import static org.briarproject.interferometer.Utils.formatSpeed;
public class MainActivity extends AppCompatActivity {
......@@ -58,15 +60,21 @@ public class MainActivity extends AppCompatActivity {
this.throughput = throughput;
showThroughput();
});
viewModel.getResults().observe(this, results -> {
if (!results.getBoolean(CONSUMED)) showResultsDialog(results);
});
}
private void showThroughput() {
if (state == DISCONNECTED) {
throughputTextView.setText(null);
} else if (state == DOWNLOADING) {
throughputTextView.setText(getString(R.string.download_format, throughput));
String speed = formatSpeed(throughput);
throughputTextView.setText(getString(R.string.download_format, speed));
} else if (state == UPLOADING) {
throughputTextView.setText(getString(R.string.upload_format, throughput));
String speed = formatSpeed(throughput);
throughputTextView.setText(getString(R.string.upload_format, speed));
}
}
......@@ -88,6 +96,11 @@ public class MainActivity extends AppCompatActivity {
}
}
private void showResultsDialog(Bundle results) {
ResultsDialogFragment fragment = ResultsDialogFragment.newInstance(results);
fragment.show(getSupportFragmentManager(), ResultsDialogFragment.TAG);
}
public void onTestClick(View view) {
TestPhase phase = viewModel.getTestPhase().getValue();
if (phase == null || phase == READY) {
......
......@@ -9,6 +9,7 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
import java.io.IOException;
......@@ -23,7 +24,6 @@ import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import androidx.annotation.NonNull;
......@@ -38,6 +38,7 @@ import static android.bluetooth.BluetoothAdapter.ACTION_STATE_CHANGED;
import static android.bluetooth.BluetoothAdapter.EXTRA_STATE;
import static android.bluetooth.BluetoothAdapter.STATE_OFF;
import static android.bluetooth.BluetoothAdapter.STATE_ON;
import static java.util.concurrent.Executors.newCachedThreadPool;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.briarproject.interferometer.MainViewModel.ConnectionState.DISCONNECTED;
import static org.briarproject.interferometer.MainViewModel.ConnectionState.DOWNLOADING;
......@@ -50,7 +51,7 @@ import static org.briarproject.interferometer.MainViewModel.TestPhase.BT_ENABLED
import static org.briarproject.interferometer.MainViewModel.TestPhase.CONNECTIONS;
import static org.briarproject.interferometer.MainViewModel.TestPhase.DISCOVERY;
import static org.briarproject.interferometer.MainViewModel.TestPhase.READY;
import static org.briarproject.interferometer.Statistics.mean;
import static org.briarproject.interferometer.Utils.mean;
public class MainViewModel extends AndroidViewModel {
......@@ -60,20 +61,31 @@ public class MainViewModel extends AndroidViewModel {
enum StartResult {INVALID_ADDRESS, NO_BLUETOOTH, STARTED}
static final String DOWNLOAD_DISABLED = "downloadDisabled";
static final String UPLOAD_DISABLED = "uploadDisabled";
static final String DOWNLOAD_ENABLED = "downloadEnabled";
static final String UPLOAD_ENABLED = "uploadEnabled";
static final String DOWNLOAD_DISCOVERY = "downloadDiscovery";
static final String UPLOAD_DISCOVERY = "uploadDiscovery";
static final String DOWNLOAD_CONNECTIONS = "downloadConnections";
static final String UPLOAD_CONNECTIONS = "uploadConnections";
static final String CONSUMED = "consumed";
private static final byte CONNECTION_TYPE_UPLOAD = 0;
private static final byte CONNECTION_TYPE_DOWNLOAD = 1;
private static final int BUFFER_SIZE = 4096;
private static final int MS_PER_UPDATE = 250;
private static final int MS_PER_TRANSFER = 5_000;
private static final int TRANSFERS_PER_CONDITION = 10;
private static final int TRANSFERS_PER_CONDITION = 5;
private static final String TAG = "Interferometer";
private final ExecutorService executorService = Executors.newCachedThreadPool();
private final ExecutorService executorService = newCachedThreadPool();
private final MutableLiveData<TestPhase> testPhase = new MutableLiveData<>();
private final MutableLiveData<ConnectionState> connectionState = new MutableLiveData<>();
private final MutableLiveData<Long> throughput = new MutableLiveData<>();
private final MutableLiveData<Bundle> results = new MutableLiveData<>();
private final List<Socket> sockets = new CopyOnWriteArrayList<>();
@Nullable
......@@ -95,6 +107,10 @@ public class MainViewModel extends AndroidViewModel {
return throughput;
}
LiveData<Bundle> getResults() {
return results;
}
@UiThread
StartResult startTest(String serverAddress) {
HostPort hostPort = parseServerAddress(serverAddress);
......@@ -128,10 +144,10 @@ public class MainViewModel extends AndroidViewModel {
testPhase.postValue(DISCOVERY);
Log.i(TAG, "Testing throughput with Bluetooth discovery");
List<Long> downloadDiscovery = new ArrayList<>();
List<Long> uploadDiscovery = new ArrayList<>();
Future<?> discoveryTask = startDiscovery(adapter);
try {
List<Long> downloadDiscovery = new ArrayList<>();
List<Long> uploadDiscovery = new ArrayList<>();
if (!testThroughput(hostPort, downloadDiscovery, uploadDiscovery)) return;
} finally {
discoveryTask.cancel(true);
......@@ -139,10 +155,10 @@ public class MainViewModel extends AndroidViewModel {
testPhase.postValue(CONNECTIONS);
Log.i(TAG, "Testing throughput with Bluetooth connections");
List<Long> downloadConnections = new ArrayList<>();
List<Long> uploadConnections = new ArrayList<>();
Future<?> connectionTask = startConnections(adapter);
try {
List<Long> downloadConnections = new ArrayList<>();
List<Long> uploadConnections = new ArrayList<>();
if (!testThroughput(hostPort, downloadConnections, uploadConnections)) return;
} finally {
// Interrupting the task may not work, so we also need to disable the adapter
......@@ -150,7 +166,19 @@ public class MainViewModel extends AndroidViewModel {
adapter.disable();
}
Log.i(TAG, "Test finished");
Bundle b = new Bundle();
b.putDouble(DOWNLOAD_DISABLED, mean(downloadDisabled));
b.putDouble(UPLOAD_DISABLED, mean(uploadDisabled));
b.putDouble(DOWNLOAD_ENABLED, mean(downloadEnabled));
b.putDouble(UPLOAD_ENABLED, mean(uploadEnabled));
b.putDouble(DOWNLOAD_DISCOVERY, mean(downloadDiscovery));
b.putDouble(UPLOAD_DISCOVERY, mean(uploadDiscovery));
b.putDouble(DOWNLOAD_CONNECTIONS, mean(downloadConnections));
b.putDouble(UPLOAD_CONNECTIONS, mean(uploadConnections));
b.putBoolean(CONSUMED, false);
results.postValue(b);
} finally {
testPhase.postValue(READY);
}
......
package org.briarproject.interferometer;
import android.annotation.SuppressLint;
import android.app.Dialog;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment;
import static org.briarproject.interferometer.MainViewModel.CONSUMED;
import static org.briarproject.interferometer.MainViewModel.DOWNLOAD_CONNECTIONS;
import static org.briarproject.interferometer.MainViewModel.DOWNLOAD_DISABLED;
import static org.briarproject.interferometer.MainViewModel.DOWNLOAD_DISCOVERY;
import static org.briarproject.interferometer.MainViewModel.DOWNLOAD_ENABLED;
import static org.briarproject.interferometer.MainViewModel.UPLOAD_CONNECTIONS;
import static org.briarproject.interferometer.MainViewModel.UPLOAD_DISABLED;
import static org.briarproject.interferometer.MainViewModel.UPLOAD_DISCOVERY;
import static org.briarproject.interferometer.MainViewModel.UPLOAD_ENABLED;
import static org.briarproject.interferometer.Utils.formatSpeed;
public class ResultsDialogFragment extends DialogFragment {
static String TAG = ResultsDialogFragment.class.getName();
static ResultsDialogFragment newInstance(Bundle results) {
ResultsDialogFragment fragment = new ResultsDialogFragment();
fragment.setArguments(results);
return fragment;
}
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
LayoutInflater inflater = requireActivity().getLayoutInflater();
@SuppressLint("InflateParams")
View v = inflater.inflate(R.layout.dialog_results, null);
Bundle args = requireArguments();
TextView btDisabled = v.findViewById(R.id.bt_disabled);
btDisabled.setText(getString(R.string.results_format_bt_disabled,
formatSpeed(args.getDouble(DOWNLOAD_DISABLED)),
formatSpeed(args.getDouble(UPLOAD_DISABLED))));
TextView btEnabled = v.findViewById(R.id.bt_enabled);
btEnabled.setText(getString(R.string.results_format_bt_enabled,
formatSpeed(args.getDouble(DOWNLOAD_ENABLED)),
formatSpeed(args.getDouble(UPLOAD_ENABLED))));
TextView discovery = v.findViewById(R.id.discovery);
discovery.setText(getString(R.string.results_format_discovery,
formatSpeed(args.getDouble(DOWNLOAD_DISCOVERY)),
formatSpeed(args.getDouble(UPLOAD_DISCOVERY))));
TextView connections = v.findViewById(R.id.connections);
connections.setText(getString(R.string.results_format_connections,
formatSpeed(args.getDouble(DOWNLOAD_CONNECTIONS)),
formatSpeed(args.getDouble(UPLOAD_CONNECTIONS))));
return new AlertDialog.Builder(requireActivity())
.setTitle(R.string.results_title)
.setView(v)
.setPositiveButton(android.R.string.ok, (dialog, which) ->
args.putBoolean(CONSUMED, true))
.create();
}
}
package org.briarproject.interferometer;
import android.annotation.SuppressLint;
import java.util.List;
class Statistics {
class Utils {
static <T extends Number> double mean(List<T> values) {
if (values.isEmpty()) throw new IllegalArgumentException();
......@@ -10,4 +12,25 @@ class Statistics {
for (T value : values) total += value.doubleValue();
return total / values.size();
}
@SuppressLint("DefaultLocale")
static String formatSpeed(double bytesPerSecond) {
double quantity;
String unit;
if (bytesPerSecond >= 1_000_000_000) {
quantity = bytesPerSecond / 1_000_000_000;
unit = "GB/s";
} else if (bytesPerSecond >= 1_000_000) {
quantity = bytesPerSecond / 1_000_000;
unit = "MB/s";
} else if (bytesPerSecond >= 1000) {
quantity = bytesPerSecond / 1000;
unit = "kB/s";
} else {
quantity = bytesPerSecond;
unit = "B/s";
}
if (quantity < 10) return String.format("%.1f %s", quantity, unit);
else return String.format("%,d %s", (long) quantity, unit);
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="@+id/bt_disabled"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp" />
<TextView
android:id="@+id/bt_enabled"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp" />
<TextView
android:id="@+id/discovery"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp" />
<TextView
android:id="@+id/connections"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp" />
</LinearLayout>
\ No newline at end of file
......@@ -14,6 +14,12 @@
<string name="testing_discovery">Testing with Bluetooth discovery</string>
<string name="testing_connections">Testing with Bluetooth connections</string>
<string name="download_format">Download: %,d bytes/sec</string>
<string name="upload_format">Upload: %,d bytes/sec</string>
<string name="download_format">Download: %s</string>
<string name="upload_format">Upload: %s</string>
<string name="results_title">Wi-Fi Throughput</string>
<string name="results_format_bt_disabled">BT disabled: %s down, %s up</string>
<string name="results_format_bt_enabled">BT enabled: %s down, %s up</string>
<string name="results_format_discovery">Discovery: %s down, %s up</string>
<string name="results_format_connections">Connections: %s down, %s up</string>
</resources>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment