diff options
author | NicoleYarroch <nicole@livio.io> | 2019-04-04 09:36:12 -0400 |
---|---|---|
committer | NicoleYarroch <nicole@livio.io> | 2019-04-04 09:36:12 -0400 |
commit | 2dc2837cd5aac9d4acd2aa923e1b3daeba1603cf (patch) | |
tree | 62d365e18cbfe74b6dbd98a7971f78ad78e44541 | |
parent | 9e3d35f21626c6915376356a5edd07c52fdc2fd0 (diff) | |
download | sdl_ios-2dc2837cd5aac9d4acd2aa923e1b3daeba1603cf.tar.gz |
Added doc and refactored system capability manager
-rw-r--r-- | SmartDeviceLink/SDLSystemCapabilityManager.m | 182 | ||||
-rw-r--r-- | SmartDeviceLinkTests/SDLSystemCapabilityManagerSpec.m | 80 |
2 files changed, 137 insertions, 125 deletions
diff --git a/SmartDeviceLink/SDLSystemCapabilityManager.m b/SmartDeviceLink/SDLSystemCapabilityManager.m index 5918bb2ee..9369f0d7a 100644 --- a/SmartDeviceLink/SDLSystemCapabilityManager.m +++ b/SmartDeviceLink/SDLSystemCapabilityManager.m @@ -75,6 +75,9 @@ NS_ASSUME_NONNULL_BEGIN return self; } +/** + * Resets the capabilities when a transport session is closed. + */ - (void)stop { SDLLogD(@"System Capability manager stopped"); _displayCapabilities = nil; @@ -97,17 +100,23 @@ NS_ASSUME_NONNULL_BEGIN _isFirstHMILevelFull = NO; } - #pragma mark - Notifications +/** + * Registers for notifications and responses from Core + */ -(void)sdl_registerForNotifications { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_registerResponse:) name:SDLDidReceiveRegisterAppInterfaceResponse object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_displayLayoutResponse:) name:SDLDidReceiveSetDisplayLayoutResponse object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_systemCapabilityResponse:) name:SDLDidReceiveGetSystemCapabilitiesResponse object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_systemCapabilityUpdatedNotification:) name:SDLDidReceiveSystemCapabilityUpdatedNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_hmiStatusNotification:) name:SDLDidChangeHMIStatusNotification object:nil]; } +/** + * Called when a `RegisterAppInterfaceResponse` response is received from Core. The head unit capabilities are saved. + * + * @param notification The `RegisterAppInterfaceResponse` response received from Core + */ - (void)sdl_registerResponse:(SDLRPCResponseNotification *)notification { SDLRegisterAppInterfaceResponse *response = (SDLRegisterAppInterfaceResponse *)notification.response; if (!response.success.boolValue) { return; } @@ -125,6 +134,11 @@ NS_ASSUME_NONNULL_BEGIN self.pcmStreamCapability = response.pcmStreamCapabilities; } +/** + * Called when a `SetDisplayLayoutResponse` response is received from Core. If the template was set successfully, the the new capabilities for the template are saved. + * + * @param notification The `SetDisplayLayoutResponse` response received from Core + */ - (void)sdl_displayLayoutResponse:(SDLRPCResponseNotification *)notification { SDLSetDisplayLayoutResponse *response = (SDLSetDisplayLayoutResponse *)notification.response; if (!response.success.boolValue) { return; } @@ -135,27 +149,91 @@ NS_ASSUME_NONNULL_BEGIN self.presetBankCapabilities = response.presetBankCapabilities; } -- (void)sdl_systemCapabilityResponse:(SDLRPCResponseNotification *)notification { - SDLGetSystemCapabilityResponse *response = (SDLGetSystemCapabilityResponse *)notification.response; - if (!response.success.boolValue) { return; } +/** + * Called when an `OnSystemCapabilityUpdated` notification is received from Core. The updated system capabilty is saved. + * + * @param notification The `OnSystemCapabilityUpdated` notification received from Core + */ +- (void)sdl_systemCapabilityUpdatedNotification:(SDLRPCNotificationNotification *)notification { + SDLOnSystemCapabilityUpdated *systemCapabilityUpdatedNotification = (SDLOnSystemCapabilityUpdated *)notification.notification; + [self sdl_saveSystemCapability:systemCapabilityUpdatedNotification.systemCapability]; +} + +/** + * Called when an `OnHMIStatus` notification is received from Core. The first time the `hmiLevel` is `FULL` attempt to subscribe to system capabilty updates. + * + * @param notification The `OnHMIStatus` notification received from Core + */ +- (void)sdl_hmiStatusNotification:(SDLRPCNotificationNotification *)notification { + SDLOnHMIStatus *hmiStatus = (SDLOnHMIStatus *)notification.notification; + if (self.isFirstHMILevelFull || ![hmiStatus.hmiLevel isEqualToEnum:SDLHMILevelFull]) { + return; + } - SDLSystemCapability *systemCapabilityResponse = ((SDLGetSystemCapabilityResponse *)response).systemCapability; + self.isFirstHMILevelFull = YES; + [self sdl_subscribeToSystemCapabilityUpdates]; +} - [self sdl_saveSystemCapability:systemCapabilityResponse]; +#pragma mark - System Capabilities - if (self.systemCapabilityHandler == nil) { return; } - self.systemCapabilityHandler(nil, self); +- (void)updateCapabilityType:(SDLSystemCapabilityType)type completionHandler:(SDLUpdateCapabilityHandler)handler { + self.systemCapabilityHandler = handler; + + SDLVersion *onSystemCapabilityNotificationRPCVersion = [SDLVersion versionWithString:@"5.1.0"]; + SDLVersion *headUnitRPCVersion = SDLGlobals.sharedGlobals.rpcVersion; + if ([headUnitRPCVersion isGreaterThanOrEqualToVersion:onSystemCapabilityNotificationRPCVersion]) { + // Just return the cached data + if (self.systemCapabilityHandler == nil) { return; } + self.systemCapabilityHandler(nil, self); + } + + SDLGetSystemCapability *getSystemCapability = [[SDLGetSystemCapability alloc] initWithType:type]; + [self sdl_sendGetSystemCapability:getSystemCapability]; } -- (void)sdl_systemCapabilityUpdatedNotification:(SDLRPCNotificationNotification *)notification { - SDLOnSystemCapabilityUpdated *systemCapabilityUpdatedNotification = (SDLOnSystemCapabilityUpdated *)notification.notification; - [self sdl_saveSystemCapability:systemCapabilityUpdatedNotification.systemCapability]; +/** + * A list of all possible system capability types. + * + * @return An array of all possible system capability types + */ ++ (NSArray<SDLSystemCapabilityType> *)sdl_systemCapabilityTypes { + return @[SDLSystemCapabilityTypeAppServices, SDLSystemCapabilityTypeNavigation, SDLSystemCapabilityTypePhoneCall, SDLSystemCapabilityTypeVideoStreaming, SDLSystemCapabilityTypeRemoteControl]; +} - // TODO: double check that this isn't going to break anything - if (self.systemCapabilityHandler == nil) { return; } - self.systemCapabilityHandler(nil, self); +/** + * 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. + */ +- (void)sdl_subscribeToSystemCapabilityUpdates { + for (NSUInteger i = 0; i < [self.class sdl_systemCapabilityTypes].count; i += 1) { + SDLGetSystemCapability *getSystemCapability = [[SDLGetSystemCapability alloc] initWithType:[self.class sdl_systemCapabilityTypes][i] subscribe:true]; + [self sdl_sendGetSystemCapability:getSystemCapability]; + } } +/** + * Sends a `GetSystemCapability` to Core and handles the response by saving the returned data and notifying the subscriber. + * + * @param getSystemCapability The `GetSystemCapability` request to send + */ +- (void)sdl_sendGetSystemCapability:(SDLGetSystemCapability *)getSystemCapability { + [self.connectionManager sendConnectionRequest:getSystemCapability withResponseHandler:^(__kindof SDLRPCRequest * _Nullable request, __kindof SDLRPCResponse * _Nullable response, NSError * _Nullable error) { + if (error != nil) { + // An error is returned if the request was unsuccessful or if a Generic Response was returned + if (self.systemCapabilityHandler == nil) { return; } + return self.systemCapabilityHandler(error, self); + } + + SDLGetSystemCapabilityResponse *getSystemCapabilityResponse = (SDLGetSystemCapabilityResponse *)response; + if (!getSystemCapabilityResponse.resultCode.boolValue) { return; } + [self sdl_saveSystemCapability:getSystemCapabilityResponse.systemCapability]; + }]; +} + +/** + * 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. + * + * @param systemCapability The system capability + */ - (void)sdl_saveSystemCapability:(SDLSystemCapability *)systemCapability { SDLSystemCapabilityType systemCapabilityType = systemCapability.systemCapabilityType; @@ -170,69 +248,27 @@ NS_ASSUME_NONNULL_BEGIN } else if ([systemCapabilityType isEqualToEnum:SDLSystemCapabilityTypeAppServices]) { if (!self.appServicesCapabilities) { self.appServicesCapabilities = systemCapability.appServicesCapabilities; + } else { + NSMutableDictionary *cachedAppServicesCapabilities = [NSMutableDictionary dictionary]; + for (NSUInteger i = 0; i < self.appServicesCapabilities.appServices.count; i += 1) { + SDLAppServiceRecord *record = self.appServicesCapabilities.appServices[i].updatedAppServiceRecord; + cachedAppServicesCapabilities[record.serviceID] = record; + } + + for (NSUInteger i = 0; i < systemCapability.appServicesCapabilities.appServices.count; i += 1) { + SDLAppServiceRecord *updatedRecord = systemCapability.appServicesCapabilities.appServices[i].updatedAppServiceRecord; + cachedAppServicesCapabilities[updatedRecord.serviceID] = updatedRecord; + } + + self.appServicesCapabilities.appServices = [cachedAppServicesCapabilities allValues]; } - - NSMutableDictionary *cachedCapabilities = [NSMutableDictionary dictionary]; - for (unsigned long i = 0; i < self.appServicesCapabilities.appServices.count; i += 1) { - SDLAppServiceRecord *record = self.appServicesCapabilities.appServices[i].updatedAppServiceRecord; - cachedCapabilities[record.serviceID] = record; - } - - for (unsigned long i = 0; i < systemCapability.appServicesCapabilities.appServices.count; i += 1) { - SDLAppServiceRecord *updatedRecord = systemCapability.appServicesCapabilities.appServices[i].updatedAppServiceRecord; - cachedCapabilities[updatedRecord.serviceID] = updatedRecord; - } - - self.appServicesCapabilities.appServices = [cachedCapabilities allValues]; } else { SDLLogW(@"Received response for unknown System Capability Type: %@", systemCapabilityType); + return; } -} - -- (void)sdl_hmiStatusNotification:(SDLRPCNotificationNotification *)notification { - SDLOnHMIStatus *hmiStatus = (SDLOnHMIStatus *)notification.notification; - - // On first hmi level of `FULL` send the `GetSystemCapability` subscription - if (!self.isFirstHMILevelFull && hmiStatus.hmiLevel == SDLHMILevelFull) { - self.isFirstHMILevelFull = YES; - - NSArray<SDLSystemCapabilityType> *allSystemCapabilityTypes = @[SDLSystemCapabilityTypeAppServices, SDLSystemCapabilityTypeNavigation, SDLSystemCapabilityTypePhoneCall, SDLSystemCapabilityTypeVideoStreaming, SDLSystemCapabilityTypeRemoteControl]; - - NSMutableArray<SDLGetSystemCapability *> *test = [NSMutableArray array]; - for (unsigned long i = 0; i < allSystemCapabilityTypes.count; i += 1) { - SDLGetSystemCapability *getSystemCapability = [[SDLGetSystemCapability alloc] initWithType:allSystemCapabilityTypes[i] subscribe:true]; - [test addObject:getSystemCapability]; - } - - [self.connectionManager sendRequests:test progressHandler:^(__kindof SDLRPCRequest * _Nonnull request, __kindof SDLRPCResponse * _Nullable response, NSError * _Nullable error, float percentComplete) { - SDLGetSystemCapabilityResponse *getSystemCapabilityResponse = (SDLGetSystemCapabilityResponse *)response; - // TODO: make sure this actually returns data - [self sdl_saveSystemCapability:getSystemCapabilityResponse.systemCapability]; - } completionHandler:^(BOOL success) { - // TODO - not sure if we need this - }]; - } -} -#pragma mark - Capability Request - -- (void)updateCapabilityType:(SDLSystemCapabilityType)type completionHandler:(SDLUpdateCapabilityHandler)handler { - self.systemCapabilityHandler = handler; - - SDLVersion *onSystemCapabilityNotificationRPCVersion = [SDLVersion versionWithString:@"5.1.0"]; - SDLVersion *headUnitRPCVersion = SDLGlobals.sharedGlobals.rpcVersion; - if ([headUnitRPCVersion isGreaterThanOrEqualToVersion:onSystemCapabilityNotificationRPCVersion]) { - // Just return the cached data - if (self.systemCapabilityHandler == nil) { return; } - self.systemCapabilityHandler(nil, self); - } - - SDLGetSystemCapability *getSystemCapability = [[SDLGetSystemCapability alloc] initWithType:type]; - [self.connectionManager sendConnectionRequest:getSystemCapability withResponseHandler:^(__kindof SDLRPCRequest * _Nullable request, __kindof SDLRPCResponse * _Nullable response, NSError * _Nullable error) { - if (error == nil) { return; } - // An error is returned if the request was unsuccessful or a Generic Response is returned - handler(error, self); - }]; + if (self.systemCapabilityHandler == nil) { return; } + self.systemCapabilityHandler(nil, self); } @end diff --git a/SmartDeviceLinkTests/SDLSystemCapabilityManagerSpec.m b/SmartDeviceLinkTests/SDLSystemCapabilityManagerSpec.m index 97a413a1c..14dfadd06 100644 --- a/SmartDeviceLinkTests/SDLSystemCapabilityManagerSpec.m +++ b/SmartDeviceLinkTests/SDLSystemCapabilityManagerSpec.m @@ -257,12 +257,12 @@ describe(@"System capability manager", ^{ }); }); - context(@"When notified of a Get System Capability Response", ^{ + context(@"When sending a Get System Capability request", ^{ __block SDLGetSystemCapabilityResponse *testGetSystemCapabilityResponse; __block SDLPhoneCapability *testPhoneCapability = nil; beforeEach(^{ - testPhoneCapability = [[SDLPhoneCapability alloc] initWithDialNumber:YES]; + testPhoneCapability = [[SDLPhoneCapability alloc] initWithDialNumber:YES]; testGetSystemCapabilityResponse = [[SDLGetSystemCapabilityResponse alloc] init]; testGetSystemCapabilityResponse.systemCapability = [[SDLSystemCapability alloc] init]; @@ -270,69 +270,45 @@ describe(@"System capability manager", ^{ testGetSystemCapabilityResponse.systemCapability.systemCapabilityType = SDLSystemCapabilityTypePhoneCall; }); - describe(@"If a Get System Capability Response notification is received", ^{ - context(@"If the request failed", ^{ - beforeEach(^{ - testGetSystemCapabilityResponse.success = @NO; - SDLRPCResponseNotification *notification = [[SDLRPCResponseNotification alloc] initWithName:SDLDidReceiveGetSystemCapabilitiesResponse object:self rpcResponse:testGetSystemCapabilityResponse]; - [[NSNotificationCenter defaultCenter] postNotification:notification]; - }); + context(@"If the request failed with an error", ^{ + __block NSError *testError = nil; - it(@"should should not save the capabilities", ^{ - expect(testSystemCapabilityManager.phoneCapability).to(beNil()); - }); + beforeEach(^{ + testGetSystemCapabilityResponse.success = @NO; + testError = [NSError errorWithDomain:NSCocoaErrorDomain code:-234 userInfo:nil]; }); - context(@"If the request succeeded", ^{ - beforeEach(^{ - testGetSystemCapabilityResponse.success = @YES; - SDLRPCResponseNotification *notification = [[SDLRPCResponseNotification alloc] initWithName:SDLDidReceiveGetSystemCapabilitiesResponse object:self rpcResponse:testGetSystemCapabilityResponse]; - [[NSNotificationCenter defaultCenter] postNotification:notification]; - }); + it(@"should should not save the capabilities", ^{ + waitUntilTimeout(1, ^(void (^done)(void)) { + [testSystemCapabilityManager updateCapabilityType:testGetSystemCapabilityResponse.systemCapability.systemCapabilityType completionHandler:^(NSError * _Nullable error, SDLSystemCapabilityManager * _Nonnull systemCapabilityManager) { + expect(error).to(equal(testConnectionManager.defaultError)); + expect(systemCapabilityManager.phoneCapability).to(beNil()); + done(); + }]; + + [NSThread sleepForTimeInterval:0.1]; - it(@"should should save the capabilities", ^{ - expect(testSystemCapabilityManager.phoneCapability).to(equal(testPhoneCapability)); + [testConnectionManager respondToLastRequestWithResponse:testGetSystemCapabilityResponse]; }); }); }); - describe(@"If a response is received for a sent Get System Capability request", ^{ - context(@"If the request failed with an error", ^{ - __block NSError *testError = nil; - - beforeEach(^{ - testGetSystemCapabilityResponse.success = @NO; - testError = [NSError errorWithDomain:NSCocoaErrorDomain code:-234 userInfo:nil]; - - waitUntilTimeout(1.0, ^(void (^done)(void)) { - [testSystemCapabilityManager updateCapabilityType:testGetSystemCapabilityResponse.systemCapability.systemCapabilityType completionHandler:^(NSError * _Nullable error, SDLSystemCapabilityManager * _Nonnull systemCapabilityManager) { - expect(error).to(equal(testConnectionManager.defaultError)); - expect(systemCapabilityManager.phoneCapability).to(beNil()); - done(); - }]; - - [testConnectionManager respondToLastRequestWithResponse:testGetSystemCapabilityResponse]; - }); - }); - - it(@"should should not save the capabilities", ^{ - expect(testSystemCapabilityManager.phoneCapability).to(beNil()); - }); + context(@"If the request succeeded", ^{ + beforeEach(^{ + testGetSystemCapabilityResponse.success = @YES; }); - context(@"If the request succeeded", ^{ - beforeEach(^{ - testGetSystemCapabilityResponse.success = @YES; - + it(@"should save the capabilitity", ^{ + waitUntilTimeout(1, ^(void (^done)(void)){ [testSystemCapabilityManager updateCapabilityType:testGetSystemCapabilityResponse.systemCapability.systemCapabilityType completionHandler:^(NSError * _Nullable error, SDLSystemCapabilityManager * _Nonnull systemCapabilityManager) { - // The handler will not be notifified + expect(testSystemCapabilityManager.phoneCapability).to(equal(testPhoneCapability)); + expect(error).to(beNil()); + done(); }]; - [testConnectionManager respondToLastRequestWithResponse:testGetSystemCapabilityResponse]; - }); + [NSThread sleepForTimeInterval:0.1]; - it(@"should not save the capabilities because a successful Get System Capability Response notification will be intercepted by the manager and be handled there", ^{ - expect(testSystemCapabilityManager.phoneCapability).to(beNil()); + [testConnectionManager respondToLastRequestWithResponse:testGetSystemCapabilityResponse]; }); }); }); @@ -357,7 +333,7 @@ describe(@"System capability manager", ^{ }); }); - fcontext(@"When the system capability manager is stopped after being started", ^{ + context(@"When the system capability manager is stopped after being started", ^{ beforeEach(^{ SDLRegisterAppInterfaceResponse *testRegisterAppInterfaceResponse = [[SDLRegisterAppInterfaceResponse alloc] init]; testRegisterAppInterfaceResponse.displayCapabilities = [[SDLDisplayCapabilities alloc] init]; |