Don't call unconfigureWebRTCSession if configureWebRTCSession fails.

Otherwise, the activeCount will become negative.

BUG=webrtc:7471

Review-Url: https://codereview.webrtc.org/2822233002
Cr-Commit-Position: refs/heads/master@{#17816}
This commit is contained in:
jtteh
2017-04-21 13:56:39 -07:00
committed by Commit bot
parent 99cdcb6dea
commit f84c1d6644
5 changed files with 78 additions and 7 deletions

View File

@ -295,6 +295,7 @@ if (rtc_include_tests) {
if (target_cpu != "x64") {
sources += [ "ios/audio_device_unittest_ios.cc" ]
}
deps += [ "//third_party/ocmock" ]
}
if (!build_with_chromium && is_clang) {
# Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).

View File

@ -206,7 +206,7 @@ class AudioDeviceIOS : public AudioDeviceGeneric,
void UpdateAudioUnit(bool can_play_or_record);
// Configures the audio session for WebRTC.
void ConfigureAudioSession();
bool ConfigureAudioSession();
// Unconfigures the audio session.
void UnconfigureAudioSession();

View File

@ -751,19 +751,24 @@ void AudioDeviceIOS::UpdateAudioUnit(bool can_play_or_record) {
}
}
void AudioDeviceIOS::ConfigureAudioSession() {
bool AudioDeviceIOS::ConfigureAudioSession() {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
RTCLog(@"Configuring audio session.");
if (has_configured_session_) {
RTCLogWarning(@"Audio session already configured.");
return;
return false;
}
RTCAudioSession* session = [RTCAudioSession sharedInstance];
[session lockForConfiguration];
[session configureWebRTCSession:nil];
bool success = [session configureWebRTCSession:nil];
[session unlockForConfiguration];
has_configured_session_ = true;
RTCLog(@"Configured audio session.");
if (success) {
has_configured_session_ = true;
RTCLog(@"Configured audio session.");
} else {
RTCLog(@"Failed to configure audio session.");
}
return success;
}
void AudioDeviceIOS::UnconfigureAudioSession() {

View File

@ -688,7 +688,7 @@ NSInteger const kRTCAudioSessionErrorConfiguration = -2;
if (![self setConfiguration:webRTCConfig active:YES error:&error]) {
RTCLogError(@"Failed to set WebRTC audio configuration: %@",
error.localizedDescription);
[self unconfigureWebRTCSession:nil];
// Do not call setActive:NO if setActive:YES failed.
if (outError) {
*outError = error;
}

View File

@ -9,11 +9,13 @@
*/
#import <Foundation/Foundation.h>
#import <OCMock/OCMock.h>
#include "webrtc/test/gtest.h"
#import "webrtc/modules/audio_device/ios/objc/RTCAudioSession.h"
#import "webrtc/modules/audio_device/ios/objc/RTCAudioSession+Private.h"
#import "webrtc/modules/audio_device/ios/objc/RTCAudioSessionConfiguration.h"
@interface RTCAudioSessionTestDelegate : NSObject <RTCAudioSessionDelegate>
@end
@ -185,6 +187,65 @@
EXPECT_EQ(0, audioSession.activationCount);
}
// Hack - fixes OCMVerify link error
// Link error is: Undefined symbols for architecture i386:
// "OCMMakeLocation(objc_object*, char const*, int)", referenced from:
// -[RTCAudioSessionTest testConfigureWebRTCSession] in RTCAudioSessionTest.o
// ld: symbol(s) not found for architecture i386
// REASON: https://github.com/erikdoe/ocmock/issues/238
OCMLocation *OCMMakeLocation(id testCase, const char *fileCString, int line){
return [OCMLocation locationWithTestCase:testCase
file:[NSString stringWithUTF8String:fileCString]
line:line];
}
- (void)testConfigureWebRTCSession {
NSError *error = nil;
void (^setActiveBlock)(NSInvocation *invocation) = ^(NSInvocation *invocation) {
__autoreleasing NSError **retError;
[invocation getArgument:&retError atIndex:4];
*retError = [NSError errorWithDomain:@"AVAudioSession"
code:AVAudioSessionErrorInsufficientPriority
userInfo:nil];
BOOL failure = NO;
[invocation setReturnValue:&failure];
};
id mockAVAudioSession = OCMPartialMock([AVAudioSession sharedInstance]);
OCMStub([[mockAVAudioSession ignoringNonObjectArgs]
setActive:YES withOptions:0 error:((NSError __autoreleasing **)[OCMArg anyPointer])]).
andDo(setActiveBlock);
id mockAudioSession = OCMPartialMock([RTCAudioSession sharedInstance]);
OCMStub([mockAudioSession session]).andReturn(mockAVAudioSession);
RTCAudioSession *audioSession = mockAudioSession;
EXPECT_EQ(0, audioSession.activationCount);
[audioSession lockForConfiguration];
EXPECT_TRUE([audioSession checkLock:nil]);
// configureWebRTCSession is forced to fail in the above mock interface,
// so activationCount should remain 0
OCMExpect([[mockAVAudioSession ignoringNonObjectArgs]
setActive:YES withOptions:0 error:((NSError __autoreleasing **)[OCMArg anyPointer])]).
andDo(setActiveBlock);
OCMExpect([mockAudioSession session]).andReturn(mockAVAudioSession);
EXPECT_FALSE([audioSession configureWebRTCSession:&error]);
EXPECT_EQ(0, audioSession.activationCount);
id session = audioSession.session;
EXPECT_EQ(session, mockAVAudioSession);
EXPECT_EQ(NO, [mockAVAudioSession setActive:YES withOptions:0 error:&error]);
[audioSession unlockForConfiguration];
OCMVerify([mockAudioSession session]);
OCMVerify([[mockAVAudioSession ignoringNonObjectArgs] setActive:YES withOptions:0 error:&error]);
OCMVerify([[mockAVAudioSession ignoringNonObjectArgs] setActive:NO withOptions:0 error:&error]);
[mockAVAudioSession stopMocking];
[mockAudioSession stopMocking];
}
@end
namespace webrtc {
@ -229,5 +290,9 @@ TEST_F(AudioSessionTest, AudioSessionActivation) {
[test testAudioSessionActivation];
}
TEST_F(AudioSessionTest, ConfigureWebRTCSession) {
RTCAudioSessionTest *test = [[RTCAudioSessionTest alloc] init];
[test testConfigureWebRTCSession];
}
} // namespace webrtc