-
Notifications
You must be signed in to change notification settings - Fork 3.3k
[camerax] Wrap Android classes/methods required to set the exposure mode #5966
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
25 commits
Select commit
Hold shift + click to select a range
e71fefc
Dart side
camsim99 916a0ae
Java side
camsim99 2267138
Commit generated tests for fixing
camsim99 5de43ae
Update packages/camera/camera_android_camerax/lib/src/camera2_camera_…
camsim99 26500e6
Run build_runner
camsim99 f5c0647
Dart tests
camsim99 5bf2a13
Change dart side to use map + refactor dart tests
camsim99 1ac6a56
Change java side to use maps
camsim99 ac0af9c
Format + add 1/2 java tests
camsim99 96c3624
Add 2/2 java tests
camsim99 29009a2
Merge remote-tracking branch 'upstream/main' into camx_cam2
camsim99 e7cb2c3
fix analyze
camsim99 cef639b
Fix android lint and bump version
camsim99 0ad3b16
Self review
camsim99 d35b58f
Add comment to pigeon
camsim99 6e71a37
Merge remote-tracking branch 'upstream/main' into camx_cam2
camsim99 b4743cc
Modify generated proxy comments
camsim99 05d41f4
Update packages/camera/camera_android_camerax/android/src/main/java/i…
camsim99 6deea90
Update packages/camera/camera_android_camerax/lib/src/camera2_camera_…
camsim99 0f140c4
Update packages/camera/camera_android_camerax/lib/src/camera2_camera_…
camsim99 35db695
Update packages/camera/camera_android_camerax/lib/src/capture_request…
camsim99 a3e9fb4
Update packages/camera/camera_android_camerax/pigeons/camerax_library…
camsim99 46076be
Merge remote-tracking branch 'refs/remotes/origin/camx_cam2' into cam…
camsim99 84280c7
Finish addressing review
camsim99 7483bde
Merge remote-tracking branch 'upstream/main' into camx_cam2
camsim99 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
140 changes: 140 additions & 0 deletions
140
...rax/android/src/main/java/io/flutter/plugins/camerax/Camera2CameraControlHostApiImpl.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
// Copyright 2013 The Flutter Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
package io.flutter.plugins.camerax; | ||
|
||
import android.content.Context; | ||
import androidx.annotation.NonNull; | ||
import androidx.annotation.OptIn; | ||
import androidx.annotation.VisibleForTesting; | ||
import androidx.camera.camera2.interop.Camera2CameraControl; | ||
import androidx.camera.camera2.interop.CaptureRequestOptions; | ||
import androidx.camera.core.CameraControl; | ||
import androidx.core.content.ContextCompat; | ||
import com.google.common.util.concurrent.FutureCallback; | ||
import com.google.common.util.concurrent.Futures; | ||
import com.google.common.util.concurrent.ListenableFuture; | ||
import io.flutter.plugins.camerax.GeneratedCameraXLibrary.Camera2CameraControlHostApi; | ||
import java.util.Objects; | ||
|
||
/** | ||
* Host API implementation for {@link Camera2CameraControl}. | ||
* | ||
* <p>This class may handle instantiating and adding native object instances that are attached to a | ||
* Dart instance or handle method calls on the associated native class or an instance of the class. | ||
*/ | ||
public class Camera2CameraControlHostApiImpl implements Camera2CameraControlHostApi { | ||
private final InstanceManager instanceManager; | ||
private final Camera2CameraControlProxy proxy; | ||
|
||
/** Proxy for constructor and methods of {@link Camera2CameraControl}. */ | ||
@VisibleForTesting | ||
public static class Camera2CameraControlProxy { | ||
Context context; | ||
|
||
/** | ||
* Creates an instance of {@link Camera2CameraControl} derived from specified {@link | ||
* CameraControl} instance. | ||
*/ | ||
@OptIn(markerClass = androidx.camera.camera2.interop.ExperimentalCamera2Interop.class) | ||
public @NonNull Camera2CameraControl create(@NonNull CameraControl cameraControl) { | ||
return Camera2CameraControl.from(cameraControl); | ||
} | ||
|
||
/** | ||
* Adds a {@link CaptureRequestOptions} to update the capture session with the options it | ||
* contains. | ||
*/ | ||
@OptIn(markerClass = androidx.camera.camera2.interop.ExperimentalCamera2Interop.class) | ||
public void addCaptureRequestOptions( | ||
@NonNull Camera2CameraControl camera2CameraControl, | ||
@NonNull CaptureRequestOptions bundle, | ||
@NonNull GeneratedCameraXLibrary.Result<Void> result) { | ||
if (context == null) { | ||
throw new IllegalStateException("Context must be set to add capture request options."); | ||
} | ||
|
||
ListenableFuture<Void> addCaptureRequestOptionsFuture = | ||
camera2CameraControl.addCaptureRequestOptions(bundle); | ||
|
||
Futures.addCallback( | ||
addCaptureRequestOptionsFuture, | ||
new FutureCallback<Void>() { | ||
public void onSuccess(Void voidResult) { | ||
result.success(null); | ||
} | ||
|
||
public void onFailure(Throwable t) { | ||
result.error(t); | ||
} | ||
}, | ||
ContextCompat.getMainExecutor(context)); | ||
} | ||
} | ||
|
||
/** | ||
* Constructs a {@link Camera2CameraControlHostApiImpl}. | ||
* | ||
* @param instanceManager maintains instances stored to communicate with attached Dart objects | ||
* @param context {@link Context} used to retrieve {@code Executor} | ||
*/ | ||
public Camera2CameraControlHostApiImpl( | ||
@NonNull InstanceManager instanceManager, @NonNull Context context) { | ||
this(instanceManager, new Camera2CameraControlProxy(), context); | ||
} | ||
|
||
/** | ||
* Constructs a {@link Camera2CameraControlHostApiImpl}. | ||
* | ||
* @param instanceManager maintains instances stored to communicate with attached Dart objects | ||
* @param proxy proxy for constructor and methods of {@link Camera2CameraControl} | ||
* @param context {@link Context} used to retrieve {@code Executor} | ||
*/ | ||
@VisibleForTesting | ||
Camera2CameraControlHostApiImpl( | ||
@NonNull InstanceManager instanceManager, | ||
@NonNull Camera2CameraControlProxy proxy, | ||
@NonNull Context context) { | ||
this.instanceManager = instanceManager; | ||
this.proxy = proxy; | ||
proxy.context = context; | ||
} | ||
|
||
/** | ||
* Sets the context that the {@code Camera2CameraControl} will use to listen for the result of | ||
* setting capture request options. | ||
* | ||
* <p>If using the camera plugin in an add-to-app context, ensure that this is called anytime that | ||
* the context changes. | ||
*/ | ||
public void setContext(@NonNull Context context) { | ||
this.proxy.context = context; | ||
} | ||
|
||
@Override | ||
public void create(@NonNull Long identifier, @NonNull Long cameraControlIdentifier) { | ||
instanceManager.addDartCreatedInstance( | ||
proxy.create(Objects.requireNonNull(instanceManager.getInstance(cameraControlIdentifier))), | ||
identifier); | ||
} | ||
|
||
@Override | ||
public void addCaptureRequestOptions( | ||
@NonNull Long identifier, | ||
@NonNull Long captureRequestOptionsIdentifier, | ||
@NonNull GeneratedCameraXLibrary.Result<Void> result) { | ||
proxy.addCaptureRequestOptions( | ||
getCamera2CameraControlInstance(identifier), | ||
Objects.requireNonNull(instanceManager.getInstance(captureRequestOptionsIdentifier)), | ||
result); | ||
} | ||
|
||
/** | ||
* Retrieves the {@link Camera2CameraControl} instance associated with the specified {@code | ||
* identifier}. | ||
*/ | ||
private Camera2CameraControl getCamera2CameraControlInstance(@NonNull Long identifier) { | ||
return Objects.requireNonNull(instanceManager.getInstance(identifier)); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
118 changes: 118 additions & 0 deletions
118
...ax/android/src/main/java/io/flutter/plugins/camerax/CaptureRequestOptionsHostApiImpl.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
// Copyright 2013 The Flutter Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
package io.flutter.plugins.camerax; | ||
|
||
import android.hardware.camera2.CaptureRequest; | ||
import androidx.annotation.NonNull; | ||
import androidx.annotation.OptIn; | ||
import androidx.annotation.VisibleForTesting; | ||
import androidx.camera.camera2.interop.CaptureRequestOptions; | ||
import io.flutter.plugins.camerax.GeneratedCameraXLibrary.CaptureRequestKeySupportedType; | ||
import io.flutter.plugins.camerax.GeneratedCameraXLibrary.CaptureRequestOptionsHostApi; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
/** | ||
* Host API implementation for {@link CaptureRequestOptions}. | ||
* | ||
* <p>This class may handle instantiating and adding native object instances that are attached to a | ||
* Dart instance or handle method calls on the associated native class or an instance of the class. | ||
*/ | ||
public class CaptureRequestOptionsHostApiImpl implements CaptureRequestOptionsHostApi { | ||
private final InstanceManager instanceManager; | ||
private final CaptureRequestOptionsProxy proxy; | ||
|
||
/** Proxy for constructor of {@link CaptureRequestOptions}. */ | ||
@VisibleForTesting | ||
public static class CaptureRequestOptionsProxy { | ||
/** Creates an instance of {@link CaptureRequestOptions}. */ | ||
// Suppression is safe because the type shared between the key and value pairs that | ||
// represent capture request options is checked on the Dart side. | ||
@SuppressWarnings("unchecked") | ||
@OptIn(markerClass = androidx.camera.camera2.interop.ExperimentalCamera2Interop.class) | ||
public @NonNull CaptureRequestOptions create( | ||
@NonNull Map<CaptureRequestKeySupportedType, Object> options) { | ||
CaptureRequestOptions.Builder builder = getCaptureRequestOptionsBuilder(); | ||
|
||
for (Map.Entry<CaptureRequestKeySupportedType, Object> option : options.entrySet()) { | ||
CaptureRequestKeySupportedType optionKeyType = option.getKey(); | ||
CaptureRequest.Key<? extends Object> optionKey = getCaptureRequestKey(optionKeyType); | ||
Object optionValue = option.getValue(); | ||
|
||
if (optionValue == null) { | ||
builder.clearCaptureRequestOption(optionKey); | ||
continue; | ||
} | ||
|
||
switch (optionKeyType) { | ||
case CONTROL_AE_LOCK: | ||
builder.setCaptureRequestOption( | ||
(CaptureRequest.Key<Boolean>) optionKey, (Boolean) optionValue); | ||
break; | ||
default: | ||
throw new IllegalArgumentException( | ||
"The capture request key " | ||
+ optionKeyType.toString() | ||
+ "is not currently supported by the plugin."); | ||
} | ||
} | ||
|
||
return builder.build(); | ||
} | ||
|
||
private CaptureRequest.Key<? extends Object> getCaptureRequestKey( | ||
CaptureRequestKeySupportedType type) { | ||
CaptureRequest.Key<? extends Object> key; | ||
switch (type) { | ||
case CONTROL_AE_LOCK: | ||
key = CaptureRequest.CONTROL_AE_LOCK; | ||
break; | ||
default: | ||
throw new IllegalArgumentException( | ||
"The capture request key is not currently supported by the plugin."); | ||
} | ||
return key; | ||
} | ||
|
||
@VisibleForTesting | ||
@OptIn(markerClass = androidx.camera.camera2.interop.ExperimentalCamera2Interop.class) | ||
public @NonNull CaptureRequestOptions.Builder getCaptureRequestOptionsBuilder() { | ||
return new CaptureRequestOptions.Builder(); | ||
} | ||
} | ||
|
||
/** | ||
* Constructs a {@link CaptureRequestOptionsHostApiImpl}. | ||
* | ||
* @param instanceManager maintains instances stored to communicate with attached Dart objects | ||
*/ | ||
public CaptureRequestOptionsHostApiImpl(@NonNull InstanceManager instanceManager) { | ||
this(instanceManager, new CaptureRequestOptionsProxy()); | ||
} | ||
|
||
/** | ||
* Constructs a {@link CaptureRequestOptionsHostApiImpl}. | ||
* | ||
* @param instanceManager maintains instances stored to communicate with attached Dart objects | ||
* @param proxy proxy for constructor of {@link CaptureRequestOptions} | ||
*/ | ||
@VisibleForTesting | ||
CaptureRequestOptionsHostApiImpl( | ||
@NonNull InstanceManager instanceManager, @NonNull CaptureRequestOptionsProxy proxy) { | ||
this.instanceManager = instanceManager; | ||
this.proxy = proxy; | ||
} | ||
|
||
@Override | ||
public void create(@NonNull Long identifier, @NonNull Map<Long, Object> options) { | ||
Map<CaptureRequestKeySupportedType, Object> decodedOptions = | ||
new HashMap<CaptureRequestKeySupportedType, Object>(); | ||
for (Map.Entry<Long, Object> option : options.entrySet()) { | ||
decodedOptions.put( | ||
CaptureRequestKeySupportedType.values()[option.getKey().intValue()], option.getValue()); | ||
} | ||
instanceManager.addDartCreatedInstance(proxy.create(decodedOptions), identifier); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.