From 43cf6ed6945b352064d8656b3664cde2b49dfd27 Mon Sep 17 00:00:00 2001 From: Joel Fischer Date: Thu, 7 Dec 2017 14:21:26 -0500 Subject: [PATCH 1/6] Create a background serial queue and run RPC notifications on it --- SmartDeviceLink/SDLLockScreenPresenter.m | 15 ++++++++++++--- SmartDeviceLink/SDLNotificationDispatcher.m | 21 ++++++++++++++++++--- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/SmartDeviceLink/SDLLockScreenPresenter.m b/SmartDeviceLink/SDLLockScreenPresenter.m index 9092972d9..3d7143492 100644 --- a/SmartDeviceLink/SDLLockScreenPresenter.m +++ b/SmartDeviceLink/SDLLockScreenPresenter.m @@ -23,7 +23,9 @@ - (void)present { return; } - [[self.class sdl_getCurrentViewController] presentViewController:self.viewController animated:YES completion:nil]; + dispatch_async(dispatch_get_main_queue(), ^{ + [[self.class sdl_getCurrentViewController] presentViewController:self.viewController animated:YES completion:nil]; + }); } - (void)dismiss { @@ -31,7 +33,9 @@ - (void)dismiss { return; } - [self.viewController.presentingViewController dismissViewControllerAnimated:YES completion:nil]; + dispatch_async(dispatch_get_main_queue(), ^{ + [self.viewController.presentingViewController dismissViewControllerAnimated:YES completion:nil]; + }); } - (BOOL)presented { @@ -39,7 +43,12 @@ - (BOOL)presented { return NO; } - return (self.viewController.isViewLoaded && (self.viewController.view.window || self.viewController.isBeingPresented)); + __block BOOL presented = NO; + dispatch_sync(dispatch_get_main_queue(), ^{ + presented = (self.viewController.isViewLoaded && (self.viewController.view.window || self.viewController.isBeingPresented)); + }); + + return presented; } + (UIViewController *)sdl_getCurrentViewController { diff --git a/SmartDeviceLink/SDLNotificationDispatcher.m b/SmartDeviceLink/SDLNotificationDispatcher.m index 142286400..5593371aa 100644 --- a/SmartDeviceLink/SDLNotificationDispatcher.m +++ b/SmartDeviceLink/SDLNotificationDispatcher.m @@ -16,28 +16,43 @@ NS_ASSUME_NONNULL_BEGIN +@interface SDLNotificationDispatcher() + +@property (strong, nonatomic) dispatch_queue_t rpcNotificationQueue; + +@end + @implementation SDLNotificationDispatcher +- (instancetype)init { + self = [super init]; + if (!self) { return nil; } + + _rpcNotificationQueue = dispatch_queue_create("com.sdl.rpcNotificationQueue", DISPATCH_QUEUE_SERIAL); + + return self; +} + - (void)postNotificationName:(NSString *)name infoObject:(nullable id)infoObject { NSDictionary *userInfo = nil; if (infoObject != nil) { userInfo = @{SDLNotificationUserInfoObject: infoObject}; } - dispatch_async(dispatch_get_main_queue(), ^{ + dispatch_async(_rpcNotificationQueue, ^{ [[NSNotificationCenter defaultCenter] postNotificationName:name object:self userInfo:userInfo]; }); } - (void)postRPCResponseNotification:(NSString *)name response:(__kindof SDLRPCResponse *)response { - dispatch_async(dispatch_get_main_queue(), ^{ + dispatch_async(_rpcNotificationQueue, ^{ SDLRPCResponseNotification *notification = [[SDLRPCResponseNotification alloc] initWithName:name object:self rpcResponse:response]; [[NSNotificationCenter defaultCenter] postNotification:notification]; }); } - (void)postRPCNotificationNotification:(NSString *)name notification:(__kindof SDLRPCNotification *)rpcNotification { - dispatch_async(dispatch_get_main_queue(), ^{ + dispatch_async(_rpcNotificationQueue, ^{ SDLRPCNotificationNotification *notification = [[SDLRPCNotificationNotification alloc] initWithName:name object:self rpcNotification:rpcNotification]; [[NSNotificationCenter defaultCenter] postNotification:notification]; }); From e1ae8ca7689a3eb585f50c636f1d9e9942f88caf Mon Sep 17 00:00:00 2001 From: Joel Fischer Date: Mon, 11 Dec 2017 16:56:48 -0500 Subject: [PATCH 2/6] Move RPC processing queue dispatch to SDLProxy --- SmartDeviceLink/SDLNotificationDispatcher.m | 26 ++++++--------------- SmartDeviceLink/SDLProxy.m | 15 ++++++------ 2 files changed, 15 insertions(+), 26 deletions(-) diff --git a/SmartDeviceLink/SDLNotificationDispatcher.m b/SmartDeviceLink/SDLNotificationDispatcher.m index 5593371aa..252fa6379 100644 --- a/SmartDeviceLink/SDLNotificationDispatcher.m +++ b/SmartDeviceLink/SDLNotificationDispatcher.m @@ -16,19 +16,13 @@ NS_ASSUME_NONNULL_BEGIN -@interface SDLNotificationDispatcher() - -@property (strong, nonatomic) dispatch_queue_t rpcNotificationQueue; - -@end - @implementation SDLNotificationDispatcher - (instancetype)init { self = [super init]; if (!self) { return nil; } - _rpcNotificationQueue = dispatch_queue_create("com.sdl.rpcNotificationQueue", DISPATCH_QUEUE_SERIAL); + return self; } @@ -38,24 +32,18 @@ - (void)postNotificationName:(NSString *)name infoObject:(nullable id)infoObject if (infoObject != nil) { userInfo = @{SDLNotificationUserInfoObject: infoObject}; } - - dispatch_async(_rpcNotificationQueue, ^{ - [[NSNotificationCenter defaultCenter] postNotificationName:name object:self userInfo:userInfo]; - }); + + [[NSNotificationCenter defaultCenter] postNotificationName:name object:self userInfo:userInfo]; } - (void)postRPCResponseNotification:(NSString *)name response:(__kindof SDLRPCResponse *)response { - dispatch_async(_rpcNotificationQueue, ^{ - SDLRPCResponseNotification *notification = [[SDLRPCResponseNotification alloc] initWithName:name object:self rpcResponse:response]; - [[NSNotificationCenter defaultCenter] postNotification:notification]; - }); + SDLRPCResponseNotification *notification = [[SDLRPCResponseNotification alloc] initWithName:name object:self rpcResponse:response]; + [[NSNotificationCenter defaultCenter] postNotification:notification]; } - (void)postRPCNotificationNotification:(NSString *)name notification:(__kindof SDLRPCNotification *)rpcNotification { - dispatch_async(_rpcNotificationQueue, ^{ - SDLRPCNotificationNotification *notification = [[SDLRPCNotificationNotification alloc] initWithName:name object:self rpcNotification:rpcNotification]; - [[NSNotificationCenter defaultCenter] postNotification:notification]; - }); + SDLRPCNotificationNotification *notification = [[SDLRPCNotificationNotification alloc] initWithName:name object:self rpcNotification:rpcNotification]; + [[NSNotificationCenter defaultCenter] postNotification:notification]; } #pragma mark - SDLProxyListener Delegate Methods diff --git a/SmartDeviceLink/SDLProxy.m b/SmartDeviceLink/SDLProxy.m index 6f19a7686..0cdadfd78 100644 --- a/SmartDeviceLink/SDLProxy.m +++ b/SmartDeviceLink/SDLProxy.m @@ -56,6 +56,7 @@ @interface SDLProxy () { @property (nullable, nonatomic, strong) SDLDisplayCapabilities *displayCapabilities; @property (nonatomic, strong) NSMutableDictionary *securityManagers; @property (nonatomic, strong) NSURLSession* urlSession; +@property (strong, nonatomic) dispatch_queue_t rpcProcessingQueue; @end @@ -68,6 +69,7 @@ - (instancetype)initWithTransport:(SDLAbstractTransport *)transport protocol:(SD SDLLogD(@"Framework Version: %@", self.proxyVersion); _debugConsoleGroupName = @"default"; _lsm = [[SDLLockScreenStatusManager alloc] init]; + _rpcProcessingQueue = dispatch_queue_create("com.sdl.rpcProcessingQueue", DISPATCH_QUEUE_SERIAL); _mutableProxyListeners = [NSMutableSet setWithObject:theDelegate]; _securityManagers = [NSMutableDictionary dictionary]; @@ -629,13 +631,12 @@ - (void)removeDelegate:(NSObject *)delegate { } - (void)invokeMethodOnDelegates:(SEL)aSelector withObject:(nullable id)object { - dispatch_async(dispatch_get_main_queue(), ^{ - @autoreleasepool { - for (id listener in self.proxyListeners) { - if ([listener respondsToSelector:aSelector]) { - // HAX: http://stackoverflow.com/questions/7017281/performselector-may-cause-a-leak-because-its-selector-is-unknown - ((void (*)(id, SEL, id))[(NSObject *)listener methodForSelector:aSelector])(listener, aSelector, object); - } + // Occurs on the protocol receive serial queue + dispatch_async(_rpcProcessingQueue, ^{ + for (id listener in self.proxyListeners) { + if ([listener respondsToSelector:aSelector]) { + // HAX: http://stackoverflow.com/questions/7017281/performselector-may-cause-a-leak-because-its-selector-is-unknown + ((void (*)(id, SEL, id))[(NSObject *)listener methodForSelector:aSelector])(listener, aSelector, object); } } }); From 006b21c05080527e77e44df246a49bcd2bc07636 Mon Sep 17 00:00:00 2001 From: Joel Fischer Date: Mon, 11 Dec 2017 16:58:42 -0500 Subject: [PATCH 3/6] Delete bonus lines --- SmartDeviceLink/SDLNotificationDispatcher.m | 2 -- 1 file changed, 2 deletions(-) diff --git a/SmartDeviceLink/SDLNotificationDispatcher.m b/SmartDeviceLink/SDLNotificationDispatcher.m index 252fa6379..ff2fb9eb9 100644 --- a/SmartDeviceLink/SDLNotificationDispatcher.m +++ b/SmartDeviceLink/SDLNotificationDispatcher.m @@ -22,8 +22,6 @@ - (instancetype)init { self = [super init]; if (!self) { return nil; } - - return self; } From d6454b186af19578362a34696589372ddc9d8d60 Mon Sep 17 00:00:00 2001 From: Joel Fischer Date: Mon, 11 Dec 2017 17:03:53 -0500 Subject: [PATCH 4/6] Comments --- SmartDeviceLink/SDLNotificationConstants.m | 2 ++ SmartDeviceLink/SDLNotificationDispatcher.h | 1 - SmartDeviceLink/SDLNotificationDispatcher.m | 5 +++++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/SmartDeviceLink/SDLNotificationConstants.m b/SmartDeviceLink/SDLNotificationConstants.m index 813a07ca6..864524205 100644 --- a/SmartDeviceLink/SDLNotificationConstants.m +++ b/SmartDeviceLink/SDLNotificationConstants.m @@ -8,6 +8,8 @@ #import "SDLNotificationConstants.h" +/// These notifications will be returned on a background serial queue + SDLNotificationUserInfoKey const SDLNotificationUserInfoObject = @"SDLNotificationUserInfoObject"; diff --git a/SmartDeviceLink/SDLNotificationDispatcher.h b/SmartDeviceLink/SDLNotificationDispatcher.h index d189ef990..ba5089a25 100644 --- a/SmartDeviceLink/SDLNotificationDispatcher.h +++ b/SmartDeviceLink/SDLNotificationDispatcher.h @@ -28,7 +28,6 @@ NS_ASSUME_NONNULL_BEGIN * @param info The object to be send along in the `userInfo` dictionary. */ - (void)postNotificationName:(NSString *)name infoObject:(nullable id)info; - - (void)postRPCResponseNotification:(NSString *)name response:(__kindof SDLRPCResponse *)response; - (void)postRPCNotificationNotification:(NSString *)name notification:(__kindof SDLRPCNotification *)rpcNotification; diff --git a/SmartDeviceLink/SDLNotificationDispatcher.m b/SmartDeviceLink/SDLNotificationDispatcher.m index ff2fb9eb9..a28befb68 100644 --- a/SmartDeviceLink/SDLNotificationDispatcher.m +++ b/SmartDeviceLink/SDLNotificationDispatcher.m @@ -31,16 +31,21 @@ - (void)postNotificationName:(NSString *)name infoObject:(nullable id)infoObject userInfo = @{SDLNotificationUserInfoObject: infoObject}; } + // Runs on `com.sdl.rpcProcessingQueue` [[NSNotificationCenter defaultCenter] postNotificationName:name object:self userInfo:userInfo]; } - (void)postRPCResponseNotification:(NSString *)name response:(__kindof SDLRPCResponse *)response { SDLRPCResponseNotification *notification = [[SDLRPCResponseNotification alloc] initWithName:name object:self rpcResponse:response]; + + // Runs on `com.sdl.rpcProcessingQueue` [[NSNotificationCenter defaultCenter] postNotification:notification]; } - (void)postRPCNotificationNotification:(NSString *)name notification:(__kindof SDLRPCNotification *)rpcNotification { SDLRPCNotificationNotification *notification = [[SDLRPCNotificationNotification alloc] initWithName:name object:self rpcNotification:rpcNotification]; + + // Runs on `com.sdl.rpcProcessingQueue` [[NSNotificationCenter defaultCenter] postNotification:notification]; } From 07965dbe5b878ede6f002de371347d829c81a694 Mon Sep 17 00:00:00 2001 From: Joel Fischer Date: Mon, 18 Dec 2017 11:39:45 -0500 Subject: [PATCH 5/6] Only dispatch_sync to the main thread if not on the main thread --- SmartDeviceLink/SDLLockScreenPresenter.m | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/SmartDeviceLink/SDLLockScreenPresenter.m b/SmartDeviceLink/SDLLockScreenPresenter.m index 3d7143492..52b88b0a4 100644 --- a/SmartDeviceLink/SDLLockScreenPresenter.m +++ b/SmartDeviceLink/SDLLockScreenPresenter.m @@ -44,9 +44,13 @@ - (BOOL)presented { } __block BOOL presented = NO; - dispatch_sync(dispatch_get_main_queue(), ^{ + if (![NSThread isMainThread]) { + dispatch_sync(dispatch_get_main_queue(), ^{ + presented = (self.viewController.isViewLoaded && (self.viewController.view.window || self.viewController.isBeingPresented)); + }); + } else { presented = (self.viewController.isViewLoaded && (self.viewController.view.window || self.viewController.isBeingPresented)); - }); + } return presented; } From cd21bff384e180b2cbb83fc36b54a06fe8df783a Mon Sep 17 00:00:00 2001 From: Joel Fischer Date: Mon, 18 Dec 2017 16:22:36 -0500 Subject: [PATCH 6/6] Force re-layout of lock screen to occur on main queue --- SmartDeviceLink/SDLLockScreenViewController.m | 64 ++++++++++--------- 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/SmartDeviceLink/SDLLockScreenViewController.m b/SmartDeviceLink/SDLLockScreenViewController.m index c69b059bb..27cc98797 100644 --- a/SmartDeviceLink/SDLLockScreenViewController.m +++ b/SmartDeviceLink/SDLLockScreenViewController.m @@ -71,37 +71,39 @@ - (void)setBackgroundColor:(UIColor *_Nullable)backgroundColor { #pragma mark - Layout - (void)sdl_layoutViews { - UIColor *iconColor = [self.class sdl_accentColorBasedOnColor:self.backgroundColor]; - - self.sdlIconImageView.image = [self.class sdl_imageWithName:@"sdl_logo_black"]; - self.sdlIconImageView.tintColor = iconColor; - - self.arrowUpImageView.image = [self.class sdl_imageWithName:@"lock_arrow_up_black"]; - self.arrowUpImageView.tintColor = iconColor; - - self.arrowDownImageView.image = [self.class sdl_imageWithName:@"lock_arrow_down_black"]; - self.arrowDownImageView.tintColor = iconColor; - - self.lockedLabel.textColor = iconColor; - - if (self.vehicleIcon != nil && self.appIcon != nil) { - [self sdl_setVehicleAndAppIconsLayout]; - } else if (self.vehicleIcon != nil) { - [self sdl_setVehicleIconOnlyLayout]; - } else if (self.appIcon != nil) { - [self sdl_setAppIconOnlyLayout]; - } else { - [self sdl_setNoIconsLayout]; - } - - // HAX: The autolayout doesn't scale for 4s, so hide a view so it doesn't look like garbage. - if (CGRectGetHeight([UIScreen mainScreen].bounds) == 480) { - self.sdlIconImageView.hidden = YES; - } else { - self.sdlIconImageView.hidden = NO; - } - - [self.view layoutIfNeeded]; + dispatch_async(dispatch_get_main_queue(), ^{ + UIColor *iconColor = [self.class sdl_accentColorBasedOnColor:self.backgroundColor]; + + self.sdlIconImageView.image = [self.class sdl_imageWithName:@"sdl_logo_black"]; + self.sdlIconImageView.tintColor = iconColor; + + self.arrowUpImageView.image = [self.class sdl_imageWithName:@"lock_arrow_up_black"]; + self.arrowUpImageView.tintColor = iconColor; + + self.arrowDownImageView.image = [self.class sdl_imageWithName:@"lock_arrow_down_black"]; + self.arrowDownImageView.tintColor = iconColor; + + self.lockedLabel.textColor = iconColor; + + if (self.vehicleIcon != nil && self.appIcon != nil) { + [self sdl_setVehicleAndAppIconsLayout]; + } else if (self.vehicleIcon != nil) { + [self sdl_setVehicleIconOnlyLayout]; + } else if (self.appIcon != nil) { + [self sdl_setAppIconOnlyLayout]; + } else { + [self sdl_setNoIconsLayout]; + } + + // HAX: The autolayout doesn't scale for 4s, so hide a view so it doesn't look like garbage. + if (CGRectGetHeight([UIScreen mainScreen].bounds) == 480) { + self.sdlIconImageView.hidden = YES; + } else { + self.sdlIconImageView.hidden = NO; + } + + [self.view layoutIfNeeded]; + }); } - (void)sdl_setVehicleAndAppIconsLayout {