From c7028fde9ba141a6aa27e7fc9170b7517ba5d2a3 Mon Sep 17 00:00:00 2001 From: Mattia Iavarone Date: Sat, 14 Dec 2019 15:04:54 +0100 Subject: [PATCH] Test --- .../cameraview/engine/CameraIntegrationTest.java | 1 + .../cameraview/engine/CameraEngine.java | 14 ++++++++++---- .../engine/orchestrator/CameraOrchestrator.java | 16 ++++++++++++++++ .../cameraview/internal/utils/WorkerHandler.java | 8 +++++++- 4 files changed, 34 insertions(+), 5 deletions(-) diff --git a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/engine/CameraIntegrationTest.java b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/engine/CameraIntegrationTest.java index 39eb8a28..59675c30 100644 --- a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/engine/CameraIntegrationTest.java +++ b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/engine/CameraIntegrationTest.java @@ -563,6 +563,7 @@ public abstract class CameraIntegrationTest extends Base @Test @Retry(emulatorOnly = true) + @SdkExclude(maxSdkVersion = 22, emulatorOnly = true) public void testSetPreviewFrameRate() { CameraOptions options = openSync(true); camera.setPreviewFrameRate(30); diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/CameraEngine.java b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/CameraEngine.java index d035512c..d3f7ecd7 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/CameraEngine.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/CameraEngine.java @@ -216,7 +216,7 @@ public abstract class CameraEngine implements mCrashHandler = new Handler(Looper.getMainLooper()); mFrameManager = instantiateFrameManager(); mAngles = new Angles(); - recreateHandler(); + recreateHandler(false); } public void setPreview(@NonNull CameraPreview cameraPreview) { @@ -276,7 +276,7 @@ public abstract class CameraEngine implements // (at least in Camera1, e.g. onError). if (fromExceptionHandler) { LOG.e("EXCEPTION:", "Handler thread is gone. Replacing."); - recreateHandler(); + recreateHandler(false); } // 2. Depending on the exception, we must destroy(false|true) to release resources, and @@ -308,7 +308,13 @@ public abstract class CameraEngine implements }); } - private void recreateHandler() { + /** + * Recreates the handler, to ensure we use a fresh one from now on. + * If we suspect that handler is currently stuck, the orchestrator should be reset + * because it hosts a chain of tasks and the last one will never complete. + * @param resetOrchestrator true to reset + */ + private void recreateHandler(boolean resetOrchestrator) { if (mHandler != null) mHandler.destroy(); mHandler = WorkerHandler.get("CameraViewEngine"); mHandler.getThread().setUncaughtExceptionHandler(new CrashExceptionHandler()); @@ -370,7 +376,7 @@ public abstract class CameraEngine implements LOG.e("DESTROY: Could not destroy synchronously after 6 seconds.", "Current thread:", Thread.currentThread(), "Handler thread:", mHandler.getThread()); - recreateHandler(); + recreateHandler(true); LOG.e("DESTROY: Could not destroy synchronously after 6 seconds.", "Trying again on thread:", mHandler.getThread()); destroy(unrecoverably); diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/orchestrator/CameraOrchestrator.java b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/orchestrator/CameraOrchestrator.java index 7ac3c2d8..45166288 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/orchestrator/CameraOrchestrator.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/orchestrator/CameraOrchestrator.java @@ -11,7 +11,9 @@ import com.otaliastudios.cameraview.CameraLogger; import com.otaliastudios.cameraview.internal.utils.WorkerHandler; import java.util.ArrayDeque; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.CancellationException; @@ -161,6 +163,20 @@ public class CameraOrchestrator { } } + public void reset() { + synchronized (mLock) { + List all = new ArrayList<>(); + //noinspection CollectionAddAllCanBeReplacedWithConstructor + all.addAll(mDelayedJobs.keySet()); + for (Token token : mJobs) { + all.add(token.name); + } + for (String job : all) { + remove(job); + } + } + } + private void ensureToken() { synchronized (mLock) { if (mJobs.isEmpty()) { diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/internal/utils/WorkerHandler.java b/cameraview/src/main/java/com/otaliastudios/cameraview/internal/utils/WorkerHandler.java index 180923ed..81743f8d 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/internal/utils/WorkerHandler.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/internal/utils/WorkerHandler.java @@ -96,7 +96,13 @@ public class WorkerHandler { private WorkerHandler(@NonNull String name) { mName = name; - mThread = new HandlerThread(name); + mThread = new HandlerThread(name) { + @NonNull + @Override + public String toString() { + return super.toString() + "[" + getThreadId() + "]"; + } + }; mThread.setDaemon(true); mThread.start(); mHandler = new Handler(mThread.getLooper());