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

Fix unguarded availability in Camera plugin #2928

Merged
merged 13 commits into from
Aug 13, 2020
Merged

Conversation

dnfield
Copy link
Contributor

@dnfield dnfield commented Aug 12, 2020

The build is failing on this plugin in an unrelated PR currrently due to these issues. This doesn't fail the build because we're specifically ignoring these warnings, so instead I'm enabling the warnings. This does cause crashes for users on older iOS versions, see linked bug.

This does make me wonder if we really should claim to support this plugin on iOS 8.0. Currently, you can't take a picture with the camera plugin on anything lower than iOS 10 - it would cause a runtime crash (now it will just result in an exception that should be recoverable).

Fixes flutter/flutter#20708

@jmagman
Copy link
Member

jmagman commented Aug 12, 2020

This does make me wonder if we really should claim to support this plugin on iOS 8.0. Currently, you can't take a picture with the camera plugin on anything lower than iOS 10 - it would cause a runtime crash (now it will just result in an exception that should be recoverable).

If you changed it to 10.0 then Flutter apps at 8.0 or 9.0 minimums couldn't use the plugin. There would be a CocoaPods error or a build time error. The dependencies need to have a lower than equal requirement.

@dnfield can we get a link to the failure?

@dnfield
Copy link
Contributor Author

dnfield commented Aug 12, 2020

Here's an example: https://cirrus-ci.com/task/5249881340116992

I only noticed the warnings because of an unrelated error that @ditman fixed and I hadn't patched in yet.

@dnfield
Copy link
Contributor Author

dnfield commented Aug 12, 2020

As it is right now, saving a picture to a file on iOS 8.0 or 9.0 would result in a crash. Video functionality would still work. Dropping support for iOS 8.0 and 9.0 might be too severe, but we may want to implement these methods in some way friendly to the version(s) we support if we support them.

@jmagman
Copy link
Member

jmagman commented Aug 12, 2020

flutter/flutter#20708

@jmagman
Copy link
Member

jmagman commented Aug 12, 2020

If you get rid of --no-analyze camera and/or --ignore-warnings camera does it pass?

- ./script/incremental_build.sh podspecs --no-analyze camera --ignore-warnings camera

@jmagman
Copy link
Member

jmagman commented Aug 12, 2020

No, it doesn't pass.
CameraPlugin.m:66:24: 'AVCapturePhotoOutput' is only available on iOS 10.0 or newer
CameraPlugin.m:69:43: 'AVCaptureResolvedPhotoSettings' is only available on iOS 10.0 or newer
CameraPlugin.m:78:7: 'JPEGPhotoDataRepresentationForJPEGSampleBuffer:previewPhotoSampleBuffer:' is only available on iOS 10.0 or newer
CameraPlugin.m:77:19: 'AVCapturePhotoOutput' is only available on iOS 10.0 or newer
CameraPlugin.m:163:52: This block declaration is not a prototype
CameraPlugin.m:170:32: 'AVCapturePhotoOutput' is only available on iOS 10.0 or newer
CameraPlugin.m:257:26: 'AVCapturePhotoOutput' is only available on iOS 10.0 or newer
CameraPlugin.m:854:10: Block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior

@dnfield
Copy link
Contributor Author

dnfield commented Aug 12, 2020

I'll see if I can fix those.

Copy link
Member

@jmagman jmagman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some other warnings:

  • AVCapturePhotoOutput and AVCaptureResolvedPhotoSettings usage (_capturePhotoOutput, -[captureOutput:::]) need the same availability treatment.
  • onFrameAvailable property is missing a void
@property(nonatomic, copy) void (^onFrameAvailable)(void);

@@ -204,7 +204,7 @@ - (void)startVideoRecordingAtPath:(NSString *)path result:(FlutterResult)result;
- (void)stopVideoRecordingWithResult:(FlutterResult)result;
- (void)startImageStreamWithMessenger:(NSObject<FlutterBinaryMessenger> *)messenger;
- (void)stopImageStream;
- (void)captureToFile:(NSString *)filename result:(FlutterResult)result;
- (void)captureToFile:(NSString *)filename result:(FlutterResult)result API_AVAILABLE(ios(10));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All the method declarations can be removed from this interface, it just needs the properties. API_AVAILABLE(ios(10.0)) can go in the implementation:

- (void)captureToFile:(NSString *)path result:(FlutterResult)result API_AVAILABLE(ios(10.0)) {

case AVCaptureDevicePositionUnspecified:
lensFacing = @"external";
break;
if (@available(iOS 10.0, *)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If call.method is availableCameras and @available(iOS 10.0, *) isn't true, should it result(@[]);? Or do we want the FlutterMethodNotImplemented (because I guess it isn't, though I don't know the side effects of that)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think FlutterMethodNotImplemented is most appropriate, since we haven't implemented the method for that platform.

Today, this is a hard crash for the end user. At least this way they can handle it in application code.

@@ -847,7 +836,7 @@ - (void)handleMethodCallAsync:(FlutterMethodCall *)call result:(FlutterResult)re
int64_t textureId = [_registry registerTexture:cam];
_camera = cam;
cam.onFrameAvailable = ^{
[_registry textureFrameAvailable:textureId];
[self.registry textureFrameAvailable:textureId];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a retain cycle?

@jmagman
Copy link
Member

jmagman commented Aug 13, 2020

One more thing to get rid of the warnings:

s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS' => 'armv7 arm64 x86_64' }

Should become:

s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS[sdk=iphonesimulator*]' => 'x86_64' }

Like all the other plugins. Example:

s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS[sdk=iphonesimulator*]' => 'x86_64' }

That will fix flutter/flutter#61927.

Copy link
Member

@jmagman jmagman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thank you!

Comment on lines +819 to +820
} else {
result(FlutterMethodNotImplemented);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think what you had before would have fallen through to FlutterMethodNotImplemented, whatever you prefer though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah but it'd make the other else blocks not run on iOS 10+ :\

@jmagman
Copy link
Member

jmagman commented Aug 13, 2020

Static analyzer error:

CameraPlugin.m:481:5: Incorrect decrement of the reference count of an object that is not owned at this point by the caller

Here:

CFRelease(sampleBuffer);

Screen Shot 2020-08-12 at 5 42 51 PM

It's being released twice if it hits this codepath:

CFRelease(sampleBuffer);

@jmagman
Copy link
Member

jmagman commented Aug 13, 2020

Looks like -[adjustTime::] is making a copy of the CMSampleBufferRef, so the code is actually right. Just need to tell the analyzer that we know what we're doing by either adding "copy" to the method name or a CF_RETURNS_RETAINED.

- (CMSampleBufferRef)adjustTime:(CMSampleBufferRef)sample by:(CMTime)offset CF_RETURNS_RETAINED {

or

- (CMSampleBufferRef)copyBufferAndAdjustTime:(CMSampleBufferRef)sample by:(CMTime)offset {

Copy link
Member

@jmagman jmagman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@dnfield dnfield merged commit 235283b into flutter:master Aug 13, 2020
@dnfield dnfield deleted the fix_camera branch August 13, 2020 06:24
jarrodcolburn pushed a commit to jarrodcolburn/plugins that referenced this pull request Aug 20, 2020
* Fix unguarded availability in Camera plugin
jorgefspereira pushed a commit to jorgefspereira/plugins_flutter that referenced this pull request Oct 10, 2020
* Fix unguarded availability in Camera plugin
FlutterSu pushed a commit to FlutterSu/flutter-plugins that referenced this pull request Nov 20, 2020
* Fix unguarded availability in Camera plugin
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

plugin: camera - crashes on iOS < 10
3 participants