Add support for ignoring errors encountered while configuring preferred attributes of an audio session.

This will allow call audio to function when audio session attributes like `preferredInputNumberOfChannels` cannot be set due to intermittent OS errors.

Bug: webrtc:10602
Change-Id: Ie9f3e58a6ab54a26a9bd795575d16c3a9fe5c65f
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/135440
Commit-Queue: Kári Helgason <kthelgason@webrtc.org>
Reviewed-by: Zeke Chin <tkchin@webrtc.org>
Reviewed-by: Kári Helgason <kthelgason@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27871}
diff --git a/sdk/objc/components/audio/RTCAudioSession+Configuration.mm b/sdk/objc/components/audio/RTCAudioSession+Configuration.mm
index 0ece592..c81ce1b 100644
--- a/sdk/objc/components/audio/RTCAudioSession+Configuration.mm
+++ b/sdk/objc/components/audio/RTCAudioSession+Configuration.mm
@@ -97,7 +97,9 @@
                                 error:&sampleRateError]) {
       RTCLogError(@"Failed to set preferred sample rate: %@",
                   sampleRateError.localizedDescription);
-      error = sampleRateError;
+      if (!self.ignoresPreferredAttributeConfigurationErrors) {
+        error = sampleRateError;
+      }
     } else {
       RTCLog(@"Set preferred sample rate to: %.2f",
              configuration.sampleRate);
@@ -110,7 +112,9 @@
                                       error:&bufferDurationError]) {
       RTCLogError(@"Failed to set preferred IO buffer duration: %@",
                   bufferDurationError.localizedDescription);
-      error = bufferDurationError;
+      if (!self.ignoresPreferredAttributeConfigurationErrors) {
+        error = bufferDurationError;
+      }
     } else {
       RTCLog(@"Set preferred IO buffer duration to: %f",
              configuration.ioBufferDuration);
@@ -139,7 +143,9 @@
                                              error:&inputChannelsError]) {
        RTCLogError(@"Failed to set preferred input number of channels: %@",
                    inputChannelsError.localizedDescription);
-       error = inputChannelsError;
+       if (!self.ignoresPreferredAttributeConfigurationErrors) {
+         error = inputChannelsError;
+       }
       } else {
         RTCLog(@"Set input number of channels to: %ld",
                (long)inputNumberOfChannels);
@@ -152,7 +158,9 @@
                                               error:&outputChannelsError]) {
         RTCLogError(@"Failed to set preferred output number of channels: %@",
                     outputChannelsError.localizedDescription);
-        error = outputChannelsError;
+        if (!self.ignoresPreferredAttributeConfigurationErrors) {
+          error = outputChannelsError;
+        }
       } else {
         RTCLog(@"Set output number of channels to: %ld",
                (long)outputNumberOfChannels);
diff --git a/sdk/objc/components/audio/RTCAudioSession.h b/sdk/objc/components/audio/RTCAudioSession.h
index d43418b..b5bba2f 100644
--- a/sdk/objc/components/audio/RTCAudioSession.h
+++ b/sdk/objc/components/audio/RTCAudioSession.h
@@ -182,6 +182,15 @@
 @property(readonly) NSTimeInterval IOBufferDuration;
 @property(readonly) NSTimeInterval preferredIOBufferDuration;
 
+/**
+ When YES, calls to -setConfiguration:error: and -setConfiguration:active:error: ignore errors in
+ configuring the audio session's "preferred" attributes (e.g. preferredInputNumberOfChannels).
+ Typically, configurations to preferred attributes are optimizations, and ignoring this type of
+ configuration error allows code flow to continue along the happy path when these optimization are
+ not available. The default value of this property is NO.
+ */
+@property(nonatomic) BOOL ignoresPreferredAttributeConfigurationErrors;
+
 /** Default constructor. */
 + (instancetype)sharedInstance;
 - (instancetype)init NS_UNAVAILABLE;
diff --git a/sdk/objc/components/audio/RTCAudioSession.mm b/sdk/objc/components/audio/RTCAudioSession.mm
index 1b2b487..09ffa16 100644
--- a/sdk/objc/components/audio/RTCAudioSession.mm
+++ b/sdk/objc/components/audio/RTCAudioSession.mm
@@ -43,6 +43,8 @@
 
 @synthesize session = _session;
 @synthesize delegates = _delegates;
+@synthesize ignoresPreferredAttributeConfigurationErrors =
+    _ignoresPreferredAttributeConfigurationErrors;
 
 + (instancetype)sharedInstance {
   static dispatch_once_t onceToken;
@@ -180,6 +182,23 @@
   }
 }
 
+- (void)setIgnoresPreferredAttributeConfigurationErrors:
+    (BOOL)ignoresPreferredAttributeConfigurationErrors {
+  @synchronized(self) {
+    if (_ignoresPreferredAttributeConfigurationErrors ==
+        ignoresPreferredAttributeConfigurationErrors) {
+      return;
+    }
+    _ignoresPreferredAttributeConfigurationErrors = ignoresPreferredAttributeConfigurationErrors;
+  }
+}
+
+- (BOOL)ignoresPreferredAttributeConfigurationErrors {
+  @synchronized(self) {
+    return _ignoresPreferredAttributeConfigurationErrors;
+  }
+}
+
 // TODO(tkchin): Check for duplicates.
 - (void)addDelegate:(id<RTCAudioSessionDelegate>)delegate {
   RTCLog(@"Adding delegate: (%p)", delegate);