diff --git a/briar-android/src/im/delight/android/identicons/AsymmetricIdenticon.java b/briar-android/src/im/delight/android/identicons/AsymmetricIdenticon.java
deleted file mode 100644
index 49e9a3cc814e7939238ef26710480aa3e8fae7bb..0000000000000000000000000000000000000000
--- a/briar-android/src/im/delight/android/identicons/AsymmetricIdenticon.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package im.delight.android.identicons;
-
-/**
- * Copyright 2014 www.delight.im <info@delight.im>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *	  http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-import org.briarproject.api.crypto.CryptoComponent;
-
-import javax.inject.Inject;
-
-public class AsymmetricIdenticon extends IdenticonView {
-
-	private IdenticonBase mDelegate;
-
-	public AsymmetricIdenticon(Context context) {
-		super(context);
-		initDelegate();
-	}
-
-	public AsymmetricIdenticon(Context context, AttributeSet attrs) {
-		super(context, attrs);
-		initDelegate();
-	}
-
-	public AsymmetricIdenticon(Context context, AttributeSet attrs, int defStyleAttr) {
-		super(context, attrs, defStyleAttr);
-		initDelegate();
-	}
-
-	@Override
-	protected IdenticonBase getDelegate() {
-		return mDelegate;
-	}
-
-	private void initDelegate() {
-		mDelegate = new IdenticonBase() {
-
-			@Override
-			protected int getRowCount() {
-				return 4;
-			}
-
-			@Override
-			protected int getColumnCount() {
-				return 4;
-			}
-
-			@Override
-			protected boolean isCellVisible(int row, int column) {
-				return getByte(3 + row * getColumnCount() + column) >= 0;
-			}
-		};
-	}
-
-}
diff --git a/briar-android/src/im/delight/android/identicons/Identicon.java b/briar-android/src/im/delight/android/identicons/Identicon.java
new file mode 100644
index 0000000000000000000000000000000000000000..42f5c959151de89a199811b4235ff1018f3fcfd1
--- /dev/null
+++ b/briar-android/src/im/delight/android/identicons/Identicon.java
@@ -0,0 +1,101 @@
+package im.delight.android.identicons;
+
+/**
+ * Copyright 2014 www.delight.im <info@delight.im>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *	  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.support.annotation.NonNull;
+import android.support.annotation.UiThread;
+
+import static android.graphics.Paint.Style.FILL;
+
+@UiThread
+class Identicon {
+
+	private static final int ROWS = 9, COLUMNS = 9;
+	private static final int CENTER_COLUMN_INDEX = COLUMNS / 2 + COLUMNS % 2;
+
+	private final byte[] input;
+	private final Paint paint;
+	private final int[][] colors;
+
+	private int cellWidth, cellHeight;
+
+	Identicon(@NonNull byte[] input) {
+		if (input.length == 0) throw new IllegalArgumentException();
+		this.input = input;
+
+		paint = new Paint();
+		paint.setStyle(FILL);
+		paint.setAntiAlias(true);
+		paint.setDither(true);
+
+		colors = new int[ROWS][COLUMNS];
+		int colorVisible = getForegroundColor();
+		int colorInvisible = getBackgroundColor();
+
+		for (int r = 0; r < ROWS; r++) {
+			for (int c = 0; c < COLUMNS; c++) {
+				if (isCellVisible(r, c)) colors[r][c] = colorVisible;
+				else colors[r][c] = colorInvisible;
+			}
+		}
+	}
+
+	private byte getByte(int index) {
+		return input[index % input.length];
+	}
+
+	private boolean isCellVisible(int row, int column) {
+		return getByte(3 + row * CENTER_COLUMN_INDEX +
+				getSymmetricColumnIndex(column)) >= 0;
+	}
+
+	private int getSymmetricColumnIndex(int index) {
+		if (index < CENTER_COLUMN_INDEX) return index;
+		else return COLUMNS - index - 1;
+	}
+
+	private int getForegroundColor() {
+		int r = getByte(0) * 3 / 4 + 96;
+		int g = getByte(1) * 3 / 4 + 96;
+		int b = getByte(2) * 3 / 4 + 96;
+		return Color.rgb(r, g, b);
+	}
+
+	private int getBackgroundColor() {
+		// http://www.google.com/design/spec/style/color.html#color-themes
+		return Color.rgb(0xFA, 0xFA, 0xFA);
+	}
+
+	void updateSize(int w, int h) {
+		cellWidth = w / COLUMNS;
+		cellHeight = h / ROWS;
+	}
+
+	void draw(Canvas canvas) {
+		for (int r = 0; r < ROWS; r++) {
+			for (int c = 0; c < COLUMNS; c++) {
+				int x = cellWidth * c;
+				int y = cellHeight * r;
+				paint.setColor(colors[r][c]);
+				canvas.drawRect(x, y + cellHeight, x + cellWidth, y, paint);
+			}
+		}
+	}
+}
diff --git a/briar-android/src/im/delight/android/identicons/IdenticonBase.java b/briar-android/src/im/delight/android/identicons/IdenticonBase.java
deleted file mode 100644
index 7b45675bee346d11d4ed228cb2a38d5b96d4d07c..0000000000000000000000000000000000000000
--- a/briar-android/src/im/delight/android/identicons/IdenticonBase.java
+++ /dev/null
@@ -1,108 +0,0 @@
-package im.delight.android.identicons;
-
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-
-import org.briarproject.api.crypto.CryptoComponent;
-
-/**
- * Created by saiimons on 05/10/14.
- */
-public abstract class IdenticonBase {
-	private final int mRowCount;
-	private final int mColumnCount;
-	private final Paint mPaint;
-	private volatile int mCellWidth;
-	private volatile int mCellHeight;
-	private volatile byte[] mHash;
-	private volatile int[][] mColors;
-	private volatile boolean mReady;
-
-	public IdenticonBase() {
-		mRowCount = getRowCount();
-		mColumnCount = getColumnCount();
-		mPaint = new Paint();
-
-		mPaint.setStyle(Paint.Style.FILL);
-		mPaint.setAntiAlias(true);
-		mPaint.setDither(true);
-	}
-
-	public byte[] getHash(byte[] input) {
-		return input;
-	}
-
-	protected void setupColors() {
-		mColors = new int[mRowCount][mColumnCount];
-		int colorVisible = getIconColor();
-		int colorInvisible = getBackgroundColor();
-
-		for (int r = 0; r < mRowCount; r++) {
-			for (int c = 0; c < mColumnCount; c++) {
-				if (isCellVisible(r, c)) {
-					mColors[r][c] = colorVisible;
-				} else {
-					mColors[r][c] = colorInvisible;
-				}
-			}
-		}
-	}
-
-	public void show(byte[] input) {
-		mHash = input;
-
-		// set up the cell colors according to the input that was provided via show(...)
-		setupColors();
-
-		// this view may now be drawn (and thus must be re-drawn)
-		mReady = true;
-	}
-
-	public byte getByte(int index) {
-		if (mHash == null) {
-			return -128;
-		} else {
-			return mHash[index % mHash.length];
-		}
-	}
-
-	abstract protected int getRowCount();
-
-	abstract protected int getColumnCount();
-
-	abstract protected boolean isCellVisible(int row, int column);
-
-	protected int getIconColor() {
-		int r = getByte(0) * 3 / 4 + 96;
-		int g = getByte(1) * 3 / 4 + 96;
-		int b = getByte(2) * 3 / 4 + 96;
-		return Color.rgb(r, g, b);
-	}
-
-	protected int getBackgroundColor() {
-		// http://www.google.com/design/spec/style/color.html#color-themes
-		return Color.rgb(0xFA, 0xFA, 0xFA);
-	}
-
-	public void updateSize(int w, int h) {
-		mCellWidth = w / mColumnCount;
-		mCellHeight = h / mRowCount;
-	}
-
-	protected void draw(Canvas canvas) {
-		if (mReady) {
-			int x, y;
-			for (int r = 0; r < mRowCount; r++) {
-				for (int c = 0; c < mColumnCount; c++) {
-					x = mCellWidth * c;
-					y = mCellHeight * r;
-
-					mPaint.setColor(mColors[r][c]);
-
-					canvas.drawRect(x, y + mCellHeight, x + mCellWidth, y, mPaint);
-				}
-			}
-		}
-	}
-}
diff --git a/briar-android/src/im/delight/android/identicons/IdenticonDrawable.java b/briar-android/src/im/delight/android/identicons/IdenticonDrawable.java
index 8d805cab9bf8fd39433ec13c1407fed392c8b91c..75663bd297eaa918f0abab90cd448b43e8601409 100644
--- a/briar-android/src/im/delight/android/identicons/IdenticonDrawable.java
+++ b/briar-android/src/im/delight/android/identicons/IdenticonDrawable.java
@@ -1,68 +1,68 @@
 package im.delight.android.identicons;
 
+/**
+ * Copyright 2014 www.delight.im <info@delight.im>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *	  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 import android.graphics.Canvas;
 import android.graphics.ColorFilter;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
-import android.util.Log;
+import android.support.annotation.NonNull;
+import android.support.annotation.UiThread;
 
-/**
- * Created by saiimons on 05/10/14.
- */
+import static android.graphics.PixelFormat.OPAQUE;
+
+@UiThread
 public class IdenticonDrawable extends Drawable {
-	private IdenticonBase mDelegate;
 
-	private static final int CENTER_COLUMN_INDEX = 5;
+	private static final int HEIGHT = 200, WIDTH = 200;
+
+	private final Identicon identicon;
 
-	public IdenticonDrawable(byte[] toShow) {
+	public IdenticonDrawable(@NonNull byte[] input) {
 		super();
-		mDelegate = new IdenticonBase() {
-
-			@Override
-			protected int getRowCount() {
-				return 9;
-			}
-
-			@Override
-			protected int getColumnCount() {
-				return 9;
-			}
-
-			@Override
-			protected boolean isCellVisible(int row, int column) {
-				return getByte(3 + row * CENTER_COLUMN_INDEX + getSymmetricColumnIndex(column)) >= 0;
-			}
-		};
-		mDelegate.show(toShow);
+		identicon = new Identicon(input);
 	}
 
 	@Override
 	public int getIntrinsicHeight() {
-		return 200;
+		return HEIGHT;
 	}
 
 	@Override
 	public int getIntrinsicWidth() {
-		return 200;
+		return WIDTH;
 	}
 
 	@Override
-	public void setBounds(Rect bounds) {
+	public void setBounds(@NonNull Rect bounds) {
 		super.setBounds(bounds);
-		Log.d("IDENTICON", "SIZE : " + (bounds.right - bounds.left) + " " + (bounds.bottom - bounds.top));
-		mDelegate.updateSize(bounds.right - bounds.left, bounds.bottom - bounds.top);
+		identicon.updateSize(bounds.right - bounds.left,
+				bounds.bottom - bounds.top);
 	}
 
 	@Override
 	public void setBounds(int left, int top, int right, int bottom) {
 		super.setBounds(left, top, right, bottom);
-		mDelegate.updateSize(right - left, bottom - top);
+		identicon.updateSize(right - left, bottom - top);
 	}
 
 	@Override
-	public void draw(Canvas canvas) {
-		Log.d("IDENTICON", "DRAW IN PROGRESS");
-		mDelegate.draw(canvas);
+	public void draw(@NonNull Canvas canvas) {
+		identicon.draw(canvas);
 	}
 
 	@Override
@@ -77,14 +77,6 @@ public class IdenticonDrawable extends Drawable {
 
 	@Override
 	public int getOpacity() {
-		return 0;
-	}
-
-	protected int getSymmetricColumnIndex(int row) {
-		if (row < CENTER_COLUMN_INDEX) {
-			return row;
-		} else {
-			return mDelegate.getColumnCount() - row - 1;
-		}
+		return OPAQUE;
 	}
 }
diff --git a/briar-android/src/im/delight/android/identicons/IdenticonView.java b/briar-android/src/im/delight/android/identicons/IdenticonView.java
deleted file mode 100644
index 41f14c5557e8b4f5a164a42d11231968da9a2c79..0000000000000000000000000000000000000000
--- a/briar-android/src/im/delight/android/identicons/IdenticonView.java
+++ /dev/null
@@ -1,113 +0,0 @@
-package im.delight.android.identicons;
-
-/**
- * Copyright 2014 www.delight.im <info@delight.im>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *	  http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.util.AttributeSet;
-import android.view.View;
-
-abstract public class IdenticonView extends View {
-
-
-	public IdenticonView(Context context) {
-		super(context);
-		init();
-	}
-
-	public IdenticonView(Context context, AttributeSet attrs) {
-		super(context, attrs);
-		init();
-	}
-
-	public IdenticonView(Context context, AttributeSet attrs, int defStyleAttr) {
-		super(context, attrs, defStyleAttr);
-		init();
-	}
-
-	protected void init() {
-		setWillNotDraw(false);
-		setLayerType(View.LAYER_TYPE_SOFTWARE, null);
-	}
-
-	public void show(byte[] input) {
-		getDelegate().show(input);
-		invalidate();
-	}
-
-	public void show(String input) {
-		show(input.getBytes());
-	}
-
-	public void show(int input) {
-		show(String.valueOf(input));
-	}
-
-	public void show(long input) {
-		show(String.valueOf(input));
-	}
-
-	public void show(float input) {
-		show(String.valueOf(input));
-	}
-
-	public void show(double input) {
-		show(String.valueOf(input));
-	}
-
-	public void show(byte input) {
-		show(new byte[] { input });
-	}
-
-	public void show(char input) {
-		show(String.valueOf(input));
-	}
-
-	public void show(boolean input) {
-		show(String.valueOf(input));
-	}
-
-	public void show(Object input) {
-		if (input == null) {
-			getDelegate().show(null);
-		} else {
-			show(String.valueOf(input));
-		}
-	}
-
-	abstract protected IdenticonBase getDelegate();
-
-	@Override
-	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
-		super.onSizeChanged(w, h, oldw, oldh);
-		getDelegate().updateSize(w, h);
-	}
-
-	@Override
-	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-		int size = Math.min(getMeasuredWidth(), getMeasuredHeight());
-		setMeasuredDimension(size, size);
-	}
-
-	@Override
-	protected void onDraw(Canvas canvas) {
-		super.onDraw(canvas);
-		getDelegate().draw(canvas);
-	}
-
-}
diff --git a/briar-android/src/im/delight/android/identicons/SymmetricIdenticon.java b/briar-android/src/im/delight/android/identicons/SymmetricIdenticon.java
deleted file mode 100644
index cb5dcc5bc729739ffa30e56bc7a28ae59fa38c07..0000000000000000000000000000000000000000
--- a/briar-android/src/im/delight/android/identicons/SymmetricIdenticon.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package im.delight.android.identicons;
-
-/**
- * Copyright 2014 www.delight.im <info@delight.im>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *	  http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-import org.briarproject.api.crypto.CryptoComponent;
-
-import javax.inject.Inject;
-
-public class SymmetricIdenticon extends IdenticonView {
-
-	private static final int CENTER_COLUMN_INDEX = 5;
-	
-	private IdenticonBase mDelegate;
-
-	public SymmetricIdenticon(Context context) {
-		super(context);
-		initDelegate();
-	}
-
-	public SymmetricIdenticon(Context context, AttributeSet attrs) {
-		super(context, attrs);
-		initDelegate();
-	}
-
-	public SymmetricIdenticon(Context context, AttributeSet attrs, int defStyleAttr) {
-		super(context, attrs, defStyleAttr);
-		initDelegate();
-	}
-
-	private void initDelegate() {
-		mDelegate = new IdenticonBase() {
-
-			@Override
-			protected int getRowCount() {
-				return 9;
-			}
-
-			@Override
-			protected int getColumnCount() {
-				return 9;
-			}
-
-			@Override
-			protected boolean isCellVisible(int row, int column) {
-				return getByte(3 + row * CENTER_COLUMN_INDEX + getSymmetricColumnIndex(column)) >= 0;
-			}
-		};
-	}
-
-	@Override
-	protected IdenticonBase getDelegate() {
-		return mDelegate;
-	}
-
-	protected int getSymmetricColumnIndex(int row) {
-		if (row < CENTER_COLUMN_INDEX) {
-			return row;
-		} else {
-			return getDelegate().getColumnCount() - row - 1;
-		}
-	}
-
-}