summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Fischer <joeljfischer@gmail.com>2019-10-02 11:35:13 -0400
committerJoel Fischer <joeljfischer@gmail.com>2019-10-02 11:35:13 -0400
commit01ed70a23acc359b496144e3a27f527b6a85b9b7 (patch)
tree308b2743dbf94ff2e1e1053aa307b6509ae38b8b
parentf907a2d8c67805b79196320b91d6b3dddd4ae302 (diff)
downloadsdl_ios-01ed70a23acc359b496144e3a27f527b6a85b9b7.tar.gz
Fix managers no longer working due to display updates
* Fix example app deprecation warnings * Stylistic fixes * Text and Graphic / Soft Button managers now start when the screen manager starts, which allows them to try subscribing to DISPLAYS once the connection is established * Add additional pragma categories for system capability manager * Permit subscribing to DISPLAYS even if on systems < 5.1.0 because updates through SetDisplayLayout route through that subscription now
-rw-r--r--Example Apps/Example ObjC/MenuManager.m2
-rw-r--r--Example Apps/Example Swift/MenuManager.swift2
-rw-r--r--SmartDeviceLink/SDLLifecycleManager.m1
-rw-r--r--SmartDeviceLink/SDLScreenManager.m2
-rw-r--r--SmartDeviceLink/SDLSoftButtonManager.h3
-rw-r--r--SmartDeviceLink/SDLSoftButtonManager.m7
-rw-r--r--SmartDeviceLink/SDLSystemCapabilityManager.m248
-rw-r--r--SmartDeviceLink/SDLTextAndGraphicManager.h3
-rw-r--r--SmartDeviceLink/SDLTextAndGraphicManager.m20
-rw-r--r--SmartDeviceLink/SDLWindowCapability+ShowManagerExtensions.h4
-rw-r--r--SmartDeviceLink/SDLWindowCapability+ShowManagerExtensions.m4
-rw-r--r--SmartDeviceLinkTests/DevAPISpecs/SDLFileManagerSpec.m2
-rw-r--r--SmartDeviceLinkTests/DevAPISpecs/SDLSoftButtonManagerSpec.m1
-rw-r--r--SmartDeviceLinkTests/DevAPISpecs/SDLTextAndGraphicManagerSpec.m23
-rw-r--r--SmartDeviceLinkTests/SDLAsynchronousRPCOperationSpec.m2
-rw-r--r--SmartDeviceLinkTests/SDLSystemCapabilityManagerSpec.m1
16 files changed, 194 insertions, 131 deletions
diff --git a/Example Apps/Example ObjC/MenuManager.m b/Example Apps/Example ObjC/MenuManager.m
index 44adcc223..4882ab7a8 100644
--- a/Example Apps/Example ObjC/MenuManager.m
+++ b/Example Apps/Example ObjC/MenuManager.m
@@ -141,7 +141,7 @@ NS_ASSUME_NONNULL_BEGIN
+ (SDLMenuCell *)sdlex_scrollableMessageMenuCellWithManager:(SDLManager *)manager {
return [[SDLMenuCell alloc] initWithTitle:ACScrollableMessageMenuName icon:nil voiceCommands:@[ACScrollableMessageMenuName] handler:^(SDLTriggerSource _Nonnull triggerSource) {
- SDLScrollableMessage *messageRPC = [[SDLScrollableMessage alloc] initWithMessage:@"This is a scrollable message\nIt can contain many lines" timeout:10000 softButtons:nil];
+ SDLScrollableMessage *messageRPC = [[SDLScrollableMessage alloc] initWithMessage:@"This is a scrollable message\nIt can contain many lines"];
[manager sendRequest:messageRPC];
}];
}
diff --git a/Example Apps/Example Swift/MenuManager.swift b/Example Apps/Example Swift/MenuManager.swift
index 7cd5dd9de..e74867ccc 100644
--- a/Example Apps/Example Swift/MenuManager.swift
+++ b/Example Apps/Example Swift/MenuManager.swift
@@ -186,7 +186,7 @@ private extension MenuManager {
private class func scrollableMessageMenuCell(with manager: SDLManager) -> SDLMenuCell {
return SDLMenuCell(title: ACScrollableMessageMenuName, icon: nil, voiceCommands: [ACScrollableMessageMenuName], handler: { _ in
- let scrollableMessage = SDLScrollableMessage(message: "This is a scrollable message\nIt can contain many lines", timeout: 10000, softButtons: nil)
+ let scrollableMessage = SDLScrollableMessage(message: "This is a scrollable message\nIt can contain many lines")
manager.send(scrollableMessage)
})
}
diff --git a/SmartDeviceLink/SDLLifecycleManager.m b/SmartDeviceLink/SDLLifecycleManager.m
index 0de7f1a37..bdeee35f1 100644
--- a/SmartDeviceLink/SDLLifecycleManager.m
+++ b/SmartDeviceLink/SDLLifecycleManager.m
@@ -142,7 +142,6 @@ NSString *const BackgroundTaskTransportName = @"com.sdl.transport.backgroundTask
_systemCapabilityManager = [[SDLSystemCapabilityManager alloc] initWithConnectionManager:self];
_screenManager = [[SDLScreenManager alloc] initWithConnectionManager:self fileManager:_fileManager systemCapabilityManager:_systemCapabilityManager];
-
if ([configuration.lifecycleConfig.appType isEqualToEnum:SDLAppHMITypeNavigation] ||
[configuration.lifecycleConfig.appType isEqualToEnum:SDLAppHMITypeProjection] ||
[configuration.lifecycleConfig.additionalAppTypes containsObject:SDLAppHMITypeNavigation] ||
diff --git a/SmartDeviceLink/SDLScreenManager.m b/SmartDeviceLink/SDLScreenManager.m
index 5ea131e30..ea9ea5676 100644
--- a/SmartDeviceLink/SDLScreenManager.m
+++ b/SmartDeviceLink/SDLScreenManager.m
@@ -50,6 +50,8 @@ NS_ASSUME_NONNULL_BEGIN
}
- (void)startWithCompletionHandler:(void (^)(NSError * _Nullable))handler {
+ [self.textAndGraphicManager start];
+ [self.softButtonManager start];
[self.choiceSetManager start];
handler(nil);
diff --git a/SmartDeviceLink/SDLSoftButtonManager.h b/SmartDeviceLink/SDLSoftButtonManager.h
index 04678200c..d7a6b4506 100644
--- a/SmartDeviceLink/SDLSoftButtonManager.h
+++ b/SmartDeviceLink/SDLSoftButtonManager.h
@@ -53,6 +53,9 @@ typedef void(^SDLSoftButtonUpdateCompletionHandler)(NSError *__nullable error);
*/
- (instancetype)initWithConnectionManager:(id<SDLConnectionManagerType>)connectionManager fileManager:(SDLFileManager *)fileManager systemCapabilityManager:(SDLSystemCapabilityManager *)systemCapabilityManager;
+/// Starts the manager. This method is used internally.
+- (void)start;
+
/**
* Stops the manager. This method is used internally.
*/
diff --git a/SmartDeviceLink/SDLSoftButtonManager.m b/SmartDeviceLink/SDLSoftButtonManager.m
index 53de9792a..f6320d645 100644
--- a/SmartDeviceLink/SDLSoftButtonManager.m
+++ b/SmartDeviceLink/SDLSoftButtonManager.m
@@ -68,12 +68,15 @@ NS_ASSUME_NONNULL_BEGIN
_transactionQueue = [self sdl_newTransactionQueue];
_batchQueue = [NSMutableArray array];
- [_systemCapabilityManager subscribeToCapabilityType:SDLSystemCapabilityTypeDisplays withObserver:self selector:@selector(sdl_displayCapabilityUpdate:)];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_hmiStatusNotification:) name:SDLDidChangeHMIStatusNotification object:nil];
return self;
}
+- (void)start {
+ [_systemCapabilityManager subscribeToCapabilityType:SDLSystemCapabilityTypeDisplays withObserver:self selector:@selector(sdl_displayCapabilityDidUpdate:)];
+}
+
- (void)stop {
_softButtonObjects = @[];
_currentMainField1 = nil;
@@ -191,7 +194,7 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - RPC Responses
-- (void)sdl_displayCapabilityUpdate:(SDLSystemCapability *)systemCapability {
+- (void)sdl_displayCapabilityDidUpdate:(SDLSystemCapability *)systemCapability {
_windowCapability = systemCapability.displayCapabilities[0].windowCapabilities[0];
// Auto-send an updated Show to account for changes to the capabilities
if (self.softButtonObjects.count > 0) {
diff --git a/SmartDeviceLink/SDLSystemCapabilityManager.m b/SmartDeviceLink/SDLSystemCapabilityManager.m
index d0be4ffc4..cf1a9e19a 100644
--- a/SmartDeviceLink/SDLSystemCapabilityManager.m
+++ b/SmartDeviceLink/SDLSystemCapabilityManager.m
@@ -194,7 +194,7 @@ typedef NSString * SDLServiceID;
// call the observers in case the new display capability list is created from deprecated types
SDLSystemCapability *systemCapability = [[SDLSystemCapability alloc] initWithDisplayCapabilities:self.displays];
- [self sdl_callSaveHandlerForCapability:systemCapability andReturnWithValue:YES handler:nil];
+ [self sdl_callObserversForCapabilityUpdate:systemCapability handler:nil];
}
/**
@@ -208,17 +208,20 @@ typedef NSString * SDLServiceID;
SDLSetDisplayLayoutResponse *response = (SDLSetDisplayLayoutResponse *)notification.response;
#pragma clang diagnostic pop
if (!response.success.boolValue) { return; }
-
+
+ // If we've received a display capability update then we should not convert our deprecated display capabilities and we should just return
+ if (!self.shouldConvertDeprecatedDisplayCapabilities) { return; }
+
self.displayCapabilities = response.displayCapabilities;
self.buttonCapabilities = response.buttonCapabilities;
self.softButtonCapabilities = response.softButtonCapabilities;
self.presetBankCapabilities = response.presetBankCapabilities;
-
+
self.displays = [self sdl_createDisplayCapabilityListFromSetDisplayLayoutResponse:response];
- // call the observers in case the new display capability list is created from deprecated types
+ // Call the observers in case the new display capability list is created from deprecated types
SDLSystemCapability *systemCapability = [[SDLSystemCapability alloc] initWithDisplayCapabilities:self.displays];
- [self sdl_callSaveHandlerForCapability:systemCapability andReturnWithValue:YES handler:nil];
+ [self sdl_callObserversForCapabilityUpdate:systemCapability handler:nil];
}
@@ -284,6 +287,25 @@ typedef NSString * SDLServiceID;
return [self windowCapabilityWithWindowID:SDLPredefinedWindowsDefaultWindow];
}
+#pragma mark Convert Deprecated to New
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated"
+/// Convert the capabilities from a `RegisterAppInterfaceResponse` into a new-style `DisplayCapability` for the main display.
+/// @param rpc The `RegisterAppInterfaceResponse` RPC
+- (NSArray<SDLDisplayCapability *> *)sdl_createDisplayCapabilityListFromRegisterResponse:(SDLRegisterAppInterfaceResponse *)rpc {
+ return [self sdl_createDisplayCapabilityListFromDeprecatedDisplayCapabilities:rpc.displayCapabilities buttons:rpc.buttonCapabilities softButtons:rpc.softButtonCapabilities];
+}
+
+- (NSArray<SDLDisplayCapability *> *)sdl_createDisplayCapabilityListFromSetDisplayLayoutResponse:(SDLSetDisplayLayoutResponse *)rpc {
+ return [self sdl_createDisplayCapabilityListFromDeprecatedDisplayCapabilities:rpc.displayCapabilities buttons:rpc.buttonCapabilities softButtons:rpc.softButtonCapabilities];
+}
+#pragma clang diagnostic pop
+
+/// Creates a "new-style" display capability from the "old-style" `SDLDisplayCapabilities` object and other "old-style" objects that were returned in `RegisterAppInterfaceResponse` and `SetDisplayLayoutResponse`
+/// @param display The old-style `SDLDisplayCapabilities` object to convert
+/// @param buttons The old-style `SDLButtonCapabilities` object to convert
+/// @param softButtons The old-style `SDLSoftButtonCapabilities` to convert
- (NSArray<SDLDisplayCapability *> *)sdl_createDisplayCapabilityListFromDeprecatedDisplayCapabilities:(SDLDisplayCapabilities *)display buttons:(NSArray<SDLButtonCapabilities *> *)buttons softButtons:(NSArray<SDLSoftButtonCapabilities *> *)softButtons {
// Based on deprecated Display capabilities we don't know if widgets are supported. The default MAIN window is the only window we know is supported, so it's the only one we will expose.
SDLWindowTypeCapabilities *windowTypeCapabilities = [[SDLWindowTypeCapabilities alloc] initWithType:SDLWindowTypeMain maximumNumberOfWindows:1];
@@ -293,26 +315,25 @@ typedef NSString * SDLServiceID;
#pragma clang diagnostic pop
SDLDisplayCapability *displayCapability = [[SDLDisplayCapability alloc] initWithDisplayName:displayName];
displayCapability.windowTypeSupported = @[windowTypeCapabilities];
-
+
// Create a window capability object for the default MAIN window
SDLWindowCapability *defaultWindowCapability = [[SDLWindowCapability alloc] init];
defaultWindowCapability.windowID = @(SDLPredefinedWindowsDefaultWindow);
defaultWindowCapability.buttonCapabilities = [buttons copy];
defaultWindowCapability.softButtonCapabilities = [softButtons copy];
-
+
// return if display capabilities don't exist.
if (display == nil) {
displayCapability.windowCapabilities = @[defaultWindowCapability];
return @[displayCapability];
}
-
+
// Copy all available display capability properties
defaultWindowCapability.templatesAvailable = [display.templatesAvailable copy];
defaultWindowCapability.numCustomPresetsAvailable = [display.numCustomPresetsAvailable copy];
defaultWindowCapability.textFields = [display.textFields copy];
defaultWindowCapability.imageFields = [display.imageFields copy];
-
-
+
/*
The description from the mobile API to "graphicSupported:
> The display's persistent screen supports referencing a static or dynamic image.
@@ -323,27 +344,21 @@ typedef NSString * SDLServiceID;
} else {
defaultWindowCapability.imageTypeSupported = @[SDLImageTypeStatic];
}
-
+
displayCapability.windowCapabilities = @[defaultWindowCapability];
return @[displayCapability];
}
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated"
-- (NSArray<SDLDisplayCapability *> *)sdl_createDisplayCapabilityListFromRegisterResponse:(SDLRegisterAppInterfaceResponse *)rpc {
- return [self sdl_createDisplayCapabilityListFromDeprecatedDisplayCapabilities:rpc.displayCapabilities buttons:rpc.buttonCapabilities softButtons:rpc.softButtonCapabilities];
-}
-
-- (NSArray<SDLDisplayCapability *> *)sdl_createDisplayCapabilityListFromSetDisplayLayoutResponse:(SDLSetDisplayLayoutResponse *)rpc {
- return [self sdl_createDisplayCapabilityListFromDeprecatedDisplayCapabilities:rpc.displayCapabilities buttons:rpc.buttonCapabilities softButtons:rpc.softButtonCapabilities];
-}
-#pragma clang diagnostic pop
+#pragma mark Convert New to Deprecated
+/// Convert from a WindowCapability (should be the main display's main window capability) to the deprecated old-style DisplayCapabilities
+/// @param displayName The display name of the display to be converted
+/// @param windowCapability The window capability to be converted
- (SDLDisplayCapabilities *)sdl_createDeprecatedDisplayCapabilitiesWithDisplayName:(NSString *)displayName windowCapability:(SDLWindowCapability *)windowCapability {
SDLDisplayCapabilities *convertedCapabilities = [[SDLDisplayCapabilities alloc] init];
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated"
- convertedCapabilities.displayType = SDLDisplayTypeGeneric; //deprecated but it is mandatory...
+ convertedCapabilities.displayType = SDLDisplayTypeGeneric; // deprecated but it is mandatory
#pragma clang diagnostic pop
convertedCapabilities.displayName = displayName;
convertedCapabilities.textFields = [windowCapability.textFields copy];
@@ -356,11 +371,10 @@ typedef NSString * SDLServiceID;
return convertedCapabilities;
}
+/// Update the internal deprecated display capability methods with new values based on the current value of the default main window capability and the primary display
- (void)sdl_updateDeprecatedDisplayCapabilities {
SDLWindowCapability *defaultMainWindowCapabilities = self.defaultMainWindowCapability;
- NSArray<SDLDisplayCapability *> *displayCapabilityList = self.displays;
-
- if (displayCapabilityList == nil || displayCapabilityList.count == 0) {
+ if (self.displays.count == 0) {
return;
}
@@ -370,46 +384,7 @@ typedef NSString * SDLServiceID;
self.softButtonCapabilities = defaultMainWindowCapabilities.softButtonCapabilities;
}
-- (void)sdl_saveDisplayCapabilityListUpdate:(NSArray<SDLDisplayCapability *> *)newCapabilities {
- NSArray<SDLDisplayCapability *> *oldCapabilities = self.displays;
-
- if (oldCapabilities == nil) {
- self.displays = newCapabilities;
- [self sdl_updateDeprecatedDisplayCapabilities];
- return;
- }
-
- SDLDisplayCapability *oldDefaultDisplayCapabilities = oldCapabilities.firstObject;
- NSMutableArray<SDLWindowCapability *> *copyWindowCapabilities = [oldDefaultDisplayCapabilities.windowCapabilities mutableCopy];
-
- SDLDisplayCapability *newDefaultDisplayCapabilities = newCapabilities.firstObject;
- NSArray<SDLWindowCapability *> *newWindowCapabilities = newDefaultDisplayCapabilities.windowCapabilities;
-
- for (SDLWindowCapability *newWindow in newWindowCapabilities) {
- BOOL oldFound = NO;
- for (NSUInteger i = 0; i < copyWindowCapabilities.count; i++) {
- SDLWindowCapability *oldWindow = copyWindowCapabilities[i];
- NSUInteger newWindowID = newWindow.windowID ? newWindow.windowID.unsignedIntegerValue : SDLPredefinedWindowsDefaultWindow;
- NSUInteger oldWindowID = oldWindow.windowID ? oldWindow.windowID.unsignedIntegerValue : SDLPredefinedWindowsDefaultWindow;
- if (newWindowID == oldWindowID) {
- copyWindowCapabilities[i] = newWindow; // replace the old window caps with new ones
- oldFound = true;
- break;
- }
- }
-
- if (!oldFound) {
- [copyWindowCapabilities addObject:newWindow]; // this is a new unknown window
- }
- }
-
- // replace the window capabilities array with the merged one.
- newDefaultDisplayCapabilities.windowCapabilities = [copyWindowCapabilities copy];
- self.displays = @[newDefaultDisplayCapabilities];
- [self sdl_updateDeprecatedDisplayCapabilities];
-}
-
-#pragma mark - System Capabilities
+#pragma mark - System Capability Updates
- (void)updateCapabilityType:(SDLSystemCapabilityType)type completionHandler:(SDLUpdateCapabilityHandler)handler {
if (self.supportsSubscriptions) {
@@ -431,6 +406,8 @@ typedef NSString * SDLServiceID;
return @[SDLSystemCapabilityTypeAppServices, SDLSystemCapabilityTypeNavigation, SDLSystemCapabilityTypePhoneCall, SDLSystemCapabilityTypeVideoStreaming, SDLSystemCapabilityTypeRemoteControl, SDLSystemCapabilityTypeDisplays, SDLSystemCapabilityTypeSeatLocation];
}
+# pragma mark Subscribing
+
/**
* Sends a subscribe request for all possible system capabilites. If connecting to Core versions 4.5+, the requested capability will be returned in the response. If connecting to Core versions 5.1+, the manager will received `OnSystemCapabilityUpdated` notifications when the capability updates if the subscription was successful.
*/
@@ -465,6 +442,8 @@ typedef NSString * SDLServiceID;
}];
}
+#pragma mark Saving Capability Responses
+
/**
Saves a system capability. All system capabilities will update with the full object except for app services. For app services only the updated app service capabilities will be included in the `SystemCapability` sent from Core. The cached `appServicesCapabilities` will be updated with the new `appService` data.
@@ -474,26 +453,42 @@ typedef NSString * SDLServiceID;
*/
- (BOOL)sdl_saveSystemCapability:(SDLSystemCapability *)systemCapability completionHandler:(nullable SDLUpdateCapabilityHandler)handler {
if ([self.lastReceivedCapability isEqual:systemCapability]) {
- return [self sdl_callSaveHandlerForCapability:systemCapability andReturnWithValue:NO handler:handler];
+ [self sdl_callObserversForCapabilityUpdate:systemCapability handler:handler];
+ return NO;
}
self.lastReceivedCapability = systemCapability;
SDLSystemCapabilityType systemCapabilityType = systemCapability.systemCapabilityType;
if ([systemCapabilityType isEqualToEnum:SDLSystemCapabilityTypePhoneCall]) {
- if ([self.phoneCapability isEqual:systemCapability.phoneCapability]) { return [self sdl_callSaveHandlerForCapability:systemCapability andReturnWithValue:NO handler:handler]; }
+ if ([self.phoneCapability isEqual:systemCapability.phoneCapability]) {
+ [self sdl_callObserversForCapabilityUpdate:systemCapability handler:handler];
+ return NO;
+ }
self.phoneCapability = systemCapability.phoneCapability;
} else if ([systemCapabilityType isEqualToEnum:SDLSystemCapabilityTypeNavigation]) {
- if ([self.navigationCapability isEqual:systemCapability.navigationCapability]) { return [self sdl_callSaveHandlerForCapability:systemCapability andReturnWithValue:NO handler:handler]; }
+ if ([self.navigationCapability isEqual:systemCapability.navigationCapability]) {
+ [self sdl_callObserversForCapabilityUpdate:systemCapability handler:handler];
+ return NO;
+ }
self.navigationCapability = systemCapability.navigationCapability;
} else if ([systemCapabilityType isEqualToEnum:SDLSystemCapabilityTypeRemoteControl]) {
- if ([self.remoteControlCapability isEqual:systemCapability.remoteControlCapability]) { return [self sdl_callSaveHandlerForCapability:systemCapability andReturnWithValue:NO handler:handler]; }
+ if ([self.remoteControlCapability isEqual:systemCapability.remoteControlCapability]) {
+ [self sdl_callObserversForCapabilityUpdate:systemCapability handler:handler];
+ return NO;
+ }
self.remoteControlCapability = systemCapability.remoteControlCapability;
} else if ([systemCapabilityType isEqualToEnum:SDLSystemCapabilityTypeSeatLocation]) {
- if ([self.seatLocationCapability isEqual:systemCapability.seatLocationCapability]) { return [self sdl_callSaveHandlerForCapability:systemCapability andReturnWithValue:NO handler:handler]; }
+ if ([self.seatLocationCapability isEqual:systemCapability.seatLocationCapability]) {
+ [self sdl_callObserversForCapabilityUpdate:systemCapability handler:handler];
+ return NO;
+ }
self.seatLocationCapability = systemCapability.seatLocationCapability;
} else if ([systemCapabilityType isEqualToEnum:SDLSystemCapabilityTypeVideoStreaming]) {
- if ([self.videoStreamingCapability isEqual:systemCapability.videoStreamingCapability]) { return [self sdl_callSaveHandlerForCapability:systemCapability andReturnWithValue:NO handler:handler]; }
+ if ([self.videoStreamingCapability isEqual:systemCapability.videoStreamingCapability]) {
+ [self sdl_callObserversForCapabilityUpdate:systemCapability handler:handler];
+ return NO;
+ }
self.videoStreamingCapability = systemCapability.videoStreamingCapability;
} else if ([systemCapabilityType isEqualToEnum:SDLSystemCapabilityTypeAppServices]) {
[self sdl_saveAppServicesCapabilitiesUpdate:systemCapability.appServicesCapabilities];
@@ -508,37 +503,11 @@ typedef NSString * SDLServiceID;
SDLLogD(@"Updated system capability manager with new data: %@", systemCapability);
- return [self sdl_callSaveHandlerForCapability:systemCapability andReturnWithValue:YES handler:handler];
+ [self sdl_callObserversForCapabilityUpdate:systemCapability handler:handler];
+ return YES;
}
-- (BOOL)sdl_callSaveHandlerForCapability:(SDLSystemCapability *)capability andReturnWithValue:(BOOL)value handler:(nullable SDLUpdateCapabilityHandler)handler {
- for (SDLSystemCapabilityObserver *observer in self.capabilityObservers[capability.systemCapabilityType]) {
- if (observer.block != nil) {
- observer.block(capability);
- } else {
- NSUInteger numberOfParametersInSelector = [NSStringFromSelector(observer.selector) componentsSeparatedByString:@":"].count - 1;
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
- if (numberOfParametersInSelector == 0) {
- if ([observer.observer respondsToSelector:observer.selector]) {
- [observer.observer performSelector:observer.selector];
- }
- } else if (numberOfParametersInSelector == 1) {
- if ([observer.observer respondsToSelector:observer.selector]) {
- [observer.observer performSelector:observer.selector withObject:capability];
- }
- } else {
- @throw [NSException sdl_invalidSelectorExceptionWithSelector:observer.selector];
- }
-#pragma clang diagnostic pop
- }
- }
-
- if (handler == nil) { return value; }
- handler(nil, self);
-
- return value;
-}
+#pragma mark Merge Capability Deltas
- (void)sdl_saveAppServicesCapabilitiesUpdate:(SDLAppServicesCapabilities *)newCapabilities {
for (SDLAppServiceCapability *capability in newCapabilities.appServices) {
@@ -554,10 +523,52 @@ typedef NSString * SDLServiceID;
}
}
-#pragma mark - Subscriptions
+/// Save a new new-style `DisplayCapability` update (only contains the delta) that was received by merging it with the existing version.
+/// @param newCapabilities The new `DisplayCapability` update delta.
+- (void)sdl_saveDisplayCapabilityListUpdate:(NSArray<SDLDisplayCapability *> *)newCapabilities {
+ NSArray<SDLDisplayCapability *> *oldCapabilities = self.displays;
+
+ if (oldCapabilities == nil) {
+ self.displays = newCapabilities;
+ [self sdl_updateDeprecatedDisplayCapabilities];
+ return;
+ }
+
+ SDLDisplayCapability *oldDefaultDisplayCapabilities = oldCapabilities.firstObject;
+ NSMutableArray<SDLWindowCapability *> *copyWindowCapabilities = [oldDefaultDisplayCapabilities.windowCapabilities mutableCopy];
+
+ SDLDisplayCapability *newDefaultDisplayCapabilities = newCapabilities.firstObject;
+ NSArray<SDLWindowCapability *> *newWindowCapabilities = newDefaultDisplayCapabilities.windowCapabilities;
+
+ for (SDLWindowCapability *newWindow in newWindowCapabilities) {
+ BOOL oldFound = NO;
+ for (NSUInteger i = 0; i < copyWindowCapabilities.count; i++) {
+ SDLWindowCapability *oldWindow = copyWindowCapabilities[i];
+ NSUInteger newWindowID = newWindow.windowID ? newWindow.windowID.unsignedIntegerValue : SDLPredefinedWindowsDefaultWindow;
+ NSUInteger oldWindowID = oldWindow.windowID ? oldWindow.windowID.unsignedIntegerValue : SDLPredefinedWindowsDefaultWindow;
+ if (newWindowID == oldWindowID) {
+ copyWindowCapabilities[i] = newWindow; // replace the old window caps with new ones
+ oldFound = true;
+ break;
+ }
+ }
+
+ if (!oldFound) {
+ [copyWindowCapabilities addObject:newWindow]; // this is a new unknown window
+ }
+ }
+
+ // replace the window capabilities array with the merged one.
+ newDefaultDisplayCapabilities.windowCapabilities = [copyWindowCapabilities copy];
+ self.displays = @[newDefaultDisplayCapabilities];
+ [self sdl_updateDeprecatedDisplayCapabilities];
+}
+
+#pragma mark - Manager Subscriptions
- (nullable id<NSObject>)subscribeToCapabilityType:(SDLSystemCapabilityType)type withBlock:(SDLCapabilityUpdateHandler)block {
- if (!self.supportsSubscriptions) { return nil; }
+ // DISPLAYS always works due to old-style SetDisplayLayoutRepsonse updates, but otherwise, subscriptions won't work
+ if (!self.supportsSubscriptions && ![type isEqualToEnum:SDLSystemCapabilityTypeDisplays]) { return nil; }
SDLSystemCapabilityObserver *observerObject = [[SDLSystemCapabilityObserver alloc] initWithObserver:[[NSObject alloc] init] block:block];
[self.capabilityObservers[type] addObject:observerObject];
@@ -566,7 +577,8 @@ typedef NSString * SDLServiceID;
}
- (BOOL)subscribeToCapabilityType:(SDLSystemCapabilityType)type withObserver:(id<NSObject>)observer selector:(SEL)selector {
- if (!self.supportsSubscriptions) { return NO; }
+ // DISPLAYS always works due to old-style SetDisplayLayoutRepsonse updates, but otherwise, subscriptions won't work
+ if (!self.supportsSubscriptions && ![type isEqualToEnum:SDLSystemCapabilityTypeDisplays]) { return nil; }
NSUInteger numberOfParametersInSelector = [NSStringFromSelector(selector) componentsSeparatedByString:@":"].count - 1;
if (numberOfParametersInSelector > 1) { return NO; }
@@ -586,6 +598,36 @@ typedef NSString * SDLServiceID;
}
}
+/// Calls all observers of a capability type with an updated capability
+/// @param capability The new capability update
+/// @param handler The update handler to call, if one exists after the observers are called
+- (void)sdl_callObserversForCapabilityUpdate:(SDLSystemCapability *)capability handler:(nullable SDLUpdateCapabilityHandler)handler {
+ for (SDLSystemCapabilityObserver *observer in self.capabilityObservers[capability.systemCapabilityType]) {
+ if (observer.block != nil) {
+ observer.block(capability);
+ } else {
+ NSUInteger numberOfParametersInSelector = [NSStringFromSelector(observer.selector) componentsSeparatedByString:@":"].count - 1;
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
+ if (numberOfParametersInSelector == 0) {
+ if ([observer.observer respondsToSelector:observer.selector]) {
+ [observer.observer performSelector:observer.selector];
+ }
+ } else if (numberOfParametersInSelector == 1) {
+ if ([observer.observer respondsToSelector:observer.selector]) {
+ [observer.observer performSelector:observer.selector withObject:capability];
+ }
+ } else {
+ @throw [NSException sdl_invalidSelectorExceptionWithSelector:observer.selector];
+ }
+#pragma clang diagnostic pop
+ }
+ }
+
+ if (handler == nil) { return; }
+ handler(nil, self);
+}
+
@end
NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLTextAndGraphicManager.h b/SmartDeviceLink/SDLTextAndGraphicManager.h
index 61523c4c9..c916e0426 100644
--- a/SmartDeviceLink/SDLTextAndGraphicManager.h
+++ b/SmartDeviceLink/SDLTextAndGraphicManager.h
@@ -65,6 +65,9 @@ typedef void(^SDLTextAndGraphicUpdateCompletionHandler)(NSError *__nullable erro
*/
- (instancetype)initWithConnectionManager:(id<SDLConnectionManagerType>)connectionManager fileManager:(SDLFileManager *)fileManager systemCapabilityManager:(SDLSystemCapabilityManager *)systemCapabilityManager;
+/// Starts the manager. This method is used internally.
+- (void)start;
+
/**
* Stops the manager. This method is used internally.
*/
diff --git a/SmartDeviceLink/SDLTextAndGraphicManager.m b/SmartDeviceLink/SDLTextAndGraphicManager.m
index 171b4619d..bc8e6aa5f 100644
--- a/SmartDeviceLink/SDLTextAndGraphicManager.m
+++ b/SmartDeviceLink/SDLTextAndGraphicManager.m
@@ -53,7 +53,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (assign, nonatomic) BOOL hasQueuedUpdate;
@property (copy, nonatomic, nullable) SDLTextAndGraphicUpdateCompletionHandler queuedUpdateHandler;
-@property (strong, nonatomic, nullable) SDLWindowCapability *defaultMainWindowCapability;
+@property (strong, nonatomic, nullable) SDLWindowCapability *windowCapability;
@property (strong, nonatomic, nullable) SDLHMILevel currentLevel;
@property (strong, nonatomic, nullable) SDLArtwork *blankArtwork;
@@ -81,12 +81,16 @@ NS_ASSUME_NONNULL_BEGIN
_waitingOnHMILevelUpdateToUpdate = NO;
_isDirty = NO;
- [_systemCapabilityManager subscribeToCapabilityType:SDLSystemCapabilityTypeDisplays withObserver:self selector:@selector(sdl_displayCapabilityUpdate:)];
+ [_systemCapabilityManager subscribeToCapabilityType:SDLSystemCapabilityTypeDisplays withObserver:self selector:@selector(sdl_displayCapabilityDidUpdate:)];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_hmiStatusNotification:) name:SDLDidChangeHMIStatusNotification object:nil];
return self;
}
+- (void)start {
+ [_systemCapabilityManager subscribeToCapabilityType:SDLSystemCapabilityTypeDisplays withObserver:self selector:@selector(sdl_displayCapabilityDidUpdate:)];
+}
+
- (void)stop {
_textField1 = nil;
_textField2 = nil;
@@ -107,7 +111,7 @@ NS_ASSUME_NONNULL_BEGIN
_queuedImageUpdate = nil;
_hasQueuedUpdate = NO;
_queuedUpdateHandler = nil;
- _defaultMainWindowCapability = nil;
+ _windowCapability = nil;
_currentLevel = SDLHMILevelNone;
_blankArtwork = nil;
_waitingOnHMILevelUpdateToUpdate = NO;
@@ -296,7 +300,7 @@ NS_ASSUME_NONNULL_BEGIN
NSArray *nonNilFields = [self sdl_findNonNilTextFields];
if (nonNilFields.count == 0) { return show; }
- NSUInteger numberOfLines = self.defaultMainWindowCapability ? self.defaultMainWindowCapability.maxNumberOfMainFieldLines : 4;
+ NSUInteger numberOfLines = self.windowCapability ? self.windowCapability.maxNumberOfMainFieldLines : 4;
if (numberOfLines == 1) {
show = [self sdl_assembleOneLineShowText:show withShowFields:nonNilFields];
} else if (numberOfLines == 2) {
@@ -507,7 +511,7 @@ NS_ASSUME_NONNULL_BEGIN
}
- (BOOL)sdl_shouldUpdatePrimaryImage {
- BOOL templateSupportsPrimaryArtwork = self.defaultMainWindowCapability ? [self.defaultMainWindowCapability hasImageFieldOfName:SDLImageFieldNameGraphic] : YES;
+ BOOL templateSupportsPrimaryArtwork = self.windowCapability ? [self.windowCapability hasImageFieldOfName:SDLImageFieldNameGraphic] : YES;
return (templateSupportsPrimaryArtwork
&& ![self.currentScreenData.graphic.value isEqualToString:self.primaryGraphic.name]
@@ -515,7 +519,7 @@ NS_ASSUME_NONNULL_BEGIN
}
- (BOOL)sdl_shouldUpdateSecondaryImage {
- BOOL templateSupportsSecondaryArtwork = self.defaultMainWindowCapability ? ([self.defaultMainWindowCapability hasImageFieldOfName:SDLImageFieldNameGraphic] || [self.defaultMainWindowCapability hasImageFieldOfName:SDLImageFieldNameSecondaryGraphic]) : YES;
+ BOOL templateSupportsSecondaryArtwork = self.windowCapability ? ([self.windowCapability hasImageFieldOfName:SDLImageFieldNameGraphic] || [self.windowCapability hasImageFieldOfName:SDLImageFieldNameSecondaryGraphic]) : YES;
// Cannot detect if there is a secondary image, so we'll just try to detect if there's a primary image and allow it if there is.
return (templateSupportsSecondaryArtwork
@@ -693,9 +697,9 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - Subscribed notifications
-- (void)sdl_displayCapabilityUpdate:(SDLSystemCapability *)systemCapability {
+- (void)sdl_displayCapabilityDidUpdate:(SDLSystemCapability *)systemCapability {
// we won't use the object in the parameter but the convenience method of the system capability manager
- self.defaultMainWindowCapability = _systemCapabilityManager.defaultMainWindowCapability;
+ self.windowCapability = _systemCapabilityManager.defaultMainWindowCapability;
// Auto-send an updated show
if ([self sdl_hasData]) {
diff --git a/SmartDeviceLink/SDLWindowCapability+ShowManagerExtensions.h b/SmartDeviceLink/SDLWindowCapability+ShowManagerExtensions.h
index 0786eb89f..14bfc9ffa 100644
--- a/SmartDeviceLink/SDLWindowCapability+ShowManagerExtensions.h
+++ b/SmartDeviceLink/SDLWindowCapability+ShowManagerExtensions.h
@@ -2,7 +2,9 @@
// SDLWindowCapability+ShowManagerExtensions.h
// SmartDeviceLink
//
-// Created by Kujtim Shala (Ford) on 13.09.19.
+// Created by Joel Fischer on 2/28/18.
+// Updated by Kujtim Shala (Ford) on 13.09.19.
+// - Renamed and adapted for WindowCapability
// Copyright © 2019 smartdevicelink. All rights reserved.
//
diff --git a/SmartDeviceLink/SDLWindowCapability+ShowManagerExtensions.m b/SmartDeviceLink/SDLWindowCapability+ShowManagerExtensions.m
index 5d8961cb5..c6b808e22 100644
--- a/SmartDeviceLink/SDLWindowCapability+ShowManagerExtensions.m
+++ b/SmartDeviceLink/SDLWindowCapability+ShowManagerExtensions.m
@@ -2,7 +2,9 @@
// SDLWindowCapability+ShowManagerExtensions.m
// SmartDeviceLink
//
-// Created by Kujtim Shala (Ford) on 13.09.19.
+// Created by Joel Fischer on 2/28/18.
+// Updated by Kujtim Shala (Ford) on 13.09.19.
+// - Renamed and adapted for WindowCapability
// Copyright © 2019 smartdevicelink. All rights reserved.
//
diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLFileManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLFileManagerSpec.m
index 2fa7dc204..1d1599cad 100644
--- a/SmartDeviceLinkTests/DevAPISpecs/SDLFileManagerSpec.m
+++ b/SmartDeviceLinkTests/DevAPISpecs/SDLFileManagerSpec.m
@@ -875,7 +875,7 @@ describe(@"uploading/deleting multiple files in the file manager", ^{
[testFileManager uploadArtworks:testArtworks progressHandler:^BOOL(NSString * _Nonnull artworkName, float uploadPercentage, NSError * _Nullable error) {
artworksDone++;
expect(artworkName).to(equal(expectedArtworkNames[artworksDone - 1]));
- expect(uploadPercentage).to(beCloseTo((float)artworksDone / 200.0).within(0.0015));
+ expect(uploadPercentage).to(beCloseTo((float)artworksDone / 200.0).within(0.01));
expect(error).to(beNil());
return YES;
} completionHandler:^(NSArray<NSString *> * _Nonnull artworkNames, NSError * _Nullable error) {
diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLSoftButtonManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLSoftButtonManagerSpec.m
index f5a80725f..6534b49df 100644
--- a/SmartDeviceLinkTests/DevAPISpecs/SDLSoftButtonManagerSpec.m
+++ b/SmartDeviceLinkTests/DevAPISpecs/SDLSoftButtonManagerSpec.m
@@ -73,6 +73,7 @@ describe(@"a soft button manager", ^{
testConnectionManager = [[TestConnectionManager alloc] init];
testManager = [[SDLSoftButtonManager alloc] initWithConnectionManager:testConnectionManager fileManager:testFileManager systemCapabilityManager:testSystemCapabilityManager];
+ [testManager start];
expect(testManager.currentLevel).to(beNil());
testManager.currentLevel = SDLHMILevelFull;
diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLTextAndGraphicManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLTextAndGraphicManagerSpec.m
index a7bcb1624..35c3f0a08 100644
--- a/SmartDeviceLinkTests/DevAPISpecs/SDLTextAndGraphicManagerSpec.m
+++ b/SmartDeviceLinkTests/DevAPISpecs/SDLTextAndGraphicManagerSpec.m
@@ -30,7 +30,7 @@
@property (assign, nonatomic) BOOL hasQueuedUpdate;
@property (copy, nonatomic, nullable) SDLTextAndGraphicUpdateCompletionHandler queuedUpdateHandler;
-@property (strong, nonatomic, nullable) SDLWindowCapability *defaultMainWindowCapability;
+@property (strong, nonatomic, nullable) SDLWindowCapability *windowCapability;
@property (strong, nonatomic, nullable) SDLHMILevel currentLevel;
@property (strong, nonatomic) SDLArtwork *blankArtwork;
@@ -56,6 +56,7 @@ describe(@"text and graphic manager", ^{
mockFileManager = OCMClassMock([SDLFileManager class]);
mockSystemCapabilityManager = OCMClassMock([SDLSystemCapabilityManager class]);
testManager = [[SDLTextAndGraphicManager alloc] initWithConnectionManager:mockConnectionManager fileManager:mockFileManager systemCapabilityManager:mockSystemCapabilityManager];
+ [testManager start];
});
it(@"should instantiate correctly", ^{
@@ -80,7 +81,7 @@ describe(@"text and graphic manager", ^{
expect(testManager.inProgressUpdate).to(beNil());
expect(testManager.queuedImageUpdate).to(beNil());
expect(testManager.hasQueuedUpdate).to(beFalse());
- expect(testManager.defaultMainWindowCapability).to(beNil());
+ expect(testManager.windowCapability).to(beNil());
expect(testManager.currentLevel).to(equal(SDLHMILevelNone));
expect(testManager.blankArtwork).toNot(beNil());
expect(testManager.isDirty).to(beFalse());
@@ -371,10 +372,10 @@ describe(@"text and graphic manager", ^{
context(@"with one line available", ^{
beforeEach(^{
- testManager.defaultMainWindowCapability = [[SDLWindowCapability alloc] init];
+ testManager.windowCapability = [[SDLWindowCapability alloc] init];
SDLTextField *lineOneField = [[SDLTextField alloc] init];
lineOneField.name = SDLTextFieldNameMainField1;
- testManager.defaultMainWindowCapability.textFields = @[lineOneField];
+ testManager.windowCapability.textFields = @[lineOneField];
});
it(@"should set mediatrack properly", ^{
@@ -472,10 +473,10 @@ describe(@"text and graphic manager", ^{
context(@"with two lines available", ^{
beforeEach(^{
- testManager.defaultMainWindowCapability = [[SDLWindowCapability alloc] init];
+ testManager.windowCapability = [[SDLWindowCapability alloc] init];
SDLTextField *lineTwoField = [[SDLTextField alloc] init];
lineTwoField.name = SDLTextFieldNameMainField2;
- testManager.defaultMainWindowCapability.textFields = @[lineTwoField];
+ testManager.windowCapability.textFields = @[lineTwoField];
});
it(@"should set mediatrack properly", ^{
@@ -582,10 +583,10 @@ describe(@"text and graphic manager", ^{
context(@"with three lines available", ^{
beforeEach(^{
- testManager.defaultMainWindowCapability = [[SDLWindowCapability alloc] init];
+ testManager.windowCapability = [[SDLWindowCapability alloc] init];
SDLTextField *lineThreeField = [[SDLTextField alloc] init];
lineThreeField.name = SDLTextFieldNameMainField3;
- testManager.defaultMainWindowCapability.textFields = @[lineThreeField];
+ testManager.windowCapability.textFields = @[lineThreeField];
});
it(@"should set mediatrack properly", ^{
@@ -696,10 +697,10 @@ describe(@"text and graphic manager", ^{
context(@"with four lines available", ^{
beforeEach(^{
- testManager.defaultMainWindowCapability = [[SDLWindowCapability alloc] init];
+ testManager.windowCapability = [[SDLWindowCapability alloc] init];
SDLTextField *lineFourField = [[SDLTextField alloc] init];
lineFourField.name = SDLTextFieldNameMainField4;
- testManager.defaultMainWindowCapability.textFields = @[lineFourField];
+ testManager.windowCapability.textFields = @[lineFourField];
});
it(@"should set mediatrack properly", ^{
@@ -968,7 +969,7 @@ describe(@"text and graphic manager", ^{
expect(testManager.inProgressUpdate).to(beNil());
expect(testManager.queuedImageUpdate).to(beNil());
expect(testManager.hasQueuedUpdate).to(beFalse());
- expect(testManager.defaultMainWindowCapability).to(beNil());
+ expect(testManager.windowCapability).to(beNil());
expect(testManager.currentLevel).to(equal(SDLHMILevelNone));
expect(testManager.blankArtwork).toNot(beNil());
expect(testManager.isDirty).to(beFalse());
diff --git a/SmartDeviceLinkTests/SDLAsynchronousRPCOperationSpec.m b/SmartDeviceLinkTests/SDLAsynchronousRPCOperationSpec.m
index 819657285..ad847378e 100644
--- a/SmartDeviceLinkTests/SDLAsynchronousRPCOperationSpec.m
+++ b/SmartDeviceLinkTests/SDLAsynchronousRPCOperationSpec.m
@@ -83,7 +83,7 @@ describe(@"sending responses and notifications", ^{
[testOperationQueue addOperation:testOperation];
[testOperationQueue cancelAllOperations];
- [NSThread sleepForTimeInterval:1.0];
+ [NSThread sleepForTimeInterval:0.5];
expect(testConnectionManager.receivedRequests).toEventually(beEmpty());
});
diff --git a/SmartDeviceLinkTests/SDLSystemCapabilityManagerSpec.m b/SmartDeviceLinkTests/SDLSystemCapabilityManagerSpec.m
index f8a0b44f6..774eae9bd 100644
--- a/SmartDeviceLinkTests/SDLSystemCapabilityManagerSpec.m
+++ b/SmartDeviceLinkTests/SDLSystemCapabilityManagerSpec.m
@@ -646,6 +646,7 @@ describe(@"System capability manager", ^{
it(@"It should reset the system capability manager properties correctly", ^{
expect(testSystemCapabilityManager.hmiCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.displays).to(beNil());
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated"
expect(testSystemCapabilityManager.displayCapabilities).to(beNil());