Fix lock behavior on RTCAudioSession.

In addition:
- Introduces RTCAudioSessionTest
- iOS/Mac gtests now have an autoreleasepool
- Moves ScopedAutoreleasePool to rtc_base_approved
- Introduces route change button in AppRTCDemo

BUG=webrtc:5649

Review URL: https://codereview.webrtc.org/1782363002

Cr-Commit-Position: refs/heads/master@{#11971}
diff --git a/webrtc/examples/objc/AppRTCDemo/ios/ARDVideoCallView.h b/webrtc/examples/objc/AppRTCDemo/ios/ARDVideoCallView.h
index 378281d..636443a 100644
--- a/webrtc/examples/objc/AppRTCDemo/ios/ARDVideoCallView.h
+++ b/webrtc/examples/objc/AppRTCDemo/ios/ARDVideoCallView.h
@@ -21,6 +21,9 @@
 // Called when the camera switch button is pressed.
 - (void)videoCallViewDidSwitchCamera:(ARDVideoCallView *)view;
 
+// Called when the route change button is pressed.
+- (void)videoCallViewDidChangeRoute:(ARDVideoCallView *)view;
+
 // Called when the hangup button is pressed.
 - (void)videoCallViewDidHangup:(ARDVideoCallView *)view;
 
diff --git a/webrtc/examples/objc/AppRTCDemo/ios/ARDVideoCallView.m b/webrtc/examples/objc/AppRTCDemo/ios/ARDVideoCallView.m
index 4c9c9d2..6e5fc59 100644
--- a/webrtc/examples/objc/AppRTCDemo/ios/ARDVideoCallView.m
+++ b/webrtc/examples/objc/AppRTCDemo/ios/ARDVideoCallView.m
@@ -23,6 +23,7 @@
 @end
 
 @implementation ARDVideoCallView {
+  UIButton *_routeChangeButton;
   UIButton *_cameraSwitchButton;
   UIButton *_hangupButton;
   CGSize _remoteVideoSize;
@@ -48,12 +49,23 @@
     _statsView.hidden = YES;
     [self addSubview:_statsView];
 
+    _routeChangeButton = [UIButton buttonWithType:UIButtonTypeCustom];
+    _routeChangeButton.backgroundColor = [UIColor whiteColor];
+    _routeChangeButton.layer.cornerRadius = kButtonSize / 2;
+    _routeChangeButton.layer.masksToBounds = YES;
+    UIImage *image = [UIImage imageNamed:@"ic_surround_sound_black_24dp.png"];
+    [_routeChangeButton setImage:image forState:UIControlStateNormal];
+    [_routeChangeButton addTarget:self
+                           action:@selector(onRouteChange:)
+                 forControlEvents:UIControlEventTouchUpInside];
+    [self addSubview:_routeChangeButton];
+
     // TODO(tkchin): don't display this if we can't actually do camera switch.
     _cameraSwitchButton = [UIButton buttonWithType:UIButtonTypeCustom];
     _cameraSwitchButton.backgroundColor = [UIColor whiteColor];
     _cameraSwitchButton.layer.cornerRadius = kButtonSize / 2;
     _cameraSwitchButton.layer.masksToBounds = YES;
-    UIImage *image = [UIImage imageNamed:@"ic_switch_video_black_24dp.png"];
+    image = [UIImage imageNamed:@"ic_switch_video_black_24dp.png"];
     [_cameraSwitchButton setImage:image forState:UIControlStateNormal];
     [_cameraSwitchButton addTarget:self
                       action:@selector(onCameraSwitch:)
@@ -140,6 +152,12 @@
       CGRectGetMaxX(cameraSwitchFrame) + kButtonPadding;
   _cameraSwitchButton.frame = cameraSwitchFrame;
 
+  // Place route button to the right of camera button.
+  CGRect routeChangeFrame = _cameraSwitchButton.frame;
+  routeChangeFrame.origin.x =
+      CGRectGetMaxX(routeChangeFrame) + kButtonPadding;
+  _routeChangeButton.frame = routeChangeFrame;
+
   [_statusLabel sizeToFit];
   _statusLabel.center =
       CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds));
@@ -160,6 +178,10 @@
   [_delegate videoCallViewDidSwitchCamera:self];
 }
 
+- (void)onRouteChange:(id)sender {
+  [_delegate videoCallViewDidChangeRoute:self];
+}
+
 - (void)onHangup:(id)sender {
   [_delegate videoCallViewDidHangup:self];
 }
diff --git a/webrtc/examples/objc/AppRTCDemo/ios/ARDVideoCallViewController.m b/webrtc/examples/objc/AppRTCDemo/ios/ARDVideoCallViewController.m
index 51290a0..9bf4c07 100644
--- a/webrtc/examples/objc/AppRTCDemo/ios/ARDVideoCallViewController.m
+++ b/webrtc/examples/objc/AppRTCDemo/ios/ARDVideoCallViewController.m
@@ -10,6 +10,9 @@
 
 #import "ARDVideoCallViewController.h"
 
+#import "webrtc/base/objc/RTCDispatcher.h"
+#import "webrtc/modules/audio_device/ios/objc/RTCAudioSession.h"
+
 #import "RTCAVFoundationVideoSource.h"
 #import "RTCLogging.h"
 
@@ -27,6 +30,7 @@
   ARDAppClient *_client;
   RTCVideoTrack *_remoteVideoTrack;
   RTCVideoTrack *_localVideoTrack;
+  AVAudioSessionPortOverride _portOverride;
 }
 
 @synthesize videoCallView = _videoCallView;
@@ -117,6 +121,26 @@
   [self switchCamera];
 }
 
+- (void)videoCallViewDidChangeRoute:(ARDVideoCallView *)view {
+  AVAudioSessionPortOverride override = AVAudioSessionPortOverrideNone;
+  if (_portOverride == AVAudioSessionPortOverrideNone) {
+    override = AVAudioSessionPortOverrideSpeaker;
+  }
+  [RTCDispatcher dispatchAsyncOnType:RTCDispatcherTypeAudioSession
+                               block:^{
+    RTCAudioSession *session = [RTCAudioSession sharedInstance];
+    [session lockForConfiguration];
+    NSError *error = nil;
+    if ([session overrideOutputAudioPort:override error:&error]) {
+      _portOverride = override;
+    } else {
+      RTCLogError(@"Error overriding output port: %@",
+                  error.localizedDescription);
+    }
+    [session unlockForConfiguration];
+  }];
+}
+
 - (void)videoCallViewDidEnableStats:(ARDVideoCallView *)view {
   _client.shouldGetStats = YES;
   _videoCallView.statsView.hidden = NO;
diff --git a/webrtc/examples/objc/AppRTCDemo/ios/resources/ic_surround_sound_black_24dp.png b/webrtc/examples/objc/AppRTCDemo/ios/resources/ic_surround_sound_black_24dp.png
new file mode 100644
index 0000000..8f3343d
--- /dev/null
+++ b/webrtc/examples/objc/AppRTCDemo/ios/resources/ic_surround_sound_black_24dp.png
Binary files differ
diff --git a/webrtc/examples/objc/AppRTCDemo/ios/resources/ic_surround_sound_black_24dp@2x.png b/webrtc/examples/objc/AppRTCDemo/ios/resources/ic_surround_sound_black_24dp@2x.png
new file mode 100644
index 0000000..7648804
--- /dev/null
+++ b/webrtc/examples/objc/AppRTCDemo/ios/resources/ic_surround_sound_black_24dp@2x.png
Binary files differ