diff options
author | NicoleYarroch <nicole@livio.io> | 2017-10-04 12:10:53 -0400 |
---|---|---|
committer | NicoleYarroch <nicole@livio.io> | 2017-10-04 12:10:53 -0400 |
commit | e1028fe45ecc934decb83f1e632d16168992a96d (patch) | |
tree | 05e7365066f5b52cdf42d199b3fc018a6753d2c8 | |
parent | 32dcb92238092fb304c75bea60a6185efe47dde4 (diff) | |
download | sdl_ios-e1028fe45ecc934decb83f1e632d16168992a96d.tar.gz |
Debugging
Signed-off-by: NicoleYarroch <nicole@livio.io>
-rw-r--r-- | SmartDeviceLink/SDLIAPSession.m | 2 | ||||
-rw-r--r-- | SmartDeviceLink/SDLIAPTransport.m | 182 | ||||
-rw-r--r-- | SmartDeviceLink/SDLLifecycleManager.m | 22 | ||||
-rw-r--r-- | SmartDeviceLink/SDLProtocol.m | 6 | ||||
-rw-r--r-- | SmartDeviceLink/SDLProxy.m | 2 | ||||
-rw-r--r-- | SmartDeviceLink/SDLStreamDelegate.m | 7 | ||||
-rw-r--r-- | SmartDeviceLink/SDLStreamingMediaLifecycleManager.m | 95 |
7 files changed, 194 insertions, 122 deletions
diff --git a/SmartDeviceLink/SDLIAPSession.m b/SmartDeviceLink/SDLIAPSession.m index 86132320c..e12e7f687 100644 --- a/SmartDeviceLink/SDLIAPSession.m +++ b/SmartDeviceLink/SDLIAPSession.m @@ -61,12 +61,14 @@ NSTimeInterval const StreamThreadWaitSecs = 1.0; strongSelf.streamDelegate.streamErrorHandler = [self streamErroredHandler]; strongSelf.streamDelegate.streamOpenHandler = [self streamOpenedHandler]; if (self.isDataSession) { + SDLLogV(@"setting up data session"); self.streamDelegate.streamHasSpaceHandler = [self sdl_streamHasSpaceHandler]; // Start I/O event loop processing events in iAP channel self.ioStreamThread = [[NSThread alloc] initWithTarget:self selector:@selector(sdl_accessoryEventLoop) object:nil]; [self.ioStreamThread setName:IOStreamThreadName]; [self.ioStreamThread start]; } else { + SDLLogV(@"setting up control session"); // Set up control session -- no need for its own thread [self startStream:self.easession.outputStream]; [self startStream:self.easession.inputStream]; diff --git a/SmartDeviceLink/SDLIAPTransport.m b/SmartDeviceLink/SDLIAPTransport.m index c077d05fa..3f5277fe2 100644 --- a/SmartDeviceLink/SDLIAPTransport.m +++ b/SmartDeviceLink/SDLIAPTransport.m @@ -42,6 +42,7 @@ int const ProtocolIndexTimeoutSeconds = 20; @implementation SDLIAPTransport - (instancetype)init { + SDLLogV(@"SDLIAPTransport Init"); if (self = [super init]) { _alreadyDestructed = NO; _sessionSetupInProgress = NO; @@ -50,19 +51,59 @@ int const ProtocolIndexTimeoutSeconds = 20; _retryCounter = 0; _protocolIndexTimer = nil; + // Get notifications if an accessory connects in future [self sdl_startEventListening]; - } - SDLLogV(@"SDLIAPTransport Init"); + // Wait for setup to complete before scanning for accessories + } return self; } +#pragma mark - Background Task + +/** + * Starts a background task that allows the app to search for accessories and while the app is in the background. + */ +- (void)sdl_backgroundTaskStart { + if (self.backgroundTaskId != UIBackgroundTaskInvalid) { + return; + } + + if (self.session != nil) { + SDLLogD(@"Data session already in progress. No background task needed."); + return; + } + + SDLLogD(@"Starting background task"); + self.backgroundTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithName:BackgroundTaskName expirationHandler:^{ + SDLLogD(@"Background task expired"); + [self sdl_backgroundTaskEnd]; + }]; +} + +/** + * Cleans up a background task when it is stopped. + */ +- (void)sdl_backgroundTaskEnd { + if (self.backgroundTaskId == UIBackgroundTaskInvalid) { + return; + } + + SDLLogD(@"Ending background task"); + [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTaskId]; + self.backgroundTaskId = UIBackgroundTaskInvalid; +} + +#pragma mark - Notifications -#pragma mark - Notification Subscriptions +#pragma mark Subscription +/** + * Registers for system notifications about connected accessories and the app life cycle. + */ - (void)sdl_startEventListening { - SDLLogV(@"SDLIAPTransport Listening For Events"); + SDLLogV(@"SDLIAPTransport started listening for events"); [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_accessoryConnected:) name:EAAccessoryDidConnectNotification @@ -78,66 +119,73 @@ int const ProtocolIndexTimeoutSeconds = 20; name:UIApplicationWillEnterForegroundNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(sdl_applicationDidEnterBackground:) + name:UIApplicationDidEnterBackgroundNotification + object:nil]; + [[EAAccessoryManager sharedAccessoryManager] registerForLocalNotifications]; } +/** + * Unsubscribes to notifications. + */ - (void)sdl_stopEventListening { - SDLLogV(@"SDLIAPTransport Stopped Listening For Events"); + SDLLogV(@"SDLIAPTransport stopped listening for events"); [[NSNotificationCenter defaultCenter] removeObserver:self]; } -- (void)setSessionSetupInProgress:(BOOL)inProgress{ - _sessionSetupInProgress = inProgress; - if (!inProgress){ - // End the background task here to catch all cases - [self sdl_backgroundTaskEnd]; - } -} - -- (void)sdl_backgroundTaskStart { - if (self.backgroundTaskId != UIBackgroundTaskInvalid) { - return; - } - - self.backgroundTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithName:BackgroundTaskName expirationHandler:^{ - [self sdl_backgroundTaskEnd]; - }]; -} - -- (void)sdl_backgroundTaskEnd { - if (self.backgroundTaskId == UIBackgroundTaskInvalid) { - return; - } - - [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTaskId]; - self.backgroundTaskId = UIBackgroundTaskInvalid; -} -#pragma mark - EAAccessory Notifications +#pragma mark EAAccessory Notifications +/** + * Handles a notification sent by the system when a new accessory has been detected by attempting to connect to the new accessory. + * + * @param notification Contains information about the connected accessory + */ - (void)sdl_accessoryConnected:(NSNotification *)notification { EAAccessory *accessory = notification.userInfo[EAAccessoryKey]; - SDLLogD(@"Accessory Connected (%@), Opening in %0.03fs", notification.userInfo[EAAccessoryKey], self.retryDelay); - [self sdl_backgroundTaskStart]; - self.retryCounter = 0; + double retryDelay = self.retryDelay; + SDLLogD(@"Accessory Connected (%@), Opening in %0.03fs", notification.userInfo[EAAccessoryKey], retryDelay); - [self performSelector:@selector(sdl_connect:) withObject:accessory afterDelay:self.retryDelay]; + if ([[UIApplication sharedApplication] applicationState] != UIApplicationStateActive) { + SDLLogD(@"Accessory connected while app is in background. Starting background task."); + [self sdl_backgroundTaskStart]; + } + + self.retryCounter = 0; + [self performSelector:@selector(sdl_connect:) withObject:accessory afterDelay:retryDelay]; } +/** + * Handles a notification sent by the system when an accessory has been disconnected by cleaning up after the disconnected device. Only check for the data session, the control session is handled separately + * + * @param notification Contains information about the connected accessory + */ - (void)sdl_accessoryDisconnected:(NSNotification *)notification { - // Only check for the data session, the control session is handled separately EAAccessory *accessory = [notification.userInfo objectForKey:EAAccessoryKey]; if (accessory.connectionID != self.session.accessory.connectionID) { - SDLLogD(@"Accessory Disconnected Event (%@)", accessory); + SDLLogD(@"Accessory Disconnected Event (%@)", accessory); } if ([accessory.serialNumber isEqualToString:self.session.accessory.serialNumber]) { + SDLLogD(@"Connected accessory disconnected event"); + self.retryCounter = 0; self.sessionSetupInProgress = NO; [self disconnect]; [self.delegate onTransportDisconnected]; } } +#pragma mark App Lifecycle Notifications + +/** + * Handles a notification sent by the system when the app enters the foreground. + * + * If the app is still searching for an accessory, a background task will be started so the app can still search for and/or connect with an accessory while it is in the background. + * + * @param notification Notification + */ - (void)sdl_applicationWillEnterForeground:(NSNotification *)notification { SDLLogV(@"App foregrounded, attempting connection"); [self sdl_backgroundTaskEnd]; @@ -145,6 +193,15 @@ int const ProtocolIndexTimeoutSeconds = 20; [self connect]; } +/** + * Handles a notification sent by the system when the app enters the background. + * + * @param notification Notification + */ +- (void)sdl_applicationDidEnterBackground:(NSNotification *)notification { + SDLLogV(@"App backgrounded, starting background task"); + [self sdl_backgroundTaskStart]; +} #pragma mark - Stream Lifecycle @@ -153,9 +210,9 @@ int const ProtocolIndexTimeoutSeconds = 20; } /** - Start the connection process by connecting to a specific accessory, or if none is specified, to scan for an accessory. - - @param accessory The accessory to attempt connection with or nil to scan for accessories. + * Starts the process to connect to an accessory. If no accessory specified, scans for a valid accessory. + * + * @param accessory The accessory to attempt connection with or nil to scan for accessories. */ - (void)sdl_connect:(nullable EAAccessory *)accessory { if (!self.session && !self.sessionSetupInProgress) { @@ -172,10 +229,12 @@ int const ProtocolIndexTimeoutSeconds = 20; } } +/** + * Cleans up after a disconnected accessory by closing any open input streams. + */ - (void)disconnect { - SDLLogD(@"IAP disconnecting data session"); - // Stop event listening here so that even if the transport is disconnected by the proxy - // we unregister for accessory local notifications + SDLLogD(@"Disconnecting IAP data session"); + // Stop event listening here so that even if the transport is disconnected by the proxy we unregister for accessory local notifications [self sdl_stopEventListening]; if (self.controlSession != nil) { [self.controlSession stop]; @@ -192,14 +251,14 @@ int const ProtocolIndexTimeoutSeconds = 20; #pragma mark - Creating Session Streams /** - Attempt to connect an accessory using the control or legacy protocols, then return whether or not we've generated an IAP session. - - @param accessory The accessory to attempt a connection with - @return Whether or not we succesfully created a session. + * Attempt to connect an accessory using the control or legacy protocols, then return whether or not we've generated an IAP session. + * + * @param accessory The accessory to attempt a connection with + * @return Whether or not we succesfully created a session. */ - (BOOL)sdl_connectAccessory:(EAAccessory *)accessory { BOOL connecting = NO; - + if ([accessory supportsProtocol:MultiSessionProtocolString] && SDL_SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"9")) { [self sdl_createIAPDataSessionWithAccessory:accessory forProtocol:MultiSessionProtocolString]; connecting = YES; @@ -210,20 +269,21 @@ int const ProtocolIndexTimeoutSeconds = 20; [self sdl_createIAPDataSessionWithAccessory:accessory forProtocol:LegacyProtocolString]; connecting = YES; } - + return connecting; } /** - Attept to establish a session with an accessory, or if nil is passed, to scan for one. - - @param accessory The accessory to try to establish a session with, or nil to scan all connected accessories. + * Attept to establish a session with an accessory, or if nil is passed, to scan for one. + * + * @param accessory The accessory to try to establish a session with, or nil to scan all connected accessories. */ - (void)sdl_establishSessionWithAccessory:(nullable EAAccessory *)accessory { SDLLogD(@"Attempting to connect"); if (self.retryCounter < CreateSessionRetries) { // We should be attempting to connect self.retryCounter++; + EAAccessory *sdlAccessory = accessory; // If we are being called from sdl_connectAccessory, the EAAccessoryDidConnectNotification will contain the SDL accessory to connect to and we can connect without searching the accessory manager's connected accessory list. Otherwise, we fall through to a search. if (sdlAccessory != nil && [self sdl_connectAccessory:sdlAccessory]) { @@ -252,7 +312,7 @@ int const ProtocolIndexTimeoutSeconds = 20; } - (void)sdl_createIAPControlSessionWithAccessory:(EAAccessory *)accessory { - SDLLogD(@"Starting IAP control session (%@)", accessory); + SDLLogD(@"Starting IAP control session"); self.controlSession = [[SDLIAPSession alloc] initWithAccessory:accessory forProtocol:ControlProtocolString]; if (self.controlSession) { @@ -276,14 +336,15 @@ int const ProtocolIndexTimeoutSeconds = 20; }; self.protocolIndexTimer.elapsedBlock = elapsedBlock; - SDLStreamDelegate *controlStreamDelegate = [SDLStreamDelegate new]; - self.controlSession.streamDelegate = controlStreamDelegate; + SDLLogD(@"Setting delegates for control stream"); + SDLStreamDelegate *controlStreamDelegate = [[SDLStreamDelegate alloc] init]; controlStreamDelegate.streamHasBytesHandler = [self sdl_controlStreamHasBytesHandlerForAccessory:accessory]; controlStreamDelegate.streamEndHandler = [self sdl_controlStreamEndedHandler]; controlStreamDelegate.streamErrorHandler = [self sdl_controlStreamErroredHandler]; + self.controlSession.streamDelegate = controlStreamDelegate; if (![self.controlSession start]) { - SDLLogW(@"Control session failed to setup (%@)", accessory); + SDLLogW(@"Control session failed to setup"); self.controlSession.streamDelegate = nil; self.controlSession = nil; [self sdl_retryEstablishSession]; @@ -326,7 +387,9 @@ int const ProtocolIndexTimeoutSeconds = 20; self.session.delegate = nil; self.session = nil; } - // No accessory to use this time, search connected accessories + + // Search connected accessories + self.retryCounter = 0; [self sdl_connect:nil]; } @@ -402,6 +465,7 @@ int const ProtocolIndexTimeoutSeconds = 20; uint8_t buf[1]; NSUInteger len = [istream read:buf maxLength:1]; if (len <= 0) { + SDLLogV(@"Nothing read from input stream"); return; } @@ -420,6 +484,7 @@ int const ProtocolIndexTimeoutSeconds = 20; if (accessory.isConnected) { dispatch_async(dispatch_get_main_queue(), ^{ + self.retryCounter = 0; [strongSelf sdl_createIAPDataSessionWithAccessory:accessory forProtocol:indexedProtocolString]; }); } @@ -562,3 +627,4 @@ int const ProtocolIndexTimeoutSeconds = 20; @end NS_ASSUME_NONNULL_END + diff --git a/SmartDeviceLink/SDLLifecycleManager.m b/SmartDeviceLink/SDLLifecycleManager.m index 6a70e6675..759a576d5 100644 --- a/SmartDeviceLink/SDLLifecycleManager.m +++ b/SmartDeviceLink/SDLLifecycleManager.m @@ -71,7 +71,6 @@ SDLLifecycleState *const SDLLifecycleStateReady = @"Ready"; // Private properties @property (copy, nonatomic) SDLManagerReadyBlock readyHandler; -@property (assign, nonatomic) BOOL firstHMINonNoneOccurred; @end @@ -105,7 +104,6 @@ SDLLifecycleState *const SDLLifecycleStateReady = @"Ready"; _notificationDispatcher = [[SDLNotificationDispatcher alloc] init]; _responseDispatcher = [[SDLResponseDispatcher alloc] initWithNotificationDispatcher:_notificationDispatcher]; _registerResponse = nil; - _firstHMINonNoneOccurred = NO; // Managers _fileManager = [[SDLFileManager alloc] initWithConnectionManager:self]; @@ -184,6 +182,10 @@ SDLLifecycleState *const SDLLifecycleStateReady = @"Ready"; self.proxy = [SDLProxyFactory buildSDLProxyWithListener:self.notificationDispatcher]; } #pragma clang diagnostic pop + + if (self.streamManager != nil) { + [self.streamManager startWithProtocol:self.proxy.protocol]; + } } - (void)didEnterStateStopped { @@ -208,7 +210,6 @@ SDLLifecycleState *const SDLLifecycleStateReady = @"Ready"; self.hmiLevel = nil; self.audioStreamingState = nil; self.systemContext = nil; - self.proxy = nil; // Due to a race condition internally with EAStream, we cannot immediately attempt to restart the proxy, as we will randomly crash. @@ -442,16 +443,6 @@ SDLLifecycleState *const SDLLifecycleStateReady = @"Ready"; return YES; } -- (void)sdl_onFirstHMINonNone { - // If we are a nav / projection app and desire to stream, we need to be in HMI background, limited, or full and perform additional setup when that occurs - if (self.streamManager == nil) { - return; - } - - [self.streamManager startWithProtocol:self.proxy.protocol]; -} - - #pragma mark SDL notification observers - (void)transportDidConnect { @@ -484,11 +475,6 @@ SDLLifecycleState *const SDLLifecycleStateReady = @"Ready"; self.systemContext = hmiStatusNotification.systemContext; SDLLogD(@"HMI level changed from %@ to %@", oldHMILevel, self.hmiLevel); - - if (!self.firstHMINonNoneOccurred && ![self.hmiLevel isEqualToEnum:SDLHMILevelNone]) { - self.firstHMINonNoneOccurred = YES; - [self sdl_onFirstHMINonNone]; - } if ([self.lifecycleStateMachine isCurrentState:SDLLifecycleStateSettingUpHMI]) { [self.lifecycleStateMachine transitionToState:SDLLifecycleStateReady]; diff --git a/SmartDeviceLink/SDLProtocol.m b/SmartDeviceLink/SDLProtocol.m index 186226414..cf5bd48da 100644 --- a/SmartDeviceLink/SDLProtocol.m +++ b/SmartDeviceLink/SDLProtocol.m @@ -403,6 +403,8 @@ NS_ASSUME_NONNULL_BEGIN // TODO: This is a v4 packet (create new delegate methods) - (void)handleProtocolStartServiceACKMessage:(SDLProtocolMessage *)startServiceACK { + SDLLogD(@"handleProtocolStartServiceACKMessage (%@)", startServiceACK); + // V5 Packet if (startServiceACK.header.version >= 5) { switch (startServiceACK.header.serviceType) { @@ -436,9 +438,13 @@ NS_ASSUME_NONNULL_BEGIN self.serviceHeaders[@(startServiceACK.header.serviceType)] = [startServiceACK.header copy]; // Pass along to all the listeners + SDLLogD(@"Listeners (%@)", self.protocolDelegateTable.allObjects); for (id<SDLProtocolListener> listener in self.protocolDelegateTable.allObjects) { if ([listener respondsToSelector:@selector(handleProtocolStartServiceACKMessage:)]) { + SDLLogD(@"responder (%@)", listener); [listener handleProtocolStartServiceACKMessage:startServiceACK]; + } else { + SDLLogD(@"no responder (%@)", listener); } } } diff --git a/SmartDeviceLink/SDLProxy.m b/SmartDeviceLink/SDLProxy.m index ef5eb9857..d7e7eb60a 100644 --- a/SmartDeviceLink/SDLProxy.m +++ b/SmartDeviceLink/SDLProxy.m @@ -42,7 +42,7 @@ typedef void (^URLSessionTaskCompletionHandler)(NSData *data, NSURLResponse *res typedef void (^URLSessionDownloadTaskCompletionHandler)(NSURL *location, NSURLResponse *response, NSError *error); NSString *const SDLProxyVersion = @"4.6.1"; -const float StartSessionTime = 10.0; +const float StartSessionTime = 100.0; const float NotifyProxyClosedDelay = 0.1; const int PoliciesCorrelationId = 65535; static float DefaultConnectionTimeout = 45.0; diff --git a/SmartDeviceLink/SDLStreamDelegate.m b/SmartDeviceLink/SDLStreamDelegate.m index 11bba6e5e..1ffe836e6 100644 --- a/SmartDeviceLink/SDLStreamDelegate.m +++ b/SmartDeviceLink/SDLStreamDelegate.m @@ -17,6 +17,8 @@ NS_ASSUME_NONNULL_BEGIN @implementation SDLStreamDelegate - (instancetype)init { + SDLLogV(@"Initing SDLStreamDelegate"); + self = [super init]; if (self) { _streamOpenHandler = defaultStreamOpenHandler; @@ -25,11 +27,16 @@ NS_ASSUME_NONNULL_BEGIN _streamErrorHandler = defaultStreamErrorHandler; _streamEndHandler = defaultStreamErrorHandler; + SDLLogV(@"Creating com.sdl.streamdelegate.input"); _input_stream_queue = dispatch_queue_create("com.sdl.streamdelegate.input", DISPATCH_QUEUE_SERIAL); } return self; } +-(void)dealloc { + SDLLogV(@"Dealloc SDLStreamDelegate"); +} + - (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode { switch (eventCode) { case NSStreamEventOpenCompleted: { diff --git a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m index 0d7ca7a01..c623bc7a8 100644 --- a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m +++ b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m @@ -145,49 +145,15 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N } - (void)startWithProtocol:(SDLAbstractProtocol *)protocol { + SDLLogV(@"Streaming media LCM start with protocol called: \(%@) hmi: %@", protocol, self.hmiLevel); _protocol = protocol; if (![self.protocol.protocolDelegateTable containsObject:self]) { + SDLLogV(@"Adding protocol to table"); [self.protocol.protocolDelegateTable addObject:self]; + } else { + SDLLogV(@"Not adding protocol to table"); } - - SDLLogD(@"Requesting video capabilities"); - __weak typeof(self) weakSelf = self; - [self sdl_requestVideoCapabilities:^(SDLVideoStreamingCapability * _Nullable capability) { - SDLLogD(@"Received video capability response"); - SDLLogV(@"%@", capability); - if (capability != nil) { - // If we got a response, get our preferred formats and resolutions - weakSelf.preferredFormats = capability.supportedFormats; - weakSelf.preferredResolutions = @[capability.preferredResolution]; - - if (weakSelf.dataSource != nil) { - SDLLogV(@"Calling data source for modified preferred formats and resolutions"); - weakSelf.preferredFormats = [weakSelf.dataSource preferredVideoFormatOrderFromHeadUnitPreferredOrder:weakSelf.preferredFormats]; - weakSelf.preferredResolutions = [weakSelf.dataSource resolutionFromHeadUnitPreferredResolution:weakSelf.preferredResolutions.firstObject]; - } - - if (weakSelf.hapticInterface != nil) { - weakSelf.hapticInterface.enableHapticDataRequests = capability.hapticSpatialDataSupported.boolValue; - } - - SDLLogD(@"Got specialized video capabilites, preferred formats: %@, resolutions: %@ haptics enabled %@", weakSelf.preferredFormats, weakSelf.preferredResolutions, (capability.hapticSpatialDataSupported.boolValue ? @"YES" : @"NO")); - } else { - // If we can't get capabilities, we're assuming it's H264 RAW at whatever the display capabilities said in the RAIR. We also aren't going to call the data source because they have no options. - SDLVideoStreamingFormat *format = [[SDLVideoStreamingFormat alloc] initWithCodec:SDLVideoStreamingCodecH264 protocol:SDLVideoStreamingProtocolRAW]; - SDLImageResolution *resolution = [[SDLImageResolution alloc] initWithWidth:weakSelf.screenSize.width height:weakSelf.screenSize.height]; - weakSelf.preferredFormats = @[format]; - weakSelf.preferredResolutions = @[resolution]; - - if (weakSelf.hapticInterface != nil) { - weakSelf.hapticInterface.enableHapticDataRequests = NO; - } - - SDLLogD(@"Using generic video capabilites, preferred formats: %@, resolutions: %@, haptics disabled", weakSelf.preferredFormats, weakSelf.preferredResolutions); - } - - [weakSelf sdl_startVideoSession]; - }]; } - (void)stop { @@ -196,6 +162,7 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N [self sdl_stopVideoSession]; self.restartVideoStream = NO; + [self.audioStreamStateMachine transitionToState:SDLAudioStreamStateStopped]; [self.videoStreamStateMachine transitionToState:SDLVideoStreamStateStopped]; } @@ -344,7 +311,42 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N SDLLogD(@"Video stream starting"); self.restartVideoStream = NO; - [self sdl_sendVideoStartService]; + __weak typeof(self) weakSelf = self; + [self sdl_requestVideoCapabilities:^(SDLVideoStreamingCapability * _Nullable capability) { + SDLLogD(@"Received video capability response"); + SDLLogV(@"%@", capability); + if (capability != nil) { + // If we got a response, get our preferred formats and resolutions + weakSelf.preferredFormats = capability.supportedFormats; + weakSelf.preferredResolutions = @[capability.preferredResolution]; + + if (weakSelf.dataSource != nil) { + SDLLogV(@"Calling data source for modified preferred formats and resolutions"); + weakSelf.preferredFormats = [weakSelf.dataSource preferredVideoFormatOrderFromHeadUnitPreferredOrder:weakSelf.preferredFormats]; + weakSelf.preferredResolutions = [weakSelf.dataSource resolutionFromHeadUnitPreferredResolution:weakSelf.preferredResolutions.firstObject]; + } + + if (weakSelf.hapticInterface != nil) { + weakSelf.hapticInterface.enableHapticDataRequests = capability.hapticSpatialDataSupported.boolValue; + } + + SDLLogD(@"Got specialized video capabilites, preferred formats: %@, resolutions: %@ haptics enabled %@", weakSelf.preferredFormats, weakSelf.preferredResolutions, (capability.hapticSpatialDataSupported.boolValue ? @"YES" : @"NO")); + } else { + // If we can't get capabilities, we're assuming it's H264 RAW at whatever the display capabilities said in the RAIR. We also aren't going to call the data source because they have no options. + SDLVideoStreamingFormat *format = [[SDLVideoStreamingFormat alloc] initWithCodec:SDLVideoStreamingCodecH264 protocol:SDLVideoStreamingProtocolRAW]; + SDLImageResolution *resolution = [[SDLImageResolution alloc] initWithWidth:weakSelf.screenSize.width height:weakSelf.screenSize.height]; + weakSelf.preferredFormats = @[format]; + weakSelf.preferredResolutions = @[resolution]; + + if (weakSelf.hapticInterface != nil) { + weakSelf.hapticInterface.enableHapticDataRequests = NO; + } + + SDLLogD(@"Using generic video capabilites, preferred formats: %@, resolutions: %@, haptics disabled", weakSelf.preferredFormats, weakSelf.preferredResolutions); + } + + [weakSelf sdl_startVideoSession]; + }]; } - (void)didEnterStateVideoStreamReady { @@ -590,11 +592,11 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N SDLLogD(@"HMI level changed from level %@ to level %@", self.hmiLevel, hmiStatus.hmiLevel); self.hmiLevel = hmiStatus.hmiLevel; - if (self.isHmiStateVideoStreamCapable) { - [self sdl_startVideoSession]; - } else { - [self sdl_stopVideoSession]; - } +// if (self.isHmiStateVideoStreamCapable) { +// [self sdl_startVideoSession]; +// } else { +// [self sdl_stopVideoSession]; +// } if (self.isHmiStateAudioStreamCapable) { [self sdl_startAudioSession]; @@ -609,20 +611,23 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N - (void)sdl_startVideoSession { SDLLogV(@"Attempting to start video session"); if (!self.isStreamingSupported) { + SDLLogW(@"AAA video streaming not supported"); return; } if (self.shouldRestartVideoStream && [self.videoStreamStateMachine isCurrentState:SDLVideoStreamStateReady]) { [self sdl_stopVideoSession]; + SDLLogW(@"AAA Stopping video session"); return; } if ([self.videoStreamStateMachine isCurrentState:SDLVideoStreamStateStopped] && self.isHmiStateVideoStreamCapable && self.isAppStateVideoStreamCapable) { + SDLLogV(@"AAA videoStreamStateMachine transitioning to SDLVideoStreamStateStarting"); [self.videoStreamStateMachine transitionToState:SDLVideoStreamStateStarting]; } else { - SDLLogE(@"Unable to start video stream\n" + SDLLogE(@"AAA Unable to start video stream\n" "State: %@\n" "HMI state: %@\n" "App state: %@", self.videoStreamStateMachine.currentState, self.hmiLevel, self.appStateMachine.currentState); |