Merge changes I7078a750,I9d1fd206,Icebddffd into androidx-master-dev
* changes:
Remove the callbackHandler from ThreadConfig.
Use the background Handler to process the image
Add an Executor as part of setAnalyzer API.
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/ImageAnalysisTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/ImageAnalysisTest.java
index 387a960..3602ea9 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/ImageAnalysisTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/ImageAnalysisTest.java
@@ -43,6 +43,7 @@
import androidx.camera.core.ImageAnalysisConfig;
import androidx.camera.core.ImageProxy;
import androidx.camera.core.UseCase.StateChangeListener;
+import androidx.camera.core.impl.utils.executor.CameraXExecutors;
import androidx.camera.testing.CameraUtil;
import androidx.test.annotation.UiThreadTest;
import androidx.test.core.app.ApplicationProvider;
@@ -145,7 +146,7 @@
Analyzer initialAnalyzer = useCase.getAnalyzer();
- useCase.setAnalyzer(mMockAnalyzer);
+ useCase.setAnalyzer(CameraXExecutors.newHandlerExecutor(mHandler), mMockAnalyzer);
Analyzer retrievedAnalyzer = useCase.getAnalyzer();
@@ -163,7 +164,7 @@
useCase.updateSuggestedResolution(suggestedResolutionMap);
useCase.addStateChangeListener(mMockListener);
- useCase.setAnalyzer(mMockAnalyzer);
+ useCase.setAnalyzer(CameraXExecutors.newHandlerExecutor(mHandler), mMockAnalyzer);
verify(mMockListener, times(1)).onUseCaseActive(useCase);
}
@@ -176,7 +177,7 @@
suggestedResolutionMap.put(mCameraId, DEFAULT_RESOLUTION);
useCase.updateSuggestedResolution(suggestedResolutionMap);
useCase.addStateChangeListener(mMockListener);
- useCase.setAnalyzer(mMockAnalyzer);
+ useCase.setAnalyzer(CameraXExecutors.newHandlerExecutor(mHandler), mMockAnalyzer);
useCase.removeAnalyzer();
verify(mMockListener, times(1)).onUseCaseInactive(useCase);
@@ -197,9 +198,8 @@
private void analyzerAnalyzesImagesWithMode(ImageReaderMode imageReaderMode)
throws InterruptedException, CameraInfoUnavailableException {
final int imageFormat = ImageFormat.YUV_420_888;
- ImageAnalysisConfig config =
- new ImageAnalysisConfig.Builder().setImageReaderMode(
- imageReaderMode).setCallbackHandler(mHandler).build();
+ ImageAnalysisConfig config = new ImageAnalysisConfig.Builder().setImageReaderMode(
+ imageReaderMode).build();
ImageAnalysis useCase = new ImageAnalysis(config);
Map<String, Size> suggestedResolutionMap = new HashMap<>();
suggestedResolutionMap.put(mCameraId, DEFAULT_RESOLUTION);
@@ -209,7 +209,7 @@
mInstrumentation.runOnMainSync(new Runnable() {
@Override
public void run() {
- useCase.setAnalyzer(mAnalyzer);
+ useCase.setAnalyzer(CameraXExecutors.newHandlerExecutor(mHandler), mAnalyzer);
}
});
@@ -229,13 +229,12 @@
@Test
@UiThreadTest
public void analyzerDoesNotAnalyzeImages_whenCameraIsNotOpen() throws InterruptedException {
- ImageAnalysisConfig config =
- new ImageAnalysisConfig.Builder().setCallbackHandler(mHandler).build();
+ ImageAnalysisConfig config = new ImageAnalysisConfig.Builder().build();
ImageAnalysis useCase = new ImageAnalysis(config);
Map<String, Size> suggestedResolutionMap = new HashMap<>();
suggestedResolutionMap.put(mCameraId, DEFAULT_RESOLUTION);
useCase.updateSuggestedResolution(suggestedResolutionMap);
- useCase.setAnalyzer(mAnalyzer);
+ useCase.setAnalyzer(CameraXExecutors.newHandlerExecutor(mHandler), mAnalyzer);
// Keep the lifecycle in an inactive state.
// Wait a little while for frames to be analyzed.
mAnalysisResultsSemaphore.tryAcquire(5, TimeUnit.SECONDS);
@@ -254,10 +253,9 @@
final int imageFormat = ImageFormat.YUV_420_888;
final Size[] sizes = {SECONDARY_RESOLUTION, DEFAULT_RESOLUTION};
- ImageAnalysisConfig config =
- new ImageAnalysisConfig.Builder().setCallbackHandler(mHandler).build();
+ ImageAnalysisConfig config = new ImageAnalysisConfig.Builder().build();
ImageAnalysis useCase = new ImageAnalysis(config);
- useCase.setAnalyzer(mAnalyzer);
+ useCase.setAnalyzer(CameraXExecutors.newHandlerExecutor(mHandler), mAnalyzer);
for (Size size : sizes) {
Map<String, Size> suggestedResolutionMap = new HashMap<>();
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/SensorOrientedMeteringPointFactoryTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/SensorOrientedMeteringPointFactoryTest.java
index dc29aaa..e472f28 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/SensorOrientedMeteringPointFactoryTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/SensorOrientedMeteringPointFactoryTest.java
@@ -22,8 +22,6 @@
import android.app.Instrumentation;
import android.content.Context;
-import android.os.Handler;
-import android.os.Looper;
import android.util.Rational;
import androidx.camera.core.AppConfig;
@@ -114,7 +112,6 @@
.setLensFacing(CameraX.LensFacing.BACK)
.setTargetAspectRatio(AspectRatio.RATIO_4_3)
.setTargetName("ImageAnalysis")
- .setCallbackHandler(new Handler(Looper.getMainLooper()))
.build();
ImageAnalysis imageAnalysis = new ImageAnalysis(imageAnalysisConfig);
mInstrumentation.runOnMainSync(new Runnable() {
@@ -139,7 +136,6 @@
.setLensFacing(CameraX.LensFacing.BACK)
.setTargetAspectRatio(AspectRatio.RATIO_4_3)
.setTargetName("ImageAnalysis")
- .setCallbackHandler(new Handler(Looper.getMainLooper()))
.build();
ImageAnalysis imageAnalysis = new ImageAnalysis(imageAnalysisConfig);
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/UseCaseCombinationTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/UseCaseCombinationTest.java
index d1c2c3f..d9f5a60 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/UseCaseCombinationTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/UseCaseCombinationTest.java
@@ -23,8 +23,6 @@
import android.Manifest;
import android.app.Instrumentation;
import android.content.Context;
-import android.os.Handler;
-import android.os.Looper;
import androidx.camera.core.AppConfig;
import androidx.camera.core.CameraX;
@@ -36,6 +34,7 @@
import androidx.camera.core.ImageProxy;
import androidx.camera.core.Preview;
import androidx.camera.core.PreviewConfig;
+import androidx.camera.core.impl.utils.executor.CameraXExecutors;
import androidx.camera.testing.CameraUtil;
import androidx.camera.testing.fakes.FakeLifecycleOwner;
import androidx.lifecycle.MutableLiveData;
@@ -144,7 +143,7 @@
@Override
public void run() {
CameraX.bindToLifecycle(mLifecycle, mPreview, mImageAnalysis);
- mImageAnalysis.setAnalyzer(mImageAnalyzer);
+ mImageAnalysis.setAnalyzer(CameraXExecutors.mainThreadExecutor(), mImageAnalyzer);
mAnalysisResult.observe(mLifecycle,
createCountIncrementingObserver());
mLifecycle.startAndResume();
@@ -171,7 +170,7 @@
@Override
public void run() {
CameraX.bindToLifecycle(mLifecycle, mPreview, mImageAnalysis, mImageCapture);
- mImageAnalysis.setAnalyzer(mImageAnalyzer);
+ mImageAnalysis.setAnalyzer(CameraXExecutors.mainThreadExecutor(), mImageAnalyzer);
mAnalysisResult.observe(mLifecycle,
createCountIncrementingObserver());
mLifecycle.startAndResume();
@@ -192,7 +191,6 @@
new ImageAnalysisConfig.Builder()
.setLensFacing(DEFAULT_LENS_FACING)
.setTargetName("ImageAnalysis")
- .setCallbackHandler(new Handler(Looper.getMainLooper()))
.build();
mImageAnalyzer =
new ImageAnalysis.Analyzer() {
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/impl/Camera2ImplCameraXTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/impl/Camera2ImplCameraXTest.java
index 0a7309f..a67fbe6 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/impl/Camera2ImplCameraXTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/impl/Camera2ImplCameraXTest.java
@@ -45,6 +45,7 @@
import androidx.camera.core.ImageCapture;
import androidx.camera.core.ImageCaptureConfig;
import androidx.camera.core.ImageProxy;
+import androidx.camera.core.impl.utils.executor.CameraXExecutors;
import androidx.camera.testing.CameraUtil;
import androidx.camera.testing.fakes.FakeLifecycleOwner;
import androidx.lifecycle.MutableLiveData;
@@ -143,7 +144,7 @@
ImageAnalysis useCase = new ImageAnalysis(builder.build());
CameraX.bindToLifecycle(mLifecycle, useCase);
- useCase.setAnalyzer(mImageAnalyzer);
+ useCase.setAnalyzer(CameraXExecutors.mainThreadExecutor(), mImageAnalyzer);
mAnalysisResult.observe(mLifecycle, mockObserver);
mLifecycle.startAndResume();
@@ -184,8 +185,8 @@
CameraX.bindToLifecycle(mLifecycle, useCase, useCase2);
- useCase.setAnalyzer(mImageAnalyzer);
- useCase2.setAnalyzer(mImageAnalyzer2);
+ useCase.setAnalyzer(CameraXExecutors.mainThreadExecutor(), mImageAnalyzer);
+ useCase2.setAnalyzer(CameraXExecutors.mainThreadExecutor(), mImageAnalyzer2);
mAnalysisResult.observe(mLifecycle, mockObserver);
mAnalysisResult2.observe(mLifecycle, mockObserver2);
@@ -216,7 +217,7 @@
.setSessionCaptureCallback(sessionCaptureCallback);
ImageAnalysis useCase = new ImageAnalysis(configBuilder.build());
CameraX.bindToLifecycle(mLifecycle, useCase);
- useCase.setAnalyzer(mImageAnalyzer);
+ useCase.setAnalyzer(CameraXExecutors.mainThreadExecutor(), mImageAnalyzer);
mAnalysisResult.observe(mLifecycle, createCountIncrementingObserver(observedCount));
mLifecycle.startAndResume();
@@ -259,7 +260,7 @@
@Override
public void run() {
CameraX.bindToLifecycle(mLifecycle, useCase);
- useCase.setAnalyzer(mImageAnalyzer);
+ useCase.setAnalyzer(CameraXExecutors.mainThreadExecutor(), mImageAnalyzer);
mLifecycle.startAndResume();
}
});
@@ -362,7 +363,7 @@
@Override
public void run() {
CameraX.bindToLifecycle(mLifecycle, useCase);
- useCase.setAnalyzer(mImageAnalyzer);
+ useCase.setAnalyzer(CameraXExecutors.mainThreadExecutor(), mImageAnalyzer);
}
});
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysis.java b/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysis.java
index 80649f8..06f9ed9 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysis.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysis.java
@@ -17,8 +17,6 @@
package androidx.camera.core;
import android.media.ImageReader;
-import android.os.Handler;
-import android.os.Looper;
import android.util.Log;
import android.util.Size;
import android.view.Display;
@@ -62,8 +60,8 @@
private static final int NON_BLOCKING_IMAGE_DEPTH = 4;
final AtomicReference<Analyzer> mSubscribedAnalyzer;
+ final AtomicReference<Executor> mAnalyzerExecutor;
final AtomicInteger mRelativeRotation = new AtomicInteger();
- final Handler mHandler;
private final ImageAnalysisConfig.Builder mUseCaseConfigBuilder;
@SuppressWarnings("WeakerAccess") /* synthetic access */
final ImageAnalysisBlockingAnalyzer mImageAnalysisBlockingAnalyzer;
@@ -86,18 +84,15 @@
// Get the combined configuration with defaults
ImageAnalysisConfig combinedConfig = (ImageAnalysisConfig) getUseCaseConfig();
mSubscribedAnalyzer = new AtomicReference<>();
- mHandler = combinedConfig.getCallbackHandler(null);
- if (mHandler == null) {
- throw new IllegalStateException("No default mHandler specified.");
- }
+ mAnalyzerExecutor = new AtomicReference<>();
setImageFormat(ImageReaderFormatRecommender.chooseCombo().imageAnalysisFormat());
// Init both instead of lazy loading to void synchronization.
mImageAnalysisBlockingAnalyzer = new ImageAnalysisBlockingAnalyzer(mSubscribedAnalyzer,
mRelativeRotation,
- mHandler);
+ mAnalyzerExecutor);
mImageAnalysisNonBlockingAnalyzer = new ImageAnalysisNonBlockingAnalyzer(
mSubscribedAnalyzer, mRelativeRotation,
- mHandler, config.getBackgroundExecutor(
+ mAnalyzerExecutor, config.getBackgroundExecutor(
CameraXExecutors.highPriorityExecutor()));
}
@@ -184,15 +179,17 @@
/**
* Removes a previously set analyzer.
*
- * <p>This is equivalent to calling {@code setAnalyzer(null)}. This will stop data from
- * streaming to the {@link ImageAnalysis}.
+ * <p>This will stop data from streaming to the {@link ImageAnalysis}.
*
* @throws IllegalStateException If not called on main thread.
*/
@UiThread
public void removeAnalyzer() {
Threads.checkMainThread();
- setAnalyzer(null);
+ mAnalyzerExecutor.set(null);
+ if (mSubscribedAnalyzer.getAndSet(null) != null) {
+ notifyInactive();
+ }
}
/**
@@ -266,8 +263,7 @@
* Sets an analyzer to receive and analyze images.
*
* <p>Setting an analyzer will signal to the camera that it should begin sending data. The
- * stream of data can be stopped by setting the analyzer to {@code null} or by calling {@link
- * #removeAnalyzer()}.
+ * stream of data can be stopped by calling {@link #removeAnalyzer()}.
*
* <p>Applications can process or copy the image by implementing the {@link Analyzer}. If
* frames should be skipped (no analysis), the analyzer function should return, instead of
@@ -276,18 +272,18 @@
* <p>Setting an analyzer function replaces any previous analyzer. Only one analyzer can be
* set at any time.
*
- * @param analyzer of the images or {@code null} to stop data streaming to
- * {@link ImageAnalysis}.
+ * @param executor The executor in which the
+ * {@link ImageAnalysis.Analyzer#analyze(ImageProxy, int)} will be run.
+ * @param analyzer of the images.
* @throws IllegalStateException If not called on main thread.
*/
@UiThread
- public void setAnalyzer(@Nullable Analyzer analyzer) {
+ public void setAnalyzer(@NonNull Executor executor, @NonNull Analyzer analyzer) {
Threads.checkMainThread();
+ mAnalyzerExecutor.set(executor);
Analyzer previousAnalyzer = mSubscribedAnalyzer.getAndSet(analyzer);
if (previousAnalyzer == null && analyzer != null) {
notifyActive();
- } else if (previousAnalyzer != null && analyzer == null) {
- notifyInactive();
}
}
@@ -385,8 +381,8 @@
/**
* Interface for analyzing images.
*
- * <p>Implement Analyzer and pass it to {@link ImageAnalysis#setAnalyzer(Analyzer)} to receive
- * images and perform custom processing by implementing the
+ * <p>Implement Analyzer and pass it to {@link ImageAnalysis#setAnalyzer(Executor, Analyzer)}
+ * to receive images and perform custom processing by implementing the
* {@link ImageAnalysis.Analyzer#analyze(ImageProxy, int)} function.
*/
public interface Analyzer {
@@ -428,7 +424,6 @@
public static final class Defaults implements ConfigProvider<ImageAnalysisConfig> {
private static final ImageReaderMode DEFAULT_IMAGE_READER_MODE =
ImageReaderMode.ACQUIRE_LATEST_IMAGE;
- private static final Handler DEFAULT_HANDLER = new Handler(Looper.getMainLooper());
private static final int DEFAULT_IMAGE_QUEUE_DEPTH = 6;
private static final Size DEFAULT_TARGET_RESOLUTION = new Size(640, 480);
private static final Size DEFAULT_MAX_RESOLUTION = new Size(1920, 1080);
@@ -440,7 +435,6 @@
ImageAnalysisConfig.Builder builder =
new ImageAnalysisConfig.Builder()
.setImageReaderMode(DEFAULT_IMAGE_READER_MODE)
- .setCallbackHandler(DEFAULT_HANDLER)
.setImageQueueDepth(DEFAULT_IMAGE_QUEUE_DEPTH)
.setDefaultResolution(DEFAULT_TARGET_RESOLUTION)
.setMaxResolution(DEFAULT_MAX_RESOLUTION)
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysisAbstractAnalyzer.java b/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysisAbstractAnalyzer.java
index 74b18c4..6d1a3c3 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysisAbstractAnalyzer.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysisAbstractAnalyzer.java
@@ -16,8 +16,7 @@
package androidx.camera.core;
-import android.os.Handler;
-
+import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
@@ -34,16 +33,16 @@
// Member variables from ImageAnalysis.
private final AtomicReference<ImageAnalysis.Analyzer> mSubscribedAnalyzer;
private final AtomicInteger mRelativeRotation;
- final Handler mUserHandler;
+ final AtomicReference<Executor> mUserExecutor;
// Flag that reflects the state of ImageAnalysis.
private AtomicBoolean mIsClosed;
ImageAnalysisAbstractAnalyzer(AtomicReference<ImageAnalysis.Analyzer> subscribedAnalyzer,
- AtomicInteger relativeRotation, Handler userHandler) {
+ AtomicInteger relativeRotation, AtomicReference<Executor> userExecutor) {
mSubscribedAnalyzer = subscribedAnalyzer;
mRelativeRotation = relativeRotation;
- mUserHandler = userHandler;
+ mUserExecutor = userExecutor;
mIsClosed = new AtomicBoolean(false);
}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysisBlockingAnalyzer.java b/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysisBlockingAnalyzer.java
index 1283f8d..43e3a65 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysisBlockingAnalyzer.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysisBlockingAnalyzer.java
@@ -16,8 +16,7 @@
package androidx.camera.core;
-import android.os.Handler;
-
+import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
@@ -30,8 +29,8 @@
ImageAnalysisBlockingAnalyzer(
AtomicReference<ImageAnalysis.Analyzer> subscribedAnalyzer,
- AtomicInteger relativeRotation, Handler userHandler) {
- super(subscribedAnalyzer, relativeRotation, userHandler);
+ AtomicInteger relativeRotation, AtomicReference<Executor> userExecutor) {
+ super(subscribedAnalyzer, relativeRotation, userExecutor);
}
@Override
@@ -40,18 +39,23 @@
if (image == null) {
return;
}
- try {
- mUserHandler.post(new Runnable() {
- @Override
- public void run() {
- try {
- analyzeImage(image);
- } finally {
- image.close();
+ Executor executor = mUserExecutor.get();
+ if (executor != null) {
+ try {
+ executor.execute(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ analyzeImage(image);
+ } finally {
+ image.close();
+ }
}
- }
- });
- } catch (RuntimeException e) {
+ });
+ } catch (RuntimeException e) {
+ image.close();
+ }
+ } else {
image.close();
}
}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysisConfig.java b/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysisConfig.java
index 98b8629..926557d4 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysisConfig.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysisConfig.java
@@ -17,7 +17,6 @@
package androidx.camera.core;
import android.media.ImageReader;
-import android.os.Handler;
import android.util.Rational;
import android.util.Size;
import android.view.Surface;
@@ -442,31 +441,6 @@
// Implementations of ThreadConfig default methods
/**
- * Returns the default handler that will be used for callbacks.
- *
- * @param valueIfMissing The value to return if this configuration option has not been set.
- * @return The stored value or <code>valueIfMissing</code> if the value does not exist in this
- * configuration.
- */
- @Override
- @Nullable
- public Handler getCallbackHandler(@Nullable Handler valueIfMissing) {
- return retrieveOption(OPTION_CALLBACK_HANDLER, valueIfMissing);
- }
-
- /**
- * Returns the default handler that will be used for callbacks.
- *
- * @return The stored value, if it exists in this configuration.
- * @throws IllegalArgumentException if the option does not exist in this configuration.
- */
- @Override
- @NonNull
- public Handler getCallbackHandler() {
- return retrieveOption(OPTION_CALLBACK_HANDLER);
- }
-
- /**
* Returns the executor that will be used for background tasks.
*
* @param valueIfMissing The value to return if this configuration option has not been set.
@@ -912,19 +886,6 @@
// Implementations of ThreadConfig.Builder default methods
/**
- * Sets the default handler that will be used for callbacks.
- *
- * @param handler The handler which will be used to post callbacks.
- * @return the current Builder.
- */
- @Override
- @NonNull
- public Builder setCallbackHandler(@NonNull Handler handler) {
- getMutableConfig().insertOption(OPTION_CALLBACK_HANDLER, handler);
- return this;
- }
-
- /**
* Sets the default executor that will be used for background tasks.
*
* @param executor The executor which will be used for background tasks.
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysisNonBlockingAnalyzer.java b/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysisNonBlockingAnalyzer.java
index 0583b38..71a6232 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysisNonBlockingAnalyzer.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysisNonBlockingAnalyzer.java
@@ -16,7 +16,6 @@
package androidx.camera.core;
-import android.os.Handler;
import android.util.Log;
import androidx.annotation.GuardedBy;
@@ -52,8 +51,9 @@
private final AtomicLong mFinishedImageTimestamp;
ImageAnalysisNonBlockingAnalyzer(AtomicReference<ImageAnalysis.Analyzer> subscribedAnalyzer,
- AtomicInteger relativeRotation, Handler userHandler, Executor executor) {
- super(subscribedAnalyzer, relativeRotation, userHandler);
+ AtomicInteger relativeRotation, AtomicReference<Executor> userExecutor,
+ Executor executor) {
+ super(subscribedAnalyzer, relativeRotation, userExecutor);
mBackgroundExecutor = executor;
mPostedImageTimestamp = new AtomicLong();
mFinishedImageTimestamp = new AtomicLong();
@@ -128,26 +128,31 @@
}
mPostedImageTimestamp.set(imageProxy.getTimestamp());
- try {
- mUserHandler.post(new Runnable() {
- @Override
- public void run() {
- try {
- analyzeImage(imageProxy);
- } finally {
- finishImage(imageProxy);
- mBackgroundExecutor.execute(new Runnable() {
- @Override
- public void run() {
- analyzeCachedImage();
- }
- });
+ Executor executor = mUserExecutor.get();
+ if (executor != null) {
+ try {
+ executor.execute(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ analyzeImage(imageProxy);
+ } finally {
+ finishImage(imageProxy);
+ mBackgroundExecutor.execute(new Runnable() {
+ @Override
+ public void run() {
+ analyzeCachedImage();
+ }
+ });
+ }
}
- }
- });
- } catch (RuntimeException e) {
- // Unblock if fails to post to user thread.
- Log.e(TAG, "Error calling user callback", e);
+ });
+ } catch (RuntimeException e) {
+ // Unblock if fails to post to user thread.
+ Log.e(TAG, "Error calling user callback", e);
+ finishImage(imageProxy);
+ }
+ } else {
finishImage(imageProxy);
}
}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java b/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java
index 8486a42..dd76501 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java
@@ -22,6 +22,7 @@
import android.media.Image;
import android.media.ImageReader;
import android.os.Handler;
+import android.os.HandlerThread;
import android.os.Looper;
import android.os.SystemClock;
import android.util.Log;
@@ -55,12 +56,13 @@
import com.google.common.util.concurrent.ListenableFuture;
import java.io.File;
-import java.util.ArrayDeque;
import java.util.ArrayList;
+import java.util.Deque;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -101,10 +103,13 @@
private static final Metadata EMPTY_METADATA = new Metadata();
@SuppressWarnings("WeakerAccess") /* synthetic accessor */
final Handler mMainHandler = new Handler(Looper.getMainLooper());
+ @Nullable
+ private HandlerThread mProcessingImageResultThread;
+ @Nullable
+ private Handler mProcessingImageResultHandler;
+
@SuppressWarnings("WeakerAccess") /* synthetic accessor */
- final ArrayDeque<ImageCaptureRequest> mImageCaptureRequests = new ArrayDeque<>();
- @SuppressWarnings("WeakerAccess") /* synthetic accessor */
- final Handler mHandler;
+ final Deque<ImageCaptureRequest> mImageCaptureRequests = new ConcurrentLinkedDeque<>();
@SuppressWarnings("WeakerAccess") /* synthetic accessor */
SessionConfig.Builder mSessionConfigBuilder;
private final CaptureConfig mCaptureConfig;
@@ -197,11 +202,6 @@
mEnableCheck3AConverged = false; // skip 3A convergence in MIN_LATENCY mode
}
- mHandler = mConfig.getCallbackHandler(null);
- if (mHandler == null) {
- throw new IllegalStateException("No default handler specified.");
- }
-
CaptureConfig.Builder captureBuilder = CaptureConfig.Builder.createFrom(mConfig);
mCaptureConfig = captureBuilder.build();
}
@@ -212,20 +212,27 @@
SessionConfig.Builder sessionConfigBuilder = SessionConfig.Builder.createFrom(config);
sessionConfigBuilder.addRepeatingCameraCaptureCallback(mSessionCallbackChecker);
+ mProcessingImageResultThread = new HandlerThread("OnImageAvailableHandlerThread");
+ mProcessingImageResultThread.start();
+ mProcessingImageResultHandler = new Handler(mProcessingImageResultThread.getLooper());
+
// Setup the ImageReader to do processing
if (mCaptureProcessor != null) {
+ // TODO: To allow user to use an Executor for the image processing.
ProcessingImageReader processingImageReader =
new ProcessingImageReader(
resolution.getWidth(),
resolution.getHeight(),
getImageFormat(), mMaxCaptureStages,
- mHandler, getCaptureBundle(CaptureBundles.singleDefaultCaptureBundle()),
+ mProcessingImageResultHandler,
+ getCaptureBundle(CaptureBundles.singleDefaultCaptureBundle()),
mCaptureProcessor);
mMetadataMatchingCaptureCallback = processingImageReader.getCameraCaptureCallback();
mImageReader = processingImageReader;
} else {
MetadataImageReader metadataImageReader = new MetadataImageReader(resolution.getWidth(),
- resolution.getHeight(), getImageFormat(), MAX_IMAGES, mHandler);
+ resolution.getHeight(), getImageFormat(), MAX_IMAGES,
+ mProcessingImageResultHandler);
mMetadataMatchingCaptureCallback = metadataImageReader.getCameraCaptureCallback();
mImageReader = metadataImageReader;
}
@@ -256,7 +263,7 @@
}
}
},
- mMainHandler);
+ mProcessingImageResultHandler);
mDeferrableSurface = new ImmediateSurface(mImageReader.getSurface());
sessionConfigBuilder.addNonRepeatingSurface(mDeferrableSurface);
@@ -285,6 +292,7 @@
mDeferrableSurface = null;
ImageReaderProxy imageReaderProxy = mImageReader;
mImageReader = null;
+ HandlerThread handlerThread = mProcessingImageResultThread;
if (deferrableSurface != null) {
deferrableSurface.setOnSurfaceDetachedListener(
@@ -295,6 +303,9 @@
if (imageReaderProxy != null) {
imageReaderProxy.close();
}
+
+ // Close the handlerThread after the ImageReader was closed.
+ handlerThread.quitSafely();
}
});
}
@@ -1160,7 +1171,6 @@
implements ConfigProvider<ImageCaptureConfig> {
private static final CaptureMode DEFAULT_CAPTURE_MODE = CaptureMode.MIN_LATENCY;
private static final FlashMode DEFAULT_FLASH_MODE = FlashMode.OFF;
- private static final Handler DEFAULT_HANDLER = new Handler(Looper.getMainLooper());
private static final int DEFAULT_SURFACE_OCCUPANCY_PRIORITY = 4;
private static final ImageCaptureConfig DEFAULT_CONFIG;
@@ -1170,7 +1180,6 @@
new ImageCaptureConfig.Builder()
.setCaptureMode(DEFAULT_CAPTURE_MODE)
.setFlashMode(DEFAULT_FLASH_MODE)
- .setCallbackHandler(DEFAULT_HANDLER)
.setSurfaceOccupancyPriority(DEFAULT_SURFACE_OCCUPANCY_PRIORITY);
DEFAULT_CONFIG = builder.build();
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ImageCaptureConfig.java b/camera/camera-core/src/main/java/androidx/camera/core/ImageCaptureConfig.java
index 4d6e7e6..617da2a 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/ImageCaptureConfig.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/ImageCaptureConfig.java
@@ -17,7 +17,6 @@
package androidx.camera.core;
import android.graphics.ImageFormat;
-import android.os.Handler;
import android.util.Rational;
import android.util.Size;
import android.view.Surface;
@@ -547,31 +546,6 @@
// Implementations of ThreadConfig default methods
/**
- * Returns the default handler that will be used for callbacks.
- *
- * @param valueIfMissing The value to return if this configuration option has not been set.
- * @return The stored value or <code>valueIfMissing</code> if the value does not exist in this
- * configuration.
- */
- @Override
- @Nullable
- public Handler getCallbackHandler(@Nullable Handler valueIfMissing) {
- return retrieveOption(OPTION_CALLBACK_HANDLER, valueIfMissing);
- }
-
- /**
- * Returns the default handler that will be used for callbacks.
- *
- * @return The stored value, if it exists in this configuration.
- * @throws IllegalArgumentException if the option does not exist in this configuration.
- */
- @Override
- @NonNull
- public Handler getCallbackHandler() {
- return retrieveOption(OPTION_CALLBACK_HANDLER);
- }
-
- /**
* Returns the executor that will be used for background tasks.
*
* @param valueIfMissing The value to return if this configuration option has not been set.
@@ -1058,19 +1032,6 @@
// Implementations of ThreadConfig.Builder default methods
/**
- * Sets the default handler that will be used for callbacks.
- *
- * @param handler The handler which will be used to post callbacks.
- * @return the current Builder.
- */
- @Override
- @NonNull
- public Builder setCallbackHandler(@NonNull Handler handler) {
- getMutableConfig().insertOption(OPTION_CALLBACK_HANDLER, handler);
- return this;
- }
-
- /**
* Sets the default executor that will be used for background tasks.
*
* @param executor The executor which will be used for background tasks.
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/Preview.java b/camera/camera-core/src/main/java/androidx/camera/core/Preview.java
index 6475597..1ad8711 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/Preview.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/Preview.java
@@ -20,7 +20,7 @@
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
import android.os.Handler;
-import android.os.Looper;
+import android.os.HandlerThread;
import android.util.Log;
import android.util.Rational;
import android.util.Size;
@@ -82,7 +82,10 @@
private static final String TAG = "Preview";
private static final String CONFLICTING_SURFACE_API_ERROR_MESSAGE =
"PreviewSurfaceCallback cannot be used with OnPreviewOutputUpdateListener.";
- private final Handler mMainHandler = new Handler(Looper.getMainLooper());
+ @Nullable
+ private HandlerThread mProcessingPreviewThread;
+ @Nullable
+ private Handler mProcessingPreviewHandler;
private final PreviewConfig.Builder mUseCaseConfigBuilder;
@Nullable
@@ -116,13 +119,20 @@
final CaptureProcessor captureProcessor = config.getCaptureProcessor(null);
if (captureProcessor != null) {
CaptureStage captureStage = new CaptureStage.DefaultCaptureStage();
+ // TODO: To allow user to use an Executor for the processing.
+
+ if (mProcessingPreviewHandler == null) {
+ mProcessingPreviewThread = new HandlerThread("ProcessingSurfaceTexture");
+ mProcessingPreviewThread.start();
+ mProcessingPreviewHandler = new Handler(mProcessingPreviewThread.getLooper());
+ }
ProcessingSurfaceTexture processingSurfaceTexture =
new ProcessingSurfaceTexture(
resolution.getWidth(),
resolution.getHeight(),
ImageFormat.YUV_420_888,
- config.getCallbackHandler(),
+ mProcessingPreviewHandler,
captureStage,
captureProcessor);
@@ -182,6 +192,14 @@
if (surfaceTextureHolder != null) {
surfaceTextureHolder.release();
}
+
+ // The handler no longer used by the ProcessingSurfaceTexture, we can close the
+ // handlerTread after the ProcessingSurfaceTexture was released.
+ if (mProcessingPreviewHandler != null) {
+ mProcessingPreviewThread.quitSafely();
+ mProcessingPreviewThread = null;
+ mProcessingPreviewHandler = null;
+ }
}
/**
@@ -584,7 +602,6 @@
*/
@RestrictTo(Scope.LIBRARY_GROUP)
public static final class Defaults implements ConfigProvider<PreviewConfig> {
- private static final Handler DEFAULT_HANDLER = new Handler(Looper.getMainLooper());
private static final Size DEFAULT_MAX_RESOLUTION =
CameraX.getSurfaceManager().getPreviewSize();
private static final int DEFAULT_SURFACE_OCCUPANCY_PRIORITY = 2;
@@ -594,7 +611,6 @@
static {
PreviewConfig.Builder builder =
new PreviewConfig.Builder()
- .setCallbackHandler(DEFAULT_HANDLER)
.setMaxResolution(DEFAULT_MAX_RESOLUTION)
.setSurfaceOccupancyPriority(DEFAULT_SURFACE_OCCUPANCY_PRIORITY);
DEFAULT_CONFIG = builder.build();
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/PreviewConfig.java b/camera/camera-core/src/main/java/androidx/camera/core/PreviewConfig.java
index 91854b5..e8b6f7e 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/PreviewConfig.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/PreviewConfig.java
@@ -16,7 +16,6 @@
package androidx.camera.core;
-import android.os.Handler;
import android.util.Rational;
import android.util.Size;
import android.view.Surface;
@@ -383,31 +382,6 @@
// Implementations of ThreadConfig default methods
/**
- * Returns the default handler that will be used for callbacks.
- *
- * @param valueIfMissing The value to return if this configuration option has not been set.
- * @return The stored value or <code>valueIfMissing</code> if the value does not exist in this
- * configuration.
- */
- @Override
- @Nullable
- public Handler getCallbackHandler(@Nullable Handler valueIfMissing) {
- return retrieveOption(OPTION_CALLBACK_HANDLER, valueIfMissing);
- }
-
- /**
- * Returns the default handler that will be used for callbacks.
- *
- * @return The stored value, if it exists in this configuration.
- * @throws IllegalArgumentException if the option does not exist in this configuration.
- */
- @Override
- @NonNull
- public Handler getCallbackHandler() {
- return retrieveOption(OPTION_CALLBACK_HANDLER);
- }
-
- /**
* Returns the executor that will be used for background tasks.
*
* @param valueIfMissing The value to return if this configuration option has not been set.
@@ -849,19 +823,6 @@
// Implementations of ThreadConfig.Builder default methods
/**
- * Sets the default handler that will be used for callbacks.
- *
- * @param handler The handler which will be used to post callbacks.
- * @return the current Builder.
- */
- @Override
- @NonNull
- public Builder setCallbackHandler(@NonNull Handler handler) {
- getMutableConfig().insertOption(OPTION_CALLBACK_HANDLER, handler);
- return this;
- }
-
- /**
* Sets the default executor that will be used for background tasks.
*
* @param executor The executor which will be used for background tasks.
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ProcessingSurfaceTexture.java b/camera/camera-core/src/main/java/androidx/camera/core/ProcessingSurfaceTexture.java
index 6744bd4..57b5262 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/ProcessingSurfaceTexture.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/ProcessingSurfaceTexture.java
@@ -18,6 +18,7 @@
import android.graphics.PixelFormat;
import android.graphics.SurfaceTexture;
+import android.os.AsyncTask;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
@@ -219,7 +220,7 @@
}
}
},
- mImageReaderHandler
+ AsyncTask.THREAD_POOL_EXECUTOR
);
// Need to wait for Surface has been detached before closing it
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ThreadConfig.java b/camera/camera-core/src/main/java/androidx/camera/core/ThreadConfig.java
index c8814ec..679d446 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/ThreadConfig.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/ThreadConfig.java
@@ -16,8 +16,6 @@
package androidx.camera.core;
-import android.os.Handler;
-
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
@@ -38,16 +36,6 @@
// *********************************************************************************************
/**
- * Option: camerax.core.thread.callbackHandler
- *
- * @hide
- */
- @RestrictTo(Scope.LIBRARY_GROUP)
- Option<Handler> OPTION_CALLBACK_HANDLER =
- Option.create("camerax.core.thread.callbackHandler", Handler.class);
-
-
- /**
* Option: camerax.core.thread.backgroundExecutor
*
* @hide
@@ -59,25 +47,6 @@
// *********************************************************************************************
/**
- * Returns the default handler that will be used for callbacks.
- *
- * @param valueIfMissing The value to return if this configuration option has not been set.
- * @return The stored value or <code>valueIfMissing</code> if the value does not exist in this
- * configuration.
- */
- @Nullable
- Handler getCallbackHandler(@Nullable Handler valueIfMissing);
-
- /**
- * Returns the default handler that will be used for callbacks.
- *
- * @return The stored value, if it exists in this configuration.
- * @throws IllegalArgumentException if the option does not exist in this configuration.
- */
- @NonNull
- Handler getCallbackHandler();
-
- /**
* Returns the executor that will be used for background tasks.
*
* @param valueIfMissing The value to return if this configuration option has not been set.
@@ -108,15 +77,6 @@
interface Builder<B> {
/**
- * Sets the default handler that will be used for callbacks.
- *
- * @param handler The handler which will be used to post callbacks.
- * @return the current Builder.
- */
- @NonNull
- B setCallbackHandler(@NonNull Handler handler);
-
- /**
* Sets the default executor that will be used for background tasks.
*
* @param executor The executor which will be used for background tasks.
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/VideoCapture.java b/camera/camera-core/src/main/java/androidx/camera/core/VideoCapture.java
index 136e04f..e30326c 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/VideoCapture.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/VideoCapture.java
@@ -921,7 +921,6 @@
static {
VideoCaptureConfig.Builder builder =
new VideoCaptureConfig.Builder()
- .setCallbackHandler(DEFAULT_HANDLER)
.setVideoFrameRate(DEFAULT_VIDEO_FRAME_RATE)
.setBitRate(DEFAULT_BIT_RATE)
.setIFrameInterval(DEFAULT_INTRA_FRAME_INTERVAL)
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/VideoCaptureConfig.java b/camera/camera-core/src/main/java/androidx/camera/core/VideoCaptureConfig.java
index bc33309..422ecdd 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/VideoCaptureConfig.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/VideoCaptureConfig.java
@@ -16,7 +16,6 @@
package androidx.camera.core;
-import android.os.Handler;
import android.util.Rational;
import android.util.Size;
import android.view.Surface;
@@ -577,31 +576,6 @@
// Implementations of ThreadConfig default methods
/**
- * Returns the default handler that will be used for callbacks.
- *
- * @param valueIfMissing The value to return if this configuration option has not been set.
- * @return The stored value or <code>valueIfMissing</code> if the value does not exist in this
- * configuration.
- */
- @Override
- @Nullable
- public Handler getCallbackHandler(@Nullable Handler valueIfMissing) {
- return retrieveOption(OPTION_CALLBACK_HANDLER, valueIfMissing);
- }
-
- /**
- * Returns the default handler that will be used for callbacks.
- *
- * @return The stored value, if it exists in this configuration.
- * @throws IllegalArgumentException if the option does not exist in this configuration.
- */
- @Override
- @NonNull
- public Handler getCallbackHandler() {
- return retrieveOption(OPTION_CALLBACK_HANDLER);
- }
-
- /**
* Returns the executor that will be used for background tasks.
*
* @param valueIfMissing The value to return if this configuration option has not been set.
@@ -1105,19 +1079,6 @@
// Implementations of ThreadConfig.Builder default methods
/**
- * Sets the default handler that will be used for callbacks.
- *
- * @param handler The handler which will be used to post callbacks.
- * @return the current Builder.
- */
- @Override
- @NonNull
- public Builder setCallbackHandler(@NonNull Handler handler) {
- getMutableConfig().insertOption(OPTION_CALLBACK_HANDLER, handler);
- return this;
- }
-
- /**
* Sets the default executor that will be used for background tasks.
*
* @param executor The executor which will be used for background tasks.
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/ImageAnalysisNonBlockingAnalyzerTest.java b/camera/camera-core/src/test/java/androidx/camera/core/ImageAnalysisNonBlockingAnalyzerTest.java
index b2d6555..1acb499 100644
--- a/camera/camera-core/src/test/java/androidx/camera/core/ImageAnalysisNonBlockingAnalyzerTest.java
+++ b/camera/camera-core/src/test/java/androidx/camera/core/ImageAnalysisNonBlockingAnalyzerTest.java
@@ -23,8 +23,6 @@
import static org.mockito.Mockito.when;
import android.os.Build;
-import android.os.Handler;
-import android.os.Looper;
import androidx.camera.core.impl.utils.executor.CameraXExecutors;
import androidx.test.filters.SmallTest;
@@ -62,7 +60,7 @@
mImageAnalysisNonBlockingAnalyzer = new ImageAnalysisNonBlockingAnalyzer(
new AtomicReference<ImageAnalysis.Analyzer>(mAnalyzer),
ROTATION,
- new Handler(Looper.getMainLooper()),
+ new AtomicReference<>(CameraXExecutors.mainThreadExecutor()),
CameraXExecutors.directExecutor()
);
}
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/ImageAnalysisTest.java b/camera/camera-core/src/test/java/androidx/camera/core/ImageAnalysisTest.java
index cec54b0..0c29520 100644
--- a/camera/camera-core/src/test/java/androidx/camera/core/ImageAnalysisTest.java
+++ b/camera/camera-core/src/test/java/androidx/camera/core/ImageAnalysisTest.java
@@ -197,18 +197,18 @@
private void setUpImageAnalysisWithMode(ImageAnalysis.ImageReaderMode imageReaderMode) {
mImageAnalysis = new ImageAnalysis(new ImageAnalysisConfig.Builder()
- .setCallbackHandler(mCallbackHandler)
.setBackgroundExecutor(mBackgroundExecutor)
.setImageQueueDepth(QUEUE_DEPTH)
.setImageReaderMode(imageReaderMode)
.build());
- mImageAnalysis.setAnalyzer(new ImageAnalysis.Analyzer() {
- @Override
- public void analyze(ImageProxy image, int rotationDegrees) {
- mImagesReceived.add(image.getImage());
- }
- });
+ mImageAnalysis.setAnalyzer(CameraXExecutors.newHandlerExecutor(mCallbackHandler),
+ new ImageAnalysis.Analyzer() {
+ @Override
+ public void analyze(ImageProxy image, int rotationDegrees) {
+ mImagesReceived.add(image.getImage());
+ }
+ });
Map<String, Size> suggestedResolutionMap = new HashMap<>();
suggestedResolutionMap.put(ShadowCameraX.DEFAULT_CAMERA_ID, DEFAULT_RESOLUTION);
diff --git a/camera/integration-tests/coretestapp/src/main/java/androidx/camera/integration/core/CameraXActivity.java b/camera/integration-tests/coretestapp/src/main/java/androidx/camera/integration/core/CameraXActivity.java
index 00d3d30..e8f9ecc 100644
--- a/camera/integration-tests/coretestapp/src/main/java/androidx/camera/integration/core/CameraXActivity.java
+++ b/camera/integration-tests/coretestapp/src/main/java/androidx/camera/integration/core/CameraXActivity.java
@@ -24,8 +24,6 @@
import android.graphics.SurfaceTexture;
import android.os.Bundle;
import android.os.Environment;
-import android.os.Handler;
-import android.os.Looper;
import android.os.StrictMode;
import android.os.SystemClock;
import android.util.Log;
@@ -396,7 +394,6 @@
new ImageAnalysisConfig.Builder()
.setLensFacing(mCurrentCameraLensFacing)
.setTargetName("ImageAnalysis")
- .setCallbackHandler(new Handler(Looper.getMainLooper()))
.build();
mImageAnalysis = new ImageAnalysis(config);
@@ -409,6 +406,7 @@
}
mImageAnalysis.setAnalyzer(
+ CameraXExecutors.mainThreadExecutor(),
new ImageAnalysis.Analyzer() {
@Override
public void analyze(ImageProxy image, int rotationDegrees) {
diff --git a/camera/integration-tests/extensionstestapp/src/main/java/androidx/camera/integration/extensions/CameraExtensionsActivity.java b/camera/integration-tests/extensionstestapp/src/main/java/androidx/camera/integration/extensions/CameraExtensionsActivity.java
index aac9f9e..52d9f26 100644
--- a/camera/integration-tests/extensionstestapp/src/main/java/androidx/camera/integration/extensions/CameraExtensionsActivity.java
+++ b/camera/integration-tests/extensionstestapp/src/main/java/androidx/camera/integration/extensions/CameraExtensionsActivity.java
@@ -23,8 +23,6 @@
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
-import android.os.Handler;
-import android.os.HandlerThread;
import android.os.StrictMode;
import android.util.Log;
import android.view.TextureView;
@@ -89,8 +87,6 @@
private ImageCapture mImageCapture;
private ImageCaptureType mCurrentImageCaptureType = ImageCaptureType.IMAGE_CAPTURE_TYPE_HDR;
- private HandlerThread mHandlerThread = new HandlerThread("CameraExtensionsActivityHandler");
-
// Espresso testing variables
@VisibleForTesting
CountingIdlingResource mTakePictureIdlingResource = new CountingIdlingResource("TakePicture");
@@ -249,7 +245,6 @@
builder);
if (hdrImageCaptureExtender.isExtensionAvailable()) {
hdrImageCaptureExtender.enableExtension();
- builder.setCallbackHandler(new Handler(mHandlerThread.getLooper()));
}
break;
case IMAGE_CAPTURE_TYPE_BOKEH:
@@ -394,8 +389,6 @@
new StrictMode.VmPolicy.Builder().detectAll().penaltyLog().build();
StrictMode.setVmPolicy(policy);
- mHandlerThread.start();
-
// Get params from adb extra string
Bundle bundle = getIntent().getExtras();
if (bundle != null) {
@@ -416,12 +409,6 @@
setupPermissions();
}
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mHandlerThread.quitSafely();
- }
-
private void setupCamera() {
try {
// Wait for permissions before proceeding.