Skip to content

Commit 88a3a56

Browse files
[camera] Convert iOS Obj-C->Dart calls to Pigeon (flutter#6568)
Converts all of the Obj-C -> Dart calls to Pigeon, using the new suffix-based Pigeon API instantiation feature. This required decentralizing some threading code slightly: since method channel calls only involve one method (due to the lack of strong types), a wrapper that automatically did thread bouncing was feasible, but with Pigeon it's not since a wrapper would have to duplicate the entire API surface, and that's more work than just doing the dispatches at the call site. Part of flutter/flutter#117905
1 parent 5d15437 commit 88a3a56

24 files changed

+1133
-609
lines changed

packages/camera/camera_avfoundation/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.9.15+4
2+
3+
* Converts host-to-Dart communcation to Pigeon.
4+
15
## 0.9.15+3
26

37
* Moves `pigeon` to `dev_dependencies`.

packages/camera/camera_avfoundation/example/ios/Runner.xcodeproj/project.pbxproj

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
E071CF7227B3061B006EF3BA /* FLTCamPhotoCaptureTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E071CF7127B3061B006EF3BA /* FLTCamPhotoCaptureTests.m */; };
3030
E071CF7427B31DE4006EF3BA /* FLTCamSampleBufferTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E071CF7327B31DE4006EF3BA /* FLTCamSampleBufferTests.m */; };
3131
E0B0D2BB27DFF2AF00E71E4B /* CameraPermissionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E0B0D2BA27DFF2AF00E71E4B /* CameraPermissionTests.m */; };
32-
E0C6E2002770F01A00EA6AA3 /* ThreadSafeMethodChannelTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E0C6E1FD2770F01A00EA6AA3 /* ThreadSafeMethodChannelTests.m */; };
3332
E0C6E2012770F01A00EA6AA3 /* ThreadSafeTextureRegistryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E0C6E1FE2770F01A00EA6AA3 /* ThreadSafeTextureRegistryTests.m */; };
3433
E0C6E2022770F01A00EA6AA3 /* ThreadSafeEventChannelTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E0C6E1FF2770F01A00EA6AA3 /* ThreadSafeEventChannelTests.m */; };
3534
E0CDBAC227CD9729002561D9 /* CameraTestUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = E0CDBAC127CD9729002561D9 /* CameraTestUtils.m */; };
@@ -96,7 +95,6 @@
9695
E071CF7127B3061B006EF3BA /* FLTCamPhotoCaptureTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FLTCamPhotoCaptureTests.m; sourceTree = "<group>"; };
9796
E071CF7327B31DE4006EF3BA /* FLTCamSampleBufferTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLTCamSampleBufferTests.m; sourceTree = "<group>"; };
9897
E0B0D2BA27DFF2AF00E71E4B /* CameraPermissionTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CameraPermissionTests.m; sourceTree = "<group>"; };
99-
E0C6E1FD2770F01A00EA6AA3 /* ThreadSafeMethodChannelTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ThreadSafeMethodChannelTests.m; sourceTree = "<group>"; };
10098
E0C6E1FE2770F01A00EA6AA3 /* ThreadSafeTextureRegistryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ThreadSafeTextureRegistryTests.m; sourceTree = "<group>"; };
10199
E0C6E1FF2770F01A00EA6AA3 /* ThreadSafeEventChannelTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ThreadSafeEventChannelTests.m; sourceTree = "<group>"; };
102100
E0CDBAC027CD9729002561D9 /* CameraTestUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CameraTestUtils.h; sourceTree = "<group>"; };
@@ -134,7 +132,6 @@
134132
03BB766C2665316900CE5A93 /* Info.plist */,
135133
033B94BD269C40A200B4DF97 /* CameraMethodChannelTests.m */,
136134
E0C6E1FF2770F01A00EA6AA3 /* ThreadSafeEventChannelTests.m */,
137-
E0C6E1FD2770F01A00EA6AA3 /* ThreadSafeMethodChannelTests.m */,
138135
E0C6E1FE2770F01A00EA6AA3 /* ThreadSafeTextureRegistryTests.m */,
139136
E04F108527A87CA600573D0C /* FLTSavePhotoDelegateTests.m */,
140137
E071CF7127B3061B006EF3BA /* FLTCamPhotoCaptureTests.m */,
@@ -454,7 +451,6 @@
454451
E0C6E2022770F01A00EA6AA3 /* ThreadSafeEventChannelTests.m in Sources */,
455452
E0C6E2012770F01A00EA6AA3 /* ThreadSafeTextureRegistryTests.m in Sources */,
456453
E0B0D2BB27DFF2AF00E71E4B /* CameraPermissionTests.m in Sources */,
457-
E0C6E2002770F01A00EA6AA3 /* ThreadSafeMethodChannelTests.m in Sources */,
458454
E01EE4A82799F3A5008C1950 /* QueueUtilsTests.m in Sources */,
459455
);
460456
runOnlyForDeploymentPostprocessing = 0;

packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraFocusTests.m

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ - (void)testAutoFocusWithContinuousModeSupported_ShouldSetContinuousAutoFocus {
3737
[[_mockDevice reject] setFocusMode:AVCaptureFocusModeAutoFocus];
3838

3939
// Run test
40-
[_camera applyFocusMode:FLTFocusModeAuto onDevice:_mockDevice];
40+
[_camera applyFocusMode:FCPPlatformFocusModeAuto onDevice:_mockDevice];
4141

4242
// Expect setFocusMode:AVCaptureFocusModeContinuousAutoFocus
4343
OCMVerify([_mockDevice setFocusMode:AVCaptureFocusModeContinuousAutoFocus]);
@@ -54,7 +54,7 @@ - (void)testAutoFocusWithContinuousModeNotSupported_ShouldSetAutoFocus {
5454
[[_mockDevice reject] setFocusMode:AVCaptureFocusModeContinuousAutoFocus];
5555

5656
// Run test
57-
[_camera applyFocusMode:FLTFocusModeAuto onDevice:_mockDevice];
57+
[_camera applyFocusMode:FCPPlatformFocusModeAuto onDevice:_mockDevice];
5858

5959
// Expect setFocusMode:AVCaptureFocusModeAutoFocus
6060
OCMVerify([_mockDevice setFocusMode:AVCaptureFocusModeAutoFocus]);
@@ -72,7 +72,7 @@ - (void)testAutoFocusWithNoModeSupported_ShouldSetNothing {
7272
[[_mockDevice reject] setFocusMode:AVCaptureFocusModeAutoFocus];
7373

7474
// Run test
75-
[_camera applyFocusMode:FLTFocusModeAuto onDevice:_mockDevice];
75+
[_camera applyFocusMode:FCPPlatformFocusModeAuto onDevice:_mockDevice];
7676
}
7777

7878
- (void)testLockedFocusWithModeSupported_ShouldSetModeAutoFocus {
@@ -85,7 +85,7 @@ - (void)testLockedFocusWithModeSupported_ShouldSetModeAutoFocus {
8585
[[_mockDevice reject] setFocusMode:AVCaptureFocusModeContinuousAutoFocus];
8686

8787
// Run test
88-
[_camera applyFocusMode:FLTFocusModeLocked onDevice:_mockDevice];
88+
[_camera applyFocusMode:FCPPlatformFocusModeLocked onDevice:_mockDevice];
8989

9090
// Expect setFocusMode:AVCaptureFocusModeAutoFocus
9191
OCMVerify([_mockDevice setFocusMode:AVCaptureFocusModeAutoFocus]);
@@ -102,7 +102,7 @@ - (void)testLockedFocusWithModeNotSupported_ShouldSetNothing {
102102
[[_mockDevice reject] setFocusMode:AVCaptureFocusModeAutoFocus];
103103

104104
// Run test
105-
[_camera applyFocusMode:FLTFocusModeLocked onDevice:_mockDevice];
105+
[_camera applyFocusMode:FCPPlatformFocusModeLocked onDevice:_mockDevice];
106106
}
107107

108108
- (void)testSetFocusPointWithResult_SetsFocusPointOfInterest {

packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraOrientationTests.m

Lines changed: 81 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -9,44 +9,87 @@
99

1010
#import <OCMock/OCMock.h>
1111

12+
@interface StubGlobalEventApi : FCPCameraGlobalEventApi
13+
@property(nonatomic) BOOL called;
14+
@property(nonatomic) FCPPlatformDeviceOrientation lastOrientation;
15+
@end
16+
17+
@implementation StubGlobalEventApi
18+
- (void)deviceOrientationChangedOrientation:(FCPPlatformDeviceOrientation)orientation
19+
completion:(void (^)(FlutterError *_Nullable))completion {
20+
self.called = YES;
21+
self.lastOrientation = orientation;
22+
completion(nil);
23+
}
24+
25+
- (FlutterBinaryMessengerConnection)setMessageHandlerOnChannel:(nonnull NSString *)channel
26+
binaryMessageHandler:
27+
(nullable FlutterBinaryMessageHandler)handler {
28+
return 0;
29+
}
30+
31+
@end
32+
33+
#pragma mark -
34+
1235
@interface CameraOrientationTests : XCTestCase
1336
@end
1437

1538
@implementation CameraOrientationTests
1639

40+
// Ensure that the given queue and then the main queue have both cycled, to wait for any pending
41+
// async events that may have been bounced between them.
42+
- (void)waitForRoundTripWithQueue:(dispatch_queue_t)queue {
43+
XCTestExpectation *expectation = [[XCTestExpectation alloc] initWithDescription:@"Queue flush"];
44+
dispatch_async(queue, ^{
45+
dispatch_async(dispatch_get_main_queue(), ^{
46+
[expectation fulfill];
47+
});
48+
});
49+
[self waitForExpectations:@[ expectation ]];
50+
}
51+
52+
- (void)sendOrientation:(UIDeviceOrientation)orientation toCamera:(CameraPlugin *)cameraPlugin {
53+
[cameraPlugin orientationChanged:[self createMockNotificationForOrientation:orientation]];
54+
[self waitForRoundTripWithQueue:cameraPlugin.captureSessionQueue];
55+
}
56+
1757
- (void)testOrientationNotifications {
18-
id mockMessenger = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
19-
CameraPlugin *cameraPlugin = [[CameraPlugin alloc] initWithRegistry:nil messenger:mockMessenger];
20-
21-
[mockMessenger setExpectationOrderMatters:YES];
22-
23-
[self rotate:UIDeviceOrientationPortraitUpsideDown
24-
expectedChannelOrientation:@"portraitDown"
25-
cameraPlugin:cameraPlugin
26-
messenger:mockMessenger];
27-
[self rotate:UIDeviceOrientationPortrait
28-
expectedChannelOrientation:@"portraitUp"
29-
cameraPlugin:cameraPlugin
30-
messenger:mockMessenger];
31-
[self rotate:UIDeviceOrientationLandscapeLeft
32-
expectedChannelOrientation:@"landscapeLeft"
33-
cameraPlugin:cameraPlugin
34-
messenger:mockMessenger];
35-
[self rotate:UIDeviceOrientationLandscapeRight
36-
expectedChannelOrientation:@"landscapeRight"
37-
cameraPlugin:cameraPlugin
38-
messenger:mockMessenger];
39-
40-
OCMReject([mockMessenger sendOnChannel:[OCMArg any] message:[OCMArg any]]);
41-
42-
// No notification when flat.
43-
[cameraPlugin
44-
orientationChanged:[self createMockNotificationForOrientation:UIDeviceOrientationFaceUp]];
45-
// No notification when facedown.
46-
[cameraPlugin
47-
orientationChanged:[self createMockNotificationForOrientation:UIDeviceOrientationFaceDown]];
48-
49-
OCMVerifyAll(mockMessenger);
58+
StubGlobalEventApi *eventAPI = [[StubGlobalEventApi alloc] init];
59+
CameraPlugin *cameraPlugin = [[CameraPlugin alloc] initWithRegistry:nil
60+
messenger:nil
61+
globalAPI:eventAPI];
62+
63+
[self sendOrientation:UIDeviceOrientationPortraitUpsideDown toCamera:cameraPlugin];
64+
XCTAssertEqual(eventAPI.lastOrientation, FCPPlatformDeviceOrientationPortraitDown);
65+
[self sendOrientation:UIDeviceOrientationPortrait toCamera:cameraPlugin];
66+
XCTAssertEqual(eventAPI.lastOrientation, FCPPlatformDeviceOrientationPortraitUp);
67+
[self sendOrientation:UIDeviceOrientationLandscapeLeft toCamera:cameraPlugin];
68+
XCTAssertEqual(eventAPI.lastOrientation, FCPPlatformDeviceOrientationLandscapeLeft);
69+
[self sendOrientation:UIDeviceOrientationLandscapeRight toCamera:cameraPlugin];
70+
XCTAssertEqual(eventAPI.lastOrientation, FCPPlatformDeviceOrientationLandscapeRight);
71+
}
72+
73+
- (void)testOrientationNotificationsNotCalledForFaceUp {
74+
StubGlobalEventApi *eventAPI = [[StubGlobalEventApi alloc] init];
75+
CameraPlugin *cameraPlugin = [[CameraPlugin alloc] initWithRegistry:nil
76+
messenger:nil
77+
globalAPI:eventAPI];
78+
79+
[self sendOrientation:UIDeviceOrientationFaceUp toCamera:cameraPlugin];
80+
81+
XCTAssertFalse(eventAPI.called);
82+
}
83+
84+
- (void)testOrientationNotificationsNotCalledForFaceDown {
85+
StubGlobalEventApi *eventAPI = [[StubGlobalEventApi alloc] init];
86+
CameraPlugin *cameraPlugin = [[CameraPlugin alloc] initWithRegistry:nil
87+
messenger:nil
88+
globalAPI:eventAPI];
89+
90+
[self sendOrientation:UIDeviceOrientationFaceDown toCamera:cameraPlugin];
91+
92+
XCTAssertFalse(eventAPI.called);
5093
}
5194

5295
- (void)testOrientationUpdateMustBeOnCaptureSessionQueue {
@@ -71,40 +114,20 @@ - (void)testOrientationUpdateMustBeOnCaptureSessionQueue {
71114
[self waitForExpectationsWithTimeout:1 handler:nil];
72115
}
73116

74-
- (void)rotate:(UIDeviceOrientation)deviceOrientation
75-
expectedChannelOrientation:(NSString *)channelOrientation
76-
cameraPlugin:(CameraPlugin *)cameraPlugin
77-
messenger:(NSObject<FlutterBinaryMessenger> *)messenger {
78-
XCTestExpectation *orientationExpectation = [self expectationWithDescription:channelOrientation];
79-
80-
OCMExpect([messenger
81-
sendOnChannel:[OCMArg any]
82-
message:[OCMArg checkWithBlock:^BOOL(NSData *data) {
83-
NSObject<FlutterMethodCodec> *codec = [FlutterStandardMethodCodec sharedInstance];
84-
FlutterMethodCall *methodCall = [codec decodeMethodCall:data];
85-
[orientationExpectation fulfill];
86-
return
87-
[methodCall.method isEqualToString:@"orientation_changed"] &&
88-
[methodCall.arguments isEqualToDictionary:@{@"orientation" : channelOrientation}];
89-
}]]);
90-
91-
[cameraPlugin orientationChanged:[self createMockNotificationForOrientation:deviceOrientation]];
92-
[self waitForExpectationsWithTimeout:30.0 handler:nil];
93-
}
94-
95117
- (void)testOrientationChanged_noRetainCycle {
96118
dispatch_queue_t captureSessionQueue = dispatch_queue_create("capture_session_queue", NULL);
97119
FLTCam *mockCam = OCMClassMock([FLTCam class]);
98-
FLTThreadSafeMethodChannel *mockChannel = OCMClassMock([FLTThreadSafeMethodChannel class]);
120+
StubGlobalEventApi *stubAPI = [[StubGlobalEventApi alloc] init];
99121

100122
__weak CameraPlugin *weakCamera;
101123

102124
@autoreleasepool {
103-
CameraPlugin *camera = [[CameraPlugin alloc] initWithRegistry:nil messenger:nil];
125+
CameraPlugin *camera = [[CameraPlugin alloc] initWithRegistry:nil
126+
messenger:nil
127+
globalAPI:stubAPI];
104128
weakCamera = camera;
105129
camera.captureSessionQueue = captureSessionQueue;
106130
camera.camera = mockCam;
107-
camera.deviceEventMethodChannel = mockChannel;
108131

109132
[camera orientationChanged:
110133
[self createMockNotificationForOrientation:UIDeviceOrientationLandscapeLeft]];
@@ -118,11 +141,11 @@ - (void)testOrientationChanged_noRetainCycle {
118141
[self expectationWithDescription:@"Dispatched to capture session queue"];
119142
dispatch_async(captureSessionQueue, ^{
120143
OCMVerify(never(), [mockCam setDeviceOrientation:UIDeviceOrientationLandscapeLeft]);
121-
OCMVerify(never(), [mockChannel invokeMethod:@"orientation_changed" arguments:OCMOCK_ANY]);
144+
XCTAssertFalse(stubAPI.called);
122145
[expectation fulfill];
123146
});
124147

125-
[self waitForExpectationsWithTimeout:1 handler:nil];
148+
[self waitForExpectationsWithTimeout:30 handler:nil];
126149
}
127150

128151
- (NSNotification *)createMockNotificationForOrientation:(UIDeviceOrientation)deviceOrientation {

packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPropertiesTests.m

Lines changed: 17 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5+
@import camera_avfoundation;
56
@import camera_avfoundation.Test;
67
@import AVFoundation;
78
@import XCTest;
@@ -31,30 +32,16 @@ - (void)testFLTGetAVCaptureFlashModeForFLTFlashMode {
3132

3233
#pragma mark - exposure mode tests
3334

34-
- (void)testFLTGetStringForFLTExposureMode {
35-
XCTAssertEqualObjects(@"auto", FLTGetStringForFLTExposureMode(FLTExposureModeAuto));
36-
XCTAssertEqualObjects(@"locked", FLTGetStringForFLTExposureMode(FLTExposureModeLocked));
37-
XCTAssertNil(FLTGetStringForFLTExposureMode(-1));
38-
}
39-
40-
- (void)testFLTGetFLTExposureModeForString {
41-
XCTAssertEqual(FLTExposureModeAuto, FLTGetFLTExposureModeForString(@"auto"));
42-
XCTAssertEqual(FLTExposureModeLocked, FLTGetFLTExposureModeForString(@"locked"));
43-
XCTAssertEqual(FLTExposureModeInvalid, FLTGetFLTExposureModeForString(@"unknown"));
35+
- (void)testFCPGetExposureModeForString {
36+
XCTAssertEqual(FCPPlatformExposureModeAuto, FCPGetExposureModeForString(@"auto"));
37+
XCTAssertEqual(FCPPlatformExposureModeLocked, FCPGetExposureModeForString(@"locked"));
4438
}
4539

4640
#pragma mark - focus mode tests
4741

48-
- (void)testFLTGetStringForFLTFocusMode {
49-
XCTAssertEqualObjects(@"auto", FLTGetStringForFLTFocusMode(FLTFocusModeAuto));
50-
XCTAssertEqualObjects(@"locked", FLTGetStringForFLTFocusMode(FLTFocusModeLocked));
51-
XCTAssertNil(FLTGetStringForFLTFocusMode(-1));
52-
}
53-
5442
- (void)testFLTGetFLTFocusModeForString {
55-
XCTAssertEqual(FLTFocusModeAuto, FLTGetFLTFocusModeForString(@"auto"));
56-
XCTAssertEqual(FLTFocusModeLocked, FLTGetFLTFocusModeForString(@"locked"));
57-
XCTAssertEqual(FLTFocusModeInvalid, FLTGetFLTFocusModeForString(@"unknown"));
43+
XCTAssertEqual(FCPPlatformFocusModeAuto, FCPGetFocusModeForString(@"auto"));
44+
XCTAssertEqual(FCPPlatformFocusModeLocked, FCPGetFocusModeForString(@"locked"));
5845
}
5946

6047
#pragma mark - resolution preset tests
@@ -93,15 +80,17 @@ - (void)testFLTGetUIDeviceOrientationForString {
9380
}
9481

9582
- (void)testFLTGetStringForUIDeviceOrientation {
96-
XCTAssertEqualObjects(@"portraitDown",
97-
FLTGetStringForUIDeviceOrientation(UIDeviceOrientationPortraitUpsideDown));
98-
XCTAssertEqualObjects(@"landscapeLeft",
99-
FLTGetStringForUIDeviceOrientation(UIDeviceOrientationLandscapeLeft));
100-
XCTAssertEqualObjects(@"landscapeRight",
101-
FLTGetStringForUIDeviceOrientation(UIDeviceOrientationLandscapeRight));
102-
XCTAssertEqualObjects(@"portraitUp",
103-
FLTGetStringForUIDeviceOrientation(UIDeviceOrientationPortrait));
104-
XCTAssertEqualObjects(@"portraitUp", FLTGetStringForUIDeviceOrientation(-1));
83+
XCTAssertEqual(
84+
FCPPlatformDeviceOrientationPortraitDown,
85+
FCPGetPigeonDeviceOrientationForOrientation(UIDeviceOrientationPortraitUpsideDown));
86+
XCTAssertEqual(FCPPlatformDeviceOrientationLandscapeLeft,
87+
FCPGetPigeonDeviceOrientationForOrientation(UIDeviceOrientationLandscapeLeft));
88+
XCTAssertEqual(FCPPlatformDeviceOrientationLandscapeRight,
89+
FCPGetPigeonDeviceOrientationForOrientation(UIDeviceOrientationLandscapeRight));
90+
XCTAssertEqual(FCPPlatformDeviceOrientationPortraitUp,
91+
FCPGetPigeonDeviceOrientationForOrientation(UIDeviceOrientationPortrait));
92+
XCTAssertEqual(FCPPlatformDeviceOrientationPortraitUp,
93+
FCPGetPigeonDeviceOrientationForOrientation(-1));
10594
}
10695

10796
#pragma mark - file format tests

packages/camera/camera_avfoundation/example/ios/RunnerTests/ThreadSafeMethodChannelTests.m

Lines changed: 0 additions & 55 deletions
This file was deleted.

0 commit comments

Comments
 (0)