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

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

Issue 1782363002: Fix lock behavior on RTCAudioSession. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Remove autoreleasepool bits Created 4 years, 9 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
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 #include "webrtc/base/checks.h" 13 #include "webrtc/base/checks.h"
14 #include "webrtc/base/criticalsection.h"
14 15
15 #import "webrtc/base/objc/RTCLogging.h" 16 #import "webrtc/base/objc/RTCLogging.h"
16 #import "webrtc/modules/audio_device/ios/objc/RTCAudioSession+Private.h" 17 #import "webrtc/modules/audio_device/ios/objc/RTCAudioSession+Private.h"
17 18
18 NSString * const kRTCAudioSessionErrorDomain = @"org.webrtc.RTCAudioSession"; 19 NSString * const kRTCAudioSessionErrorDomain = @"org.webrtc.RTCAudioSession";
19 NSInteger const kRTCAudioSessionErrorLockRequired = -1; 20 NSInteger const kRTCAudioSessionErrorLockRequired = -1;
20 21
21 // This class needs to be thread-safe because it is accessed from many threads. 22 // This class needs to be thread-safe because it is accessed from many threads.
22 // TODO(tkchin): Consider more granular locking. We're not expecting a lot of 23 // TODO(tkchin): Consider more granular locking. We're not expecting a lot of
23 // lock contention so coarse locks should be fine for now. 24 // lock contention so coarse locks should be fine for now.
24 @implementation RTCAudioSession { 25 @implementation RTCAudioSession {
26 rtc::CriticalSection _crit;
25 AVAudioSession *_session; 27 AVAudioSession *_session;
26 NSHashTable *_delegates; 28 NSHashTable *_delegates;
27 NSInteger _activationCount; 29 NSInteger _activationCount;
30 NSInteger _lockRecursionCount;
28 BOOL _isActive; 31 BOOL _isActive;
29 BOOL _isLocked;
30 } 32 }
31 33
32 @synthesize session = _session; 34 @synthesize session = _session;
33 @synthesize lock = _lock;
34 35
35 + (instancetype)sharedInstance { 36 + (instancetype)sharedInstance {
36 static dispatch_once_t onceToken; 37 static dispatch_once_t onceToken;
37 static RTCAudioSession *sharedInstance = nil; 38 static RTCAudioSession *sharedInstance = nil;
38 dispatch_once(&onceToken, ^{ 39 dispatch_once(&onceToken, ^{
39 sharedInstance = [[RTCAudioSession alloc] init]; 40 sharedInstance = [[RTCAudioSession alloc] init];
40 }); 41 });
41 return sharedInstance; 42 return sharedInstance;
42 } 43 }
43 44
44 - (instancetype)init { 45 - (instancetype)init {
45 if (self = [super init]) { 46 if (self = [super init]) {
46 _session = [AVAudioSession sharedInstance]; 47 _session = [AVAudioSession sharedInstance];
47 _delegates = [NSHashTable weakObjectsHashTable]; 48 _delegates = [NSHashTable weakObjectsHashTable];
48 _lock = [[NSRecursiveLock alloc] init]; 49
49 NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; 50 NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
50 [center addObserver:self 51 [center addObserver:self
51 selector:@selector(handleInterruptionNotification:) 52 selector:@selector(handleInterruptionNotification:)
52 name:AVAudioSessionInterruptionNotification 53 name:AVAudioSessionInterruptionNotification
53 object:nil]; 54 object:nil];
54 [center addObserver:self 55 [center addObserver:self
55 selector:@selector(handleRouteChangeNotification:) 56 selector:@selector(handleRouteChangeNotification:)
56 name:AVAudioSessionRouteChangeNotification 57 name:AVAudioSessionRouteChangeNotification
57 object:nil]; 58 object:nil];
58 // TODO(tkchin): Maybe listen to SilenceSecondaryAudioHintNotification. 59 // TODO(tkchin): Maybe listen to SilenceSecondaryAudioHintNotification.
(...skipping 20 matching lines...) Expand all
79 } 80 }
80 81
81 - (BOOL)isActive { 82 - (BOOL)isActive {
82 @synchronized(self) { 83 @synchronized(self) {
83 return _isActive; 84 return _isActive;
84 } 85 }
85 } 86 }
86 87
87 - (BOOL)isLocked { 88 - (BOOL)isLocked {
88 @synchronized(self) { 89 @synchronized(self) {
89 return _isLocked; 90 return _lockRecursionCount > 0;
90 } 91 }
91 } 92 }
92 93
93 - (void)addDelegate:(id<RTCAudioSessionDelegate>)delegate { 94 - (void)addDelegate:(id<RTCAudioSessionDelegate>)delegate {
94 @synchronized(self) { 95 @synchronized(self) {
95 [_delegates addObject:delegate]; 96 [_delegates addObject:delegate];
96 } 97 }
97 } 98 }
98 99
99 - (void)removeDelegate:(id<RTCAudioSessionDelegate>)delegate { 100 - (void)removeDelegate:(id<RTCAudioSessionDelegate>)delegate {
100 @synchronized(self) { 101 @synchronized(self) {
101 [_delegates removeObject:delegate]; 102 [_delegates removeObject:delegate];
102 } 103 }
103 } 104 }
104 105
105 - (void)lockForConfiguration { 106 - (void)lockForConfiguration {
106 [_lock lock]; 107 _crit.Enter();
107 @synchronized(self) { 108 @synchronized(self) {
108 _isLocked = YES; 109 ++_lockRecursionCount;
109 } 110 }
110 } 111 }
111 112
112 - (void)unlockForConfiguration { 113 - (void)unlockForConfiguration {
113 // Don't let threads other than the one that called lockForConfiguration 114 // Don't let threads other than the one that called lockForConfiguration
114 // unlock. 115 // unlock.
115 if ([_lock tryLock]) { 116 if (_crit.TryEnter()) {
116 @synchronized(self) { 117 @synchronized(self) {
117 _isLocked = NO; 118 --_lockRecursionCount;
118 } 119 }
119 // One unlock for the tryLock, and another one to actually unlock. If this 120 // One unlock for the tryLock, and another one to actually unlock. If this
120 // was called without anyone calling lock, the underlying NSRecursiveLock 121 // was called without anyone calling lock, we will hit an assertion.
121 // should spit out an error. 122 _crit.Leave();
122 [_lock unlock]; 123 _crit.Leave();
123 [_lock unlock];
124 } 124 }
125 } 125 }
126 126
127 #pragma mark - AVAudioSession proxy methods 127 #pragma mark - AVAudioSession proxy methods
128 128
129 - (NSString *)category { 129 - (NSString *)category {
130 return self.session.category; 130 return self.session.category;
131 } 131 }
132 132
133 - (AVAudioSessionCategoryOptions)categoryOptions { 133 - (AVAudioSessionCategoryOptions)categoryOptions {
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after
524 } 524 }
525 } 525 }
526 526
527 - (void)notifyMediaServicesWereReset { 527 - (void)notifyMediaServicesWereReset {
528 for (id<RTCAudioSessionDelegate> delegate in self.delegates) { 528 for (id<RTCAudioSessionDelegate> delegate in self.delegates) {
529 [delegate audioSessionMediaServicesWereReset:self]; 529 [delegate audioSessionMediaServicesWereReset:self];
530 } 530 }
531 } 531 }
532 532
533 @end 533 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698