Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(739)

Side by Side Diff: webrtc/modules/audio_device/ios/objc/RTCAudioSession.mm

Issue 2181163005: Treat foreground event as interruption end. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | webrtc/modules/audio_device/ios/objc/RTCAudioSession+Private.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2016 The WebRTC Project Authors. All rights reserved. 2 * Copyright 2016 The WebRTC Project Authors. All rights reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #import "webrtc/modules/audio_device/ios/objc/RTCAudioSession.h" 11 #import "webrtc/modules/audio_device/ios/objc/RTCAudioSession.h"
12 12
13 #import <UIKit/UIKit.h>
14
13 #include "webrtc/base/atomicops.h" 15 #include "webrtc/base/atomicops.h"
14 #include "webrtc/base/checks.h" 16 #include "webrtc/base/checks.h"
15 #include "webrtc/base/criticalsection.h" 17 #include "webrtc/base/criticalsection.h"
16 #include "webrtc/modules/audio_device/ios/audio_device_ios.h" 18 #include "webrtc/modules/audio_device/ios/audio_device_ios.h"
17 19
18 #import "WebRTC/RTCLogging.h" 20 #import "WebRTC/RTCLogging.h"
19 #import "webrtc/modules/audio_device/ios/objc/RTCAudioSession+Private.h" 21 #import "webrtc/modules/audio_device/ios/objc/RTCAudioSession+Private.h"
20 #import "webrtc/modules/audio_device/ios/objc/RTCAudioSessionConfiguration.h" 22 #import "webrtc/modules/audio_device/ios/objc/RTCAudioSessionConfiguration.h"
21 23
22 NSString * const kRTCAudioSessionErrorDomain = @"org.webrtc.RTCAudioSession"; 24 NSString * const kRTCAudioSessionErrorDomain = @"org.webrtc.RTCAudioSession";
23 NSInteger const kRTCAudioSessionErrorLockRequired = -1; 25 NSInteger const kRTCAudioSessionErrorLockRequired = -1;
24 NSInteger const kRTCAudioSessionErrorConfiguration = -2; 26 NSInteger const kRTCAudioSessionErrorConfiguration = -2;
25 27
26 // This class needs to be thread-safe because it is accessed from many threads. 28 // This class needs to be thread-safe because it is accessed from many threads.
27 // TODO(tkchin): Consider more granular locking. We're not expecting a lot of 29 // TODO(tkchin): Consider more granular locking. We're not expecting a lot of
28 // lock contention so coarse locks should be fine for now. 30 // lock contention so coarse locks should be fine for now.
29 @implementation RTCAudioSession { 31 @implementation RTCAudioSession {
30 rtc::CriticalSection _crit; 32 rtc::CriticalSection _crit;
31 AVAudioSession *_session; 33 AVAudioSession *_session;
32 volatile int _activationCount; 34 volatile int _activationCount;
33 volatile int _lockRecursionCount; 35 volatile int _lockRecursionCount;
34 volatile int _webRTCSessionCount; 36 volatile int _webRTCSessionCount;
35 BOOL _isActive; 37 BOOL _isActive;
36 BOOL _useManualAudio; 38 BOOL _useManualAudio;
37 BOOL _isAudioEnabled; 39 BOOL _isAudioEnabled;
38 BOOL _canPlayOrRecord; 40 BOOL _canPlayOrRecord;
41 BOOL _isInterrupted;
39 } 42 }
40 43
41 @synthesize session = _session; 44 @synthesize session = _session;
42 @synthesize delegates = _delegates; 45 @synthesize delegates = _delegates;
43 46
44 + (instancetype)sharedInstance { 47 + (instancetype)sharedInstance {
45 static dispatch_once_t onceToken; 48 static dispatch_once_t onceToken;
46 static RTCAudioSession *sharedInstance = nil; 49 static RTCAudioSession *sharedInstance = nil;
47 dispatch_once(&onceToken, ^{ 50 dispatch_once(&onceToken, ^{
48 sharedInstance = [[self alloc] init]; 51 sharedInstance = [[self alloc] init];
(...skipping 16 matching lines...) Expand all
65 object:nil]; 68 object:nil];
66 // TODO(tkchin): Maybe listen to SilenceSecondaryAudioHintNotification. 69 // TODO(tkchin): Maybe listen to SilenceSecondaryAudioHintNotification.
67 [center addObserver:self 70 [center addObserver:self
68 selector:@selector(handleMediaServicesWereLost:) 71 selector:@selector(handleMediaServicesWereLost:)
69 name:AVAudioSessionMediaServicesWereLostNotification 72 name:AVAudioSessionMediaServicesWereLostNotification
70 object:nil]; 73 object:nil];
71 [center addObserver:self 74 [center addObserver:self
72 selector:@selector(handleMediaServicesWereReset:) 75 selector:@selector(handleMediaServicesWereReset:)
73 name:AVAudioSessionMediaServicesWereResetNotification 76 name:AVAudioSessionMediaServicesWereResetNotification
74 object:nil]; 77 object:nil];
78 // Also track foreground event in order to deal with interruption ended situ ation.
79 [center addObserver:self
80 selector:@selector(handleApplicationDidBecomeActive:)
81 name:UIApplicationDidBecomeActiveNotification
82 object:nil];
75 } 83 }
76 return self; 84 return self;
77 } 85 }
78 86
79 - (void)dealloc { 87 - (void)dealloc {
80 [[NSNotificationCenter defaultCenter] removeObserver:self]; 88 [[NSNotificationCenter defaultCenter] removeObserver:self];
81 } 89 }
82 90
83 - (NSString *)description { 91 - (NSString *)description {
84 NSString *format = 92 NSString *format =
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after
427 435
428 - (void)handleInterruptionNotification:(NSNotification *)notification { 436 - (void)handleInterruptionNotification:(NSNotification *)notification {
429 NSNumber* typeNumber = 437 NSNumber* typeNumber =
430 notification.userInfo[AVAudioSessionInterruptionTypeKey]; 438 notification.userInfo[AVAudioSessionInterruptionTypeKey];
431 AVAudioSessionInterruptionType type = 439 AVAudioSessionInterruptionType type =
432 (AVAudioSessionInterruptionType)typeNumber.unsignedIntegerValue; 440 (AVAudioSessionInterruptionType)typeNumber.unsignedIntegerValue;
433 switch (type) { 441 switch (type) {
434 case AVAudioSessionInterruptionTypeBegan: 442 case AVAudioSessionInterruptionTypeBegan:
435 RTCLog(@"Audio session interruption began."); 443 RTCLog(@"Audio session interruption began.");
436 self.isActive = NO; 444 self.isActive = NO;
445 self.isInterrupted = YES;
437 [self notifyDidBeginInterruption]; 446 [self notifyDidBeginInterruption];
438 break; 447 break;
439 case AVAudioSessionInterruptionTypeEnded: { 448 case AVAudioSessionInterruptionTypeEnded: {
440 RTCLog(@"Audio session interruption ended."); 449 RTCLog(@"Audio session interruption ended.");
450 self.isInterrupted = NO;
441 [self updateAudioSessionAfterEvent]; 451 [self updateAudioSessionAfterEvent];
442 NSNumber *optionsNumber = 452 NSNumber *optionsNumber =
443 notification.userInfo[AVAudioSessionInterruptionOptionKey]; 453 notification.userInfo[AVAudioSessionInterruptionOptionKey];
444 AVAudioSessionInterruptionOptions options = 454 AVAudioSessionInterruptionOptions options =
445 optionsNumber.unsignedIntegerValue; 455 optionsNumber.unsignedIntegerValue;
446 BOOL shouldResume = 456 BOOL shouldResume =
447 options & AVAudioSessionInterruptionOptionShouldResume; 457 options & AVAudioSessionInterruptionOptionShouldResume;
448 [self notifyDidEndInterruptionWithShouldResumeSession:shouldResume]; 458 [self notifyDidEndInterruptionWithShouldResumeSession:shouldResume];
449 break; 459 break;
450 } 460 }
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
498 [self updateAudioSessionAfterEvent]; 508 [self updateAudioSessionAfterEvent];
499 [self notifyMediaServicesWereLost]; 509 [self notifyMediaServicesWereLost];
500 } 510 }
501 511
502 - (void)handleMediaServicesWereReset:(NSNotification *)notification { 512 - (void)handleMediaServicesWereReset:(NSNotification *)notification {
503 RTCLog(@"Media services were reset."); 513 RTCLog(@"Media services were reset.");
504 [self updateAudioSessionAfterEvent]; 514 [self updateAudioSessionAfterEvent];
505 [self notifyMediaServicesWereReset]; 515 [self notifyMediaServicesWereReset];
506 } 516 }
507 517
518 - (void)handleApplicationDidBecomeActive:(NSNotification *)notification {
519 if (self.isInterrupted) {
520 RTCLog(@"Application became active after an interruption. Treating as interr uption end.");
521 self.isInterrupted = NO;
522 [self updateAudioSessionAfterEvent];
523 [self notifyDidEndInterruptionWithShouldResumeSession:YES];
524 }
525 }
526
508 #pragma mark - Private 527 #pragma mark - Private
509 528
510 + (NSError *)lockError { 529 + (NSError *)lockError {
511 NSDictionary *userInfo = @{ 530 NSDictionary *userInfo = @{
512 NSLocalizedDescriptionKey: 531 NSLocalizedDescriptionKey:
513 @"Must call lockForConfiguration before calling this method." 532 @"Must call lockForConfiguration before calling this method."
514 }; 533 };
515 NSError *error = 534 NSError *error =
516 [[NSError alloc] initWithDomain:kRTCAudioSessionErrorDomain 535 [[NSError alloc] initWithDomain:kRTCAudioSessionErrorDomain
517 code:kRTCAudioSessionErrorLockRequired 536 code:kRTCAudioSessionErrorLockRequired
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
558 } 577 }
559 578
560 - (int)webRTCSessionCount { 579 - (int)webRTCSessionCount {
561 return _webRTCSessionCount; 580 return _webRTCSessionCount;
562 } 581 }
563 582
564 - (BOOL)canPlayOrRecord { 583 - (BOOL)canPlayOrRecord {
565 return !self.useManualAudio || self.isAudioEnabled; 584 return !self.useManualAudio || self.isAudioEnabled;
566 } 585 }
567 586
587 - (BOOL)isInterrupted {
588 @synchronized(self) {
589 return _isInterrupted;
590 }
591 }
592
593 - (void)setIsInterrupted:(BOOL)isInterrupted {
594 @synchronized(self) {
595 if (_isInterrupted == isInterrupted) {
596 return;
597 }
598 _isInterrupted = isInterrupted;
599 }
600 }
601
568 - (BOOL)checkLock:(NSError **)outError { 602 - (BOOL)checkLock:(NSError **)outError {
569 // Check ivar instead of trying to acquire lock so that we won't accidentally 603 // Check ivar instead of trying to acquire lock so that we won't accidentally
570 // acquire lock if it hasn't already been called. 604 // acquire lock if it hasn't already been called.
571 if (!self.isLocked) { 605 if (!self.isLocked) {
572 if (outError) { 606 if (outError) {
573 *outError = [RTCAudioSession lockError]; 607 *outError = [RTCAudioSession lockError];
574 } 608 }
575 return NO; 609 return NO;
576 } 610 }
577 return YES; 611 return YES;
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
788 - (void)notifyDidStopPlayOrRecord { 822 - (void)notifyDidStopPlayOrRecord {
789 for (auto delegate : self.delegates) { 823 for (auto delegate : self.delegates) {
790 SEL sel = @selector(audioSessionDidStopPlayOrRecord:); 824 SEL sel = @selector(audioSessionDidStopPlayOrRecord:);
791 if ([delegate respondsToSelector:sel]) { 825 if ([delegate respondsToSelector:sel]) {
792 [delegate audioSessionDidStopPlayOrRecord:self]; 826 [delegate audioSessionDidStopPlayOrRecord:self];
793 } 827 }
794 } 828 }
795 } 829 }
796 830
797 @end 831 @end
OLDNEW
« no previous file with comments | « no previous file | webrtc/modules/audio_device/ios/objc/RTCAudioSession+Private.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698