Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ dependencies {
testImplementation 'junit:junit:4.12'

implementation 'com.android.support:support-annotations:27.+'
implementation('org.saltyrtc.client:saltyrtc-client:0.11.+', {
implementation('org.saltyrtc.client:saltyrtc-client:1.+', {
exclude group: 'org.json', module: 'json'
})
implementation 'org.saltyrtc.tasks.webrtc:saltyrtc-task-webrtc:0.13.+'
Expand Down
1 change: 1 addition & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".BenchmarkActivity" android:screenOrientation="portrait"/>
</application>

</manifest>
238 changes: 238 additions & 0 deletions android/app/src/main/java/org/saltyrtc/demo/app/BenchmarkActivity.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
/*
* Copyright (c) 2016-2018 Threema GmbH
*
* Licensed under the Apache License, Version 2.0, <see LICENSE-APACHE file>
* or the MIT license <see LICENSE-MIT file>, at your option. This file may not be
* copied, modified, or distributed except according to those terms.
*/
package org.saltyrtc.demo.app;

import android.annotation.SuppressLint;
import android.app.ActionBar;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.AnyThread;
import android.support.annotation.ColorRes;
import android.support.annotation.Nullable;
import android.support.annotation.UiThread;
import android.util.Log;
import android.util.TypedValue;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;

import org.saltyrtc.client.exceptions.CryptoFailedException;
import org.saltyrtc.client.exceptions.InvalidKeyException;
import org.saltyrtc.client.keystore.KeyStore;
import org.saltyrtc.client.keystore.SharedKeyStore;
import org.saltyrtc.vendor.com.neilalexander.jnacl.NaCl;

import java.util.Random;

public class BenchmarkActivity extends Activity {

private static final String LOG_TAG = BenchmarkActivity.class.getSimpleName();

private Random random;
private LinearLayout messagesLayout;
private ScrollView messagesScrollView;
private Button buttonRunBenchmarks;

@Nullable
private AsyncTask<Void, Void, Void> benchmarkTask;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle(R.string.benchmarks);
final ActionBar actionBar = getActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
setContentView(R.layout.activity_benchmarks);

// Get views
this.messagesLayout = findViewById(R.id.messages);
this.messagesScrollView = findViewById(R.id.messages_scroll);
this.buttonRunBenchmarks = findViewById(R.id.button_run_benchmarks);

this.random = new Random();
}

@Override
protected void onDestroy() {
Log.d(LOG_TAG, "Cancelling benchmark task");
this.benchmarkTask.cancel(true);
super.onDestroy();
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
this.finish();
return true;
}
return super.onOptionsItemSelected(item);
}

/**
* Show message and scroll to bottom.
*/
@UiThread
private void showMessage(String text, @ColorRes int colorResource) {
// Create text view
final TextView view = new TextView(this);
view.setText(text);
view.setBackgroundColor(getResources().getColor(colorResource));

// Set layout parameters
final LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
final int spacing = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, this.getResources().getDisplayMetrics());
params.setMargins(spacing, spacing, spacing, 0);
view.setPadding(spacing, spacing, spacing, spacing);
view.setLayoutParams(params);

BenchmarkActivity.this.messagesLayout.addView(view);
BenchmarkActivity.this.messagesScrollView.post(
() -> BenchmarkActivity.this.messagesScrollView.fullScroll(ScrollView.FOCUS_DOWN)
);
}

@UiThread
@SuppressLint("StaticFieldLeak")
public void runBenchmarks(View view) {
Log.d(LOG_TAG, "Running benchmarks in background thread...");
if (this.benchmarkTask != null) {
Log.e(LOG_TAG, "Benchmark task is already defined!");
return;
}
this.benchmarkTask = new AsyncTask<Void, Void, Void>() {
@Override
protected void onPreExecute() {
BenchmarkActivity.this.buttonRunBenchmarks.setEnabled(false);
super.onPreExecute();
}

@Override
protected Void doInBackground(Void... voids) {
try {
runOnUiThread(() -> showMessage("Starting benchmark 1...", R.color.colorMessageIn));
if (!isCancelled()) { benchmark1EncryptKeyStore(1, 64); }
if (!isCancelled()) { benchmark1EncryptKeyStore(1, 1024 * 20); }
if (!isCancelled()) { benchmark1EncryptKeyStore(20, 1024); }
if (!isCancelled()) { benchmark1EncryptKeyStore(320, 64); }
runOnUiThread(() -> showMessage("Starting benchmark 2...", R.color.colorMessageIn));
if (!isCancelled()) { benchmark2EncryptKeyStore(1, 64); }
if (!isCancelled()) { benchmark2EncryptKeyStore(1, 1024 * 20); }
if (!isCancelled()) { benchmark2EncryptKeyStore(20, 1024); }
if (!isCancelled()) { benchmark2EncryptKeyStore(320, 64); }
} catch (CryptoFailedException | InvalidKeyException e) {
Log.e(LOG_TAG, "Crypto error", e);
e.printStackTrace();
}
return null;
}

@Override
protected void onPostExecute(Void aVoid) {
BenchmarkActivity.this.buttonRunBenchmarks.setEnabled(true);
BenchmarkActivity.this.benchmarkTask = null;
showMessage("Benchmarks done!", R.color.colorMessageIn);
super.onPostExecute(aVoid);
}

@Override
protected void onCancelled() {
Log.d(LOG_TAG, "Async task cancelled");
BenchmarkActivity.this.benchmarkTask = null;
super.onCancelled();
}
};
this.messagesLayout.removeAllViews();
this.benchmarkTask.execute();
}

/**
* Encrypt the specified number of kilobytes of random data using the classic `KeyStore`.
*/
@AnyThread
private void benchmark1EncryptKeyStore(int count, int kilobytes) throws CryptoFailedException, InvalidKeyException {
Log.d(LOG_TAG, "Benchmark 1: Start: Encrypt " + count + "x" + kilobytes + " KiB");

// Gerate random plaintext
final byte[] plaintext = new byte[1024 * kilobytes];
final byte[] nonce = new byte[NaCl.NONCEBYTES];
final byte[] otherKey = new byte[NaCl.PUBLICKEYBYTES];
this.random.nextBytes(plaintext);
this.random.nextBytes(nonce);
this.random.nextBytes(otherKey);

// Create keystore
final KeyStore keyStore = new KeyStore();

// Warmup caches?
keyStore.encrypt(plaintext, nonce, otherKey);

// Encrypt
final long t1 = System.nanoTime();
for (int i = 0; i < count; i++) {
keyStore.encrypt(plaintext, nonce, otherKey);
}
final long t2 = System.nanoTime();

Log.d(LOG_TAG, "Benchmark 1: End: Encrypted " + count + "x" + kilobytes + " KiB");

runOnUiThread(
() -> showMessage(
"--> Encrypting " + count + "x" + kilobytes + " KiB took " + ((t2 - t1) / 1000 / 1000) + " ms",
R.color.colorMessageOut
)
);
}

/**
* Encrypt the specified number of kilobytes of random data using the `SharedKeyStore`.
*/
@AnyThread
private void benchmark2EncryptKeyStore(int count, int kilobytes) throws CryptoFailedException, InvalidKeyException {
Log.d(LOG_TAG, "Benchmark 2: Start: Encrypt " + count + "x" + kilobytes + " KiB");

// Gerate random plaintext
final byte[] plaintext = new byte[1024 * kilobytes];
final byte[] nonce = new byte[NaCl.NONCEBYTES];
final byte[] otherKey = new byte[NaCl.PUBLICKEYBYTES];
this.random.nextBytes(plaintext);
this.random.nextBytes(nonce);
this.random.nextBytes(otherKey);

// Create keystore
final KeyStore keyStore = new KeyStore();

// Warmup caches?
keyStore.encrypt(plaintext, nonce, otherKey);

// Encrypt
final long t1 = System.nanoTime();
final SharedKeyStore sharedKeyStore = keyStore.getSharedKeyStore(otherKey);
for (int i = 0; i < count; i++) {
sharedKeyStore.encrypt(plaintext, nonce);
}
final long t2 = System.nanoTime();

Log.d(LOG_TAG, "Benchmark 2: End: Encrypted " + count + "x" + kilobytes + " KiB");

runOnUiThread(
() -> showMessage(
"--> Encrypting " + count + "x" + kilobytes + " KiB took " + ((t2 - t1) / 1000 / 1000) + " ms",
R.color.colorMessageOut
)
);
}
}
29 changes: 27 additions & 2 deletions android/app/src/main/java/org/saltyrtc/demo/app/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,16 @@
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.AnyThread;
import android.support.annotation.ColorRes;
import android.support.annotation.UiThread;
import android.util.Log;
import android.util.TypedValue;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
Expand Down Expand Up @@ -50,7 +55,7 @@

public class MainActivity extends Activity {

private static final String LOG_TAG = MainActivity.class.getName();
private static final String LOG_TAG = MainActivity.class.getSimpleName();

private SaltyRTC client;
private WebRTCTask task;
Expand Down Expand Up @@ -96,6 +101,26 @@ protected void onCreate(Bundle savedInstanceState) {
this.resetStates();
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main_menu, menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case R.id.benchmarks:
final Intent intent = new Intent(this, BenchmarkActivity.class);
this.startActivity(intent);
return true;
default:
return super.onOptionsItemSelected(item);
}
}

/**
* Reset all states to "Unknown".
*/
Expand Down Expand Up @@ -336,7 +361,7 @@ public void setState(final StateType type, final String state) {

}

private TextView getMessageTextView(int colorResource, String text) {
private TextView getMessageTextView(@ColorRes int colorResource, String text) {
// Create text view
final TextView view = new TextView(this);
view.setText(text);
Expand Down
42 changes: 42 additions & 0 deletions android/app/src/main/res/layout/activity_benchmarks.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context="org.saltyrtc.demo.app.BenchmarkActivity">

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/benchmarks_text"/>

<Button
android:id="@+id/button_run_benchmarks"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="runBenchmarks"
android:text="@string/button_run_benchmarks"/>

<ScrollView
android:id="@+id/messages_scroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#dddddd"
android:layout_marginTop="8dp">
<LinearLayout
android:id="@+id/messages"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="8dp"
android:orientation="vertical">
</LinearLayout>
</ScrollView>

</LinearLayout>
6 changes: 6 additions & 0 deletions android/app/src/main/res/menu/main_menu.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/benchmarks"
android:title="@string/benchmarks"
android:showAsAction="never"/>
</menu>
3 changes: 3 additions & 0 deletions android/app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,7 @@
<string name="loading">Loading...</string>
<string name="button_start">Start</string>
<string name="button_stop">Stop</string>
<string name="benchmarks">Benchmarks</string>
<string name="benchmarks_text">This benchmark will run some encrypt/decrypt operations and measure the time it takes to do so.</string>
<string name="button_run_benchmarks">Run benchmarks</string>
</resources>