summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicoleYarroch <nicole@livio.io>2017-10-04 12:10:53 -0400
committerNicoleYarroch <nicole@livio.io>2017-10-04 12:10:53 -0400
commite1028fe45ecc934decb83f1e632d16168992a96d (patch)
tree05e7365066f5b52cdf42d199b3fc018a6753d2c8
parent32dcb92238092fb304c75bea60a6185efe47dde4 (diff)
downloadsdl_ios-e1028fe45ecc934decb83f1e632d16168992a96d.tar.gz
Debugging
Signed-off-by: NicoleYarroch <nicole@livio.io>
-rw-r--r--SmartDeviceLink/SDLIAPSession.m2
-rw-r--r--SmartDeviceLink/SDLIAPTransport.m182
-rw-r--r--SmartDeviceLink/SDLLifecycleManager.m22
-rw-r--r--SmartDeviceLink/SDLProtocol.m6
-rw-r--r--SmartDeviceLink/SDLProxy.m2
-rw-r--r--SmartDeviceLink/SDLStreamDelegate.m7
-rw-r--r--SmartDeviceLink/SDLStreamingMediaLifecycleManager.m95
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);