Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

[camerax] Wrap methods necessary for preview implementation #7046

Merged
merged 26 commits into from
Feb 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
496ca83
Add code needed from proof of concept
camsim99 Jan 20, 2023
c9593ba
Add test files, delete unecessary method
camsim99 Jan 27, 2023
8e8779e
Merge remote-tracking branch 'upstream/main' into camx_s3
camsim99 Jan 27, 2023
6e5bc8e
Add tests, remove unecessary code
camsim99 Jan 27, 2023
268d9f5
Fix analyze
camsim99 Jan 30, 2023
2001c33
Update changelog
camsim99 Jan 30, 2023
7552ad9
Merge remote-tracking branch 'upstream/main' into camx_s3
camsim99 Jan 30, 2023
7ff2a94
Cleanup:
camsim99 Jan 30, 2023
dfc3071
Cleanup and add switch
camsim99 Jan 30, 2023
4ba07e2
Finish todo
camsim99 Jan 30, 2023
754939c
Merge remote-tracking branch 'upstream/main' into camx_s3
camsim99 Jan 31, 2023
fb44db3
Add onCameraError
camsim99 Jan 31, 2023
858815d
Fix pigeon file
camsim99 Jan 31, 2023
78edaa2
Add method for releasing flutter texture and cleanup surface logic
camsim99 Jan 31, 2023
3527322
Add test for release method
camsim99 Jan 31, 2023
335372b
Add dart test
camsim99 Jan 31, 2023
4dd9c4c
Update changelog
camsim99 Jan 31, 2023
24b1bdb
Modify flutter api names to avoid stack overflow
camsim99 Jan 31, 2023
e0efef2
Cleanup
camsim99 Jan 31, 2023
e90f45c
Fix tests
camsim99 Feb 1, 2023
73cb5f8
Delete space
camsim99 Feb 1, 2023
abf4e58
Address review 1
camsim99 Feb 1, 2023
659c2e0
Update switch
camsim99 Feb 2, 2023
5f269c7
Add annotations and constants in tests
camsim99 Feb 3, 2023
a6fe15c
Merge remote-tracking branch 'upstream/main' into camx_s3
camsim99 Feb 3, 2023
78e0d0f
Reset verification behavior
camsim99 Feb 6, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/camera/camera_android_camerax/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@
* Adds Camera and UseCase classes, along with methods for binding UseCases to a lifecycle with the ProcessCameraProvider.
* Bump CameraX version to 1.3.0-alpha03 and Kotlin version to 1.8.0.
* Changes instance manager to allow the separate creation of identical objects.
* Adds Preview and Surface classes, along with other methods needed to implement camera preview.
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ void setUp(BinaryMessenger binaryMessenger, Context context, TextureRegistry tex
binaryMessenger, processCameraProviderHostApi);
systemServicesHostApi = new SystemServicesHostApiImpl(binaryMessenger, instanceManager);
GeneratedCameraXLibrary.SystemServicesHostApi.setup(binaryMessenger, systemServicesHostApi);
GeneratedCameraXLibrary.PreviewHostApi.setup(
binaryMessenger, new PreviewHostApiImpl(binaryMessenger, instanceManager, textureRegistry));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,14 @@
package io.flutter.plugins.camerax;

import android.app.Activity;
import android.graphics.SurfaceTexture;
import android.view.Surface;
import androidx.annotation.NonNull;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.Preview;
import io.flutter.plugin.common.BinaryMessenger;

/** Utility class used to create CameraX-related objects primarily for testing purposes. */
public class CameraXProxy {
public CameraSelector.Builder createCameraSelectorBuilder() {
return new CameraSelector.Builder();
Expand All @@ -17,10 +23,29 @@ public CameraPermissionsManager createCameraPermissionsManager() {
}

public DeviceOrientationManager createDeviceOrientationManager(
Activity activity,
Boolean isFrontFacing,
int sensorOrientation,
DeviceOrientationManager.DeviceOrientationChangeCallback callback) {
@NonNull Activity activity,
@NonNull Boolean isFrontFacing,
@NonNull int sensorOrientation,
@NonNull DeviceOrientationManager.DeviceOrientationChangeCallback callback) {
return new DeviceOrientationManager(activity, isFrontFacing, sensorOrientation, callback);
}

public Preview.Builder createPreviewBuilder() {
return new Preview.Builder();
}

public Surface createSurface(@NonNull SurfaceTexture surfaceTexture) {
return new Surface(surfaceTexture);
}

/**
* Creates an instance of the {@code SystemServicesFlutterApiImpl}.
*
* <p>Included in this class to utilize the callback methods it provides, e.g. {@code
* onCameraError(String)}.
*/
public SystemServicesFlutterApiImpl createSystemServicesFlutterApiImpl(
@NonNull BinaryMessenger binaryMessenger) {
return new SystemServicesFlutterApiImpl(binaryMessenger);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,82 @@
@SuppressWarnings({"unused", "unchecked", "CodeBlock2Expr", "RedundantSuppression"})
public class GeneratedCameraXLibrary {

/** Generated class from Pigeon that represents data sent in messages. */
public static class ResolutionInfo {
private @NonNull Long width;

public @NonNull Long getWidth() {
return width;
}

public void setWidth(@NonNull Long setterArg) {
if (setterArg == null) {
throw new IllegalStateException("Nonnull field \"width\" is null.");
}
this.width = setterArg;
}

private @NonNull Long height;

public @NonNull Long getHeight() {
return height;
}

public void setHeight(@NonNull Long setterArg) {
if (setterArg == null) {
throw new IllegalStateException("Nonnull field \"height\" is null.");
}
this.height = setterArg;
}

/** Constructor is private to enforce null safety; use Builder. */
private ResolutionInfo() {}

public static final class Builder {
private @Nullable Long width;

public @NonNull Builder setWidth(@NonNull Long setterArg) {
this.width = setterArg;
return this;
}

private @Nullable Long height;

public @NonNull Builder setHeight(@NonNull Long setterArg) {
this.height = setterArg;
return this;
}

public @NonNull ResolutionInfo build() {
ResolutionInfo pigeonReturn = new ResolutionInfo();
pigeonReturn.setWidth(width);
pigeonReturn.setHeight(height);
return pigeonReturn;
}
}

@NonNull
Map<String, Object> toMap() {
Map<String, Object> toMapResult = new HashMap<>();
toMapResult.put("width", width);
toMapResult.put("height", height);
return toMapResult;
}

static @NonNull ResolutionInfo fromMap(@NonNull Map<String, Object> map) {
ResolutionInfo pigeonResult = new ResolutionInfo();
Object width = map.get("width");
pigeonResult.setWidth(
(width == null) ? null : ((width instanceof Integer) ? (Integer) width : (Long) width));
Object height = map.get("height");
pigeonResult.setHeight(
(height == null)
? null
: ((height instanceof Integer) ? (Integer) height : (Long) height));
return pigeonResult;
}
}

/** Generated class from Pigeon that represents data sent in messages. */
public static class CameraPermissionsErrorData {
private @NonNull String errorCode;
Expand Down Expand Up @@ -843,6 +919,185 @@ public void onDeviceOrientationChanged(@NonNull String orientationArg, Reply<Voi
callback.reply(null);
});
}

public void onCameraError(@NonNull String errorDescriptionArg, Reply<Void> callback) {
BasicMessageChannel<Object> channel =
new BasicMessageChannel<>(
binaryMessenger,
"dev.flutter.pigeon.SystemServicesFlutterApi.onCameraError",
getCodec());
channel.send(
new ArrayList<Object>(Arrays.asList(errorDescriptionArg)),
channelReply -> {
callback.reply(null);
});
}
}

private static class PreviewHostApiCodec extends StandardMessageCodec {
public static final PreviewHostApiCodec INSTANCE = new PreviewHostApiCodec();

private PreviewHostApiCodec() {}

@Override
protected Object readValueOfType(byte type, ByteBuffer buffer) {
switch (type) {
case (byte) 128:
return ResolutionInfo.fromMap((Map<String, Object>) readValue(buffer));

case (byte) 129:
return ResolutionInfo.fromMap((Map<String, Object>) readValue(buffer));

default:
return super.readValueOfType(type, buffer);
}
}

@Override
protected void writeValue(ByteArrayOutputStream stream, Object value) {
if (value instanceof ResolutionInfo) {
stream.write(128);
writeValue(stream, ((ResolutionInfo) value).toMap());
} else if (value instanceof ResolutionInfo) {
stream.write(129);
writeValue(stream, ((ResolutionInfo) value).toMap());
} else {
super.writeValue(stream, value);
}
}
}

/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
public interface PreviewHostApi {
void create(
@NonNull Long identifier,
@Nullable Long rotation,
@Nullable ResolutionInfo targetResolution);

@NonNull
Long setSurfaceProvider(@NonNull Long identifier);

void releaseFlutterSurfaceTexture();

@NonNull
ResolutionInfo getResolutionInfo(@NonNull Long identifier);

/** The codec used by PreviewHostApi. */
static MessageCodec<Object> getCodec() {
return PreviewHostApiCodec.INSTANCE;
}

/** Sets up an instance of `PreviewHostApi` to handle messages through the `binaryMessenger`. */
static void setup(BinaryMessenger binaryMessenger, PreviewHostApi api) {
{
BasicMessageChannel<Object> channel =
new BasicMessageChannel<>(
binaryMessenger, "dev.flutter.pigeon.PreviewHostApi.create", getCodec());
if (api != null) {
channel.setMessageHandler(
(message, reply) -> {
Map<String, Object> wrapped = new HashMap<>();
try {
ArrayList<Object> args = (ArrayList<Object>) message;
Number identifierArg = (Number) args.get(0);
if (identifierArg == null) {
throw new NullPointerException("identifierArg unexpectedly null.");
}
Number rotationArg = (Number) args.get(1);
ResolutionInfo targetResolutionArg = (ResolutionInfo) args.get(2);
api.create(
(identifierArg == null) ? null : identifierArg.longValue(),
(rotationArg == null) ? null : rotationArg.longValue(),
targetResolutionArg);
wrapped.put("result", null);
} catch (Error | RuntimeException exception) {
wrapped.put("error", wrapError(exception));
}
reply.reply(wrapped);
});
} else {
channel.setMessageHandler(null);
}
}
{
BasicMessageChannel<Object> channel =
new BasicMessageChannel<>(
binaryMessenger,
"dev.flutter.pigeon.PreviewHostApi.setSurfaceProvider",
getCodec());
if (api != null) {
channel.setMessageHandler(
(message, reply) -> {
Map<String, Object> wrapped = new HashMap<>();
try {
ArrayList<Object> args = (ArrayList<Object>) message;
Number identifierArg = (Number) args.get(0);
if (identifierArg == null) {
throw new NullPointerException("identifierArg unexpectedly null.");
}
Long output =
api.setSurfaceProvider(
(identifierArg == null) ? null : identifierArg.longValue());
wrapped.put("result", output);
} catch (Error | RuntimeException exception) {
wrapped.put("error", wrapError(exception));
}
reply.reply(wrapped);
});
} else {
channel.setMessageHandler(null);
}
}
{
BasicMessageChannel<Object> channel =
new BasicMessageChannel<>(
binaryMessenger,
"dev.flutter.pigeon.PreviewHostApi.releaseFlutterSurfaceTexture",
getCodec());
if (api != null) {
channel.setMessageHandler(
(message, reply) -> {
Map<String, Object> wrapped = new HashMap<>();
try {
api.releaseFlutterSurfaceTexture();
wrapped.put("result", null);
} catch (Error | RuntimeException exception) {
wrapped.put("error", wrapError(exception));
}
reply.reply(wrapped);
});
} else {
channel.setMessageHandler(null);
}
}
{
BasicMessageChannel<Object> channel =
new BasicMessageChannel<>(
binaryMessenger, "dev.flutter.pigeon.PreviewHostApi.getResolutionInfo", getCodec());
if (api != null) {
channel.setMessageHandler(
(message, reply) -> {
Map<String, Object> wrapped = new HashMap<>();
try {
ArrayList<Object> args = (ArrayList<Object>) message;
Number identifierArg = (Number) args.get(0);
if (identifierArg == null) {
throw new NullPointerException("identifierArg unexpectedly null.");
}
ResolutionInfo output =
api.getResolutionInfo(
(identifierArg == null) ? null : identifierArg.longValue());
wrapped.put("result", output);
} catch (Error | RuntimeException exception) {
wrapped.put("error", wrapError(exception));
}
reply.reply(wrapped);
});
} else {
channel.setMessageHandler(null);
}
}
}
}

private static Map<String, Object> wrapError(Throwable exception) {
Expand Down
Loading