summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Fischer <joeljfischer@gmail.com>2019-08-01 16:13:42 -0400
committerGitHub <noreply@github.com>2019-08-01 16:13:42 -0400
commitf43c7f46c0e535a322afbd76afb312bfa1fdeedc (patch)
tree1a966bafe3a8709e959d9bd0ee99a91638b4c09b
parent2cfac60d47843502b819f345d5202ea1893c48b2 (diff)
parent12d5bd61d7bd219a1d352f2add8a785671dcdecf (diff)
downloadsdl_ios-f43c7f46c0e535a322afbd76afb312bfa1fdeedc.tar.gz
Merge pull request #1351 from smartdevicelink/feature/issue-806-OpenMenuRPC
Implement SDL-0116 Open Menu RPC
-rw-r--r--SmartDeviceLink-iOS.podspec2
-rw-r--r--SmartDeviceLink-iOS.xcodeproj/project.pbxproj24
-rw-r--r--SmartDeviceLink.podspec2
-rw-r--r--SmartDeviceLink/SDLFunctionID.m1
-rw-r--r--SmartDeviceLink/SDLMenuManager.h5
-rw-r--r--SmartDeviceLink/SDLMenuManager.m43
-rw-r--r--SmartDeviceLink/SDLNotificationConstants.h2
-rw-r--r--SmartDeviceLink/SDLNotificationConstants.m3
-rw-r--r--SmartDeviceLink/SDLNotificationDispatcher.m8
-rw-r--r--SmartDeviceLink/SDLProxyListener.h16
-rw-r--r--SmartDeviceLink/SDLRPCFunctionNames.h1
-rw-r--r--SmartDeviceLink/SDLRPCFunctionNames.m1
-rw-r--r--SmartDeviceLink/SDLScreenManager.h13
-rw-r--r--SmartDeviceLink/SDLScreenManager.m12
-rw-r--r--SmartDeviceLink/SDLShowAppMenu.h35
-rw-r--r--SmartDeviceLink/SDLShowAppMenu.m48
-rw-r--r--SmartDeviceLink/SDLShowAppMenuResponse.h20
-rw-r--r--SmartDeviceLink/SDLShowAppMenuResponse.m23
-rw-r--r--SmartDeviceLink/SmartDeviceLink.h2
-rw-r--r--SmartDeviceLinkTests/DevAPISpecs/SDLMenuManagerSpec.m86
-rw-r--r--SmartDeviceLinkTests/Notifications/SDLNotificationDispatcherSpec.m2
-rw-r--r--SmartDeviceLinkTests/RPCSpecs/RequestSpecs/SDLShowAppMenuSpec.m50
-rw-r--r--SmartDeviceLinkTests/RPCSpecs/ResponseSpecs/SDLShowAppMenuResponseSpec.m19
-rw-r--r--SmartDeviceLinkTests/SDLScreenManagerSpec.m6
24 files changed, 422 insertions, 2 deletions
diff --git a/SmartDeviceLink-iOS.podspec b/SmartDeviceLink-iOS.podspec
index 66412c182..1f9316962 100644
--- a/SmartDeviceLink-iOS.podspec
+++ b/SmartDeviceLink-iOS.podspec
@@ -325,6 +325,8 @@ ss.public_header_files = [
'SmartDeviceLink/SDLSetMediaClockTimer.h',
'SmartDeviceLink/SDLSetMediaClockTimerResponse.h',
'SmartDeviceLink/SDLShow.h',
+'SmartDeviceLink/SDLShowAppMenu.h',
+'SmartDeviceLink/SDLShowAppMenuResponse.h',
'SmartDeviceLink/SDLShowConstantTBT.h',
'SmartDeviceLink/SDLShowConstantTBTResponse.h',
'SmartDeviceLink/SDLShowResponse.h',
diff --git a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj
index df83d8900..77acb13a2 100644
--- a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj
+++ b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj
@@ -1233,9 +1233,15 @@
752ECDB7228B4D6B00D945F4 /* SDLDynamicMenuUpdateAlgorithm.m in Sources */ = {isa = PBXBuildFile; fileRef = 752ECDB5228B4D6B00D945F4 /* SDLDynamicMenuUpdateAlgorithm.m */; };
752ECDB9228C42E100D945F4 /* SDLMenuRunScoreSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 752ECDB8228C42E100D945F4 /* SDLMenuRunScoreSpec.m */; };
752ECDBB228C532600D945F4 /* SDLMenuUpdateAlgorithmSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 752ECDBA228C532600D945F4 /* SDLMenuUpdateAlgorithmSpec.m */; };
+ 7538764F22D8CEDB00FE8484 /* SDLShowAppMenu.h in Headers */ = {isa = PBXBuildFile; fileRef = 7538764D22D8CEDB00FE8484 /* SDLShowAppMenu.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 7538765022D8CEDB00FE8484 /* SDLShowAppMenu.m in Sources */ = {isa = PBXBuildFile; fileRef = 7538764E22D8CEDB00FE8484 /* SDLShowAppMenu.m */; };
+ 7538765322D8D95100FE8484 /* SDLShowAppMenuResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 7538765122D8D95100FE8484 /* SDLShowAppMenuResponse.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 7538765422D8D95100FE8484 /* SDLShowAppMenuResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = 7538765222D8D95100FE8484 /* SDLShowAppMenuResponse.m */; };
+ 7538765622DCAF5400FE8484 /* SDLShowAppMenuSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 7538765522DCAF5400FE8484 /* SDLShowAppMenuSpec.m */; };
755F176222A00B7C0041B9CB /* SDLMenuManagerConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 755F176122A00B7C0041B9CB /* SDLMenuManagerConstants.h */; settings = {ATTRIBUTES = (Public, ); }; };
756C62762289F11F008B57A2 /* SDLDynamicMenuUpdateRunScore.h in Headers */ = {isa = PBXBuildFile; fileRef = 756C62742289F11F008B57A2 /* SDLDynamicMenuUpdateRunScore.h */; };
756C62772289F11F008B57A2 /* SDLDynamicMenuUpdateRunScore.m in Sources */ = {isa = PBXBuildFile; fileRef = 756C62752289F11F008B57A2 /* SDLDynamicMenuUpdateRunScore.m */; };
+ 75FF2E3822DF9D5900D0C13B /* SDLShowAppMenuResponseSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 75FF2E3722DF9D5900D0C13B /* SDLShowAppMenuResponseSpec.m */; };
75FF2E3B22E0DD5400D0C13B /* SDLMsgVersion.h in Headers */ = {isa = PBXBuildFile; fileRef = 75FF2E3922E0DD5400D0C13B /* SDLMsgVersion.h */; settings = {ATTRIBUTES = (Public, ); }; };
75FF2E3C22E0DD5400D0C13B /* SDLMsgVersion.m in Sources */ = {isa = PBXBuildFile; fileRef = 75FF2E3A22E0DD5400D0C13B /* SDLMsgVersion.m */; };
880245A420F79C3400ED195B /* SDLFileManagerConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 880245A220F79C3400ED195B /* SDLFileManagerConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -2900,9 +2906,15 @@
752ECDB5228B4D6B00D945F4 /* SDLDynamicMenuUpdateAlgorithm.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLDynamicMenuUpdateAlgorithm.m; sourceTree = "<group>"; };
752ECDB8228C42E100D945F4 /* SDLMenuRunScoreSpec.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLMenuRunScoreSpec.m; sourceTree = "<group>"; };
752ECDBA228C532600D945F4 /* SDLMenuUpdateAlgorithmSpec.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLMenuUpdateAlgorithmSpec.m; sourceTree = "<group>"; };
+ 7538764D22D8CEDB00FE8484 /* SDLShowAppMenu.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDLShowAppMenu.h; sourceTree = "<group>"; };
+ 7538764E22D8CEDB00FE8484 /* SDLShowAppMenu.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLShowAppMenu.m; sourceTree = "<group>"; };
+ 7538765122D8D95100FE8484 /* SDLShowAppMenuResponse.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDLShowAppMenuResponse.h; sourceTree = "<group>"; };
+ 7538765222D8D95100FE8484 /* SDLShowAppMenuResponse.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLShowAppMenuResponse.m; sourceTree = "<group>"; };
+ 7538765522DCAF5400FE8484 /* SDLShowAppMenuSpec.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLShowAppMenuSpec.m; sourceTree = "<group>"; };
755F176122A00B7C0041B9CB /* SDLMenuManagerConstants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDLMenuManagerConstants.h; sourceTree = "<group>"; };
756C62742289F11F008B57A2 /* SDLDynamicMenuUpdateRunScore.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDLDynamicMenuUpdateRunScore.h; sourceTree = "<group>"; };
756C62752289F11F008B57A2 /* SDLDynamicMenuUpdateRunScore.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLDynamicMenuUpdateRunScore.m; sourceTree = "<group>"; };
+ 75FF2E3722DF9D5900D0C13B /* SDLShowAppMenuResponseSpec.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLShowAppMenuResponseSpec.m; sourceTree = "<group>"; };
75FF2E3922E0DD5400D0C13B /* SDLMsgVersion.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDLMsgVersion.h; sourceTree = "<group>"; };
75FF2E3A22E0DD5400D0C13B /* SDLMsgVersion.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLMsgVersion.m; sourceTree = "<group>"; };
880245A220F79C3400ED195B /* SDLFileManagerConfiguration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDLFileManagerConfiguration.h; sourceTree = "<group>"; };
@@ -3463,6 +3475,7 @@
162E82581A9BDE8A00906325 /* SDLSetMediaClockTimerSpec.m */,
162E82591A9BDE8A00906325 /* SDLShowConstantTBTSpec.m */,
162E825A1A9BDE8A00906325 /* SDLShowSpec.m */,
+ 7538765522DCAF5400FE8484 /* SDLShowAppMenuSpec.m */,
162E825B1A9BDE8A00906325 /* SDLSliderSpec.m */,
162E825C1A9BDE8A00906325 /* SDLSpeakSpec.m */,
162E825D1A9BDE8A00906325 /* SDLSubscribeButtonSpec.m */,
@@ -3529,6 +3542,7 @@
162E82811A9BDE8A00906325 /* SDLSetMediaClockTimerResponseSpec.m */,
162E82821A9BDE8A00906325 /* SDLShowConstantTBTResponseSpec.m */,
162E82831A9BDE8A00906325 /* SDLShowResponseSpec.m */,
+ 75FF2E3722DF9D5900D0C13B /* SDLShowAppMenuResponseSpec.m */,
162E82841A9BDE8A00906325 /* SDLSliderResponseSpec.m */,
162E82851A9BDE8A00906325 /* SDLSpeakResponseSpec.m */,
162E82861A9BDE8A00906325 /* SDLSubscribeButtonResponseSpec.m */,
@@ -4203,6 +4217,8 @@
DA9F7E6E1DCBFFDB00ACAE48 /* SDLGetWayPoints.m */,
5D61FAFF1A84238A00846EE7 /* SDLListFiles.h */,
5D61FB001A84238A00846EE7 /* SDLListFiles.m */,
+ 7538764D22D8CEDB00FE8484 /* SDLShowAppMenu.h */,
+ 7538764E22D8CEDB00FE8484 /* SDLShowAppMenu.m */,
88AF11DA220B6B3D00A59985 /* SDLPerformAppServiceInteraction.h */,
88AF11DB220B6B3D00A59985 /* SDLPerformAppServiceInteraction.m */,
5D61FB381A84238B00846EE7 /* SDLPerformAudioPassThru.h */,
@@ -4364,6 +4380,8 @@
5D61FBA71A84238B00846EE7 /* SDLShowConstantTBTResponse.m */,
5D61FBA81A84238B00846EE7 /* SDLShowResponse.h */,
5D61FBA91A84238B00846EE7 /* SDLShowResponse.m */,
+ 7538765122D8D95100FE8484 /* SDLShowAppMenuResponse.h */,
+ 7538765222D8D95100FE8484 /* SDLShowAppMenuResponse.m */,
5D61FBB01A84238B00846EE7 /* SDLSliderResponse.h */,
5D61FBB11A84238B00846EE7 /* SDLSliderResponse.m */,
5D61FBBA1A84238B00846EE7 /* SDLSpeakResponse.h */,
@@ -6368,6 +6386,7 @@
5D61FC8A1A84238C00846EE7 /* SDLDiagnosticMessageResponse.h in Headers */,
5D61FC2D1A84238C00846EE7 /* SDLAddCommand.h in Headers */,
88B3BF9C20DA8BBC00943565 /* SDLFuelRange.h in Headers */,
+ 7538765322D8D95100FE8484 /* SDLShowAppMenuResponse.h in Headers */,
5D61FD931A84238C00846EE7 /* SDLShowConstantTBTResponse.h in Headers */,
5DBF06391E64ABBE00A5CF03 /* SDLLogConfiguration.h in Headers */,
5D61FCCB1A84238C00846EE7 /* SDLIgnitionStatus.h in Headers */,
@@ -6614,6 +6633,7 @@
88A5E7F7220B5BBC00495E8A /* SDLGetAppServiceData.h in Headers */,
1E5AD0441F1F5A1F0029B8AF /* SDLRadioControlCapabilities.h in Headers */,
88F65136220C74FD00CAF321 /* SDLWeatherData.h in Headers */,
+ 7538764F22D8CEDB00FE8484 /* SDLShowAppMenu.h in Headers */,
1E5AD0841F20B9290029B8AF /* SDLButtonPressResponse.h in Headers */,
1E5AD0681F2080B50029B8AF /* SDLRadioControlData.h in Headers */,
1E5AD0481F1F773E0029B8AF /* SDLModuleType.h in Headers */,
@@ -7095,6 +7115,7 @@
8881AFBF2225E9BB00EA870B /* SDLGetCloudAppPropertiesResponse.m in Sources */,
1E5AD0691F2080B50029B8AF /* SDLRadioControlData.m in Sources */,
888F86FE221DEE200052FE4C /* SDLAsynchronousRPCOperation.m in Sources */,
+ 7538765422D8D95100FE8484 /* SDLShowAppMenuResponse.m in Sources */,
5D61FCC01A84238C00846EE7 /* SDLHexUtility.m in Sources */,
5DB9964F1F26886C002D8795 /* SDLControlFramePayloadEndService.m in Sources */,
5D61FD821A84238C00846EE7 /* SDLSetAppIconResponse.m in Sources */,
@@ -7203,6 +7224,7 @@
5D61FC4E1A84238C00846EE7 /* SDLBitsPerSample.m in Sources */,
5D00AC701F1511B9004000D9 /* SDLGetSystemCapability.m in Sources */,
5D61FDEA1A84238C00846EE7 /* SDLUnsubscribeButtonResponse.m in Sources */,
+ 7538765022D8CEDB00FE8484 /* SDLShowAppMenu.m in Sources */,
1E5AD05D1F2064A80029B8AF /* SDLRDSData.m in Sources */,
5D61FCA61A84238C00846EE7 /* SDLEndAudioPassThruResponse.m in Sources */,
5D61FD281A84238C00846EE7 /* SDLPerformAudioPassThruResponse.m in Sources */,
@@ -7776,6 +7798,7 @@
162E834C1A9BDE8B00906325 /* SDLAlertResponseSpec.m in Sources */,
1680B11B1A9CD7AD00DBD79E /* SDLFunctionIDSpec.m in Sources */,
5DB1BCDA1D243D85002FFC37 /* SDLStateMachineSpec.m in Sources */,
+ 7538765622DCAF5400FE8484 /* SDLShowAppMenuSpec.m in Sources */,
8831FA4B2202402B00B8FFB7 /* SDLAppServicesCapabilitiesSpec.m in Sources */,
5D4346731E6F617D00B639C6 /* TestLogTarget.m in Sources */,
1EE8C43C1F347EAE00FDC2CF /* SDLTemperatureUnitSpec.m in Sources */,
@@ -7956,6 +7979,7 @@
162E82EC1A9BDE8B00906325 /* SDLLockScreenStatusSpec.m in Sources */,
DA96C0661D4D4F730022F520 /* SDLAppInfoSpec.m in Sources */,
162E832F1A9BDE8B00906325 /* SDLGetDTCsSpec.m in Sources */,
+ 75FF2E3822DF9D5900D0C13B /* SDLShowAppMenuResponseSpec.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/SmartDeviceLink.podspec b/SmartDeviceLink.podspec
index 06974750f..5e1f6be76 100644
--- a/SmartDeviceLink.podspec
+++ b/SmartDeviceLink.podspec
@@ -326,6 +326,8 @@ sdefault.public_header_files = [
'SmartDeviceLink/SDLSetMediaClockTimer.h',
'SmartDeviceLink/SDLSetMediaClockTimerResponse.h',
'SmartDeviceLink/SDLShow.h',
+'SmartDeviceLink/SDLShowAppMenu.h',
+'SmartDeviceLink/SDLShowAppMenuResponse.h',
'SmartDeviceLink/SDLShowConstantTBT.h',
'SmartDeviceLink/SDLShowConstantTBTResponse.h',
'SmartDeviceLink/SDLShowResponse.h',
diff --git a/SmartDeviceLink/SDLFunctionID.m b/SmartDeviceLink/SDLFunctionID.m
index d1940883c..80cc2437d 100644
--- a/SmartDeviceLink/SDLFunctionID.m
+++ b/SmartDeviceLink/SDLFunctionID.m
@@ -90,6 +90,7 @@ NS_ASSUME_NONNULL_BEGIN
@55: SDLRPCFunctionNamePerformAppServiceInteraction,
@56: SDLRPCFunctionNameUnpublishAppService,
@58: SDLRPCFunctionNameCloseApplication,
+ @59: SDLRPCFunctionNameShowAppMenu,
@32768: SDLRPCFunctionNameOnHMIStatus,
@32769: SDLRPCFunctionNameOnAppInterfaceUnregistered,
@32770: SDLRPCFunctionNameOnButtonEvent,
diff --git a/SmartDeviceLink/SDLMenuManager.h b/SmartDeviceLink/SDLMenuManager.h
index f559b6fb8..475c4195d 100644
--- a/SmartDeviceLink/SDLMenuManager.h
+++ b/SmartDeviceLink/SDLMenuManager.h
@@ -36,6 +36,11 @@ typedef void(^SDLMenuUpdateCompletionHandler)(NSError *__nullable error);
@property (copy, nonatomic) NSArray<SDLMenuCell *> *menuCells;
@property (assign, nonatomic) SDLDynamicMenuUpdatesMode dynamicMenuUpdatesMode;
+
+- (BOOL)openMenu;
+
+- (BOOL)openSubmenu:(SDLMenuCell *)cell;
+
@end
NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLMenuManager.m b/SmartDeviceLink/SDLMenuManager.m
index 3f95a5353..1ca796dcc 100644
--- a/SmartDeviceLink/SDLMenuManager.m
+++ b/SmartDeviceLink/SDLMenuManager.m
@@ -18,6 +18,7 @@
#import "SDLDisplayCapabilities+ShowManagerExtensions.h"
#import "SDLError.h"
#import "SDLFileManager.h"
+#import "SDLGlobals.h"
#import "SDLImage.h"
#import "SDLLogMacros.h"
#import "SDLMenuCell.h"
@@ -31,6 +32,8 @@
#import "SDLRPCResponseNotification.h"
#import "SDLSetDisplayLayoutResponse.h"
#import "SDLScreenManager.h"
+#import "SDLShowAppMenu.h"
+#import "SDLVersion.h"
#import "SDLVoiceCommand.h"
NS_ASSUME_NONNULL_BEGIN
@@ -638,6 +641,46 @@ UInt32 const MenuCellIdMin = 1;
}
}
+- (BOOL)openMenu {
+ if ([SDLGlobals.sharedGlobals.rpcVersion isLessThanVersion:[[SDLVersion alloc] initWithMajor:6 minor:0 patch:0]]) {
+ SDLLogE(@"The openMenu method is not supported on this head unit.");
+ return NO;
+ }
+
+ SDLShowAppMenu *openMenu = [[SDLShowAppMenu alloc] init];
+
+ [self.connectionManager sendConnectionRequest:openMenu withResponseHandler:^(__kindof SDLRPCRequest * _Nullable request, __kindof SDLRPCResponse * _Nullable response, NSError * _Nullable error) {
+ if (error != nil) {
+ SDLLogE(@"Error opening application menu: %@", error);
+ }
+ }];
+
+ return YES;
+}
+
+- (BOOL)openSubmenu:(SDLMenuCell *)cell {
+ if (cell.subCells.count == 0) {
+ SDLLogE(@"The cell %@ does not contain any sub cells, so no submenu can be opened", cell);
+ return NO;
+ } else if ([SDLGlobals.sharedGlobals.rpcVersion isLessThanVersion:[[SDLVersion alloc] initWithMajor:6 minor:0 patch:0]]) {
+ SDLLogE(@"The openSubmenu method is not supported on this head unit.");
+ return NO;
+ } else if (![self.menuCells containsObject:cell]) {
+ SDLLogE(@"This cell has not been sent to the head unit, so no submenu can be opened. Make sure that the cell exists in the SDLManager.menu array");
+ return NO;
+ }
+
+ SDLShowAppMenu *subMenu = [[SDLShowAppMenu alloc] initWithMenuID:cell.cellId];
+
+ [self.connectionManager sendConnectionRequest:subMenu withResponseHandler:^(__kindof SDLRPCRequest * _Nullable request, __kindof SDLRPCResponse * _Nullable response, NSError * _Nullable error) {
+ if (error != nil) {
+ SDLLogE(@"Error opening application to submenu cell: %@, with error: %@", cell, error);
+ }
+ }];
+
+ return YES;
+}
+
@end
NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLNotificationConstants.h b/SmartDeviceLink/SDLNotificationConstants.h
index df651dfe9..995923606 100644
--- a/SmartDeviceLink/SDLNotificationConstants.h
+++ b/SmartDeviceLink/SDLNotificationConstants.h
@@ -161,6 +161,7 @@ extern SDLNotificationName const SDLDidReceiveSetInteriorVehicleDataResponse;
extern SDLNotificationName const SDLDidReceiveSetMediaClockTimerResponse;
extern SDLNotificationName const SDLDidReceiveShowConstantTBTResponse;
extern SDLNotificationName const SDLDidReceiveShowResponse;
+extern SDLNotificationName const SDLDidReceiveShowAppMenuResponse;
extern SDLNotificationName const SDLDidReceiveSliderResponse;
extern SDLNotificationName const SDLDidReceiveSpeakResponse;
extern SDLNotificationName const SDLDidReceiveSubscribeButtonResponse;
@@ -221,6 +222,7 @@ extern SDLNotificationName const SDLDidReceiveSetGlobalPropertiesRequest;
extern SDLNotificationName const SDLDidReceiveSetInteriorVehicleDataRequest;
extern SDLNotificationName const SDLDidReceiveSetMediaClockTimerRequest;
extern SDLNotificationName const SDLDidReceiveShowRequest;
+extern SDLNotificationName const SDLDidReceiveShowAppMenuRequest;
extern SDLNotificationName const SDLDidReceiveShowConstantTBTRequest;
extern SDLNotificationName const SDLDidReceiveSliderRequest;
extern SDLNotificationName const SDLDidReceiveSpeakRequest;
diff --git a/SmartDeviceLink/SDLNotificationConstants.m b/SmartDeviceLink/SDLNotificationConstants.m
index ff56baac0..7e0083a51 100644
--- a/SmartDeviceLink/SDLNotificationConstants.m
+++ b/SmartDeviceLink/SDLNotificationConstants.m
@@ -69,6 +69,7 @@ SDLNotificationName const SDLDidReceiveSetInteriorVehicleDataResponse = @"com.sd
SDLNotificationName const SDLDidReceiveSetMediaClockTimerResponse = @"com.sdl.response.setMediaClockTimer";
SDLNotificationName const SDLDidReceiveShowConstantTBTResponse = @"com.sdl.response.showConstantTBT";
SDLNotificationName const SDLDidReceiveShowResponse = @"com.sdl.response.show";
+SDLNotificationName const SDLDidReceiveShowAppMenuResponse = @"com.sdl.response.showAppMenu";
SDLNotificationName const SDLDidReceiveSliderResponse = @"com.sdl.response.slider";
SDLNotificationName const SDLDidReceiveSpeakResponse = @"com.sdl.response.speak";
SDLNotificationName const SDLDidReceiveSubscribeButtonResponse = @"com.sdl.response.subscribeButton";
@@ -126,6 +127,7 @@ SDLNotificationName const SDLDidReceiveSetGlobalPropertiesRequest = @"com.sdl.re
SDLNotificationName const SDLDidReceiveSetInteriorVehicleDataRequest = @"com.sdl.request.setInteriorVehicleData";
SDLNotificationName const SDLDidReceiveSetMediaClockTimerRequest = @"com.sdl.request.setMediaClockTimer";
SDLNotificationName const SDLDidReceiveShowRequest = @"com.sdl.request.show";
+SDLNotificationName const SDLDidReceiveShowAppMenuRequest = @"com.sdl.request.showAppMenu";
SDLNotificationName const SDLDidReceiveShowConstantTBTRequest = @"com.sdl.request.showConstantTBT";
SDLNotificationName const SDLDidReceiveSliderRequest = @"com.sdl.request.slider";
SDLNotificationName const SDLDidReceiveSpeakRequest = @"com.sdl.request.speak";
@@ -214,6 +216,7 @@ SDLNotificationName const SDLDidReceiveWaypointNotification = @"com.sdl.notifica
SDLDidReceiveSetMediaClockTimerResponse,
SDLDidReceiveShowConstantTBTResponse,
SDLDidReceiveShowResponse,
+ SDLDidReceiveShowAppMenuResponse,
SDLDidReceiveSliderResponse,
SDLDidReceiveSpeakResponse,
SDLDidReceiveSubscribeButtonResponse,
diff --git a/SmartDeviceLink/SDLNotificationDispatcher.m b/SmartDeviceLink/SDLNotificationDispatcher.m
index 4bf552e17..c45aa658a 100644
--- a/SmartDeviceLink/SDLNotificationDispatcher.m
+++ b/SmartDeviceLink/SDLNotificationDispatcher.m
@@ -275,6 +275,10 @@ NS_ASSUME_NONNULL_BEGIN
[self postRPCResponseNotification:SDLDidReceiveShowResponse response:response];
}
+- (void)onShowAppMenuResponse:(SDLShowAppMenuResponse *)response {
+ [self postRPCResponseNotification:SDLDidReceiveShowAppMenuResponse response:response];
+}
+
- (void)onSliderResponse:(SDLSliderResponse *)response {
[self postRPCResponseNotification:SDLDidReceiveSliderResponse response:response];
}
@@ -497,6 +501,10 @@ NS_ASSUME_NONNULL_BEGIN
[self postRPCRequestNotification:SDLDidReceiveShowRequest request:request];
}
+- (void)onShowAppMenu:(SDLShowAppMenu *)request {
+ [self postRPCRequestNotification:SDLDidReceiveShowAppMenuRequest request:request];
+}
+
- (void)onShowConstantTBT:(SDLShowConstantTBT *)request {
[self postRPCRequestNotification:SDLDidReceiveShowConstantTBTRequest request:request];
}
diff --git a/SmartDeviceLink/SDLProxyListener.h b/SmartDeviceLink/SDLProxyListener.h
index de1384286..c95a64383 100644
--- a/SmartDeviceLink/SDLProxyListener.h
+++ b/SmartDeviceLink/SDLProxyListener.h
@@ -112,6 +112,8 @@
@class SDLSetMediaClockTimer;
@class SDLSetMediaClockTimerResponse;
@class SDLShow;
+@class SDLShowAppMenu;
+@class SDLShowAppMenuResponse;
@class SDLShowConstantTBT;
@class SDLShowConstantTBTResponse;
@class SDLShowResponse;
@@ -496,6 +498,13 @@ NS_ASSUME_NONNULL_BEGIN
- (void)onShowResponse:(SDLShowResponse *)response;
/**
+ * Called when a ShowAppMenu Response is received from Core
+ *
+ * @param response A SDLShowAppMenuResponse object
+ */
+- (void)onShowAppMenuResponse:(SDLShowAppMenuResponse *)response;
+
+/**
* Called when a Slider Response is received from Core
*
* @param response A SDLSliderResponse object
@@ -883,6 +892,13 @@ NS_ASSUME_NONNULL_BEGIN
- (void)onShow:(SDLShow *)request;
/**
+ * Called when a `ShowAppMenu` is received from Core
+ *
+ * @param request A SDLShowAppMenu object
+ */
+- (void)onShowAppMenu:(SDLShowAppMenu *)request;
+
+/**
* Called when a `ShowConstantTBT` request is received from Core
*
* @param request A SDLShowConstantTBT object
diff --git a/SmartDeviceLink/SDLRPCFunctionNames.h b/SmartDeviceLink/SDLRPCFunctionNames.h
index f6aabf081..fa3cce56d 100644
--- a/SmartDeviceLink/SDLRPCFunctionNames.h
+++ b/SmartDeviceLink/SDLRPCFunctionNames.h
@@ -81,6 +81,7 @@ extern SDLRPCFunctionName const SDLRPCFunctionNameSetGlobalProperties;
extern SDLRPCFunctionName const SDLRPCFunctionNameSetInteriorVehicleData;
extern SDLRPCFunctionName const SDLRPCFunctionNameSetMediaClockTimer;
extern SDLRPCFunctionName const SDLRPCFunctionNameShow;
+extern SDLRPCFunctionName const SDLRPCFunctionNameShowAppMenu;
extern SDLRPCFunctionName const SDLRPCFunctionNameShowConstantTBT;
extern SDLRPCFunctionName const SDLRPCFunctionNameSlider;
extern SDLRPCFunctionName const SDLRPCFunctionNameSpeak;
diff --git a/SmartDeviceLink/SDLRPCFunctionNames.m b/SmartDeviceLink/SDLRPCFunctionNames.m
index 2ca574da0..4aceed985 100644
--- a/SmartDeviceLink/SDLRPCFunctionNames.m
+++ b/SmartDeviceLink/SDLRPCFunctionNames.m
@@ -76,6 +76,7 @@ SDLRPCFunctionName const SDLRPCFunctionNameSetGlobalProperties = @"SetGlobalProp
SDLRPCFunctionName const SDLRPCFunctionNameSetInteriorVehicleData = @"SetInteriorVehicleData";
SDLRPCFunctionName const SDLRPCFunctionNameSetMediaClockTimer = @"SetMediaClockTimer";
SDLRPCFunctionName const SDLRPCFunctionNameShow = @"Show";
+SDLRPCFunctionName const SDLRPCFunctionNameShowAppMenu = @"ShowAppMenu";
SDLRPCFunctionName const SDLRPCFunctionNameShowConstantTBT = @"ShowConstantTBT";
SDLRPCFunctionName const SDLRPCFunctionNameSlider = @"Slider";
SDLRPCFunctionName const SDLRPCFunctionNameSpeak = @"Speak";
diff --git a/SmartDeviceLink/SDLScreenManager.h b/SmartDeviceLink/SDLScreenManager.h
index ce2d2b2d6..412f7b4f7 100644
--- a/SmartDeviceLink/SDLScreenManager.h
+++ b/SmartDeviceLink/SDLScreenManager.h
@@ -282,6 +282,19 @@ If set to `SDLDynamicMenuUpdatesModeForceOff`, menu updates will work the legacy
*/
- (void)presentKeyboardWithInitialText:(NSString *)initialText delegate:(id<SDLKeyboardDelegate>)delegate;
+#pragma mark Menu
+/**
+ Present the top-level of your application menu. This method should be called if the menu needs to be opened programmatically because the built in menu button is hidden.
+ */
+- (BOOL)openMenu;
+
+/**
+ Present the application menu. This method should be called if the menu needs to be opened programmatically because the built in menu button is hidden. You must update the menu with the proper cells before calling this method. This RPC will fail if the cell does not contain a sub menu, or is not in the menu array.
+
+@param cell The submenu cell that should be opened as a sub menu, with its sub cells as the options.
+ */
+- (BOOL)openSubmenu:(SDLMenuCell *)cell;
+
@end
NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLScreenManager.m b/SmartDeviceLink/SDLScreenManager.m
index 4e5c06314..d03791ac5 100644
--- a/SmartDeviceLink/SDLScreenManager.m
+++ b/SmartDeviceLink/SDLScreenManager.m
@@ -13,7 +13,6 @@
#import "SDLSoftButtonManager.h"
#import "SDLTextAndGraphicManager.h"
#import "SDLVoiceCommandManager.h"
-
NS_ASSUME_NONNULL_BEGIN
@interface SDLScreenManager()
@@ -268,6 +267,17 @@ NS_ASSUME_NONNULL_BEGIN
[self.choiceSetManager presentKeyboardWithInitialText:initialText delegate:delegate];
}
+#pragma mark - Menu
+
+- (BOOL)openMenu {
+ return [self.menuManager openMenu];
+}
+
+- (BOOL)openSubmenu:(SDLMenuCell *)cell {
+ return [self.menuManager openSubmenu:cell];
+}
+
+
@end
NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLShowAppMenu.h b/SmartDeviceLink/SDLShowAppMenu.h
new file mode 100644
index 000000000..a7ca2cf0f
--- /dev/null
+++ b/SmartDeviceLink/SDLShowAppMenu.h
@@ -0,0 +1,35 @@
+//
+// SDLOpenMenu.h
+// SmartDeviceLink
+//
+// Created by Justin Gluck on 7/12/19.
+// Copyright © 2019 smartdevicelink. All rights reserved.
+//
+
+#import "SDLRPCRequest.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ Used by an app to show the app's menu, typically this is used by a navigation app if the menu button is hidden.
+
+ Added in SmartDeviceLink 6.0
+ */
+@interface SDLShowAppMenu : SDLRPCRequest
+
+/**
+ Creates a ShowAppMenu RPC to open the app menu directly to a AddSubMenu RPC's submenu.
+
+ @param menuID The ID of the AddSubMenu to open
+ @return SDLShowAppMenu RPCRequest
+ */
+- (instancetype)initWithMenuID:(UInt32)menuID;
+
+/**
+ A Menu ID that identifies the AddSubMenu to open if it correlates with the AddSubMenu menuID parameter. If not set the top level menu will be opened.
+ */
+@property (nullable, strong, nonatomic) NSNumber<SDLInt> *menuID;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLShowAppMenu.m b/SmartDeviceLink/SDLShowAppMenu.m
new file mode 100644
index 000000000..d93b8480d
--- /dev/null
+++ b/SmartDeviceLink/SDLShowAppMenu.m
@@ -0,0 +1,48 @@
+//
+// SDLOpenMenu.m
+// SmartDeviceLink
+//
+// Created by Justin Gluck on 7/12/19.
+// Copyright © 2019 smartdevicelink. All rights reserved.
+//
+
+#import "SDLShowAppMenu.h"
+#import "NSMutableDictionary+Store.h"
+#import "SDLRPCParameterNames.h"
+#import "SDLRPCFunctionNames.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@implementation SDLShowAppMenu
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+- (instancetype)init {
+ if (self = [super initWithName:SDLRPCFunctionNameShowAppMenu]) {
+ }
+ return self;
+}
+#pragma clang diagnostic pop
+
+- (instancetype)initWithMenuID:(UInt32)menuID {
+ self = [self init];
+ if (!self) {
+ return nil;
+ }
+
+ self.menuID = @(menuID);
+ return self;
+}
+
+- (void)setMenuID:(nullable NSNumber<SDLInt> *)menuID {
+ [self.parameters sdl_setObject:menuID forName:SDLRPCParameterNameMenuId];
+}
+
+- (nullable NSNumber<SDLInt> *)menuID {
+ NSError *error = nil;
+ return [self.parameters sdl_objectForName:SDLRPCParameterNameMenuId ofClass:NSNumber.class error:&error];
+}
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLShowAppMenuResponse.h b/SmartDeviceLink/SDLShowAppMenuResponse.h
new file mode 100644
index 000000000..d5acd4c34
--- /dev/null
+++ b/SmartDeviceLink/SDLShowAppMenuResponse.h
@@ -0,0 +1,20 @@
+//
+// SDLOpenMenuResponse.h
+// SmartDeviceLink
+//
+// Created by Justin Gluck on 7/12/19.
+// Copyright © 2019 smartdevicelink. All rights reserved.
+//
+
+#import "SDLRPCResponse.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ * Response to the request to show the app menu.
+ */
+@interface SDLShowAppMenuResponse : SDLRPCResponse
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLShowAppMenuResponse.m b/SmartDeviceLink/SDLShowAppMenuResponse.m
new file mode 100644
index 000000000..281079e7b
--- /dev/null
+++ b/SmartDeviceLink/SDLShowAppMenuResponse.m
@@ -0,0 +1,23 @@
+//
+// SDLOpenMenuResponse.m
+// SmartDeviceLink
+//
+// Created by Justin Gluck on 7/12/19.
+// Copyright © 2019 smartdevicelink. All rights reserved.
+//
+
+#import "SDLShowAppMenuResponse.h"
+#import "SDLRPCFunctionNames.h"
+
+@implementation SDLShowAppMenuResponse
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+- (instancetype)init {
+ if (self = [super initWithName:SDLRPCFunctionNameShowAppMenu]) {
+ }
+ return self;
+}
+#pragma clang diagnostic pop
+
+@end
diff --git a/SmartDeviceLink/SmartDeviceLink.h b/SmartDeviceLink/SmartDeviceLink.h
index 661e88fbe..4d7e2e052 100644
--- a/SmartDeviceLink/SmartDeviceLink.h
+++ b/SmartDeviceLink/SmartDeviceLink.h
@@ -62,6 +62,7 @@ FOUNDATION_EXPORT const unsigned char SmartDeviceLinkVersionString[];
#import "SDLSetInteriorVehicleData.h"
#import "SDLSetMediaClockTimer.h"
#import "SDLShow.h"
+#import "SDLShowAppMenu.h"
#import "SDLShowConstantTBT.h"
#import "SDLSlider.h"
#import "SDLSpeak.h"
@@ -123,6 +124,7 @@ FOUNDATION_EXPORT const unsigned char SmartDeviceLinkVersionString[];
#import "SDLSetMediaClockTimerResponse.h"
#import "SDLShowConstantTBTResponse.h"
#import "SDLShowResponse.h"
+#import "SDLShowAppMenuResponse.h"
#import "SDLSliderResponse.h"
#import "SDLSpeakResponse.h"
#import "SDLSubscribeButtonResponse.h"
diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLMenuManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLMenuManagerSpec.m
index 6980fb02a..ba91df0d6 100644
--- a/SmartDeviceLinkTests/DevAPISpecs/SDLMenuManagerSpec.m
+++ b/SmartDeviceLinkTests/DevAPISpecs/SDLMenuManagerSpec.m
@@ -6,6 +6,7 @@
#import "SDLMenuManager.h"
#import "TestConnectionManager.h"
+#import "SDLGlobals.h"
@interface SDLMenuCell()
@@ -610,6 +611,91 @@ describe(@"menu manager", ^{
});
});
+ describe(@"ShowMenu RPC", ^{
+ beforeEach(^{
+ testManager.currentHMILevel = SDLHMILevelFull;
+ testManager.currentSystemContext = SDLSystemContextMain;
+ testManager.displayCapabilities = [[SDLDisplayCapabilities alloc] init];
+ });
+
+ context(@"when open menu RPC can be sent", ^{
+ beforeEach(^{
+ SDLVersion *oldVersion = [SDLVersion versionWithMajor:6 minor:0 patch:0];
+ id globalMock = OCMPartialMock([SDLGlobals sharedGlobals]);
+ OCMStub([globalMock rpcVersion]).andReturn(oldVersion);
+ });
+
+ it(@"should send showAppMenu RPC", ^{
+ BOOL canSendRPC = [testManager openMenu];
+
+ NSPredicate *showMenu = [NSPredicate predicateWithFormat:@"self isMemberOfClass: %@", [SDLShowAppMenu class]];
+ NSArray *openMenu = [[mockConnectionManager.receivedRequests copy] filteredArrayUsingPredicate:showMenu];
+
+ expect(mockConnectionManager.receivedRequests).toNot(beEmpty());
+ expect(openMenu).to(haveCount(1));
+ expect(canSendRPC).to(equal(YES));
+ });
+
+ it(@"should send showAppMenu RPC with cellID", ^ {
+ testManager.menuCells = @[submenuCell];
+ [mockConnectionManager respondToLastMultipleRequestsWithSuccess:YES];
+ [mockConnectionManager respondToLastMultipleRequestsWithSuccess:YES];
+
+ BOOL canSendRPC = [testManager openSubmenu:submenuCell];
+
+ NSPredicate *addSubmenuPredicate = [NSPredicate predicateWithFormat:@"self isMemberOfClass: %@", [SDLShowAppMenu class]];
+ NSArray *openMenu = [[mockConnectionManager.receivedRequests copy] filteredArrayUsingPredicate:addSubmenuPredicate];
+
+ expect(mockConnectionManager.receivedRequests).toNot(beEmpty());
+ expect(openMenu).to(haveCount(1));
+ expect(canSendRPC).to(equal(YES));
+ });
+ });
+
+ context(@"when open menu RPC can not be sent", ^{
+ it(@"should not send a showAppMenu RPC when cell has no subcells", ^ {
+ BOOL canSendRPC = [testManager openSubmenu:textOnlyCell];
+
+ NSPredicate *addSubmenuPredicate = [NSPredicate predicateWithFormat:@"self isMemberOfClass: %@", [SDLShowAppMenu class]];
+ NSArray *openMenu = [[mockConnectionManager.receivedRequests copy] filteredArrayUsingPredicate:addSubmenuPredicate];
+
+ expect(mockConnectionManager.receivedRequests).to(beEmpty());
+ expect(openMenu).to(haveCount(0));
+ expect(canSendRPC).to(equal(NO));
+ });
+
+ it(@"should not send a showAppMenu RPC when RPC verison is not at least 6.0.0", ^ {
+ SDLVersion *oldVersion = [SDLVersion versionWithMajor:5 minor:0 patch:0];
+ id globalMock = OCMPartialMock([SDLGlobals sharedGlobals]);
+ OCMStub([globalMock rpcVersion]).andReturn(oldVersion);
+
+ BOOL canSendRPC = [testManager openSubmenu:submenuCell];
+
+ NSPredicate *addSubmenuPredicate = [NSPredicate predicateWithFormat:@"self isMemberOfClass: %@", [SDLShowAppMenu class]];
+ NSArray *openMenu = [[mockConnectionManager.receivedRequests copy] filteredArrayUsingPredicate:addSubmenuPredicate];
+
+ expect(mockConnectionManager.receivedRequests).to(beEmpty());
+ expect(openMenu).to(haveCount(0));
+ expect(canSendRPC).to(equal(NO));
+ });
+
+ it(@"should not send a showAppMenu RPC when the cell is not in the menu array", ^ {
+ SDLVersion *oldVersion = [SDLVersion versionWithMajor:6 minor:0 patch:0];
+ id globalMock = OCMPartialMock([SDLGlobals sharedGlobals]);
+ OCMStub([globalMock rpcVersion]).andReturn(oldVersion);
+
+ BOOL canSendRPC = [testManager openSubmenu:submenuCell];
+
+ NSPredicate *addSubmenuPredicate = [NSPredicate predicateWithFormat:@"self isMemberOfClass: %@", [SDLShowAppMenu class]];
+ NSArray *openMenu = [[mockConnectionManager.receivedRequests copy] filteredArrayUsingPredicate:addSubmenuPredicate];
+
+ expect(mockConnectionManager.receivedRequests).to(beEmpty());
+ expect(openMenu).to(haveCount(0));
+ expect(canSendRPC).to(equal(NO));
+ });
+ });
+ });
+
afterEach(^{
testManager = nil;
});
diff --git a/SmartDeviceLinkTests/Notifications/SDLNotificationDispatcherSpec.m b/SmartDeviceLinkTests/Notifications/SDLNotificationDispatcherSpec.m
index 5b3f87212..cfa34340d 100644
--- a/SmartDeviceLinkTests/Notifications/SDLNotificationDispatcherSpec.m
+++ b/SmartDeviceLinkTests/Notifications/SDLNotificationDispatcherSpec.m
@@ -69,6 +69,7 @@ describe(@"a notification dispatcher", ^{
expect(@([testDispatcher respondsToSelector:@selector(onSetMediaClockTimerResponse:)])).to(beTruthy());
expect(@([testDispatcher respondsToSelector:@selector(onShowConstantTBTResponse:)])).to(beTruthy());
expect(@([testDispatcher respondsToSelector:@selector(onShowResponse:)])).to(beTruthy());
+ expect(@([testDispatcher respondsToSelector:@selector(onShowAppMenuResponse:)])).to(beTruthy());
expect(@([testDispatcher respondsToSelector:@selector(onSliderResponse:)])).to(beTruthy());
expect(@([testDispatcher respondsToSelector:@selector(onSpeakResponse:)])).to(beTruthy());
expect(@([testDispatcher respondsToSelector:@selector(onSubscribeButtonResponse:)])).to(beTruthy());
@@ -122,6 +123,7 @@ describe(@"a notification dispatcher", ^{
expect(@([testDispatcher respondsToSelector:@selector(onSetInteriorVehicleData:)])).to(beTruthy());
expect(@([testDispatcher respondsToSelector:@selector(onSetMediaClockTimer:)])).to(beTruthy());
expect(@([testDispatcher respondsToSelector:@selector(onShow:)])).to(beTruthy());
+ expect(@([testDispatcher respondsToSelector:@selector(onShowAppMenu:)])).to(beTruthy());
expect(@([testDispatcher respondsToSelector:@selector(onShowConstantTBT:)])).to(beTruthy());
expect(@([testDispatcher respondsToSelector:@selector(onSlider:)])).to(beTruthy());
expect(@([testDispatcher respondsToSelector:@selector(onSpeak:)])).to(beTruthy());
diff --git a/SmartDeviceLinkTests/RPCSpecs/RequestSpecs/SDLShowAppMenuSpec.m b/SmartDeviceLinkTests/RPCSpecs/RequestSpecs/SDLShowAppMenuSpec.m
new file mode 100644
index 000000000..4557c014a
--- /dev/null
+++ b/SmartDeviceLinkTests/RPCSpecs/RequestSpecs/SDLShowAppMenuSpec.m
@@ -0,0 +1,50 @@
+//
+// SDLShowAppMenuSpec.m
+// SmartDeviceLinkTests
+//
+// Created by Justin Gluck on 7/15/19.
+// Copyright © 2019 smartdevicelink. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+#import <Quick/Quick.h>
+#import <Nimble/Nimble.h>
+
+#import "SDLRPCParameterNames.h"
+#import "SDLRPCFunctionNames.h"
+#import "SDLShowAppMenu.h"
+
+QuickSpecBegin(SDLShowAppMenuSpec)
+describe(@"Getter/Setter Tests", ^ {
+ __block UInt32 menuId = 4345645;
+
+ it(@"Should set and get correctly", ^ {
+ SDLShowAppMenu *testRequest = [[SDLShowAppMenu alloc] init];
+
+ testRequest.menuID = @(menuId);
+
+ expect(testRequest.menuID).to(equal(testRequest.menuID));
+ });
+
+ it(@"Should get correctly when initialized with dictonary", ^ {
+ NSDictionary<NSString *, id> *dict = [@{SDLRPCParameterNameRequest:
+ @{SDLRPCParameterNameParameters:
+ @{SDLRPCParameterNameMenuId:@4345645,
+ },
+ SDLRPCParameterNameOperationName:SDLRPCFunctionNameShowAppMenu}} mutableCopy];
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+ SDLShowAppMenu* testRequest = [[SDLShowAppMenu alloc] initWithDictionary:dict];
+#pragma clang diagnostic pop
+ expect(testRequest.menuID).to(equal(@(menuId)));
+ });
+
+ it(@"Should return nil if not set", ^ {
+ SDLShowAppMenu *testRequest = [[SDLShowAppMenu alloc] init];
+
+ expect(testRequest.menuID).to(beNil());
+ });
+
+});
+QuickSpecEnd
diff --git a/SmartDeviceLinkTests/RPCSpecs/ResponseSpecs/SDLShowAppMenuResponseSpec.m b/SmartDeviceLinkTests/RPCSpecs/ResponseSpecs/SDLShowAppMenuResponseSpec.m
new file mode 100644
index 000000000..7d32948a5
--- /dev/null
+++ b/SmartDeviceLinkTests/RPCSpecs/ResponseSpecs/SDLShowAppMenuResponseSpec.m
@@ -0,0 +1,19 @@
+//
+// SDLShowAppMenuResponseSpec.m
+// SmartDeviceLinkTests
+//
+// Created by Justin Gluck on 7/17/19.
+// Copyright © 2019 smartdevicelink. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+#import <Quick/Quick.h>
+#import <Nimble/Nimble.h>
+
+#import "SDLShowResponse.h"
+#import "SDLRPCParameterNames.h"
+
+QuickSpecBegin(SDLShowAppMenuResponseSpec)
+
+QuickSpecEnd
diff --git a/SmartDeviceLinkTests/SDLScreenManagerSpec.m b/SmartDeviceLinkTests/SDLScreenManagerSpec.m
index 5bb3943c5..02882be78 100644
--- a/SmartDeviceLinkTests/SDLScreenManagerSpec.m
+++ b/SmartDeviceLinkTests/SDLScreenManagerSpec.m
@@ -11,12 +11,15 @@
#import "SDLSoftButtonState.h"
#import "SDLTextAndGraphicManager.h"
#import "TestConnectionManager.h"
+#import "SDLVersion.h"
+#import "SDLGlobals.h"
+#import "SDLMenuCell.h"
+#import "SDLMenuManager.h"
@interface SDLSoftButtonManager()
@property (weak, nonatomic) id<SDLConnectionManagerType> connectionManager;
@property (weak, nonatomic) SDLFileManager *fileManager;
-
@property (strong, nonatomic) NSOperationQueue *transactionQueue;
@property (copy, nonatomic, nullable) SDLHMILevel currentLevel;
@@ -36,6 +39,7 @@
@property (strong, nonatomic) SDLTextAndGraphicManager *textAndGraphicManager;
@property (strong, nonatomic) SDLSoftButtonManager *softButtonManager;
+@property (strong, nonatomic) SDLMenuManager *menuManager;
@end