forked from flutter/packages
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[camerax] Prevent using unsupported concurrent camera use cases (flut…
…ter#6608) Adds logic + documentation to prevent the usage of unsupported (by CameraX) concurrent camera use cases. The CameraX plugin should only support the concurrent camera use cases supported by Camerax; see [their documentation](https://developer.android.com/media/camera/camerax/architecture#combine-use-cases) for more information. To avoid the usage of unsupported concurrent use cases, this PR changes the plugin so that it behaves according to the following: * If the preview is paused (via `pausePreview`), concurrent video recording and image streaming (via `startVideoCapturing(cameraId, VideoCaptureOptions(streamCallback:...))`) is supported. * If the preview is not paused * **and** the camera device is at least supported hardware [`LIMITED`](https://developer.android.com/reference/android/hardware/camera2/CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED), then concurrent image capture and video recording is supported. * **and** the camera device is at least supported hardware [`LEVEL_3`](https://developer.android.com/reference/android/hardware/camera2/CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_3), then concurrent video recording and image streaming is supported, but if used, concurrent image capture alongside this is not supported. Also changes `Surface` constants to match Dart style and small documentation nits I noticed. Fixes flutter/flutter#146395, fixes flutter/flutter#144414.
- Loading branch information
Showing
26 changed files
with
2,333 additions
and
545 deletions.
There are no files selected for viewing
This file contains 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 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
27 changes: 27 additions & 0 deletions
27
...rax/android/src/main/java/io/flutter/plugins/camerax/Camera2CameraInfoFlutterApiImpl.java
This file contains 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,27 @@ | ||
// 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 androidx.annotation.NonNull; | ||
import androidx.annotation.Nullable; | ||
import androidx.camera.camera2.interop.Camera2CameraInfo; | ||
import io.flutter.plugin.common.BinaryMessenger; | ||
import io.flutter.plugins.camerax.GeneratedCameraXLibrary.Camera2CameraInfoFlutterApi; | ||
|
||
public class Camera2CameraInfoFlutterApiImpl extends Camera2CameraInfoFlutterApi { | ||
private final InstanceManager instanceManager; | ||
|
||
public Camera2CameraInfoFlutterApiImpl( | ||
@Nullable BinaryMessenger binaryMessenger, @Nullable InstanceManager instanceManager) { | ||
super(binaryMessenger); | ||
this.instanceManager = instanceManager; | ||
} | ||
|
||
void create(@NonNull Camera2CameraInfo camera2CameraInfo, @Nullable Reply<Void> reply) { | ||
if (!instanceManager.containsInstance(camera2CameraInfo)) { | ||
create(instanceManager.addHostCreatedInstance(camera2CameraInfo), reply); | ||
} | ||
} | ||
} |
111 changes: 111 additions & 0 deletions
111
...amerax/android/src/main/java/io/flutter/plugins/camerax/Camera2CameraInfoHostApiImpl.java
This file contains 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,111 @@ | ||
// 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 android.hardware.camera2.CameraCharacteristics; | ||
import androidx.annotation.NonNull; | ||
import androidx.annotation.OptIn; | ||
import androidx.annotation.VisibleForTesting; | ||
import androidx.camera.camera2.interop.Camera2CameraInfo; | ||
import androidx.camera.camera2.interop.ExperimentalCamera2Interop; | ||
import androidx.camera.core.CameraInfo; | ||
import io.flutter.plugin.common.BinaryMessenger; | ||
import io.flutter.plugins.camerax.GeneratedCameraXLibrary.Camera2CameraInfoHostApi; | ||
import java.util.Objects; | ||
|
||
/** | ||
* Host API implementation for {@link Camera2CameraInfo}. | ||
* | ||
* <p>This class handles 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 Camera2CameraInfoHostApiImpl implements Camera2CameraInfoHostApi { | ||
private final BinaryMessenger binaryMessenger; | ||
private final InstanceManager instanceManager; | ||
private final Camera2CameraInfoProxy proxy; | ||
|
||
/** Proxy for methods of {@link Camera2CameraInfo}. */ | ||
@VisibleForTesting | ||
public static class Camera2CameraInfoProxy { | ||
|
||
@NonNull | ||
@OptIn(markerClass = ExperimentalCamera2Interop.class) | ||
public Camera2CameraInfo createFrom(@NonNull CameraInfo cameraInfo) { | ||
return Camera2CameraInfo.from(cameraInfo); | ||
} | ||
|
||
@NonNull | ||
@OptIn(markerClass = ExperimentalCamera2Interop.class) | ||
public Integer getSupportedHardwareLevel(@NonNull Camera2CameraInfo camera2CameraInfo) { | ||
return camera2CameraInfo.getCameraCharacteristic( | ||
CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL); | ||
} | ||
|
||
@NonNull | ||
@OptIn(markerClass = ExperimentalCamera2Interop.class) | ||
public String getCameraId(@NonNull Camera2CameraInfo camera2CameraInfo) { | ||
return camera2CameraInfo.getCameraId(); | ||
} | ||
} | ||
|
||
/** | ||
* Constructs an {@link Camera2CameraInfoHostApiImpl}. | ||
* | ||
* @param binaryMessenger used to communicate with Dart over asynchronous messages | ||
* @param instanceManager maintains instances stored to communicate with attached Dart objects | ||
* @param context {@link Context} used to retrieve {@code Executor} | ||
*/ | ||
public Camera2CameraInfoHostApiImpl( | ||
@NonNull BinaryMessenger binaryMessenger, @NonNull InstanceManager instanceManager) { | ||
this(binaryMessenger, instanceManager, new Camera2CameraInfoProxy()); | ||
} | ||
|
||
/** | ||
* Constructs an {@link Camera2CameraInfoHostApiImpl}. | ||
* | ||
* @param binaryMessenger used to communicate with Dart over asynchronous messages | ||
* @param instanceManager maintains instances stored to communicate with attached Dart objects | ||
* @param proxy proxy for methods of {@link Camera2CameraInfo} | ||
*/ | ||
@VisibleForTesting | ||
Camera2CameraInfoHostApiImpl( | ||
@NonNull BinaryMessenger binaryMessenger, | ||
@NonNull InstanceManager instanceManager, | ||
@NonNull Camera2CameraInfoProxy proxy) { | ||
this.instanceManager = instanceManager; | ||
this.binaryMessenger = binaryMessenger; | ||
this.proxy = proxy; | ||
} | ||
|
||
@Override | ||
@NonNull | ||
public Long createFrom(@NonNull Long cameraInfoIdentifier) { | ||
final CameraInfo cameraInfo = | ||
Objects.requireNonNull(instanceManager.getInstance(cameraInfoIdentifier)); | ||
final Camera2CameraInfo camera2CameraInfo = proxy.createFrom(cameraInfo); | ||
final Camera2CameraInfoFlutterApiImpl flutterApi = | ||
new Camera2CameraInfoFlutterApiImpl(binaryMessenger, instanceManager); | ||
|
||
flutterApi.create(camera2CameraInfo, reply -> {}); | ||
return instanceManager.getIdentifierForStrongReference(camera2CameraInfo); | ||
} | ||
|
||
@Override | ||
@NonNull | ||
public Long getSupportedHardwareLevel(@NonNull Long identifier) { | ||
return Long.valueOf(proxy.getSupportedHardwareLevel(getCamera2CameraInfoInstance(identifier))); | ||
} | ||
|
||
@Override | ||
@NonNull | ||
public String getCameraId(@NonNull Long identifier) { | ||
return proxy.getCameraId(getCamera2CameraInfoInstance(identifier)); | ||
} | ||
|
||
private Camera2CameraInfo getCamera2CameraInfoInstance(@NonNull Long identifier) { | ||
return Objects.requireNonNull(instanceManager.getInstance(identifier)); | ||
} | ||
} |
This file contains 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 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.