diff --git a/SmartDeviceLink/SDLIAPDataSession.m b/SmartDeviceLink/SDLIAPDataSession.m index 5bf61e304..3cd2d7492 100644 --- a/SmartDeviceLink/SDLIAPDataSession.m +++ b/SmartDeviceLink/SDLIAPDataSession.m @@ -110,6 +110,9 @@ - (void)sdl_stopAndDestroySession { [self sdl_isIOThreadCanceled:self.canceledSemaphore completionHandler:^(BOOL success) { if (success == NO) { SDLLogE(@"Destroying thread (IOStreamThread) for data session when I/O streams have not yet closed."); + + // FIX: Try to close the session if the canceledSemaphore is never triggered by the `sdl_accessoryEventLoop` + [self sdl_closeSession]; } self.ioStreamThread = nil; [super cleanupClosedSession]; diff --git a/SmartDeviceLink/SDLIAPTransport.m b/SmartDeviceLink/SDLIAPTransport.m index e83e5aa3d..5c6da5635 100644 --- a/SmartDeviceLink/SDLIAPTransport.m +++ b/SmartDeviceLink/SDLIAPTransport.m @@ -91,18 +91,15 @@ - (void)sdl_stopEventListening { * @param notification Contains information about the connected accessory */ - (void)sdl_accessoryConnected:(NSNotification *)notification { - EAAccessory *newAccessory = [notification.userInfo objectForKey:EAAccessoryKey]; + EAAccessory *newAccessory = notification.userInfo[EAAccessoryKey]; if ([self sdl_isDataSessionActive:self.dataSession newAccessory:newAccessory]) { self.accessoryConnectDuringActiveSession = YES; return; } - double retryDelay = self.sdl_retryDelay; - SDLLogD(@"Accessory Connected (%@), Opening in %0.03fs", notification.userInfo[EAAccessoryKey], retryDelay); - self.retryCounter = 0; - [self performSelector:@selector(sdl_connect:) withObject:nil afterDelay:retryDelay]; + [self sdl_connect:newAccessory]; } /** @@ -304,6 +301,7 @@ - (void)controlSessionShouldRetry { * @param protocolString The protocol string to be used to open the data session */ - (void)controlSession:(nonnull SDLIAPControlSession *)controlSession didReceiveProtocolString:(nonnull NSString *)protocolString { + SDLLogD(@"Control transport session received data session number: %@", protocolString); self.dataSession = [[SDLIAPDataSession alloc] initWithAccessory:controlSession.accessory delegate:self forProtocol:protocolString]; [self.dataSession startSession]; } @@ -495,14 +493,21 @@ - (BOOL)createSessionWithAccessory:(EAAccessory *)accessory protocolString:(NSSt if ([protocolString isEqualToString:MultiSessionProtocolString] && SDL_SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"9")) { self.dataSession = [[SDLIAPDataSession alloc] initWithAccessory:accessory delegate:self forProtocol:protocolString]; + + SDLLogD(@"Accessory Connected (%@), Opening immediately", accessory); [self.dataSession startSession]; return YES; } else if ([protocolString isEqualToString:ControlProtocolString]) { self.controlSession = [[SDLIAPControlSession alloc] initWithAccessory:accessory delegate:self]; - [self.controlSession startSession]; + + double retryDelay = [self sdl_retryDelay]; + SDLLogD(@"Accessory Connected (%@), Opening in %0.03fs", accessory, retryDelay); + [self.controlSession performSelector:@selector(startSession) withObject:nil afterDelay:retryDelay]; return YES; } else if ([protocolString isEqualToString:LegacyProtocolString]) { self.dataSession = [[SDLIAPDataSession alloc] initWithAccessory:accessory delegate:self forProtocol:protocolString]; + + SDLLogD(@"Accessory Connected (%@), Opening immediately", accessory); [self.dataSession startSession]; return YES; } diff --git a/SmartDeviceLink/SDLLifecycleManager.m b/SmartDeviceLink/SDLLifecycleManager.m index ff90d3171..5fd6d8c42 100644 --- a/SmartDeviceLink/SDLLifecycleManager.m +++ b/SmartDeviceLink/SDLLifecycleManager.m @@ -222,8 +222,8 @@ - (void)didEnterStateStarted { [self.backgroundTaskManager startBackgroundTask]; // Start up the internal proxy object - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wdeprecated-declarations" +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" self.secondaryTransportManager = nil; if (self.configuration.lifecycleConfig.tcpDebugMode) { self.proxy = [SDLProxy tcpProxyWithListener:self.notificationDispatcher @@ -237,7 +237,7 @@ - (void)didEnterStateStarted { self.secondaryTransportManager = [[SDLSecondaryTransportManager alloc] initWithStreamingProtocolDelegate:self serialQueue:self.lifecycleQueue]; self.proxy = [SDLProxy iapProxyWithListener:self.notificationDispatcher secondaryTransportManager:self.secondaryTransportManager]; } - #pragma clang diagnostic pop +#pragma clang diagnostic pop } - (void)didEnterStateStopped { @@ -316,25 +316,25 @@ - (void)didEnterStateConnected { // Send the request and depending on the response, post the notification __weak typeof(self) weakSelf = self; [self sdl_sendRequest:regRequest - withResponseHandler:^(__kindof SDLRPCRequest *_Nullable request, __kindof SDLRPCResponse *_Nullable response, NSError *_Nullable error) { - // If the success BOOL is NO or we received an error at this point, we failed. Call the ready handler and transition to the DISCONNECTED state. - if (error != nil || ![response.success boolValue]) { - SDLLogE(@"Failed to register the app. Error: %@, Response: %@", error, response); - if (weakSelf.readyHandler) { - weakSelf.readyHandler(NO, error); - } - - if (weakSelf.lifecycleState != SDLLifecycleStateReconnecting) { - [weakSelf sdl_transitionToState:SDLLifecycleStateStopped]; - } + withResponseHandler:^(__kindof SDLRPCRequest *_Nullable request, __kindof SDLRPCResponse *_Nullable response, NSError *_Nullable error) { + // If the success BOOL is NO or we received an error at this point, we failed. Call the ready handler and transition to the DISCONNECTED state. + if (error != nil || ![response.success boolValue]) { + SDLLogE(@"Failed to register the app. Error: %@, Response: %@", error, response); + if (weakSelf.readyHandler) { + weakSelf.readyHandler(NO, error); + } - return; + if (weakSelf.lifecycleState != SDLLifecycleStateReconnecting) { + [weakSelf sdl_transitionToState:SDLLifecycleStateStopped]; } - weakSelf.registerResponse = (SDLRegisterAppInterfaceResponse *)response; - [SDLGlobals sharedGlobals].rpcVersion = [SDLVersion versionWithSDLMsgVersion:weakSelf.registerResponse.sdlMsgVersion]; - [weakSelf sdl_transitionToState:SDLLifecycleStateRegistered]; - }]; + return; + } + + weakSelf.registerResponse = (SDLRegisterAppInterfaceResponse *)response; + [SDLGlobals sharedGlobals].rpcVersion = [SDLVersion versionWithSDLMsgVersion:weakSelf.registerResponse.sdlMsgVersion]; + [weakSelf sdl_transitionToState:SDLLifecycleStateRegistered]; + }]; } - (void)didEnterStateRegistered { @@ -359,33 +359,41 @@ - (void)didEnterStateRegistered { } - (void)didEnterStateUpdatingConfiguration { - // we can expect that the delegate has implemented the update method and the actual language is a supported language + // We can expect that the delegate has implemented the update method and the actual language is a supported language SDLLanguage actualLanguage = self.registerResponse.language; + SDLLogD(@"Updating configuration due to language mismatch. New langugage: %@", actualLanguage); - SDLLifecycleConfigurationUpdate *configUpdate = [self.delegate managerShouldUpdateLifecycleToLanguage:actualLanguage]; + SDLLifecycleConfigurationUpdate *configUpdate = [self.delegate managerShouldUpdateLifecycleToLanguage:actualLanguage]; - if (configUpdate) { - self.configuration.lifecycleConfig.language = actualLanguage; - if (configUpdate.appName) { - self.configuration.lifecycleConfig.appName = configUpdate.appName; - } - if (configUpdate.shortAppName) { - self.configuration.lifecycleConfig.shortAppName = configUpdate.shortAppName; - } - if (configUpdate.ttsName) { - self.configuration.lifecycleConfig.ttsName = configUpdate.ttsName; - } - if (configUpdate.voiceRecognitionCommandNames) { - self.configuration.lifecycleConfig.voiceRecognitionCommandNames = configUpdate.voiceRecognitionCommandNames; - } + if (configUpdate) { + self.configuration.lifecycleConfig.language = actualLanguage; + if (configUpdate.appName) { + self.configuration.lifecycleConfig.appName = configUpdate.appName; + } + if (configUpdate.shortAppName) { + self.configuration.lifecycleConfig.shortAppName = configUpdate.shortAppName; + } + if (configUpdate.ttsName) { + self.configuration.lifecycleConfig.ttsName = configUpdate.ttsName; + } + if (configUpdate.voiceRecognitionCommandNames) { + self.configuration.lifecycleConfig.voiceRecognitionCommandNames = configUpdate.voiceRecognitionCommandNames; + } - SDLChangeRegistration *changeRegistration = [[SDLChangeRegistration alloc] initWithLanguage:actualLanguage hmiDisplayLanguage:actualLanguage]; - changeRegistration.appName = configUpdate.appName; - changeRegistration.ngnMediaScreenAppName = configUpdate.shortAppName; - changeRegistration.ttsName = configUpdate.ttsName; - changeRegistration.vrSynonyms = configUpdate.voiceRecognitionCommandNames; + SDLChangeRegistration *changeRegistration = [[SDLChangeRegistration alloc] initWithLanguage:actualLanguage hmiDisplayLanguage:actualLanguage]; + changeRegistration.appName = configUpdate.appName; + changeRegistration.ngnMediaScreenAppName = configUpdate.shortAppName; + changeRegistration.ttsName = configUpdate.ttsName; + changeRegistration.vrSynonyms = configUpdate.voiceRecognitionCommandNames; - [self sendConnectionManagerRequest:changeRegistration withResponseHandler:nil]; + [self sendConnectionManagerRequest:changeRegistration withResponseHandler:^(__kindof SDLRPCRequest * _Nullable request, __kindof SDLRPCResponse * _Nullable response, NSError * _Nullable error) { + if (error != nil) { + SDLLogW(@"Failed to update language with change registration. Request: %@, Response: %@, error: %@", request, response, error); + return; + } + + SDLLogD(@"Successfully updated language with change registration. Request sent: %@", request); + }]; } [self sdl_transitionToState:SDLLifecycleStateSettingUpManagers]; @@ -424,7 +432,7 @@ - (void)didEnterStateSettingUpManagers { [self videoServiceProtocolDidUpdateFromOldProtocol:nil toNewProtocol:self.proxy.protocol]; } - dispatch_group_enter(managerGroup); + dispatch_group_enter(managerGroup); [self.screenManager startWithCompletionHandler:^(NSError * _Nullable error) { if (error != nil) { SDLLogW(@"Screen Manager was unable to start; error: %@", error); @@ -460,7 +468,7 @@ - (void)didEnterStateSettingUpAppIcon { [weakself sdl_transitionToState:SDLLifecycleStateSettingUpHMI]; } }); - }]; + }]; } - (void)didEnterStateSettingUpHMI { @@ -497,7 +505,7 @@ - (void)didEnterStateReady { [self.delegate audioStreamingState:SDLAudioStreamingStateNotAudible didChangeToState:self.audioStreamingState]; } - // Stop the background task now that setup has completed + // Stop the background task now that setup has completed [self.backgroundTaskManager endBackgroundTask]; } @@ -506,13 +514,13 @@ - (void)didEnterStateUnregistering { __weak typeof(self) weakSelf = self; [self sdl_sendRequest:unregisterRequest - withResponseHandler:^(__kindof SDLRPCRequest *_Nullable request, __kindof SDLRPCResponse *_Nullable response, NSError *_Nullable error) { - if (error != nil || ![response.success boolValue]) { - SDLLogE(@"SDL Error unregistering, we are going to hard disconnect: %@, response: %@", error, response); - } + withResponseHandler:^(__kindof SDLRPCRequest *_Nullable request, __kindof SDLRPCResponse *_Nullable response, NSError *_Nullable error) { + if (error != nil || ![response.success boolValue]) { + SDLLogE(@"SDL Error unregistering, we are going to hard disconnect: %@, response: %@", error, response); + } - [weakSelf sdl_transitionToState:SDLLifecycleStateStopped]; - }]; + [weakSelf sdl_transitionToState:SDLLifecycleStateStopped]; + }]; } @@ -546,13 +554,13 @@ - (void)sdl_sendAppIcon:(nullable SDLFile *)appIcon withCompletion:(void (^)(voi [self sdl_sendRequest:setAppIcon withResponseHandler:^(__kindof SDLRPCRequest *_Nullable request, __kindof SDLRPCResponse *_Nullable response, NSError *_Nullable error) { - if (error != nil) { - SDLLogW(@"Error setting up app icon: %@", error); - } + if (error != nil) { + SDLLogW(@"Error setting up app icon: %@", error); + } - // We've succeeded or failed - completion(); - }]; + // We've succeeded or failed + completion(); + }]; }]; }