diff --git a/briar-android/src/org/briarproject/android/keyagreement/ShowQrCodeFragment.java b/briar-android/src/org/briarproject/android/keyagreement/ShowQrCodeFragment.java index c53200bec967051e20fb95dc28d99bb1acdbcdda..3ebe742ebc23115c3c3eef89b523f6b2b863c12d 100644 --- a/briar-android/src/org/briarproject/android/keyagreement/ShowQrCodeFragment.java +++ b/briar-android/src/org/briarproject/android/keyagreement/ShowQrCodeFragment.java @@ -89,10 +89,8 @@ public class ShowQrCodeFragment extends BaseEventFragment private BluetoothStateReceiver receiver; private QrCodeDecoder decoder; - private boolean gotRemotePayload; - - private volatile KeyAgreementTask task; - private volatile boolean waitingForBluetooth; + private boolean gotRemotePayload, waitingForBluetooth; + private KeyAgreementTask task; public static ShowQrCodeFragment newInstance() { @@ -190,26 +188,33 @@ public class ShowQrCodeFragment extends BaseEventFragment if (receiver != null) getActivity().unregisterReceiver(receiver); } + @UiThread private void startListening() { - task = keyAgreementTaskFactory.getTask(); + final KeyAgreementTask oldTask = task; + final KeyAgreementTask newTask = keyAgreementTaskFactory.getTask(); + task = newTask; ioExecutor.execute(new Runnable() { @Override public void run() { - task.listen(); + if (oldTask != null) oldTask.stopListening(); + newTask.listen(); } }); } + @UiThread private void stopListening() { + final KeyAgreementTask oldTask = task; ioExecutor.execute(new Runnable() { @Override public void run() { - task.stopListening(); + if (oldTask != null) oldTask.stopListening(); } }); } @SuppressWarnings("deprecation") + @UiThread private void openCamera() { LOG.info("Opening camera"); Camera camera; @@ -229,6 +234,7 @@ public class ShowQrCodeFragment extends BaseEventFragment cameraView.start(camera, decoder, 0); } + @UiThread private void releaseCamera() { LOG.info("Releasing camera"); try { @@ -240,6 +246,7 @@ public class ShowQrCodeFragment extends BaseEventFragment } } + @UiThread private void reset() { statusView.setVisibility(INVISIBLE); cameraView.setVisibility(VISIBLE); @@ -248,6 +255,7 @@ public class ShowQrCodeFragment extends BaseEventFragment startListening(); } + @UiThread private void qrCodeScanned(String content) { try { Payload remotePayload = payloadParser.parse( @@ -320,7 +328,6 @@ public class ShowQrCodeFragment extends BaseEventFragment } private void setQrCode(final Payload localPayload) { - listener.runOnUiThread(new Runnable() { @Override public void run() { @@ -397,6 +404,7 @@ public class ShowQrCodeFragment extends BaseEventFragment } private class BluetoothStateReceiver extends BroadcastReceiver { + @UiThread @Override public void onReceive(Context ctx, Intent intent) { int state = intent.getIntExtra(EXTRA_STATE, 0); diff --git a/briar-android/src/org/briarproject/android/util/PreviewConsumer.java b/briar-android/src/org/briarproject/android/util/PreviewConsumer.java index e2fb6eed9556dc44bcb79246f9aaf6179ac112f9..fbe2b67269bc6763c5b8ca3fbf56482833e52a81 100644 --- a/briar-android/src/org/briarproject/android/util/PreviewConsumer.java +++ b/briar-android/src/org/briarproject/android/util/PreviewConsumer.java @@ -1,11 +1,14 @@ package org.briarproject.android.util; import android.hardware.Camera; +import android.support.annotation.UiThread; @SuppressWarnings("deprecation") public interface PreviewConsumer { + @UiThread void start(Camera camera); + @UiThread void stop(); } diff --git a/briar-android/src/org/briarproject/android/util/QrCodeDecoder.java b/briar-android/src/org/briarproject/android/util/QrCodeDecoder.java index 207adf368c342e1ac26fda83193d5443b3d8a219..1eac4a10974550dc20f78f491e4cdfcd28c2f2a4 100644 --- a/briar-android/src/org/briarproject/android/util/QrCodeDecoder.java +++ b/briar-android/src/org/briarproject/android/util/QrCodeDecoder.java @@ -4,6 +4,7 @@ import android.hardware.Camera; import android.hardware.Camera.PreviewCallback; import android.hardware.Camera.Size; import android.os.AsyncTask; +import android.support.annotation.UiThread; import com.google.zxing.BinaryBitmap; import com.google.zxing.LuminanceSource; @@ -33,19 +34,24 @@ public class QrCodeDecoder implements PreviewConsumer, PreviewCallback { this.callback = callback; } + @Override public void start(Camera camera) { stopped = false; askForPreviewFrame(camera); } + @Override public void stop() { stopped = true; } + @UiThread private void askForPreviewFrame(Camera camera) { if (!stopped) camera.setOneShotPreviewCallback(this); } + @UiThread + @Override public void onPreviewFrame(byte[] data, Camera camera) { if (!stopped) { Size size = camera.getParameters().getPreviewSize(); @@ -55,9 +61,9 @@ public class QrCodeDecoder implements PreviewConsumer, PreviewCallback { private class DecoderTask extends AsyncTask<Void, Void, Void> { - final Camera camera; - final byte[] data; - final int width, height; + private final Camera camera; + private final byte[] data; + private final int width, height; DecoderTask(Camera camera, byte[] data, int width, int height) { this.camera = camera; diff --git a/briar-android/src/org/briarproject/android/view/CameraView.java b/briar-android/src/org/briarproject/android/view/CameraView.java index 388f3a9a9205a128b66783d9abfa2ae3d5787d65..afbff4f54a44a1d8992a2e871442ec1f2b85eae7 100644 --- a/briar-android/src/org/briarproject/android/view/CameraView.java +++ b/briar-android/src/org/briarproject/android/view/CameraView.java @@ -7,6 +7,7 @@ import android.hardware.Camera.CameraInfo; import android.hardware.Camera.Parameters; import android.hardware.Camera.Size; import android.os.Build; +import android.support.annotation.UiThread; import android.util.AttributeSet; import android.view.Surface; import android.view.SurfaceHolder; @@ -72,6 +73,7 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback, if (surface != null) surface.release(); } + @UiThread public void start(Camera camera, PreviewConsumer previewConsumer, int rotationDegrees) { this.camera = camera; @@ -97,17 +99,18 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback, if (surface != null) startPreview(getHolder()); } + @UiThread public void stop() { stopPreview(); try { - if (camera != null) - camera.release(); + if (camera != null) camera.release(); } catch (RuntimeException e) { LOG.log(WARNING, "Error releasing camera", e); } camera = null; } + @UiThread private void startPreview(SurfaceHolder holder) { try { camera.setPreviewDisplay(holder); @@ -118,28 +121,29 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback, } } + @UiThread private void stopPreview() { try { stopConsumer(); - if (camera != null) - camera.stopPreview(); + if (camera != null) camera.stopPreview(); } catch (RuntimeException e) { LOG.log(WARNING, "Error stopping camera preview", e); } } + @UiThread public void startConsumer() { if (autoFocus) camera.autoFocus(this); previewConsumer.start(camera); } + @UiThread public void stopConsumer() { - if (previewConsumer != null) { - previewConsumer.stop(); - } + if (previewConsumer != null) previewConsumer.stop(); if (autoFocus) camera.cancelAutoFocus(); } + @UiThread private void setDisplayOrientation(int rotationDegrees) { int orientation; CameraInfo info = new CameraInfo(); @@ -160,6 +164,7 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback, displayOrientation = orientation; } + @UiThread private Parameters setSceneMode(Camera camera, Parameters params) { List<String> sceneModes = params.getSupportedSceneModes(); if (sceneModes == null) return params; @@ -172,18 +177,21 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback, return params; } + @UiThread private Parameters disableFlash(Camera camera, Parameters params) { params.setFlashMode(FLASH_MODE_OFF); camera.setParameters(params); return camera.getParameters(); } + @UiThread private Parameters disableSceneMode(Camera camera, Parameters params) { params.setSceneMode(SCENE_MODE_AUTO); camera.setParameters(params); return camera.getParameters(); } + @UiThread private Parameters setBestParameters(Camera camera, Parameters params) { setVideoStabilisation(params); setFocusMode(params); @@ -193,6 +201,7 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback, return camera.getParameters(); } + @UiThread private void setVideoStabilisation(Parameters params) { if (Build.VERSION.SDK_INT >= 15 && params.isVideoStabilizationSupported()) { @@ -200,6 +209,7 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback, } } + @UiThread private void setFocusMode(Parameters params) { List<String> focusModes = params.getSupportedFocusModes(); if (LOG.isLoggable(INFO)) LOG.info("Focus modes: " + focusModes); @@ -218,6 +228,7 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback, } } + @UiThread private void setPreviewSize(Parameters params) { if (surfaceWidth == 0 || surfaceHeight == 0) return; float idealRatio = (float) surfaceWidth / surfaceHeight; @@ -249,11 +260,13 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback, } } + @UiThread private void enableAutoFocus(String focusMode) { autoFocus = FOCUS_MODE_AUTO.equals(focusMode) || FOCUS_MODE_MACRO.equals(focusMode); } + @UiThread private void logCameraParameters() { if (LOG.isLoggable(INFO)) { Parameters params = camera.getParameters(); @@ -270,7 +283,17 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback, } @Override - public void surfaceCreated(SurfaceHolder holder) { + public void surfaceCreated(final SurfaceHolder holder) { + post(new Runnable() { + @Override + public void run() { + surfaceCreatedUi(holder); + } + }); + } + + @UiThread + private void surfaceCreatedUi(SurfaceHolder holder) { LOG.info("Surface created"); if (surface != null) throw new IllegalStateException(); surface = holder.getSurface(); @@ -278,7 +301,18 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback, } @Override - public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { + public void surfaceChanged(final SurfaceHolder holder, int format, + final int w, final int h) { + post(new Runnable() { + @Override + public void run() { + surfaceChangedUi(holder, w, h); + } + }); + } + + @UiThread + private void surfaceChangedUi(SurfaceHolder holder, int w, int h) { if (LOG.isLoggable(INFO)) LOG.info("Surface changed: " + w + "x" + h); // Release the previous surface if necessary if (surface != null && surface != holder.getSurface()) @@ -300,7 +334,17 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback, } @Override - public void surfaceDestroyed(SurfaceHolder holder) { + public void surfaceDestroyed(final SurfaceHolder holder) { + post(new Runnable() { + @Override + public void run() { + surfaceDestroyedUi(holder); + } + }); + } + + @UiThread + private void surfaceDestroyedUi(SurfaceHolder holder) { LOG.info("Surface destroyed"); if (holder.getSurface() != surface) throw new IllegalStateException(); if (surface != null) surface.release(); @@ -317,6 +361,7 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback, }, AUTO_FOCUS_RETRY_DELAY); } + @UiThread private void retryAutoFocus() { try { if (camera != null) camera.autoFocus(this); diff --git a/briar-core/src/org/briarproject/keyagreement/KeyAgreementTaskImpl.java b/briar-core/src/org/briarproject/keyagreement/KeyAgreementTaskImpl.java index 12f7678740421fbae7f1251c7f7a107cb6b967f8..e50267698764a701a893cd8c00af402494ff710f 100644 --- a/briar-core/src/org/briarproject/keyagreement/KeyAgreementTaskImpl.java +++ b/briar-core/src/org/briarproject/keyagreement/KeyAgreementTaskImpl.java @@ -39,7 +39,7 @@ class KeyAgreementTaskImpl extends Thread implements private Payload localPayload; private Payload remotePayload; - public KeyAgreementTaskImpl(Clock clock, CryptoComponent crypto, + KeyAgreementTaskImpl(Clock clock, CryptoComponent crypto, EventBus eventBus, PayloadEncoder payloadEncoder, PluginManager pluginManager, Executor ioExecutor) { this.crypto = crypto;