summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicoleYarroch <nicole@livio.io>2018-05-22 09:42:34 -0400
committerNicoleYarroch <nicole@livio.io>2018-05-22 09:42:34 -0400
commit7854e92a8ad339d82ee11a797df1bc3ddb75413b (patch)
tree976785d74d60fcfe2efd8df78102e64a0407b677
parent1c0930c8c5bf31e26a2fea8ff9d1fce06a5757d4 (diff)
parent84c6e6f99a4aff5b62d48d9d07f4cd98ea78f80e (diff)
downloadsdl_ios-7854e92a8ad339d82ee11a797df1bc3ddb75413b.tar.gz
Merge branch 'develop' into bug/issue_97_add_remaining_documentation
Signed-off-by: NicoleYarroch <nicole@livio.io> # Conflicts: # SmartDeviceLink/SDLProtocolHeader.h # SmartDeviceLink/SDLShow.h
-rw-r--r--SmartDeviceLink-Example-Swift-Info.plist81
-rw-r--r--SmartDeviceLink-iOS.podspec17
-rw-r--r--SmartDeviceLink-iOS.xcodeproj/project.pbxproj912
-rw-r--r--SmartDeviceLink.podspec17
-rw-r--r--SmartDeviceLink/SDLAbstractProtocol.h38
-rw-r--r--SmartDeviceLink/SDLAbstractProtocol.m77
-rw-r--r--SmartDeviceLink/SDLAbstractTransport.m34
-rw-r--r--SmartDeviceLink/SDLArtwork.m24
-rw-r--r--SmartDeviceLink/SDLAsynchronousRPCRequestOperation.h2
-rw-r--r--SmartDeviceLink/SDLAsynchronousRPCRequestOperation.m9
-rw-r--r--SmartDeviceLink/SDLConnectionManagerType.h4
-rw-r--r--SmartDeviceLink/SDLDisplayCapabilities+ShowManagerExtensions.m4
-rw-r--r--SmartDeviceLink/SDLError.h8
-rw-r--r--SmartDeviceLink/SDLError.m9
-rw-r--r--SmartDeviceLink/SDLErrorConstants.h4
-rw-r--r--SmartDeviceLink/SDLFile.m24
-rw-r--r--SmartDeviceLink/SDLFocusableItemLocator.m4
-rw-r--r--SmartDeviceLink/SDLFocusableItemLocatorType.h8
-rw-r--r--SmartDeviceLink/SDLIAPTransport.h6
-rw-r--r--SmartDeviceLink/SDLLifecycleManager.h2
-rw-r--r--SmartDeviceLink/SDLLifecycleManager.m23
-rw-r--r--SmartDeviceLink/SDLLockScreenManager.m4
-rw-r--r--SmartDeviceLink/SDLLockScreenPresenter.m3
-rw-r--r--SmartDeviceLink/SDLLogFileModuleMap.m7
-rw-r--r--SmartDeviceLink/SDLManager.h37
-rw-r--r--SmartDeviceLink/SDLManager.m4
-rw-r--r--SmartDeviceLink/SDLMenuCell.h51
-rw-r--r--SmartDeviceLink/SDLMenuCell.m58
-rw-r--r--SmartDeviceLink/SDLMenuManager.h39
-rw-r--r--SmartDeviceLink/SDLMenuManager.m443
-rw-r--r--SmartDeviceLink/SDLNotificationConstants.h27
-rw-r--r--SmartDeviceLink/SDLPermissionManager.m4
-rw-r--r--SmartDeviceLink/SDLProtocol.h18
-rw-r--r--SmartDeviceLink/SDLProtocol.m25
-rw-r--r--SmartDeviceLink/SDLProtocolConstants.h42
-rw-r--r--SmartDeviceLink/SDLProtocolConstants.m9
-rw-r--r--SmartDeviceLink/SDLProtocolHeader.h67
-rw-r--r--SmartDeviceLink/SDLProxy.h18
-rw-r--r--SmartDeviceLink/SDLProxy.m32
-rw-r--r--SmartDeviceLink/SDLProxyFactory.h23
-rw-r--r--SmartDeviceLink/SDLProxyFactory.m39
-rw-r--r--SmartDeviceLink/SDLRegisterAppInterface.h4
-rw-r--r--SmartDeviceLink/SDLRegisterAppInterface.m8
-rw-r--r--SmartDeviceLink/SDLScreenManager.h10
-rw-r--r--SmartDeviceLink/SDLScreenManager.m29
-rw-r--r--SmartDeviceLink/SDLShow.h17
-rw-r--r--SmartDeviceLink/SDLShow.m18
-rw-r--r--SmartDeviceLink/SDLSoftButtonManager.h5
-rw-r--r--SmartDeviceLink/SDLSoftButtonManager.m24
-rw-r--r--SmartDeviceLink/SDLStreamingMediaConfiguration.h22
-rw-r--r--SmartDeviceLink/SDLStreamingMediaConfiguration.m12
-rw-r--r--SmartDeviceLink/SDLStreamingMediaLifecycleManager.h4
-rw-r--r--SmartDeviceLink/SDLStreamingMediaLifecycleManager.m8
-rw-r--r--SmartDeviceLink/SDLStreamingMediaManager.h4
-rw-r--r--SmartDeviceLink/SDLStreamingMediaManager.m2
-rw-r--r--SmartDeviceLink/SDLSystemCapabilityManager.h194
-rw-r--r--SmartDeviceLink/SDLSystemCapabilityManager.m156
-rw-r--r--SmartDeviceLink/SDLTCPTransport.h7
-rw-r--r--SmartDeviceLink/SDLTCPTransport.m10
-rw-r--r--SmartDeviceLink/SDLTextAndGraphicManager.h11
-rw-r--r--SmartDeviceLink/SDLTextAndGraphicManager.m33
-rw-r--r--SmartDeviceLink/SDLTouchManager.m39
-rw-r--r--SmartDeviceLink/SDLTransportType.h (renamed from SmartDeviceLink/SDLAbstractTransport.h)6
-rw-r--r--SmartDeviceLink/SDLUploadFileOperation.m4
-rw-r--r--SmartDeviceLink/SDLVoiceCommand.h31
-rw-r--r--SmartDeviceLink/SDLVoiceCommand.m37
-rw-r--r--SmartDeviceLink/SDLVoiceCommandManager.h38
-rw-r--r--SmartDeviceLink/SDLVoiceCommandManager.m260
-rw-r--r--SmartDeviceLink/SmartDeviceLink.h32
-rw-r--r--SmartDeviceLinkSwift/SDLLog.swift21
-rw-r--r--SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleManagerSpec.m132
-rw-r--r--SmartDeviceLinkTests/DevAPISpecs/SDLMenuCellSpec.m47
-rw-r--r--SmartDeviceLinkTests/DevAPISpecs/SDLMenuManagerSpec.m340
-rw-r--r--SmartDeviceLinkTests/DevAPISpecs/SDLPermissionsManagerSpec.m17
-rw-r--r--SmartDeviceLinkTests/DevAPISpecs/SDLResponseDispatcherSpec.m1
-rw-r--r--SmartDeviceLinkTests/DevAPISpecs/SDLSoftButtonManagerSpec.m110
-rw-r--r--SmartDeviceLinkTests/DevAPISpecs/SDLTextAndGraphicManagerSpec.m152
-rw-r--r--SmartDeviceLinkTests/DevAPISpecs/SDLVoiceCommandManagerSpec.m144
-rw-r--r--SmartDeviceLinkTests/DevAPISpecs/SDLVoiceCommandSpec.m26
-rw-r--r--SmartDeviceLinkTests/ProtocolSpecs/MessageSpecs/SDLProtocolSpec.m12
-rw-r--r--SmartDeviceLinkTests/ProtocolSpecs/SDLAbstractProtocolSpec.m57
-rw-r--r--SmartDeviceLinkTests/RPCSpecs/RequestSpecs/SDLShowSpec.m305
-rw-r--r--SmartDeviceLinkTests/SDLScreenManagerSpec.m6
-rw-r--r--SmartDeviceLinkTests/SDLStreamingMediaLifecycleManagerSpec.m2
-rw-r--r--SmartDeviceLinkTests/SDLSystemCapabilityManagerSpec.m397
-rw-r--r--SmartDeviceLinkTests/TestUtilities/TestConnectionManager.m26
-rw-r--r--SmartDeviceLinkTests/UtilitiesSpecs/Touches/SDLTouchManagerSpec.m57
-rw-r--r--SmartDeviceLink_Example/AlertManager.h22
-rw-r--r--SmartDeviceLink_Example/AlertManager.m45
-rw-r--r--SmartDeviceLink_Example/AlertManager.swift36
-rw-r--r--SmartDeviceLink_Example/AppConstants.h100
-rw-r--r--SmartDeviceLink_Example/AppConstants.m95
-rw-r--r--SmartDeviceLink_Example/AppDelegate.h (renamed from SmartDeviceLink_Example/Classes/AppDelegate.h)0
-rw-r--r--SmartDeviceLink_Example/AppDelegate.m (renamed from SmartDeviceLink_Example/Classes/AppDelegate.m)0
-rw-r--r--SmartDeviceLink_Example/AppDelegate.swift44
-rw-r--r--SmartDeviceLink_Example/AppUserDefaults.swift43
-rw-r--r--SmartDeviceLink_Example/AudioManager.h26
-rw-r--r--SmartDeviceLink_Example/AudioManager.m277
-rw-r--r--SmartDeviceLink_Example/AudioManager.swift229
-rw-r--r--SmartDeviceLink_Example/Base.lproj/ConnectionTCPTableViewController.storyboard22
-rw-r--r--SmartDeviceLink_Example/Base.lproj/Main.storyboard18
-rw-r--r--SmartDeviceLink_Example/ButtonManager.h31
-rw-r--r--SmartDeviceLink_Example/ButtonManager.m146
-rw-r--r--SmartDeviceLink_Example/ButtonManager.swift121
-rw-r--r--SmartDeviceLink_Example/Classes/ConnectionIAPTableViewController.m2
-rw-r--r--SmartDeviceLink_Example/Classes/ConnectionTCPTableViewController.m2
-rw-r--r--SmartDeviceLink_Example/Classes/ProxyManager.h9
-rw-r--r--SmartDeviceLink_Example/Classes/ProxyManager.m468
-rw-r--r--SmartDeviceLink_Example/ConnectionContainerViewController.swift82
-rw-r--r--SmartDeviceLink_Example/ConnectionIAPTableViewController.storyboard69
-rw-r--r--SmartDeviceLink_Example/ConnectionIAPTableViewController.swift72
-rw-r--r--SmartDeviceLink_Example/ConnectionTCPTableViewController.storyboard135
-rw-r--r--SmartDeviceLink_Example/ConnectionTCPTableViewController.swift88
-rw-r--r--SmartDeviceLink_Example/Images.xcassets/car.imageset/Contents.json (renamed from SmartDeviceLink_Example/Images.xcassets/star_softbutton_icon.imageset/Contents.json)2
-rw-r--r--SmartDeviceLink_Example/Images.xcassets/car.imageset/iconmonstr-car-1-64.pngbin0 -> 1381 bytes
-rw-r--r--SmartDeviceLink_Example/Images.xcassets/car_icon.imageset/Contents.json (renamed from SmartDeviceLink_Example/Images.xcassets/hexagon_on_softbutton_icon.imageset/Contents.json)2
-rw-r--r--SmartDeviceLink_Example/Images.xcassets/car_icon.imageset/car.pngbin0 -> 14551 bytes
-rw-r--r--SmartDeviceLink_Example/Images.xcassets/choice_set.imageset/Contents.json (renamed from SmartDeviceLink_Example/Images.xcassets/hexagon_off_softbutton_icon.imageset/Contents.json)2
-rw-r--r--SmartDeviceLink_Example/Images.xcassets/choice_set.imageset/iconmonstr-text-23-64.pngbin0 -> 224 bytes
-rw-r--r--SmartDeviceLink_Example/Images.xcassets/hexagon_off_softbutton_icon.imageset/hexagon_black_softbutton_icon.pngbin669 -> 0 bytes
-rw-r--r--SmartDeviceLink_Example/Images.xcassets/hexagon_on_softbutton_icon.imageset/hexagon_pink_softbutton_icon.pngbin791 -> 0 bytes
-rw-r--r--SmartDeviceLink_Example/Images.xcassets/laptop_icon.imageset/Contents.json21
-rw-r--r--SmartDeviceLink_Example/Images.xcassets/laptop_icon.imageset/screen.pngbin0 -> 8264 bytes
-rw-r--r--SmartDeviceLink_Example/Images.xcassets/microphone.imageset/Contents.json21
-rw-r--r--SmartDeviceLink_Example/Images.xcassets/microphone.imageset/microphone.pngbin0 -> 2608 bytes
-rw-r--r--SmartDeviceLink_Example/Images.xcassets/phone.imageset/Contents.json21
-rw-r--r--SmartDeviceLink_Example/Images.xcassets/phone.imageset/phone.pngbin0 -> 3434 bytes
-rw-r--r--SmartDeviceLink_Example/Images.xcassets/speak.imageset/Contents.json21
-rw-r--r--SmartDeviceLink_Example/Images.xcassets/speak.imageset/iconmonstr-speech-bubble-5-64.pngbin0 -> 1502 bytes
-rw-r--r--SmartDeviceLink_Example/Images.xcassets/star_softbutton_icon.imageset/star_black_softbutton_icon.pngbin909 -> 0 bytes
-rw-r--r--SmartDeviceLink_Example/Images.xcassets/wheel_icon.imageset/Contents.json21
-rw-r--r--SmartDeviceLink_Example/Images.xcassets/wheel_icon.imageset/wheel.pngbin0 -> 16899 bytes
-rw-r--r--SmartDeviceLink_Example/LaunchScreen.xib37
-rw-r--r--SmartDeviceLink_Example/Main.storyboard66
-rw-r--r--SmartDeviceLink_Example/MenuManager.h24
-rw-r--r--SmartDeviceLink_Example/MenuManager.m106
-rw-r--r--SmartDeviceLink_Example/MenuManager.swift154
-rw-r--r--SmartDeviceLink_Example/PerformInteractionManager.h24
-rw-r--r--SmartDeviceLink_Example/PerformInteractionManager.m56
-rw-r--r--SmartDeviceLink_Example/PerformInteractionManager.swift65
-rw-r--r--SmartDeviceLink_Example/Protocol+ProxyManagerDelegate.swift13
-rw-r--r--SmartDeviceLink_Example/ProxyManager.swift285
-rw-r--r--SmartDeviceLink_Example/RPCPermissionsManager.h21
-rw-r--r--SmartDeviceLink_Example/RPCPermissionsManager.m138
-rw-r--r--SmartDeviceLink_Example/RPCPermissionsManager.swift119
-rw-r--r--SmartDeviceLink_Example/SmartDeviceLink-Example-ObjC-Info.plist (renamed from SmartDeviceLink_Example/Info.plist)4
-rw-r--r--SmartDeviceLink_Example/SmartDeviceLink-Example-Swift-Bridging-Header.h5
-rw-r--r--SmartDeviceLink_Example/VehicleDataManager.h33
-rw-r--r--SmartDeviceLink_Example/VehicleDataManager.m216
-rw-r--r--SmartDeviceLink_Example/VehicleDataManager.swift184
150 files changed, 7702 insertions, 1275 deletions
diff --git a/SmartDeviceLink-Example-Swift-Info.plist b/SmartDeviceLink-Example-Swift-Info.plist
new file mode 100644
index 000000000..e35e656dd
--- /dev/null
+++ b/SmartDeviceLink-Example-Swift-Info.plist
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>NSSpeechRecognitionUsageDescription</key>
+ <string>Requesting access to the speech recognition API</string>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>en</string>
+ <key>CFBundleExecutable</key>
+ <string>$(EXECUTABLE_NAME)</string>
+ <key>CFBundleIdentifier</key>
+ <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>7.0</string>
+ <key>CFBundleName</key>
+ <string>$(PRODUCT_NAME)</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>5.2.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+ <key>LSRequiresIPhoneOS</key>
+ <true/>
+ <key>UIBackgroundModes</key>
+ <array>
+ <string>external-accessory</string>
+ </array>
+ <key>UIFileSharingEnabled</key>
+ <true/>
+ <key>UILaunchStoryboardName</key>
+ <string>LaunchScreen</string>
+ <key>UIMainStoryboardFile</key>
+ <string>Main</string>
+ <key>UIRequiredDeviceCapabilities</key>
+ <array>
+ <string>armv7</string>
+ </array>
+ <key>UISupportedExternalAccessoryProtocols</key>
+ <array>
+ <string>com.smartdevicelink.prot29</string>
+ <string>com.smartdevicelink.prot28</string>
+ <string>com.smartdevicelink.prot27</string>
+ <string>com.smartdevicelink.prot26</string>
+ <string>com.smartdevicelink.prot25</string>
+ <string>com.smartdevicelink.prot24</string>
+ <string>com.smartdevicelink.prot23</string>
+ <string>com.smartdevicelink.prot22</string>
+ <string>com.smartdevicelink.prot21</string>
+ <string>com.smartdevicelink.prot20</string>
+ <string>com.smartdevicelink.prot19</string>
+ <string>com.smartdevicelink.prot18</string>
+ <string>com.smartdevicelink.prot17</string>
+ <string>com.smartdevicelink.prot16</string>
+ <string>com.smartdevicelink.prot15</string>
+ <string>com.smartdevicelink.prot14</string>
+ <string>com.smartdevicelink.prot13</string>
+ <string>com.smartdevicelink.prot12</string>
+ <string>com.smartdevicelink.prot11</string>
+ <string>com.smartdevicelink.prot10</string>
+ <string>com.smartdevicelink.prot9</string>
+ <string>com.smartdevicelink.prot8</string>
+ <string>com.smartdevicelink.prot7</string>
+ <string>com.smartdevicelink.prot6</string>
+ <string>com.smartdevicelink.prot5</string>
+ <string>com.smartdevicelink.prot4</string>
+ <string>com.smartdevicelink.prot3</string>
+ <string>com.smartdevicelink.prot2</string>
+ <string>com.smartdevicelink.prot1</string>
+ <string>com.smartdevicelink.prot0</string>
+ <string>com.ford.sync.prot0</string>
+ <string>com.smartdevicelink.multisession</string>
+ </array>
+ <key>UISupportedInterfaceOrientations</key>
+ <array>
+ <string>UIInterfaceOrientationPortrait</string>
+ </array>
+</dict>
+</plist>
diff --git a/SmartDeviceLink-iOS.podspec b/SmartDeviceLink-iOS.podspec
index 3ac9fc85d..0c6790dbb 100644
--- a/SmartDeviceLink-iOS.podspec
+++ b/SmartDeviceLink-iOS.podspec
@@ -19,8 +19,6 @@ ss.source_files = 'SmartDeviceLink/*.{h,m}'
ss.public_header_files = [
'SmartDeviceLink/NSNumber+NumberType.h',
-'SmartDeviceLink/SDLAbstractProtocol.h',
-'SmartDeviceLink/SDLAbstractTransport.h',
'SmartDeviceLink/SDLAddCommand.h',
'SmartDeviceLink/SDLAddCommandResponse.h',
'SmartDeviceLink/SDLAddSubMenu.h',
@@ -121,8 +119,6 @@ ss.public_header_files = [
'SmartDeviceLink/SDLHMILevel.h',
'SmartDeviceLink/SDLHMIPermissions.h',
'SmartDeviceLink/SDLHMIZoneCapabilities.h',
-'SmartDeviceLink/SDLIAPSessionDelegate.h',
-'SmartDeviceLink/SDLIAPTransport.h',
'SmartDeviceLink/SDLIgnitionStableStatus.h',
'SmartDeviceLink/SDLIgnitionStatus.h',
'SmartDeviceLink/SDLImage.h',
@@ -161,6 +157,8 @@ ss.public_header_files = [
'SmartDeviceLink/SDLManager.h',
'SmartDeviceLink/SDLManagerDelegate.h',
'SmartDeviceLink/SDLMediaClockFormat.h',
+'SmartDeviceLink/SDLMenuCell.h',
+'SmartDeviceLink/SDLMenuManager.h',
'SmartDeviceLink/SDLMenuParams.h',
'SmartDeviceLink/SDLMetadataTags.h',
'SmartDeviceLink/SDLMetadataType.h',
@@ -208,13 +206,6 @@ ss.public_header_files = [
'SmartDeviceLink/SDLPresetBankCapabilities.h',
'SmartDeviceLink/SDLPrimaryAudioSource.h',
'SmartDeviceLink/SDLPRNDL.h',
-'SmartDeviceLink/SDLProtocol.h',
-'SmartDeviceLink/SDLProtocolHeader.h',
-'SmartDeviceLink/SDLProtocolListener.h',
-'SmartDeviceLink/SDLProtocolMessage.h',
-'SmartDeviceLink/SDLProxy.h',
-'SmartDeviceLink/SDLProxyFactory.h',
-'SmartDeviceLink/SDLProxyListener.h',
'SmartDeviceLink/SDLPutFile.h',
'SmartDeviceLink/SDLPutFileResponse.h',
'SmartDeviceLink/SDLRadioBand.h',
@@ -292,12 +283,12 @@ ss.public_header_files = [
'SmartDeviceLink/SDLSyncPDataResponse.h',
'SmartDeviceLink/SDLSystemAction.h',
'SmartDeviceLink/SDLSystemCapability.h',
+'SmartDeviceLink/SDLSystemCapabilityManager.h',
'SmartDeviceLink/SDLSystemCapabilityType.h',
'SmartDeviceLink/SDLSystemContext.h',
'SmartDeviceLink/SDLTBTState.h',
'SmartDeviceLink/SDLTemperature.h',
'SmartDeviceLink/SDLTemperatureUnit.h',
-'SmartDeviceLink/SDLTCPTransport.h',
'SmartDeviceLink/SDLTextAlignment.h',
'SmartDeviceLink/SDLTextField.h',
'SmartDeviceLink/SDLTextFieldName.h',
@@ -310,7 +301,6 @@ ss.public_header_files = [
'SmartDeviceLink/SDLTouchManager.h',
'SmartDeviceLink/SDLTouchManagerDelegate.h',
'SmartDeviceLink/SDLTouchType.h',
-'SmartDeviceLink/SDLTransportDelegate.h',
'SmartDeviceLink/SDLTriggerSource.h',
'SmartDeviceLink/SDLTTSChunk.h',
'SmartDeviceLink/SDLTurn.h',
@@ -338,6 +328,7 @@ ss.public_header_files = [
'SmartDeviceLink/SDLVideoStreamingCodec.h',
'SmartDeviceLink/SDLVideoStreamingFormat.h',
'SmartDeviceLink/SDLVideoStreamingProtocol.h',
+'SmartDeviceLink/SDLVoiceCommand.h',
'SmartDeviceLink/SDLVrCapabilities.h',
'SmartDeviceLink/SDLVrHelpItem.h',
'SmartDeviceLink/SDLWarningLightStatus.h',
diff --git a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj
index b61eb996c..a4993e762 100644
--- a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj
+++ b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj
@@ -226,7 +226,6 @@
1680B1171A9CD7AD00DBD79E /* SDLProtocolSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 1680B10B1A9CD7AD00DBD79E /* SDLProtocolSpec.m */; };
1680B1181A9CD7AD00DBD79E /* SDLV1ProtocolMessageSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 1680B10C1A9CD7AD00DBD79E /* SDLV1ProtocolMessageSpec.m */; };
1680B1191A9CD7AD00DBD79E /* SDLV2ProtocolMessageSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 1680B10D1A9CD7AD00DBD79E /* SDLV2ProtocolMessageSpec.m */; };
- 1680B11A1A9CD7AD00DBD79E /* SDLAbstractProtocolSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 1680B10E1A9CD7AD00DBD79E /* SDLAbstractProtocolSpec.m */; };
1680B11B1A9CD7AD00DBD79E /* SDLFunctionIDSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 1680B10F1A9CD7AD00DBD79E /* SDLFunctionIDSpec.m */; };
1680B11C1A9CD7AD00DBD79E /* SDLProtocolMessageAssemblerSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 1680B1101A9CD7AD00DBD79E /* SDLProtocolMessageAssemblerSpec.m */; };
1680B11D1A9CD7AD00DBD79E /* SDLProtocolMessageDisassemblerSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 1680B1111A9CD7AD00DBD79E /* SDLProtocolMessageDisassemblerSpec.m */; };
@@ -348,6 +347,12 @@
5D293AFE1FE078A9000CBD7E /* SDLCarWindowViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D293AFC1FE078A9000CBD7E /* SDLCarWindowViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
5D293AFF1FE078A9000CBD7E /* SDLCarWindowViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D293AFD1FE078A9000CBD7E /* SDLCarWindowViewController.m */; };
5D2F58081D0717D5001085CE /* SDLManagerDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D2F58071D0717D5001085CE /* SDLManagerDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 5D339CEA207C066E000CC364 /* SDLMenuCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D339CE8207C066E000CC364 /* SDLMenuCell.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 5D339CEB207C066E000CC364 /* SDLMenuCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D339CE9207C066E000CC364 /* SDLMenuCell.m */; };
+ 5D339CEF207C08BA000CC364 /* SDLVoiceCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D339CED207C08BA000CC364 /* SDLVoiceCommand.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 5D339CF0207C08BA000CC364 /* SDLVoiceCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D339CEE207C08BA000CC364 /* SDLVoiceCommand.m */; };
+ 5D339CF3207C0ACE000CC364 /* SDLMenuManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D339CF1207C0ACE000CC364 /* SDLMenuManager.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 5D339CF4207C0ACE000CC364 /* SDLMenuManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D339CF2207C0ACE000CC364 /* SDLMenuManager.m */; };
5D3E48751D6F3B330000BFEF /* SDLAsynchronousOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D3E48731D6F3B330000BFEF /* SDLAsynchronousOperation.h */; };
5D3E48761D6F3B330000BFEF /* SDLAsynchronousOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D3E48741D6F3B330000BFEF /* SDLAsynchronousOperation.m */; };
5D3E487B1D6F888E0000BFEF /* SDLRPCResponseNotification.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D3E48791D6F888E0000BFEF /* SDLRPCResponseNotification.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -361,12 +366,10 @@
5D4029E41A76F0760006B0C2 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5D4029E11A76F0760006B0C2 /* Main.storyboard */; };
5D4346471E6F0BDA00B639C6 /* SDLLogFileModuleSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D4346461E6F0BDA00B639C6 /* SDLLogFileModuleSpec.m */; };
5D43465B1E6F154400B639C6 /* SDLLogConfigurationSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D43465A1E6F154400B639C6 /* SDLLogConfigurationSpec.m */; };
- 5D4346651E6F38E600B639C6 /* SmartDeviceLinkSwift.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D4346631E6F38E600B639C6 /* SmartDeviceLinkSwift.h */; settings = {ATTRIBUTES = (Public, ); }; };
5D43466B1E6F3B4C00B639C6 /* SDLLogFilterSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D43466A1E6F3B4C00B639C6 /* SDLLogFilterSpec.m */; };
5D43466D1E6F522000B639C6 /* SDLLogModelSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D43466C1E6F522000B639C6 /* SDLLogModelSpec.m */; };
5D43466F1E6F55BD00B639C6 /* SDLLogManagerSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D43466E1E6F55BD00B639C6 /* SDLLogManagerSpec.m */; };
5D4346731E6F617D00B639C6 /* TestLogTarget.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D4346721E6F617D00B639C6 /* TestLogTarget.m */; };
- 5D4346861E771B5700B639C6 /* SDLLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D4346851E771B5700B639C6 /* SDLLog.swift */; };
5D4631041F2120A30092EFDC /* SDLControlFramePayloadType.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D4631031F2120A30092EFDC /* SDLControlFramePayloadType.h */; };
5D4631081F21261A0092EFDC /* SDLControlFramePayloadRPCStartServiceAck.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D4631061F21261A0092EFDC /* SDLControlFramePayloadRPCStartServiceAck.h */; };
5D4631091F21261B0092EFDC /* SDLControlFramePayloadRPCStartServiceAck.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D4631071F21261A0092EFDC /* SDLControlFramePayloadRPCStartServiceAck.m */; };
@@ -407,10 +410,7 @@
5D61FA211A84237100846EE7 /* SmartDeviceLink.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D61FA201A84237100846EE7 /* SmartDeviceLink.h */; settings = {ATTRIBUTES = (Public, ); }; };
5D61FA331A84237100846EE7 /* SmartDeviceLink.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5D61FA1C1A84237100846EE7 /* SmartDeviceLink.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
5D61FA341A84237100846EE7 /* SmartDeviceLink.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 5D61FA1C1A84237100846EE7 /* SmartDeviceLink.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
- 5D61FC291A84238C00846EE7 /* SDLAbstractProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D61FA3C1A84238A00846EE7 /* SDLAbstractProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
- 5D61FC2A1A84238C00846EE7 /* SDLAbstractProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D61FA3D1A84238A00846EE7 /* SDLAbstractProtocol.m */; };
- 5D61FC2B1A84238C00846EE7 /* SDLAbstractTransport.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D61FA3E1A84238A00846EE7 /* SDLAbstractTransport.h */; settings = {ATTRIBUTES = (Public, ); }; };
- 5D61FC2C1A84238C00846EE7 /* SDLAbstractTransport.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D61FA3F1A84238A00846EE7 /* SDLAbstractTransport.m */; };
+ 5D61FC2B1A84238C00846EE7 /* SDLTransportType.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D61FA3E1A84238A00846EE7 /* SDLTransportType.h */; };
5D61FC2D1A84238C00846EE7 /* SDLAddCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D61FA401A84238A00846EE7 /* SDLAddCommand.h */; settings = {ATTRIBUTES = (Public, ); }; };
5D61FC2E1A84238C00846EE7 /* SDLAddCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D61FA411A84238A00846EE7 /* SDLAddCommand.m */; };
5D61FC2F1A84238C00846EE7 /* SDLAddCommandResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D61FA421A84238A00846EE7 /* SDLAddCommandResponse.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -558,7 +558,7 @@
5D61FCC41A84238C00846EE7 /* SDLHMIPermissions.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D61FAD71A84238A00846EE7 /* SDLHMIPermissions.m */; };
5D61FCC51A84238C00846EE7 /* SDLHMIZoneCapabilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D61FAD81A84238A00846EE7 /* SDLHMIZoneCapabilities.h */; settings = {ATTRIBUTES = (Public, ); }; };
5D61FCC61A84238C00846EE7 /* SDLHMIZoneCapabilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D61FAD91A84238A00846EE7 /* SDLHMIZoneCapabilities.m */; };
- 5D61FCC71A84238C00846EE7 /* SDLIAPTransport.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D61FADA1A84238A00846EE7 /* SDLIAPTransport.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 5D61FCC71A84238C00846EE7 /* SDLIAPTransport.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D61FADA1A84238A00846EE7 /* SDLIAPTransport.h */; };
5D61FCC81A84238C00846EE7 /* SDLIAPTransport.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D61FADB1A84238A00846EE7 /* SDLIAPTransport.m */; };
5D61FCC91A84238C00846EE7 /* SDLIgnitionStableStatus.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D61FADC1A84238A00846EE7 /* SDLIgnitionStableStatus.h */; settings = {ATTRIBUTES = (Public, ); }; };
5D61FCCA1A84238C00846EE7 /* SDLIgnitionStableStatus.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D61FADD1A84238A00846EE7 /* SDLIgnitionStableStatus.m */; };
@@ -675,12 +675,12 @@
5D61FD401A84238C00846EE7 /* SDLPrioritizedObjectCollection.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D61FB531A84238B00846EE7 /* SDLPrioritizedObjectCollection.m */; };
5D61FD411A84238C00846EE7 /* SDLPRNDL.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D61FB541A84238B00846EE7 /* SDLPRNDL.h */; settings = {ATTRIBUTES = (Public, ); }; };
5D61FD421A84238C00846EE7 /* SDLPRNDL.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D61FB551A84238B00846EE7 /* SDLPRNDL.m */; };
- 5D61FD431A84238C00846EE7 /* SDLProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D61FB561A84238B00846EE7 /* SDLProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 5D61FD431A84238C00846EE7 /* SDLProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D61FB561A84238B00846EE7 /* SDLProtocol.h */; };
5D61FD441A84238C00846EE7 /* SDLProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D61FB571A84238B00846EE7 /* SDLProtocol.m */; };
- 5D61FD451A84238C00846EE7 /* SDLProtocolHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D61FB581A84238B00846EE7 /* SDLProtocolHeader.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 5D61FD451A84238C00846EE7 /* SDLProtocolHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D61FB581A84238B00846EE7 /* SDLProtocolHeader.h */; };
5D61FD461A84238C00846EE7 /* SDLProtocolHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D61FB591A84238B00846EE7 /* SDLProtocolHeader.m */; };
- 5D61FD471A84238C00846EE7 /* SDLProtocolListener.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D61FB5A1A84238B00846EE7 /* SDLProtocolListener.h */; settings = {ATTRIBUTES = (Public, ); }; };
- 5D61FD481A84238C00846EE7 /* SDLProtocolMessage.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D61FB5B1A84238B00846EE7 /* SDLProtocolMessage.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 5D61FD471A84238C00846EE7 /* SDLProtocolListener.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D61FB5A1A84238B00846EE7 /* SDLProtocolListener.h */; };
+ 5D61FD481A84238C00846EE7 /* SDLProtocolMessage.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D61FB5B1A84238B00846EE7 /* SDLProtocolMessage.h */; };
5D61FD491A84238C00846EE7 /* SDLProtocolMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D61FB5C1A84238B00846EE7 /* SDLProtocolMessage.m */; };
5D61FD4A1A84238C00846EE7 /* SDLProtocolMessageAssembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D61FB5D1A84238B00846EE7 /* SDLProtocolMessageAssembler.h */; };
5D61FD4B1A84238C00846EE7 /* SDLProtocolMessageAssembler.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D61FB5E1A84238B00846EE7 /* SDLProtocolMessageAssembler.m */; };
@@ -688,11 +688,9 @@
5D61FD4D1A84238C00846EE7 /* SDLProtocolMessageDisassembler.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D61FB601A84238B00846EE7 /* SDLProtocolMessageDisassembler.m */; };
5D61FD4E1A84238C00846EE7 /* SDLProtocolReceivedMessageRouter.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D61FB611A84238B00846EE7 /* SDLProtocolReceivedMessageRouter.h */; };
5D61FD4F1A84238C00846EE7 /* SDLProtocolReceivedMessageRouter.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D61FB621A84238B00846EE7 /* SDLProtocolReceivedMessageRouter.m */; };
- 5D61FD501A84238C00846EE7 /* SDLProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D61FB631A84238B00846EE7 /* SDLProxy.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 5D61FD501A84238C00846EE7 /* SDLProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D61FB631A84238B00846EE7 /* SDLProxy.h */; };
5D61FD511A84238C00846EE7 /* SDLProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D61FB641A84238B00846EE7 /* SDLProxy.m */; };
- 5D61FD521A84238C00846EE7 /* SDLProxyFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D61FB651A84238B00846EE7 /* SDLProxyFactory.h */; settings = {ATTRIBUTES = (Public, ); }; };
- 5D61FD531A84238C00846EE7 /* SDLProxyFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D61FB661A84238B00846EE7 /* SDLProxyFactory.m */; };
- 5D61FD541A84238C00846EE7 /* SDLProxyListener.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D61FB671A84238B00846EE7 /* SDLProxyListener.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 5D61FD541A84238C00846EE7 /* SDLProxyListener.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D61FB671A84238B00846EE7 /* SDLProxyListener.h */; };
5D61FD551A84238C00846EE7 /* SDLPutFile.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D61FB681A84238B00846EE7 /* SDLPutFile.h */; settings = {ATTRIBUTES = (Public, ); }; };
5D61FD561A84238C00846EE7 /* SDLPutFile.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D61FB691A84238B00846EE7 /* SDLPutFile.m */; };
5D61FD571A84238C00846EE7 /* SDLPutFileResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D61FB6A1A84238B00846EE7 /* SDLPutFileResponse.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -798,7 +796,7 @@
5D61FDC21A84238C00846EE7 /* SDLSystemRequestResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D61FBD51A84238B00846EE7 /* SDLSystemRequestResponse.m */; };
5D61FDC31A84238C00846EE7 /* SDLTBTState.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D61FBD61A84238B00846EE7 /* SDLTBTState.h */; settings = {ATTRIBUTES = (Public, ); }; };
5D61FDC41A84238C00846EE7 /* SDLTBTState.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D61FBD71A84238B00846EE7 /* SDLTBTState.m */; };
- 5D61FDC51A84238C00846EE7 /* SDLTCPTransport.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D61FBD81A84238B00846EE7 /* SDLTCPTransport.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 5D61FDC51A84238C00846EE7 /* SDLTCPTransport.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D61FBD81A84238B00846EE7 /* SDLTCPTransport.h */; };
5D61FDC61A84238C00846EE7 /* SDLTCPTransport.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D61FBD91A84238B00846EE7 /* SDLTCPTransport.m */; };
5D61FDC71A84238C00846EE7 /* SDLTextAlignment.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D61FBDA1A84238B00846EE7 /* SDLTextAlignment.h */; settings = {ATTRIBUTES = (Public, ); }; };
5D61FDC81A84238C00846EE7 /* SDLTextAlignment.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D61FBDB1A84238C00846EE7 /* SDLTextAlignment.m */; };
@@ -818,7 +816,7 @@
5D61FDD61A84238C00846EE7 /* SDLTouchEventCapabilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D61FBE91A84238C00846EE7 /* SDLTouchEventCapabilities.m */; };
5D61FDD71A84238C00846EE7 /* SDLTouchType.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D61FBEA1A84238C00846EE7 /* SDLTouchType.h */; settings = {ATTRIBUTES = (Public, ); }; };
5D61FDD81A84238C00846EE7 /* SDLTouchType.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D61FBEB1A84238C00846EE7 /* SDLTouchType.m */; };
- 5D61FDDA1A84238C00846EE7 /* SDLTransportDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D61FBED1A84238C00846EE7 /* SDLTransportDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 5D61FDDA1A84238C00846EE7 /* SDLTransportDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D61FBED1A84238C00846EE7 /* SDLTransportDelegate.h */; };
5D61FDDB1A84238C00846EE7 /* SDLTriggerSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D61FBEE1A84238C00846EE7 /* SDLTriggerSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
5D61FDDC1A84238C00846EE7 /* SDLTriggerSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D61FBEF1A84238C00846EE7 /* SDLTriggerSource.m */; };
5D61FDDD1A84238C00846EE7 /* SDLTTSChunk.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D61FBF01A84238C00846EE7 /* SDLTTSChunk.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -968,6 +966,10 @@
5DA49CE61F1EA83300E65FC5 /* SDLControlFramePayloadRPCStartService.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DA49CE41F1EA83300E65FC5 /* SDLControlFramePayloadRPCStartService.m */; };
5DA8A0E91E955F710039C50D /* SDLStreamingMediaManagerConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8966F31E56977C00413EAB /* SDLStreamingMediaManagerConstants.m */; };
5DA8A0EA1E955FE00039C50D /* SDLLogModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DBF06301E64A9C600A5CF03 /* SDLLogModel.m */; };
+ 5DAB5F512098994C00A020C8 /* SDLMenuCellSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DAB5F502098994C00A020C8 /* SDLMenuCellSpec.m */; };
+ 5DAB5F5320989A8300A020C8 /* SDLVoiceCommandSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DAB5F5220989A8300A020C8 /* SDLVoiceCommandSpec.m */; };
+ 5DAB5F562098E5D100A020C8 /* SDLProtocolConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DAB5F542098E5D100A020C8 /* SDLProtocolConstants.h */; };
+ 5DAB5F572098E5D100A020C8 /* SDLProtocolConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DAB5F552098E5D100A020C8 /* SDLProtocolConstants.m */; };
5DAD5F7F204DEDEB0025624C /* SDLScreenManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DAD5F7D204DEDEB0025624C /* SDLScreenManager.h */; settings = {ATTRIBUTES = (Public, ); }; };
5DAD5F80204DEDEB0025624C /* SDLScreenManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DAD5F7E204DEDEB0025624C /* SDLScreenManager.m */; };
5DAD5F8520507E1F0025624C /* SDLScreenManagerSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DAD5F8420507E1F0025624C /* SDLScreenManagerSpec.m */; };
@@ -1051,15 +1053,59 @@
5DEF695D1FD6FA01004B8C2F /* testAudio.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 5DEF695C1FD6FA01004B8C2F /* testAudio.mp3 */; };
5DEF69611FD6FB75004B8C2F /* SDLAudioStreamManagerSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DEF69601FD6FB75004B8C2F /* SDLAudioStreamManagerSpec.m */; };
5DEF69661FD6FEF7004B8C2F /* SDLStreamingAudioManagerMock.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DEF69651FD6FEF7004B8C2F /* SDLStreamingAudioManagerMock.m */; };
+ 5DF40B22208E761A00DD6FDA /* SDLVoiceCommandManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DF40B20208E761A00DD6FDA /* SDLVoiceCommandManager.h */; };
+ 5DF40B23208E761A00DD6FDA /* SDLVoiceCommandManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DF40B21208E761A00DD6FDA /* SDLVoiceCommandManager.m */; };
+ 5DF40B26208FA7DE00DD6FDA /* SDLMenuManagerSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DF40B25208FA7DE00DD6FDA /* SDLMenuManagerSpec.m */; };
+ 5DF40B28208FDA9700DD6FDA /* SDLVoiceCommandManagerSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DF40B27208FDA9700DD6FDA /* SDLVoiceCommandManagerSpec.m */; };
5DFFB9151BD7C89700DB3F04 /* SDLConnectionManagerType.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DFFB9141BD7C89700DB3F04 /* SDLConnectionManagerType.h */; };
+ 8800871E20A6356D008E1EA0 /* ButtonManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 8800871B20A6338C008E1EA0 /* ButtonManager.m */; };
+ 8803A0AF208E2A3A009FDC02 /* AudioManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 8803A0AC208E2907009FDC02 /* AudioManager.m */; };
+ 8803A0B2208E7CA4009FDC02 /* VehicleDataManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 8803A0B1208E7CA4009FDC02 /* VehicleDataManager.m */; };
+ 880E35B42088F75A00181259 /* SDLSystemCapabilityManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 880E35B22088F75A00181259 /* SDLSystemCapabilityManager.m */; };
+ 880E35B52088F75A00181259 /* SDLSystemCapabilityManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 880E35B32088F75A00181259 /* SDLSystemCapabilityManager.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 880E35B82088F78E00181259 /* SDLSystemCapabilityManagerSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 880E35B72088F78E00181259 /* SDLSystemCapabilityManagerSpec.m */; };
+ 8814AEA720AB65FC00466E0F /* MenuManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 8814AEA620AB65FC00466E0F /* MenuManager.m */; };
+ 8814AEAA20AB663800466E0F /* PerformInteractionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 8814AEA920AB663800466E0F /* PerformInteractionManager.m */; };
+ 8814AEAC20AB667B00466E0F /* PerformInteractionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8814AEAB20AB667B00466E0F /* PerformInteractionManager.swift */; };
+ 88166B00207E41E900076236 /* MenuManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88166AFF207E41E900076236 /* MenuManager.swift */; };
+ 8829568B207CF68800EF056C /* SmartDeviceLink.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5D61FA1C1A84237100846EE7 /* SmartDeviceLink.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
+ 88295690207CF68800EF056C /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5D4029D31A76F0340006B0C2 /* Images.xcassets */; };
+ 88295693207CF68800EF056C /* SmartDeviceLink.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 5D61FA1C1A84237100846EE7 /* SmartDeviceLink.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+ 8829569E207CFD0E00EF056C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8829569D207CFD0E00EF056C /* AppDelegate.swift */; };
8850DB601F4475D30053A48D /* TestMultipleFilesConnectionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 8850DB5F1F4475D30053A48D /* TestMultipleFilesConnectionManager.m */; };
+ 8863B59D207D3849002D6459 /* AppConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = 8863B597207D2388002D6459 /* AppConstants.m */; };
+ 8870C3EA208662540070E018 /* AudioManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8870C3E82086623F0070E018 /* AudioManager.swift */; };
8877F5EB1F34A3BE00DC128A /* SDLSendHapticDataSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 8877F5EA1F34A3BE00DC128A /* SDLSendHapticDataSpec.m */; };
8877F5EE1F34A72200DC128A /* SDLSendHapticDataResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 8877F5EC1F34A72200DC128A /* SDLSendHapticDataResponse.h */; settings = {ATTRIBUTES = (Public, ); }; };
8877F5EF1F34A72200DC128A /* SDLSendHapticDataResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = 8877F5ED1F34A72200DC128A /* SDLSendHapticDataResponse.m */; };
8877F5F11F34AA2D00DC128A /* SDLSendHapticDataResponseSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 8877F5F01F34AA2D00DC128A /* SDLSendHapticDataResponseSpec.m */; };
+ 88802FE920853AE600E9EBC6 /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = 5D9FDA971F2A7D3F00A495C8 /* LICENSE */; };
+ 88802FEA20853AE600E9EBC6 /* SDLAssets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5D6F7A3D1BC811FC0070BF37 /* SDLAssets.xcassets */; };
+ 88802FEB20853AE600E9EBC6 /* SDLLockScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5D616B481D552F7A00553F6B /* SDLLockScreen.storyboard */; };
+ 88802FF120853BB700E9EBC6 /* SDLLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D4346851E771B5700B639C6 /* SDLLog.swift */; };
+ 88802FF420853BED00E9EBC6 /* SmartDeviceLinkSwift.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D4346631E6F38E600B639C6 /* SmartDeviceLinkSwift.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 88802FF520853CD500E9EBC6 /* SmartDeviceLinkSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 88802FEF20853AE600E9EBC6 /* SmartDeviceLinkSwift.framework */; };
+ 88802FF620853CD500E9EBC6 /* SmartDeviceLinkSwift.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 88802FEF20853AE600E9EBC6 /* SmartDeviceLinkSwift.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+ 888D178F207E7F42008E9F8F /* ButtonManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 888D178D207E7F0E008E9F8F /* ButtonManager.swift */; };
+ 888D1790207E815C008E9F8F /* AppConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = 8863B597207D2388002D6459 /* AppConstants.m */; };
+ 88A0AA56207CFE5D0075132C /* AppUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88A0AA55207CFE5C0075132C /* AppUserDefaults.swift */; };
+ 88A0AA58207CFE650075132C /* ProxyManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88A0AA57207CFE650075132C /* ProxyManager.swift */; };
+ 88A0AA5C207CFE740075132C /* ConnectionContainerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88A0AA59207CFE740075132C /* ConnectionContainerViewController.swift */; };
+ 88A0AA5D207CFE740075132C /* ConnectionIAPTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88A0AA5A207CFE740075132C /* ConnectionIAPTableViewController.swift */; };
+ 88A0AA5E207CFE740075132C /* ConnectionTCPTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88A0AA5B207CFE740075132C /* ConnectionTCPTableViewController.swift */; };
+ 88A0AA65207CFF980075132C /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 88A0AA61207CFF970075132C /* LaunchScreen.xib */; };
+ 88A0AA66207CFF980075132C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 88A0AA62207CFF970075132C /* Main.storyboard */; };
+ 88A0AA67207CFF980075132C /* ConnectionIAPTableViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 88A0AA63207CFF970075132C /* ConnectionIAPTableViewController.storyboard */; };
+ 88A0AA68207CFF980075132C /* ConnectionTCPTableViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 88A0AA64207CFF980075132C /* ConnectionTCPTableViewController.storyboard */; };
88B848C31F45E1A600DED768 /* TestResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = 88B848C21F45E1A600DED768 /* TestResponse.m */; };
88B848C91F462E3600DED768 /* TestFileProgressResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = 88B848C81F462E3600DED768 /* TestFileProgressResponse.m */; };
+ 88B849C52080F4B3002A034D /* RPCPermissionsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88B849C32080F4AF002A034D /* RPCPermissionsManager.swift */; };
+ 88B849C820812442002A034D /* VehicleDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88B849C620812412002A034D /* VehicleDataManager.swift */; };
88D2AAE41F682BB20078D5B2 /* SDLLogConstantsSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 88D2AAE31F682BB20078D5B2 /* SDLLogConstantsSpec.m */; };
+ 88DA6D10209794A400AD8297 /* AlertManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 88DA6D0F209794A400AD8297 /* AlertManager.m */; };
+ 88DE80B720A5C8DD00BA9CF0 /* RPCPermissionsManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 88DE80B620A5C8DD00BA9CF0 /* RPCPermissionsManager.m */; };
+ 88DFB053207F8E100079D19D /* Protocol+ProxyManagerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88DFB051207F8DF50079D19D /* Protocol+ProxyManagerDelegate.swift */; };
+ 88DFB055207F96EE0079D19D /* AlertManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88DFB054207F96EE0079D19D /* AlertManager.swift */; };
88EED8381F33AE1700E6C42E /* SDLHapticRect.h in Headers */ = {isa = PBXBuildFile; fileRef = 88EED8361F33AE1700E6C42E /* SDLHapticRect.h */; settings = {ATTRIBUTES = (Public, ); }; };
88EED8391F33AE1700E6C42E /* SDLHapticRect.m in Sources */ = {isa = PBXBuildFile; fileRef = 88EED8371F33AE1700E6C42E /* SDLHapticRect.m */; };
88EED83B1F33BECB00E6C42E /* SDLHapticRectSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 88EED83A1F33BECB00E6C42E /* SDLHapticRectSpec.m */; };
@@ -1159,7 +1205,7 @@
E4139D1E1F6017770005B6EA /* SDLLifecycleConfigurationUpdate.m in Sources */ = {isa = PBXBuildFile; fileRef = E4139D1C1F6017770005B6EA /* SDLLifecycleConfigurationUpdate.m */; };
E9C32B911AB20BA200F283AF /* SDLIAPSession.h in Headers */ = {isa = PBXBuildFile; fileRef = E9C32B891AB20BA200F283AF /* SDLIAPSession.h */; };
E9C32B921AB20BA200F283AF /* SDLIAPSession.m in Sources */ = {isa = PBXBuildFile; fileRef = E9C32B8A1AB20BA200F283AF /* SDLIAPSession.m */; };
- E9C32B931AB20BA200F283AF /* SDLIAPSessionDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = E9C32B8B1AB20BA200F283AF /* SDLIAPSessionDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ E9C32B931AB20BA200F283AF /* SDLIAPSessionDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = E9C32B8B1AB20BA200F283AF /* SDLIAPSessionDelegate.h */; };
E9C32B941AB20BA200F283AF /* SDLStreamDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = E9C32B8C1AB20BA200F283AF /* SDLStreamDelegate.h */; };
E9C32B951AB20BA200F283AF /* SDLStreamDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = E9C32B8D1AB20BA200F283AF /* SDLStreamDelegate.m */; };
E9C32B961AB20BA200F283AF /* SDLTimer.h in Headers */ = {isa = PBXBuildFile; fileRef = E9C32B8E1AB20BA200F283AF /* SDLTimer.h */; };
@@ -1178,34 +1224,48 @@
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
- 5D43468B1E788E2200B639C6 /* PBXContainerItemProxy */ = {
+ 5D61FA281A84237100846EE7 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 5D4019A71A76EC350006B0C2 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 5D61FA1B1A84237100846EE7;
remoteInfo = SmartDeviceLink;
};
- 5D61FA281A84237100846EE7 /* PBXContainerItemProxy */ = {
+ 5D61FA2A1A84237100846EE7 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 5D4019A71A76EC350006B0C2 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 5D4019AE1A76EC350006B0C2;
+ remoteInfo = "SmartDeviceLink-Example";
+ };
+ 5D61FA311A84237100846EE7 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 5D4019A71A76EC350006B0C2 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 5D61FA1B1A84237100846EE7;
remoteInfo = SmartDeviceLink;
};
- 5D61FA2A1A84237100846EE7 /* PBXContainerItemProxy */ = {
+ 8829567F207CF68800EF056C /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 5D4019A71A76EC350006B0C2 /* Project object */;
proxyType = 1;
- remoteGlobalIDString = 5D4019AE1A76EC350006B0C2;
- remoteInfo = "SmartDeviceLink-Example";
+ remoteGlobalIDString = 5D61FA1B1A84237100846EE7;
+ remoteInfo = SmartDeviceLink;
};
- 5D61FA311A84237100846EE7 /* PBXContainerItemProxy */ = {
+ 88802FF220853BBF00E9EBC6 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 5D4019A71A76EC350006B0C2 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 5D61FA1B1A84237100846EE7;
remoteInfo = SmartDeviceLink;
};
+ 88802FF720853CD500E9EBC6 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 5D4019A71A76EC350006B0C2 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 88802CD720853AE600E9EBC6;
+ remoteInfo = SmartDeviceLinkSwift;
+ };
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
@@ -1234,6 +1294,18 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 88295692207CF68800EF056C /* Embed Frameworks */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 10;
+ files = (
+ 88802FF620853CD500E9EBC6 /* SmartDeviceLinkSwift.framework in Embed Frameworks */,
+ 88295693207CF68800EF056C /* SmartDeviceLink.framework in Embed Frameworks */,
+ );
+ name = "Embed Frameworks";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
@@ -1455,7 +1527,6 @@
1680B10B1A9CD7AD00DBD79E /* SDLProtocolSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SDLProtocolSpec.m; path = MessageSpecs/SDLProtocolSpec.m; sourceTree = "<group>"; };
1680B10C1A9CD7AD00DBD79E /* SDLV1ProtocolMessageSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLV1ProtocolMessageSpec.m; sourceTree = "<group>"; };
1680B10D1A9CD7AD00DBD79E /* SDLV2ProtocolMessageSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLV2ProtocolMessageSpec.m; sourceTree = "<group>"; };
- 1680B10E1A9CD7AD00DBD79E /* SDLAbstractProtocolSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLAbstractProtocolSpec.m; sourceTree = "<group>"; };
1680B10F1A9CD7AD00DBD79E /* SDLFunctionIDSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLFunctionIDSpec.m; sourceTree = "<group>"; };
1680B1101A9CD7AD00DBD79E /* SDLProtocolMessageAssemblerSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLProtocolMessageAssemblerSpec.m; sourceTree = "<group>"; };
1680B1111A9CD7AD00DBD79E /* SDLProtocolMessageDisassemblerSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLProtocolMessageDisassemblerSpec.m; sourceTree = "<group>"; };
@@ -1588,6 +1659,12 @@
5D293AFC1FE078A9000CBD7E /* SDLCarWindowViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDLCarWindowViewController.h; sourceTree = "<group>"; };
5D293AFD1FE078A9000CBD7E /* SDLCarWindowViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLCarWindowViewController.m; sourceTree = "<group>"; };
5D2F58071D0717D5001085CE /* SDLManagerDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLManagerDelegate.h; sourceTree = "<group>"; };
+ 5D339CE8207C066E000CC364 /* SDLMenuCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDLMenuCell.h; sourceTree = "<group>"; };
+ 5D339CE9207C066E000CC364 /* SDLMenuCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLMenuCell.m; sourceTree = "<group>"; };
+ 5D339CED207C08BA000CC364 /* SDLVoiceCommand.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDLVoiceCommand.h; sourceTree = "<group>"; };
+ 5D339CEE207C08BA000CC364 /* SDLVoiceCommand.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLVoiceCommand.m; sourceTree = "<group>"; };
+ 5D339CF1207C0ACE000CC364 /* SDLMenuManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDLMenuManager.h; sourceTree = "<group>"; };
+ 5D339CF2207C0ACE000CC364 /* SDLMenuManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLMenuManager.m; sourceTree = "<group>"; };
5D3E48731D6F3B330000BFEF /* SDLAsynchronousOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLAsynchronousOperation.h; sourceTree = "<group>"; };
5D3E48741D6F3B330000BFEF /* SDLAsynchronousOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLAsynchronousOperation.m; sourceTree = "<group>"; };
5D3E48791D6F888E0000BFEF /* SDLRPCResponseNotification.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLRPCResponseNotification.h; sourceTree = "<group>"; };
@@ -1598,12 +1675,11 @@
5D3E48CA1D7722FE0000BFEF /* NSBundle+SDLBundle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSBundle+SDLBundle.m"; sourceTree = "<group>"; };
5D4019AF1A76EC350006B0C2 /* SDL Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "SDL Example.app"; sourceTree = BUILT_PRODUCTS_DIR; };
5D4029D31A76F0340006B0C2 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = SmartDeviceLink_Example/Images.xcassets; sourceTree = SOURCE_ROOT; };
- 5D4029D51A76F0410006B0C2 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = SmartDeviceLink_Example/Info.plist; sourceTree = SOURCE_ROOT; };
+ 5D4029D51A76F0410006B0C2 /* SmartDeviceLink-Example-ObjC-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "SmartDeviceLink-Example-ObjC-Info.plist"; path = "SmartDeviceLink_Example/SmartDeviceLink-Example-ObjC-Info.plist"; sourceTree = SOURCE_ROOT; };
5D4029E01A76F0760006B0C2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = SmartDeviceLink_Example/Base.lproj/LaunchScreen.xib; sourceTree = SOURCE_ROOT; };
5D4029E21A76F0760006B0C2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = SmartDeviceLink_Example/Base.lproj/Main.storyboard; sourceTree = SOURCE_ROOT; };
5D4346461E6F0BDA00B639C6 /* SDLLogFileModuleSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SDLLogFileModuleSpec.m; path = LoggingSpecs/SDLLogFileModuleSpec.m; sourceTree = "<group>"; };
5D43465A1E6F154400B639C6 /* SDLLogConfigurationSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SDLLogConfigurationSpec.m; path = LoggingSpecs/SDLLogConfigurationSpec.m; sourceTree = "<group>"; };
- 5D4346611E6F38E600B639C6 /* SmartDeviceLinkSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SmartDeviceLinkSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; };
5D4346631E6F38E600B639C6 /* SmartDeviceLinkSwift.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SmartDeviceLinkSwift.h; sourceTree = "<group>"; };
5D4346641E6F38E600B639C6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
5D43466A1E6F3B4C00B639C6 /* SDLLogFilterSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SDLLogFilterSpec.m; path = LoggingSpecs/SDLLogFilterSpec.m; sourceTree = "<group>"; };
@@ -1637,8 +1713,8 @@
5D535DC41B72473800CF7760 /* SDLGlobals.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLGlobals.m; sourceTree = "<group>"; };
5D53C46B1B7A99B9003526EA /* SDLStreamingMediaManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLStreamingMediaManager.h; sourceTree = "<group>"; };
5D53C46C1B7A99B9003526EA /* SDLStreamingMediaManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLStreamingMediaManager.m; sourceTree = "<group>"; };
- 5D59350B1A855EB300687FB9 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = SmartDeviceLink_Example/Classes/AppDelegate.h; sourceTree = SOURCE_ROOT; };
- 5D59350C1A855EB300687FB9 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = SmartDeviceLink_Example/Classes/AppDelegate.m; sourceTree = SOURCE_ROOT; };
+ 5D59350B1A855EB300687FB9 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = SmartDeviceLink_Example/AppDelegate.h; sourceTree = SOURCE_ROOT; };
+ 5D59350C1A855EB300687FB9 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = SmartDeviceLink_Example/AppDelegate.m; sourceTree = SOURCE_ROOT; };
5D5935111A855EBE00687FB9 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = SmartDeviceLink_Example/Classes/main.m; sourceTree = SOURCE_ROOT; };
5D59DD461B14FDEE00BE744D /* SDLLockScreenStatusManagerSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SDLLockScreenStatusManagerSpec.m; path = ProxySpecs/SDLLockScreenStatusManagerSpec.m; sourceTree = "<group>"; };
5D5DBF071D48E39C00D4F914 /* FBSnapshotTestCase.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FBSnapshotTestCase.framework; path = sdl_ios/Carthage/Build/iOS/FBSnapshotTestCase.framework; sourceTree = "<group>"; };
@@ -1666,10 +1742,7 @@
5D61FA201A84237100846EE7 /* SmartDeviceLink.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SmartDeviceLink.h; sourceTree = "<group>"; wrapsLines = 0; };
5D61FA261A84237100846EE7 /* SmartDeviceLinkTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SmartDeviceLinkTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
5D61FA2E1A84237100846EE7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
- 5D61FA3C1A84238A00846EE7 /* SDLAbstractProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLAbstractProtocol.h; sourceTree = "<group>"; };
- 5D61FA3D1A84238A00846EE7 /* SDLAbstractProtocol.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLAbstractProtocol.m; sourceTree = "<group>"; };
- 5D61FA3E1A84238A00846EE7 /* SDLAbstractTransport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLAbstractTransport.h; sourceTree = "<group>"; };
- 5D61FA3F1A84238A00846EE7 /* SDLAbstractTransport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLAbstractTransport.m; sourceTree = "<group>"; };
+ 5D61FA3E1A84238A00846EE7 /* SDLTransportType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLTransportType.h; sourceTree = "<group>"; };
5D61FA401A84238A00846EE7 /* SDLAddCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLAddCommand.h; sourceTree = "<group>"; };
5D61FA411A84238A00846EE7 /* SDLAddCommand.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLAddCommand.m; sourceTree = "<group>"; };
5D61FA421A84238A00846EE7 /* SDLAddCommandResponse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLAddCommandResponse.h; sourceTree = "<group>"; };
@@ -1949,8 +2022,6 @@
5D61FB621A84238B00846EE7 /* SDLProtocolReceivedMessageRouter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLProtocolReceivedMessageRouter.m; sourceTree = "<group>"; };
5D61FB631A84238B00846EE7 /* SDLProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLProxy.h; sourceTree = "<group>"; };
5D61FB641A84238B00846EE7 /* SDLProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLProxy.m; sourceTree = "<group>"; };
- 5D61FB651A84238B00846EE7 /* SDLProxyFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLProxyFactory.h; sourceTree = "<group>"; };
- 5D61FB661A84238B00846EE7 /* SDLProxyFactory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLProxyFactory.m; sourceTree = "<group>"; };
5D61FB671A84238B00846EE7 /* SDLProxyListener.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLProxyListener.h; sourceTree = "<group>"; };
5D61FB681A84238B00846EE7 /* SDLPutFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLPutFile.h; sourceTree = "<group>"; };
5D61FB691A84238B00846EE7 /* SDLPutFile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLPutFile.m; sourceTree = "<group>"; };
@@ -2224,6 +2295,10 @@
5DA3F36F1BC4489A0026F2D0 /* SDLManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLManager.m; sourceTree = "<group>"; };
5DA49CE31F1EA83300E65FC5 /* SDLControlFramePayloadRPCStartService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLControlFramePayloadRPCStartService.h; sourceTree = "<group>"; };
5DA49CE41F1EA83300E65FC5 /* SDLControlFramePayloadRPCStartService.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLControlFramePayloadRPCStartService.m; sourceTree = "<group>"; };
+ 5DAB5F502098994C00A020C8 /* SDLMenuCellSpec.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SDLMenuCellSpec.m; path = DevAPISpecs/SDLMenuCellSpec.m; sourceTree = "<group>"; };
+ 5DAB5F5220989A8300A020C8 /* SDLVoiceCommandSpec.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SDLVoiceCommandSpec.m; path = DevAPISpecs/SDLVoiceCommandSpec.m; sourceTree = "<group>"; };
+ 5DAB5F542098E5D100A020C8 /* SDLProtocolConstants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDLProtocolConstants.h; sourceTree = "<group>"; };
+ 5DAB5F552098E5D100A020C8 /* SDLProtocolConstants.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLProtocolConstants.m; sourceTree = "<group>"; };
5DAD5F7D204DEDEB0025624C /* SDLScreenManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDLScreenManager.h; sourceTree = "<group>"; };
5DAD5F7E204DEDEB0025624C /* SDLScreenManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLScreenManager.m; sourceTree = "<group>"; };
5DAD5F8420507E1F0025624C /* SDLScreenManagerSpec.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLScreenManagerSpec.m; sourceTree = "<group>"; };
@@ -2317,18 +2392,63 @@
5DEF69641FD6FEF7004B8C2F /* SDLStreamingAudioManagerMock.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDLStreamingAudioManagerMock.h; sourceTree = "<group>"; };
5DEF69651FD6FEF7004B8C2F /* SDLStreamingAudioManagerMock.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLStreamingAudioManagerMock.m; sourceTree = "<group>"; };
5DF2BB9C1B94E38A00CE5994 /* SDLURLSessionSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SDLURLSessionSpec.m; path = "UtilitiesSpecs/HTTP Connection/SDLURLSessionSpec.m"; sourceTree = "<group>"; };
+ 5DF40B20208E761A00DD6FDA /* SDLVoiceCommandManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDLVoiceCommandManager.h; sourceTree = "<group>"; };
+ 5DF40B21208E761A00DD6FDA /* SDLVoiceCommandManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLVoiceCommandManager.m; sourceTree = "<group>"; };
+ 5DF40B25208FA7DE00DD6FDA /* SDLMenuManagerSpec.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SDLMenuManagerSpec.m; path = DevAPISpecs/SDLMenuManagerSpec.m; sourceTree = "<group>"; };
+ 5DF40B27208FDA9700DD6FDA /* SDLVoiceCommandManagerSpec.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SDLVoiceCommandManagerSpec.m; path = DevAPISpecs/SDLVoiceCommandManagerSpec.m; sourceTree = "<group>"; };
5DFFB9141BD7C89700DB3F04 /* SDLConnectionManagerType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLConnectionManagerType.h; sourceTree = "<group>"; };
+ 8800871A20A6338C008E1EA0 /* ButtonManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ButtonManager.h; sourceTree = "<group>"; };
+ 8800871B20A6338C008E1EA0 /* ButtonManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ButtonManager.m; sourceTree = "<group>"; };
+ 8803A0AB208E2907009FDC02 /* AudioManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AudioManager.h; sourceTree = "<group>"; };
+ 8803A0AC208E2907009FDC02 /* AudioManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AudioManager.m; sourceTree = "<group>"; };
+ 8803A0B0208E7CA4009FDC02 /* VehicleDataManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VehicleDataManager.h; sourceTree = "<group>"; };
+ 8803A0B1208E7CA4009FDC02 /* VehicleDataManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VehicleDataManager.m; sourceTree = "<group>"; };
+ 880E35B22088F75A00181259 /* SDLSystemCapabilityManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLSystemCapabilityManager.m; sourceTree = "<group>"; };
+ 880E35B32088F75A00181259 /* SDLSystemCapabilityManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLSystemCapabilityManager.h; sourceTree = "<group>"; };
+ 880E35B72088F78E00181259 /* SDLSystemCapabilityManagerSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLSystemCapabilityManagerSpec.m; sourceTree = "<group>"; };
+ 8814AEA520AB65FC00466E0F /* MenuManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MenuManager.h; sourceTree = "<group>"; };
+ 8814AEA620AB65FC00466E0F /* MenuManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MenuManager.m; sourceTree = "<group>"; };
+ 8814AEA820AB663800466E0F /* PerformInteractionManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PerformInteractionManager.h; sourceTree = "<group>"; };
+ 8814AEA920AB663800466E0F /* PerformInteractionManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PerformInteractionManager.m; sourceTree = "<group>"; };
+ 8814AEAB20AB667B00466E0F /* PerformInteractionManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PerformInteractionManager.swift; sourceTree = "<group>"; };
+ 88166AFF207E41E900076236 /* MenuManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuManager.swift; sourceTree = "<group>"; };
+ 88295697207CF68800EF056C /* SDL Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "SDL Example.app"; sourceTree = BUILT_PRODUCTS_DIR; };
+ 88295698207CF68800EF056C /* SmartDeviceLink-Example-Swift-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "SmartDeviceLink-Example-Swift-Info.plist"; path = "/Users/nicolelivioradio.com/sdl_ios/SmartDeviceLink-Example-Swift-Info.plist"; sourceTree = "<absolute>"; };
+ 8829569C207CFD0D00EF056C /* SmartDeviceLink-Example-Swift-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SmartDeviceLink-Example-Swift-Bridging-Header.h"; sourceTree = "<group>"; };
+ 8829569D207CFD0E00EF056C /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
8850DB5E1F4475D30053A48D /* TestMultipleFilesConnectionManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestMultipleFilesConnectionManager.h; sourceTree = "<group>"; };
8850DB5F1F4475D30053A48D /* TestMultipleFilesConnectionManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TestMultipleFilesConnectionManager.m; sourceTree = "<group>"; };
+ 8863B596207D2388002D6459 /* AppConstants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppConstants.h; sourceTree = "<group>"; };
+ 8863B597207D2388002D6459 /* AppConstants.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppConstants.m; sourceTree = "<group>"; };
+ 8870C3E82086623F0070E018 /* AudioManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioManager.swift; sourceTree = "<group>"; };
8877F5EA1F34A3BE00DC128A /* SDLSendHapticDataSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLSendHapticDataSpec.m; sourceTree = "<group>"; };
8877F5EC1F34A72200DC128A /* SDLSendHapticDataResponse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLSendHapticDataResponse.h; sourceTree = "<group>"; };
8877F5ED1F34A72200DC128A /* SDLSendHapticDataResponse.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLSendHapticDataResponse.m; sourceTree = "<group>"; };
8877F5F01F34AA2D00DC128A /* SDLSendHapticDataResponseSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLSendHapticDataResponseSpec.m; sourceTree = "<group>"; };
+ 88802FEF20853AE600E9EBC6 /* SmartDeviceLinkSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SmartDeviceLinkSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ 888D178D207E7F0E008E9F8F /* ButtonManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonManager.swift; sourceTree = "<group>"; };
+ 88A0AA55207CFE5C0075132C /* AppUserDefaults.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppUserDefaults.swift; sourceTree = "<group>"; };
+ 88A0AA57207CFE650075132C /* ProxyManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProxyManager.swift; sourceTree = "<group>"; };
+ 88A0AA59207CFE740075132C /* ConnectionContainerViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConnectionContainerViewController.swift; sourceTree = "<group>"; };
+ 88A0AA5A207CFE740075132C /* ConnectionIAPTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConnectionIAPTableViewController.swift; sourceTree = "<group>"; };
+ 88A0AA5B207CFE740075132C /* ConnectionTCPTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConnectionTCPTableViewController.swift; sourceTree = "<group>"; };
+ 88A0AA61207CFF970075132C /* LaunchScreen.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = LaunchScreen.xib; sourceTree = "<group>"; };
+ 88A0AA62207CFF970075132C /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = "<group>"; };
+ 88A0AA63207CFF970075132C /* ConnectionIAPTableViewController.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = ConnectionIAPTableViewController.storyboard; sourceTree = "<group>"; };
+ 88A0AA64207CFF980075132C /* ConnectionTCPTableViewController.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = ConnectionTCPTableViewController.storyboard; sourceTree = "<group>"; };
88B848C11F45E1A600DED768 /* TestResponse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestResponse.h; sourceTree = "<group>"; };
88B848C21F45E1A600DED768 /* TestResponse.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TestResponse.m; sourceTree = "<group>"; };
88B848C71F462E3600DED768 /* TestFileProgressResponse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestFileProgressResponse.h; sourceTree = "<group>"; };
88B848C81F462E3600DED768 /* TestFileProgressResponse.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TestFileProgressResponse.m; sourceTree = "<group>"; };
+ 88B849C32080F4AF002A034D /* RPCPermissionsManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RPCPermissionsManager.swift; sourceTree = "<group>"; };
+ 88B849C620812412002A034D /* VehicleDataManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VehicleDataManager.swift; sourceTree = "<group>"; };
88D2AAE31F682BB20078D5B2 /* SDLLogConstantsSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLLogConstantsSpec.m; sourceTree = "<group>"; };
+ 88DA6D0E209794A400AD8297 /* AlertManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AlertManager.h; sourceTree = "<group>"; };
+ 88DA6D0F209794A400AD8297 /* AlertManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AlertManager.m; sourceTree = "<group>"; };
+ 88DE80B520A5C8DD00BA9CF0 /* RPCPermissionsManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RPCPermissionsManager.h; sourceTree = "<group>"; };
+ 88DE80B620A5C8DD00BA9CF0 /* RPCPermissionsManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RPCPermissionsManager.m; sourceTree = "<group>"; };
+ 88DFB051207F8DF50079D19D /* Protocol+ProxyManagerDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Protocol+ProxyManagerDelegate.swift"; sourceTree = "<group>"; };
+ 88DFB054207F96EE0079D19D /* AlertManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertManager.swift; sourceTree = "<group>"; };
88EED8361F33AE1700E6C42E /* SDLHapticRect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLHapticRect.h; sourceTree = "<group>"; };
88EED8371F33AE1700E6C42E /* SDLHapticRect.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLHapticRect.m; sourceTree = "<group>"; };
88EED83A1F33BECB00E6C42E /* SDLHapticRectSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLHapticRectSpec.m; sourceTree = "<group>"; };
@@ -2457,13 +2577,6 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
- 5D43465D1E6F38E600B639C6 /* Frameworks */ = {
- isa = PBXFrameworksBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
5D61FA181A84237100846EE7 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@@ -2483,6 +2596,22 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 8829568A207CF68800EF056C /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 88802FF520853CD500E9EBC6 /* SmartDeviceLinkSwift.framework in Frameworks */,
+ 8829568B207CF68800EF056C /* SmartDeviceLink.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 88802E5220853AE600E9EBC6 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
@@ -2832,7 +2961,6 @@
5DC09ED71F2F7F1A00F4AB1D /* Control Frame Payloads */,
1680B1051A9CD7AD00DBD79E /* HeaderSpecs */,
1680B1091A9CD7AD00DBD79E /* MessageSpecs */,
- 1680B10E1A9CD7AD00DBD79E /* SDLAbstractProtocolSpec.m */,
1680B10F1A9CD7AD00DBD79E /* SDLFunctionIDSpec.m */,
1680B10B1A9CD7AD00DBD79E /* SDLProtocolSpec.m */,
1680B1101A9CD7AD00DBD79E /* SDLProtocolMessageAssemblerSpec.m */,
@@ -2862,13 +2990,6 @@
path = MessageSpecs;
sourceTree = "<group>";
};
- 5D0218E71A8D611600D1BF62 /* Frameworks */ = {
- isa = PBXGroup;
- children = (
- );
- name = Frameworks;
- sourceTree = "<group>";
- };
5D0218EB1A8E795700D1BF62 /* UI */ = {
isa = PBXGroup;
children = (
@@ -2917,6 +3038,7 @@
5D0A736F203F0C450001595D /* Screen */ = {
isa = PBXGroup;
children = (
+ 5D339CE5207C0651000CC364 /* Menu */,
5D0A737F203F23D10001595D /* Soft Button */,
5D0A737D203F23B30001595D /* Text and Graphic */,
5DAD5F7D204DEDEB0025624C /* SDLScreenManager.h */,
@@ -3029,6 +3151,29 @@
path = Utilities;
sourceTree = "<group>";
};
+ 5D339CE5207C0651000CC364 /* Menu */ = {
+ isa = PBXGroup;
+ children = (
+ 5D339CEC207C08AB000CC364 /* Cells */,
+ 5D339CF1207C0ACE000CC364 /* SDLMenuManager.h */,
+ 5D339CF2207C0ACE000CC364 /* SDLMenuManager.m */,
+ 5DF40B20208E761A00DD6FDA /* SDLVoiceCommandManager.h */,
+ 5DF40B21208E761A00DD6FDA /* SDLVoiceCommandManager.m */,
+ );
+ name = Menu;
+ sourceTree = "<group>";
+ };
+ 5D339CEC207C08AB000CC364 /* Cells */ = {
+ isa = PBXGroup;
+ children = (
+ 5D339CE8207C066E000CC364 /* SDLMenuCell.h */,
+ 5D339CE9207C066E000CC364 /* SDLMenuCell.m */,
+ 5D339CED207C08BA000CC364 /* SDLVoiceCommand.h */,
+ 5D339CEE207C08BA000CC364 /* SDLVoiceCommand.m */,
+ );
+ name = Cells;
+ sourceTree = "<group>";
+ };
5D3E48771D6F3DA40000BFEF /* Superclass Operation */ = {
isa = PBXGroup;
children = (
@@ -3063,7 +3208,7 @@
5D4019A61A76EC350006B0C2 = {
isa = PBXGroup;
children = (
- 5D4019B11A76EC350006B0C2 /* Example */,
+ 5D4019B11A76EC350006B0C2 /* Examples */,
5D61FA1D1A84237100846EE7 /* SmartDeviceLink */,
5D61FA2C1A84237100846EE7 /* SmartDeviceLinkTests */,
5D4346621E6F38E600B639C6 /* SmartDeviceLinkSwift */,
@@ -3078,34 +3223,31 @@
5D4019AF1A76EC350006B0C2 /* SDL Example.app */,
5D61FA1C1A84237100846EE7 /* SmartDeviceLink.framework */,
5D61FA261A84237100846EE7 /* SmartDeviceLinkTests.xctest */,
- 5D4346611E6F38E600B639C6 /* SmartDeviceLinkSwift.framework */,
+ 88295697207CF68800EF056C /* SDL Example.app */,
+ 88802FEF20853AE600E9EBC6 /* SmartDeviceLinkSwift.framework */,
);
name = Products;
sourceTree = "<group>";
};
- 5D4019B11A76EC350006B0C2 /* Example */ = {
+ 5D4019B11A76EC350006B0C2 /* Examples */ = {
isa = PBXGroup;
children = (
- 5D48329E1A92865900252386 /* SDL */,
- 5D48329A1A8EA31500252386 /* Utilities */,
- 5D0218EB1A8E795700D1BF62 /* UI */,
- 5D59350B1A855EB300687FB9 /* AppDelegate.h */,
- 5D59350C1A855EB300687FB9 /* AppDelegate.m */,
- 5D4029D31A76F0340006B0C2 /* Images.xcassets */,
- 5D4029DF1A76F0760006B0C2 /* LaunchScreen.xib */,
- 5D4029E11A76F0760006B0C2 /* Main.storyboard */,
- 5D4019B21A76EC350006B0C2 /* Supporting Files */,
+ 88295699207CFBD900EF056C /* Shared Assets */,
+ 88295678207CF47F00EF056C /* Swift */,
+ 88295677207CF46C00EF056C /* Objective-C */,
);
- name = Example;
+ name = Examples;
path = SmartDeviceLink_Example;
sourceTree = "<group>";
};
5D4019B21A76EC350006B0C2 /* Supporting Files */ = {
isa = PBXGroup;
children = (
- 5D0218E71A8D611600D1BF62 /* Frameworks */,
+ 5D59350B1A855EB300687FB9 /* AppDelegate.h */,
+ 5D59350C1A855EB300687FB9 /* AppDelegate.m */,
+ 5D4029DF1A76F0760006B0C2 /* LaunchScreen.xib */,
5D5935111A855EBE00687FB9 /* main.m */,
- 5D4029D51A76F0410006B0C2 /* Info.plist */,
+ 5D4029D51A76F0410006B0C2 /* SmartDeviceLink-Example-ObjC-Info.plist */,
);
name = "Supporting Files";
sourceTree = "<group>";
@@ -3176,6 +3318,7 @@
5D4832991A8EA27200252386 /* Storyboards */ = {
isa = PBXGroup;
children = (
+ 5D4029E11A76F0760006B0C2 /* Main.storyboard */,
5D0218F71A8E7A7300D1BF62 /* ConnectionTCPTableViewController.storyboard */,
5D0219031A8E9F6D00D1BF62 /* ConnectionIAPTableViewController.storyboard */,
);
@@ -3196,6 +3339,20 @@
children = (
5D48329F1A92868E00252386 /* ProxyManager.h */,
5D4832A01A92868E00252386 /* ProxyManager.m */,
+ 88DA6D0E209794A400AD8297 /* AlertManager.h */,
+ 88DA6D0F209794A400AD8297 /* AlertManager.m */,
+ 8803A0AB208E2907009FDC02 /* AudioManager.h */,
+ 8803A0AC208E2907009FDC02 /* AudioManager.m */,
+ 8800871A20A6338C008E1EA0 /* ButtonManager.h */,
+ 8800871B20A6338C008E1EA0 /* ButtonManager.m */,
+ 8814AEA520AB65FC00466E0F /* MenuManager.h */,
+ 8814AEA620AB65FC00466E0F /* MenuManager.m */,
+ 8814AEA820AB663800466E0F /* PerformInteractionManager.h */,
+ 8814AEA920AB663800466E0F /* PerformInteractionManager.m */,
+ 88DE80B520A5C8DD00BA9CF0 /* RPCPermissionsManager.h */,
+ 88DE80B620A5C8DD00BA9CF0 /* RPCPermissionsManager.m */,
+ 8803A0B0208E7CA4009FDC02 /* VehicleDataManager.h */,
+ 8803A0B1208E7CA4009FDC02 /* VehicleDataManager.m */,
);
name = SDL;
sourceTree = "<group>";
@@ -3222,8 +3379,6 @@
5D61FB451A84238B00846EE7 /* SDLPolicyDataParser.m */,
5D61FB631A84238B00846EE7 /* SDLProxy.h */,
5D61FB641A84238B00846EE7 /* SDLProxy.m */,
- 5D61FB651A84238B00846EE7 /* SDLProxyFactory.h */,
- 5D61FB661A84238B00846EE7 /* SDLProxyFactory.m */,
);
name = Proxy;
sourceTree = "<group>";
@@ -3235,12 +3390,12 @@
5D5934FA1A851AC900687FB9 /* @protocols */,
5D5935011A851D7E00687FB9 /* Header */,
5D5935021A851D8700687FB9 /* Message */,
- 5D61FA3C1A84238A00846EE7 /* SDLAbstractProtocol.h */,
- 5D61FA3D1A84238A00846EE7 /* SDLAbstractProtocol.m */,
5D61FAC01A84238A00846EE7 /* SDLFunctionID.h */,
5D61FAC11A84238A00846EE7 /* SDLFunctionID.m */,
5D61FB561A84238B00846EE7 /* SDLProtocol.h */,
5D61FB571A84238B00846EE7 /* SDLProtocol.m */,
+ 5DAB5F542098E5D100A020C8 /* SDLProtocolConstants.h */,
+ 5DAB5F552098E5D100A020C8 /* SDLProtocolConstants.m */,
5D61FB5D1A84238B00846EE7 /* SDLProtocolMessageAssembler.h */,
5D61FB5E1A84238B00846EE7 /* SDLProtocolMessageAssembler.m */,
5D61FB5F1A84238B00846EE7 /* SDLProtocolMessageDisassembler.h */,
@@ -3268,18 +3423,9 @@
5D5934F01A85161A00687FB9 /* Transport */ = {
isa = PBXGroup;
children = (
+ 5DAB5F592098E8CB00A020C8 /* TCP */,
+ 5DAB5F582098E8BC00A020C8 /* IAP */,
5D5935001A851D0B00687FB9 /* @protocols */,
- 5D61FA3E1A84238A00846EE7 /* SDLAbstractTransport.h */,
- 5D61FA3F1A84238A00846EE7 /* SDLAbstractTransport.m */,
- E9C32B891AB20BA200F283AF /* SDLIAPSession.h */,
- E9C32B8A1AB20BA200F283AF /* SDLIAPSession.m */,
- E9C32B8B1AB20BA200F283AF /* SDLIAPSessionDelegate.h */,
- 5D61FADA1A84238A00846EE7 /* SDLIAPTransport.h */,
- 5D61FADB1A84238A00846EE7 /* SDLIAPTransport.m */,
- E9C32B8C1AB20BA200F283AF /* SDLStreamDelegate.h */,
- E9C32B8D1AB20BA200F283AF /* SDLStreamDelegate.m */,
- 5D61FBD81A84238B00846EE7 /* SDLTCPTransport.h */,
- 5D61FBD91A84238B00846EE7 /* SDLTCPTransport.m */,
);
name = Transport;
sourceTree = "<group>";
@@ -3930,6 +4076,7 @@
5D5935001A851D0B00687FB9 /* @protocols */ = {
isa = PBXGroup;
children = (
+ 5D61FA3E1A84238A00846EE7 /* SDLTransportType.h */,
5D61FBED1A84238C00846EE7 /* SDLTransportDelegate.h */,
);
name = "@protocols";
@@ -4350,14 +4497,38 @@
name = "Focus / Haptic";
sourceTree = "<group>";
};
- 5DAD5F8120507DE40025624C /* Show */ = {
+ 5DAB5F582098E8BC00A020C8 /* IAP */ = {
isa = PBXGroup;
children = (
+ E9C32B891AB20BA200F283AF /* SDLIAPSession.h */,
+ E9C32B8A1AB20BA200F283AF /* SDLIAPSession.m */,
+ E9C32B8B1AB20BA200F283AF /* SDLIAPSessionDelegate.h */,
+ 5D61FADA1A84238A00846EE7 /* SDLIAPTransport.h */,
+ 5D61FADB1A84238A00846EE7 /* SDLIAPTransport.m */,
+ E9C32B8C1AB20BA200F283AF /* SDLStreamDelegate.h */,
+ E9C32B8D1AB20BA200F283AF /* SDLStreamDelegate.m */,
+ );
+ name = IAP;
+ sourceTree = "<group>";
+ };
+ 5DAB5F592098E8CB00A020C8 /* TCP */ = {
+ isa = PBXGroup;
+ children = (
+ 5D61FBD81A84238B00846EE7 /* SDLTCPTransport.h */,
+ 5D61FBD91A84238B00846EE7 /* SDLTCPTransport.m */,
+ );
+ name = TCP;
+ sourceTree = "<group>";
+ };
+ 5DAD5F8120507DE40025624C /* Screen */ = {
+ isa = PBXGroup;
+ children = (
+ 5DF40B24208FA7C500DD6FDA /* Menu */,
5DAD5F8220507DED0025624C /* Soft Button */,
5DAD5F8320507DF30025624C /* Text and Graphic */,
5DAD5F8420507E1F0025624C /* SDLScreenManagerSpec.m */,
);
- name = Show;
+ name = Screen;
sourceTree = "<group>";
};
5DAD5F8220507DED0025624C /* Soft Button */ = {
@@ -4508,6 +4679,7 @@
5D8204291BCEA91400D0A41B /* Permissions */,
DA8966E71E56937100413EAB /* Streaming */,
5D0A736F203F0C450001595D /* Screen */,
+ 880E35B12088F73400181259 /* System Capabilities */,
);
name = Managers;
sourceTree = "<group>";
@@ -4524,8 +4696,9 @@
5DBAE0A81D35886E00CE00BF /* Managers */ = {
isa = PBXGroup;
children = (
- 5DAD5F8120507DE40025624C /* Show */,
+ 5DAD5F8120507DE40025624C /* Screen */,
DA8966ED1E5693D100413EAB /* Streaming */,
+ 880E35B62088F77C00181259 /* System Capabilities */,
5D1654541D3E753100554D93 /* Lifecycle */,
5D76E31A1D3805E600647CFA /* LockScreen */,
5D9F507F1BE7E6C900FEF399 /* Permissions */,
@@ -4673,6 +4846,130 @@
name = Mocks;
sourceTree = "<group>";
};
+ 5DF40B24208FA7C500DD6FDA /* Menu */ = {
+ isa = PBXGroup;
+ children = (
+ 5DF40B25208FA7DE00DD6FDA /* SDLMenuManagerSpec.m */,
+ 5DF40B27208FDA9700DD6FDA /* SDLVoiceCommandManagerSpec.m */,
+ 5DAB5F502098994C00A020C8 /* SDLMenuCellSpec.m */,
+ 5DAB5F5220989A8300A020C8 /* SDLVoiceCommandSpec.m */,
+ );
+ name = Menu;
+ sourceTree = "<group>";
+ };
+ 880E35B12088F73400181259 /* System Capabilities */ = {
+ isa = PBXGroup;
+ children = (
+ 880E35B32088F75A00181259 /* SDLSystemCapabilityManager.h */,
+ 880E35B22088F75A00181259 /* SDLSystemCapabilityManager.m */,
+ );
+ name = "System Capabilities";
+ sourceTree = "<group>";
+ };
+ 880E35B62088F77C00181259 /* System Capabilities */ = {
+ isa = PBXGroup;
+ children = (
+ 880E35B72088F78E00181259 /* SDLSystemCapabilityManagerSpec.m */,
+ );
+ name = "System Capabilities";
+ sourceTree = "<group>";
+ };
+ 88295677207CF46C00EF056C /* Objective-C */ = {
+ isa = PBXGroup;
+ children = (
+ 5D48329E1A92865900252386 /* SDL */,
+ 5D48329A1A8EA31500252386 /* Utilities */,
+ 5D0218EB1A8E795700D1BF62 /* UI */,
+ 5D4019B21A76EC350006B0C2 /* Supporting Files */,
+ );
+ name = "Objective-C";
+ sourceTree = "<group>";
+ };
+ 88295678207CF47F00EF056C /* Swift */ = {
+ isa = PBXGroup;
+ children = (
+ 88295679207CF48C00EF056C /* SDL */,
+ 8829567C207CF4AB00EF056C /* Utilities */,
+ 8829567B207CF49F00EF056C /* UI */,
+ 8829567A207CF49600EF056C /* Supporting Files */,
+ );
+ name = Swift;
+ sourceTree = "<group>";
+ };
+ 88295679207CF48C00EF056C /* SDL */ = {
+ isa = PBXGroup;
+ children = (
+ 88A0AA57207CFE650075132C /* ProxyManager.swift */,
+ 88DFB054207F96EE0079D19D /* AlertManager.swift */,
+ 8870C3E82086623F0070E018 /* AudioManager.swift */,
+ 888D178D207E7F0E008E9F8F /* ButtonManager.swift */,
+ 88166AFF207E41E900076236 /* MenuManager.swift */,
+ 8814AEAB20AB667B00466E0F /* PerformInteractionManager.swift */,
+ 88B849C32080F4AF002A034D /* RPCPermissionsManager.swift */,
+ 88B849C620812412002A034D /* VehicleDataManager.swift */,
+ );
+ name = SDL;
+ sourceTree = "<group>";
+ };
+ 8829567A207CF49600EF056C /* Supporting Files */ = {
+ isa = PBXGroup;
+ children = (
+ 8829569D207CFD0E00EF056C /* AppDelegate.swift */,
+ 88A0AA61207CFF970075132C /* LaunchScreen.xib */,
+ 88295698207CF68800EF056C /* SmartDeviceLink-Example-Swift-Info.plist */,
+ 8829569C207CFD0D00EF056C /* SmartDeviceLink-Example-Swift-Bridging-Header.h */,
+ );
+ name = "Supporting Files";
+ sourceTree = "<group>";
+ };
+ 8829567B207CF49F00EF056C /* UI */ = {
+ isa = PBXGroup;
+ children = (
+ 88A0AA5F207CFEA60075132C /* Connection */,
+ 88A0AA59207CFE740075132C /* ConnectionContainerViewController.swift */,
+ 88A0AA5A207CFE740075132C /* ConnectionIAPTableViewController.swift */,
+ 88A0AA5B207CFE740075132C /* ConnectionTCPTableViewController.swift */,
+ );
+ name = UI;
+ sourceTree = "<group>";
+ };
+ 8829567C207CF4AB00EF056C /* Utilities */ = {
+ isa = PBXGroup;
+ children = (
+ 88A0AA55207CFE5C0075132C /* AppUserDefaults.swift */,
+ 88DFB051207F8DF50079D19D /* Protocol+ProxyManagerDelegate.swift */,
+ );
+ name = Utilities;
+ sourceTree = "<group>";
+ };
+ 88295699207CFBD900EF056C /* Shared Assets */ = {
+ isa = PBXGroup;
+ children = (
+ 5D4029D31A76F0340006B0C2 /* Images.xcassets */,
+ 8863B596207D2388002D6459 /* AppConstants.h */,
+ 8863B597207D2388002D6459 /* AppConstants.m */,
+ );
+ name = "Shared Assets";
+ sourceTree = "<group>";
+ };
+ 88A0AA5F207CFEA60075132C /* Connection */ = {
+ isa = PBXGroup;
+ children = (
+ 88A0AA60207CFEAC0075132C /* Storyboards */,
+ );
+ name = Connection;
+ sourceTree = "<group>";
+ };
+ 88A0AA60207CFEAC0075132C /* Storyboards */ = {
+ isa = PBXGroup;
+ children = (
+ 88A0AA63207CFF970075132C /* ConnectionIAPTableViewController.storyboard */,
+ 88A0AA64207CFF980075132C /* ConnectionTCPTableViewController.storyboard */,
+ 88A0AA62207CFF970075132C /* Main.storyboard */,
+ );
+ name = Storyboards;
+ sourceTree = "<group>";
+ };
88B848C41F45E20900DED768 /* Helpers */ = {
isa = PBXGroup;
children = (
@@ -4796,14 +5093,6 @@
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
- 5D43465E1E6F38E600B639C6 /* Headers */ = {
- isa = PBXHeadersBuildPhase;
- buildActionMask = 2147483647;
- files = (
- 5D4346651E6F38E600B639C6 /* SmartDeviceLinkSwift.h in Headers */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
5D61FA191A84237100846EE7 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
@@ -4829,7 +5118,6 @@
5D61FD151A84238C00846EE7 /* SDLOnLockScreenStatus.h in Headers */,
5D61FD291A84238C00846EE7 /* SDLPerformInteraction.h in Headers */,
DAC572571D1067270004288B /* SDLTouchManager.h in Headers */,
- 5D61FD521A84238C00846EE7 /* SDLProxyFactory.h in Headers */,
5D61FE0D1A84238C00846EE7 /* SDLVrCapabilities.h in Headers */,
5DBF06271E64A91D00A5CF03 /* SDLLogFileModule.h in Headers */,
5D61FC531A84238C00846EE7 /* SDLButtonEventMode.h in Headers */,
@@ -4885,7 +5173,7 @@
5DA3F3541BC448060026F2D0 /* NSMapTable+Subscripting.h in Headers */,
5D61FC591A84238C00846EE7 /* SDLCarModeStatus.h in Headers */,
5D1665C41CF8CA2700CC4CA1 /* SDLListFilesOperation.h in Headers */,
- 5D61FC2B1A84238C00846EE7 /* SDLAbstractTransport.h in Headers */,
+ 5D61FC2B1A84238C00846EE7 /* SDLTransportType.h in Headers */,
5D61FD791A84238C00846EE7 /* SDLScreenParams.h in Headers */,
5D61FDCF1A84238C00846EE7 /* SDLTireStatus.h in Headers */,
5D61FDFD1A84238C00846EE7 /* SDLVehicleDataActiveStatus.h in Headers */,
@@ -4899,6 +5187,7 @@
5D61FD091A84238C00846EE7 /* SDLOnDriverDistraction.h in Headers */,
E9C32B9E1AB20C5900F283AF /* EAAccessoryManager+SDLProtocols.h in Headers */,
5DAD5F7F204DEDEB0025624C /* SDLScreenManager.h in Headers */,
+ 5D339CEF207C08BA000CC364 /* SDLVoiceCommand.h in Headers */,
5D61FC4B1A84238C00846EE7 /* SDLBeltStatus.h in Headers */,
DAC5726B1D10D5FC0004288B /* dispatch_timer.h in Headers */,
DA9F7E991DCC052C00ACAE48 /* SDLLocationCoordinate.h in Headers */,
@@ -4979,7 +5268,6 @@
5DCF76F51ACDBAD300BB647B /* SDLSendLocation.h in Headers */,
5D61FC9E1A84238C00846EE7 /* SDLEncodedSyncPData.h in Headers */,
1FF7DABA1F75B2A800B46C30 /* SDLFocusableItemLocator.h in Headers */,
- 5D61FC291A84238C00846EE7 /* SDLAbstractProtocol.h in Headers */,
5D61FDE11A84238C00846EE7 /* SDLTurn.h in Headers */,
5D9FC29B1FD8812F00ACA5C2 /* SDLAudioStreamManagerDelegate.h in Headers */,
5D61FC801A84238C00846EE7 /* SDLDeleteSubMenuResponse.h in Headers */,
@@ -5008,6 +5296,7 @@
5D61FC8C1A84238C00846EE7 /* SDLDIDResult.h in Headers */,
5D61FD1F1A84238C00846EE7 /* SDLOnTouchEvent.h in Headers */,
5D61FCB31A84238C00846EE7 /* SDLGetDTCsResponse.h in Headers */,
+ 5DAB5F562098E5D100A020C8 /* SDLProtocolConstants.h in Headers */,
5D61FC4D1A84238C00846EE7 /* SDLBitsPerSample.h in Headers */,
5D61FD9B1A84238C00846EE7 /* SDLSlider.h in Headers */,
5D61FD111A84238C00846EE7 /* SDLOnKeyboardInput.h in Headers */,
@@ -5069,6 +5358,7 @@
5DD67CB81E661C4A009CD394 /* SDLLogTargetFile.h in Headers */,
5D61FD591A84238C00846EE7 /* SDLReadDID.h in Headers */,
5D82041A1BCD80BA00D0A41B /* SDLLockScreenConfiguration.h in Headers */,
+ 880E35B52088F75A00181259 /* SDLSystemCapabilityManager.h in Headers */,
5D61FC611A84238C00846EE7 /* SDLChoice.h in Headers */,
5D1BF6AF204742FB00D36881 /* SDLDisplayCapabilities+ShowManagerExtensions.h in Headers */,
5D7F87F31CE3C29E002DD7C4 /* SDLFileWrapper.h in Headers */,
@@ -5170,6 +5460,7 @@
5D1665CB1CF8CA6700CC4CA1 /* NSNumber+NumberType.h in Headers */,
5D9FDA941F2A7D3400A495C8 /* bson_util.h in Headers */,
5D61FD771A84238C00846EE7 /* SDLSamplingRate.h in Headers */,
+ 5DF40B22208E761A00DD6FDA /* SDLVoiceCommandManager.h in Headers */,
5D61FCBB1A84238C00846EE7 /* SDLGPSData.h in Headers */,
5D61FDA31A84238C00846EE7 /* SDLSoftButtonType.h in Headers */,
5D61FC431A84238C00846EE7 /* SDLAppInterfaceUnregisteredReason.h in Headers */,
@@ -5197,6 +5488,7 @@
97E26DEC1E807AD70074A3C7 /* SDLMutableDataQueue.h in Headers */,
5D61FDF71A84238C00846EE7 /* SDLV1ProtocolMessage.h in Headers */,
5D61FDFB1A84238C00846EE7 /* SDLV2ProtocolMessage.h in Headers */,
+ 5D339CEA207C066E000CC364 /* SDLMenuCell.h in Headers */,
5DBF06311E64A9C600A5CF03 /* SDLLogModel.h in Headers */,
5D7F87EB1CE3C1A1002DD7C4 /* SDLDeleteFileOperation.h in Headers */,
5D61FCFC1A84238C00846EE7 /* SDLNames.h in Headers */,
@@ -5210,17 +5502,26 @@
5D00AC6B1F141339004000D9 /* SDLSystemCapability.h in Headers */,
5DCD7AE01FCCA8D200A0FC7F /* SDLCarWindow.h in Headers */,
5D61FD6F1A84238C00846EE7 /* SDLRPCPayload.h in Headers */,
+ 5D339CF3207C0ACE000CC364 /* SDLMenuManager.h in Headers */,
5D61FCF01A84238C00846EE7 /* SDLLockScreenStatusManager.h in Headers */,
5D61FD311A84238C00846EE7 /* SDLPolicyDataParser.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 88802E5320853AE600E9EBC6 /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 88802FF420853BED00E9EBC6 /* SmartDeviceLinkSwift.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
- 5D4019AE1A76EC350006B0C2 /* SmartDeviceLink-Example */ = {
+ 5D4019AE1A76EC350006B0C2 /* SmartDeviceLink-Example-ObjC */ = {
isa = PBXNativeTarget;
- buildConfigurationList = 5D4019D21A76EC350006B0C2 /* Build configuration list for PBXNativeTarget "SmartDeviceLink-Example" */;
+ buildConfigurationList = 5D4019D21A76EC350006B0C2 /* Build configuration list for PBXNativeTarget "SmartDeviceLink-Example-ObjC" */;
buildPhases = (
5D4019AB1A76EC350006B0C2 /* Sources */,
5D4019AC1A76EC350006B0C2 /* Frameworks */,
@@ -5232,30 +5533,11 @@
dependencies = (
5D61FA321A84237100846EE7 /* PBXTargetDependency */,
);
- name = "SmartDeviceLink-Example";
+ name = "SmartDeviceLink-Example-ObjC";
productName = "SmartDeviceLink-iOS";
productReference = 5D4019AF1A76EC350006B0C2 /* SDL Example.app */;
productType = "com.apple.product-type.application";
};
- 5D4346601E6F38E600B639C6 /* SmartDeviceLinkSwift */ = {
- isa = PBXNativeTarget;
- buildConfigurationList = 5D4346661E6F38E600B639C6 /* Build configuration list for PBXNativeTarget "SmartDeviceLinkSwift" */;
- buildPhases = (
- 5D43465C1E6F38E600B639C6 /* Sources */,
- 5D43465D1E6F38E600B639C6 /* Frameworks */,
- 5D43465E1E6F38E600B639C6 /* Headers */,
- 5D43465F1E6F38E600B639C6 /* Resources */,
- );
- buildRules = (
- );
- dependencies = (
- 5D43468C1E788E2200B639C6 /* PBXTargetDependency */,
- );
- name = SmartDeviceLinkSwift;
- productName = SmartDeviceLinkSwift;
- productReference = 5D4346611E6F38E600B639C6 /* SmartDeviceLinkSwift.framework */;
- productType = "com.apple.product-type.framework";
- };
5D61FA1B1A84237100846EE7 /* SmartDeviceLink */ = {
isa = PBXNativeTarget;
buildConfigurationList = 5D61FA351A84237100846EE7 /* Build configuration list for PBXNativeTarget "SmartDeviceLink" */;
@@ -5294,6 +5576,45 @@
productReference = 5D61FA261A84237100846EE7 /* SmartDeviceLinkTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
+ 8829567D207CF68800EF056C /* SmartDeviceLink-Example-Swift */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 88295694207CF68800EF056C /* Build configuration list for PBXNativeTarget "SmartDeviceLink-Example-Swift" */;
+ buildPhases = (
+ 88295680207CF68800EF056C /* Sources */,
+ 8829568A207CF68800EF056C /* Frameworks */,
+ 8829568C207CF68800EF056C /* Resources */,
+ 88295692207CF68800EF056C /* Embed Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 8829567E207CF68800EF056C /* PBXTargetDependency */,
+ 88802FF820853CD500E9EBC6 /* PBXTargetDependency */,
+ );
+ name = "SmartDeviceLink-Example-Swift";
+ productName = "SmartDeviceLink-iOS";
+ productReference = 88295697207CF68800EF056C /* SDL Example.app */;
+ productType = "com.apple.product-type.application";
+ };
+ 88802CD720853AE600E9EBC6 /* SmartDeviceLinkSwift */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 88802FEC20853AE600E9EBC6 /* Build configuration list for PBXNativeTarget "SmartDeviceLinkSwift" */;
+ buildPhases = (
+ 88802CD820853AE600E9EBC6 /* Sources */,
+ 88802E5220853AE600E9EBC6 /* Frameworks */,
+ 88802E5320853AE600E9EBC6 /* Headers */,
+ 88802FE820853AE600E9EBC6 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 88802FF320853BBF00E9EBC6 /* PBXTargetDependency */,
+ );
+ name = SmartDeviceLinkSwift;
+ productName = SmartDeviceLink;
+ productReference = 88802FEF20853AE600E9EBC6 /* SmartDeviceLinkSwift.framework */;
+ productType = "com.apple.product-type.framework";
+ };
/* End PBXNativeTarget section */
/* Begin PBXProject section */
@@ -5317,11 +5638,6 @@
};
};
};
- 5D4346601E6F38E600B639C6 = {
- CreatedOnToolsVersion = 8.2.1;
- LastSwiftMigration = 0900;
- ProvisioningStyle = Automatic;
- };
5D61FA1B1A84237100846EE7 = {
CreatedOnToolsVersion = 6.1.1;
LastSwiftMigration = 0930;
@@ -5330,6 +5646,9 @@
CreatedOnToolsVersion = 6.1.1;
LastSwiftMigration = 0920;
};
+ 8829567D207CF68800EF056C = {
+ LastSwiftMigration = 0930;
+ };
};
};
buildConfigurationList = 5D4019AA1A76EC350006B0C2 /* Build configuration list for PBXProject "SmartDeviceLink-iOS" */;
@@ -5345,10 +5664,11 @@
projectDirPath = "";
projectRoot = "";
targets = (
- 5D4019AE1A76EC350006B0C2 /* SmartDeviceLink-Example */,
5D61FA1B1A84237100846EE7 /* SmartDeviceLink */,
5D61FA251A84237100846EE7 /* SmartDeviceLinkTests */,
- 5D4346601E6F38E600B639C6 /* SmartDeviceLinkSwift */,
+ 5D4019AE1A76EC350006B0C2 /* SmartDeviceLink-Example-ObjC */,
+ 8829567D207CF68800EF056C /* SmartDeviceLink-Example-Swift */,
+ 88802CD720853AE600E9EBC6 /* SmartDeviceLinkSwift */,
);
};
/* End PBXProject section */
@@ -5366,13 +5686,6 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
- 5D43465F1E6F38E600B639C6 /* Resources */ = {
- isa = PBXResourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
5D61FA1A1A84237100846EE7 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
@@ -5400,6 +5713,28 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 8829568C207CF68800EF056C /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 88A0AA66207CFF980075132C /* Main.storyboard in Resources */,
+ 88A0AA68207CFF980075132C /* ConnectionTCPTableViewController.storyboard in Resources */,
+ 88A0AA65207CFF980075132C /* LaunchScreen.xib in Resources */,
+ 88295690207CF68800EF056C /* Images.xcassets in Resources */,
+ 88A0AA67207CFF980075132C /* ConnectionIAPTableViewController.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 88802FE820853AE600E9EBC6 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 88802FE920853AE600E9EBC6 /* LICENSE in Resources */,
+ 88802FEA20853AE600E9EBC6 /* SDLAssets.xcassets in Resources */,
+ 88802FEB20853AE600E9EBC6 /* SDLLockScreen.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@@ -5408,22 +5743,22 @@
buildActionMask = 2147483647;
files = (
5D4832A51A94F90D00252386 /* ConnectionTransitionContext.m in Sources */,
+ 8800871E20A6356D008E1EA0 /* ButtonManager.m in Sources */,
5D0218FC1A8E7E1700D1BF62 /* ConnectionContainerViewController.m in Sources */,
+ 88DA6D10209794A400AD8297 /* AlertManager.m in Sources */,
+ 8803A0AF208E2A3A009FDC02 /* AudioManager.m in Sources */,
5D0218FF1A8E9E0D00D1BF62 /* ConnectionIAPTableViewController.m in Sources */,
+ 8803A0B2208E7CA4009FDC02 /* VehicleDataManager.m in Sources */,
5D48329D1A8EA33D00252386 /* Preferences.m in Sources */,
+ 8814AEA720AB65FC00466E0F /* MenuManager.m in Sources */,
+ 8814AEAA20AB663800466E0F /* PerformInteractionManager.m in Sources */,
5D59350F1A855EB300687FB9 /* AppDelegate.m in Sources */,
5D5935121A855EBE00687FB9 /* main.m in Sources */,
5D4832A81A95191B00252386 /* ConnectionAnimatedTransition.m in Sources */,
+ 88DE80B720A5C8DD00BA9CF0 /* RPCPermissionsManager.m in Sources */,
5D4832A11A92868E00252386 /* ProxyManager.m in Sources */,
5D0218F61A8E79C400D1BF62 /* ConnectionTCPTableViewController.m in Sources */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
- 5D43465C1E6F38E600B639C6 /* Sources */ = {
- isa = PBXSourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- 5D4346861E771B5700B639C6 /* SDLLog.swift in Sources */,
+ 8863B59D207D3849002D6459 /* AppConstants.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -5445,7 +5780,6 @@
5D61FDEC1A84238C00846EE7 /* SDLUnsubscribeVehicleData.m in Sources */,
5D61FDBE1A84238C00846EE7 /* SDLSystemContext.m in Sources */,
5D61FC441A84238C00846EE7 /* SDLAppInterfaceUnregisteredReason.m in Sources */,
- 5D61FD531A84238C00846EE7 /* SDLProxyFactory.m in Sources */,
5D0A7387203F24060001595D /* SDLSoftButtonState.m in Sources */,
5D61FDCA1A84238C00846EE7 /* SDLTextField.m in Sources */,
DAA41D561DF66B2000BC7337 /* SDLH264VideoEncoder.m in Sources */,
@@ -5675,6 +6009,7 @@
5D61FDC41A84238C00846EE7 /* SDLTBTState.m in Sources */,
5D61FDA61A84238C00846EE7 /* SDLSpeak.m in Sources */,
5D4631111F2135850092EFDC /* SDLControlFramePayloadConstants.m in Sources */,
+ 5D339CF0207C08BA000CC364 /* SDLVoiceCommand.m in Sources */,
DA9F7E881DCC049900ACAE48 /* SDLSubscribeWayPoints.m in Sources */,
5D61FDDE1A84238C00846EE7 /* SDLTTSChunk.m in Sources */,
5D61FD9E1A84238C00846EE7 /* SDLSliderResponse.m in Sources */,
@@ -5688,9 +6023,11 @@
5D16545B1D3E7A1600554D93 /* SDLLifecycleManager.m in Sources */,
E9C32B971AB20BA200F283AF /* SDLTimer.m in Sources */,
5D61FCB61A84238C00846EE7 /* SDLGetVehicleData.m in Sources */,
+ 5DAB5F572098E5D100A020C8 /* SDLProtocolConstants.m in Sources */,
5D61FC9F1A84238C00846EE7 /* SDLEncodedSyncPData.m in Sources */,
5D61FE061A84238C00846EE7 /* SDLVehicleDataResultCode.m in Sources */,
5D61FCA41A84238C00846EE7 /* SDLEndAudioPassThru.m in Sources */,
+ 5D339CEB207C066E000CC364 /* SDLMenuCell.m in Sources */,
5D8B17541AC9E11B006A6E1C /* SDLDialNumberResponse.m in Sources */,
DA6223BE1E7B088200878689 /* CVPixelBufferRef+SDLUtil.m in Sources */,
1FF7DABC1F75B2BF00B46C30 /* SDLFocusableItemLocator.m in Sources */,
@@ -5703,6 +6040,7 @@
5D61FD581A84238C00846EE7 /* SDLPutFileResponse.m in Sources */,
5D61FCB21A84238C00846EE7 /* SDLGetDTCs.m in Sources */,
5D61FD441A84238C00846EE7 /* SDLProtocol.m in Sources */,
+ 5DF40B23208E761A00DD6FDA /* SDLVoiceCommandManager.m in Sources */,
5D61FC341A84238C00846EE7 /* SDLAddSubMenuResponse.m in Sources */,
5DA240011F325621009C0313 /* SDLStreamingMediaConfiguration.m in Sources */,
5D6F7A2F1BC5650B0070BF37 /* SDLLifecycleConfiguration.m in Sources */,
@@ -5757,7 +6095,6 @@
8877F5EF1F34A72200DC128A /* SDLSendHapticDataResponse.m in Sources */,
5D61FD181A84238C00846EE7 /* SDLOnPermissionsChange.m in Sources */,
5D61FD3E1A84238C00846EE7 /* SDLPrimaryAudioSource.m in Sources */,
- 5D61FC2A1A84238C00846EE7 /* SDLAbstractProtocol.m in Sources */,
1E5AD0851F20B9290029B8AF /* SDLButtonPressResponse.m in Sources */,
5D82041F1BCD8E6100D0A41B /* SDLConfiguration.m in Sources */,
5D61FD381A84238C00846EE7 /* SDLPredefinedLayout.m in Sources */,
@@ -5783,11 +6120,11 @@
5DCD7AF71FCCA8E400A0FC7F /* SDLScreenshotViewController.m in Sources */,
5D61FD081A84238C00846EE7 /* SDLOnCommand.m in Sources */,
5D53C46E1B7A99B9003526EA /* SDLStreamingMediaManager.m in Sources */,
+ 5D339CF4207C0ACE000CC364 /* SDLMenuManager.m in Sources */,
5D61FD6A1A84238C00846EE7 /* SDLRPCMessage.m in Sources */,
1E5AD0391F1F4E390029B8AF /* SDLClimateControlCapabilities.m in Sources */,
5D61FDA21A84238C00846EE7 /* SDLSoftButtonCapabilities.m in Sources */,
5D8204321BD001C700D0A41B /* SDLArtwork.m in Sources */,
- 5D61FC2C1A84238C00846EE7 /* SDLAbstractTransport.m in Sources */,
5D61FD8E1A84238C00846EE7 /* SDLSetMediaClockTimerResponse.m in Sources */,
5D61FD721A84238C00846EE7 /* SDLRPCRequest.m in Sources */,
EED5CA081F4D1E2E00F04000 /* SDLRTPH264Packetizer.m in Sources */,
@@ -5795,6 +6132,7 @@
5D61FC931A84238C00846EE7 /* SDLDisplayType.m in Sources */,
5D61FCE31A84238C00846EE7 /* SDLKeyboardLayout.m in Sources */,
5D61FE0C1A84238C00846EE7 /* SDLVehicleType.m in Sources */,
+ 880E35B42088F75A00181259 /* SDLSystemCapabilityManager.m in Sources */,
DA9F7E941DCC04E400ACAE48 /* SDLUnsubscribeWayPoints.m in Sources */,
5D61FDCC1A84238C00846EE7 /* SDLTextFieldName.m in Sources */,
5D61FC751A84238C00846EE7 /* SDLDeleteCommandResponse.m in Sources */,
@@ -5848,7 +6186,6 @@
162E83331A9BDE8B00906325 /* SDLPerformInteractionSpec.m in Sources */,
5D0A9F951F15585B00CC80DD /* SDLPhoneCapabilitySpec.m in Sources */,
1EE8C4561F38788A00FDC2CF /* SDLButtonPressSpec.m in Sources */,
- 1680B11A1A9CD7AD00DBD79E /* SDLAbstractProtocolSpec.m in Sources */,
1680B1151A9CD7AD00DBD79E /* SDLV2ProtocolHeaderSpec.m in Sources */,
1EE8C4541F38762E00FDC2CF /* SDLOnInteriorVehicleDataSpec.m in Sources */,
162E83101A9BDE8B00906325 /* SDLOnAudioPassThruSpec.m in Sources */,
@@ -5856,6 +6193,7 @@
5DBEFA581F436132009EE295 /* SDLFakeSecurityManager.m in Sources */,
162E82D91A9BDE8A00906325 /* SDLDisplayTypeSpec.m in Sources */,
162E83871A9BDE8B00906325 /* SDLPermissionItemSpec.m in Sources */,
+ 5DAB5F5320989A8300A020C8 /* SDLVoiceCommandSpec.m in Sources */,
162E82E31A9BDE8B00906325 /* SDLIgnitionStatusSpec.m in Sources */,
162E83511A9BDE8B00906325 /* SDLDeleteInteractionChoiceSetResponseSpec.m in Sources */,
DA9F7EB41DCC086400ACAE48 /* SDLDateTimeSpec.m in Sources */,
@@ -5880,6 +6218,7 @@
162E83681A9BDE8B00906325 /* SDLSpeakResponseSpec.m in Sources */,
162E83661A9BDE8B00906325 /* SDLShowResponseSpec.m in Sources */,
5D9F50831BEA5C6100FEF399 /* SDLFileManagerSpec.m in Sources */,
+ 5DAB5F512098994C00A020C8 /* SDLMenuCellSpec.m in Sources */,
1EE8C4481F38430900FDC2CF /* SDLRadioControlCapabilitiesSpec.m in Sources */,
162E83221A9BDE8B00906325 /* SDLAddCommandSpec.m in Sources */,
162E83121A9BDE8B00906325 /* SDLOnButtonPressSpec.m in Sources */,
@@ -5888,6 +6227,7 @@
162E836E1A9BDE8B00906325 /* SDLUnsubscribeButtonResponseSpec.m in Sources */,
5DEF69611FD6FB75004B8C2F /* SDLAudioStreamManagerSpec.m in Sources */,
162E835B1A9BDE8B00906325 /* SDLPerformInteractionResponseSpec.m in Sources */,
+ 880E35B82088F78E00181259 /* SDLSystemCapabilityManagerSpec.m in Sources */,
162E832D1A9BDE8B00906325 /* SDLEncodedSyncPDataSpec.m in Sources */,
1EE8C44C1F385C7100FDC2CF /* SDLRDSDataSpec.m in Sources */,
5DB92D241AC47B2C00C15BB0 /* SDLHexUtilitySpec.m in Sources */,
@@ -6103,6 +6443,7 @@
162E83971A9BDE8B00906325 /* SDLVehicleTypeSpec.m in Sources */,
1680B1131A9CD7AD00DBD79E /* SDLProtocolHeaderSpec.m in Sources */,
162E82D01A9BDE8A00906325 /* SDLButtonEventModeSpec.m in Sources */,
+ 5DF40B26208FA7DE00DD6FDA /* SDLMenuManagerSpec.m in Sources */,
162E83781A9BDE8B00906325 /* SDLDeviceInfoSpec.m in Sources */,
162E83391A9BDE8B00906325 /* SDLSetAppIconSpec.m in Sources */,
162E83011A9BDE8B00906325 /* SDLTimerModeSpec.m in Sources */,
@@ -6141,6 +6482,7 @@
162E82CF1A9BDE8A00906325 /* SDLBitsPerSampleSpec.m in Sources */,
162E831E1A9BDE8B00906325 /* SDLOnTBTClientStateSpec.m in Sources */,
162E83351A9BDE8B00906325 /* SDLReadDIDSpec.m in Sources */,
+ 5DF40B28208FDA9700DD6FDA /* SDLVoiceCommandManagerSpec.m in Sources */,
162E836F1A9BDE8B00906325 /* SDLUnsubscribeVehicleDataResponseSpec.m in Sources */,
162E82DB1A9BDE8B00906325 /* SDLECallConfirmationStatusSpec.m in Sources */,
162E82D81A9BDE8A00906325 /* SDLDimensionSpec.m in Sources */,
@@ -6164,14 +6506,39 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 88295680207CF68800EF056C /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 88A0AA5C207CFE740075132C /* ConnectionContainerViewController.swift in Sources */,
+ 88B849C52080F4B3002A034D /* RPCPermissionsManager.swift in Sources */,
+ 8870C3EA208662540070E018 /* AudioManager.swift in Sources */,
+ 88DFB055207F96EE0079D19D /* AlertManager.swift in Sources */,
+ 888D178F207E7F42008E9F8F /* ButtonManager.swift in Sources */,
+ 88A0AA5E207CFE740075132C /* ConnectionTCPTableViewController.swift in Sources */,
+ 88DFB053207F8E100079D19D /* Protocol+ProxyManagerDelegate.swift in Sources */,
+ 88B849C820812442002A034D /* VehicleDataManager.swift in Sources */,
+ 8829569E207CFD0E00EF056C /* AppDelegate.swift in Sources */,
+ 88A0AA58207CFE650075132C /* ProxyManager.swift in Sources */,
+ 88166B00207E41E900076236 /* MenuManager.swift in Sources */,
+ 8814AEAC20AB667B00466E0F /* PerformInteractionManager.swift in Sources */,
+ 888D1790207E815C008E9F8F /* AppConstants.m in Sources */,
+ 88A0AA5D207CFE740075132C /* ConnectionIAPTableViewController.swift in Sources */,
+ 88A0AA56207CFE5D0075132C /* AppUserDefaults.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 88802CD820853AE600E9EBC6 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 88802FF120853BB700E9EBC6 /* SDLLog.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
- 5D43468C1E788E2200B639C6 /* PBXTargetDependency */ = {
- isa = PBXTargetDependency;
- target = 5D61FA1B1A84237100846EE7 /* SmartDeviceLink */;
- targetProxy = 5D43468B1E788E2200B639C6 /* PBXContainerItemProxy */;
- };
5D61FA291A84237100846EE7 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 5D61FA1B1A84237100846EE7 /* SmartDeviceLink */;
@@ -6179,7 +6546,7 @@
};
5D61FA2B1A84237100846EE7 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
- target = 5D4019AE1A76EC350006B0C2 /* SmartDeviceLink-Example */;
+ target = 5D4019AE1A76EC350006B0C2 /* SmartDeviceLink-Example-ObjC */;
targetProxy = 5D61FA2A1A84237100846EE7 /* PBXContainerItemProxy */;
};
5D61FA321A84237100846EE7 /* PBXTargetDependency */ = {
@@ -6187,6 +6554,21 @@
target = 5D61FA1B1A84237100846EE7 /* SmartDeviceLink */;
targetProxy = 5D61FA311A84237100846EE7 /* PBXContainerItemProxy */;
};
+ 8829567E207CF68800EF056C /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 5D61FA1B1A84237100846EE7 /* SmartDeviceLink */;
+ targetProxy = 8829567F207CF68800EF056C /* PBXContainerItemProxy */;
+ };
+ 88802FF320853BBF00E9EBC6 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 5D61FA1B1A84237100846EE7 /* SmartDeviceLink */;
+ targetProxy = 88802FF220853BBF00E9EBC6 /* PBXContainerItemProxy */;
+ };
+ 88802FF820853CD500E9EBC6 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 88802CD720853AE600E9EBC6 /* SmartDeviceLinkSwift */;
+ targetProxy = 88802FF720853CD500E9EBC6 /* PBXContainerItemProxy */;
+ };
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
@@ -6350,7 +6732,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "iPhone Developer";
DEVELOPMENT_TEAM = NCVC2MHU7M;
- INFOPLIST_FILE = "$(SRCROOT)/SmartDeviceLink_Example/Info.plist";
+ INFOPLIST_FILE = "$(SRCROOT)/SmartDeviceLink_Example/SmartDeviceLink-Example-ObjC-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.smartdevicelink.SDLTestApp;
@@ -6364,7 +6746,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "iPhone Developer";
DEVELOPMENT_TEAM = NCVC2MHU7M;
- INFOPLIST_FILE = "$(SRCROOT)/SmartDeviceLink_Example/Info.plist";
+ INFOPLIST_FILE = "$(SRCROOT)/SmartDeviceLink_Example/SmartDeviceLink-Example-ObjC-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.smartdevicelink.SDLTestApp;
@@ -6372,65 +6754,6 @@
};
name = Release;
};
- 5D4346671E6F38E600B639C6 /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- CLANG_ANALYZER_NONNULL = YES;
- CLANG_ENABLE_MODULES = YES;
- CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
- CODE_SIGN_IDENTITY = "";
- CURRENT_PROJECT_VERSION = 1;
- DEBUG_INFORMATION_FORMAT = dwarf;
- DEFINES_MODULE = YES;
- DYLIB_COMPATIBILITY_VERSION = 1;
- DYLIB_CURRENT_VERSION = 1;
- DYLIB_INSTALL_NAME_BASE = "@rpath";
- INFOPLIST_FILE = SmartDeviceLinkSwift/Info.plist;
- INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
- IPHONEOS_DEPLOYMENT_TARGET = 8.0;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
- PRODUCT_BUNDLE_IDENTIFIER = com.smartdevicelink.SmartDeviceLinkSwift;
- PRODUCT_NAME = "$(TARGET_NAME)";
- SKIP_INSTALL = YES;
- SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
- SWIFT_OPTIMIZATION_LEVEL = "-Onone";
- SWIFT_SWIFT3_OBJC_INFERENCE = On;
- SWIFT_VERSION = 4.0;
- TARGETED_DEVICE_FAMILY = "1,2";
- VERSIONING_SYSTEM = "apple-generic";
- VERSION_INFO_PREFIX = "";
- };
- name = Debug;
- };
- 5D4346681E6F38E600B639C6 /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- CLANG_ANALYZER_NONNULL = YES;
- CLANG_ENABLE_MODULES = YES;
- CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
- CODE_SIGN_IDENTITY = "";
- COPY_PHASE_STRIP = NO;
- CURRENT_PROJECT_VERSION = 1;
- DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
- DEFINES_MODULE = YES;
- DYLIB_COMPATIBILITY_VERSION = 1;
- DYLIB_CURRENT_VERSION = 1;
- DYLIB_INSTALL_NAME_BASE = "@rpath";
- INFOPLIST_FILE = SmartDeviceLinkSwift/Info.plist;
- INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
- IPHONEOS_DEPLOYMENT_TARGET = 8.0;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
- PRODUCT_BUNDLE_IDENTIFIER = com.smartdevicelink.SmartDeviceLinkSwift;
- PRODUCT_NAME = "$(TARGET_NAME)";
- SKIP_INSTALL = YES;
- SWIFT_SWIFT3_OBJC_INFERENCE = On;
- SWIFT_VERSION = 4.0;
- TARGETED_DEVICE_FAMILY = "1,2";
- VERSIONING_SYSTEM = "apple-generic";
- VERSION_INFO_PREFIX = "";
- };
- name = Release;
- };
5D61FA361A84237100846EE7 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@@ -6528,7 +6851,7 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
- DEVELOPMENT_TEAM = "";
+ DEVELOPMENT_TEAM = NCVC2MHU7M;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(DEVELOPER_FRAMEWORKS_DIR)",
@@ -6564,7 +6887,7 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
- DEVELOPMENT_TEAM = "";
+ DEVELOPMENT_TEAM = NCVC2MHU7M;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(DEVELOPER_FRAMEWORKS_DIR)",
@@ -6590,6 +6913,142 @@
};
name = Release;
};
+ 88295695207CF68800EF056C /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ DEVELOPMENT_TEAM = NCVC2MHU7M;
+ INFOPLIST_FILE = "SmartDeviceLink-Example-Swift-Info.plist";
+ IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = com.smartdevicelink.SDLTestApp;
+ PRODUCT_NAME = "SDL Example";
+ SWIFT_OBJC_BRIDGING_HEADER = "SmartDeviceLink_Example/SmartDeviceLink-Example-Swift-Bridging-Header.h";
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 3.0;
+ };
+ name = Debug;
+ };
+ 88295696207CF68800EF056C /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ DEVELOPMENT_TEAM = NCVC2MHU7M;
+ INFOPLIST_FILE = "SmartDeviceLink-Example-Swift-Info.plist";
+ IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = com.smartdevicelink.SDLTestApp;
+ PRODUCT_NAME = "SDL Example";
+ SWIFT_OBJC_BRIDGING_HEADER = "SmartDeviceLink_Example/SmartDeviceLink-Example-Swift-Bridging-Header.h";
+ SWIFT_VERSION = 3.0;
+ };
+ name = Release;
+ };
+ 88802FED20853AE600E9EBC6 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES;
+ CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES;
+ CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES;
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_STATIC_ANALYZER_MODE = deep;
+ CLANG_UNDEFINED_BEHAVIOR_SANITIZER_INTEGER = YES;
+ CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_FLOAT_CONVERSION = YES;
+ CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ CURRENT_PROJECT_VERSION = 1;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ DEFINES_MODULE = YES;
+ DEVELOPMENT_TEAM = NCVC2MHU7M;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ DYLIB_INSTALL_NAME_BASE = "@rpath";
+ FRAMEWORK_SEARCH_PATHS = "$(inherited)";
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
+ GCC_WARN_SIGN_COMPARE = NO;
+ GCC_WARN_UNKNOWN_PRAGMAS = YES;
+ INFOPLIST_FILE = SmartDeviceLinkSwift/Info.plist;
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+ IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ LIBRARY_SEARCH_PATHS = "$(inherited)";
+ PRODUCT_BUNDLE_IDENTIFIER = com.smartdevicelink.SmartDeviceLinkSwift;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ RUN_CLANG_STATIC_ANALYZER = YES;
+ SKIP_INSTALL = YES;
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_SWIFT3_OBJC_INFERENCE = On;
+ SWIFT_VERSION = 4.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VERSIONING_SYSTEM = "apple-generic";
+ VERSION_INFO_PREFIX = "";
+ };
+ name = Debug;
+ };
+ 88802FEE20853AE600E9EBC6 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES;
+ CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES;
+ CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES;
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_STATIC_ANALYZER_MODE = deep;
+ CLANG_UNDEFINED_BEHAVIOR_SANITIZER_INTEGER = YES;
+ CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_FLOAT_CONVERSION = YES;
+ CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ CURRENT_PROJECT_VERSION = 1;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ DEFINES_MODULE = YES;
+ DEVELOPMENT_TEAM = NCVC2MHU7M;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ DYLIB_INSTALL_NAME_BASE = "@rpath";
+ FRAMEWORK_SEARCH_PATHS = "$(inherited)";
+ GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
+ GCC_WARN_SIGN_COMPARE = NO;
+ GCC_WARN_UNKNOWN_PRAGMAS = YES;
+ INFOPLIST_FILE = SmartDeviceLinkSwift/Info.plist;
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+ IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ LIBRARY_SEARCH_PATHS = "$(inherited)";
+ PRODUCT_BUNDLE_IDENTIFIER = com.smartdevicelink.SmartDeviceLinkSwift;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ RUN_CLANG_STATIC_ANALYZER = YES;
+ SKIP_INSTALL = YES;
+ SWIFT_SWIFT3_OBJC_INFERENCE = On;
+ SWIFT_VERSION = 4.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VERSIONING_SYSTEM = "apple-generic";
+ VERSION_INFO_PREFIX = "";
+ };
+ name = Release;
+ };
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
@@ -6602,7 +7061,7 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
- 5D4019D21A76EC350006B0C2 /* Build configuration list for PBXNativeTarget "SmartDeviceLink-Example" */ = {
+ 5D4019D21A76EC350006B0C2 /* Build configuration list for PBXNativeTarget "SmartDeviceLink-Example-ObjC" */ = {
isa = XCConfigurationList;
buildConfigurations = (
5D4019D31A76EC350006B0C2 /* Debug */,
@@ -6611,15 +7070,6 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
- 5D4346661E6F38E600B639C6 /* Build configuration list for PBXNativeTarget "SmartDeviceLinkSwift" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- 5D4346671E6F38E600B639C6 /* Debug */,
- 5D4346681E6F38E600B639C6 /* Release */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
5D61FA351A84237100846EE7 /* Build configuration list for PBXNativeTarget "SmartDeviceLink" */ = {
isa = XCConfigurationList;
buildConfigurations = (
@@ -6638,6 +7088,24 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
+ 88295694207CF68800EF056C /* Build configuration list for PBXNativeTarget "SmartDeviceLink-Example-Swift" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 88295695207CF68800EF056C /* Debug */,
+ 88295696207CF68800EF056C /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 88802FEC20853AE600E9EBC6 /* Build configuration list for PBXNativeTarget "SmartDeviceLinkSwift" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 88802FED20853AE600E9EBC6 /* Debug */,
+ 88802FEE20853AE600E9EBC6 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
/* End XCConfigurationList section */
};
rootObject = 5D4019A71A76EC350006B0C2 /* Project object */;
diff --git a/SmartDeviceLink.podspec b/SmartDeviceLink.podspec
index a94f95b85..09d6d5b03 100644
--- a/SmartDeviceLink.podspec
+++ b/SmartDeviceLink.podspec
@@ -19,8 +19,6 @@ ss.source_files = 'SmartDeviceLink/*.{h,m}'
ss.public_header_files = [
'SmartDeviceLink/NSNumber+NumberType.h',
-'SmartDeviceLink/SDLAbstractProtocol.h',
-'SmartDeviceLink/SDLAbstractTransport.h',
'SmartDeviceLink/SDLAddCommand.h',
'SmartDeviceLink/SDLAddCommandResponse.h',
'SmartDeviceLink/SDLAddSubMenu.h',
@@ -121,8 +119,6 @@ ss.public_header_files = [
'SmartDeviceLink/SDLHMILevel.h',
'SmartDeviceLink/SDLHMIPermissions.h',
'SmartDeviceLink/SDLHMIZoneCapabilities.h',
-'SmartDeviceLink/SDLIAPSessionDelegate.h',
-'SmartDeviceLink/SDLIAPTransport.h',
'SmartDeviceLink/SDLIgnitionStableStatus.h',
'SmartDeviceLink/SDLIgnitionStatus.h',
'SmartDeviceLink/SDLImage.h',
@@ -161,6 +157,8 @@ ss.public_header_files = [
'SmartDeviceLink/SDLManager.h',
'SmartDeviceLink/SDLManagerDelegate.h',
'SmartDeviceLink/SDLMediaClockFormat.h',
+'SmartDeviceLink/SDLMenuCell.h',
+'SmartDeviceLink/SDLMenuManager.h',
'SmartDeviceLink/SDLMenuParams.h',
'SmartDeviceLink/SDLMetadataTags.h',
'SmartDeviceLink/SDLMetadataType.h',
@@ -208,13 +206,6 @@ ss.public_header_files = [
'SmartDeviceLink/SDLPresetBankCapabilities.h',
'SmartDeviceLink/SDLPrimaryAudioSource.h',
'SmartDeviceLink/SDLPRNDL.h',
-'SmartDeviceLink/SDLProtocol.h',
-'SmartDeviceLink/SDLProtocolHeader.h',
-'SmartDeviceLink/SDLProtocolListener.h',
-'SmartDeviceLink/SDLProtocolMessage.h',
-'SmartDeviceLink/SDLProxy.h',
-'SmartDeviceLink/SDLProxyFactory.h',
-'SmartDeviceLink/SDLProxyListener.h',
'SmartDeviceLink/SDLPutFile.h',
'SmartDeviceLink/SDLPutFileResponse.h',
'SmartDeviceLink/SDLRadioBand.h',
@@ -292,12 +283,12 @@ ss.public_header_files = [
'SmartDeviceLink/SDLSyncPDataResponse.h',
'SmartDeviceLink/SDLSystemAction.h',
'SmartDeviceLink/SDLSystemCapability.h',
+'SmartDeviceLink/SDLSystemCapabilityManager.h',
'SmartDeviceLink/SDLSystemCapabilityType.h',
'SmartDeviceLink/SDLSystemContext.h',
'SmartDeviceLink/SDLTBTState.h',
'SmartDeviceLink/SDLTemperature.h',
'SmartDeviceLink/SDLTemperatureUnit.h',
-'SmartDeviceLink/SDLTCPTransport.h',
'SmartDeviceLink/SDLTextAlignment.h',
'SmartDeviceLink/SDLTextField.h',
'SmartDeviceLink/SDLTextFieldName.h',
@@ -310,7 +301,6 @@ ss.public_header_files = [
'SmartDeviceLink/SDLTouchManager.h',
'SmartDeviceLink/SDLTouchManagerDelegate.h',
'SmartDeviceLink/SDLTouchType.h',
-'SmartDeviceLink/SDLTransportDelegate.h',
'SmartDeviceLink/SDLTriggerSource.h',
'SmartDeviceLink/SDLTTSChunk.h',
'SmartDeviceLink/SDLTurn.h',
@@ -338,6 +328,7 @@ ss.public_header_files = [
'SmartDeviceLink/SDLVideoStreamingCodec.h',
'SmartDeviceLink/SDLVideoStreamingFormat.h',
'SmartDeviceLink/SDLVideoStreamingProtocol.h',
+'SmartDeviceLink/SDLVoiceCommand.h',
'SmartDeviceLink/SDLVrCapabilities.h',
'SmartDeviceLink/SDLVrHelpItem.h',
'SmartDeviceLink/SDLWarningLightStatus.h',
diff --git a/SmartDeviceLink/SDLAbstractProtocol.h b/SmartDeviceLink/SDLAbstractProtocol.h
deleted file mode 100644
index e629e302a..000000000
--- a/SmartDeviceLink/SDLAbstractProtocol.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// SDLAbstractProtocol.h
-//
-
-@class SDLAbstractTransport;
-@class SDLRPCMessage;
-@class SDLRPCRequest;
-
-#import "SDLProtocolListener.h"
-#import "SDLSecurityType.h"
-#import "SDLTransportDelegate.h"
-
-NS_ASSUME_NONNULL_BEGIN
-
-@interface SDLAbstractProtocol : NSObject <SDLTransportDelegate>
-
-@property (strong, nonatomic) NSString *debugConsoleGroupName;
-@property (nullable, weak, nonatomic) SDLAbstractTransport *transport;
-@property (nullable, strong, nonatomic) NSHashTable<id<SDLProtocolListener>> *protocolDelegateTable;
-@property (nullable, nonatomic, strong) id<SDLSecurityType> securityManager;
-@property (nonatomic, copy) NSString *appId;
-
-// Sending
-- (void)startServiceWithType:(SDLServiceType)serviceType payload:(nullable NSData *)payload;
-- (void)startSecureServiceWithType:(SDLServiceType)serviceType payload:(nullable NSData *)payload completionHandler:(void (^)(BOOL success, NSError *error))completionHandler;
-- (void)endServiceWithType:(SDLServiceType)serviceType;
-
-- (void)sendRPC:(SDLRPCMessage *)message;
-- (BOOL)sendRPC:(SDLRPCMessage *)message encrypted:(BOOL)encryption error:(NSError **)error;
-
-- (void)sendRawData:(NSData *)data withServiceType:(SDLServiceType)serviceType;
-- (void)sendEncryptedRawData:(NSData *)data onService:(SDLServiceType)serviceType;
-
-// Recieving
-- (void)handleBytesFromTransport:(NSData *)receivedData;
-
-@end
-
-NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLAbstractProtocol.m b/SmartDeviceLink/SDLAbstractProtocol.m
deleted file mode 100644
index 70b482d5e..000000000
--- a/SmartDeviceLink/SDLAbstractProtocol.m
+++ /dev/null
@@ -1,77 +0,0 @@
-// SDLAbstractProtocol.m
-
-#import "SDLAbstractProtocol.h"
-
-#import "SDLRPCMessage.h"
-
-NS_ASSUME_NONNULL_BEGIN
-
-@implementation SDLAbstractProtocol
-
-- (instancetype)init {
- if (self = [super init]) {
- _protocolDelegateTable = [NSHashTable weakObjectsHashTable];
- _debugConsoleGroupName = @"default";
- }
- return self;
-}
-
-// Implement in subclasses.
-- (void)startServiceWithType:(SDLServiceType)serviceType payload:(nullable NSData *)payload {
- [self doesNotRecognizeSelector:_cmd];
-}
-
-- (void)startSecureServiceWithType:(SDLServiceType)serviceType payload:(nullable NSData *)payload completionHandler:(void (^)(BOOL, NSError *))completionHandler {
- [self doesNotRecognizeSelector:_cmd];
-}
-
-- (void)endServiceWithType:(SDLServiceType)serviceType {
- [self doesNotRecognizeSelector:_cmd];
-}
-
-- (void)sendRPC:(SDLRPCMessage *)message {
- [self doesNotRecognizeSelector:_cmd];
-}
-
-- (BOOL)sendRPC:(SDLRPCMessage *)message encrypted:(BOOL)encryption error:(NSError *__autoreleasing *)error {
- [self doesNotRecognizeSelector:_cmd];
- return NO;
-}
-
-- (void)handleBytesFromTransport:(NSData *)receivedData {
- [self doesNotRecognizeSelector:_cmd];
-}
-
-- (void)sendRawData:(NSData *)data withServiceType:(SDLServiceType)serviceType {
- [self doesNotRecognizeSelector:_cmd];
-}
-
-- (void)sendEncryptedRawData:(NSData *)data onService:(SDLServiceType)serviceType {
- [self doesNotRecognizeSelector:_cmd];
-}
-
-
-#pragma mark - SDLTransportListener Implementation
-- (void)onTransportConnected {
- for (id<SDLProtocolListener> listener in self.protocolDelegateTable.allObjects) {
- if ([listener respondsToSelector:@selector(onProtocolOpened)]) {
- [listener onProtocolOpened];
- }
- }
-}
-
-- (void)onTransportDisconnected {
- for (id<SDLProtocolListener> listener in self.protocolDelegateTable.allObjects) {
- if ([listener respondsToSelector:@selector(onProtocolClosed)]) {
- [listener onProtocolClosed];
- }
- }
-}
-
-- (void)onDataReceived:(NSData *)receivedData {
- [self handleBytesFromTransport:receivedData];
-}
-
-@end
-
-NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLAbstractTransport.m b/SmartDeviceLink/SDLAbstractTransport.m
deleted file mode 100644
index 4f2657bd2..000000000
--- a/SmartDeviceLink/SDLAbstractTransport.m
+++ /dev/null
@@ -1,34 +0,0 @@
-// SDLAbstractTransport.m
-
-#import "SDLAbstractTransport.h"
-
-NS_ASSUME_NONNULL_BEGIN
-
-@implementation SDLAbstractTransport
-
-- (instancetype)init {
- if (self = [super init]) {
- }
- return self;
-}
-
-- (void)connect {
- [self doesNotRecognizeSelector:_cmd];
-}
-
-- (void)disconnect {
- [self doesNotRecognizeSelector:_cmd];
-}
-
-- (void)sendData:(NSData *)dataToSend {
- [self doesNotRecognizeSelector:_cmd];
-}
-
-- (double)retryDelay {
- [self doesNotRecognizeSelector:_cmd];
- return 0.0;
-}
-
-@end
-
-NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLArtwork.m b/SmartDeviceLink/SDLArtwork.m
index 062374858..bf2861b67 100644
--- a/SmartDeviceLink/SDLArtwork.m
+++ b/SmartDeviceLink/SDLArtwork.m
@@ -111,6 +111,30 @@ NS_ASSUME_NONNULL_BEGIN
return formattedHash;
}
+#pragma mark - NSObject overrides
+
+- (NSUInteger)hash {
+ return self.name.hash ^ self.data.hash;
+}
+
+- (BOOL)isEqual:(id)object {
+ if (self == object) { return YES; }
+
+ if (![object isKindOfClass:[SDLArtwork class]]) { return NO; }
+
+ return [self isEqualToArtwork:(SDLArtwork *)object];
+}
+
+- (BOOL)isEqualToArtwork:(SDLArtwork *)artwork {
+ if (!artwork) { return NO; }
+
+ BOOL haveEqualNames = [self.name isEqualToString:artwork.name];
+ BOOL haveEqualData = [self.data isEqualToData:artwork.data];
+ BOOL haveEqualFormats = [self.fileType isEqualToEnum:artwork.fileType];
+
+ return haveEqualNames && haveEqualData && haveEqualFormats;
+}
+
@end
NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLAsynchronousRPCRequestOperation.h b/SmartDeviceLink/SDLAsynchronousRPCRequestOperation.h
index b08c700a2..a24165dad 100644
--- a/SmartDeviceLink/SDLAsynchronousRPCRequestOperation.h
+++ b/SmartDeviceLink/SDLAsynchronousRPCRequestOperation.h
@@ -17,6 +17,8 @@ NS_ASSUME_NONNULL_BEGIN
@interface SDLAsynchronousRPCRequestOperation : SDLAsynchronousOperation
+@property (copy, nonatomic) NSArray<SDLRPCRequest *> *requests;
+
- (instancetype)initWithConnectionManager:(id<SDLConnectionManagerType>)connectionManager requests:(NSArray<SDLRPCRequest *> *)requests progressHandler:(nullable SDLMultipleAsyncRequestProgressHandler)progressHandler completionHandler:(nullable SDLMultipleRequestCompletionHandler)completionHandler;
- (instancetype)initWithConnectionManager:(id<SDLConnectionManagerType>)connectionManager request:(SDLRPCRequest *)request responseHandler:(nullable SDLResponseHandler)responseHandler;
diff --git a/SmartDeviceLink/SDLAsynchronousRPCRequestOperation.m b/SmartDeviceLink/SDLAsynchronousRPCRequestOperation.m
index a79b30b09..c92a23c74 100644
--- a/SmartDeviceLink/SDLAsynchronousRPCRequestOperation.m
+++ b/SmartDeviceLink/SDLAsynchronousRPCRequestOperation.m
@@ -16,7 +16,6 @@ NS_ASSUME_NONNULL_BEGIN
@interface SDLAsynchronousRPCRequestOperation ()
-@property (copy, nonatomic) NSArray<SDLRPCRequest *> *requests;
@property (weak, nonatomic) id<SDLConnectionManagerType> connectionManager;
@property (copy, nonatomic, nullable) SDLMultipleAsyncRequestProgressHandler progressHandler;
@property (copy, nonatomic, nullable) SDLMultipleRequestCompletionHandler completionHandler;
@@ -160,6 +159,14 @@ NS_ASSUME_NONNULL_BEGIN
return NSOperationQueuePriorityNormal;
}
+- (NSString *)description {
+ return [NSString stringWithFormat:@"%@, request count=%lu, requests started=%lu, finished=%lu, failed=%@", self.name, self.requests.count, self.requestsStarted, self.requestsComplete, (self.requestFailed ? @"YES": @"NO")];
+}
+
+- (NSString *)debugDescription {
+ return [NSString stringWithFormat:@"%@, request count=%lu, requests started=%lu, finished=%lu, failed=%@, requests=%@", self.name, self.requests.count, self.requestsStarted, self.requestsComplete, (self.requestFailed ? @"YES": @"NO"), self.requests];
+}
+
@end
NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLConnectionManagerType.h b/SmartDeviceLink/SDLConnectionManagerType.h
index d1b316343..f7052f67d 100644
--- a/SmartDeviceLink/SDLConnectionManagerType.h
+++ b/SmartDeviceLink/SDLConnectionManagerType.h
@@ -33,6 +33,10 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (void)sendConnectionRequest:(__kindof SDLRPCRequest *)request withResponseHandler:(nullable SDLResponseHandler)handler;
+- (void)sendRequests:(NSArray<SDLRPCRequest *> *)requests progressHandler:(nullable SDLMultipleAsyncRequestProgressHandler)progressHandler completionHandler:(nullable SDLMultipleRequestCompletionHandler)completionHandler;
+
+- (void)sendSequentialRequests:(NSArray<SDLRPCRequest *> *)requests progressHandler:(nullable SDLMultipleSequentialRequestProgressHandler)progressHandler completionHandler:(nullable SDLMultipleRequestCompletionHandler)completionHandler;
+
@end
NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLDisplayCapabilities+ShowManagerExtensions.m b/SmartDeviceLink/SDLDisplayCapabilities+ShowManagerExtensions.m
index 351c62532..188b10729 100644
--- a/SmartDeviceLink/SDLDisplayCapabilities+ShowManagerExtensions.m
+++ b/SmartDeviceLink/SDLDisplayCapabilities+ShowManagerExtensions.m
@@ -40,6 +40,10 @@
}
- (BOOL)hasImageFieldOfName:(SDLImageFieldName)name {
+ if (!self.graphicSupported.boolValue) {
+ return NO;
+ }
+
for (SDLImageField *imageField in self.imageFields) {
if ([imageField.name isEqualToString:name]) {
return YES;
diff --git a/SmartDeviceLink/SDLError.h b/SmartDeviceLink/SDLError.h
index 3ae76736a..4a6ccf21b 100644
--- a/SmartDeviceLink/SDLError.h
+++ b/SmartDeviceLink/SDLError.h
@@ -19,6 +19,9 @@ NS_ASSUME_NONNULL_BEGIN
typedef NSString SDLErrorDomain;
extern SDLErrorDomain *const SDLErrorDomainLifecycleManager;
extern SDLErrorDomain *const SDLErrorDomainFileManager;
+extern SDLErrorDomain *const SDLErrorDomainTextAndGraphicManager;
+extern SDLErrorDomain *const SDLErrorDomainSoftButtonManager;
+extern SDLErrorDomain *const SDLErrorDomainMenuManager;
@interface NSError (SDLErrors)
@@ -47,9 +50,14 @@ extern SDLErrorDomain *const SDLErrorDomainFileManager;
+ (NSError *)sdl_fileManager_dataMissingError;
#pragma mark Show Managers
+
+ (NSError *)sdl_softButtonManager_pendingUpdateSuperseded;
+ (NSError *)sdl_textAndGraphicManager_pendingUpdateSuperseded;
+#pragma mark Menu Manager
+
++ (NSError *)sdl_menuManager_failedToUpdateWithDictionary:(NSDictionary *)userInfo;
+
@end
@interface NSException (SDLExceptions)
diff --git a/SmartDeviceLink/SDLError.m b/SmartDeviceLink/SDLError.m
index c5bda35f0..722eb3534 100644
--- a/SmartDeviceLink/SDLError.m
+++ b/SmartDeviceLink/SDLError.m
@@ -16,6 +16,7 @@ SDLErrorDomain *const SDLErrorDomainLifecycleManager = @"com.sdl.lifecyclemanage
SDLErrorDomain *const SDLErrorDomainFileManager = @"com.sdl.filemanager.error";
SDLErrorDomain *const SDLErrorDomainTextAndGraphicManager = @"com.sdl.textandgraphicmanager.error";
SDLErrorDomain *const SDLErrorDomainSoftButtonManager = @"com.sdl.softbuttonmanager.error";
+SDLErrorDomain *const SDLErrorDomainMenuManager = @"com.sdl.menumanager.error";
@implementation NSError (SDLErrors)
@@ -185,7 +186,7 @@ SDLErrorDomain *const SDLErrorDomainSoftButtonManager = @"com.sdl.softbuttonmana
return [NSError errorWithDomain:SDLErrorDomainFileManager code:SDLFileManagerErrorFileDoesNotExist userInfo:userInfo];
}
-#pragma mark Show Managers
+#pragma mark Screen Managers
+ (NSError *)sdl_textAndGraphicManager_pendingUpdateSuperseded {
return [NSError errorWithDomain:SDLErrorDomainTextAndGraphicManager code:SDLTextAndGraphicManagerErrorPendingUpdateSuperseded userInfo:nil];
@@ -195,6 +196,12 @@ SDLErrorDomain *const SDLErrorDomainSoftButtonManager = @"com.sdl.softbuttonmana
return [NSError errorWithDomain:SDLErrorDomainSoftButtonManager code:SDLSoftButtonManagerErrorPendingUpdateSuperseded userInfo:nil];
}
+#pragma mark Menu Manager
+
++ (NSError *)sdl_menuManager_failedToUpdateWithDictionary:(NSDictionary *)userInfo {
+ return [NSError errorWithDomain:SDLErrorDomainMenuManager code:SDLMenuManagerErrorRPCsFailed userInfo:userInfo];
+}
+
@end
diff --git a/SmartDeviceLink/SDLErrorConstants.h b/SmartDeviceLink/SDLErrorConstants.h
index 5eefd10f4..7cd7eba44 100644
--- a/SmartDeviceLink/SDLErrorConstants.h
+++ b/SmartDeviceLink/SDLErrorConstants.h
@@ -95,3 +95,7 @@ typedef NS_ENUM(NSInteger, SDLTextAndGraphicManagerError) {
typedef NS_ENUM(NSInteger, SDLSoftButtonManagerError) {
SDLSoftButtonManagerErrorPendingUpdateSuperseded = -1
};
+
+typedef NS_ENUM(NSInteger, SDLMenuManagerError) {
+ SDLMenuManagerErrorRPCsFailed = -1
+};
diff --git a/SmartDeviceLink/SDLFile.m b/SmartDeviceLink/SDLFile.m
index 9fc4d5423..522171f24 100644
--- a/SmartDeviceLink/SDLFile.m
+++ b/SmartDeviceLink/SDLFile.m
@@ -161,6 +161,30 @@ NS_ASSUME_NONNULL_BEGIN
return [[self.class allocWithZone:zone] initWithFileURL:_fileURL name:_name persistent:_persistent];
}
+#pragma mark - NSObject overrides
+
+- (NSUInteger)hash {
+ return self.name.hash ^ self.data.hash;
+}
+
+- (BOOL)isEqual:(id)object {
+ if (self == object) { return YES; }
+
+ if (![object isKindOfClass:[SDLFile class]]) { return NO; }
+
+ return [self isEqualToFile:(SDLFile *)object];
+}
+
+- (BOOL)isEqualToFile:(SDLFile *)file {
+ if (!file) { return NO; }
+
+ BOOL haveEqualNames = [self.name isEqualToString:file.name];
+ BOOL haveEqualData = [self.data isEqualToData:file.data];
+ BOOL haveEqualFormats = [self.fileType isEqualToEnum:file.fileType];
+
+ return haveEqualNames && haveEqualData && haveEqualFormats;
+}
+
@end
NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLFocusableItemLocator.m b/SmartDeviceLink/SDLFocusableItemLocator.m
index dbd3e0fef..1969512e5 100644
--- a/SmartDeviceLink/SDLFocusableItemLocator.m
+++ b/SmartDeviceLink/SDLFocusableItemLocator.m
@@ -33,10 +33,6 @@ NS_ASSUME_NONNULL_BEGIN
@implementation SDLFocusableItemLocator
-- (instancetype)initWithWindow:(UIWindow *)window connectionManager:(id<SDLConnectionManagerType>)connectionManager{
- return [self initWithViewController:window.rootViewController connectionManager:connectionManager];
-}
-
- (instancetype)initWithViewController:(UIViewController *)viewController connectionManager:(id<SDLConnectionManagerType>)connectionManager {
self = [super init];
if(!self) {
diff --git a/SmartDeviceLink/SDLFocusableItemLocatorType.h b/SmartDeviceLink/SDLFocusableItemLocatorType.h
index c75d61140..64c2337bc 100644
--- a/SmartDeviceLink/SDLFocusableItemLocatorType.h
+++ b/SmartDeviceLink/SDLFocusableItemLocatorType.h
@@ -27,14 +27,6 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, strong) UIViewController *viewController;
/**
- Initializes haptic interface. After initializing the application must call updateInterfaceLayout to process the UIWindow. Application must update later view changes in the window by sending SDLDidUpdateProjectionView notification.
-
- @param window UIWindow to be stored in haptic interface
- @param connectionManager Object of a class that implements ConnectionManagerType. This is used for RPC communication.
- */
-- (instancetype)initWithWindow:(UIWindow *)window connectionManager:(id<SDLConnectionManagerType>)connectionManager __deprecated_msg("Use initWithViewController:connectionManager: instead");
-
-/**
Initializes the haptic interface. After initializing the application must call updateInterfaceLayout to process the view controller. Application must update later view changes in the view controller (or a change in the view controller itself) by sending the SDLDidUpdateProjectionView notification.
@param viewController UIViewController to be checked for focusable views
diff --git a/SmartDeviceLink/SDLIAPTransport.h b/SmartDeviceLink/SDLIAPTransport.h
index 94fd01bda..06359edb0 100644
--- a/SmartDeviceLink/SDLIAPTransport.h
+++ b/SmartDeviceLink/SDLIAPTransport.h
@@ -3,16 +3,18 @@
#import <ExternalAccessory/ExternalAccessory.h>
-#import "SDLAbstractTransport.h"
+#import "SDLTransportType.h"
#import "SDLIAPSessionDelegate.h"
NS_ASSUME_NONNULL_BEGIN
-@interface SDLIAPTransport : SDLAbstractTransport <SDLIAPSessionDelegate>
+@interface SDLIAPTransport : NSObject <SDLTransportType, SDLIAPSessionDelegate>
@property (nullable, strong, nonatomic) SDLIAPSession *controlSession;
@property (nullable, strong, nonatomic) SDLIAPSession *session;
+@property (nullable, weak, nonatomic) id<SDLTransportDelegate> delegate;
+
@end
NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLLifecycleManager.h b/SmartDeviceLink/SDLLifecycleManager.h
index c41c2d971..594dccba3 100644
--- a/SmartDeviceLink/SDLLifecycleManager.h
+++ b/SmartDeviceLink/SDLLifecycleManager.h
@@ -32,6 +32,7 @@
@class SDLScreenManager;
@class SDLStateMachine;
@class SDLStreamingMediaManager;
+@class SDLSystemCapabilityManager;
@protocol SDLManagerDelegate;
@@ -67,6 +68,7 @@ typedef void (^SDLManagerReadyBlock)(BOOL success, NSError *_Nullable error);
@property (strong, nonatomic, nullable) SDLStreamingMediaManager *streamManager;
@property (strong, nonatomic) SDLLockScreenManager *lockScreenManager;
@property (strong, nonatomic, readonly) SDLScreenManager *screenManager;
+@property (strong, nonatomic) SDLSystemCapabilityManager *systemCapabilityManager;
@property (strong, nonatomic, readonly) SDLNotificationDispatcher *notificationDispatcher;
@property (strong, nonatomic, readonly) SDLResponseDispatcher *responseDispatcher;
diff --git a/SmartDeviceLink/SDLLifecycleManager.m b/SmartDeviceLink/SDLLifecycleManager.m
index e321854a1..58cc78e1e 100644
--- a/SmartDeviceLink/SDLLifecycleManager.m
+++ b/SmartDeviceLink/SDLLifecycleManager.m
@@ -11,7 +11,6 @@
#import "SDLLifecycleManager.h"
#import "NSMapTable+Subscripting.h"
-#import "SDLAbstractProtocol.h"
#import "SDLAsynchronousRPCRequestOperation.h"
#import "SDLChangeRegistration.h"
#import "SDLConfiguration.h"
@@ -35,8 +34,8 @@
#import "SDLOnHMIStatus.h"
#import "SDLOnHashChange.h"
#import "SDLPermissionManager.h"
+#import "SDLProtocol.h"
#import "SDLProxy.h"
-#import "SDLProxyFactory.h"
#import "SDLRPCNotificationNotification.h"
#import "SDLRegisterAppInterface.h"
#import "SDLRegisterAppInterfaceResponse.h"
@@ -48,6 +47,7 @@
#import "SDLStateMachine.h"
#import "SDLStreamingMediaConfiguration.h"
#import "SDLStreamingMediaManager.h"
+#import "SDLSystemCapabilityManager.h"
#import "SDLUnregisterAppInterface.h"
@@ -122,6 +122,7 @@ SDLLifecycleState *const SDLLifecycleStateReady = @"Ready";
_permissionManager = [[SDLPermissionManager alloc] init];
_lockScreenManager = [[SDLLockScreenManager alloc] initWithConfiguration:_configuration.lockScreenConfig notificationDispatcher:_notificationDispatcher presenter:[[SDLLockScreenPresenter alloc] init]];
_screenManager = [[SDLScreenManager alloc] initWithConnectionManager:self fileManager:_fileManager];
+ _systemCapabilityManager = [[SDLSystemCapabilityManager alloc] initWithConnectionManager:self];
if ([configuration.lifecycleConfig.appType isEqualToEnum:SDLAppHMITypeNavigation] ||
[configuration.lifecycleConfig.appType isEqualToEnum:SDLAppHMITypeProjection] ||
@@ -201,9 +202,11 @@ SDLLifecycleState *const SDLLifecycleStateReady = @"Ready";
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
if (self.configuration.lifecycleConfig.tcpDebugMode) {
- self.proxy = [SDLProxyFactory buildSDLProxyWithListener:self.notificationDispatcher tcpIPAddress:self.configuration.lifecycleConfig.tcpDebugIPAddress tcpPort:[@(self.configuration.lifecycleConfig.tcpDebugPort) stringValue]];
+ self.proxy = [SDLProxy tcpProxyWithListener:self.notificationDispatcher
+ tcpIPAddress:self.configuration.lifecycleConfig.tcpDebugIPAddress
+ tcpPort:@(self.configuration.lifecycleConfig.tcpDebugPort).stringValue];
} else {
- self.proxy = [SDLProxyFactory buildSDLProxyWithListener:self.notificationDispatcher];
+ self.proxy = [SDLProxy iapProxyWithListener:self.notificationDispatcher];
}
#pragma clang diagnostic pop
@@ -226,7 +229,9 @@ SDLLifecycleState *const SDLLifecycleStateReady = @"Ready";
[self.fileManager stop];
[self.permissionManager stop];
[self.lockScreenManager stop];
+ [self.screenManager stop];
[self.streamManager stop];
+ [self.systemCapabilityManager stop];
[self.responseDispatcher clear];
[self.rpcOperationQueue cancelAllOperations];
@@ -485,11 +490,21 @@ SDLLifecycleState *const SDLLifecycleStateReady = @"Ready";
}
- (void)sendRequests:(NSArray<SDLRPCRequest *> *)requests progressHandler:(nullable SDLMultipleAsyncRequestProgressHandler)progressHandler completionHandler:(nullable SDLMultipleRequestCompletionHandler)completionHandler {
+ if (requests.count == 0) {
+ completionHandler(YES);
+ return;
+ }
+
SDLAsynchronousRPCRequestOperation *op = [[SDLAsynchronousRPCRequestOperation alloc] initWithConnectionManager:self requests:requests progressHandler:progressHandler completionHandler:completionHandler];
[self.rpcOperationQueue addOperation:op];
}
- (void)sendSequentialRequests:(NSArray<SDLRPCRequest *> *)requests progressHandler:(nullable SDLMultipleSequentialRequestProgressHandler)progressHandler completionHandler:(nullable SDLMultipleRequestCompletionHandler)completionHandler {
+ if (requests.count == 0) {
+ completionHandler(YES);
+ return;
+ }
+
SDLSequentialRPCRequestOperation *op = [[SDLSequentialRPCRequestOperation alloc] initWithConnectionManager:self requests:requests progressHandler:progressHandler completionHandler:completionHandler];
[self.rpcOperationQueue addOperation:op];
}
diff --git a/SmartDeviceLink/SDLLockScreenManager.m b/SmartDeviceLink/SDLLockScreenManager.m
index de9d56f0f..c15c5318c 100644
--- a/SmartDeviceLink/SDLLockScreenManager.m
+++ b/SmartDeviceLink/SDLLockScreenManager.m
@@ -82,7 +82,9 @@ NS_ASSUME_NONNULL_BEGIN
self.canPresent = NO;
// Remove the lock screen if presented, don't allow it to present again until we start
- [self.presenter dismiss];
+ if (self.presenter.lockViewController != nil) {
+ [self.presenter dismiss];
+ }
}
- (nullable UIViewController *)lockScreenViewController {
diff --git a/SmartDeviceLink/SDLLockScreenPresenter.m b/SmartDeviceLink/SDLLockScreenPresenter.m
index 60fc82a9c..3162f8cc9 100644
--- a/SmartDeviceLink/SDLLockScreenPresenter.m
+++ b/SmartDeviceLink/SDLLockScreenPresenter.m
@@ -96,6 +96,9 @@ NS_ASSUME_NONNULL_BEGIN
} else if (appWindow.isKeyWindow) {
SDLLogW(@"Attempted to dismiss lock screen, but it is already dismissed");
return;
+ } else if (self.lockViewController == nil) {
+ SDLLogW(@"Attempted to dismiss lock screen, but lockViewController is not set");
+ return;
}
// Let us know we are about to dismiss.
diff --git a/SmartDeviceLink/SDLLogFileModuleMap.m b/SmartDeviceLink/SDLLogFileModuleMap.m
index cdbeccc71..812c75313 100644
--- a/SmartDeviceLink/SDLLogFileModuleMap.m
+++ b/SmartDeviceLink/SDLLogFileModuleMap.m
@@ -21,7 +21,8 @@
[self sdl_fileManagerModule],
[self sdl_lifecycleManagerModule],
[self sdl_lockscreenManagerModule],
- [self sdl_streamingMediaManagerModule]]];
+ [self sdl_streamingMediaManagerModule],
+ [self sdl_screenManagerModule]]];
}
+ (SDLLogFileModule *)sdl_transportModule {
@@ -56,7 +57,7 @@
}
+ (SDLLogFileModule *)sdl_lockscreenManagerModule {
- return [SDLLogFileModule moduleWithName:@"Lockscreen" files:[NSSet setWithArray:@[@"SDLLockScreenManager", @"SDLLockScreenViewController"]]];
+ return [SDLLogFileModule moduleWithName:@"Lockscreen" files:[NSSet setWithArray:@[@"SDLLockScreenManager", @"SDLLockScreenViewController", @"SDLLockScreenPresenter"]]];
}
+ (SDLLogFileModule *)sdl_streamingMediaManagerModule {
@@ -64,7 +65,7 @@
}
+ (SDLLogFileModule *)sdl_screenManagerModule {
- return [SDLLogFileModule moduleWithName:@"Screen" files:[NSSet setWithArray:@[@"SDLTextAndGraphicManager", @"SDLSoftButtonManager", @"SDLScreenManager", @"SDLSoftButtonObject", @"SDLSoftButtonState"]]];
+ return [SDLLogFileModule moduleWithName:@"Screen" files:[NSSet setWithArray:@[@"SDLTextAndGraphicManager", @"SDLSoftButtonManager", @"SDLScreenManager", @"SDLSoftButtonObject", @"SDLSoftButtonState", @"SDLMenuManager", @"SDLVoiceCommandManager"]]];
}
diff --git a/SmartDeviceLink/SDLManager.h b/SmartDeviceLink/SDLManager.h
index 32a91ce2d..b984a58a5 100644
--- a/SmartDeviceLink/SDLManager.h
+++ b/SmartDeviceLink/SDLManager.h
@@ -20,40 +20,13 @@
@class SDLRPCResponse;
@class SDLScreenManager;
@class SDLStreamingMediaManager;
+@class SDLSystemCapabilityManager;
@protocol SDLManagerDelegate;
NS_ASSUME_NONNULL_BEGIN
-/**
- A completion handler called after a sequential or simultaneous set of requests have completed sending.
-
- @param success True if every request succeeded, false if any failed. See the progress handler for more details on failures.
- */
-typedef void (^SDLMultipleRequestCompletionHandler)(BOOL success);
-
-/**
- A handler called after each response to a request comes in in a multiple request send.
-
- @param request The request that received a response
- @param response The response received
- @param error The error that occurred during the request if any occurred.
- @param percentComplete The percentage of requests that have received a response
- @return continueSendingRequests NO to cancel any requests that have not yet been sent. This is really only useful for a sequential send (sendSequentialRequests:progressHandler:completionHandler:). Return YES to continue sending requests.
- */
-typedef BOOL (^SDLMultipleSequentialRequestProgressHandler)(__kindof SDLRPCRequest *request, __kindof SDLRPCResponse *__nullable response, NSError *__nullable error, float percentComplete);
-
-/**
- A handler called after each response to a request comes in in a multiple request send.
-
- @param request The request that received a response
- @param response The response received
- @param error The error that occurred during the request if any occurred.
- @param percentComplete The percentage of requests that have received a response
- */
-typedef void (^SDLMultipleAsyncRequestProgressHandler)(__kindof SDLRPCRequest *request, __kindof SDLRPCResponse *__nullable response, NSError *__nullable error, float percentComplete);
-
typedef void (^SDLManagerReadyBlock)(BOOL success, NSError *_Nullable error);
@@ -95,9 +68,17 @@ typedef void (^SDLManagerReadyBlock)(BOOL success, NSError *_Nullable error);
*/
@property (strong, nonatomic, readonly, nullable) SDLStreamingMediaManager *streamManager;
+/**
+ * The screen manager for sending UI related RPCs.
+ */
@property (strong, nonatomic, readonly) SDLScreenManager *screenManager;
/**
+ * Centralized manager for retrieving all system capabilities.
+ */
+@property (strong, nonatomic, readonly) SDLSystemCapabilityManager *systemCapabilityManager;
+
+/**
* The response of a register call after it has been received.
*/
@property (strong, nonatomic, readonly, nullable) SDLRegisterAppInterfaceResponse *registerResponse;
diff --git a/SmartDeviceLink/SDLManager.m b/SmartDeviceLink/SDLManager.m
index 575711abb..e30ae87ea 100644
--- a/SmartDeviceLink/SDLManager.m
+++ b/SmartDeviceLink/SDLManager.m
@@ -88,6 +88,10 @@ NS_ASSUME_NONNULL_BEGIN
return self.lifecycleManager.screenManager;
}
+- (SDLSystemCapabilityManager *)systemCapabilityManager {
+ return self.lifecycleManager.systemCapabilityManager;
+}
+
- (nullable SDLRegisterAppInterfaceResponse *)registerResponse {
return self.lifecycleManager.registerResponse;
}
diff --git a/SmartDeviceLink/SDLMenuCell.h b/SmartDeviceLink/SDLMenuCell.h
new file mode 100644
index 000000000..80edc70b1
--- /dev/null
+++ b/SmartDeviceLink/SDLMenuCell.h
@@ -0,0 +1,51 @@
+//
+// SDLMenuCell.h
+// SmartDeviceLink
+//
+// Created by Joel Fischer on 4/9/18.
+// Copyright © 2018 smartdevicelink. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+#import "SDLTriggerSource.h"
+
+@class SDLArtwork;
+
+NS_ASSUME_NONNULL_BEGIN
+
+typedef void(^SDLMenuCellSelectionHandler)(SDLTriggerSource triggerSource);
+
+@interface SDLMenuCell : NSObject
+
+/**
+ The cell's text to be displayed
+ */
+@property (copy, nonatomic, readonly) NSString *title;
+
+/**
+ The cell's icon to be displayed
+ */
+@property (strong, nonatomic, readonly, nullable) SDLArtwork *icon;
+
+/**
+ The strings the user can say to activate this voice command
+ */
+@property (copy, nonatomic, readonly, nullable) NSArray<NSString *> *voiceCommands;
+
+/**
+ The handler that will be called when the command is activated
+ */
+@property (copy, nonatomic, readonly, nullable) SDLMenuCellSelectionHandler handler;
+
+/**
+ If this is non-nil, this cell will be a sub-menu button, displaying the subcells in a menu when pressed.
+ */
+@property (copy, nonatomic, readonly, nullable) NSArray<SDLMenuCell *> *subCells;
+
+- (instancetype)initWithTitle:(NSString *)title icon:(nullable SDLArtwork *)icon voiceCommands:(nullable NSArray<NSString *> *)voiceCommands handler:(SDLMenuCellSelectionHandler)handler;
+- (instancetype)initWithTitle:(NSString *)title subCells:(NSArray<SDLMenuCell *> *)subCells;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLMenuCell.m b/SmartDeviceLink/SDLMenuCell.m
new file mode 100644
index 000000000..b5a259544
--- /dev/null
+++ b/SmartDeviceLink/SDLMenuCell.m
@@ -0,0 +1,58 @@
+//
+// SDLMenuCell.m
+// SmartDeviceLink
+//
+// Created by Joel Fischer on 4/9/18.
+// Copyright © 2018 smartdevicelink. All rights reserved.
+//
+
+#import "SDLMenuCell.h"
+
+#import "SDLArtwork.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface SDLMenuCell()
+
+@property (assign, nonatomic) UInt32 parentCellId;
+@property (assign, nonatomic) UInt32 cellId;
+
+@end
+
+@implementation SDLMenuCell
+
+- (instancetype)initWithTitle:(NSString *)title icon:(nullable SDLArtwork *)icon voiceCommands:(nullable NSArray<NSString *> *)voiceCommands handler:(SDLMenuCellSelectionHandler)handler {
+ self = [super init];
+ if (!self) { return nil; }
+
+ _title = title;
+ _icon = icon;
+ _voiceCommands = voiceCommands;
+ _handler = handler;
+
+ _cellId = UINT32_MAX;
+ _parentCellId = UINT32_MAX;
+
+ return self;
+}
+
+- (instancetype)initWithTitle:(NSString *)title subCells:(NSArray<SDLMenuCell *> *)subCells {
+ self = [super init];
+ if (!self) { return nil; }
+
+ _title = title;
+ _subCells = subCells;
+
+ _cellId = UINT32_MAX;
+ _parentCellId = UINT32_MAX;
+
+ return self;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"SDLMenuCell: %u-\"%@\", artworkName: %@, voice commands: %lu, isSubcell: %@, hasSubcells: %@", (unsigned int)_cellId, _title, _icon.name, _voiceCommands.count, (_parentCellId != UINT32_MAX ? @"YES" : @"NO"), (_subCells.count > 0 ? @"YES" : @"NO")];
+}
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLMenuManager.h b/SmartDeviceLink/SDLMenuManager.h
new file mode 100644
index 000000000..cd3ead610
--- /dev/null
+++ b/SmartDeviceLink/SDLMenuManager.h
@@ -0,0 +1,39 @@
+//
+// SDLMenuManager.h
+// SmartDeviceLink
+//
+// Created by Joel Fischer on 4/9/18.
+// Copyright © 2018 smartdevicelink. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@class SDLFileManager;
+@class SDLMenuCell;
+@class SDLVoiceCommand;
+
+@protocol SDLConnectionManagerType;
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ The handler run when the update has completed
+
+ @param error An error if the update failed and an error occurred
+ */
+typedef void(^SDLMenuUpdateCompletionHandler)(NSError *__nullable error);
+
+@interface SDLMenuManager : NSObject
+
+- (instancetype)initWithConnectionManager:(id<SDLConnectionManagerType>)connectionManager fileManager:(SDLFileManager *)fileManager;
+
+/**
+ * Stops the manager. This method is used internally.
+ */
+- (void)stop;
+
+@property (copy, nonatomic) NSArray<SDLMenuCell *> *menuCells;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLMenuManager.m b/SmartDeviceLink/SDLMenuManager.m
new file mode 100644
index 000000000..4ad83d939
--- /dev/null
+++ b/SmartDeviceLink/SDLMenuManager.m
@@ -0,0 +1,443 @@
+//
+// SDLMenuManager.m
+// SmartDeviceLink
+//
+// Created by Joel Fischer on 4/9/18.
+// Copyright © 2018 smartdevicelink. All rights reserved.
+//
+
+#import "SDLMenuManager.h"
+
+#import "SDLAddCommand.h"
+#import "SDLAddSubMenu.h"
+#import "SDLArtwork.h"
+#import "SDLConnectionManagerType.h"
+#import "SDLDeleteCommand.h"
+#import "SDLDeleteSubMenu.h"
+#import "SDLDisplayCapabilities.h"
+#import "SDLDisplayCapabilities+ShowManagerExtensions.h"
+#import "SDLError.h"
+#import "SDLFileManager.h"
+#import "SDLImage.h"
+#import "SDLLogMacros.h"
+#import "SDLMenuCell.h"
+#import "SDLMenuParams.h"
+#import "SDLOnCommand.h"
+#import "SDLOnHMIStatus.h"
+#import "SDLRegisterAppInterfaceResponse.h"
+#import "SDLRPCNotificationNotification.h"
+#import "SDLRPCResponseNotification.h"
+#import "SDLSetDisplayLayoutResponse.h"
+#import "SDLVoiceCommand.h"
+
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface SDLMenuCell()
+
+@property (assign, nonatomic) UInt32 parentCellId;
+@property (assign, nonatomic) UInt32 cellId;
+
+@end
+
+@interface SDLMenuManager()
+
+@property (weak, nonatomic) id<SDLConnectionManagerType> connectionManager;
+@property (weak, nonatomic) SDLFileManager *fileManager;
+
+@property (copy, nonatomic, nullable) SDLHMILevel currentHMILevel;
+@property (copy, nonatomic, nullable) SDLSystemContext currentSystemContext;
+@property (strong, nonatomic, nullable) SDLDisplayCapabilities *displayCapabilities;
+
+@property (strong, nonatomic, nullable) NSArray<SDLRPCRequest *> *inProgressUpdate;
+@property (assign, nonatomic) BOOL hasQueuedUpdate;
+@property (assign, nonatomic) BOOL waitingOnHMIUpdate;
+@property (copy, nonatomic) NSArray<SDLMenuCell *> *waitingUpdateMenuCells;
+
+@property (assign, nonatomic) UInt32 lastMenuId;
+@property (copy, nonatomic) NSArray<SDLMenuCell *> *oldMenuCells;
+
+@end
+
+UInt32 const ParentIdNotFound = UINT32_MAX;
+UInt32 const MenuCellIdMin = 1;
+
+@implementation SDLMenuManager
+
+- (instancetype)init {
+ self = [super init];
+ if (!self) { return nil; }
+
+ _lastMenuId = MenuCellIdMin;
+ _menuCells = @[];
+ _oldMenuCells = @[];
+
+ [[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_hmiStatusNotification:) name:SDLDidChangeHMIStatusNotification object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_commandNotification:) name:SDLDidReceiveCommandNotification object:nil];
+
+ return self;
+}
+
+- (instancetype)initWithConnectionManager:(id<SDLConnectionManagerType>)connectionManager fileManager:(SDLFileManager *)fileManager {
+ self = [self init];
+ if (!self) { return nil; }
+
+ _connectionManager = connectionManager;
+ _fileManager = fileManager;
+
+ return self;
+}
+
+- (void)stop {
+ _lastMenuId = MenuCellIdMin;
+ _menuCells = @[];
+ _oldMenuCells = @[];
+
+ _currentHMILevel = nil;
+ _currentSystemContext = SDLSystemContextMain;
+ _displayCapabilities = nil;
+ _inProgressUpdate = nil;
+ _hasQueuedUpdate = NO;
+ _waitingOnHMIUpdate = NO;
+ _waitingUpdateMenuCells = @[];
+}
+
+#pragma mark - Setters
+
+- (void)setMenuCells:(NSArray<SDLMenuCell *> *)menuCells {
+ if (self.currentHMILevel == nil
+ || [self.currentHMILevel isEqualToEnum:SDLHMILevelNone]
+ || [self.currentSystemContext isEqualToEnum:SDLSystemContextMenu]) {
+ self.waitingOnHMIUpdate = YES;
+ self.waitingUpdateMenuCells = menuCells;
+ return;
+ }
+
+ self.waitingOnHMIUpdate = NO;
+
+ // Check for duplicate titles
+ NSMutableSet *titleCheckSet = [NSMutableSet set];
+ for (SDLMenuCell *cell in menuCells) {
+ [titleCheckSet addObject:cell.title];
+ }
+ if (titleCheckSet.count != menuCells.count) {
+ SDLLogE(@"Not all cell titles are unique. The menu will not be set.");
+ return;
+ }
+
+ // Set the ids
+ self.lastMenuId = MenuCellIdMin;
+ [self sdl_updateIdsOnMenuCells:menuCells parentId:ParentIdNotFound];
+
+ _oldMenuCells = _menuCells;
+ _menuCells = menuCells;
+
+ // Upload the artworks
+ NSArray<SDLArtwork *> *artworksToBeUploaded = [self sdl_findAllArtworksToBeUploadedFromCells:self.menuCells];
+ if (artworksToBeUploaded.count > 0) {
+ [self.fileManager uploadArtworks:artworksToBeUploaded completionHandler:^(NSArray<NSString *> * _Nonnull artworkNames, NSError * _Nullable error) {
+ if (error != nil) {
+ SDLLogE(@"Error uploading menu artworks: %@", error);
+ }
+
+ SDLLogD(@"Menu artworks uploaded");
+ [self sdl_updateWithCompletionHandler:nil];
+ }];
+ }
+
+ [self sdl_updateWithCompletionHandler:nil];
+}
+
+#pragma mark - Updating System
+
+- (void)sdl_updateWithCompletionHandler:(nullable SDLMenuUpdateCompletionHandler)completionHandler {
+ if (self.currentHMILevel == nil
+ || [self.currentHMILevel isEqualToEnum:SDLHMILevelNone]
+ || [self.currentSystemContext isEqualToEnum:SDLSystemContextMenu]) {
+ self.waitingOnHMIUpdate = YES;
+ self.waitingUpdateMenuCells = self.menuCells;
+ return;
+ }
+
+ if (self.inProgressUpdate != nil) {
+ // There's an in progress update, we need to put this on hold
+ self.hasQueuedUpdate = YES;
+ return;
+ }
+
+ __weak typeof(self) weakself = self;
+ [self sdl_sendDeleteCurrentMenu:^(NSError * _Nullable error) {
+ [weakself sdl_sendCurrentMenu:^(NSError * _Nullable error) {
+ weakself.inProgressUpdate = nil;
+
+ if (completionHandler != nil) {
+ completionHandler(error);
+ }
+
+ if (weakself.hasQueuedUpdate) {
+ [weakself sdl_updateWithCompletionHandler:nil];
+ weakself.hasQueuedUpdate = NO;
+ }
+ }];
+ }];
+}
+
+#pragma mark Delete Old Menu Items
+
+- (void)sdl_sendDeleteCurrentMenu:(SDLMenuUpdateCompletionHandler)completionHandler {
+ if (self.oldMenuCells.count == 0) {
+ completionHandler(nil);
+ return;
+ }
+
+ NSArray<SDLRPCRequest *> *deleteMenuCommands = [self sdl_deleteCommandsForCells:self.oldMenuCells];
+ self.oldMenuCells = @[];
+ [self.connectionManager sendRequests:deleteMenuCommands progressHandler:nil completionHandler:^(BOOL success) {
+ if (!success) {
+ SDLLogW(@"Unable to delete all old menu commands");
+ } else {
+ SDLLogD(@"Finished deleting old menu");
+ }
+
+ completionHandler(nil);
+ }];
+}
+
+#pragma mark Send New Menu Items
+
+- (void)sdl_sendCurrentMenu:(SDLMenuUpdateCompletionHandler)completionHandler {
+ if (self.menuCells.count == 0) {
+ SDLLogD(@"No main menu to send");
+ completionHandler(nil);
+
+ return;
+ }
+
+ NSArray<SDLRPCRequest *> *mainMenuCommands = nil;
+ NSArray<SDLRPCRequest *> *subMenuCommands = nil;
+ if ([self sdl_findAllArtworksToBeUploadedFromCells:self.menuCells].count > 0 || ![self.displayCapabilities hasImageFieldOfName:SDLImageFieldNameCommandIcon]) {
+ // Send artwork-less menu
+ mainMenuCommands = [self sdl_mainMenuCommandsForCells:self.menuCells withArtwork:NO];
+ subMenuCommands = [self sdl_subMenuCommandsForCells:self.menuCells withArtwork:NO];
+ } else {
+ // Send full artwork menu
+ mainMenuCommands = [self sdl_mainMenuCommandsForCells:self.menuCells withArtwork:YES];
+ subMenuCommands = [self sdl_subMenuCommandsForCells:self.menuCells withArtwork:YES];
+ }
+
+ self.inProgressUpdate = [mainMenuCommands arrayByAddingObjectsFromArray:subMenuCommands];
+
+ __block NSMutableDictionary<SDLRPCRequest *, NSError *> *errors = [NSMutableDictionary dictionary];
+ __weak typeof(self) weakSelf = self;
+ [self.connectionManager sendRequests:mainMenuCommands progressHandler:^(__kindof SDLRPCRequest * _Nonnull request, __kindof SDLRPCResponse * _Nullable response, NSError * _Nullable error, float percentComplete) {
+ if (error != nil) {
+ errors[request] = error;
+ }
+ } completionHandler:^(BOOL success) {
+ if (!success) {
+ SDLLogE(@"Failed to send main menu commands: %@", errors);
+ completionHandler([NSError sdl_menuManager_failedToUpdateWithDictionary:errors]);
+ return;
+ }
+
+ weakSelf.oldMenuCells = weakSelf.menuCells;
+ [weakSelf.connectionManager sendRequests:subMenuCommands progressHandler:^(__kindof SDLRPCRequest * _Nonnull request, __kindof SDLRPCResponse * _Nullable response, NSError * _Nullable error, float percentComplete) {
+ if (error != nil) {
+ errors[request] = error;
+ }
+ } completionHandler:^(BOOL success) {
+ if (!success) {
+ SDLLogE(@"Failed to send sub menu commands: %@", errors);
+ completionHandler([NSError sdl_menuManager_failedToUpdateWithDictionary:errors]);
+ return;
+ }
+
+ SDLLogD(@"Finished updating menu");
+ completionHandler(nil);
+ }];
+ }];
+}
+
+#pragma mark - Helpers
+
+#pragma mark Artworks
+
+- (NSArray<SDLArtwork *> *)sdl_findAllArtworksToBeUploadedFromCells:(NSArray<SDLMenuCell *> *)cells {
+ if (![self.displayCapabilities hasImageFieldOfName:SDLImageFieldNameCommandIcon]) {
+ return @[];
+ }
+
+ NSMutableSet<SDLArtwork *> *mutableArtworks = [NSMutableSet set];
+ for (SDLMenuCell *cell in cells) {
+ if (cell.icon != nil && ![self.fileManager hasUploadedFile:cell.icon]) {
+ [mutableArtworks addObject:cell.icon];
+ }
+
+ if (cell.subCells.count > 0) {
+ [mutableArtworks addObjectsFromArray:[self sdl_findAllArtworksToBeUploadedFromCells:cell.subCells]];
+ }
+ }
+
+ return [mutableArtworks allObjects];
+}
+
+#pragma mark IDs
+
+- (void)sdl_updateIdsOnMenuCells:(NSArray<SDLMenuCell *> *)menuCells parentId:(UInt32)parentId {
+ for (SDLMenuCell *cell in menuCells) {
+ cell.cellId = self.lastMenuId++;
+ cell.parentCellId = parentId;
+ if (cell.subCells.count > 0) {
+ [self sdl_updateIdsOnMenuCells:cell.subCells parentId:cell.cellId];
+ }
+ }
+}
+
+#pragma mark Deletes
+
+- (NSArray<SDLRPCRequest *> *)sdl_deleteCommandsForCells:(NSArray<SDLMenuCell *> *)cells {
+ NSMutableArray<SDLRPCRequest *> *mutableDeletes = [NSMutableArray array];
+ for (SDLMenuCell *cell in cells) {
+ if (cell.subCells == nil) {
+ SDLDeleteCommand *delete = [[SDLDeleteCommand alloc] initWithId:cell.cellId];
+ [mutableDeletes addObject:delete];
+ } else {
+ SDLDeleteSubMenu *delete = [[SDLDeleteSubMenu alloc] initWithId:cell.cellId];
+ [mutableDeletes addObject:delete];
+ }
+ }
+
+ return [mutableDeletes copy];
+}
+
+#pragma mark Commands / SubMenu RPCs
+
+- (NSArray<SDLRPCRequest *> *)sdl_mainMenuCommandsForCells:(NSArray<SDLMenuCell *> *)cells withArtwork:(BOOL)shouldHaveArtwork {
+ NSMutableArray<SDLRPCRequest *> *mutableCommands = [NSMutableArray array];
+ [cells enumerateObjectsUsingBlock:^(SDLMenuCell * _Nonnull cell, NSUInteger index, BOOL * _Nonnull stop) {
+ if (cell.subCells.count > 0) {
+ [mutableCommands addObject:[self sdl_subMenuCommandForMenuCell:cell position:(UInt16)index]];
+ } else {
+ [mutableCommands addObject:[self sdl_commandForMenuCell:cell withArtwork:shouldHaveArtwork position:(UInt16)index]];
+ }
+ }];
+
+ return [mutableCommands copy];
+}
+
+- (NSArray<SDLRPCRequest *> *)sdl_subMenuCommandsForCells:(NSArray<SDLMenuCell *> *)cells withArtwork:(BOOL)shouldHaveArtwork {
+ NSMutableArray<SDLRPCRequest *> *mutableCommands = [NSMutableArray array];
+ for (SDLMenuCell *cell in cells) {
+ if (cell.subCells.count > 0) {
+ [mutableCommands addObjectsFromArray:[self sdl_allCommandsForCells:cell.subCells withArtwork:shouldHaveArtwork]];
+ }
+ }
+
+ return [mutableCommands copy];
+}
+
+- (NSArray<SDLRPCRequest *> *)sdl_allCommandsForCells:(NSArray<SDLMenuCell *> *)cells withArtwork:(BOOL)shouldHaveArtwork {
+ NSMutableArray<SDLRPCRequest *> *mutableCommands = [NSMutableArray array];
+ [cells enumerateObjectsUsingBlock:^(SDLMenuCell * _Nonnull cell, NSUInteger index, BOOL * _Nonnull stop) {
+ if (cell.subCells.count > 0) {
+ [mutableCommands addObject:[self sdl_subMenuCommandForMenuCell:cell position:(UInt16)index]];
+ [mutableCommands addObjectsFromArray:[self sdl_allCommandsForCells:cell.subCells withArtwork:shouldHaveArtwork]];
+ } else {
+ [mutableCommands addObject:[self sdl_commandForMenuCell:cell withArtwork:shouldHaveArtwork position:(UInt16)index]];
+ }
+ }];
+
+ return [mutableCommands copy];
+}
+
+- (SDLAddCommand *)sdl_commandForMenuCell:(SDLMenuCell *)cell withArtwork:(BOOL)shouldHaveArtwork position:(UInt16)position {
+ SDLAddCommand *command = [[SDLAddCommand alloc] init];
+
+ SDLMenuParams *params = [[SDLMenuParams alloc] init];
+ params.menuName = cell.title;
+ params.parentID = cell.parentCellId != UINT32_MAX ? @(cell.parentCellId) : nil;
+ params.position = @(position);
+
+ command.menuParams = params;
+ command.vrCommands = cell.voiceCommands;
+ command.cmdIcon = (cell.icon && shouldHaveArtwork) ? [[SDLImage alloc] initWithName:cell.icon.name] : nil;
+ command.cmdID = @(cell.cellId);
+
+ return command;
+}
+
+- (SDLAddSubMenu *)sdl_subMenuCommandForMenuCell:(SDLMenuCell *)cell position:(UInt16)position {
+ SDLAddSubMenu *submenu = [[SDLAddSubMenu alloc] initWithId:cell.cellId menuName:cell.title];
+ submenu.position = @(position);
+
+ return submenu;
+}
+
+#pragma mark - Calling handlers
+
+- (BOOL)sdl_callHandlerForCells:(NSArray<SDLMenuCell *> *)cells command:(SDLOnCommand *)onCommand {
+ for (SDLMenuCell *cell in cells) {
+ if (cell.cellId == onCommand.cmdID.unsignedIntegerValue && cell.handler != nil) {
+ cell.handler(onCommand.triggerSource);
+ return YES;
+ }
+
+ if (cell.subCells.count > 0) {
+ BOOL succeeded = [self sdl_callHandlerForCells:cell.subCells command:onCommand];
+ if (succeeded) { return YES; }
+ }
+ }
+
+ return NO;
+}
+
+#pragma mark - Observers
+
+- (void)sdl_commandNotification:(SDLRPCNotificationNotification *)notification {
+ SDLOnCommand *onCommand = (SDLOnCommand *)notification.notification;
+
+ [self sdl_callHandlerForCells:self.menuCells command:onCommand];
+}
+
+- (void)sdl_registerResponse:(SDLRPCResponseNotification *)notification {
+ SDLRegisterAppInterfaceResponse *response = (SDLRegisterAppInterfaceResponse *)notification.response;
+ self.displayCapabilities = response.displayCapabilities;
+}
+
+- (void)sdl_displayLayoutResponse:(SDLRPCResponseNotification *)notification {
+ SDLSetDisplayLayoutResponse *response = (SDLSetDisplayLayoutResponse *)notification.response;
+ self.displayCapabilities = response.displayCapabilities;
+}
+
+- (void)sdl_hmiStatusNotification:(SDLRPCNotificationNotification *)notification {
+ SDLOnHMIStatus *hmiStatus = (SDLOnHMIStatus *)notification.notification;
+ SDLHMILevel oldHMILevel = self.currentHMILevel;
+ self.currentHMILevel = hmiStatus.hmiLevel;
+
+ // Auto-send an updated menu if we were in NONE and now we are not, and we need an update
+ if ([oldHMILevel isEqualToString:SDLHMILevelNone] && ![self.currentHMILevel isEqualToString:SDLHMILevelNone] &&
+ ![self.currentSystemContext isEqualToEnum:SDLSystemContextMenu]) {
+ if (self.waitingOnHMIUpdate) {
+ [self setMenuCells:self.waitingUpdateMenuCells];
+ self.waitingUpdateMenuCells = @[];
+ return;
+ }
+ }
+
+ // If we don't check for this and only update when not in the menu, there can be IN_USE errors, especially with submenus. We also don't want to encourage changing out the menu while the user is using it for usability reasons.
+ SDLSystemContext oldSystemContext = self.currentSystemContext;
+ self.currentSystemContext = hmiStatus.systemContext;
+
+ if ([oldSystemContext isEqualToEnum:SDLSystemContextMenu] && ![self.currentSystemContext isEqualToEnum:SDLSystemContextMenu] && ![self.currentHMILevel isEqualToEnum:SDLHMILevelNone]) {
+ if (self.waitingOnHMIUpdate) {
+ [self setMenuCells:self.waitingUpdateMenuCells];
+ self.waitingUpdateMenuCells = @[];
+ }
+ }
+}
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLNotificationConstants.h b/SmartDeviceLink/SDLNotificationConstants.h
index be7c0b2aa..52b025303 100644
--- a/SmartDeviceLink/SDLNotificationConstants.h
+++ b/SmartDeviceLink/SDLNotificationConstants.h
@@ -47,6 +47,33 @@ typedef void (^SDLAudioPassThruHandler)(NSData *__nullable audioData);
*/
typedef void (^SDLResponseHandler)(__kindof SDLRPCRequest *__nullable request, __kindof SDLRPCResponse *__nullable response, NSError *__nullable error);
+/**
+ A completion handler called after a sequential or simultaneous set of requests have completed sending.
+
+ @param success True if every request succeeded, false if any failed. See the progress handler for more details on failures.
+ */
+typedef void (^SDLMultipleRequestCompletionHandler)(BOOL success);
+
+/**
+ A handler called after each response to a request comes in in a multiple request send.
+
+ @param request The request that received a response
+ @param response The response received
+ @param error The error that occurred during the request if any occurred.
+ @param percentComplete The percentage of requests that have received a response
+ @return continueSendingRequests NO to cancel any requests that have not yet been sent. This is really only useful for a sequential send (sendSequentialRequests:progressHandler:completionHandler:). Return YES to continue sending requests.
+ */
+typedef BOOL (^SDLMultipleSequentialRequestProgressHandler)(__kindof SDLRPCRequest *request, __kindof SDLRPCResponse *__nullable response, NSError *__nullable error, float percentComplete);
+
+/**
+ A handler called after each response to a request comes in in a multiple request send.
+
+ @param request The request that received a response
+ @param response The response received
+ @param error The error that occurred during the request if any occurred.
+ @param percentComplete The percentage of requests that have received a response
+ */
+typedef void (^SDLMultipleAsyncRequestProgressHandler)(__kindof SDLRPCRequest *request, __kindof SDLRPCResponse *__nullable response, NSError *__nullable error, float percentComplete);
/**
A handler that may optionally be run when an SDLSubscribeButton or SDLSoftButton has a corresponding notification occur.
diff --git a/SmartDeviceLink/SDLPermissionManager.m b/SmartDeviceLink/SDLPermissionManager.m
index f07d4b24f..08c37eebe 100644
--- a/SmartDeviceLink/SDLPermissionManager.m
+++ b/SmartDeviceLink/SDLPermissionManager.m
@@ -55,7 +55,9 @@ NS_ASSUME_NONNULL_BEGIN
}
- (void)stop {
- // Nothing to do here right now
+ _permissions = [NSMutableDictionary<SDLPermissionRPCName, SDLPermissionItem *> dictionary];
+ _filters = [NSMutableArray<SDLPermissionFilter *> array];
+ _currentHMILevel = nil;
}
diff --git a/SmartDeviceLink/SDLProtocol.h b/SmartDeviceLink/SDLProtocol.h
index a0a4d1ecd..8567c0cf5 100644
--- a/SmartDeviceLink/SDLProtocol.h
+++ b/SmartDeviceLink/SDLProtocol.h
@@ -1,9 +1,17 @@
// SDLSmartDeviceLinkProtocol.h
//
-#import "SDLAbstractProtocol.h"
+#import <Foundation/Foundation.h>
+
+#import "SDLTransportType.h"
+#import "SDLProtocolConstants.h"
+#import "SDLProtocolListener.h"
+#import "SDLSecurityType.h"
+#import "SDLTransportDelegate.h"
+
@class SDLProtocolHeader;
@class SDLProtocolRecievedMessageRouter;
+@class SDLRPCMessage;
NS_ASSUME_NONNULL_BEGIN
@@ -14,7 +22,13 @@ typedef NS_ENUM(NSUInteger, SDLProtocolError) {
extern NSString *const SDLProtocolSecurityErrorDomain;
-@interface SDLProtocol : SDLAbstractProtocol <SDLProtocolListener>
+@interface SDLProtocol : NSObject <SDLProtocolListener, SDLTransportDelegate>
+
+@property (strong, nonatomic) NSString *debugConsoleGroupName;
+@property (nullable, weak, nonatomic) id<SDLTransportType> transport;
+@property (nullable, strong, nonatomic) NSHashTable<id<SDLProtocolListener>> *protocolDelegateTable;
+@property (nullable, nonatomic, strong) id<SDLSecurityType> securityManager;
+@property (nonatomic, copy) NSString *appId;
// Sending
- (void)startServiceWithType:(SDLServiceType)serviceType payload:(nullable NSData *)payload;
diff --git a/SmartDeviceLink/SDLProtocol.m b/SmartDeviceLink/SDLProtocol.m
index 4093dbfa2..89bd5aeb8 100644
--- a/SmartDeviceLink/SDLProtocol.m
+++ b/SmartDeviceLink/SDLProtocol.m
@@ -4,7 +4,7 @@
#import "SDLFunctionID.h"
-#import "SDLAbstractTransport.h"
+#import "SDLTransportType.h"
#import "SDLControlFramePayloadConstants.h"
#import "SDLControlFramePayloadEndService.h"
#import "SDLControlFramePayloadNak.h"
@@ -63,6 +63,7 @@ NS_ASSUME_NONNULL_BEGIN
_receiveQueue = dispatch_queue_create("com.sdl.protocol.receive", DISPATCH_QUEUE_SERIAL);
_sendQueue = dispatch_queue_create("com.sdl.protocol.transmit", DISPATCH_QUEUE_SERIAL);
_prioritizedCollection = [[SDLPrioritizedObjectCollection alloc] init];
+ _protocolDelegateTable = [NSHashTable weakObjectsHashTable];
_serviceHeaders = [[NSMutableDictionary alloc] init];
_messageRouter = [[SDLProtocolReceivedMessageRouter alloc] init];
_messageRouter.delegate = self;
@@ -73,6 +74,7 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - Service metadata
+
- (UInt8)sdl_retrieveSessionIDforServiceType:(SDLServiceType)serviceType {
SDLProtocolHeader *header = self.serviceHeaders[@(serviceType)];
if (header == nil) {
@@ -82,6 +84,27 @@ NS_ASSUME_NONNULL_BEGIN
return header.sessionID;
}
+#pragma mark - SDLTransportDelegate
+
+- (void)onTransportConnected {
+ for (id<SDLProtocolListener> listener in self.protocolDelegateTable.allObjects) {
+ if ([listener respondsToSelector:@selector(onProtocolOpened)]) {
+ [listener onProtocolOpened];
+ }
+ }
+}
+
+- (void)onTransportDisconnected {
+ for (id<SDLProtocolListener> listener in self.protocolDelegateTable.allObjects) {
+ if ([listener respondsToSelector:@selector(onProtocolClosed)]) {
+ [listener onProtocolClosed];
+ }
+ }
+}
+
+- (void)onDataReceived:(NSData *)receivedData {
+ [self handleBytesFromTransport:receivedData];
+}
#pragma mark - Start Service
diff --git a/SmartDeviceLink/SDLProtocolConstants.h b/SmartDeviceLink/SDLProtocolConstants.h
new file mode 100644
index 000000000..642492b35
--- /dev/null
+++ b/SmartDeviceLink/SDLProtocolConstants.h
@@ -0,0 +1,42 @@
+//
+// SDLProtocolConstants.h
+// SmartDeviceLink
+//
+// Created by Joel Fischer on 5/1/18.
+// Copyright © 2018 smartdevicelink. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+typedef NS_ENUM(UInt8, SDLFrameType) {
+ SDLFrameTypeControl = 0x00,
+ SDLFrameTypeSingle = 0x01,
+ SDLFrameTypeFirst = 0x02,
+ SDLFrameTypeConsecutive = 0x03
+};
+
+typedef NS_ENUM(UInt8, SDLServiceType) {
+ SDLServiceTypeControl = 0x00,
+ SDLServiceTypeRPC NS_SWIFT_NAME(rpc) = 0x07,
+ SDLServiceTypeAudio = 0x0A,
+ SDLServiceTypeVideo = 0x0B,
+ SDLServiceTypeBulkData = 0x0F
+};
+
+typedef NS_ENUM(UInt8, SDLFrameInfo) {
+ SDLFrameInfoHeartbeat = 0x00,
+ SDLFrameInfoStartService = 0x01,
+ SDLFrameInfoStartServiceACK = 0x02,
+ SDLFrameInfoStartServiceNACK = 0x03,
+ SDLFrameInfoEndService = 0x04,
+ SDLFrameInfoEndServiceACK = 0x05,
+ SDLFrameInfoEndServiceNACK = 0x06,
+ SDLFrameInfoServiceDataAck = 0xFE,
+ SDLFrameInfoHeartbeatACK = 0xFF,
+ // If frameType == Single (0x01)
+ SDLFrameInfoSingleFrame = 0x00,
+ // If frameType == First (0x02)
+ SDLFrameInfoFirstFrame = 0x00,
+ // If frametype == Consecutive (0x03)
+ SDLFrameInfoConsecutiveLastFrame = 0x00
+};
diff --git a/SmartDeviceLink/SDLProtocolConstants.m b/SmartDeviceLink/SDLProtocolConstants.m
new file mode 100644
index 000000000..c60de84dc
--- /dev/null
+++ b/SmartDeviceLink/SDLProtocolConstants.m
@@ -0,0 +1,9 @@
+//
+// SDLProtocolConstants.m
+// SmartDeviceLink
+//
+// Created by Joel Fischer on 5/1/18.
+// Copyright © 2018 smartdevicelink. All rights reserved.
+//
+
+#import "SDLProtocolConstants.h"
diff --git a/SmartDeviceLink/SDLProtocolHeader.h b/SmartDeviceLink/SDLProtocolHeader.h
index 6d0d84a69..2cae62abb 100644
--- a/SmartDeviceLink/SDLProtocolHeader.h
+++ b/SmartDeviceLink/SDLProtocolHeader.h
@@ -3,72 +3,7 @@
#import <Foundation/Foundation.h>
-
-/**
- * The packet's header and payload combination.
-
- - SDLFrameTypeControl: Lowest-level type of packets. They can be sent over any of the defined services. They are used for the control of the services in which they are sent.
- - SDLFrameTypeSingle: Contains all the data for a particular packet in the payload. The majority of frames sent over the protocol utilize this frame type.
- - SDLFrameTypeFirst: The First Frame in a multiple frame payload contains information about the entire sequence of frames so that the receiving end can correctly parse all the frames and reassemble the entire payload. The payload of this frame is only eight bytes and contains information regarding the rest of the sequence.
- - SDLFrameTypeConsecutive: The Consecutive Frames in a multiple frame payload contain the actual raw data of the original payload. The parsed payload contained in each of the Consecutive Frames' payloads should be buffered until the entire sequence is complete.
- */
-typedef NS_ENUM(UInt8, SDLFrameType) {
- SDLFrameTypeControl = 0x00,
- SDLFrameTypeSingle = 0x01,
- SDLFrameTypeFirst = 0x02,
- SDLFrameTypeConsecutive = 0x03
-};
-
-/**
- * The packet's format and priority.
-
- - SDLServiceTypeControl: The lowest level service available.
- - SDLServiceTypeRPC: Used to send requests, responses, and notifications between an application and a head unit.
- - SDLServiceTypeAudio: The application can start the audio service to send PCM audio data to the head unit. After the StartService packet is sent and the ACK received, the payload for the Audio Service is only PCM audio data.
- - SDLServiceTypeVideo: The application can start the video service to send H.264 video data to the head unit. After the StartService packet is sent and the ACK received, the payload for the Video Service is only H.264 video data.
- - SDLServiceTypeBulkData: Similar to the RPC Service but adds a bulk data field. The payload of a message sent via the Hybrid service consists of a Binary Header, JSON Data, and Bulk Data.
- */
-typedef NS_ENUM(UInt8, SDLServiceType) {
- SDLServiceTypeControl = 0x00,
- SDLServiceTypeRPC NS_SWIFT_NAME(rpc) = 0x07,
- SDLServiceTypeAudio = 0x0A,
- SDLServiceTypeVideo = 0x0B,
- SDLServiceTypeBulkData = 0x0F
-};
-
-/**
- * The packet's available data.
-
- - SDLFrameInfoHeartbeat: A ping packet that is sent to ensure the connection is still active and the service is still valid.
- - SDLFrameInfoStartService: Requests that a specific type of service is started.
- - SDLFrameInfoStartServiceACK: Acknowledges that the specific service has been started successfully.
- - SDLFrameInfoStartServiceNACK: Negatively acknowledges that the specific service was not started.
- - SDLFrameInfoEndService: Requests that a specific type of service is ended.
- - SDLFrameInfoEndServiceACK: Acknowledges that the specific service has been ended successfully.
- - SDLFrameInfoEndServiceNACK: Negatively acknowledges that the specific service was not ended or has not yet been started.
- - SDLFrameInfoServiceDataAck: Deprecated.
- - SDLFrameInfoHeartbeatACK: Acknowledges that a Heartbeat control packet has been received.
- - SDLFrameInfoSingleFrame: Payload contains a single packet.
- - SDLFrameInfoFirstFrame: First frame in a multiple frame payload.
- - SDLFrameInfoConsecutiveLastFrame: Frame in a multiple frame payload.
- */
-typedef NS_ENUM(UInt8, SDLFrameInfo) {
- SDLFrameInfoHeartbeat = 0x00,
- SDLFrameInfoStartService = 0x01,
- SDLFrameInfoStartServiceACK = 0x02,
- SDLFrameInfoStartServiceNACK = 0x03,
- SDLFrameInfoEndService = 0x04,
- SDLFrameInfoEndServiceACK = 0x05,
- SDLFrameInfoEndServiceNACK = 0x06,
- SDLFrameInfoServiceDataAck = 0xFE,
- SDLFrameInfoHeartbeatACK = 0xFF,
- // If frameType == Single (0x01)
- SDLFrameInfoSingleFrame = 0x00,
- // If frameType == First (0x02)
- SDLFrameInfoFirstFrame = 0x00,
- // If frametype == Consecutive (0x03)
- SDLFrameInfoConsecutiveLastFrame = 0x00
-};
+#import "SDLProtocolConstants.h"
NS_ASSUME_NONNULL_BEGIN
diff --git a/SmartDeviceLink/SDLProxy.h b/SmartDeviceLink/SDLProxy.h
index 112a85a10..7c702c9e5 100644
--- a/SmartDeviceLink/SDLProxy.h
+++ b/SmartDeviceLink/SDLProxy.h
@@ -1,8 +1,6 @@
// SDLProxy.h
//
-@class SDLAbstractProtocol;
-@class SDLAbstractTransport;
@class SDLProtocol;
@class SDLPutFile;
@class SDLRPCMessage;
@@ -12,26 +10,26 @@
#import "SDLProtocolListener.h"
#import "SDLProxyListener.h"
#import "SDLSecurityType.h"
+#import "SDLTransportType.h"
NS_ASSUME_NONNULL_BEGIN
-__deprecated_msg("Use SDLManager instead")
- @interface SDLProxy : NSObject<SDLProtocolListener, NSStreamDelegate> {
+@interface SDLProxy : NSObject <SDLProtocolListener, NSStreamDelegate> {
Byte _version;
Byte _bulkSessionID;
BOOL _isConnected;
}
-@property (nullable, strong, nonatomic) SDLAbstractProtocol *protocol;
-@property (nullable, strong, nonatomic) SDLAbstractTransport *transport;
+@property (nullable, strong, nonatomic) SDLProtocol *protocol;
+@property (nullable, strong, nonatomic) id<SDLTransportType> transport;
@property (readonly, copy, nonatomic) NSSet<NSObject<SDLProxyListener> *> *proxyListeners;
@property (strong, nonatomic) SDLTimer *startSessionTimer;
-@property (copy, nonatomic) NSString *debugConsoleGroupName;
@property (readonly, copy, nonatomic) NSString *proxyVersion;
-- (id)initWithTransport:(SDLAbstractTransport *)transport
- protocol:(SDLAbstractProtocol *)protocol
- delegate:(NSObject<SDLProxyListener> *)delegate;
+- (id)initWithTransport:(id<SDLTransportType>)transport delegate:(id<SDLProxyListener>)delegate;
+
++ (SDLProxy *)iapProxyWithListener:(id<SDLProxyListener>)delegate;
++ (SDLProxy *)tcpProxyWithListener:(id<SDLProxyListener>)delegate tcpIPAddress:(NSString *)ipaddress tcpPort:(NSString *)port;
- (void)addDelegate:(NSObject<SDLProxyListener> *)delegate;
- (void)removeDelegate:(NSObject<SDLProxyListener> *)delegate;
diff --git a/SmartDeviceLink/SDLProxy.m b/SmartDeviceLink/SDLProxy.m
index cc2a5f7ff..2fe4b9253 100644
--- a/SmartDeviceLink/SDLProxy.m
+++ b/SmartDeviceLink/SDLProxy.m
@@ -6,7 +6,7 @@
#import <UIKit/UIKit.h>
#import <objc/runtime.h>
-#import "SDLAbstractTransport.h"
+#import "SDLTransportType.h"
#import "SDLAudioStreamingState.h"
#import "SDLLogMacros.h"
#import "SDLEncodedSyncPData.h"
@@ -14,10 +14,10 @@
#import "SDLFunctionID.h"
#import "SDLGlobals.h"
#import "SDLHMILevel.h"
+#import "SDLIAPTransport.h"
#import "SDLLanguage.h"
#import "SDLLayoutMode.h"
#import "SDLLockScreenStatusManager.h"
-
#import "SDLOnHMIStatus.h"
#import "SDLOnSystemRequest.h"
#import "SDLPolicyDataParser.h"
@@ -31,6 +31,7 @@
#import "SDLStreamingMediaManager.h"
#import "SDLSystemContext.h"
#import "SDLSystemRequest.h"
+#import "SDLTCPTransport.h"
#import "SDLTimer.h"
#import "SDLVehicleType.h"
@@ -64,18 +65,18 @@ static float DefaultConnectionTimeout = 45.0;
@implementation SDLProxy
#pragma mark - Object lifecycle
-- (instancetype)initWithTransport:(SDLAbstractTransport *)transport protocol:(SDLAbstractProtocol *)protocol delegate:(NSObject<SDLProxyListener> *)theDelegate {
+- (instancetype)initWithTransport:(id<SDLTransportType>)transport delegate:(id<SDLProxyListener>)delegate {
if (self = [super init]) {
SDLLogD(@"Framework Version: %@", self.proxyVersion);
- _debugConsoleGroupName = @"default";
_lsm = [[SDLLockScreenStatusManager alloc] init];
_rpcProcessingQueue = dispatch_queue_create("com.sdl.rpcProcessingQueue", DISPATCH_QUEUE_SERIAL);
-
- _mutableProxyListeners = [NSMutableSet setWithObject:theDelegate];
+ _mutableProxyListeners = [NSMutableSet setWithObject:delegate];
_securityManagers = [NSMutableDictionary dictionary];
- _protocol = protocol;
+
+ _protocol = [[SDLProtocol alloc] init];
_transport = transport;
- _transport.delegate = protocol;
+ _transport.delegate = _protocol;
+
[_protocol.protocolDelegateTable addObject:self];
_protocol.transport = transport;
@@ -96,6 +97,21 @@ static float DefaultConnectionTimeout = 45.0;
return self;
}
++ (SDLProxy *)iapProxyWithListener:(id<SDLProxyListener>)delegate {
+ SDLIAPTransport *transport = [[SDLIAPTransport alloc] init];
+ SDLProxy *ret = [[SDLProxy alloc] initWithTransport:transport delegate:delegate];
+
+ return ret;
+}
+
++ (SDLProxy *)tcpProxyWithListener:(id<SDLProxyListener>)delegate tcpIPAddress:(NSString *)ipaddress tcpPort:(NSString *)port {
+ SDLTCPTransport *transport = [[SDLTCPTransport alloc] initWithHostName:ipaddress portNumber:port];
+
+ SDLProxy *ret = [[SDLProxy alloc] initWithTransport:transport delegate:delegate];
+
+ return ret;
+}
+
- (void)dealloc {
if (self.protocol.securityManager != nil) {
[self.protocol.securityManager stop];
diff --git a/SmartDeviceLink/SDLProxyFactory.h b/SmartDeviceLink/SDLProxyFactory.h
deleted file mode 100644
index 5d2212e58..000000000
--- a/SmartDeviceLink/SDLProxyFactory.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// SDLProxyFactory.h
-//
-
-#import <Foundation/Foundation.h>
-
-#import "SDLProxyListener.h"
-
-@class SDLProxy;
-
-NS_ASSUME_NONNULL_BEGIN
-
-__deprecated_msg("Use SDLManager instead")
-@interface SDLProxyFactory : NSObject {
-}
-
-+ (SDLProxy *)buildSDLProxyWithListener:(NSObject<SDLProxyListener> *)listener;
-
-+ (SDLProxy *)buildSDLProxyWithListener:(NSObject<SDLProxyListener> *)listener
- tcpIPAddress:(NSString *)ipaddress
- tcpPort:(NSString *)port;
-@end
-
-NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLProxyFactory.m b/SmartDeviceLink/SDLProxyFactory.m
deleted file mode 100644
index 3a703e073..000000000
--- a/SmartDeviceLink/SDLProxyFactory.m
+++ /dev/null
@@ -1,39 +0,0 @@
-// SDLSyncProxyFactory.m
-//
-
-#import "SDLProxyFactory.h"
-
-#import "SDLIAPTransport.h"
-#import "SDLProtocol.h"
-#import "SDLProxy.h"
-#import "SDLTCPTransport.h"
-
-NS_ASSUME_NONNULL_BEGIN
-
-@implementation SDLProxyFactory
-
-+ (SDLProxy *)buildSDLProxyWithListener:(NSObject<SDLProxyListener> *)delegate {
- SDLIAPTransport *transport = [[SDLIAPTransport alloc] init];
- SDLProtocol *protocol = [[SDLProtocol alloc] init];
- SDLProxy *ret = [[SDLProxy alloc] initWithTransport:transport protocol:protocol delegate:delegate];
-
- return ret;
-}
-
-+ (SDLProxy *)buildSDLProxyWithListener:(NSObject<SDLProxyListener> *)delegate
- tcpIPAddress:(NSString *)ipaddress
- tcpPort:(NSString *)port {
- SDLTCPTransport *transport = [[SDLTCPTransport alloc] init];
- transport.hostName = ipaddress;
- transport.portNumber = port;
-
- SDLProtocol *protocol = [[SDLProtocol alloc] init];
-
- SDLProxy *ret = [[SDLProxy alloc] initWithTransport:transport protocol:protocol delegate:delegate];
-
- return ret;
-}
-
-@end
-
-NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLRegisterAppInterface.h b/SmartDeviceLink/SDLRegisterAppInterface.h
index d6f2ca527..6e9501e4a 100644
--- a/SmartDeviceLink/SDLRegisterAppInterface.h
+++ b/SmartDeviceLink/SDLRegisterAppInterface.h
@@ -92,12 +92,8 @@ NS_ASSUME_NONNULL_BEGIN
- (instancetype)initWithAppName:(NSString *)appName appId:(NSString *)appId languageDesired:(SDLLanguage)languageDesired;
-- (instancetype)initWithAppName:(NSString *)appName appId:(NSString *)appId languageDesired:(SDLLanguage)languageDesired isMediaApp:(BOOL)isMediaApp appType:(SDLAppHMIType)appType shortAppName:(nullable NSString *)shortAppName __deprecated_msg(("use initWithAppName:appId:languageDesired:isMediaApp:appTypes:shortAppName:"));
-
- (instancetype)initWithAppName:(NSString *)appName appId:(NSString *)appId languageDesired:(SDLLanguage)languageDesired isMediaApp:(BOOL)isMediaApp appTypes:(NSArray<SDLAppHMIType> *)appTypes shortAppName:(nullable NSString *)shortAppName;
-- (instancetype)initWithAppName:(NSString *)appName appId:(NSString *)appId languageDesired:(SDLLanguage)languageDesired isMediaApp:(BOOL)isMediaApp appType:(SDLAppHMIType)appType shortAppName:(nullable NSString *)shortAppName ttsName:(nullable NSArray<SDLTTSChunk *> *)ttsName vrSynonyms:(nullable NSArray<NSString *> *)vrSynonyms hmiDisplayLanguageDesired:(SDLLanguage)hmiDisplayLanguageDesired resumeHash:(nullable NSString *)resumeHash __deprecated_msg(("use initWithAppName:appId:languageDesired:isMediaApp:appTypes:shortAppName:ttsName:vrSynonyms:hmiDisplayLanguageDesired:resumeHash:"));
-
- (instancetype)initWithAppName:(NSString *)appName appId:(NSString *)appId languageDesired:(SDLLanguage)languageDesired isMediaApp:(BOOL)isMediaApp appTypes:(NSArray<SDLAppHMIType> *)appTypes shortAppName:(nullable NSString *)shortAppName ttsName:(nullable NSArray<SDLTTSChunk *> *)ttsName vrSynonyms:(nullable NSArray<NSString *> *)vrSynonyms hmiDisplayLanguageDesired:(SDLLanguage)hmiDisplayLanguageDesired resumeHash:(nullable NSString *)resumeHash;
/**
diff --git a/SmartDeviceLink/SDLRegisterAppInterface.m b/SmartDeviceLink/SDLRegisterAppInterface.m
index 6562b78be..34fe41ac5 100644
--- a/SmartDeviceLink/SDLRegisterAppInterface.m
+++ b/SmartDeviceLink/SDLRegisterAppInterface.m
@@ -57,10 +57,6 @@ NS_ASSUME_NONNULL_BEGIN
return self;
}
-- (instancetype)initWithAppName:(NSString *)appName appId:(NSString *)appId languageDesired:(SDLLanguage)languageDesired isMediaApp:(BOOL)isMediaApp appType:(SDLAppHMIType)appType shortAppName:(nullable NSString *)shortAppName {
- return [self initWithAppName:appName appId:appId languageDesired:languageDesired isMediaApp:isMediaApp appTypes:@[appType] shortAppName:shortAppName];
-}
-
- (instancetype)initWithAppName:(NSString *)appName appId:(NSString *)appId languageDesired:(SDLLanguage)languageDesired isMediaApp:(BOOL)isMediaApp appTypes:(NSArray<SDLAppHMIType> *)appTypes shortAppName:(nullable NSString *)shortAppName {
self = [self initWithAppName:appName appId:appId languageDesired:languageDesired];
if (!self) {
@@ -74,10 +70,6 @@ NS_ASSUME_NONNULL_BEGIN
return self;
}
-- (instancetype)initWithAppName:(NSString *)appName appId:(NSString *)appId languageDesired:(SDLLanguage)languageDesired isMediaApp:(BOOL)isMediaApp appType:(SDLAppHMIType)appType shortAppName:(nullable NSString *)shortAppName ttsName:(nullable NSArray<SDLTTSChunk *> *)ttsName vrSynonyms:(nullable NSArray<NSString *> *)vrSynonyms hmiDisplayLanguageDesired:(SDLLanguage)hmiDisplayLanguageDesired resumeHash:(nullable NSString *)resumeHash {
- return [self initWithAppName:appName appId:appId languageDesired:languageDesired isMediaApp:isMediaApp appTypes:@[appType] shortAppName:shortAppName ttsName:ttsName vrSynonyms:vrSynonyms hmiDisplayLanguageDesired:hmiDisplayLanguageDesired resumeHash:resumeHash];
-}
-
- (instancetype)initWithAppName:(NSString *)appName appId:(NSString *)appId languageDesired:(SDLLanguage)languageDesired isMediaApp:(BOOL)isMediaApp appTypes:(NSArray<SDLAppHMIType> *)appTypes shortAppName:(nullable NSString *)shortAppName ttsName:(nullable NSArray<SDLTTSChunk *> *)ttsName vrSynonyms:(nullable NSArray<NSString *> *)vrSynonyms hmiDisplayLanguageDesired:(SDLLanguage)hmiDisplayLanguageDesired resumeHash:(nullable NSString *)resumeHash {
self = [self initWithAppName:appName appId:appId languageDesired:languageDesired isMediaApp:isMediaApp appTypes:appTypes shortAppName:shortAppName];
if (!self) {
diff --git a/SmartDeviceLink/SDLScreenManager.h b/SmartDeviceLink/SDLScreenManager.h
index 716a0eae9..c3dc1e020 100644
--- a/SmartDeviceLink/SDLScreenManager.h
+++ b/SmartDeviceLink/SDLScreenManager.h
@@ -13,6 +13,8 @@
@class SDLArtwork;
@class SDLFileManager;
+@class SDLMenuCell;
+@class SDLVoiceCommand;
@class SDLSoftButtonObject;
@protocol SDLConnectionManagerType;
@@ -44,9 +46,17 @@ typedef void(^SDLScreenManagerUpdateCompletionHandler)(NSError *__nullable error
@property (copy, nonatomic) NSArray<SDLSoftButtonObject *> *softButtonObjects;
+@property (copy, nonatomic) NSArray<SDLMenuCell *> *menu;
+@property (copy, nonatomic) NSArray<SDLVoiceCommand *> *voiceCommands;
+
- (instancetype)initWithConnectionManager:(id<SDLConnectionManagerType>)connectionManager fileManager:(SDLFileManager *)fileManager;
/**
+ * Stops the manager. This method is used internally.
+ */
+- (void)stop;
+
+/**
Delays all screen updates until endUpdatesWithCompletionHandler: is called.
*/
- (void)beginUpdates;
diff --git a/SmartDeviceLink/SDLScreenManager.m b/SmartDeviceLink/SDLScreenManager.m
index 85c5793e5..798659283 100644
--- a/SmartDeviceLink/SDLScreenManager.m
+++ b/SmartDeviceLink/SDLScreenManager.m
@@ -9,8 +9,10 @@
#import "SDLScreenManager.h"
#import "SDLArtwork.h"
+#import "SDLMenuManager.h"
#import "SDLSoftButtonManager.h"
#import "SDLTextAndGraphicManager.h"
+#import "SDLVoiceCommandManager.h"
NS_ASSUME_NONNULL_BEGIN
@@ -18,6 +20,8 @@ NS_ASSUME_NONNULL_BEGIN
@property (strong, nonatomic) SDLTextAndGraphicManager *textAndGraphicManager;
@property (strong, nonatomic) SDLSoftButtonManager *softButtonManager;
+@property (strong, nonatomic) SDLMenuManager *menuManager;
+@property (strong, nonatomic) SDLVoiceCommandManager *voiceCommandMenuManager;
@property (weak, nonatomic) id<SDLConnectionManagerType> connectionManager;
@property (weak, nonatomic) SDLFileManager *fileManager;
@@ -35,10 +39,19 @@ NS_ASSUME_NONNULL_BEGIN
_textAndGraphicManager = [[SDLTextAndGraphicManager alloc] initWithConnectionManager:connectionManager fileManager:fileManager];
_softButtonManager = [[SDLSoftButtonManager alloc] initWithConnectionManager:connectionManager fileManager:fileManager];
+ _menuManager = [[SDLMenuManager alloc] initWithConnectionManager:connectionManager fileManager:fileManager];
+ _voiceCommandMenuManager = [[SDLVoiceCommandManager alloc] initWithConnectionManager:connectionManager];
return self;
}
+- (void)stop {
+ [self.textAndGraphicManager stop];
+ [self.softButtonManager stop];
+ [self.menuManager stop];
+ [self.voiceCommandMenuManager stop];
+}
+
- (nullable SDLSoftButtonObject *)softButtonObjectNamed:(NSString *)name {
return [self.softButtonManager softButtonObjectNamed:name];
}
@@ -108,6 +121,14 @@ NS_ASSUME_NONNULL_BEGIN
self.softButtonManager.softButtonObjects = softButtonObjects;
}
+- (void)setMenu:(NSArray<SDLMenuCell *> *)menu {
+ self.menuManager.menuCells = menu;
+}
+
+- (void)setVoiceCommands:(NSArray<SDLVoiceCommand *> *)voiceCommands {
+ self.voiceCommandMenuManager.voiceCommands = voiceCommands;
+}
+
#pragma mark - Getters
- (nullable NSString *)textField1 {
@@ -170,6 +191,14 @@ NS_ASSUME_NONNULL_BEGIN
return _softButtonManager.softButtonObjects;
}
+- (NSArray<SDLMenuCell *> *)menu {
+ return _menuManager.menuCells;
+}
+
+- (NSArray<SDLVoiceCommand *> *)voiceCommands {
+ return _voiceCommandMenuManager.voiceCommands;
+}
+
#pragma mark - Begin / End Updates
- (void)beginUpdates {
diff --git a/SmartDeviceLink/SDLShow.h b/SmartDeviceLink/SDLShow.h
index 770a8ba1e..833a3dea1 100644
--- a/SmartDeviceLink/SDLShow.h
+++ b/SmartDeviceLink/SDLShow.h
@@ -226,8 +226,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
* The Custom Presets defined by the App
*
- * @discussion A Vector value representing the Custom Presets defined by the
- * App
+ * @discussion A Vector value representing the Custom Presets defined by the App
* <p>
* <ul>
* <li>If omitted on supported displays, the presets will be shown as not defined</li>
@@ -239,15 +238,11 @@ NS_ASSUME_NONNULL_BEGIN
@property (strong, nonatomic, nullable) NSArray<NSString *> *customPresets;
/**
- * Text Field Metadata
- *
- * @discussion A Vector value representing the Custom Presets defined by the
- * App
- * <p>
- * App defined metadata information. See MetadataStruct. Uses mainField1, mainField2, mainField3, mainField4.
- * If omitted on supported displays, the currently set metadata tags will not change.
- * If any text field contains no tags or the none tag, the metadata tag for that textfield should be removed.
- * @since SmartDeviceLink 2.0
+ Text Field Metadata
+
+ App defined metadata information. See MetadataStruct. Uses mainField1, mainField2, mainField3, mainField4. If omitted on supported displays, the currently set metadata tags will not change. If any text field contains no tags or the none tag, the metadata tag for that textfield should be removed.
+
+ @since SmartDeviceLink 2.0
*/
@property (strong, nonatomic, nullable) SDLMetadataTags *metadataTags;
diff --git a/SmartDeviceLink/SDLShow.m b/SmartDeviceLink/SDLShow.m
index 388865d24..743e4940a 100644
--- a/SmartDeviceLink/SDLShow.m
+++ b/SmartDeviceLink/SDLShow.m
@@ -31,9 +31,9 @@ NS_ASSUME_NONNULL_BEGIN
return nil;
}
- NSArray<SDLMetadataType> *field1Array = @[mainField1Type];
- NSArray<SDLMetadataType> *field2Array = @[mainField2Type];
- SDLMetadataTags* metadataTags = [[SDLMetadataTags alloc] initWithTextFieldTypes:field1Array mainField2:field2Array];
+ NSArray<SDLMetadataType> *field1Array = mainField1Type ? @[mainField1Type] : nil;
+ NSArray<SDLMetadataType> *field2Array = mainField2Type ? @[mainField2Type] : nil;
+ SDLMetadataTags* metadataTags = (field1Array != nil || field2Array != nil) ? [[SDLMetadataTags alloc] initWithTextFieldTypes:field1Array mainField2:field2Array] : nil;
self.mainField1 = mainField1;
self.mainField2 = mainField2;
@@ -47,17 +47,17 @@ NS_ASSUME_NONNULL_BEGIN
return [self initWithMainField1:mainField1 mainField2:mainField2 mainField3:mainField3 mainField4:mainField4 alignment:alignment statusBar:nil mediaClock:nil mediaTrack:nil graphic:nil softButtons:nil customPresets:nil textFieldMetadata:nil];
}
-- (instancetype)initWithMainField1:(nullable NSString *)mainField1 mainField1Type:(nullable SDLMetadataType)mainField1Type mainField2:(nullable NSString *)mainField2 mainField2Type:(nullable SDLMetadataType)mainField2Type mainField3:(nullable NSString *)mainField3 mainField3Type:(nullable SDLMetadataType)mainField3Type mainField4:(nullable NSString *)mainField4 mainField4Type:(nullable SDLMetadataType)mainField4Type alignment:(nullable SDLTextAlignment)alignment{
+- (instancetype)initWithMainField1:(nullable NSString *)mainField1 mainField1Type:(nullable SDLMetadataType)mainField1Type mainField2:(nullable NSString *)mainField2 mainField2Type:(nullable SDLMetadataType)mainField2Type mainField3:(nullable NSString *)mainField3 mainField3Type:(nullable SDLMetadataType)mainField3Type mainField4:(nullable NSString *)mainField4 mainField4Type:(nullable SDLMetadataType)mainField4Type alignment:(nullable SDLTextAlignment)alignment {
self = [self init];
if (!self) {
return nil;
}
- NSArray<SDLMetadataType> *field1Array = @[mainField1Type];
- NSArray<SDLMetadataType> *field2Array = @[mainField2Type];
- NSArray<SDLMetadataType> *field3Array = @[mainField3Type];
- NSArray<SDLMetadataType> *field4Array = @[mainField4Type];
- SDLMetadataTags* metadataTags = [[SDLMetadataTags alloc] initWithTextFieldTypes:field1Array mainField2:field2Array mainField3:field3Array mainField4:field4Array];
+ NSArray<SDLMetadataType> *field1Array = mainField1Type ? @[mainField1Type] : nil;
+ NSArray<SDLMetadataType> *field2Array = mainField2Type ? @[mainField2Type] : nil;
+ NSArray<SDLMetadataType> *field3Array = mainField3Type ? @[mainField3Type] : nil;
+ NSArray<SDLMetadataType> *field4Array = mainField4Type ? @[mainField4Type] : nil;
+ SDLMetadataTags* metadataTags = (field1Array != nil || field2Array != nil || field3Array != nil || field4Array != nil) ? [[SDLMetadataTags alloc] initWithTextFieldTypes:field1Array mainField2:field2Array mainField3:field3Array mainField4:field4Array] : nil;
self.mainField1 = mainField1;
self.mainField2 = mainField2;
diff --git a/SmartDeviceLink/SDLSoftButtonManager.h b/SmartDeviceLink/SDLSoftButtonManager.h
index 04f646d8d..b163fe599 100644
--- a/SmartDeviceLink/SDLSoftButtonManager.h
+++ b/SmartDeviceLink/SDLSoftButtonManager.h
@@ -49,6 +49,11 @@ typedef void(^SDLSoftButtonUpdateCompletionHandler)(NSError *__nullable error);
- (instancetype)initWithConnectionManager:(id<SDLConnectionManagerType>)connectionManager fileManager:(SDLFileManager *)fileManager;
/**
+ * Stops the manager. This method is used internally.
+ */
+- (void)stop;
+
+/**
Cause all transitions in between `beginUpdates` and this method call to occur in one RPC update.
@param handler The handler called once the update is completed.
diff --git a/SmartDeviceLink/SDLSoftButtonManager.m b/SmartDeviceLink/SDLSoftButtonManager.m
index 995c0c142..f65acb444 100644
--- a/SmartDeviceLink/SDLSoftButtonManager.m
+++ b/SmartDeviceLink/SDLSoftButtonManager.m
@@ -43,7 +43,6 @@ NS_ASSUME_NONNULL_BEGIN
@property (strong, nonatomic, nullable) SDLShow *inProgressUpdate;
@property (copy, nonatomic, nullable) SDLSoftButtonUpdateCompletionHandler inProgressHandler;
-@property (strong, nonatomic, nullable) SDLShow *queuedImageUpdate;
@property (assign, nonatomic) BOOL hasQueuedUpdate;
@property (copy, nonatomic, nullable) SDLSoftButtonUpdateCompletionHandler queuedUpdateHandler;
@@ -65,7 +64,7 @@ NS_ASSUME_NONNULL_BEGIN
_fileManager = fileManager;
_softButtonObjects = @[];
- _currentLevel = SDLHMILevelNone; // Assume NONE until we get something else
+ _currentLevel = nil;
_waitingOnHMILevelUpdateToSetButtons = NO;
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_registerResponse:) name:SDLDidReceiveRegisterAppInterfaceResponse object:nil];
@@ -75,6 +74,20 @@ NS_ASSUME_NONNULL_BEGIN
return self;
}
+- (void)stop {
+ _softButtonObjects = @[];
+ _currentMainField1 = nil;
+
+ _inProgressUpdate = nil;
+ _inProgressHandler = nil;
+ _hasQueuedUpdate = NO;
+ _queuedUpdateHandler = nil;
+ _currentLevel = nil;
+ _displayCapabilities = nil;
+ _softButtonCapabilities = nil;
+ _waitingOnHMILevelUpdateToSetButtons = NO;
+}
+
- (void)setSoftButtonObjects:(NSArray<SDLSoftButtonObject *> *)softButtonObjects {
if (self.currentLevel == nil || [self.currentLevel isEqualToString:SDLHMILevelNone]) {
_waitingOnHMILevelUpdateToSetButtons = YES;
@@ -203,12 +216,15 @@ NS_ASSUME_NONNULL_BEGIN
self.inProgressHandler = [handler copy];
self.inProgressUpdate = [[SDLShow alloc] init];
self.inProgressUpdate.mainField1 = self.currentMainField1 ?: @"";
+
+ BOOL headUnitSupportsImages = self.softButtonCapabilities ? self.softButtonCapabilities.imageSupported.boolValue : NO;
+
if (self.softButtonObjects == nil) {
SDLLogV(@"Soft button objects are nil, sending an empty array");
self.inProgressUpdate.softButtons = @[];
} else if (([self sdl_currentStateHasImages] && ![self sdl_allCurrentStateImagesAreUploaded])
- && (self.softButtonCapabilities ? !self.softButtonCapabilities.imageSupported : YES)) {
- // The images don't yet exist on the head unit, or we cannot use images, send a text update if possible, otherwise, don't send anything yet
+ || !headUnitSupportsImages) {
+ // The images don't yet exist on the head unit, or we cannot use images, send a text update, if possible. Otherwise, don't send anything yet.
NSArray<SDLSoftButton *> *textOnlyButtons = [self sdl_textButtonsForCurrentState];
if (textOnlyButtons != nil) {
SDLLogV(@"Soft button images unavailable, sending text buttons");
diff --git a/SmartDeviceLink/SDLStreamingMediaConfiguration.h b/SmartDeviceLink/SDLStreamingMediaConfiguration.h
index 7902d6566..98db9258d 100644
--- a/SmartDeviceLink/SDLStreamingMediaConfiguration.h
+++ b/SmartDeviceLink/SDLStreamingMediaConfiguration.h
@@ -47,17 +47,6 @@ typedef NS_ENUM(NSUInteger, SDLCarWindowRenderingType) {
@property (weak, nonatomic, nullable) id<SDLStreamingMediaManagerDataSource> dataSource;
/**
- Set the window your video streaming content is within.
-
- Activates the haptic view parser when set. If the window contains `UIView` based views, these will be discovered and automatically sent to the head unit if it uses a haptic interface. Whether or not it supports the haptic interace, this library will also use that information to attempt to return the touched view to you in `SDLTouchManagerDelegate`.
-
- @warning Apps using views outside of the `UIView` heirarchy (such as OpenGL) are currently unsupported. If you app uses partial views in the heirarchy, only those views will be discovered. Your OpenGL views will not be discoverable to a haptic interface head unit and you will have to manually make these views discoverable via the `SDLSendHapticData` RPC request.
-
- @warning This is a weak property and it's therefore your job to hold a strong reference to this window.
- */
-@property (weak, nonatomic, nullable) UIWindow *window __deprecated_msg("Use rootViewController instead");
-
-/**
Set the initial view controller your video streaming content is within.
Activates the haptic view parser and CarWindow systems when set. This library will also use that information to attempt to return the touched view to you in `SDLTouchManagerDelegate`.
@@ -102,17 +91,6 @@ typedef NS_ENUM(NSUInteger, SDLCarWindowRenderingType) {
@param securityManagers The security managers to use or nil for none.
@param encryptionFlag The maximum encrpytion supported. If the connected head unit supports less than set here, it will still connect, but if it supports more than set here, it will not connect.
@param videoSettings Custom video encoder settings to be used in video streaming.
- @param window The UIWindow you are running the content that is being streamed on, to use for haptics if needed and possible (only works for UIViews)
- @return The configuration
- */
-- (instancetype)initWithSecurityManagers:(nullable NSArray<Class<SDLSecurityType>> *)securityManagers encryptionFlag:(SDLStreamingEncryptionFlag)encryptionFlag videoSettings:(nullable NSDictionary<NSString *, id> *)videoSettings dataSource:(nullable id<SDLStreamingMediaManagerDataSource>)dataSource window:(nullable UIWindow *)window __deprecated_msg("Use initWithSecurityManagers:encryptionFlag:videoSettings:dataSource:rootViewController: instead");
-
-/**
- Manually set all the properties to the streaming media configuration
-
- @param securityManagers The security managers to use or nil for none.
- @param encryptionFlag The maximum encrpytion supported. If the connected head unit supports less than set here, it will still connect, but if it supports more than set here, it will not connect.
- @param videoSettings Custom video encoder settings to be used in video streaming.
@param rootViewController The UIViewController wih the content that is being streamed on, to use for haptics if needed and possible (only works for UIViews)
@return The configuration
*/
diff --git a/SmartDeviceLink/SDLStreamingMediaConfiguration.m b/SmartDeviceLink/SDLStreamingMediaConfiguration.m
index 5b26d670b..41c7df822 100644
--- a/SmartDeviceLink/SDLStreamingMediaConfiguration.m
+++ b/SmartDeviceLink/SDLStreamingMediaConfiguration.m
@@ -23,10 +23,6 @@ NS_ASSUME_NONNULL_BEGIN
return [[self alloc] init];
}
-- (instancetype)initWithSecurityManagers:(nullable NSArray<Class<SDLSecurityType>> *)securityManagers encryptionFlag:(SDLStreamingEncryptionFlag)encryptionFlag videoSettings:(nullable NSDictionary<NSString *,id> *)videoSettings dataSource:(nullable id<SDLStreamingMediaManagerDataSource>)dataSource window:(nullable UIWindow *)window {
- return [self initWithSecurityManagers:securityManagers encryptionFlag:encryptionFlag videoSettings:videoSettings dataSource:dataSource rootViewController:window.rootViewController];
-}
-
- (instancetype)initWithSecurityManagers:(nullable NSArray<Class<SDLSecurityType>> *)securityManagers encryptionFlag:(SDLStreamingEncryptionFlag)encryptionFlag videoSettings:(nullable NSDictionary<NSString *,id> *)videoSettings dataSource:(nullable id<SDLStreamingMediaManagerDataSource>)dataSource rootViewController:(nullable UIViewController *)rootViewController {
self = [super init];
if (!self) {
@@ -64,14 +60,6 @@ NS_ASSUME_NONNULL_BEGIN
return [[self alloc] initWithSecurityManagers:securityManagers encryptionFlag:SDLStreamingEncryptionFlagAuthenticateAndEncrypt videoSettings:nil dataSource:nil rootViewController:initialViewController];
}
-#pragma mark - Getters / Setters
-- (void)setWindow:(nullable UIWindow *)window {
- _window = window;
- if (window != nil) {
- _rootViewController = window.rootViewController;
- }
-}
-
#pragma mark NSCopying
- (id)copyWithZone:(nullable NSZone *)zone {
diff --git a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.h b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.h
index 008cb2a01..6456e125f 100644
--- a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.h
+++ b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.h
@@ -15,10 +15,10 @@
#import "SDLStreamingAudioManagerType.h"
#import "SDLStreamingMediaManagerConstants.h"
-@class SDLAbstractProtocol;
@class SDLAudioStreamManager;
@class SDLCarWindow;
@class SDLImageResolution;
+@class SDLProtocol;
@class SDLStateMachine;
@class SDLStreamingMediaConfiguration;
@class SDLTouchManager;
@@ -177,7 +177,7 @@ extern SDLAudioStreamState *const SDLAudioStreamStateShuttingDown;
/**
* Start the manager with a completion block that will be called when startup completes. This is used internally. To use an SDLStreamingMediaManager, you should use the manager found on `SDLManager`.
*/
-- (void)startWithProtocol:(SDLAbstractProtocol *)protocol;
+- (void)startWithProtocol:(SDLProtocol *)protocol;
/**
* Stop the manager. This method is used internally.
diff --git a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m
index a77f87820..ddb617d3a 100644
--- a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m
+++ b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m
@@ -8,7 +8,6 @@
#import "SDLStreamingMediaLifecycleManager.h"
-#import "SDLAbstractProtocol.h"
#import "SDLAudioStreamManager.h"
#import "SDLCarWindow.h"
#import "SDLControlFramePayloadAudioStartServiceAck.h"
@@ -28,6 +27,7 @@
#import "SDLLogMacros.h"
#import "SDLNotificationConstants.h"
#import "SDLOnHMIStatus.h"
+#import "SDLProtocol.h"
#import "SDLProtocolMessage.h"
#import "SDLRegisterAppInterfaceResponse.h"
#import "SDLRPCNotificationNotification.h"
@@ -70,7 +70,7 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
@interface SDLStreamingMediaLifecycleManager () <SDLVideoEncoderDelegate>
@property (weak, nonatomic) id<SDLConnectionManagerType> connectionManager;
-@property (weak, nonatomic) SDLAbstractProtocol *protocol;
+@property (weak, nonatomic) SDLProtocol *protocol;
@property (assign, nonatomic, readonly, getter=isAppStateVideoStreamCapable) BOOL appStateVideoStreamCapable;
@property (assign, nonatomic, readonly, getter=isHmiStateAudioStreamCapable) BOOL hmiStateAudioStreamCapable;
@@ -170,7 +170,7 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
return self;
}
-- (void)startWithProtocol:(SDLAbstractProtocol *)protocol {
+- (void)startWithProtocol:(SDLProtocol *)protocol {
_protocol = protocol;
if (![self.protocol.protocolDelegateTable containsObject:self]) {
@@ -422,7 +422,7 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
NSInteger targetFramerate = ((NSNumber *)self.videoEncoderSettings[(__bridge NSString *)kVTCompressionPropertyKey_ExpectedFrameRate]).integerValue;
SDLLogD(@"Initializing CADisplayLink with framerate: %ld", (long)targetFramerate);
self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(sdl_displayLinkFired:)];
- if (SDL_SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10")) {
+ if (@available(iOS 10, *)) {
self.displayLink.preferredFramesPerSecond = targetFramerate;
} else {
self.displayLink.frameInterval = (60 / targetFramerate);
diff --git a/SmartDeviceLink/SDLStreamingMediaManager.h b/SmartDeviceLink/SDLStreamingMediaManager.h
index 76f4ab8a2..bad1d90e3 100644
--- a/SmartDeviceLink/SDLStreamingMediaManager.h
+++ b/SmartDeviceLink/SDLStreamingMediaManager.h
@@ -12,8 +12,8 @@
#import "SDLStreamingAudioManagerType.h"
#import "SDLStreamingMediaManagerConstants.h"
-@class SDLAbstractProtocol;
@class SDLAudioStreamManager;
+@class SDLProtocol;
@class SDLStreamingMediaConfiguration;
@class SDLTouchManager;
@class SDLVideoStreamingFormat;
@@ -120,7 +120,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
* Start the manager with a completion block that will be called when startup completes. This is used internally. To use an SDLStreamingMediaManager, you should use the manager found on `SDLManager`.
*/
-- (void)startWithProtocol:(SDLAbstractProtocol *)protocol;
+- (void)startWithProtocol:(SDLProtocol *)protocol;
/**
* Stop the manager. This method is used internally.
diff --git a/SmartDeviceLink/SDLStreamingMediaManager.m b/SmartDeviceLink/SDLStreamingMediaManager.m
index 4a0b08b28..ade1165e7 100644
--- a/SmartDeviceLink/SDLStreamingMediaManager.m
+++ b/SmartDeviceLink/SDLStreamingMediaManager.m
@@ -41,7 +41,7 @@ NS_ASSUME_NONNULL_BEGIN
return self;
}
-- (void)startWithProtocol:(SDLAbstractProtocol *)protocol {
+- (void)startWithProtocol:(SDLProtocol *)protocol {
[self.lifecycleManager startWithProtocol:protocol];
}
diff --git a/SmartDeviceLink/SDLSystemCapabilityManager.h b/SmartDeviceLink/SDLSystemCapabilityManager.h
new file mode 100644
index 000000000..36f58a735
--- /dev/null
+++ b/SmartDeviceLink/SDLSystemCapabilityManager.h
@@ -0,0 +1,194 @@
+//
+// SDLSystemCapabilityManager.h
+// SmartDeviceLink
+//
+// Created by Nicole on 3/26/18.
+// Copyright © 2018 smartdevicelink. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+#import "SDLHMIZoneCapabilities.h"
+#import "SDLPrerecordedSpeech.h"
+#import "SDLSpeechCapabilities.h"
+#import "SDLSystemCapabilityType.h"
+#import "SDLVrCapabilities.h"
+
+@class SDLAudioPassThruCapabilities;
+@class SDLButtonCapabilities;
+@class SDLDisplayCapabilities;
+@class SDLHMICapabilities;
+@class SDLNavigationCapability;
+@class SDLPhoneCapability;
+@class SDLPresetBankCapabilities;
+@class SDLRemoteControlCapabilities;
+@class SDLSoftButtonCapabilities;
+@class SDLSystemCapabilityManager;
+@class SDLVideoStreamingCapability;
+
+@protocol SDLConnectionManagerType;
+
+NS_ASSUME_NONNULL_BEGIN
+
+
+/**
+ * A completion handler called after a request for the capability type is returned from the remote system.
+ *
+ * @param error The error returned if the request for a capability type failed. The error is nil if the request was successful.
+ * @param systemCapabilityManager The system capability manager
+ */
+typedef void (^SDLUpdateCapabilityHandler)(NSError * _Nullable error, SDLSystemCapabilityManager *systemCapabilityManager);
+
+
+@interface SDLSystemCapabilityManager : NSObject
+
+/**
+ * @see SDLDisplayCapabilities
+ *
+ * Optional
+ */
+@property (nullable, strong, nonatomic, readonly) SDLDisplayCapabilities *displayCapabilities;
+
+/**
+ * @see SDLHMICapabilities
+ *
+ * Optional
+ */
+@property (nullable, strong, nonatomic, readonly) SDLHMICapabilities *hmiCapabilities;
+
+/**
+ * If returned, the platform supports on-screen SoftButtons
+ *
+ * @see SDLSoftButtonCapabilities
+ *
+ * Optional, Array of length 1 - 100, of SDLSoftButtonCapabilities
+ */
+@property (nullable, copy, nonatomic, readonly) NSArray<SDLSoftButtonCapabilities *> *softButtonCapabilities;
+
+/**
+ * @see SDLButtonCapabilities
+ *
+ * Optional, Array of length 1 - 100, of SDLButtonCapabilities
+ */
+@property (nullable, copy, nonatomic, readonly) NSArray<SDLButtonCapabilities *> *buttonCapabilities;
+
+/**
+ * If returned, the platform supports custom on-screen Presets
+ *
+ * @see SDLPresetBankCapabilities
+ *
+ * Optional
+ */
+@property (nullable, strong, nonatomic, readonly) SDLPresetBankCapabilities *presetBankCapabilities;
+
+/**
+ * @see SDLHMIZoneCapabilities
+ *
+ * Optional, Array of length 1 - 100, of SDLHMIZoneCapabilities
+ */
+@property (nullable, copy, nonatomic, readonly) NSArray<SDLHMIZoneCapabilities> *hmiZoneCapabilities;
+
+/**
+ * @see SDLSpeechCapabilities
+ *
+ * Optional, Array of length 1 - 100, of SDLSpeechCapabilities
+ */
+@property (nullable, copy, nonatomic, readonly) NSArray<SDLSpeechCapabilities> *speechCapabilities;
+
+/**
+ * @see SDLPrerecordedSpeech
+ *
+ * Optional, Array of length 1 - 100, of SDLPrerecordedSpeech
+ */
+@property (nullable, copy, nonatomic, readonly) NSArray<SDLPrerecordedSpeech> *prerecordedSpeechCapabilities;
+
+/**
+ * @see SDLVRCapabilities
+ *
+ * True if the head unit supports voice recognition; false if not.
+ */
+@property (nonatomic, assign, readonly) BOOL vrCapability;
+
+/**
+ * @see SDLAudioPassThruCapabilities
+ *
+ * Optional, Array of length 1 - 100, of SDLAudioPassThruCapabilities
+ */
+@property (nullable, copy, nonatomic, readonly) NSArray<SDLAudioPassThruCapabilities *> *audioPassThruCapabilities;
+
+/**
+ * @see SDLAudioPassThruCapabilities
+ *
+ * Optional, Array of length 1 - 100, of SDLAudioPassThruCapabilities
+ */
+@property (nullable, strong, nonatomic, readonly) SDLAudioPassThruCapabilities *pcmStreamCapability;
+
+/**
+ * If returned, the platform supports navigation
+ *
+ * @see SDLNavigationCapability
+ *
+ * Optional
+ */
+@property (nullable, strong, nonatomic, readonly) SDLNavigationCapability *navigationCapability;
+
+/**
+ * If returned, the platform supports making phone calls
+ *
+ * @see SDLPhoneCapability
+ *
+ * Optional
+ */
+@property (nullable, strong, nonatomic, readonly) SDLPhoneCapability *phoneCapability;
+
+/**
+ * If returned, the platform supports video streaming
+ *
+ * @see SDLVideoStreamingCapability
+ *
+ * Optional
+ */
+@property (nullable, strong, nonatomic, readonly) SDLVideoStreamingCapability *videoStreamingCapability;
+
+/**
+ * If returned, the platform supports remote control capabilities
+ *
+ * @see SDLRemoteControlCapabilities
+ *
+ * Optional
+ */
+@property (nullable, strong, nonatomic, readonly) SDLRemoteControlCapabilities *remoteControlCapability;
+
+/**
+ * Init is unavailable. Dependencies must be injected using initWithConnectionManager:
+ *
+ * @return nil
+ */
+- (instancetype)init NS_UNAVAILABLE;
+
+/**
+ * Creates a new system capability manager with a specified connection manager
+ *
+ * @param manager A connection manager to use to forward on RPCs
+ *
+ * @return An instance of SDLSystemCapabilityManager
+ */
+- (instancetype)initWithConnectionManager:(id<SDLConnectionManagerType>)manager NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Stops the manager. This method is used internally.
+ */
+- (void)stop;
+
+/**
+ * Retrieves a capability type from the remote system. This function must be called in order to retrieve the values of `navigationCapability`, `phoneCapability`, `videoStreamingCapability` and `remoteControlCapability`. If you do not call this method first, those values will be nil. After calling this method, assuming there is no error in the handler, you may retrieve the capability you requested from the manager within the handler.
+ *
+ * @param type The type of capability to retrieve
+ * @param handler The handler to be called when the retrieval is complete
+ */
+- (void)updateCapabilityType:(SDLSystemCapabilityType)type completionHandler:(SDLUpdateCapabilityHandler)handler;
+
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLSystemCapabilityManager.m b/SmartDeviceLink/SDLSystemCapabilityManager.m
new file mode 100644
index 000000000..cd9db463a
--- /dev/null
+++ b/SmartDeviceLink/SDLSystemCapabilityManager.m
@@ -0,0 +1,156 @@
+//
+// SDLSystemCapabilityManager.m
+// SmartDeviceLink
+//
+// Created by Nicole on 3/26/18.
+// Copyright © 2018 smartdevicelink. All rights reserved.
+//
+
+#import "SDLSystemCapabilityManager.h"
+
+#import "SDLConnectionManagerType.h"
+#import "SDLGenericResponse.h"
+#import "SDLGetSystemCapability.h"
+#import "SDLGetSystemCapabilityResponse.h"
+#import "SDLLogMacros.h"
+#import "SDLNotificationConstants.h"
+#import "SDLRegisterAppInterfaceResponse.h"
+#import "SDLRPCResponseNotification.h"
+#import "SDLSetDisplayLayoutResponse.h"
+#import "SDLSystemCapability.h"
+#import "SDLVideoStreamingCapability.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface SDLSystemCapabilityManager ()
+
+@property (weak, nonatomic) id<SDLConnectionManagerType> connectionManager;
+@property (copy, nonatomic, nullable) SDLUpdateCapabilityHandler systemCapabilityHandler;
+
+@property (nullable, strong, nonatomic, readwrite) SDLDisplayCapabilities *displayCapabilities;
+@property (nullable, strong, nonatomic, readwrite) SDLHMICapabilities *hmiCapabilities;
+@property (nullable, copy, nonatomic, readwrite) NSArray<SDLSoftButtonCapabilities *> *softButtonCapabilities;
+@property (nullable, copy, nonatomic, readwrite) NSArray<SDLButtonCapabilities *> *buttonCapabilities;
+@property (nullable, strong, nonatomic, readwrite) SDLPresetBankCapabilities *presetBankCapabilities;
+@property (nullable, copy, nonatomic, readwrite) NSArray<SDLHMIZoneCapabilities> *hmiZoneCapabilities;
+@property (nullable, copy, nonatomic, readwrite) NSArray<SDLSpeechCapabilities> *speechCapabilities;
+@property (nullable, copy, nonatomic, readwrite) NSArray<SDLPrerecordedSpeech> *prerecordedSpeechCapabilities;
+@property (nonatomic, assign, readwrite) BOOL vrCapability;
+@property (nullable, copy, nonatomic, readwrite) NSArray<SDLAudioPassThruCapabilities *> *audioPassThruCapabilities;
+@property (nullable, strong, nonatomic, readwrite) SDLAudioPassThruCapabilities *pcmStreamCapability;
+@property (nullable, strong, nonatomic, readwrite) SDLNavigationCapability *navigationCapability;
+@property (nullable, strong, nonatomic, readwrite) SDLPhoneCapability *phoneCapability;
+@property (nullable, strong, nonatomic, readwrite) SDLVideoStreamingCapability *videoStreamingCapability;
+@property (nullable, strong, nonatomic, readwrite) SDLRemoteControlCapabilities *remoteControlCapability;
+
+@end
+
+@implementation SDLSystemCapabilityManager
+
+#pragma mark - Lifecycle
+
+- (instancetype)initWithConnectionManager:(id<SDLConnectionManagerType>)manager {
+ self = [super init];
+ if (!self) {
+ return nil;
+ }
+
+ _connectionManager = manager;
+ [self sdl_registerForNotifications];
+
+ return self;
+}
+
+- (void)stop {
+ SDLLogD(@"System Capability manager stopped");
+ _displayCapabilities = nil;
+ _hmiCapabilities = nil;
+ _softButtonCapabilities = nil;
+ _buttonCapabilities = nil;
+ _presetBankCapabilities = nil;
+ _hmiZoneCapabilities = nil;
+ _speechCapabilities = nil;
+ _prerecordedSpeechCapabilities = nil;
+ _vrCapability = NO;
+ _audioPassThruCapabilities = nil;
+ _pcmStreamCapability = nil;
+ _navigationCapability = nil;
+ _phoneCapability = nil;
+ _videoStreamingCapability = nil;
+ _remoteControlCapability = nil;
+}
+
+
+#pragma mark - Notifications
+
+-(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];
+}
+
+- (void)sdl_registerResponse:(SDLRPCResponseNotification *)notification {
+ SDLRegisterAppInterfaceResponse *response = (SDLRegisterAppInterfaceResponse *)notification.response;
+ if (!response.success.boolValue) { return; }
+
+ self.displayCapabilities = response.displayCapabilities;
+ self.hmiCapabilities = response.hmiCapabilities;
+ self.softButtonCapabilities = response.softButtonCapabilities;
+ self.buttonCapabilities = response.buttonCapabilities;
+ self.presetBankCapabilities = response.presetBankCapabilities;
+ self.hmiZoneCapabilities = response.hmiZoneCapabilities;
+ self.speechCapabilities = response.speechCapabilities;
+ self.prerecordedSpeechCapabilities = response.prerecordedSpeech;
+ self.vrCapability = (response.vrCapabilities.count > 0 && [response.vrCapabilities.firstObject isEqualToEnum:SDLVRCapabilitiesText]) ? YES : NO;
+ self.audioPassThruCapabilities = response.audioPassThruCapabilities;
+ self.pcmStreamCapability = response.pcmStreamCapabilities;
+}
+
+- (void)sdl_displayLayoutResponse:(SDLRPCResponseNotification *)notification {
+ SDLSetDisplayLayoutResponse *response = (SDLSetDisplayLayoutResponse *)notification.response;
+ if (!response.success.boolValue) { return; }
+
+ self.displayCapabilities = response.displayCapabilities;
+ self.buttonCapabilities = response.buttonCapabilities;
+ self.softButtonCapabilities = response.softButtonCapabilities;
+ self.presetBankCapabilities = response.presetBankCapabilities;
+}
+
+- (void)sdl_systemCapabilityResponse:(SDLRPCResponseNotification *)notification {
+ SDLGetSystemCapabilityResponse *response = (SDLGetSystemCapabilityResponse *)notification.response;
+ if (!response.success.boolValue) { return; }
+
+ SDLSystemCapability *systemCapabilityResponse = ((SDLGetSystemCapabilityResponse *)response).systemCapability;
+ SDLSystemCapabilityType systemCapabilityType = systemCapabilityResponse.systemCapabilityType;
+
+ if ([systemCapabilityType isEqualToEnum:SDLSystemCapabilityTypePhoneCall]) {
+ self.phoneCapability = systemCapabilityResponse.phoneCapability;
+ } else if ([systemCapabilityType isEqualToEnum:SDLSystemCapabilityTypeNavigation]) {
+ self.navigationCapability = systemCapabilityResponse.navigationCapability;
+ } else if ([systemCapabilityType isEqualToEnum:SDLSystemCapabilityTypeRemoteControl]) {
+ self.remoteControlCapability = systemCapabilityResponse.remoteControlCapability;
+ } else if ([systemCapabilityType isEqualToEnum:SDLSystemCapabilityTypeVideoStreaming]) {
+ self.videoStreamingCapability = systemCapabilityResponse.videoStreamingCapability;
+ } else {
+ SDLLogW(@"Received response for unknown System Capability Type: %@", systemCapabilityType);
+ }
+
+ if (self.systemCapabilityHandler == nil) { return; }
+ self.systemCapabilityHandler(nil, self);
+}
+
+#pragma mark - Capability Request
+
+- (void)updateCapabilityType:(SDLSystemCapabilityType)type completionHandler:(SDLUpdateCapabilityHandler)handler {
+ self.systemCapabilityHandler = handler;
+ 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);
+ }];
+}
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLTCPTransport.h b/SmartDeviceLink/SDLTCPTransport.h
index ed8da7e41..66a526da4 100644
--- a/SmartDeviceLink/SDLTCPTransport.h
+++ b/SmartDeviceLink/SDLTCPTransport.h
@@ -1,16 +1,19 @@
// SDLTCPTransport.h
//
-#import "SDLAbstractTransport.h"
+#import "SDLTransportType.h"
NS_ASSUME_NONNULL_BEGIN
-@interface SDLTCPTransport : SDLAbstractTransport {
+@interface SDLTCPTransport : NSObject <SDLTransportType> {
_Nullable CFSocketRef socket;
}
+- (instancetype)initWithHostName:(NSString *)hostName portNumber:(NSString *)portNumber;
+
@property (strong, nonatomic) NSString *hostName;
@property (strong, nonatomic) NSString *portNumber;
+@property (nullable, weak, nonatomic) id<SDLTransportDelegate> delegate;
@end
diff --git a/SmartDeviceLink/SDLTCPTransport.m b/SmartDeviceLink/SDLTCPTransport.m
index 920af4d38..b8b0a9520 100644
--- a/SmartDeviceLink/SDLTCPTransport.m
+++ b/SmartDeviceLink/SDLTCPTransport.m
@@ -41,6 +41,16 @@ static void TCPCallback(CFSocketRef socket, CFSocketCallBackType type, CFDataRef
return self;
}
+- (instancetype)initWithHostName:(NSString *)hostName portNumber:(NSString *)portNumber {
+ self = [self init];
+ if (!self) { return nil; }
+
+ _hostName = hostName;
+ _portNumber = portNumber;
+
+ return self;
+}
+
- (void)dealloc {
[self disconnect];
}
diff --git a/SmartDeviceLink/SDLTextAndGraphicManager.h b/SmartDeviceLink/SDLTextAndGraphicManager.h
index 4becbd77d..a3a9c23be 100644
--- a/SmartDeviceLink/SDLTextAndGraphicManager.h
+++ b/SmartDeviceLink/SDLTextAndGraphicManager.h
@@ -46,9 +46,11 @@ typedef void(^SDLTextAndGraphicUpdateCompletionHandler)(NSError *__nullable erro
@property (copy, nonatomic, nullable) SDLMetadataType textField4Type;
/**
- If you want to make a graphic blank, set it to this artwork
+ * If you want to remove the current artwork, set it to this blank artwork.
+ *
+ * This artwork is set to null on disconnects to prevent a `sdl_fileManager_fileDoesNotExistError` error when the artwork is sent again on reconnects.
*/
-@property (strong, nonatomic, readonly) SDLArtwork *blankArtwork;
+@property (strong, nonatomic, readonly, nullable) SDLArtwork *blankArtwork;
@property (assign, nonatomic, getter=isBatchingUpdates) BOOL batchUpdates;
@@ -62,6 +64,11 @@ typedef void(^SDLTextAndGraphicUpdateCompletionHandler)(NSError *__nullable erro
- (instancetype)initWithConnectionManager:(id<SDLConnectionManagerType>)connectionManager fileManager:(SDLFileManager *)fileManager;
/**
+ * Stops the manager. This method is used internally.
+ */
+- (void)stop;
+
+/**
Update text fields with new text set into the text field properties. Pass an empty string `\@""` to clear the text field.
If the system does not support a full 4 fields, this will automatically be concatenated and properly send the field available.
diff --git a/SmartDeviceLink/SDLTextAndGraphicManager.m b/SmartDeviceLink/SDLTextAndGraphicManager.m
index 7ec1406ea..eadc37992 100644
--- a/SmartDeviceLink/SDLTextAndGraphicManager.m
+++ b/SmartDeviceLink/SDLTextAndGraphicManager.m
@@ -52,7 +52,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (strong, nonatomic, nullable) SDLDisplayCapabilities *displayCapabilities;
@property (strong, nonatomic, nullable) SDLHMILevel currentLevel;
-@property (strong, nonatomic) SDLArtwork *blankArtwork;
+@property (strong, nonatomic, nullable) SDLArtwork *blankArtwork;
@property (assign, nonatomic) BOOL isDirty;
@@ -79,6 +79,32 @@ NS_ASSUME_NONNULL_BEGIN
return self;
}
+- (void)stop {
+ _textField1 = nil;
+ _textField2 = nil;
+ _textField3 = nil;
+ _textField4 = nil;
+ _mediaTrackTextField = nil;
+ _primaryGraphic = nil;
+ _secondaryGraphic = nil;
+ _alignment = SDLTextAlignmentCenter;
+ _textField1Type = nil;
+ _textField2Type = nil;
+ _textField3Type = nil;
+ _textField4Type = nil;
+
+ _currentScreenData = [[SDLShow alloc] init];
+ _inProgressUpdate = nil;
+ _inProgressHandler = nil;
+ _queuedImageUpdate = nil;
+ _hasQueuedUpdate = NO;
+ _queuedUpdateHandler = nil;
+ _displayCapabilities = nil;
+ _currentLevel = SDLHMILevelNone;
+ _blankArtwork = nil;
+ _isDirty = NO;
+}
+
#pragma mark - Upload / Send
- (void)updateWithCompletionHandler:(nullable SDLTextAndGraphicUpdateCompletionHandler)handler {
@@ -378,6 +404,7 @@ NS_ASSUME_NONNULL_BEGIN
show.mainField2 = @"";
show.mainField3 = @"";
show.mainField4 = @"";
+ show.mediaTrack = @"";
return show;
}
@@ -390,6 +417,7 @@ NS_ASSUME_NONNULL_BEGIN
newShow.mainField2 = show.mainField2;
newShow.mainField3 = show.mainField3;
newShow.mainField4 = show.mainField4;
+ newShow.mediaTrack = show.mediaTrack;
newShow.metadataTags = show.metadataTags;
return newShow;
@@ -409,6 +437,7 @@ NS_ASSUME_NONNULL_BEGIN
self.currentScreenData.mainField2 = show.mainField2 ?: self.currentScreenData.mainField2;
self.currentScreenData.mainField3 = show.mainField3 ?: self.currentScreenData.mainField3;
self.currentScreenData.mainField4 = show.mainField4 ?: self.currentScreenData.mainField4;
+ self.currentScreenData.mediaTrack = show.mediaTrack ?: self.currentScreenData.mediaTrack;
self.currentScreenData.metadataTags = show.metadataTags ?: self.currentScreenData.metadataTags;
self.currentScreenData.alignment = show.alignment ?: self.currentScreenData.alignment;
self.currentScreenData.graphic = show.graphic ?: self.currentScreenData.graphic;
@@ -589,7 +618,7 @@ NS_ASSUME_NONNULL_BEGIN
return (_hasQueuedUpdate || _queuedUpdateHandler != nil);
}
-- (SDLArtwork *)blankArtwork {
+- (nullable SDLArtwork *)blankArtwork {
if (_blankArtwork != nil) {
return _blankArtwork;
}
diff --git a/SmartDeviceLink/SDLTouchManager.m b/SmartDeviceLink/SDLTouchManager.m
index 1d601d14a..518877e96 100644
--- a/SmartDeviceLink/SDLTouchManager.m
+++ b/SmartDeviceLink/SDLTouchManager.m
@@ -183,28 +183,29 @@ static NSUInteger const MaximumNumberOfTouches = 2;
SDLOnTouchEvent* onTouchEvent = (SDLOnTouchEvent*)notification.notification;
SDLTouchType touchType = onTouchEvent.type;
- SDLTouchEvent *touchEvent = onTouchEvent.event.firstObject;
- SDLTouch *touch = [[SDLTouch alloc] initWithTouchEvent:touchEvent];
+ [onTouchEvent.event enumerateObjectsUsingBlock:^(SDLTouchEvent *touchEvent, NSUInteger idx, BOOL *stop) {
+ SDLTouch *touch = [[SDLTouch alloc] initWithTouchEvent:touchEvent];
- if (self.touchEventHandler) {
- self.touchEventHandler(touch, touchType);
- }
-
- if (!self.touchEventDelegate || (touch.identifier > MaximumNumberOfTouches)) {
- return;
- }
+ if (self.touchEventHandler) {
+ self.touchEventHandler(touch, touchType);
+ }
- dispatch_async(dispatch_get_main_queue(), ^{
- if ([onTouchEvent.type isEqualToEnum:SDLTouchTypeBegin]) {
- [self sdl_handleTouchBegan:touch];
- } else if ([onTouchEvent.type isEqualToEnum:SDLTouchTypeMove]) {
- [self sdl_handleTouchMoved:touch];
- } else if ([onTouchEvent.type isEqualToEnum:SDLTouchTypeEnd]) {
- [self sdl_handleTouchEnded:touch];
- } else if ([onTouchEvent.type isEqualToEnum:SDLTouchTypeCancel]) {
- [self sdl_handleTouchCanceled:touch];
+ if (!self.touchEventDelegate || (touch.identifier > MaximumNumberOfTouches)) {
+ return;
}
- });
+
+ dispatch_async(dispatch_get_main_queue(), ^{
+ if ([onTouchEvent.type isEqualToEnum:SDLTouchTypeBegin]) {
+ [self sdl_handleTouchBegan:touch];
+ } else if ([onTouchEvent.type isEqualToEnum:SDLTouchTypeMove]) {
+ [self sdl_handleTouchMoved:touch];
+ } else if ([onTouchEvent.type isEqualToEnum:SDLTouchTypeEnd]) {
+ [self sdl_handleTouchEnded:touch];
+ } else if ([onTouchEvent.type isEqualToEnum:SDLTouchTypeCancel]) {
+ [self sdl_handleTouchCanceled:touch];
+ }
+ });
+ }];
}
#pragma mark - Private
diff --git a/SmartDeviceLink/SDLAbstractTransport.h b/SmartDeviceLink/SDLTransportType.h
index 0273b8425..5d516808d 100644
--- a/SmartDeviceLink/SDLAbstractTransport.h
+++ b/SmartDeviceLink/SDLTransportType.h
@@ -1,4 +1,4 @@
-// SDLAbstractTransport.h
+// SDLTransportType.h
#import <Foundation/Foundation.h>
@@ -6,15 +6,13 @@
NS_ASSUME_NONNULL_BEGIN
-@interface SDLAbstractTransport : NSObject
+@protocol SDLTransportType <NSObject>
@property (nullable, weak, nonatomic) id<SDLTransportDelegate> delegate;
-@property (strong, nonatomic) NSString *debugConsoleGroupName;
- (void)connect;
- (void)disconnect;
- (void)sendData:(NSData *)dataToSend;
-- (double)retryDelay;
@end
diff --git a/SmartDeviceLink/SDLUploadFileOperation.m b/SmartDeviceLink/SDLUploadFileOperation.m
index a084bd16a..a7366c7c3 100644
--- a/SmartDeviceLink/SDLUploadFileOperation.m
+++ b/SmartDeviceLink/SDLUploadFileOperation.m
@@ -113,7 +113,7 @@ NS_ASSUME_NONNULL_BEGIN
// The putfile's length parameter is based on the current offset
SDLPutFile *putFile = [[SDLPutFile alloc] initWithFileName:file.name fileType:file.fileType persistentFile:file.isPersistent];
putFile.offset = @(currentOffset);
- putFile.length = @([self.class sdl_getPutFileLengthForOffset:currentOffset fileSize:file.fileSize mtuSize:mtuSize]);
+ putFile.length = @([self.class sdl_getPutFileLengthForOffset:currentOffset fileSize:(NSUInteger)file.fileSize mtuSize:mtuSize]);
// Get a chunk of data from the input stream
NSUInteger dataSize = [self.class sdl_getDataSizeForOffset:currentOffset fileSize:file.fileSize mtuSize:mtuSize];
@@ -177,7 +177,7 @@ NS_ASSUME_NONNULL_BEGIN
@param mtuSize The maximum packet size allowed
@return The the length of the data being sent in the putfile
*/
-+ (NSUInteger)sdl_getPutFileLengthForOffset:(NSUInteger)currentOffset fileSize:(unsigned long long)fileSize mtuSize:(NSUInteger)mtuSize {
++ (NSUInteger)sdl_getPutFileLengthForOffset:(NSUInteger)currentOffset fileSize:(NSUInteger)fileSize mtuSize:(NSUInteger)mtuSize {
NSUInteger putFileLength = 0;
if (currentOffset == 0) {
// The first putfile sends the full file size
diff --git a/SmartDeviceLink/SDLVoiceCommand.h b/SmartDeviceLink/SDLVoiceCommand.h
new file mode 100644
index 000000000..252fbaeae
--- /dev/null
+++ b/SmartDeviceLink/SDLVoiceCommand.h
@@ -0,0 +1,31 @@
+//
+// SDLVoiceCommand.h
+// SmartDeviceLink
+//
+// Created by Joel Fischer on 4/9/18.
+// Copyright © 2018 smartdevicelink. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+typedef void(^SDLVoiceCommandSelectionHandler)(void);
+
+@interface SDLVoiceCommand : NSObject
+
+/**
+ The strings the user can say to activate this voice command
+ */
+@property (copy, nonatomic, readonly) NSArray<NSString *> *voiceCommands;
+
+/**
+ The handler that will be called when the command is activated
+ */
+@property (copy, nonatomic, readonly, nullable) SDLVoiceCommandSelectionHandler handler;
+
+- (instancetype)initWithVoiceCommands:(NSArray<NSString *> *)voiceCommands handler:(SDLVoiceCommandSelectionHandler)handler;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLVoiceCommand.m b/SmartDeviceLink/SDLVoiceCommand.m
new file mode 100644
index 000000000..e9a619945
--- /dev/null
+++ b/SmartDeviceLink/SDLVoiceCommand.m
@@ -0,0 +1,37 @@
+//
+// SDLVoiceCommand.m
+// SmartDeviceLink
+//
+// Created by Joel Fischer on 4/9/18.
+// Copyright © 2018 smartdevicelink. All rights reserved.
+//
+
+#import "SDLVoiceCommand.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface SDLVoiceCommand()
+
+@property (assign, nonatomic) UInt32 commandId;
+
+@end
+
+@implementation SDLVoiceCommand
+
+- (instancetype)initWithVoiceCommands:(NSArray<NSString *> *)voiceCommands handler:(SDLVoiceCommandSelectionHandler)handler {
+ self = [super init];
+ if (!self) { return nil; }
+
+ _voiceCommands = voiceCommands;
+ _handler = handler;
+
+ return self;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"SDLVoiceCommand: %u-\"%@\", voice commands: %lu", (unsigned int)_commandId, _voiceCommands.firstObject, _voiceCommands.count];
+}
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLVoiceCommandManager.h b/SmartDeviceLink/SDLVoiceCommandManager.h
new file mode 100644
index 000000000..8c3f3f78f
--- /dev/null
+++ b/SmartDeviceLink/SDLVoiceCommandManager.h
@@ -0,0 +1,38 @@
+//
+// SDLVoiceCommandManager.h
+// SmartDeviceLink
+//
+// Created by Joel Fischer on 4/23/18.
+// Copyright © 2018 smartdevicelink. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@class SDLFileManager;
+@class SDLVoiceCommand;
+
+@protocol SDLConnectionManagerType;
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ The handler run when the update has completed
+
+ @param error An error if the update failed and an error occurred
+ */
+typedef void(^SDLMenuUpdateCompletionHandler)(NSError *__nullable error);
+
+@interface SDLVoiceCommandManager : NSObject
+
+- (instancetype)initWithConnectionManager:(id<SDLConnectionManagerType>)connectionManager;
+
+/**
+ * Stops the manager. This method is used internally.
+ */
+- (void)stop;
+
+@property (copy, nonatomic) NSArray<SDLVoiceCommand *> *voiceCommands;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLVoiceCommandManager.m b/SmartDeviceLink/SDLVoiceCommandManager.m
new file mode 100644
index 000000000..ef5027c95
--- /dev/null
+++ b/SmartDeviceLink/SDLVoiceCommandManager.m
@@ -0,0 +1,260 @@
+//
+// SDLVoiceCommandManager.m
+// SmartDeviceLink
+//
+// Created by Joel Fischer on 4/23/18.
+// Copyright © 2018 smartdevicelink. All rights reserved.
+//
+
+#import "SDLVoiceCommandManager.h"
+
+#import "SDLAddCommand.h"
+#import "SDLConnectionManagerType.h"
+#import "SDLDeleteCommand.h"
+#import "SDLError.h"
+#import "SDLHMILevel.h"
+#import "SDLLogMacros.h"
+#import "SDLNotificationConstants.h"
+#import "SDLOnCommand.h"
+#import "SDLOnHMIStatus.h"
+#import "SDLRPCNotificationNotification.h"
+#import "SDLRPCRequest.h"
+#import "SDLVoiceCommand.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface SDLVoiceCommand()
+
+@property (assign, nonatomic) UInt32 commandId;
+
+@end
+
+@interface SDLVoiceCommandManager()
+
+@property (weak, nonatomic) id<SDLConnectionManagerType> connectionManager;
+
+@property (assign, nonatomic) BOOL waitingOnHMIUpdate;
+@property (copy, nonatomic, nullable) SDLHMILevel currentHMILevel;
+
+@property (strong, nonatomic, nullable) NSArray<SDLRPCRequest *> *inProgressUpdate;
+@property (assign, nonatomic) BOOL hasQueuedUpdate;
+
+@property (assign, nonatomic) UInt32 lastVoiceCommandId;
+@property (copy, nonatomic) NSArray<SDLVoiceCommand *> *oldVoiceCommands;
+
+@end
+
+UInt32 const VoiceCommandIdMin = 1900000000;
+
+@implementation SDLVoiceCommandManager
+
+- (instancetype)init {
+ self = [super init];
+ if (!self) { return nil; }
+
+ _lastVoiceCommandId = VoiceCommandIdMin;
+ _voiceCommands = @[];
+ _oldVoiceCommands = @[];
+
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_hmiStatusNotification:) name:SDLDidChangeHMIStatusNotification object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_commandNotification:) name:SDLDidReceiveCommandNotification object:nil];
+
+ return self;
+}
+
+- (instancetype)initWithConnectionManager:(id<SDLConnectionManagerType>)connectionManager {
+ self = [self init];
+ if (!self) { return nil; }
+
+ _connectionManager = connectionManager;
+
+ return self;
+}
+
+- (void)stop {
+ _lastVoiceCommandId = VoiceCommandIdMin;
+ _voiceCommands = @[];
+ _oldVoiceCommands = @[];
+
+ _waitingOnHMIUpdate = NO;
+ _currentHMILevel = nil;
+ _inProgressUpdate = nil;
+ _hasQueuedUpdate = NO;
+}
+
+#pragma mark - Setters
+
+- (void)setVoiceCommands:(NSArray<SDLVoiceCommand *> *)voiceCommands {
+ if (self.currentHMILevel == nil || [self.currentHMILevel isEqualToEnum:SDLHMILevelNone]) {
+ self.waitingOnHMIUpdate = YES;
+ return;
+ }
+
+ self.waitingOnHMIUpdate = NO;
+
+ // Set the ids
+ self.lastVoiceCommandId = VoiceCommandIdMin;
+ [self sdl_updateIdsOnVoiceCommands:voiceCommands];
+
+ _oldVoiceCommands = _voiceCommands;
+ _voiceCommands = voiceCommands;
+
+ [self sdl_updateWithCompletionHandler:nil];
+}
+
+#pragma mark - Updating System
+
+- (void)sdl_updateWithCompletionHandler:(nullable SDLMenuUpdateCompletionHandler)completionHandler {
+ if (self.currentHMILevel == nil || [self.currentHMILevel isEqualToEnum:SDLHMILevelNone]) {
+ self.waitingOnHMIUpdate = YES;
+ return;
+ }
+
+ if (self.inProgressUpdate != nil) {
+ // There's an in progress update, we need to put this on hold
+ self.hasQueuedUpdate = YES;
+ return;
+ }
+
+ __weak typeof(self) weakself = self;
+ [self sdl_sendDeleteCurrentVoiceCommands:^(NSError * _Nullable error) {
+ [weakself sdl_sendCurrentVoiceCommands:^(NSError * _Nullable error) {
+ weakself.inProgressUpdate = nil;
+
+ if (completionHandler != nil) {
+ completionHandler(error);
+ }
+
+ if (weakself.hasQueuedUpdate) {
+ [weakself sdl_updateWithCompletionHandler:nil];
+ weakself.hasQueuedUpdate = NO;
+ }
+ }];
+ }];
+}
+
+#pragma mark Delete Old Menu Items
+
+- (void)sdl_sendDeleteCurrentVoiceCommands:(SDLMenuUpdateCompletionHandler)completionHandler {
+ if (self.oldVoiceCommands.count == 0) {
+ completionHandler(nil);
+
+ return;
+ }
+
+ NSArray<SDLRPCRequest *> *deleteVoiceCommands = [self sdl_deleteCommandsForVoiceCommands:self.oldVoiceCommands];
+ self.oldVoiceCommands = @[];
+ [self.connectionManager sendRequests:deleteVoiceCommands progressHandler:nil completionHandler:^(BOOL success) {
+ if (!success) {
+ SDLLogE(@"Error deleting old voice commands");
+ } else {
+ SDLLogD(@"Finished deleting old voice commands");
+ }
+
+ completionHandler(nil);
+ }];
+}
+
+#pragma mark Send New Menu Items
+
+- (void)sdl_sendCurrentVoiceCommands:(SDLMenuUpdateCompletionHandler)completionHandler {
+ if (self.voiceCommands.count == 0) {
+ SDLLogD(@"No voice commands to send");
+ completionHandler(nil);
+
+ return;
+ }
+
+ self.inProgressUpdate = [self sdl_addCommandsForVoiceCommands:self.voiceCommands];
+
+ __block NSMutableDictionary<SDLRPCRequest *, NSError *> *errors = [NSMutableDictionary dictionary];
+ __weak typeof(self) weakSelf = self;
+ [self.connectionManager sendRequests:self.inProgressUpdate progressHandler:^(__kindof SDLRPCRequest * _Nonnull request, __kindof SDLRPCResponse * _Nullable response, NSError * _Nullable error, float percentComplete) {
+ if (error != nil) {
+ errors[request] = error;
+ }
+ } completionHandler:^(BOOL success) {
+ if (!success) {
+ SDLLogE(@"Failed to send main menu commands: %@", errors);
+ completionHandler([NSError sdl_menuManager_failedToUpdateWithDictionary:errors]);
+ return;
+ }
+
+ SDLLogD(@"Finished updating voice commands");
+ weakSelf.oldVoiceCommands = weakSelf.voiceCommands;
+ completionHandler(nil);
+ }];
+}
+
+#pragma mark - Helpers
+
+#pragma mark IDs
+
+- (void)sdl_updateIdsOnVoiceCommands:(NSArray<SDLVoiceCommand *> *)voiceCommands {
+ for (SDLVoiceCommand *voiceCommand in voiceCommands) {
+ voiceCommand.commandId = self.lastVoiceCommandId++;
+ }
+}
+
+#pragma mark Deletes
+
+- (NSArray<SDLDeleteCommand *> *)sdl_deleteCommandsForVoiceCommands:(NSArray<SDLVoiceCommand *> *)voiceCommands {
+ NSMutableArray<SDLDeleteCommand *> *mutableDeletes = [NSMutableArray array];
+ for (SDLVoiceCommand *command in voiceCommands) {
+ SDLDeleteCommand *delete = [[SDLDeleteCommand alloc] initWithId:command.commandId];
+ [mutableDeletes addObject:delete];
+ }
+
+ return [mutableDeletes copy];
+}
+
+#pragma mark Commands
+
+- (NSArray<SDLAddCommand *> *)sdl_addCommandsForVoiceCommands:(NSArray<SDLVoiceCommand *> *)voiceCommands {
+ NSMutableArray<SDLAddCommand *> *mutableCommands = [NSMutableArray array];
+ for (SDLVoiceCommand *command in voiceCommands) {
+ [mutableCommands addObject:[self sdl_commandForVoiceCommand:command]];
+ }
+
+ return [mutableCommands copy];
+}
+
+- (SDLAddCommand *)sdl_commandForVoiceCommand:(SDLVoiceCommand *)voiceCommand {
+ SDLAddCommand *command = [[SDLAddCommand alloc] init];
+ command.vrCommands = voiceCommand.voiceCommands;
+ command.cmdID = @(voiceCommand.commandId);
+
+ return command;
+}
+
+#pragma mark - Observers
+
+- (void)sdl_commandNotification:(SDLRPCNotificationNotification *)notification {
+ SDLOnCommand *onCommand = (SDLOnCommand *)notification.notification;
+
+ for (SDLVoiceCommand *voiceCommand in self.voiceCommands) {
+ if (onCommand.cmdID.unsignedIntegerValue != voiceCommand.commandId) { continue; }
+
+ voiceCommand.handler();
+ break;
+ }
+}
+
+- (void)sdl_hmiStatusNotification:(SDLRPCNotificationNotification *)notification {
+ SDLOnHMIStatus *hmiStatus = (SDLOnHMIStatus *)notification.notification;
+ SDLHMILevel oldHMILevel = self.currentHMILevel;
+ self.currentHMILevel = hmiStatus.hmiLevel;
+
+ // Auto-send an updated show if we were in NONE and now we are not
+ if ([oldHMILevel isEqualToEnum:SDLHMILevelNone] && ![self.currentHMILevel isEqualToEnum:SDLHMILevelNone]) {
+ if (self.waitingOnHMIUpdate) {
+ [self setVoiceCommands:_voiceCommands];
+ } else {
+ [self sdl_updateWithCompletionHandler:nil];
+ }
+ }
+}
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SmartDeviceLink.h b/SmartDeviceLink/SmartDeviceLink.h
index 339f23910..a6a50289e 100644
--- a/SmartDeviceLink/SmartDeviceLink.h
+++ b/SmartDeviceLink/SmartDeviceLink.h
@@ -9,29 +9,6 @@ FOUNDATION_EXPORT double SmartDeviceLinkVersionNumber;
//! Project version string for SmartDeviceLink.
FOUNDATION_EXPORT const unsigned char SmartDeviceLinkVersionString[];
-/***** Proxy *****/
-#import "SDLProxy.h"
-#import "SDLProxyFactory.h"
-#import "SDLProxyListener.h"
-
-/***** Transport *****/
-#import "SDLAbstractTransport.h"
-#import "SDLIAPSessionDelegate.h"
-#import "SDLIAPTransport.h"
-#import "SDLTCPTransport.h"
-#import "SDLTransportDelegate.h"
-
-/***** Protocol *****/
-#import "SDLAbstractProtocol.h"
-#import "SDLProtocol.h"
-#import "SDLProtocolListener.h"
-
-// Header
-#import "SDLProtocolHeader.h"
-
-// Message
-#import "SDLProtocolMessage.h"
-
/***** RPCs *****/
// Superclasses
#import "SDLEnum.h"
@@ -343,15 +320,22 @@ FOUNDATION_EXPORT const unsigned char SmartDeviceLinkVersionString[];
#import "SDLManager.h"
#import "SDLManagerDelegate.h"
+// System Capabilities
+#import "SDLSystemCapabilityManager.h"
+
// Permissions
#import "SDLPermissionConstants.h"
#import "SDLPermissionManager.h"
-// Show
+// Screen
#import "SDLScreenManager.h"
#import "SDLSoftButtonObject.h"
#import "SDLSoftButtonState.h"
+#import "SDLMenuManager.h"
+#import "SDLMenuCell.h"
+#import "SDLVoiceCommand.h"
+
// Touches
#import "SDLPinchGesture.h"
#import "SDLTouch.h"
diff --git a/SmartDeviceLinkSwift/SDLLog.swift b/SmartDeviceLinkSwift/SDLLog.swift
index d2391a0e4..c7bc4b070 100644
--- a/SmartDeviceLinkSwift/SDLLog.swift
+++ b/SmartDeviceLinkSwift/SDLLog.swift
@@ -27,7 +27,7 @@ public class SDLLog {
/// - function: The function the log is coming from, you should probably leave this as the default.
/// - line: The line the log is coming from, you should probably leave this as the default.
public class func v(_ message: @autoclosure () -> Any, _ file: String = #file, _ function: String = #function, _ line: Int = #line) {
- SDLLogManager.log(with: .verbose, timestamp: Date(), file: file, functionName: function, line: line, queue: logQueue(), message: "\(message())")
+ SDLLogManager.log(with: .verbose, timestamp: Date(), file: stripFileName(file), functionName: function, line: line, queue: logQueue(), message: "\(message())")
}
/// Log a debug message through SDL's custom logging framework.
@@ -38,7 +38,7 @@ public class SDLLog {
/// - function: The function the log is coming from, you should probably leave this as the default.
/// - line: The line the log is coming from, you should probably leave this as the default.
public class func d(_ message: @autoclosure () -> Any, _ file: String = #file, _ function: String = #function, _ line: Int = #line) {
- SDLLogManager.log(with: .debug, timestamp: Date(), file: file, functionName: function, line: line, queue: logQueue(), message: "\(message())")
+ SDLLogManager.log(with: .debug, timestamp: Date(), file: stripFileName(file), functionName: function, line: line, queue: logQueue(), message: "\(message())")
}
/// Log a warning message through SDL's custom logging framework.
@@ -49,7 +49,7 @@ public class SDLLog {
/// - function: The function the log is coming from, you should probably leave this as the default.
/// - line: The line the log is coming from, you should probably leave this as the default.
public class func w(_ message: @autoclosure () -> Any, _ file: String = #file, _ function: String = #function, _ line: Int = #line) {
- SDLLogManager.log(with: .warning, timestamp: Date(), file: file, functionName: function, line: line, queue: logQueue(), message: "\(message())")
+ SDLLogManager.log(with: .warning, timestamp: Date(), file: stripFileName(file), functionName: function, line: line, queue: logQueue(), message: "\(message())")
}
/// Log an error message through SDL's custom logging framework.
@@ -60,7 +60,12 @@ public class SDLLog {
/// - function: The function the log is coming from, you should probably leave this as the default.
/// - line: The line the log is coming from, you should probably leave this as the default.
public class func e(_ message: @autoclosure () -> Any, _ file: String = #file, _ function: String = #function, _ line: Int = #line) {
- SDLLogManager.log(with: .error, timestamp: Date(), file: file, functionName: function, line: line, queue: logQueue(), message: "\(message())")
+ SDLLogManager.log(with: .error, timestamp: Date(), file: stripFileName(file), functionName: function, line: line, queue: logQueue(), message: "\(message())")
+ }
+
+ class func stripFileName(_ file: String) -> String {
+ let url = URL(fileURLWithPath: file)
+ return url.deletingPathExtension().lastPathComponent
}
}
@@ -72,7 +77,7 @@ public class SDLLog {
/// - function: The function the log is coming from, you should probably leave this as the default.
/// - line: The line the log is coming from, you should probably leave this as the default.
public func SDLV(_ message: @autoclosure () -> Any, _ file: String = #file, _ function: String = #function, _ line: Int = #line) {
- SDLLogManager.log(with: .verbose, timestamp: Date(), file: file, functionName: function, line: line, queue: logQueue(), message: "\(message())")
+ SDLLogManager.log(with: .verbose, timestamp: Date(), file: SDLLog.stripFileName(file), functionName: function, line: line, queue: logQueue(), message: "\(message())")
}
/// Log a debug message through SDL's custom logging framework.
@@ -83,7 +88,7 @@ public func SDLV(_ message: @autoclosure () -> Any, _ file: String = #file, _ fu
/// - function: The function the log is coming from, you should probably leave this as the default.
/// - line: The line the log is coming from, you should probably leave this as the default.
public func SDLD(_ message: @autoclosure () -> Any, _ file: String = #file, _ function: String = #function, _ line: Int = #line) {
- SDLLogManager.log(with: .debug, timestamp: Date(), file: file, functionName: function, line: line, queue: logQueue(), message: "\(message())")
+ SDLLogManager.log(with: .debug, timestamp: Date(), file: SDLLog.stripFileName(file), functionName: function, line: line, queue: logQueue(), message: "\(message())")
}
/// Log a warning message through SDL's custom logging framework.
@@ -94,7 +99,7 @@ public func SDLD(_ message: @autoclosure () -> Any, _ file: String = #file, _ fu
/// - function: The function the log is coming from, you should probably leave this as the default.
/// - line: The line the log is coming from, you should probably leave this as the default.
public func SDLW(_ message: @autoclosure () -> Any, _ file: String = #file, _ function: String = #function, _ line: Int = #line) {
- SDLLogManager.log(with: .warning, timestamp: Date(), file: file, functionName: function, line: line, queue: logQueue(), message: "\(message())")
+ SDLLogManager.log(with: .warning, timestamp: Date(), file: SDLLog.stripFileName(file), functionName: function, line: line, queue: logQueue(), message: "\(message())")
}
/// Log an error message through SDL's custom logging framework.
@@ -105,7 +110,7 @@ public func SDLW(_ message: @autoclosure () -> Any, _ file: String = #file, _ fu
/// - function: The function the log is coming from, you should probably leave this as the default.
/// - line: The line the log is coming from, you should probably leave this as the default.
public func SDLE(_ message: @autoclosure () -> Any, _ file: String = #file, _ function: String = #function, _ line: Int = #line) {
- SDLLogManager.log(with: .error, timestamp: Date(), file: file, functionName: function, line: line, queue: logQueue(), message: "\(message())")
+ SDLLogManager.log(with: .error, timestamp: Date(), file: SDLLog.stripFileName(file), functionName: function, line: line, queue: logQueue(), message: "\(message())")
}
private func logQueue() -> String {
diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleManagerSpec.m
index 1ba37a291..acdcb833c 100644
--- a/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleManagerSpec.m
+++ b/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleManagerSpec.m
@@ -19,7 +19,6 @@
#import "SDLOnHMIStatus.h"
#import "SDLPermissionManager.h"
#import "SDLProxy.h"
-#import "SDLProxyFactory.h"
#import "SDLProtocol.h"
#import "SDLRegisterAppInterface.h"
#import "SDLRegisterAppInterfaceResponse.h"
@@ -28,7 +27,9 @@
#import "SDLStateMachine.h"
#import "SDLStreamingMediaConfiguration.h"
#import "SDLStreamingMediaManager.h"
+#import "SDLSystemCapabilityManager.h"
#import "SDLTextAlignment.h"
+#import "SDLTTSChunk.h"
#import "SDLUnregisterAppInterface.h"
#import "SDLUnregisterAppInterfaceResponse.h"
@@ -61,17 +62,16 @@ describe(@"a lifecycle manager", ^{
__block SDLLifecycleManager *testManager = nil;
__block SDLConfiguration *testConfig = nil;
- __block id managerDelegateMock = OCMProtocolMock(@protocol(SDLManagerDelegate));
- __block id protocolMock = OCMClassMock([SDLAbstractProtocol class]);
- __block id proxyBuilderClassMock = OCMStrictClassMock([SDLProxyFactory class]);
+ __block id protocolMock = OCMClassMock([SDLProtocol class]);
__block id proxyMock = OCMClassMock([SDLProxy class]);
__block id lockScreenManagerMock = OCMClassMock([SDLLockScreenManager class]);
__block id fileManagerMock = OCMClassMock([SDLFileManager class]);
__block id permissionManagerMock = OCMClassMock([SDLPermissionManager class]);
__block id streamingManagerMock = OCMClassMock([SDLStreamingMediaManager class]);
+ __block id systemCapabilityMock = OCMClassMock([SDLSystemCapabilityManager class]);
beforeEach(^{
- OCMStub([proxyBuilderClassMock buildSDLProxyWithListener:[OCMArg any]]).andReturn(proxyMock);
+ OCMStub([proxyMock iapProxyWithListener:[OCMArg any]]).andReturn(proxyMock);
OCMStub([(SDLProxy*)proxyMock protocol]).andReturn(protocolMock);
SDLLifecycleConfiguration *testLifecycleConfig = [SDLLifecycleConfiguration defaultConfigurationWithAppName:@"Test App" appId:@"Test Id"];
@@ -81,16 +81,17 @@ describe(@"a lifecycle manager", ^{
testConfig = [SDLConfiguration configurationWithLifecycle:testLifecycleConfig lockScreen:[SDLLockScreenConfiguration disabledConfiguration] logging:[SDLLogConfiguration defaultConfiguration] streamingMedia:[SDLStreamingMediaConfiguration insecureConfiguration]];
testConfig.lifecycleConfig.languagesSupported = @[SDLLanguageEnUs, SDLLanguageEnGb];
testConfig.lifecycleConfig.language = SDLLanguageEnUs;
- testManager = [[SDLLifecycleManager alloc] initWithConfiguration:testConfig delegate:managerDelegateMock];
+ testManager = [[SDLLifecycleManager alloc] initWithConfiguration:testConfig delegate:OCMProtocolMock(@protocol(SDLManagerDelegate))];
testManager.lockScreenManager = lockScreenManagerMock;
testManager.fileManager = fileManagerMock;
testManager.permissionManager = permissionManagerMock;
testManager.streamManager = streamingManagerMock;
+ testManager.systemCapabilityManager = systemCapabilityMock;
});
- xit(@"should initialize properties", ^{
+ it(@"should initialize properties", ^{
expect(testManager.configuration).toNot(equal(testConfig)); // This is copied
- expect(testManager.delegate).to(equal(managerDelegateMock)); // TODO: Broken on OCMock 3.3.1 & Swift 3 Quick / Nimble
+ expect(testManager.delegate).toNot(beNil());
expect(testManager.lifecycleState).to(match(SDLLifecycleStateStopped));
expect(@(testManager.lastCorrelationId)).to(equal(@0));
expect(testManager.fileManager).toNot(beNil());
@@ -102,6 +103,7 @@ describe(@"a lifecycle manager", ^{
expect(testManager.notificationDispatcher).toNot(beNil());
expect(testManager.responseDispatcher).toNot(beNil());
expect(testManager.streamManager).toNot(beNil());
+ expect(testManager.systemCapabilityManager).toNot(beNil());
expect(@([testManager conformsToProtocol:@protocol(SDLConnectionManagerType)])).to(equal(@YES));
});
@@ -344,50 +346,58 @@ describe(@"a lifecycle manager", ^{
});
});
- context(@"when the register response is of another language", ^{
- xit(@"should call config update delegate method before saying it's ready", ^{
- SDLRegisterAppInterfaceResponse *response = [[SDLRegisterAppInterfaceResponse alloc] init];
- response.success = @YES;
- response.resultCode = SDLResultWrongLanguage;
- response.info = @"Language mismatch";
- response.language = SDLLanguageEnGb;
-
- testManager.registerResponse = response;
-
- SDLLifecycleConfigurationUpdate *update = [[SDLLifecycleConfigurationUpdate alloc] initWithAppName:@"EnGb" shortAppName:nil ttsName:nil voiceRecognitionCommandNames:nil];
-
- OCMStub([managerDelegateMock managerShouldUpdateLifecycleToLanguage:[OCMArg any]]).andReturn(update);
- expect(testManager.configuration.lifecycleConfig.language).to(be(SDLLanguageEnUs));
-
- [testManager.lifecycleStateMachine setToState:SDLLifecycleStateRegistered fromOldState:SDLLifecycleStateConnected callEnterTransition:YES];
+ context(@"when the register response returns different language than the one passed with the lifecycle configuration", ^{
+ beforeEach(^{
+ expect(testManager.configuration.lifecycleConfig.appName).to(equal(testConfig.lifecycleConfig.appName));
+ expect(testManager.configuration.lifecycleConfig.shortAppName).to(equal(testConfig.lifecycleConfig.shortAppName));
+ expect(testManager.configuration.lifecycleConfig.ttsName).to(beNil());
+ expect(testManager.configuration.lifecycleConfig.language).to(equal(testConfig.lifecycleConfig.language));
+ expect(testManager.configuration.lifecycleConfig.languagesSupported).to(equal(testConfig.lifecycleConfig.languagesSupported));
+ });
+
+ it(@"should should update the configuration when the app supports the head unit language", ^{
+ SDLRegisterAppInterfaceResponse *registerAppInterfaceResponse = [[SDLRegisterAppInterfaceResponse alloc] init];
+ registerAppInterfaceResponse.success = @YES;
+ registerAppInterfaceResponse.resultCode = SDLResultWrongLanguage;
+ registerAppInterfaceResponse.info = @"Language mismatch";
+ registerAppInterfaceResponse.language = SDLLanguageEnGb;
+ testManager.registerResponse = registerAppInterfaceResponse;
+
+ SDLLifecycleConfigurationUpdate *update = [[SDLLifecycleConfigurationUpdate alloc] initWithAppName:@"EnGb" shortAppName:@"E" ttsName:[SDLTTSChunk textChunksFromString:@"EnGb ttsName"] voiceRecognitionCommandNames:nil];
+ OCMStub([testManager.delegate managerShouldUpdateLifecycleToLanguage:[OCMArg any]]).andReturn(update);
- // TODO: testManager delgate broken on OCMock 3.3.1 & Swift 3 Quick / Nimble
- OCMVerify([managerDelegateMock managerShouldUpdateLifecycleToLanguage:[OCMArg any]]);
+ [testManager.lifecycleStateMachine setToState:SDLLifecycleStateUpdatingConfiguration fromOldState:SDLLifecycleStateRegistered callEnterTransition:YES];
+ // Transition to StateSettingUpManagers to prevent assert error from the lifecycle machine
+ [testManager.lifecycleStateMachine setToState:SDLLifecycleStateSettingUpManagers fromOldState:SDLLifecycleStateUpdatingConfiguration callEnterTransition:NO];
+
+ expect(testManager.configuration.lifecycleConfig.language).to(equal(SDLLanguageEnGb));
expect(testManager.configuration.lifecycleConfig.appName).to(equal(@"EnGb"));
- expect(testManager.configuration.lifecycleConfig.language).to(be(SDLLanguageEnGb));
+ expect(testManager.configuration.lifecycleConfig.shortAppName).to(equal(@"E"));
+ expect(testManager.configuration.lifecycleConfig.ttsName).to(equal([SDLTTSChunk textChunksFromString:@"EnGb ttsName"]));
+
+ OCMVerify([testManager.delegate managerShouldUpdateLifecycleToLanguage:[OCMArg any]]);
});
- });
-
- context(@"when the register response is of another not supported language", ^{
- xit(@"should not update configuration as language is not supported", ^{
- SDLRegisterAppInterfaceResponse *response = [[SDLRegisterAppInterfaceResponse alloc] init];
- response.success = @YES;
- response.resultCode = SDLResultWrongLanguage;
- response.info = @"Language mismatch";
- response.language = SDLLanguageDeDe;
-
- testManager.registerResponse = response;
-
- SDLLifecycleConfigurationUpdate *update = nil;
- // TODO: testManager delgate broken on OCMock 3.3.1 & Swift 3 Quick / Nimble
- OCMStub([managerDelegateMock managerShouldUpdateLifecycleToLanguage:[OCMArg any]]).andReturn(update);
- expect(testManager.configuration.lifecycleConfig.language).to(be(SDLLanguageEnUs));
-
- [testManager.lifecycleStateMachine setToState:SDLLifecycleStateRegistered fromOldState:SDLLifecycleStateConnected callEnterTransition:YES];
-
- OCMVerify([managerDelegateMock managerShouldUpdateLifecycleToLanguage:[OCMArg any]]);
- expect(testManager.configuration.lifecycleConfig.language).to(be(SDLLanguageEnUs));
+ it(@"should not update the configuration when the app does not support the head unit language", ^{
+ SDLRegisterAppInterfaceResponse *registerAppInterfaceResponse = [[SDLRegisterAppInterfaceResponse alloc] init];
+ registerAppInterfaceResponse.success = @YES;
+ registerAppInterfaceResponse.resultCode = SDLResultWrongLanguage;
+ registerAppInterfaceResponse.info = @"Language mismatch";
+ registerAppInterfaceResponse.language = SDLLanguageDeDe;
+ testManager.registerResponse = registerAppInterfaceResponse;
+
+ OCMStub([testManager.delegate managerShouldUpdateLifecycleToLanguage:[OCMArg any]]).andReturn(nil);
+
+ [testManager.lifecycleStateMachine setToState:SDLLifecycleStateUpdatingConfiguration fromOldState:SDLLifecycleStateRegistered callEnterTransition:YES];
+ // Transition to StateSettingUpManagers to prevent assert error from the lifecycle machine
+ [testManager.lifecycleStateMachine setToState:SDLLifecycleStateSettingUpManagers fromOldState:SDLLifecycleStateUpdatingConfiguration callEnterTransition:NO];
+
+ expect(testManager.configuration.lifecycleConfig.language).to(equal(SDLLanguageEnUs));
+ expect(testManager.configuration.lifecycleConfig.appName).to(equal(@"Test App"));
+ expect(testManager.configuration.lifecycleConfig.shortAppName).to(equal(@"Short Name"));
+ expect(testManager.configuration.lifecycleConfig.ttsName).to(beNil());
+
+ OCMVerify([testManager.delegate managerShouldUpdateLifecycleToLanguage:[OCMArg any]]);
});
});
});
@@ -396,11 +406,11 @@ describe(@"a lifecycle manager", ^{
beforeEach(^{
[testManager.lifecycleStateMachine setToState:SDLLifecycleStateReady fromOldState:nil callEnterTransition:NO];
});
-
+
it(@"can send an RPC", ^{
SDLShow *testShow = [[SDLShow alloc] initWithMainField1:@"test" mainField2:nil alignment:nil];
[testManager sendRequest:testShow];
-
+
OCMVerify([proxyMock sendRPC:[OCMArg isKindOfClass:[SDLShow class]]]);
});
@@ -454,7 +464,9 @@ describe(@"a lifecycle manager", ^{
});
it(@"should call the delegate", ^{
- OCMVerify([managerDelegateMock hmiLevel:oldHMILevel didChangeToLevel:testHMILevel]);
+ // Since notifications are sent to SDLManagerDelegate observers on the main thread, force the block to execute manually on the main thread. If this is not done, the test case may fail.
+ [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.01]];
+ OCMVerify([testManager.delegate hmiLevel:[OCMArg any] didChangeToLevel:[OCMArg any]]);
});
});
});
@@ -482,7 +494,10 @@ describe(@"a lifecycle manager", ^{
});
it(@"should call the delegate", ^{
- OCMVerify([managerDelegateMock audioStreamingState:oldAudioStreamingState didChangeToState:testAudioStreamingState]);
+ // Since notifications are sent to SDLManagerDelegate observers on the main thread, force the block to execute manually on the main thread. If this is not done, the test case may fail.
+ [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.01]];
+
+ OCMVerify([testManager.delegate audioStreamingState:oldAudioStreamingState didChangeToState:testAudioStreamingState]);
});
});
});
@@ -491,7 +506,7 @@ describe(@"a lifecycle manager", ^{
__block SDLOnHMIStatus *testHMIStatus = nil;
__block SDLSystemContext testSystemContext = nil;
__block SDLSystemContext oldSystemContext = nil;
-
+
beforeEach(^{
oldSystemContext = testManager.systemContext;
testHMIStatus = [[SDLOnHMIStatus alloc] init];
@@ -499,6 +514,9 @@ describe(@"a lifecycle manager", ^{
context(@"a alert system context state", ^{
beforeEach(^{
+ expect(testManager.lifecycleStateMachine.currentState).to(equal(SDLLifecycleStateReady));
+ expect(testManager.systemContext).to(beNil());
+
testSystemContext = SDLSystemContextAlert;
testHMIStatus.systemContext = testSystemContext;
@@ -510,7 +528,13 @@ describe(@"a lifecycle manager", ^{
});
it(@"should call the delegate", ^{
- OCMVerify([managerDelegateMock systemContext:oldSystemContext didChangeToContext:testSystemContext]);
+ // Since notifications are sent to SDLManagerDelegate observers on the main thread, force the block to execute manually on the main thread. If this is not done, the test case may fail.
+ [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.01]];
+ OCMVerify([testManager.delegate systemContext:[OCMArg any] didChangeToContext:[OCMArg any]]);
+ });
+
+ afterEach(^{
+ expect(testManager.delegate).toNot(beNil());
});
});
});
diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLMenuCellSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLMenuCellSpec.m
new file mode 100644
index 000000000..b6b52f0a0
--- /dev/null
+++ b/SmartDeviceLinkTests/DevAPISpecs/SDLMenuCellSpec.m
@@ -0,0 +1,47 @@
+#import <Quick/Quick.h>
+#import <Nimble/Nimble.h>
+
+#import "SDLArtwork.h"
+#import "SDLMenuCell.h"
+
+QuickSpecBegin(SDLMenuCellSpec)
+
+describe(@"a menu cell", ^{
+ __block SDLMenuCell *testCell = nil;
+
+ describe(@"initializing", ^{
+ __block NSString *someTitle = nil;
+ __block SDLArtwork *someArtwork = nil;
+ __block NSArray<NSString *> *someVoiceCommands = nil;
+ __block NSArray<SDLMenuCell *> *someSubcells = nil;
+
+ beforeEach(^{
+ someTitle = @"Some Title";
+ someArtwork = [[SDLArtwork alloc] initWithData:[[NSData alloc] initWithBase64EncodedString:@"data" options:kNilOptions] name:@"Some artwork" fileExtension:@"png" persistent:NO];
+ someVoiceCommands = @[@"some command"];
+
+ SDLMenuCell *subcell = [[SDLMenuCell alloc] initWithTitle:@"Hello" icon:nil voiceCommands:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}];
+ someSubcells = @[subcell];
+ });
+
+ it(@"should initialize properly as a menu item", ^{
+ testCell = [[SDLMenuCell alloc] initWithTitle:someTitle icon:someArtwork voiceCommands:someVoiceCommands handler:^(SDLTriggerSource _Nonnull triggerSource) {}];
+
+ expect(testCell.title).to(equal(someTitle));
+ expect(testCell.icon).to(equal(someArtwork));
+ expect(testCell.voiceCommands).to(equal(someVoiceCommands));
+ expect(testCell.subCells).to(beNil());
+ });
+
+ it(@"should initialize properly as a submenu item", ^{
+ testCell = [[SDLMenuCell alloc] initWithTitle:someTitle subCells:someSubcells];
+
+ expect(testCell.title).to(equal(someTitle));
+ expect(testCell.icon).to(beNil());
+ expect(testCell.voiceCommands).to(beNil());
+ expect(testCell.subCells).to(equal(someSubcells));
+ });
+ });
+});
+
+QuickSpecEnd
diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLMenuManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLMenuManagerSpec.m
new file mode 100644
index 000000000..a0c078d40
--- /dev/null
+++ b/SmartDeviceLinkTests/DevAPISpecs/SDLMenuManagerSpec.m
@@ -0,0 +1,340 @@
+#import <Quick/Quick.h>
+#import <Nimble/Nimble.h>
+#import <OCMock/OCMock.h>
+
+#import "SDLAddCommand.h"
+#import "SDLAddSubMenu.h"
+#import "SDLDeleteCommand.h"
+#import "SDLDisplayCapabilities.h"
+#import "SDLFileManager.h"
+#import "SDLHMILevel.h"
+#import "SDLImage.h"
+#import "SDLImageField.h"
+#import "SDLImageFieldName.h"
+#import "SDLMenuCell.h"
+#import "SDLMenuManager.h"
+#import "SDLOnCommand.h"
+#import "SDLOnHMIStatus.h"
+#import "SDLRPCNotificationNotification.h"
+#import "SDLSystemContext.h"
+#import "TestConnectionManager.h"
+
+@interface SDLMenuCell()
+
+@property (assign, nonatomic) UInt32 parentCellId;
+@property (assign, nonatomic) UInt32 cellId;
+
+@end
+
+@interface SDLMenuManager()
+
+@property (weak, nonatomic) id<SDLConnectionManagerType> connectionManager;
+@property (weak, nonatomic) SDLFileManager *fileManager;
+
+@property (copy, nonatomic, nullable) SDLHMILevel currentHMILevel;
+@property (copy, nonatomic, nullable) SDLSystemContext currentSystemContext;
+@property (strong, nonatomic, nullable) SDLDisplayCapabilities *displayCapabilities;
+
+@property (strong, nonatomic, nullable) NSArray<SDLRPCRequest *> *inProgressUpdate;
+@property (assign, nonatomic) BOOL hasQueuedUpdate;
+@property (assign, nonatomic) BOOL waitingOnHMIUpdate;
+@property (copy, nonatomic) NSArray<SDLMenuCell *> *waitingUpdateMenuCells;
+
+@property (assign, nonatomic) UInt32 lastMenuId;
+@property (copy, nonatomic) NSArray<SDLMenuCell *> *oldMenuCells;
+
+@end
+
+QuickSpecBegin(SDLMenuManagerSpec)
+
+describe(@"menu manager", ^{
+ __block SDLMenuManager *testManager = nil;
+ __block TestConnectionManager *mockConnectionManager = nil;
+ __block SDLFileManager *mockFileManager = nil;
+
+ __block SDLArtwork *testArtwork = [[SDLArtwork alloc] initWithData:[@"Test data" dataUsingEncoding:NSUTF8StringEncoding] name:@"some artwork name" fileExtension:@"png" persistent:NO];
+
+ __block SDLMenuCell *textOnlyCell = [[SDLMenuCell alloc] initWithTitle:@"Test 1" icon:nil voiceCommands:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}];
+ __block SDLMenuCell *textAndImageCell = [[SDLMenuCell alloc] initWithTitle:@"Test 2" icon:testArtwork voiceCommands:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}];
+ __block SDLMenuCell *submenuCell = [[SDLMenuCell alloc] initWithTitle:@"Test 3" subCells:@[textOnlyCell, textAndImageCell]];
+
+ beforeEach(^{
+ mockConnectionManager = [[TestConnectionManager alloc] init];
+ mockFileManager = OCMClassMock([SDLFileManager class]);
+ testManager = [[SDLMenuManager alloc] initWithConnectionManager:mockConnectionManager fileManager:mockFileManager];
+ });
+
+ it(@"should instantiate correctly", ^{
+ expect(testManager.menuCells).to(beEmpty());
+ expect(testManager.connectionManager).to(equal(mockConnectionManager));
+ expect(testManager.fileManager).to(equal(mockFileManager));
+ expect(testManager.currentHMILevel).to(beNil());
+ expect(testManager.displayCapabilities).to(beNil());
+ expect(testManager.inProgressUpdate).to(beNil());
+ expect(testManager.hasQueuedUpdate).to(beFalse());
+ expect(testManager.waitingOnHMIUpdate).to(beFalse());
+ expect(testManager.lastMenuId).to(equal(1));
+ expect(testManager.oldMenuCells).to(beEmpty());
+ expect(testManager.waitingUpdateMenuCells).to(beNil());
+ });
+
+ describe(@"updating menu cells before HMI is ready", ^{
+ context(@"when in HMI NONE", ^{
+ beforeEach(^{
+ testManager.currentHMILevel = SDLHMILevelNone;
+ testManager.menuCells = @[textOnlyCell];
+ });
+
+ it(@"should not update", ^{
+ expect(mockConnectionManager.receivedRequests).to(beEmpty());
+ });
+
+ describe(@"when entering the foreground", ^{
+ beforeEach(^{
+ SDLOnHMIStatus *onHMIStatus = [[SDLOnHMIStatus alloc] init];
+ onHMIStatus.hmiLevel = SDLHMILevelFull;
+ onHMIStatus.systemContext = SDLSystemContextMain;
+
+ SDLRPCNotificationNotification *testSystemContextNotification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangeHMIStatusNotification object:nil rpcNotification:onHMIStatus];
+ [[NSNotificationCenter defaultCenter] postNotification:testSystemContextNotification];
+ });
+
+ it(@"should update", ^{
+ expect(mockConnectionManager.receivedRequests).toNot(beEmpty());
+ });
+ });
+ });
+
+ context(@"when no HMI level has been received", ^{
+ beforeEach(^{
+ testManager.currentHMILevel = nil;
+ testManager.menuCells = @[textOnlyCell];
+ });
+
+ it(@"should not update", ^{
+ expect(mockConnectionManager.receivedRequests).to(beEmpty());
+ });
+ });
+
+ context(@"when in the menu", ^{
+ beforeEach(^{
+ testManager.currentHMILevel = SDLHMILevelFull;
+ testManager.currentSystemContext = SDLSystemContextMenu;
+ testManager.menuCells = @[textOnlyCell];
+ });
+
+ it(@"should not update", ^{
+ expect(mockConnectionManager.receivedRequests).to(beEmpty());
+ });
+
+ describe(@"when exiting the menu", ^{
+ beforeEach(^{
+ SDLOnHMIStatus *onHMIStatus = [[SDLOnHMIStatus alloc] init];
+ onHMIStatus.hmiLevel = SDLHMILevelFull;
+ onHMIStatus.systemContext = SDLSystemContextMain;
+
+ SDLRPCNotificationNotification *testSystemContextNotification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangeHMIStatusNotification object:nil rpcNotification:onHMIStatus];
+ [[NSNotificationCenter defaultCenter] postNotification:testSystemContextNotification];
+ });
+
+ it(@"should update", ^{
+ expect(mockConnectionManager.receivedRequests).toNot(beEmpty());
+ });
+ });
+ });
+ });
+
+ describe(@"updating menu cells", ^{
+ beforeEach(^{
+ testManager.currentHMILevel = SDLHMILevelFull;
+ testManager.currentSystemContext = SDLSystemContextMain;
+
+ testManager.displayCapabilities = [[SDLDisplayCapabilities alloc] init];
+ SDLImageField *commandIconField = [[SDLImageField alloc] init];
+ commandIconField.name = SDLImageFieldNameCommandIcon;
+ testManager.displayCapabilities.imageFields = @[commandIconField];
+ testManager.displayCapabilities.graphicSupported = @YES;
+ });
+
+ it(@"should fail with a duplicate title", ^{
+ testManager.menuCells = @[textOnlyCell, textOnlyCell];
+
+ expect(testManager.menuCells).to(beEmpty());
+ });
+
+ it(@"should properly update a text cell", ^{
+ testManager.menuCells = @[textOnlyCell];
+
+ NSPredicate *deleteCommandPredicate = [NSPredicate predicateWithFormat:@"self isMemberOfClass: %@", [SDLDeleteCommand class]];
+ NSArray *deletes = [[mockConnectionManager.receivedRequests copy] filteredArrayUsingPredicate:deleteCommandPredicate];
+ expect(deletes).to(beEmpty());
+
+ NSPredicate *addCommandPredicate = [NSPredicate predicateWithFormat:@"self isMemberOfClass: %@", [SDLAddCommand class]];
+ NSArray *add = [[mockConnectionManager.receivedRequests copy] filteredArrayUsingPredicate:addCommandPredicate];
+ expect(add).toNot(beEmpty());
+ });
+
+ describe(@"updating with an image", ^{
+ context(@"when the image is already on the head unit", ^{
+ beforeEach(^{
+ OCMStub([mockFileManager hasUploadedFile:[OCMArg isNotNil]]).andReturn(YES);
+ });
+
+ it(@"should properly update an image cell", ^{
+ testManager.menuCells = @[textAndImageCell];
+
+ NSPredicate *addCommandPredicate = [NSPredicate predicateWithFormat:@"self isMemberOfClass: %@", [SDLAddCommand class]];
+ NSArray *add = [[mockConnectionManager.receivedRequests copy] filteredArrayUsingPredicate:addCommandPredicate];
+ SDLAddCommand *sentCommand = add.firstObject;
+
+ expect(add).to(haveCount(1));
+ expect(sentCommand.cmdIcon.value).to(equal(testArtwork.name));
+ });
+ });
+
+ context(@"when the image is not on the head unit", ^{
+ beforeEach(^{
+ OCMStub([mockFileManager hasUploadedFile:[OCMArg isNotNil]]).andReturn(NO);
+ });
+
+ it(@"should immediately attempt to update without the image", ^{
+ testManager.menuCells = @[textAndImageCell];
+
+ NSPredicate *addCommandPredicate = [NSPredicate predicateWithFormat:@"self isMemberOfClass: %@", [SDLAddCommand class]];
+ NSArray *add = [[mockConnectionManager.receivedRequests copy] filteredArrayUsingPredicate:addCommandPredicate];
+ SDLAddCommand *sentCommand = add.firstObject;
+
+ expect(add).to(haveCount(1));
+ expect(sentCommand.cmdIcon.value).to(beNil());
+ });
+ });
+ });
+
+ it(@"should properly update with subcells", ^{
+ testManager.menuCells = @[submenuCell];
+
+ NSPredicate *addCommandPredicate = [NSPredicate predicateWithFormat:@"self isMemberOfClass: %@", [SDLAddCommand class]];
+ NSArray *adds = [[mockConnectionManager.receivedRequests copy] filteredArrayUsingPredicate:addCommandPredicate];
+
+ NSPredicate *submenuCommandPredicate = [NSPredicate predicateWithFormat:@"self isMemberOfClass: %@", [SDLAddSubMenu class]];
+ NSArray *submenus = [[mockConnectionManager.receivedRequests copy] filteredArrayUsingPredicate:submenuCommandPredicate];
+
+ expect(adds).to(haveCount(2));
+ expect(submenus).to(haveCount(1));
+ });
+
+ context(@"when a menu already exists", ^{
+ beforeEach(^{
+ testManager.menuCells = @[textOnlyCell];
+ });
+
+ it(@"should send deletes first", ^{
+ testManager.menuCells = @[textAndImageCell];
+
+ NSPredicate *deleteCommandPredicate = [NSPredicate predicateWithFormat:@"self isMemberOfClass: %@", [SDLDeleteCommand class]];
+ NSArray *deletes = [[mockConnectionManager.receivedRequests copy] filteredArrayUsingPredicate:deleteCommandPredicate];
+
+ NSPredicate *addCommandPredicate = [NSPredicate predicateWithFormat:@"self isMemberOfClass: %@", [SDLAddCommand class]];
+ NSArray *adds = [[mockConnectionManager.receivedRequests copy] filteredArrayUsingPredicate:addCommandPredicate];
+
+ expect(deletes).to(haveCount(1));
+ expect(adds).to(haveCount(2));
+ });
+ });
+ });
+
+ describe(@"running menu cell handlers", ^{
+ __block SDLMenuCell *cellWithHandler = nil;
+ __block BOOL cellCalled = NO;
+ __block SDLTriggerSource testTriggerSource = nil;
+
+ beforeEach(^{
+ testManager.currentHMILevel = SDLHMILevelFull;
+ testManager.currentSystemContext = SDLSystemContextMain;
+
+ testManager.displayCapabilities = [[SDLDisplayCapabilities alloc] init];
+ SDLImageField *commandIconField = [[SDLImageField alloc] init];
+ commandIconField.name = SDLImageFieldNameCommandIcon;
+ testManager.displayCapabilities.imageFields = @[commandIconField];
+ testManager.displayCapabilities.graphicSupported = @YES;
+
+ cellCalled = NO;
+ testTriggerSource = nil;
+ });
+
+ context(@"on a main menu cell", ^{
+ beforeEach(^{
+ cellWithHandler = [[SDLMenuCell alloc] initWithTitle:@"Hello" icon:nil voiceCommands:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {
+ cellCalled = YES;
+ testTriggerSource = triggerSource;
+ }];
+
+ testManager.menuCells = @[cellWithHandler];
+ });
+
+ it(@"should call the cell handler", ^{
+ SDLOnCommand *onCommand = [[SDLOnCommand alloc] init];
+ onCommand.cmdID = @1;
+ onCommand.triggerSource = SDLTriggerSourceMenu;
+
+ SDLRPCNotificationNotification *notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidReceiveCommandNotification object:nil rpcNotification:onCommand];
+ [[NSNotificationCenter defaultCenter] postNotification:notification];
+
+ expect(cellCalled).to(beTrue());
+ expect(testTriggerSource).to(equal(SDLTriggerSourceMenu));
+ });
+ });
+
+ context(@"on a submenu menu cell", ^{
+ beforeEach(^{
+ cellWithHandler = [[SDLMenuCell alloc] initWithTitle:@"Hello" icon:nil voiceCommands:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {
+ cellCalled = YES;
+ testTriggerSource = triggerSource;
+ }];
+
+ SDLMenuCell *submenuCell = [[SDLMenuCell alloc] initWithTitle:@"Submenu" subCells:@[cellWithHandler]];
+
+ testManager.menuCells = @[submenuCell];
+ });
+
+ it(@"should call the cell handler", ^{
+ SDLOnCommand *onCommand = [[SDLOnCommand alloc] init];
+ onCommand.cmdID = @2;
+ onCommand.triggerSource = SDLTriggerSourceMenu;
+
+ SDLRPCNotificationNotification *notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidReceiveCommandNotification object:nil rpcNotification:onCommand];
+ [[NSNotificationCenter defaultCenter] postNotification:notification];
+
+ expect(cellCalled).to(beTrue());
+ expect(testTriggerSource).to(equal(SDLTriggerSourceMenu));
+ });
+ });
+ });
+
+ context(@"On disconnects", ^{
+ beforeEach(^{
+ [testManager stop];
+ });
+
+ it(@"should reset correctly", ^{
+ expect(testManager.connectionManager).to(equal(mockConnectionManager));
+ expect(testManager.fileManager).to(equal(mockFileManager));
+
+ expect(testManager.menuCells).to(beEmpty());
+ expect(testManager.currentHMILevel).to(beNil());
+ expect(testManager.displayCapabilities).to(beNil());
+ expect(testManager.inProgressUpdate).to(beNil());
+ expect(testManager.hasQueuedUpdate).to(beFalse());
+ expect(testManager.waitingOnHMIUpdate).to(beFalse());
+ expect(testManager.lastMenuId).to(equal(1));
+ expect(testManager.oldMenuCells).to(beEmpty());
+ expect(testManager.waitingUpdateMenuCells).to(beEmpty());
+ });
+ });
+
+ afterEach(^{
+ testManager = nil;
+ });
+});
+
+QuickSpecEnd
diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLPermissionsManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLPermissionsManagerSpec.m
index dbf5e940f..efb3cc035 100644
--- a/SmartDeviceLinkTests/DevAPISpecs/SDLPermissionsManagerSpec.m
+++ b/SmartDeviceLinkTests/DevAPISpecs/SDLPermissionsManagerSpec.m
@@ -8,11 +8,20 @@
#import "SDLOnHMIStatus.h"
#import "SDLOnPermissionsChange.h"
#import "SDLParameterPermissions.h"
+#import "SDLPermissionFilter.h"
#import "SDLPermissionItem.h"
#import "SDLPermissionManager.h"
#import "SDLRPCNotificationNotification.h"
#import "SDLRPCResponseNotification.h"
+@interface SDLPermissionManager ()
+
+@property (strong, nonatomic) NSMutableDictionary<SDLPermissionRPCName, SDLPermissionItem *> *permissions;
+@property (strong, nonatomic) NSMutableArray<SDLPermissionFilter *> *filters;
+@property (copy, nonatomic, nullable) SDLHMILevel currentHMILevel;
+
+@end
+
QuickSpecBegin(SDLPermissionsManagerSpec)
describe(@"SDLPermissionsManager", ^{
@@ -111,6 +120,14 @@ describe(@"SDLPermissionsManager", ^{
backgroundHMINotification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangeHMIStatusNotification object:nil rpcNotification:testBackgroundHMIStatus];
noneHMINotification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangeHMIStatusNotification object:nil rpcNotification:testNoneHMIStatus];
});
+
+ it(@"should clear when stopped", ^{
+ [testPermissionsManager stop];
+
+ expect(testPermissionsManager.filters).to(beEmpty());
+ expect(testPermissionsManager.permissions).to(beEmpty());
+ expect(testPermissionsManager.currentHMILevel).to(beNil());
+ });
describe(@"checking if a permission is allowed", ^{
__block NSString *someRPCName = nil;
diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLResponseDispatcherSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLResponseDispatcherSpec.m
index 8adb0a6ad..410d24386 100644
--- a/SmartDeviceLinkTests/DevAPISpecs/SDLResponseDispatcherSpec.m
+++ b/SmartDeviceLinkTests/DevAPISpecs/SDLResponseDispatcherSpec.m
@@ -273,6 +273,7 @@ describe(@"a response dispatcher", ^{
beforeEach(^{
testOnCommand = [[SDLOnCommand alloc] init];
testOnCommand.cmdID = @(testCommandId);
+ testOnCommand.triggerSource = SDLTriggerSourceMenu;
SDLRPCNotificationNotification *commandNotification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidReceiveCommandNotification object:nil rpcNotification:testOnCommand];
diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLSoftButtonManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLSoftButtonManagerSpec.m
index 0115d318e..7eaad7142 100644
--- a/SmartDeviceLinkTests/DevAPISpecs/SDLSoftButtonManagerSpec.m
+++ b/SmartDeviceLinkTests/DevAPISpecs/SDLSoftButtonManagerSpec.m
@@ -24,6 +24,9 @@
@interface SDLSoftButtonManager()
+@property (weak, nonatomic) id<SDLConnectionManagerType> connectionManager;
+@property (weak, nonatomic) SDLFileManager *fileManager;
+
@property (strong, nonatomic) NSArray<SDLSoftButton *> *currentSoftButtons;
@property (strong, nonatomic, nullable) SDLShow *inProgressUpdate;
@@ -60,10 +63,13 @@ describe(@"a soft button manager", ^{
__block SDLSoftButtonObject *testObject2 = nil;
__block NSString *object2Name = @"O2 Name";
__block NSString *object2State1Name = @"O2S1 Name";
+ __block NSString *object2State2Name = @"O2S2 Name";
__block NSString *object2State1Text = @"O2S1 Text";
+ __block NSString *object2State2Text = @"O2S2 Text";
__block NSString *object2State1ArtworkName = @"O2S1 Artwork";
__block SDLArtwork *object2State1Art = [[SDLArtwork alloc] initWithData:[@"TestData" dataUsingEncoding:NSUTF8StringEncoding] name:object2State1ArtworkName fileExtension:@"png" persistent:YES];
__block SDLSoftButtonState *object2State1 = [[SDLSoftButtonState alloc] initWithStateName:object2State1Name text:object2State1Text artwork:object2State1Art];
+ __block SDLSoftButtonState *object2State2 = [[SDLSoftButtonState alloc] initWithStateName:object2State2Name text:object2State2Text image:nil];
beforeEach(^{
testFileManager = OCMClassMock([SDLFileManager class]);
@@ -71,9 +77,23 @@ describe(@"a soft button manager", ^{
testManager = [[SDLSoftButtonManager alloc] initWithConnectionManager:testConnectionManager fileManager:testFileManager];
+ expect(testManager.currentLevel).to(beNil());
testManager.currentLevel = SDLHMILevelFull;
});
+ it(@"should instantiate correctly", ^{
+ expect(testManager.connectionManager).to(equal(testConnectionManager));
+ expect(testManager.fileManager).to(equal(testFileManager));
+
+ expect(testManager.softButtonObjects).to(beEmpty());
+ expect(testManager.currentMainField1).to(beNil());
+ expect(testManager.inProgressUpdate).to(beNil());
+ expect(testManager.hasQueuedUpdate).to(beFalse());
+ expect(testManager.displayCapabilities).to(beNil());
+ expect(testManager.softButtonCapabilities).to(beNil());
+ expect(testManager.waitingOnHMILevelUpdateToSetButtons).to(beFalse());
+ });
+
context(@"when in HMI NONE", ^{
beforeEach(^{
testManager.currentLevel = SDLHMILevelNone;
@@ -156,8 +176,14 @@ describe(@"a soft button manager", ^{
});
});
- describe(@"uploading the images", ^{
- context(@"when files are already on the file system", ^{
+ describe(@"uploading soft buttons to a head unit that supports images", ^{
+ beforeEach(^{
+ SDLSoftButtonCapabilities *softButtonImagesSupported = [[SDLSoftButtonCapabilities alloc] init];
+ softButtonImagesSupported.imageSupported = @YES;
+ testManager.softButtonCapabilities = softButtonImagesSupported;
+ });
+
+ context(@"when button artworks are already on the file system", ^{
beforeEach(^{
OCMStub([testFileManager hasUploadedFile:[OCMArg isNotNil]]).andReturn(YES);
@@ -184,7 +210,7 @@ describe(@"a soft button manager", ^{
});
});
- context(@"when files are not already on the file system, before upload finishes", ^{
+ context(@"when button artworks are not already on the file system, before upload finishes", ^{
beforeEach(^{
OCMStub([testFileManager hasUploadedFile:[OCMArg isNotNil]]).andReturn(NO);
@@ -211,7 +237,7 @@ describe(@"a soft button manager", ^{
});
});
- context(@"when files are not already on the file system, after upload finishes", ^{
+ context(@"when button artworks are not already on the file system, after upload finishes", ^{
beforeEach(^{
OCMStub([testFileManager hasUploadedFile:[OCMArg isNotNil]]).andReturn(NO);
OCMStub([testFileManager uploadArtworks:[OCMArg any] completionHandler:[OCMArg invokeBlock]]);
@@ -240,6 +266,62 @@ describe(@"a soft button manager", ^{
});
});
+ describe(@"uploading soft buttons to a head unit that does not support images", ^{
+ beforeEach(^{
+ SDLSoftButtonCapabilities *softButtonImagesSupported = [[SDLSoftButtonCapabilities alloc] init];
+ softButtonImagesSupported.imageSupported = @NO;
+ testManager.softButtonCapabilities = softButtonImagesSupported;
+ });
+
+ context(@"when the button contains images", ^{
+ beforeEach(^{
+ testObject1 = [[SDLSoftButtonObject alloc] initWithName:object1Name states:@[object1State1, object1State2] initialStateName:object1State1Name handler:nil];
+ testObject2 = [[SDLSoftButtonObject alloc] initWithName:object2Name state:object2State2 handler:nil];
+ testManager.softButtonObjects = @[testObject1, testObject2];
+ });
+
+ it(@"should not have attempted to upload any artworks", ^{
+ OCMReject([testFileManager uploadArtworks:[OCMArg any] completionHandler:[OCMArg any]]);
+ });
+
+ it(@"should set the in progress update to be text buttons", ^{
+ NSArray<SDLSoftButton *> *inProgressSoftButtons = testManager.inProgressUpdate.softButtons;
+
+ expect(testManager.hasQueuedUpdate).to(beFalse());
+ expect(testManager.inProgressUpdate.mainField1).to(equal(@""));
+ expect(inProgressSoftButtons).to(haveCount(2));
+ expect(inProgressSoftButtons[0].text).to(equal(object1State1Text));
+ expect(inProgressSoftButtons[1].text).to(equal(object2State2Text));
+ expect(inProgressSoftButtons[0].image).to(beNil());
+ expect(inProgressSoftButtons[1].image.value).to(beNil());
+ });
+ });
+
+ context(@"when the button does not contain images", ^{
+ beforeEach(^{
+ testObject1 = [[SDLSoftButtonObject alloc] initWithName:object1Name states:@[object1State1, object1State2] initialStateName:object1State1Name handler:nil];
+ testObject2 = [[SDLSoftButtonObject alloc] initWithName:object2Name state:object2State2 handler:nil];
+ testManager.softButtonObjects = @[testObject1, testObject2];
+ });
+
+ it(@"should not have attempted to upload any artworks", ^{
+ OCMReject([testFileManager uploadArtworks:[OCMArg any] completionHandler:[OCMArg any]]);
+ });
+
+ it(@"should set the in progress update to be text buttons", ^{
+ NSArray<SDLSoftButton *> *inProgressSoftButtons = testManager.inProgressUpdate.softButtons;
+
+ expect(testManager.hasQueuedUpdate).to(beFalse());
+ expect(testManager.inProgressUpdate.mainField1).to(equal(@""));
+ expect(inProgressSoftButtons).to(haveCount(2));
+ expect(inProgressSoftButtons[0].text).to(equal(object1State1Text));
+ expect(inProgressSoftButtons[1].text).to(equal(object2State2Text));
+ expect(inProgressSoftButtons[0].image).to(beNil());
+ expect(inProgressSoftButtons[1].image.value).to(beNil());
+ });
+ });
+ });
+
describe(@"transitioning soft button states", ^{
beforeEach(^{
OCMStub([testFileManager hasUploadedFile:[OCMArg isNotNil]]).andReturn(YES);
@@ -260,6 +342,26 @@ describe(@"a soft button manager", ^{
expect(testManager.inProgressUpdate.softButtons[1].text).to(equal(object2State1Text));
});
});
+
+ context(@"On disconnects", ^{
+ beforeEach(^{
+ [testManager stop];
+ });
+
+ it(@"should reset correctly", ^{
+ expect(testManager.connectionManager).to(equal(testConnectionManager));
+ expect(testManager.fileManager).to(equal(testFileManager));
+
+ expect(testManager.softButtonObjects).to(beEmpty());
+ expect(testManager.currentMainField1).to(beNil());
+ expect(testManager.inProgressUpdate).to(beNil());
+ expect(testManager.hasQueuedUpdate).to(beFalse());
+ expect(testManager.currentLevel).to(beNil());
+ expect(testManager.displayCapabilities).to(beNil());
+ expect(testManager.softButtonCapabilities).to(beNil());
+ expect(testManager.waitingOnHMILevelUpdateToSetButtons).to(beFalse());
+ });
+ });
});
QuickSpecEnd
diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLTextAndGraphicManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLTextAndGraphicManagerSpec.m
index cb29f3433..5005483d0 100644
--- a/SmartDeviceLinkTests/DevAPISpecs/SDLTextAndGraphicManagerSpec.m
+++ b/SmartDeviceLinkTests/DevAPISpecs/SDLTextAndGraphicManagerSpec.m
@@ -53,10 +53,14 @@ describe(@"text and graphic manager", ^{
});
it(@"should instantiate correctly", ^{
+ expect(testManager.connectionManager).to(equal(mockConnectionManager));
+ expect(testManager.fileManager).to(equal(mockFileManager));
+
expect(testManager.textField1).to(beNil());
expect(testManager.textField2).to(beNil());
expect(testManager.textField3).to(beNil());
expect(testManager.textField4).to(beNil());
+ expect(testManager.mediaTrackTextField).to(beNil());
expect(testManager.primaryGraphic).to(beNil());
expect(testManager.secondaryGraphic).to(beNil());
expect(testManager.alignment).to(equal(SDLTextAlignmentCenter));
@@ -64,39 +68,48 @@ describe(@"text and graphic manager", ^{
expect(testManager.textField2Type).to(beNil());
expect(testManager.textField3Type).to(beNil());
expect(testManager.textField4Type).to(beNil());
+
+ expect(testManager.currentScreenData).to(equal([[SDLShow alloc] init]));
+ expect(testManager.inProgressUpdate).to(beNil());
+ expect(testManager.queuedImageUpdate).to(beNil());
+ expect(testManager.hasQueuedUpdate).to(beFalse());
+ expect(testManager.displayCapabilities).to(beNil());
+ expect(testManager.currentLevel).to(equal(SDLHMILevelNone));
+ expect(testManager.blankArtwork).toNot(beNil());
+ expect(testManager.isDirty).to(beFalse());
});
- context(@"when in HMI NONE", ^{
+ describe(@"setting setters", ^{
beforeEach(^{
- testManager.currentLevel = SDLHMILevelNone;
+ testManager.currentLevel = SDLHMILevelFull;
});
- it(@"should not set text field 1", ^{
- testManager.textField1 = testString;
+ context(@"when in HMI NONE", ^{
+ beforeEach(^{
+ testManager.currentLevel = SDLHMILevelNone;
+ });
- expect(testManager.textField1).to(equal(testString));
- expect(testManager.inProgressUpdate).to(beNil());
- expect(testManager.isDirty).to(beFalse());
- });
- });
+ it(@"should not set text field 1", ^{
+ testManager.textField1 = testString;
- context(@"when no HMI level has been received", ^{
- beforeEach(^{
- testManager.currentLevel = nil;
+ expect(testManager.textField1).to(equal(testString));
+ expect(testManager.inProgressUpdate).to(beNil());
+ expect(testManager.isDirty).to(beFalse());
+ });
});
- it(@"should not set text field 1", ^{
- testManager.textField1 = testString;
+ context(@"when no HMI level has been received", ^{
+ beforeEach(^{
+ testManager.currentLevel = nil;
+ });
- expect(testManager.textField1).to(equal(testString));
- expect(testManager.inProgressUpdate).to(beNil());
- expect(testManager.isDirty).to(beFalse());
- });
- });
+ it(@"should not set text field 1", ^{
+ testManager.textField1 = testString;
- describe(@"setting setters", ^{
- beforeEach(^{
- testManager.currentLevel = SDLHMILevelFull;
+ expect(testManager.textField1).to(equal(testString));
+ expect(testManager.inProgressUpdate).to(beNil());
+ expect(testManager.isDirty).to(beFalse());
+ });
});
context(@"while batching", ^{
@@ -136,6 +149,14 @@ describe(@"text and graphic manager", ^{
expect(testManager.isDirty).to(beTrue());
});
+ it(@"should set media track text field", ^{
+ testManager.mediaTrackTextField = testString;
+
+ expect(testManager.mediaTrackTextField).to(equal(testString));
+ expect(testManager.inProgressUpdate).to(beNil());
+ expect(testManager.isDirty).to(beTrue());
+ });
+
it(@"should set primary graphic", ^{
testManager.primaryGraphic = testArtwork;
@@ -230,6 +251,14 @@ describe(@"text and graphic manager", ^{
expect(testManager.isDirty).to(beFalse());
});
+ it(@"should set media track text field", ^{
+ testManager.mediaTrackTextField = testString;
+
+ expect(testManager.mediaTrackTextField).to(equal(testString));
+ expect(testManager.inProgressUpdate).toNot(beNil());
+ expect(testManager.isDirty).to(beFalse());
+ });
+
it(@"should set primary graphic", ^{
testManager.primaryGraphic = testArtwork;
@@ -293,6 +322,7 @@ describe(@"text and graphic manager", ^{
NSString *textLine2 = @"line2";
NSString *textLine3 = @"line3";
NSString *textLine4 = @"line4";
+ NSString *textMediaTrack = @"line5";
SDLMetadataType line1Type = SDLMetadataTypeMediaTitle;
SDLMetadataType line2Type = SDLMetadataTypeMediaAlbum;
@@ -307,6 +337,7 @@ describe(@"text and graphic manager", ^{
testManager.textField2 = nil;
testManager.textField3 = nil;
testManager.textField4 = nil;
+ testManager.mediaTrackTextField = nil;
testManager.textField1Type = nil;
testManager.textField2Type = nil;
testManager.textField3Type = nil;
@@ -321,6 +352,17 @@ describe(@"text and graphic manager", ^{
testManager.displayCapabilities.textFields = @[lineOneField];
});
+ it(@"should set mediatrack properly", ^{
+ testManager.mediaTrackTextField = textMediaTrack;
+
+ testManager.batchUpdates = NO;
+ [testManager updateWithCompletionHandler:nil];
+
+ expect(testManager.inProgressUpdate.mediaTrack).to(equal(textMediaTrack));
+ expect(testManager.inProgressUpdate.mainField1).to(beEmpty());
+ expect(testManager.inProgressUpdate.metadataTags.mainField1).to(beNil());
+ });
+
it(@"should format a one line text and metadata update properly", ^{
testManager.textField1 = textLine1;
testManager.textField1Type = line1Type;
@@ -400,6 +442,17 @@ describe(@"text and graphic manager", ^{
testManager.displayCapabilities.textFields = @[lineTwoField];
});
+ it(@"should set mediatrack properly", ^{
+ testManager.mediaTrackTextField = textMediaTrack;
+
+ testManager.batchUpdates = NO;
+ [testManager updateWithCompletionHandler:nil];
+
+ expect(testManager.inProgressUpdate.mediaTrack).to(equal(textMediaTrack));
+ expect(testManager.inProgressUpdate.mainField1).to(beEmpty());
+ expect(testManager.inProgressUpdate.metadataTags.mainField1).to(beNil());
+ });
+
it(@"should format a one line text and metadata update properly", ^{
testManager.textField1 = textLine1;
testManager.textField1Type = line1Type;
@@ -488,6 +541,17 @@ describe(@"text and graphic manager", ^{
testManager.displayCapabilities.textFields = @[lineThreeField];
});
+ it(@"should set mediatrack properly", ^{
+ testManager.mediaTrackTextField = textMediaTrack;
+
+ testManager.batchUpdates = NO;
+ [testManager updateWithCompletionHandler:nil];
+
+ expect(testManager.inProgressUpdate.mediaTrack).to(equal(textMediaTrack));
+ expect(testManager.inProgressUpdate.mainField1).to(beEmpty());
+ expect(testManager.inProgressUpdate.metadataTags.mainField1).to(beNil());
+ });
+
it(@"should format a one line text and metadata update properly", ^{
testManager.textField1 = textLine1;
testManager.textField1Type = line1Type;
@@ -580,6 +644,17 @@ describe(@"text and graphic manager", ^{
testManager.displayCapabilities.textFields = @[lineFourField];
});
+ it(@"should set mediatrack properly", ^{
+ testManager.mediaTrackTextField = textMediaTrack;
+
+ testManager.batchUpdates = NO;
+ [testManager updateWithCompletionHandler:nil];
+
+ expect(testManager.inProgressUpdate.mediaTrack).to(equal(textMediaTrack));
+ expect(testManager.inProgressUpdate.mainField1).to(beEmpty());
+ expect(testManager.inProgressUpdate.metadataTags.mainField1).to(beNil());
+ });
+
it(@"should format a one line text and metadata update properly", ^{
testManager.textField1 = textLine1;
testManager.textField1Type = line1Type;
@@ -706,6 +781,39 @@ describe(@"text and graphic manager", ^{
});
});
});
+
+ context(@"On disconnects", ^{
+ beforeEach(^{
+ [testManager stop];
+ });
+
+ it(@"should reset correctly", ^{
+ expect(testManager.connectionManager).to(equal(mockConnectionManager));
+ expect(testManager.fileManager).to(equal(mockFileManager));
+
+ expect(testManager.textField1).to(beNil());
+ expect(testManager.textField2).to(beNil());
+ expect(testManager.textField3).to(beNil());
+ expect(testManager.textField4).to(beNil());
+ expect(testManager.mediaTrackTextField).to(beNil());
+ expect(testManager.primaryGraphic).to(beNil());
+ expect(testManager.secondaryGraphic).to(beNil());
+ expect(testManager.alignment).to(equal(SDLTextAlignmentCenter));
+ expect(testManager.textField1Type).to(beNil());
+ expect(testManager.textField2Type).to(beNil());
+ expect(testManager.textField3Type).to(beNil());
+ expect(testManager.textField4Type).to(beNil());
+
+ expect(testManager.currentScreenData).to(equal([[SDLShow alloc] init]));
+ expect(testManager.inProgressUpdate).to(beNil());
+ expect(testManager.queuedImageUpdate).to(beNil());
+ expect(testManager.hasQueuedUpdate).to(beFalse());
+ expect(testManager.displayCapabilities).to(beNil());
+ expect(testManager.currentLevel).to(equal(SDLHMILevelNone));
+ expect(testManager.blankArtwork).toNot(beNil());
+ expect(testManager.isDirty).to(beFalse());
+ });
+ });
});
QuickSpecEnd
diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLVoiceCommandManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLVoiceCommandManagerSpec.m
new file mode 100644
index 000000000..57ed8db1c
--- /dev/null
+++ b/SmartDeviceLinkTests/DevAPISpecs/SDLVoiceCommandManagerSpec.m
@@ -0,0 +1,144 @@
+#import <Quick/Quick.h>
+#import <Nimble/Nimble.h>
+#import <OCMock/OCMock.h>
+
+#import "SDLAddCommand.h"
+#import "SDLDeleteCommand.h"
+#import "SDLFileManager.h"
+#import "SDLHMILevel.h"
+#import "SDLVoiceCommand.h"
+#import "SDLVoiceCommandManager.h"
+#import "TestConnectionManager.h"
+
+@interface SDLVoiceCommand()
+
+@property (assign, nonatomic) UInt32 commandId;
+
+@end
+
+@interface SDLVoiceCommandManager()
+
+@property (weak, nonatomic) id<SDLConnectionManagerType> connectionManager;
+
+@property (assign, nonatomic) BOOL waitingOnHMIUpdate;
+@property (copy, nonatomic, nullable) SDLHMILevel currentHMILevel;
+
+@property (strong, nonatomic, nullable) NSArray<SDLRPCRequest *> *inProgressUpdate;
+@property (assign, nonatomic) BOOL hasQueuedUpdate;
+
+@property (assign, nonatomic) UInt32 lastVoiceCommandId;
+@property (copy, nonatomic) NSArray<SDLVoiceCommand *> *oldVoiceCommands;
+
+@end
+
+UInt32 const VoiceCommandIdMin = 1900000000;
+
+QuickSpecBegin(SDLVoiceCommandManagerSpec)
+
+describe(@"voice command manager", ^{
+ __block SDLVoiceCommandManager *testManager = nil;
+ __block TestConnectionManager *mockConnectionManager = nil;
+
+ __block SDLVoiceCommand *testVoiceCommand = [[SDLVoiceCommand alloc] initWithVoiceCommands:@[@"Test 1"] handler:^{}];
+ __block SDLVoiceCommand *testVoiceCommand2 = [[SDLVoiceCommand alloc] initWithVoiceCommands:@[@"Test 2"] handler:^{}];
+
+ beforeEach(^{
+ mockConnectionManager = [[TestConnectionManager alloc] init];
+ testManager = [[SDLVoiceCommandManager alloc] initWithConnectionManager:mockConnectionManager];
+ });
+
+ it(@"should instantiate correctly", ^{
+ expect(testManager.connectionManager).to(equal(mockConnectionManager));
+
+ expect(testManager.voiceCommands).to(beEmpty());
+ expect(testManager.connectionManager).to(equal(mockConnectionManager));
+ expect(testManager.currentHMILevel).to(beNil());
+ expect(testManager.inProgressUpdate).to(beNil());
+ expect(testManager.hasQueuedUpdate).to(beFalse());
+ expect(testManager.waitingOnHMIUpdate).to(beFalse());
+ expect(testManager.lastVoiceCommandId).to(equal(VoiceCommandIdMin));
+ expect(testManager.oldVoiceCommands).to(beEmpty());
+ });
+
+ describe(@"updating voice commands before HMI is ready", ^{
+ context(@"when in HMI NONE", ^{
+ beforeEach(^{
+ testManager.currentHMILevel = SDLHMILevelNone;
+ });
+
+ it(@"should not update", ^{
+ testManager.voiceCommands = @[testVoiceCommand];
+ expect(testManager.inProgressUpdate).to(beNil());
+ });
+ });
+
+ context(@"when no HMI level has been received", ^{
+ beforeEach(^{
+ testManager.currentHMILevel = nil;
+ });
+
+ it(@"should not update", ^{
+ testManager.voiceCommands = @[testVoiceCommand];
+ expect(testManager.inProgressUpdate).to(beNil());
+ });
+ });
+ });
+
+ describe(@"updating voice commands", ^{
+ beforeEach(^{
+ testManager.currentHMILevel = SDLHMILevelFull;
+ });
+
+ it(@"should properly update a command", ^{
+ testManager.voiceCommands = @[testVoiceCommand];
+
+ NSPredicate *deleteCommandPredicate = [NSPredicate predicateWithFormat:@"self isMemberOfClass: %@", [SDLDeleteCommand class]];
+ NSArray *deletes = [[mockConnectionManager.receivedRequests copy] filteredArrayUsingPredicate:deleteCommandPredicate];
+ expect(deletes).to(beEmpty());
+
+ NSPredicate *addCommandPredicate = [NSPredicate predicateWithFormat:@"self isMemberOfClass: %@", [SDLAddCommand class]];
+ NSArray *add = [[mockConnectionManager.receivedRequests copy] filteredArrayUsingPredicate:addCommandPredicate];
+ expect(add).toNot(beEmpty());
+ });
+
+ context(@"when a menu already exists", ^{
+ beforeEach(^{
+ testManager.voiceCommands = @[testVoiceCommand];
+ });
+
+ it(@"should send deletes first", ^{
+ testManager.voiceCommands = @[testVoiceCommand2];
+
+ NSPredicate *deleteCommandPredicate = [NSPredicate predicateWithFormat:@"self isMemberOfClass: %@", [SDLDeleteCommand class]];
+ NSArray *deletes = [[mockConnectionManager.receivedRequests copy] filteredArrayUsingPredicate:deleteCommandPredicate];
+
+ NSPredicate *addCommandPredicate = [NSPredicate predicateWithFormat:@"self isMemberOfClass: %@", [SDLAddCommand class]];
+ NSArray *adds = [[mockConnectionManager.receivedRequests copy] filteredArrayUsingPredicate:addCommandPredicate];
+
+ expect(deletes).to(haveCount(1));
+ expect(adds).to(haveCount(2));
+ });
+ });
+ });
+
+ context(@"On disconnects", ^{
+ beforeEach(^{
+ [testManager stop];
+ });
+
+ it(@"should reset correctly", ^{
+ expect(testManager.connectionManager).to(equal(mockConnectionManager));
+
+ expect(testManager.voiceCommands).to(beEmpty());
+ expect(testManager.connectionManager).to(equal(mockConnectionManager));
+ expect(testManager.currentHMILevel).to(beNil());
+ expect(testManager.inProgressUpdate).to(beNil());
+ expect(testManager.hasQueuedUpdate).to(beFalse());
+ expect(testManager.waitingOnHMIUpdate).to(beFalse());
+ expect(testManager.lastVoiceCommandId).to(equal(VoiceCommandIdMin));
+ expect(testManager.oldVoiceCommands).to(beEmpty());
+ });
+ });
+});
+
+QuickSpecEnd
diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLVoiceCommandSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLVoiceCommandSpec.m
new file mode 100644
index 000000000..8e8a2e7c3
--- /dev/null
+++ b/SmartDeviceLinkTests/DevAPISpecs/SDLVoiceCommandSpec.m
@@ -0,0 +1,26 @@
+#import <Quick/Quick.h>
+#import <Nimble/Nimble.h>
+
+#import "SDLVoiceCommand.h"
+
+QuickSpecBegin(SDLVoiceCommandSpec)
+
+describe(@"a voice command", ^{
+ __block SDLVoiceCommand *testCommand = nil;
+
+ describe(@"initializing", ^{
+ __block NSArray<NSString *> *someVoiceCommands = nil;
+
+ beforeEach(^{
+ someVoiceCommands = @[@"some command"];
+ });
+
+ it(@"should initialize properly", ^{
+ testCommand = [[SDLVoiceCommand alloc] initWithVoiceCommands:someVoiceCommands handler:^{}];
+
+ expect(testCommand.voiceCommands).to(equal(someVoiceCommands));
+ });
+ });
+});
+
+QuickSpecEnd
diff --git a/SmartDeviceLinkTests/ProtocolSpecs/MessageSpecs/SDLProtocolSpec.m b/SmartDeviceLinkTests/ProtocolSpecs/MessageSpecs/SDLProtocolSpec.m
index 635dea80d..4131fed51 100644
--- a/SmartDeviceLinkTests/ProtocolSpecs/MessageSpecs/SDLProtocolSpec.m
+++ b/SmartDeviceLinkTests/ProtocolSpecs/MessageSpecs/SDLProtocolSpec.m
@@ -9,7 +9,7 @@
#import <Nimble/Nimble.h>
#import <OCMock/OCMock.h>
-#import "SDLAbstractTransport.h"
+#import "SDLTransportType.h"
#import "SDLProtocolHeader.h"
#import "SDLProtocol.h"
#import "SDLProtocolMessage.h"
@@ -38,7 +38,7 @@ describe(@"Send StartService Tests", ^ {
SDLProtocol* testProtocol = [[SDLProtocol alloc] init];
__block BOOL verified = NO;
- id transportMock = OCMClassMock([SDLAbstractTransport class]);
+ id transportMock = OCMProtocolMock(@protocol(SDLTransportType));
[[[transportMock stub] andDo:^(NSInvocation* invocation) {
verified = YES;
@@ -77,7 +77,7 @@ describe(@"Send EndSession Tests", ^ {
[testProtocol handleProtocolStartServiceACKMessage:[SDLProtocolMessage messageWithHeader:testHeader andPayload:nil]];
__block BOOL verified = NO;
- id transportMock = OCMClassMock([SDLAbstractTransport class]);
+ id transportMock = OCMProtocolMock(@protocol(SDLTransportType));
[[[transportMock stub] andDo:^(NSInvocation* invocation) {
verified = YES;
@@ -106,7 +106,7 @@ describe(@"Send EndSession Tests", ^ {
[testProtocol handleProtocolStartServiceACKMessage:[SDLProtocolMessage messageWithHeader:testHeader andPayload:nil]];
__block BOOL verified = NO;
- id transportMock = OCMClassMock([SDLAbstractTransport class]);
+ id transportMock = OCMProtocolMock(@protocol(SDLTransportType));
[[[transportMock stub] andDo:^(NSInvocation* invocation) {
verified = YES;
@@ -144,7 +144,7 @@ describe(@"SendRPCRequest Tests", ^ {
[testProtocol handleProtocolStartServiceACKMessage:[SDLProtocolMessage messageWithHeader:testHeader andPayload:nil]];
__block BOOL verified = NO;
- id transportMock = OCMClassMock([SDLAbstractTransport class]);
+ id transportMock = OCMProtocolMock(@protocol(SDLTransportType));
[[[transportMock stub] andDo:^(NSInvocation* invocation) {
verified = YES;
@@ -184,7 +184,7 @@ describe(@"SendRPCRequest Tests", ^ {
[testProtocol handleProtocolStartServiceACKMessage:[SDLProtocolMessage messageWithHeader:testHeader andPayload:nil]];
__block BOOL verified = NO;
- id transportMock = OCMClassMock([SDLAbstractTransport class]);
+ id transportMock = OCMProtocolMock(@protocol(SDLTransportType));
[[[transportMock stub] andDo:^(NSInvocation* invocation) {
verified = YES;
diff --git a/SmartDeviceLinkTests/ProtocolSpecs/SDLAbstractProtocolSpec.m b/SmartDeviceLinkTests/ProtocolSpecs/SDLAbstractProtocolSpec.m
deleted file mode 100644
index 38d6f3c03..000000000
--- a/SmartDeviceLinkTests/ProtocolSpecs/SDLAbstractProtocolSpec.m
+++ /dev/null
@@ -1,57 +0,0 @@
-//
-// SDLAbstractProtocolSpec.m
-// SmartDeviceLink-iOS
-
-
-#import <Foundation/Foundation.h>
-
-#import <Quick/Quick.h>
-#import <Nimble/Nimble.h>
-#import <OCMock/OCMock.h>
-
-#import "SDLAbstractProtocol.h"
-#import "SDLProtocolListener.h"
-
-QuickSpecBegin(SDLAbstractProtocolSpec)
-
-xdescribe(@"OnTransportConnected Tests", ^ {
- it(@"Should invoke the correct method", ^ {
- id delegateMock = OCMProtocolMock(@protocol(SDLProtocolListener));
-
- SDLAbstractProtocol* abstractProtocol = [[SDLAbstractProtocol alloc] init];
- [abstractProtocol.protocolDelegateTable addObject:delegateMock];
-
- __block BOOL verified = NO;
- [[[delegateMock stub] andDo:^(NSInvocation* invocation) {verified = YES;}] onProtocolOpened];
-
- [abstractProtocol onTransportConnected];
-
- //Verifications don't work with Nimble at this point
- //OCMVerify([delegateMock onProtocolOpened]);
-
- //Workaround for now
- expect(@(verified)).to(beTruthy());
- });
-});
-
-xdescribe(@"OnTransportDisconnected Tests", ^ {
- it(@"Should invoke the correct method", ^ {
- id delegateMock = OCMProtocolMock(@protocol(SDLProtocolListener));
-
- SDLAbstractProtocol* abstractProtocol = [[SDLAbstractProtocol alloc] init];
- [abstractProtocol.protocolDelegateTable addObject:delegateMock];
-
- __block BOOL verified = NO;
- [[[delegateMock stub] andDo:^(NSInvocation* invocation) {verified = YES;}] onProtocolClosed];
-
- [abstractProtocol onTransportDisconnected];
-
- //Verifications don't work with Nimble at this point
- //OCMVerify([delegateMock onProtocolClosed]);
-
- //Workaround for now
- expect(@(verified)).to(beTruthy());
- });
-});
-
-QuickSpecEnd
diff --git a/SmartDeviceLinkTests/RPCSpecs/RequestSpecs/SDLShowSpec.m b/SmartDeviceLinkTests/RPCSpecs/RequestSpecs/SDLShowSpec.m
index 80733245e..e41d73cc8 100644
--- a/SmartDeviceLinkTests/RPCSpecs/RequestSpecs/SDLShowSpec.m
+++ b/SmartDeviceLinkTests/RPCSpecs/RequestSpecs/SDLShowSpec.m
@@ -59,41 +59,7 @@ describe(@"Getter/Setter Tests", ^ {
});
- it(@"Should get correctly when initialized", ^ {
- NSMutableDictionary* dict = [@{SDLNameRequest:
- @{SDLNameParameters:
- @{SDLNameMainField1:@"field1",
- SDLNameMainField2:@"field2",
- SDLNameMainField3:@"field3",
- SDLNameMainField4:@"field4",
- SDLNameAlignment:SDLTextAlignmentLeft,
- SDLNameStatusBar:@"status",
- SDLNameMediaClock:@"TheTime",
- SDLNameMediaTrack:@"In The Clear",
- SDLNameGraphic:image1,
- SDLNameSecondaryGraphic:image2,
- SDLNameSoftButtons:[@[button] mutableCopy],
- SDLNameCustomPresets:[@[@"preset1", @"preset2"] mutableCopy],
- SDLNameMetadataTags:testMetadata},
- SDLNameOperationName:SDLNameShow}} mutableCopy];
- SDLShow* testRequest = [[SDLShow alloc] initWithDictionary:dict];
-
- expect(testRequest.mainField1).to(equal(@"field1"));
- expect(testRequest.mainField2).to(equal(@"field2"));
- expect(testRequest.mainField3).to(equal(@"field3"));
- expect(testRequest.mainField4).to(equal(@"field4"));
- expect(testRequest.alignment).to(equal(SDLTextAlignmentLeft));
- expect(testRequest.statusBar).to(equal(@"status"));
- expect(testRequest.mediaClock).to(equal(@"TheTime"));
- expect(testRequest.mediaTrack).to(equal(@"In The Clear"));
- expect(testRequest.graphic).to(equal(image1));
- expect(testRequest.secondaryGraphic).to(equal(image2));
- expect(testRequest.softButtons).to(equal([@[button] mutableCopy]));
- expect(testRequest.customPresets).to(equal([@[@"preset1", @"preset2"] mutableCopy]));
- expect(testRequest.metadataTags).to(equal(testMetadata));
- });
-
- it(@"Should return nil if not set", ^ {
+ it(@"Should return nil if not set", ^{
SDLShow* testRequest = [[SDLShow alloc] init];
expect(testRequest.mainField1).to(beNil());
@@ -110,6 +76,275 @@ describe(@"Getter/Setter Tests", ^ {
expect(testRequest.customPresets).to(beNil());
expect(testRequest.metadataTags).to(beNil());
});
+
+ describe(@"initializing", ^{
+ __block NSString *testString1 = @"Test 1";
+ __block NSString *testString2 = @"Test 2";
+ __block NSString *testString3 = @"Test 3";
+ __block NSString *testString4 = @"Test 4";
+ __block NSString *testStatusBarString = @"Test Status";
+ __block NSString *testMediaClockString = @"Test Clock";
+ __block NSString *testMediaTrackString = @"Test Track";
+ __block SDLImage *testGraphic = nil;
+ __block NSArray<NSString *> *testCustomPresets = nil;
+ __block SDLSoftButton *testButton = nil;
+ __block NSArray<SDLSoftButton *> *testSoftButtons = nil;
+ __block SDLMetadataType testType1 = SDLMetadataTypeHumidity;
+ __block SDLMetadataType testType2 = SDLMetadataTypeRating;
+ __block SDLMetadataType testType3 = SDLMetadataTypeMediaYear;
+ __block SDLMetadataType testType4 = SDLMetadataTypeWeatherTerm;
+ __block SDLTextAlignment testAlignment = SDLTextAlignmentCenter;
+ __block SDLMetadataTags *testTags = nil;
+
+ beforeEach(^{
+ testGraphic = [[SDLImage alloc] initWithName:@"test name"];
+ testCustomPresets = @[testString1];
+ testButton = [[SDLSoftButton alloc] initWithType:SDLSoftButtonTypeText text:@"Test Button" image:nil highlighted:NO buttonId:0 systemAction:nil handler:nil];
+ testSoftButtons = @[testButton];
+ testTags = [[SDLMetadataTags alloc] initWithTextFieldTypes:@[testType1] mainField2:@[testType2] mainField3:@[testType3] mainField4:@[testType4]];
+ });
+
+ it(@"should initialize with initWithMainField1:mainField2:alignment:", ^{
+ SDLShow *testShow = [[SDLShow alloc] initWithMainField1:testString1 mainField2:testString2 alignment:testAlignment];
+ expect(testShow.mainField1).to(equal(testString1));
+ expect(testShow.mainField2).to(equal(testString2));
+ expect(testShow.mainField3).to(beNil());
+ expect(testShow.mainField4).to(beNil());
+ expect(testShow.alignment).to(equal(testAlignment));
+ expect(testShow.statusBar).to(beNil());
+ expect(testShow.mediaClock).to(beNil());
+ expect(testShow.mediaTrack).to(beNil());
+ expect(testShow.graphic).to(beNil());
+ expect(testShow.secondaryGraphic).to(beNil());
+ expect(testShow.softButtons).to(beNil());
+ expect(testShow.customPresets).to(beNil());
+ expect(testShow.metadataTags).to(beNil());
+
+ testShow = [[SDLShow alloc] initWithMainField1:nil mainField2:nil alignment:nil];
+ expect(testShow.mainField1).to(beNil());
+ expect(testShow.mainField2).to(beNil());
+ expect(testShow.mainField3).to(beNil());
+ expect(testShow.mainField4).to(beNil());
+ expect(testShow.alignment).to(beNil());
+ expect(testShow.statusBar).to(beNil());
+ expect(testShow.mediaClock).to(beNil());
+ expect(testShow.mediaTrack).to(beNil());
+ expect(testShow.graphic).to(beNil());
+ expect(testShow.secondaryGraphic).to(beNil());
+ expect(testShow.softButtons).to(beNil());
+ expect(testShow.customPresets).to(beNil());
+ expect(testShow.metadataTags).to(beNil());
+ });
+
+ it(@"should initialize correctly with initWithMainField1:mainField1Type:mainField2:mainField2Type:alignment:", ^{
+ SDLShow *testShow = [[SDLShow alloc] initWithMainField1:testString1 mainField1Type:testType1 mainField2:testString2 mainField2Type:testType2 alignment:testAlignment];
+ expect(testShow.mainField1).to(equal(testString1));
+ expect(testShow.mainField2).to(equal(testString2));
+ expect(testShow.mainField3).to(beNil());
+ expect(testShow.mainField4).to(beNil());
+ expect(testShow.alignment).to(equal(testAlignment));
+ expect(testShow.statusBar).to(beNil());
+ expect(testShow.mediaClock).to(beNil());
+ expect(testShow.mediaTrack).to(beNil());
+ expect(testShow.graphic).to(beNil());
+ expect(testShow.secondaryGraphic).to(beNil());
+ expect(testShow.softButtons).to(beNil());
+ expect(testShow.customPresets).to(beNil());
+ expect(testShow.metadataTags.mainField1).to(contain(testType1));
+ expect(testShow.metadataTags.mainField2).to(contain(testType2));
+ expect(testShow.metadataTags.mainField3).to(beNil());
+ expect(testShow.metadataTags.mainField4).to(beNil());
+
+ testShow = [[SDLShow alloc] initWithMainField1:nil mainField1Type:nil mainField2:nil mainField2Type:nil alignment:nil];
+ expect(testShow.mainField1).to(beNil());
+ expect(testShow.mainField2).to(beNil());
+ expect(testShow.mainField3).to(beNil());
+ expect(testShow.mainField4).to(beNil());
+ expect(testShow.alignment).to(beNil());
+ expect(testShow.statusBar).to(beNil());
+ expect(testShow.mediaClock).to(beNil());
+ expect(testShow.mediaTrack).to(beNil());
+ expect(testShow.graphic).to(beNil());
+ expect(testShow.secondaryGraphic).to(beNil());
+ expect(testShow.softButtons).to(beNil());
+ expect(testShow.customPresets).to(beNil());
+ expect(testShow.metadataTags).to(beNil());
+ });
+
+ it(@"should initialize correctly with initWithMainField1:mainField2:mainField3:mainField4:alignment:", ^{
+ SDLShow *testShow = [[SDLShow alloc] initWithMainField1:testString1 mainField2:testString2 mainField3:testString3 mainField4:testString4 alignment:testAlignment];
+ expect(testShow.mainField1).to(equal(testString1));
+ expect(testShow.mainField2).to(equal(testString2));
+ expect(testShow.mainField3).to(equal(testString3));
+ expect(testShow.mainField4).to(equal(testString4));
+ expect(testShow.alignment).to(equal(testAlignment));
+ expect(testShow.statusBar).to(beNil());
+ expect(testShow.mediaClock).to(beNil());
+ expect(testShow.mediaTrack).to(beNil());
+ expect(testShow.graphic).to(beNil());
+ expect(testShow.secondaryGraphic).to(beNil());
+ expect(testShow.softButtons).to(beNil());
+ expect(testShow.customPresets).to(beNil());
+ expect(testShow.metadataTags.mainField1).to(beNil());
+ expect(testShow.metadataTags.mainField2).to(beNil());
+ expect(testShow.metadataTags.mainField3).to(beNil());
+ expect(testShow.metadataTags.mainField4).to(beNil());
+
+ testShow = [[SDLShow alloc] initWithMainField1:nil mainField2:nil mainField3:nil mainField4:nil alignment:nil];
+ expect(testShow.mainField1).to(beNil());
+ expect(testShow.mainField2).to(beNil());
+ expect(testShow.mainField3).to(beNil());
+ expect(testShow.mainField4).to(beNil());
+ expect(testShow.alignment).to(beNil());
+ expect(testShow.statusBar).to(beNil());
+ expect(testShow.mediaClock).to(beNil());
+ expect(testShow.mediaTrack).to(beNil());
+ expect(testShow.graphic).to(beNil());
+ expect(testShow.secondaryGraphic).to(beNil());
+ expect(testShow.softButtons).to(beNil());
+ expect(testShow.customPresets).to(beNil());
+ expect(testShow.metadataTags).to(beNil());
+ });
+
+ it(@"should initialize correctly with initWithMainField1:mainField1Type:mainField2:mainField2Type:mainField3:mainField3Type:mainField4:mainField4Type:alignment:", ^{
+ SDLShow *testShow = [[SDLShow alloc] initWithMainField1:testString1 mainField1Type:testType1 mainField2:testString2 mainField2Type:testType2 mainField3:testString3 mainField3Type:testType3 mainField4:testString4 mainField4Type:testType4 alignment:testAlignment];
+ expect(testShow.mainField1).to(equal(testString1));
+ expect(testShow.mainField2).to(equal(testString2));
+ expect(testShow.mainField3).to(equal(testString3));
+ expect(testShow.mainField4).to(equal(testString4));
+ expect(testShow.alignment).to(equal(testAlignment));
+ expect(testShow.statusBar).to(beNil());
+ expect(testShow.mediaClock).to(beNil());
+ expect(testShow.mediaTrack).to(beNil());
+ expect(testShow.graphic).to(beNil());
+ expect(testShow.secondaryGraphic).to(beNil());
+ expect(testShow.softButtons).to(beNil());
+ expect(testShow.customPresets).to(beNil());
+ expect(testShow.metadataTags.mainField1).to(contain(testType1));
+ expect(testShow.metadataTags.mainField2).to(contain(testType2));
+ expect(testShow.metadataTags.mainField3).to(contain(testType3));
+ expect(testShow.metadataTags.mainField4).to(contain(testType4));
+
+ testShow = [[SDLShow alloc] initWithMainField1:nil mainField1Type:nil mainField2:nil mainField2Type:nil mainField3:nil mainField3Type:nil mainField4:nil mainField4Type:nil alignment:nil];
+ expect(testShow.mainField1).to(beNil());
+ expect(testShow.mainField2).to(beNil());
+ expect(testShow.mainField3).to(beNil());
+ expect(testShow.mainField4).to(beNil());
+ expect(testShow.alignment).to(beNil());
+ expect(testShow.statusBar).to(beNil());
+ expect(testShow.mediaClock).to(beNil());
+ expect(testShow.mediaTrack).to(beNil());
+ expect(testShow.graphic).to(beNil());
+ expect(testShow.secondaryGraphic).to(beNil());
+ expect(testShow.softButtons).to(beNil());
+ expect(testShow.customPresets).to(beNil());
+ expect(testShow.metadataTags).to(beNil());
+ });
+
+ it(@"should initialize correctly with initWithMainField1:mainField2:alignment:statusBar:mediaClock:mediaTrack:", ^{
+ SDLShow *testShow = [[SDLShow alloc] initWithMainField1:testString1 mainField2:testString2 alignment:testAlignment statusBar:testStatusBarString mediaClock:testMediaClockString mediaTrack:testMediaTrackString];
+ expect(testShow.mainField1).to(equal(testString1));
+ expect(testShow.mainField2).to(equal(testString2));
+ expect(testShow.mainField3).to(beNil());
+ expect(testShow.mainField4).to(beNil());
+ expect(testShow.alignment).to(equal(testAlignment));
+ expect(testShow.statusBar).to(equal(testStatusBarString));
+ expect(testShow.mediaClock).to(equal(testMediaClockString));
+ expect(testShow.mediaTrack).to(equal(testMediaTrackString));
+ expect(testShow.graphic).to(beNil());
+ expect(testShow.secondaryGraphic).to(beNil());
+ expect(testShow.softButtons).to(beNil());
+ expect(testShow.customPresets).to(beNil());
+ expect(testShow.metadataTags.mainField1).to(beNil());
+ expect(testShow.metadataTags.mainField2).to(beNil());
+ expect(testShow.metadataTags.mainField3).to(beNil());
+ expect(testShow.metadataTags.mainField4).to(beNil());
+
+ testShow = [[SDLShow alloc] initWithMainField1:nil mainField2:nil alignment:nil statusBar:nil mediaClock:nil mediaTrack:nil];
+ expect(testShow.mainField1).to(beNil());
+ expect(testShow.mainField2).to(beNil());
+ expect(testShow.mainField3).to(beNil());
+ expect(testShow.mainField4).to(beNil());
+ expect(testShow.alignment).to(beNil());
+ expect(testShow.statusBar).to(beNil());
+ expect(testShow.mediaClock).to(beNil());
+ expect(testShow.mediaTrack).to(beNil());
+ expect(testShow.graphic).to(beNil());
+ expect(testShow.secondaryGraphic).to(beNil());
+ expect(testShow.softButtons).to(beNil());
+ expect(testShow.customPresets).to(beNil());
+ expect(testShow.metadataTags).to(beNil());
+ });
+
+ it(@"should initialize correctly with initWithMainField1:mainField2:mainField3:mainField4:alignment:statusBar:mediaClock:mediaTrack:graphic:softButtons:customPresets:textFieldMetadata:", ^{
+ SDLShow *testShow = [[SDLShow alloc] initWithMainField1:testString1 mainField2:testString2 mainField3:testString3 mainField4:testString4 alignment:testAlignment statusBar:testStatusBarString mediaClock:testMediaClockString mediaTrack:testMediaTrackString graphic:testGraphic softButtons:testSoftButtons customPresets:testCustomPresets textFieldMetadata:testTags];
+ expect(testShow.mainField1).to(equal(testString1));
+ expect(testShow.mainField2).to(equal(testString2));
+ expect(testShow.mainField3).to(equal(testString3));
+ expect(testShow.mainField4).to(equal(testString4));
+ expect(testShow.alignment).to(equal(testAlignment));
+ expect(testShow.statusBar).to(equal(testStatusBarString));
+ expect(testShow.mediaClock).to(equal(testMediaClockString));
+ expect(testShow.mediaTrack).to(equal(testMediaTrackString));
+ expect(testShow.graphic).to(equal(testGraphic));
+ expect(testShow.secondaryGraphic).to(beNil());
+ expect(testShow.softButtons).to(contain(testButton));
+ expect(testShow.customPresets).to(contain(testString1));
+ expect(testShow.metadataTags.mainField1).to(contain(testType1));
+ expect(testShow.metadataTags.mainField2).to(contain(testType2));
+ expect(testShow.metadataTags.mainField3).to(contain(testType3));
+ expect(testShow.metadataTags.mainField4).to(contain(testType4));
+
+ testShow = [[SDLShow alloc] initWithMainField1:nil mainField2:nil mainField3:nil mainField4:nil alignment:nil statusBar:nil mediaClock:nil mediaTrack:nil graphic:nil softButtons:nil customPresets:nil textFieldMetadata:nil];
+ expect(testShow.mainField1).to(beNil());
+ expect(testShow.mainField2).to(beNil());
+ expect(testShow.mainField3).to(beNil());
+ expect(testShow.mainField4).to(beNil());
+ expect(testShow.alignment).to(beNil());
+ expect(testShow.statusBar).to(beNil());
+ expect(testShow.mediaClock).to(beNil());
+ expect(testShow.mediaTrack).to(beNil());
+ expect(testShow.graphic).to(beNil());
+ expect(testShow.secondaryGraphic).to(beNil());
+ expect(testShow.softButtons).to(beNil());
+ expect(testShow.customPresets).to(beNil());
+ expect(testShow.metadataTags).to(beNil());
+ });
+
+ it(@"Should get correctly when initialized with a dictionary", ^ {
+ NSMutableDictionary* dict = [@{SDLNameRequest:
+ @{SDLNameParameters:
+ @{SDLNameMainField1:@"field1",
+ SDLNameMainField2:@"field2",
+ SDLNameMainField3:@"field3",
+ SDLNameMainField4:@"field4",
+ SDLNameAlignment:SDLTextAlignmentLeft,
+ SDLNameStatusBar:@"status",
+ SDLNameMediaClock:@"TheTime",
+ SDLNameMediaTrack:@"In The Clear",
+ SDLNameGraphic:image1,
+ SDLNameSecondaryGraphic:image2,
+ SDLNameSoftButtons:[@[button] mutableCopy],
+ SDLNameCustomPresets:[@[@"preset1", @"preset2"] mutableCopy],
+ SDLNameMetadataTags:testMetadata},
+ SDLNameOperationName:SDLNameShow}} mutableCopy];
+ SDLShow* testRequest = [[SDLShow alloc] initWithDictionary:dict];
+
+ expect(testRequest.mainField1).to(equal(@"field1"));
+ expect(testRequest.mainField2).to(equal(@"field2"));
+ expect(testRequest.mainField3).to(equal(@"field3"));
+ expect(testRequest.mainField4).to(equal(@"field4"));
+ expect(testRequest.alignment).to(equal(SDLTextAlignmentLeft));
+ expect(testRequest.statusBar).to(equal(@"status"));
+ expect(testRequest.mediaClock).to(equal(@"TheTime"));
+ expect(testRequest.mediaTrack).to(equal(@"In The Clear"));
+ expect(testRequest.graphic).to(equal(image1));
+ expect(testRequest.secondaryGraphic).to(equal(image2));
+ expect(testRequest.softButtons).to(equal([@[button] mutableCopy]));
+ expect(testRequest.customPresets).to(equal([@[@"preset1", @"preset2"] mutableCopy]));
+ expect(testRequest.metadataTags).to(equal(testMetadata));
+ });
+ });
});
QuickSpecEnd
diff --git a/SmartDeviceLinkTests/SDLScreenManagerSpec.m b/SmartDeviceLinkTests/SDLScreenManagerSpec.m
index 6e56ea140..481295539 100644
--- a/SmartDeviceLinkTests/SDLScreenManagerSpec.m
+++ b/SmartDeviceLinkTests/SDLScreenManagerSpec.m
@@ -3,6 +3,7 @@
#import <OCMock/OCMock.h>
#import "SDLFileManager.h"
+#import "SDLHMILevel.h"
#import "SDLScreenManager.h"
#import "SDLShow.h"
#import "SDLSoftButtonManager.h"
@@ -17,6 +18,7 @@
@property (weak, nonatomic) SDLFileManager *fileManager;
@property (strong, nonatomic, nullable) SDLShow *inProgressUpdate;
+@property (copy, nonatomic, nullable) SDLHMILevel currentLevel;
@end
@@ -26,6 +28,7 @@
@property (weak, nonatomic) SDLFileManager *fileManager;
@property (strong, nonatomic, nullable) SDLShow *inProgressUpdate;
+@property (copy, nonatomic, nullable) SDLHMILevel currentLevel;
@end
@@ -77,6 +80,9 @@ describe(@"screen manager", ^{
describe(@"batching updates", ^{
beforeEach(^{
+ SDLHMILevel hmiLevelFull = SDLHMILevelFull;
+ testScreenManager.softButtonManager.currentLevel = hmiLevelFull;
+ testScreenManager.textAndGraphicManager.currentLevel = hmiLevelFull;
[testScreenManager beginUpdates];
});
diff --git a/SmartDeviceLinkTests/SDLStreamingMediaLifecycleManagerSpec.m b/SmartDeviceLinkTests/SDLStreamingMediaLifecycleManagerSpec.m
index c33499ecc..9a1ebc2f0 100644
--- a/SmartDeviceLinkTests/SDLStreamingMediaLifecycleManagerSpec.m
+++ b/SmartDeviceLinkTests/SDLStreamingMediaLifecycleManagerSpec.m
@@ -101,7 +101,7 @@ describe(@"the streaming media manager", ^{
__block BOOL readyHandlerSuccess = NO;
__block NSError *readyHandlerError = nil;
- __block id protocolMock = OCMClassMock([SDLAbstractProtocol class]);
+ __block id protocolMock = OCMClassMock([SDLProtocol class]);
beforeEach(^{
readyHandlerSuccess = NO;
diff --git a/SmartDeviceLinkTests/SDLSystemCapabilityManagerSpec.m b/SmartDeviceLinkTests/SDLSystemCapabilityManagerSpec.m
new file mode 100644
index 000000000..ae6ba1ca9
--- /dev/null
+++ b/SmartDeviceLinkTests/SDLSystemCapabilityManagerSpec.m
@@ -0,0 +1,397 @@
+#import <Quick/Quick.h>
+#import <Nimble/Nimble.h>
+
+#import "SDLAudioPassThruCapabilities.h"
+#import "SDLButtonCapabilities.h"
+#import "SDLDisplayCapabilities.h"
+#import "SDLGetSystemCapability.h"
+#import "SDLGetSystemCapabilityResponse.h"
+#import "SDLHMICapabilities.h"
+#import "SDLNavigationCapability.h"
+#import "SDLNotificationConstants.h"
+#import "SDLPhoneCapability.h"
+#import "SDLPresetBankCapabilities.h"
+#import "SDLRegisterAppInterfaceResponse.h"
+#import "SDLRemoteControlCapabilities.h"
+#import "SDLRPCNotificationNotification.h"
+#import "SDLRPCResponseNotification.h"
+#import "SDLScreenParams.h"
+#import "SDLSetDisplayLayoutResponse.h"
+#import "SDLSoftButtonCapabilities.h"
+#import "SDLSystemCapability.h"
+#import "SDLSystemCapabilityManager.h"
+#import "SDLVideoStreamingCapability.h"
+#import "TestConnectionManager.h"
+
+
+QuickSpecBegin(SDLSystemCapabilityManagerSpec)
+
+describe(@"System capability manager", ^{
+ __block SDLSystemCapabilityManager *testSystemCapabilityManager = nil;
+ __block TestConnectionManager *testConnectionManager = nil;
+
+ beforeEach(^{
+ testConnectionManager = [[TestConnectionManager alloc] init];
+ testSystemCapabilityManager = [[SDLSystemCapabilityManager alloc] initWithConnectionManager:testConnectionManager];
+ });
+
+ it(@"should initialize the system capability manager properties correctly", ^{
+ expect(testSystemCapabilityManager.displayCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.hmiCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.softButtonCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.buttonCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.presetBankCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.hmiZoneCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.speechCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.prerecordedSpeechCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.vrCapability).to(beFalse());
+ expect(testSystemCapabilityManager.audioPassThruCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.pcmStreamCapability).to(beNil());
+ expect(testSystemCapabilityManager.phoneCapability).to(beNil());
+ expect(testSystemCapabilityManager.navigationCapability).to(beNil());
+ expect(testSystemCapabilityManager.videoStreamingCapability).to(beNil());
+ expect(testSystemCapabilityManager.remoteControlCapability).to(beNil());
+ });
+
+ context(@"When notified of a register app interface response", ^{
+ __block SDLRegisterAppInterfaceResponse *testRegisterAppInterfaceResponse = nil;
+ __block SDLDisplayCapabilities *testDisplayCapabilities = nil;
+ __block SDLHMICapabilities *testHMICapabilities = nil;
+ __block NSArray<SDLSoftButtonCapabilities *> *testSoftButtonCapabilities = nil;
+ __block NSArray<SDLButtonCapabilities *> *testButtonCapabilities = nil;
+ __block SDLPresetBankCapabilities *testPresetBankCapabilities = nil;
+ __block NSArray<SDLHMIZoneCapabilities> *testHMIZoneCapabilities = nil;
+ __block NSArray<SDLSpeechCapabilities> *testSpeechCapabilities = nil;
+ __block NSArray<SDLPrerecordedSpeech> *testPrerecordedSpeechCapabilities = nil;
+ __block NSArray<SDLVRCapabilities> *testVRCapabilities = nil;
+ __block NSArray<SDLAudioPassThruCapabilities *> *testAudioPassThruCapabilities = nil;
+ __block SDLAudioPassThruCapabilities *testPCMStreamCapability = nil;
+
+ beforeEach(^{
+ testDisplayCapabilities = [[SDLDisplayCapabilities alloc] init];
+ testDisplayCapabilities.graphicSupported = @NO;
+
+ testHMICapabilities = [[SDLHMICapabilities alloc] init];
+ testHMICapabilities.navigation = @NO;
+ testHMICapabilities.phoneCall = @YES;
+ testHMICapabilities.videoStreaming = @YES;
+
+ SDLSoftButtonCapabilities *softButtonCapability = [[SDLSoftButtonCapabilities alloc] init];
+ softButtonCapability.shortPressAvailable = @YES;
+ softButtonCapability.longPressAvailable = @NO;
+ softButtonCapability.upDownAvailable = @NO;
+ softButtonCapability.imageSupported = @YES;
+ testSoftButtonCapabilities = @[softButtonCapability];
+
+ SDLButtonCapabilities *buttonCapabilities = [[SDLButtonCapabilities alloc] init];
+ buttonCapabilities.name = SDLButtonNameOk;
+ buttonCapabilities.shortPressAvailable = @YES;
+ buttonCapabilities.longPressAvailable = @YES;
+ buttonCapabilities.upDownAvailable = @YES;
+ testButtonCapabilities = @[buttonCapabilities];
+
+ testPresetBankCapabilities = [[SDLPresetBankCapabilities alloc] init];
+ testPresetBankCapabilities.onScreenPresetsAvailable = @NO;
+
+ testHMIZoneCapabilities = @[SDLHMIZoneCapabilitiesFront, SDLHMIZoneCapabilitiesBack];
+ testSpeechCapabilities = @[SDLSpeechCapabilitiesText, SDLSpeechCapabilitiesSilence];
+ testPrerecordedSpeechCapabilities = @[SDLPrerecordedSpeechHelp, SDLPrerecordedSpeechInitial];
+ testVRCapabilities = @[SDLVRCapabilitiesText];
+
+ SDLAudioPassThruCapabilities *audioPassThruCapability = [[SDLAudioPassThruCapabilities alloc] init];
+ audioPassThruCapability.samplingRate = SDLSamplingRate8KHZ;
+ audioPassThruCapability.bitsPerSample = SDLBitsPerSample8Bit;
+ audioPassThruCapability.audioType = SDLAudioTypePCM;
+ testAudioPassThruCapabilities = @[audioPassThruCapability];
+ testPCMStreamCapability = audioPassThruCapability;
+
+ testRegisterAppInterfaceResponse = [[SDLRegisterAppInterfaceResponse alloc] init];
+ testRegisterAppInterfaceResponse.displayCapabilities = testDisplayCapabilities;
+ testRegisterAppInterfaceResponse.hmiCapabilities = testHMICapabilities;
+ testRegisterAppInterfaceResponse.softButtonCapabilities = testSoftButtonCapabilities;
+ testRegisterAppInterfaceResponse.buttonCapabilities = testButtonCapabilities;
+ testRegisterAppInterfaceResponse.presetBankCapabilities = testPresetBankCapabilities;
+ testRegisterAppInterfaceResponse.hmiZoneCapabilities = testHMIZoneCapabilities;
+ testRegisterAppInterfaceResponse.speechCapabilities = testSpeechCapabilities;
+ testRegisterAppInterfaceResponse.prerecordedSpeech = testPrerecordedSpeechCapabilities;
+ testRegisterAppInterfaceResponse.vrCapabilities = testVRCapabilities;
+ testRegisterAppInterfaceResponse.audioPassThruCapabilities = testAudioPassThruCapabilities;
+ testRegisterAppInterfaceResponse.pcmStreamCapabilities = testPCMStreamCapability;
+ });
+
+ describe(@"If the Register App Interface request fails", ^{
+ beforeEach(^{
+ testRegisterAppInterfaceResponse.success = @NO;
+ SDLRPCResponseNotification *notification = [[SDLRPCResponseNotification alloc] initWithName:SDLDidReceiveRegisterAppInterfaceResponse object:self rpcResponse:testRegisterAppInterfaceResponse];
+ [[NSNotificationCenter defaultCenter] postNotification:notification];
+ });
+
+ it(@"should not save any of the RAIR capabilities", ^{
+ expect(testSystemCapabilityManager.displayCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.hmiCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.softButtonCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.buttonCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.presetBankCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.hmiZoneCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.speechCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.prerecordedSpeechCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.vrCapability).to(beFalse());
+ expect(testSystemCapabilityManager.audioPassThruCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.pcmStreamCapability).to(beNil());
+ });
+ });
+
+ describe(@"If the Register App Interface request succeeds", ^{
+ beforeEach(^{
+ testRegisterAppInterfaceResponse.success = @YES;
+ SDLRPCResponseNotification *notification = [[SDLRPCResponseNotification alloc] initWithName:SDLDidReceiveRegisterAppInterfaceResponse object:self rpcResponse:testRegisterAppInterfaceResponse];
+ [[NSNotificationCenter defaultCenter] postNotification:notification];
+ });
+
+ it(@"should should save the RAIR capabilities", ^{
+ expect(testSystemCapabilityManager.displayCapabilities).to(equal(testDisplayCapabilities));
+ expect(testSystemCapabilityManager.hmiCapabilities).to(equal(testHMICapabilities));
+ expect(testSystemCapabilityManager.softButtonCapabilities).to(equal(testSoftButtonCapabilities));
+ expect(testSystemCapabilityManager.buttonCapabilities).to(equal(testButtonCapabilities));
+ expect(testSystemCapabilityManager.presetBankCapabilities).to(equal(testPresetBankCapabilities));
+ expect(testSystemCapabilityManager.hmiZoneCapabilities).to(equal(testHMIZoneCapabilities));
+ expect(testSystemCapabilityManager.speechCapabilities).to(equal(testSpeechCapabilities));
+ expect(testSystemCapabilityManager.prerecordedSpeechCapabilities).to(equal(testPrerecordedSpeechCapabilities));
+ expect(testSystemCapabilityManager.vrCapability).to(beTrue());
+ expect(testSystemCapabilityManager.audioPassThruCapabilities).to(equal(testAudioPassThruCapabilities));
+ expect(testSystemCapabilityManager.pcmStreamCapability).to(equal(testPCMStreamCapability));
+ });
+ });
+
+ afterEach(^{
+ // Make sure the system capabilities properties were not inadverdently set
+ expect(testSystemCapabilityManager.phoneCapability).to(beNil());
+ expect(testSystemCapabilityManager.navigationCapability).to(beNil());
+ expect(testSystemCapabilityManager.videoStreamingCapability).to(beNil());
+ expect(testSystemCapabilityManager.remoteControlCapability).to(beNil());
+ });
+ });
+
+ context(@"When notified of a Set Display Layout Response", ^ {
+ __block SDLSetDisplayLayoutResponse *testSetDisplayLayoutResponse = nil;
+ __block SDLDisplayCapabilities *testDisplayCapabilities = nil;
+ __block NSArray<SDLSoftButtonCapabilities *> *testSoftButtonCapabilities = nil;
+ __block NSArray<SDLButtonCapabilities *> *testButtonCapabilities = nil;
+ __block SDLPresetBankCapabilities *testPresetBankCapabilities = nil;
+
+ beforeEach(^{
+ testDisplayCapabilities = [[SDLDisplayCapabilities alloc] init];
+ testDisplayCapabilities.graphicSupported = @NO;
+
+ SDLSoftButtonCapabilities *softButtonCapability = [[SDLSoftButtonCapabilities alloc] init];
+ softButtonCapability.shortPressAvailable = @NO;
+ softButtonCapability.longPressAvailable = @NO;
+ softButtonCapability.upDownAvailable = @NO;
+ softButtonCapability.imageSupported = @NO;
+ testSoftButtonCapabilities = @[softButtonCapability];
+
+ SDLButtonCapabilities *buttonCapabilities = [[SDLButtonCapabilities alloc] init];
+ buttonCapabilities.name = SDLButtonNameOk;
+ buttonCapabilities.shortPressAvailable = @NO;
+ buttonCapabilities.longPressAvailable = @NO;
+ buttonCapabilities.upDownAvailable = @NO;
+ testButtonCapabilities = @[buttonCapabilities];
+
+ testPresetBankCapabilities = [[SDLPresetBankCapabilities alloc] init];
+ testPresetBankCapabilities.onScreenPresetsAvailable = @NO;
+
+ testSetDisplayLayoutResponse = [[SDLSetDisplayLayoutResponse alloc] init];
+ testSetDisplayLayoutResponse.displayCapabilities = testDisplayCapabilities;
+ testSetDisplayLayoutResponse.buttonCapabilities = testButtonCapabilities;
+ testSetDisplayLayoutResponse.softButtonCapabilities = testSoftButtonCapabilities;
+ testSetDisplayLayoutResponse.presetBankCapabilities = testPresetBankCapabilities;
+ });
+
+ describe(@"If the Set Display Layout request fails", ^{
+ beforeEach(^{
+ testSetDisplayLayoutResponse.success = @NO;
+ SDLRPCResponseNotification *notification = [[SDLRPCResponseNotification alloc] initWithName:SDLDidReceiveSetDisplayLayoutResponse object:self rpcResponse:testSetDisplayLayoutResponse];
+ [[NSNotificationCenter defaultCenter] postNotification:notification];
+ });
+
+ it(@"should not save any capabilities", ^{
+ expect(testSystemCapabilityManager.displayCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.softButtonCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.buttonCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.presetBankCapabilities).to(beNil());
+ });
+ });
+
+ describe(@"If the Set Display Layout request succeeds", ^{
+ beforeEach(^{
+ testSetDisplayLayoutResponse.success = @YES;
+ SDLRPCResponseNotification *notification = [[SDLRPCResponseNotification alloc] initWithName:SDLDidReceiveSetDisplayLayoutResponse object:self rpcResponse:testSetDisplayLayoutResponse];
+ [[NSNotificationCenter defaultCenter] postNotification:notification];
+ });
+
+ it(@"should should save the capabilities", ^{
+ expect(testSystemCapabilityManager.displayCapabilities).to(equal(testDisplayCapabilities));
+ expect(testSystemCapabilityManager.softButtonCapabilities).to(equal(testSoftButtonCapabilities));
+ expect(testSystemCapabilityManager.buttonCapabilities).to(equal(testButtonCapabilities));
+ expect(testSystemCapabilityManager.presetBankCapabilities).to(equal(testPresetBankCapabilities));
+ });
+ });
+
+ afterEach(^{
+ // Make sure the other RAIR properties and system capabilities were not inadverdently set
+ expect(testSystemCapabilityManager.hmiCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.hmiZoneCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.speechCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.prerecordedSpeechCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.vrCapability).to(beFalse());
+ expect(testSystemCapabilityManager.audioPassThruCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.pcmStreamCapability).to(beNil());
+ expect(testSystemCapabilityManager.phoneCapability).to(beNil());
+ expect(testSystemCapabilityManager.navigationCapability).to(beNil());
+ expect(testSystemCapabilityManager.videoStreamingCapability).to(beNil());
+ expect(testSystemCapabilityManager.remoteControlCapability).to(beNil());
+ });
+ });
+
+ context(@"When notified of a Get System Capability Response", ^{
+ __block SDLGetSystemCapabilityResponse *testGetSystemCapabilityResponse;
+ __block SDLPhoneCapability *testPhoneCapability = nil;
+
+ beforeEach(^{
+ testPhoneCapability = [[SDLPhoneCapability alloc] initWithDialNumber:YES];
+
+ testGetSystemCapabilityResponse = [[SDLGetSystemCapabilityResponse alloc] init];
+ testGetSystemCapabilityResponse.systemCapability = [[SDLSystemCapability alloc] init];
+ testGetSystemCapabilityResponse.systemCapability.phoneCapability = testPhoneCapability;
+ 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];
+ });
+
+ it(@"should should not save the capabilities", ^{
+ expect(testSystemCapabilityManager.phoneCapability).to(beNil());
+ });
+ });
+
+ 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 save the capabilities", ^{
+ expect(testSystemCapabilityManager.phoneCapability).to(equal(testPhoneCapability));
+ });
+ });
+ });
+
+ 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(testError));
+ expect(systemCapabilityManager.phoneCapability).to(beNil());
+ done();
+ }];
+
+ [testConnectionManager respondToLastRequestWithResponse:testGetSystemCapabilityResponse error:testError];
+ });
+ });
+
+ it(@"should should not save the capabilities", ^{
+ expect(testSystemCapabilityManager.phoneCapability).to(beNil());
+ });
+ });
+
+ context(@"If the request succeeded", ^{
+ beforeEach(^{
+ testGetSystemCapabilityResponse.success = @YES;
+
+ [testSystemCapabilityManager updateCapabilityType:testGetSystemCapabilityResponse.systemCapability.systemCapabilityType completionHandler:^(NSError * _Nullable error, SDLSystemCapabilityManager * _Nonnull systemCapabilityManager) {
+ // The handler will not be notifified
+ }];
+
+ [testConnectionManager respondToLastRequestWithResponse:testGetSystemCapabilityResponse error:nil];
+ });
+
+ 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());
+ });
+ });
+ });
+
+ afterEach(^{
+ // Make sure the RAIR properties and other system capabilities were not inadverdently set
+ expect(testSystemCapabilityManager.displayCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.hmiCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.softButtonCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.buttonCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.presetBankCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.hmiZoneCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.speechCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.prerecordedSpeechCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.vrCapability).to(beFalse());
+ expect(testSystemCapabilityManager.audioPassThruCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.pcmStreamCapability).to(beNil());
+ expect(testSystemCapabilityManager.navigationCapability).to(beNil());
+ expect(testSystemCapabilityManager.videoStreamingCapability).to(beNil());
+ expect(testSystemCapabilityManager.remoteControlCapability).to(beNil());
+ });
+ });
+
+ context(@"When the system capability manager is stopped after being started", ^{
+ beforeEach(^{
+ SDLDisplayCapabilities *testDisplayCapabilities = [[SDLDisplayCapabilities alloc] init];
+ testDisplayCapabilities.graphicSupported = @NO;
+
+ SDLRegisterAppInterfaceResponse *testRegisterAppInterfaceResponse = [[SDLRegisterAppInterfaceResponse alloc] init];
+ testRegisterAppInterfaceResponse.displayCapabilities = testDisplayCapabilities;
+ testRegisterAppInterfaceResponse.success = @YES;
+
+ SDLRPCResponseNotification *notification = [[SDLRPCResponseNotification alloc] initWithName:SDLDidReceiveRegisterAppInterfaceResponse object:self rpcResponse:testRegisterAppInterfaceResponse];
+ [[NSNotificationCenter defaultCenter] postNotification:notification];
+
+ expect(testSystemCapabilityManager.displayCapabilities).to(equal(testDisplayCapabilities));
+ });
+
+ describe(@"When stopped", ^{
+ beforeEach(^{
+ [testSystemCapabilityManager stop];
+ });
+
+ it(@"It should reset the system capability manager properties correctly", ^{
+ expect(testSystemCapabilityManager.displayCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.hmiCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.softButtonCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.buttonCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.presetBankCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.hmiZoneCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.speechCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.prerecordedSpeechCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.vrCapability).to(beFalse());
+ expect(testSystemCapabilityManager.audioPassThruCapabilities).to(beNil());
+ expect(testSystemCapabilityManager.pcmStreamCapability).to(beNil());
+ expect(testSystemCapabilityManager.phoneCapability).to(beNil());
+ expect(testSystemCapabilityManager.navigationCapability).to(beNil());
+ expect(testSystemCapabilityManager.videoStreamingCapability).to(beNil());
+ expect(testSystemCapabilityManager.remoteControlCapability).to(beNil());
+ });
+ });
+ });
+});
+
+QuickSpecEnd
+
diff --git a/SmartDeviceLinkTests/TestUtilities/TestConnectionManager.m b/SmartDeviceLinkTests/TestUtilities/TestConnectionManager.m
index adb494fb6..ba0c29930 100644
--- a/SmartDeviceLinkTests/TestUtilities/TestConnectionManager.m
+++ b/SmartDeviceLinkTests/TestUtilities/TestConnectionManager.m
@@ -35,6 +35,32 @@ NS_ASSUME_NONNULL_BEGIN
[self sendConnectionRequest:request withResponseHandler:handler];
}
+- (void)sendRequests:(nonnull NSArray<SDLRPCRequest *> *)requests progressHandler:(nullable SDLMultipleAsyncRequestProgressHandler)progressHandler completionHandler:(nullable SDLMultipleRequestCompletionHandler)completionHandler {
+ [requests enumerateObjectsUsingBlock:^(SDLRPCRequest * _Nonnull request, NSUInteger idx, BOOL * _Nonnull stop) {
+ [self sendConnectionRequest:request withResponseHandler:nil];
+
+ if (progressHandler != nil) {
+ progressHandler(request, nil, nil, (double)idx / (double)requests.count);
+ }
+ }];
+
+ if (completionHandler != nil) {
+ completionHandler(YES);
+ }
+}
+
+- (void)sendSequentialRequests:(nonnull NSArray<SDLRPCRequest *> *)requests progressHandler:(nullable SDLMultipleSequentialRequestProgressHandler)progressHandler completionHandler:(nullable SDLMultipleRequestCompletionHandler)completionHandler {
+ [requests enumerateObjectsUsingBlock:^(SDLRPCRequest * _Nonnull request, NSUInteger idx, BOOL * _Nonnull stop) {
+ [self sendConnectionRequest:request withResponseHandler:nil];
+ progressHandler(request, nil, nil, (double)idx / (double)requests.count);
+ }];
+
+ if (completionHandler != nil) {
+ completionHandler(YES);
+ }
+}
+
+
- (void)respondToLastRequestWithResponse:(__kindof SDLRPCResponse *)response {
[self respondToLastRequestWithResponse:response error:nil];
}
diff --git a/SmartDeviceLinkTests/UtilitiesSpecs/Touches/SDLTouchManagerSpec.m b/SmartDeviceLinkTests/UtilitiesSpecs/Touches/SDLTouchManagerSpec.m
index 0c45c687e..25fad6316 100644
--- a/SmartDeviceLinkTests/UtilitiesSpecs/Touches/SDLTouchManagerSpec.m
+++ b/SmartDeviceLinkTests/UtilitiesSpecs/Touches/SDLTouchManagerSpec.m
@@ -713,6 +713,7 @@ describe(@"SDLTouchManager Tests", ^{
__block SDLOnTouchEvent* pinchStartFirstFingerOnTouchEvent;
__block SDLOnTouchEvent* pinchStartSecondFingerOnTouchEvent;
+ __block SDLOnTouchEvent* pinchStartTwoFingerOnTouchEvent;
__block SDLOnTouchEvent* pinchMoveSecondFingerOnTouchEvent;
__block SDLOnTouchEvent* pinchEndSecondFingerOnTouchEvent;
__block SDLOnTouchEvent* pinchCancelFirstFingerOnTouchEvent;
@@ -748,6 +749,11 @@ describe(@"SDLTouchManager Tests", ^{
CGFloat pinchStartDistance = hypotf(firstFingerTouchCoord.x.floatValue - secondFingerTouchCoord.x.floatValue,
firstFingerTouchCoord.y.floatValue - secondFingerTouchCoord.y.floatValue);
+ // First and second finger touch down
+ pinchStartTwoFingerOnTouchEvent = [[SDLOnTouchEvent alloc] init];
+ pinchStartTwoFingerOnTouchEvent.event = [NSArray arrayWithObjects:firstFingerTouchEvent, secondFingerTouchEvent, nil];
+ pinchStartTwoFingerOnTouchEvent.type = SDLTouchTypeBegin;
+
// Second finger move
SDLTouchCoord* secondFingerMoveTouchCoord = [[SDLTouchCoord alloc] init];
secondFingerMoveTouchCoord.x = @(secondFingerTouchCoord.x.floatValue - 50);
@@ -850,6 +856,57 @@ describe(@"SDLTouchManager Tests", ^{
expectedNumTimesHandlerCalled = 4;
});
});
+
+ context(@"when first and second touch begin events are notified with single SDLOnTouchEvent, and pinch gesture is not interrupted", ^{
+ it(@"should correctly send all pinch delegate callbacks", ^{
+ pinchStartTests = ^(NSInvocation* invocation) {
+ __unsafe_unretained SDLTouchManager* touchManagerCallback;
+
+ CGPoint point;
+ [invocation getArgument:&touchManagerCallback atIndex:2];
+ [invocation getArgument:&point atIndex:4];
+
+ expect(touchManagerCallback).to(equal(touchManager));
+ expect(@(CGPointEqualToPoint(point, pinchStartCenter))).to(beTruthy());
+ };
+
+ pinchMoveTests = ^(NSInvocation* invocation) {
+ __unsafe_unretained SDLTouchManager* touchManagerCallback;
+
+ CGPoint point;
+ CGFloat scale;
+ [invocation getArgument:&touchManagerCallback atIndex:2];
+ [invocation getArgument:&point atIndex:3];
+ [invocation getArgument:&scale atIndex:4];
+
+ expect(touchManagerCallback).to(equal(touchManager));
+ expect(@(CGPointEqualToPoint(point, pinchMoveCenter))).to(beTruthy());
+ expect(@(scale)).to(beCloseTo(@(pinchMoveScale)).within(0.0001));
+ };
+
+ pinchEndTests = ^(NSInvocation* invocation) {
+ __unsafe_unretained SDLTouchManager* touchManagerCallback;
+
+ CGPoint point;
+ [invocation getArgument:&touchManagerCallback atIndex:2];
+ [invocation getArgument:&point atIndex:4];
+
+ expect(touchManagerCallback).to(equal(touchManager));
+ expect(@(CGPointEqualToPoint(point, pinchEndCenter))).to(beTruthy());
+ };
+
+ performTouchEvent(touchManager, pinchStartTwoFingerOnTouchEvent);
+ performTouchEvent(touchManager, pinchMoveSecondFingerOnTouchEvent);
+ [touchManager syncFrame];
+ performTouchEvent(touchManager, pinchEndSecondFingerOnTouchEvent);
+
+ expectedDidCallBeginPinch = YES;
+ expectedDidCallMovePinch = YES;
+ expectedDidCallEndPinch = YES;
+ expectedDidCallCancelPinch = NO;
+ expectedNumTimesHandlerCalled = 4;
+ });
+ });
context(@"when a pinch gesture is canceled", ^{
it(@"should notify delegates if pinch is canceled right after it started", ^{
diff --git a/SmartDeviceLink_Example/AlertManager.h b/SmartDeviceLink_Example/AlertManager.h
new file mode 100644
index 000000000..1d4471b95
--- /dev/null
+++ b/SmartDeviceLink_Example/AlertManager.h
@@ -0,0 +1,22 @@
+//
+// AlertManager.h
+// SmartDeviceLink-Example-ObjC
+//
+// Created by Nicole on 4/30/18.
+// Copyright © 2018 smartdevicelink. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@class SDLAlert;
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface AlertManager : NSObject
+
++ (SDLAlert *)alertWithMessage:(NSString *)textField1 textField2:(nullable NSString *)textField2;
++ (SDLAlert *)alertWithMessageAndCloseButton:(NSString *)textField1 textField2:(nullable NSString *)textField2;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink_Example/AlertManager.m b/SmartDeviceLink_Example/AlertManager.m
new file mode 100644
index 000000000..cab877a5e
--- /dev/null
+++ b/SmartDeviceLink_Example/AlertManager.m
@@ -0,0 +1,45 @@
+//
+// AlertManager.m
+// SmartDeviceLink-Example-ObjC
+//
+// Created by Nicole on 4/30/18.
+// Copyright © 2018 smartdevicelink. All rights reserved.
+//
+
+#import "AlertManager.h"
+#import "SmartDeviceLink.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@implementation AlertManager
+
+/**
+ * Creates an alert with a single line of text
+ *
+ * @param textField1 The first line of a message to display in the alert
+ * @param textField2 The second line of a message to display in the alert
+ * @return An SDLAlert object
+ */
++ (SDLAlert *)alertWithMessage:(NSString *)textField1 textField2:(nullable NSString *)textField2 {
+ return [[SDLAlert alloc] initWithAlertText1:textField1 alertText2:textField2 duration:5000];
+}
+
+/**
+ * Creates an alert with up to two lines of text and a close button that will dismiss the alert when tapped
+ *
+ * @param textField1 The first line of a message to display in the alert
+ * @param textField2 The second line of a message to display in the alert
+ * @return An SDLAlert object
+ */
++ (SDLAlert *)alertWithMessageAndCloseButton:(NSString *)textField1 textField2:(nullable NSString *)textField2 {
+ return [[SDLAlert alloc] initWithAlertText1:textField1 alertText2:textField2 alertText3:nil duration:5000 softButtons:@[[self sdlex_okSoftButton]]];
+}
+
++ (SDLSoftButton *)sdlex_okSoftButton {
+ SDLSoftButton *okSoftButton = [[SDLSoftButton alloc] initWithType:SDLSoftButtonTypeText text:@"OK" image:nil highlighted:YES buttonId:1 systemAction:nil handler:nil];
+ return okSoftButton;
+}
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink_Example/AlertManager.swift b/SmartDeviceLink_Example/AlertManager.swift
new file mode 100644
index 000000000..c463e7d36
--- /dev/null
+++ b/SmartDeviceLink_Example/AlertManager.swift
@@ -0,0 +1,36 @@
+//
+// AlertManager.swift
+// SmartDeviceLink-Example-Swift
+//
+// Created by Nicole on 4/12/18.
+// Copyright © 2018 smartdevicelink. All rights reserved.
+//
+
+import Foundation
+import SmartDeviceLink
+
+class AlertManager {
+ private class var okSoftButton: SDLSoftButton {
+ return SDLSoftButton(type: .text, text: "OK", image: nil, highlighted: true, buttonId: 1, systemAction: nil, handler: nil)
+ }
+
+ /// Creates an alert with one or two lines of text.
+ ///
+ /// - Parameters:
+ /// - textField1: The first line of a message to display in the alert
+ /// - textField2: The second line of a message to display in the alert
+ /// - Returns: An SDLAlert object
+ class func alertWithMessage(_ textField1: String, textField2: String? = nil) -> SDLAlert {
+ return SDLAlert(alertText1: textField1, alertText2: nil, alertText3: nil)
+ }
+
+ /// Creates an alert with up to two lines of text and a close button that will dismiss the alert when tapped
+ ///
+ /// - Parameters:
+ /// - textField1: The first line of a message to display in the alert
+ /// - textField2: The second line of a message to display in the alert
+ /// - Returns: An SDLAlert object
+ class func alertWithMessageAndCloseButton(_ textField1: String, textField2: String? = nil) -> SDLAlert {
+ return SDLAlert(alertText1: textField1, alertText2: textField2, alertText3: nil, duration: 5000, softButtons: [AlertManager.okSoftButton])
+ }
+}
diff --git a/SmartDeviceLink_Example/AppConstants.h b/SmartDeviceLink_Example/AppConstants.h
new file mode 100644
index 000000000..c38b1b70b
--- /dev/null
+++ b/SmartDeviceLink_Example/AppConstants.h
@@ -0,0 +1,100 @@
+//
+// AppConstants.h
+// SmartDeviceLink
+//
+// Created by Nicole on 4/10/18.
+// Copyright © 2018 smartdevicelink. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+#pragma mark - SDL Configuration
+extern NSString * const ExampleAppName;
+extern NSString * const ExampleAppNameShort;
+extern NSString * const ExampleAppNameTTS;
+extern NSString * const ExampleAppId;
+extern BOOL const ExampleAppShouldRestartSDLManagerOnDisconnect;
+
+#pragma mark - SDL Textfields
+extern NSString * const SmartDeviceLinkText;
+extern NSString * const ExampleAppText;
+
+#pragma mark - SDL Soft Buttons
+extern NSString * const ToggleSoftButton;
+extern NSString * const ToggleSoftButtonImageOnState;
+extern NSString * const ToggleSoftButtonImageOffState;
+extern NSString * const ToggleSoftButtonTextOnState;
+extern NSString * const ToggleSoftButtonTextOffState;
+extern NSString * const ToggleSoftButtonTextTextOnText;
+extern NSString * const ToggleSoftButtonTextTextOffText;
+
+extern NSString * const AlertSoftButton;
+extern NSString * const AlertSoftButtonImageState;
+extern NSString * const AlertSoftButtonTextState;
+extern NSString * const AlertSoftButtonText;
+
+extern NSString * const TextVisibleSoftButton;
+extern NSString * const TextVisibleSoftButtonTextOnState;
+extern NSString * const TextVisibleSoftButtonTextOffState;
+extern NSString * const TextVisibleSoftButtonTextOnText;
+extern NSString * const TextVisibleSoftButtonTextOffText;
+
+extern NSString * const ImagesVisibleSoftButton;
+extern NSString * const ImagesVisibleSoftButtonImageOnState;
+extern NSString * const ImagesVisibleSoftButtonImageOffState;
+extern NSString * const ImagesVisibleSoftButtonImageOnText;
+extern NSString * const ImagesVisibleSoftButtonImageOffText;
+
+#pragma martk - SDL Text-To-Speech
+extern NSString * const TTSGoodJob;
+extern NSString * const TTSYouMissed;
+
+#pragma martk - SDL Voice Commands
+extern NSString * const VCStart;
+extern NSString * const VCStop;
+
+#pragma mark - SDL Perform Interaction Choice Set Menu
+extern NSString * const PICSInitialText;
+extern NSString * const PICSInitialPrompt;
+extern NSString * const PICSHelpPrompt;
+extern NSString * const PICSTimeoutPrompt;
+extern NSString * const PICSFirstChoice;
+extern NSString * const PICSSecondChoice;
+extern NSString * const PICSThirdChoice;
+
+#pragma mark - SDL Add Command Menu
+extern NSString * const ACSpeakAppNameMenuName;
+extern NSString * const ACShowChoiceSetMenuName;
+extern NSString * const ACGetVehicleDataMenuName;
+extern NSString * const ACRecordInCarMicrophoneAudioMenuName;
+extern NSString * const ACDialPhoneNumberMenuName;
+extern NSString * const ACSubmenuMenuName;
+extern NSString * const ACSubmenuItemMenuName;
+
+
+#pragma mark - SDL Image Names
+extern NSString * const ExampleAppLogoName;
+extern NSString * const CarIconImageName;
+extern NSString * const LaptopIconImageName;
+extern NSString * const WheelIconImageName;
+extern NSString * const SpeakBWIconImageName;
+extern NSString * const CarBWIconImageName;
+extern NSString * const MenuBWIconImageName;
+extern NSString * const PhoneBWIconImageName;
+extern NSString * const MicrophoneBWIconImageName;
+
+#pragma mark - SDL App Name in Different Languages
+extern NSString * const ExampleAppNameSpanish;
+extern NSString * const ExampleAppNameFrench;
+
+#pragma mark - SDL Vehicle Data
+extern NSString * const VehicleDataOdometerName;
+extern NSString * const VehicleDataSpeedName;
+
+@interface AppConstants : NSObject
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink_Example/AppConstants.m b/SmartDeviceLink_Example/AppConstants.m
new file mode 100644
index 000000000..c9ff9ad91
--- /dev/null
+++ b/SmartDeviceLink_Example/AppConstants.m
@@ -0,0 +1,95 @@
+//
+// AppConstants.m
+// SmartDeviceLink
+//
+// Created by Nicole on 4/10/18.
+// Copyright © 2018 smartdevicelink. All rights reserved.
+//
+
+#import "AppConstants.h"
+
+#pragma mark - SDL Configuration
+NSString * const ExampleAppName = @"SDL Example App";
+NSString * const ExampleAppNameShort = @"SDL";
+NSString * const ExampleAppNameTTS = @"S D L Example App";
+NSString * const ExampleAppId = @"9c21";
+BOOL const ExampleAppShouldRestartSDLManagerOnDisconnect = NO;
+
+#pragma mark - SDL Textfields
+NSString * const SmartDeviceLinkText = @"SmartDeviceLink (SDL)";
+NSString * const ExampleAppText = @"Example App";
+
+#pragma mark - SDL Soft Buttons
+NSString * const ToggleSoftButton = @"ToggleSoftButton";
+NSString * const ToggleSoftButtonImageOnState = @"ToggleSoftButtonImageOnState";
+NSString * const ToggleSoftButtonImageOffState = @"ToggleSoftButtonImageOffState";
+NSString * const ToggleSoftButtonTextOnState = @"ToggleSoftButtonTextOnState";
+NSString * const ToggleSoftButtonTextOffState = @"ToggleSoftButtonTextOffState";
+NSString * const ToggleSoftButtonTextTextOnText = @"➖";
+NSString * const ToggleSoftButtonTextTextOffText = @"➕";
+
+NSString * const AlertSoftButton = @"AlertSoftButton";
+NSString * const AlertSoftButtonImageState = @"AlertSoftButtonImageState";
+NSString * const AlertSoftButtonTextState = @"AlertSoftButtonTextState";
+NSString * const AlertSoftButtonText = @"Tap Me";
+
+NSString * const TextVisibleSoftButton = @"TextVisibleSoftButton";
+NSString * const TextVisibleSoftButtonTextOnState = @"TextVisibleSoftButtonTextOnState";
+NSString * const TextVisibleSoftButtonTextOffState = @"TextVisibleSoftButtonTextOffState";
+NSString * const TextVisibleSoftButtonTextOnText = @"➖Text";
+NSString * const TextVisibleSoftButtonTextOffText = @"➕Text";
+
+NSString * const ImagesVisibleSoftButton = @"ImagesVisibleSoftButton";
+NSString * const ImagesVisibleSoftButtonImageOnState = @"ImagesVisibleSoftButtonImageOnState";
+NSString * const ImagesVisibleSoftButtonImageOffState = @"ImagesVisibleSoftButtonImageOffState";
+NSString * const ImagesVisibleSoftButtonImageOnText = @"➖Icons";
+NSString * const ImagesVisibleSoftButtonImageOffText = @"➕Icons";
+
+#pragma mart - SDL Text-To-Speech
+NSString * const TTSGoodJob = @"Good Job";
+NSString * const TTSYouMissed = @"You Missed";
+
+#pragma martk - SDL Voice Commands
+NSString * const VCStart = @"Start";
+NSString * const VCStop = @"Stop";
+
+#pragma mark - SDL Perform Interaction Choice Set Menu
+NSString * const PICSInitialText = @"Perform Interaction Choice Set Menu Example";
+NSString * const PICSInitialPrompt = @"Select an item from the menu";
+NSString * const PICSHelpPrompt = @"Select a menu row using your voice or by tapping on the screen";
+NSString * const PICSTimeoutPrompt = @"Closing the menu";
+NSString * const PICSFirstChoice = @"First Choice";
+NSString * const PICSSecondChoice = @"Second Choice";
+NSString * const PICSThirdChoice = @"Third Choice";
+
+#pragma mark - SDL Add Command Menu
+NSString * const ACSpeakAppNameMenuName = @"Speak App Name";
+NSString * const ACShowChoiceSetMenuName = @"Show Perform Interaction Choice Set";
+NSString * const ACGetVehicleDataMenuName = @"Get Vehicle Speed";
+NSString * const ACRecordInCarMicrophoneAudioMenuName = @"Record In-Car Microphone Audio";
+NSString * const ACDialPhoneNumberMenuName = @"Dial Phone Number";
+NSString * const ACSubmenuMenuName = @"Submenu";
+NSString * const ACSubmenuItemMenuName = @"Item";
+
+#pragma mark - SDL Image Names
+NSString * const ExampleAppLogoName = @"sdl_logo_green";
+NSString * const CarIconImageName = @"car_icon";
+NSString * const LaptopIconImageName = @"laptop_icon";
+NSString * const WheelIconImageName = @"wheel_icon";
+NSString * const SpeakBWIconImageName = @"speak";
+NSString * const CarBWIconImageName = @"car";
+NSString * const MenuBWIconImageName = @"choice_set";
+NSString * const PhoneBWIconImageName = @"phone";
+NSString * const MicrophoneBWIconImageName = @"microphone";
+
+#pragma mark - SDL App Name in Different Languages
+NSString * const ExampleAppNameSpanish = @"SDL Aplicación de ejemplo";
+NSString * const ExampleAppNameFrench = @"SDL Exemple App";
+
+#pragma mark - SDL Vehicle Data
+NSString * const VehicleDataOdometerName = @"Odometer";
+NSString * const VehicleDataSpeedName = @"Speed";
+
+@implementation AppConstants
+
+@end
diff --git a/SmartDeviceLink_Example/Classes/AppDelegate.h b/SmartDeviceLink_Example/AppDelegate.h
index b86efb1a6..b86efb1a6 100644
--- a/SmartDeviceLink_Example/Classes/AppDelegate.h
+++ b/SmartDeviceLink_Example/AppDelegate.h
diff --git a/SmartDeviceLink_Example/Classes/AppDelegate.m b/SmartDeviceLink_Example/AppDelegate.m
index 1ceb6f765..1ceb6f765 100644
--- a/SmartDeviceLink_Example/Classes/AppDelegate.m
+++ b/SmartDeviceLink_Example/AppDelegate.m
diff --git a/SmartDeviceLink_Example/AppDelegate.swift b/SmartDeviceLink_Example/AppDelegate.swift
new file mode 100644
index 000000000..fd42468d3
--- /dev/null
+++ b/SmartDeviceLink_Example/AppDelegate.swift
@@ -0,0 +1,44 @@
+//
+// AppDelegate.swift
+// SmartDeviceLink-ExampleSwift
+//
+// Created by Bretty White on 5/12/17.
+// Copyright © 2017 smartdevicelink. All rights reserved.
+//
+
+import UIKit
+
+@UIApplicationMain
+class AppDelegate: UIResponder, UIApplicationDelegate {
+
+ var window: UIWindow?
+
+ func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
+
+ AppUserDefaults.setDefaults()
+
+ return true
+ }
+
+ func applicationWillResignActive(_ application: UIApplication) {
+ // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
+ // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
+ }
+
+ func applicationDidEnterBackground(_ application: UIApplication) {
+ // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
+ // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
+ }
+
+ func applicationWillEnterForeground(_ application: UIApplication) {
+ // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
+ }
+
+ func applicationDidBecomeActive(_ application: UIApplication) {
+ // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
+ }
+
+ func applicationWillTerminate(_ application: UIApplication) {
+ // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
+ }
+}
diff --git a/SmartDeviceLink_Example/AppUserDefaults.swift b/SmartDeviceLink_Example/AppUserDefaults.swift
new file mode 100644
index 000000000..2589ab467
--- /dev/null
+++ b/SmartDeviceLink_Example/AppUserDefaults.swift
@@ -0,0 +1,43 @@
+//
+// ESUserDefaults.swift
+// SmartDeviceLink-iOS
+//
+// Copyright © 2017 smartdevicelink. All rights reserved.
+//
+import UIKit
+
+class AppUserDefaults {
+ struct Keys {
+ static let ipAddress = "ipAddress"
+ static let port = "port"
+ }
+
+ static let shared = AppUserDefaults()
+
+ static func setDefaults() {
+ var defaults: [String : Any] = [:]
+
+ defaults[Keys.ipAddress] = String()
+ defaults[Keys.port] = String()
+
+ UserDefaults.standard.register(defaults: defaults)
+ }
+
+ var ipAddress: String? {
+ get {
+ return UserDefaults.standard.string(forKey: Keys.ipAddress)
+ }
+ set {
+ UserDefaults.standard.set(newValue!, forKey: Keys.ipAddress)
+ }
+ }
+
+ var port: String? {
+ get {
+ return UserDefaults.standard.string(forKey: Keys.port)
+ }
+ set {
+ UserDefaults.standard.setValue(newValue!, forKeyPath: Keys.port)
+ }
+ }
+}
diff --git a/SmartDeviceLink_Example/AudioManager.h b/SmartDeviceLink_Example/AudioManager.h
new file mode 100644
index 000000000..b02138e2c
--- /dev/null
+++ b/SmartDeviceLink_Example/AudioManager.h
@@ -0,0 +1,26 @@
+//
+// AudioManager.h
+// SmartDeviceLink
+//
+// Created by Nicole on 4/23/18.
+// Copyright © 2018 smartdevicelink. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@class SDLManager;
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface AudioManager : NSObject
+
+- (instancetype)init NS_UNAVAILABLE;
+- (instancetype)initWithManager:(SDLManager *)manager;
+- (void)stopManager;
+
+- (void)startRecording;
+- (void)stopRecording;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink_Example/AudioManager.m b/SmartDeviceLink_Example/AudioManager.m
new file mode 100644
index 000000000..6d1b66c48
--- /dev/null
+++ b/SmartDeviceLink_Example/AudioManager.m
@@ -0,0 +1,277 @@
+//
+// AudioManager.m
+// SmartDeviceLink
+//
+// Created by Nicole on 4/23/18.
+// Copyright © 2018 smartdevicelink. All rights reserved.
+//
+
+#import "AlertManager.h"
+#import "AudioManager.h"
+#import <AVFoundation/AVFoundation.h>
+#import "SDLLogMacros.h"
+#import "SmartDeviceLink.h"
+#import <Speech/Speech.h>
+
+
+typedef NS_ENUM(NSUInteger, AudioRecordingState) {
+ AudioRecordingStateListening,
+ AudioRecordingStateNotListening
+};
+
+typedef NS_ENUM(NSUInteger, SpeechRecognitionAuthState) {
+ SpeechRecognitionAuthStateAuthorized,
+ SpeechRecognitionAuthStateNotAuthorized,
+ SpeechRecognitionAuthStateBadRegion
+};
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface AudioManager () <SFSpeechRecognizerDelegate>
+
+@property (strong, nonatomic) SDLManager *sdlManager;
+@property (strong, nonatomic, nullable) NSMutableData *audioData;
+@property (assign, nonatomic) AudioRecordingState audioRecordingState;
+
+@property (assign, nonatomic) SpeechRecognitionAuthState speechRecognitionAuthState;
+@property (strong, nonatomic, nullable) SFSpeechAudioBufferRecognitionRequest *speechRecognitionRequest;
+@property (strong, nonatomic) SFSpeechRecognizer *speechRecognizer;
+@property (strong, nonatomic, nullable) SFSpeechRecognitionTask *speechRecognitionTask;
+@property (strong, nonatomic) NSString *speechTranscription;
+
+@property (nonatomic, copy, nullable) SDLResponseHandler audioPassThruEndedHandler;
+@property (nonatomic, copy, nullable) void (^audioDataReceivedHandler)(NSData *__nullable audioData);
+
+@end
+
+
+@implementation AudioManager
+
+#pragma mark - Lifecycle
+
+- (instancetype)initWithManager:(SDLManager *)manager {
+ self = [super init];
+ if (!self) {
+ return nil;
+ }
+
+ _sdlManager = manager;
+ _audioData = [NSMutableData data];
+ _audioRecordingState = AudioRecordingStateNotListening;
+ _speechRecognitionAuthState = SpeechRecognitionAuthStateNotAuthorized;
+ NSLocale *speechDefaultLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en-US"];
+ _speechRecognizer = [[SFSpeechRecognizer alloc] initWithLocale:speechDefaultLocale];
+ _speechRecognizer.delegate = self;
+ _speechRecognitionAuthState = [AudioManager sdlex_checkSpeechRecognizerAuth:self.speechRecognizer];
+
+ if (self.speechRecognitionAuthState != SpeechRecognitionAuthStateAuthorized) {
+ [self sdlex_requestSFSpeechRecognizerAuthorization];
+ }
+
+ return self;
+}
+
+/**
+ * Resets the manager
+ */
+- (void)stopManager {
+ self.audioRecordingState = AudioRecordingStateNotListening;
+ self.audioData = [NSMutableData data];
+ self.speechTranscription = @"";
+}
+
+/**
+ * Starts an audio recording using the in-car microphone. During the recording, a pop-up will let the user know that they are being recorded. The pop-up is only dismissed when the recording stops.
+ */
+- (void)startRecording {
+ if (self.speechRecognitionAuthState != SpeechRecognitionAuthStateAuthorized) {
+ SDLLogW(@"This app does not have permission to access the Speech Recognition API");
+ [self.sdlManager sendRequest:[AlertManager alertWithMessageAndCloseButton:@"You must give this app permission to access Speech Recognition" textField2:nil]];
+ return;
+ }
+
+ if (self.audioRecordingState != AudioRecordingStateNotListening) {
+ SDLLogW(@"Audio recording already in progress");
+ return;
+ }
+
+ [self sdlex_startSpeechRecognitionTask];
+
+ UInt32 recordingDurationInMilliseconds = 10000;
+ SDLPerformAudioPassThru *performAudioPassThru = [[SDLPerformAudioPassThru alloc] initWithInitialPrompt:@"Starting sound recording" audioPassThruDisplayText1:@"Say Something" audioPassThruDisplayText2:[NSString stringWithFormat:@"Recording for %d seconds", (recordingDurationInMilliseconds / 1000)] samplingRate:SDLSamplingRate16KHZ bitsPerSample:SDLBitsPerSample16Bit audioType:SDLAudioTypePCM maxDuration:recordingDurationInMilliseconds muteAudio:true audioDataHandler:self.audioDataReceivedHandler];
+
+ [self.sdlManager sendRequest:performAudioPassThru withResponseHandler:self.audioPassThruEndedHandler];
+}
+
+/**
+ * Manually stop an ongoing audio recording.
+ */
+- (void)stopRecording {
+ if (self.audioRecordingState != AudioRecordingStateListening) { return; }
+ self.audioRecordingState = AudioRecordingStateNotListening;
+
+ SDLEndAudioPassThru *endAudioPassThru = [[SDLEndAudioPassThru alloc] init];
+ [self.sdlManager sendRequest:endAudioPassThru];
+}
+
+#pragma mark - Audio Pass Thru Notifications
+
+/**
+ * SDL streams the audio data as it is collected.
+ */
+- (nullable void (^)(NSData * _Nullable))audioDataReceivedHandler {
+ if (!_audioDataReceivedHandler) {
+ __weak typeof(self) weakSelf = self;
+ self.audioDataReceivedHandler = ^(NSData * _Nullable audioData) {
+ if (audioData.length == 0) { return; }
+ if (weakSelf.audioRecordingState == AudioRecordingStateNotListening) {
+ weakSelf.audioData = [NSMutableData data];
+ weakSelf.audioRecordingState = AudioRecordingStateListening;
+ }
+
+ AVAudioPCMBuffer *buffer = [weakSelf sdlex_createPCMBufferWithData:[NSMutableData dataWithData:audioData]];
+ if (buffer == nil) { return; }
+ [weakSelf.speechRecognitionRequest appendAudioPCMBuffer:buffer];
+ };
+ }
+
+ return _audioDataReceivedHandler;
+}
+
+/**
+ * Called when `PerformAudioPassThru` request times out or when a `EndAudioPassThru` request is sent
+ *
+ * @return A SDLResponseHandler
+ */
+- (nullable SDLResponseHandler)audioPassThruEndedHandler {
+ if (!_audioPassThruEndedHandler) {
+ __weak typeof(self) weakSelf = self;
+ self.audioPassThruEndedHandler = ^(__kindof SDLRPCRequest * _Nullable request, __kindof SDLRPCResponse * _Nullable response, NSError * _Nullable error) {
+ if (response == nil) { return; }
+ weakSelf.audioRecordingState = AudioRecordingStateNotListening;
+
+ SDLResult resultCode = response.resultCode;
+ if ([resultCode isEqualToEnum:SDLResultSuccess]) {
+ // The `PerformAudioPassThru` timed out or the "Done" button was pressed in the pop-up.
+ SDLLogD(@"Audio Pass Thru ended successfully");
+ NSString *alertMessage = [NSString stringWithFormat:@"You said: %@", weakSelf.speechTranscription.length == 0 ? @"No speech detected" : weakSelf.speechTranscription];
+ [weakSelf.sdlManager sendRequest:[AlertManager alertWithMessageAndCloseButton:alertMessage textField2:nil]];
+ } else if ([resultCode isEqualToEnum:SDLResultAborted]) {
+ // The "Cancel" button was pressed in the pop-up. Ignore this audio pass thru.
+ SDLLogD(@"Audio recording canceled");
+ } else {
+ SDLLogD(@"Audio recording not successful: \(response.resultCode)");
+ }
+
+ [weakSelf sdlex_stopSpeechRecognitionTask];
+ };
+ }
+
+ return _audioPassThruEndedHandler;
+}
+
+#pragma mark - Audio Data Conversion
+
+/**
+ * Converts the audio data to PCM formatted audio that can be passed, if desired, to the iOS SFSpeech framework (SDL does not provide speech recognition, however the SFSpeech framework or another third party library can be used for speech recognition). The audio format and sample rate should match those set in the `SDLPerformAudioPassThru`.
+ *
+ * @param data The audio data
+ * @return An AVAudioPCMBuffer object
+ */
+- (AVAudioPCMBuffer *)sdlex_createPCMBufferWithData:(NSMutableData *)data {
+ [self.audioData appendData:data];
+
+ AVAudioFormat *audioFormat = [[AVAudioFormat alloc] initWithCommonFormat:AVAudioPCMFormatInt16 sampleRate:16000 channels:1 interleaved:NO];
+ UInt32 numberOfFrames = (UInt32)data.length / audioFormat.streamDescription->mBytesPerFrame;
+ AVAudioPCMBuffer *buffer = [[AVAudioPCMBuffer alloc] initWithPCMFormat:audioFormat frameCapacity:numberOfFrames];
+ buffer.frameLength = numberOfFrames;
+
+ memcpy(buffer.int16ChannelData[0], data.bytes, data.length);
+
+ return buffer;
+}
+
+#pragma mark - Speech Recognition
+
+/**
+ * Configures speech recognition
+ */
+- (void)sdlex_startSpeechRecognitionTask {
+ self.speechRecognitionRequest = [[SFSpeechAudioBufferRecognitionRequest alloc] init];
+
+ if (self.speechRecognitionRequest == nil || self.speechRecognizer == nil) {
+ SDLLogE(@"Unable to do speech recognition");
+ return;
+ }
+
+ self.speechRecognitionRequest.shouldReportPartialResults = YES;
+ self.speechRecognitionRequest.taskHint = SFSpeechRecognitionTaskHintSearch;
+
+ self.speechRecognitionTask = [self.speechRecognizer recognitionTaskWithRequest:self.speechRecognitionRequest resultHandler:^(SFSpeechRecognitionResult * _Nullable result, NSError * _Nullable error) {
+ if (result == nil) { return; }
+ if (error != nil) {
+ SDLLogE(@"Speech recognition error: %@", error.localizedDescription);
+ return;
+ }
+
+ NSString *speechTranscription = result.bestTranscription.formattedString;
+ SDLLogD(@"Ongoing transcription: %@", speechTranscription);
+ self.speechTranscription = speechTranscription;
+ }];
+}
+
+/**
+ * Cleans up a speech detection session that has ended
+ */
+- (void)sdlex_stopSpeechRecognitionTask {
+ self.audioRecordingState = AudioRecordingStateNotListening;
+ self.audioData = [NSMutableData data];
+ self.speechTranscription = @"";
+ [self.speechRecognitionTask cancel];
+ [self.speechRecognitionRequest endAudio];
+ self.speechRecognitionTask = nil;
+ self.speechRecognitionRequest = nil;
+}
+
+#pragma mark - Speech Recognition Authorization
+
+- (void)speechRecognizer:(SFSpeechRecognizer *)speechRecognizer availabilityDidChange:(BOOL)available {
+ self.speechRecognitionAuthState = [AudioManager sdlex_checkSpeechRecognizerAuth:speechRecognizer];
+}
+
+/**
+ * Checks the current authorization status of the Speech Recognition API. The user can change this status via the native Settings app.
+ *
+ * @param speechRecognizer The SFSpeechRecognizer
+ * @return The current authorization status
+ */
++ (SpeechRecognitionAuthState)sdlex_checkSpeechRecognizerAuth:(SFSpeechRecognizer *)speechRecognizer {
+ if (speechRecognizer == nil) {
+ return SpeechRecognitionAuthStateBadRegion;
+ }
+
+ if (SFSpeechRecognizer.authorizationStatus == SFSpeechRecognizerAuthorizationStatusAuthorized) {
+ return SpeechRecognitionAuthStateAuthorized;
+ } else {
+ return SpeechRecognitionAuthStateNotAuthorized;
+ }
+}
+
+/**
+ * Asks the user via an alert if they want to authorize this app to access the Speech Recognition API.
+ */
+- (void)sdlex_requestSFSpeechRecognizerAuthorization {
+ [SFSpeechRecognizer requestAuthorization:^(SFSpeechRecognizerAuthorizationStatus status) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ if (status == SFSpeechRecognizerAuthorizationStatusAuthorized) {
+ self.speechRecognitionAuthState = SpeechRecognitionAuthStateAuthorized;
+ } else {
+ self.speechRecognitionAuthState = SpeechRecognitionAuthStateNotAuthorized;
+ }
+ });
+ }];
+}
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink_Example/AudioManager.swift b/SmartDeviceLink_Example/AudioManager.swift
new file mode 100644
index 000000000..a2e80929d
--- /dev/null
+++ b/SmartDeviceLink_Example/AudioManager.swift
@@ -0,0 +1,229 @@
+//
+// AudioManager.swift
+// SmartDeviceLink
+//
+// Created by Nicole on 4/17/18.
+// Copyright © 2018 smartdevicelink. All rights reserved.
+//
+
+import Foundation
+import SmartDeviceLink
+import SmartDeviceLinkSwift
+import Speech
+
+fileprivate enum AudioRecordingState {
+ case listening, notListening
+}
+
+fileprivate enum SpeechRecognitionAuthState {
+ case authorized, notAuthorized, badRegion
+}
+
+@available(iOS 10.0, *)
+class AudioManager: NSObject {
+ fileprivate let sdlManager: SDLManager
+ fileprivate var audioData: Data?
+ fileprivate var audioRecordingState: AudioRecordingState
+
+ fileprivate var speechRecognitionAuthState: SpeechRecognitionAuthState
+ fileprivate var speechRecognitionRequest: SFSpeechAudioBufferRecognitionRequest?
+ fileprivate var speechRecognizer: SFSpeechRecognizer?
+ fileprivate var speechRecognitionTask: SFSpeechRecognitionTask?
+ fileprivate var speechTranscription: String = ""
+ private let speechDefaultLocale = Locale(identifier: "en-US")
+
+ init(sdlManager: SDLManager) {
+ self.sdlManager = sdlManager
+ audioData = Data()
+ audioRecordingState = .notListening
+ speechRecognitionAuthState = .notAuthorized
+ speechRecognizer = SFSpeechRecognizer(locale: speechDefaultLocale)
+
+ super.init()
+
+ speechRecognizer?.delegate = self
+ speechRecognitionAuthState = AudioManager.checkAuthorization(speechRecognizer: speechRecognizer)
+
+ if speechRecognitionAuthState != .authorized {
+ requestSFSpeechRecognizerAuthorization()
+ }
+ }
+
+ /// Resets the manager to its default values
+ func stopManager() {
+ audioRecordingState = .notListening
+ audioData = Data()
+ speechTranscription = ""
+ }
+
+ /// Starts an audio recording using the in-car microphone. During the recording, a pop-up will let the user know that they are being recorded. The pop-up is only dismissed when the recording stops.
+ func startRecording() {
+ guard speechRecognitionAuthState == .authorized else {
+ SDLLog.w("This app does not have permission to access the Speech Recognition API")
+ sdlManager.send(AlertManager.alertWithMessageAndCloseButton("You must give this app permission to access Speech Recognition"))
+ return
+ }
+
+ guard audioRecordingState == .notListening else {
+ SDLLog.w("Audio recording already in progress")
+ return
+ }
+
+ startSpeechRecognitionTask()
+ let recordingDurationMilliseconds: UInt32 = 10000
+ let performAudioPassThru = SDLPerformAudioPassThru(initialPrompt: "Starting sound recording", audioPassThruDisplayText1: "Say Something", audioPassThruDisplayText2: "Recording for \(recordingDurationMilliseconds / 1000) seconds", samplingRate: .rate16KHZ, bitsPerSample: .sample16Bit, audioType: .PCM, maxDuration: recordingDurationMilliseconds, muteAudio: true, audioDataHandler: audioDataReceivedHandler)
+
+ sdlManager.send(request: performAudioPassThru, responseHandler: audioPassThruEndedHandler)
+ }
+
+ /// Manually stop an ongoing audio recording.
+ func stopRecording() {
+ guard audioRecordingState == .listening else { return }
+ audioRecordingState = .notListening
+
+ let endAudioPassThruRequest = SDLEndAudioPassThru()
+ sdlManager.send(endAudioPassThruRequest)
+ }
+}
+
+// MARK: - Audio Pass Thru Notifications
+
+@available(iOS 10.0, *)
+private extension AudioManager {
+ /// SDL streams the audio data as it is collected.
+ var audioDataReceivedHandler: SDLAudioPassThruHandler? {
+ return { [weak self] data in
+ guard let data = data else { return }
+ if self?.audioRecordingState == .notListening {
+ self?.audioRecordingState = .listening
+ }
+
+ guard let buffer = self?.createPCMBuffer(with: data) else { return }
+ self?.speechRecognitionRequest!.append(buffer)
+ }
+ }
+
+ /// Called when `PerformAudioPassThru` request times out or when a `EndAudioPassThru` request is sent
+ var audioPassThruEndedHandler: SDLResponseHandler? {
+ return { [weak self] (request, response, error) in
+ guard let response = response else { return }
+
+ switch response.resultCode {
+ case .success: // The `PerformAudioPassThru` timed out or the "Done" button was pressed in the pop-up.
+ SDLLog.d("Audio Pass Thru ended successfully")
+ guard let speechTranscription = self?.speechTranscription else { return }
+ self?.sdlManager.send(AlertManager.alertWithMessageAndCloseButton("You said: \(speechTranscription.isEmpty ? "No speech detected" : speechTranscription)"))
+ case .aborted: // The "Cancel" button was pressed in the pop-up. Ignore this audio pass thru.
+ SDLLog.d("Audio recording canceled")
+ default:
+ SDLLog.d("Audio recording not successful: \(response.resultCode)")
+ }
+
+ self?.stopSpeechRecognitionTask()
+ }
+ }
+
+ /// Converts the audio data to PCM formatted audio that can be passed, if desired, to the iOS SFSpeech framework (SDL does not provide speech recognition, however the SFSpeech framework or another third party library can be used for speech recognition). The audio format and sample rate should match those set in the `SDLPerformAudioPassThru`.
+ ///
+ /// - Parameter data: The audio data
+ /// - Returns: An AVAudioPCMBuffer object
+ func createPCMBuffer(with data: Data) -> AVAudioPCMBuffer {
+ audioData?.append(data)
+
+ let audioFormat = AVAudioFormat(commonFormat: .pcmFormatInt16, sampleRate: 16000, channels: 1, interleaved: false)
+ let numFrames = UInt32(data.count) / (audioFormat.streamDescription.pointee.mBytesPerFrame)
+ let buffer = AVAudioPCMBuffer(pcmFormat: audioFormat, frameCapacity: numFrames)
+ buffer.frameLength = numFrames
+ let bufferChannels = buffer.int16ChannelData!
+ let bufferDataCount = data.copyBytes(to: UnsafeMutableBufferPointer(start: bufferChannels[0], count: data.count))
+
+ SDLLog.v("Audio data has \(bufferDataCount) bytes in \(buffer)")
+
+ return buffer
+ }
+}
+
+// MARK: - Speech Recognition
+
+@available(iOS 10.0, *)
+private extension AudioManager {
+ /// Configures speech recognition
+ func startSpeechRecognitionTask() {
+ speechRecognitionRequest = SFSpeechAudioBufferRecognitionRequest()
+ guard let speechRecognitionRequest = speechRecognitionRequest, let speechRecognizer = speechRecognizer else {
+ SDLLog.e("Unable to do speech recognition")
+ return
+ }
+
+ speechRecognitionRequest.shouldReportPartialResults = true
+ speechRecognitionRequest.taskHint = .search
+
+ speechRecognitionTask = speechRecognizer.recognitionTask(with: speechRecognitionRequest) { [weak self] result, error in
+ guard let result = result else { return }
+
+ if error != nil {
+ SDLLog.e("Speech recognition error: \(error!.localizedDescription)")
+ }
+
+ let speechTranscription = result.bestTranscription.formattedString
+ SDLLog.d("Ongoing transcription: \(speechTranscription)")
+ self?.speechTranscription = speechTranscription
+ }
+ }
+
+ /// Cleans up a speech detection session that has ended
+ func stopSpeechRecognitionTask() {
+ audioRecordingState = .notListening
+ audioData = Data()
+ speechTranscription = ""
+
+ guard self.speechRecognitionTask != nil, self.speechRecognitionRequest != nil else { return }
+ self.speechRecognitionTask!.cancel()
+ self.speechRecognitionRequest!.endAudio()
+ self.speechRecognitionTask = nil
+ self.speechRecognitionRequest = nil
+ }
+}
+
+// MARK: - Speech Recognition Authorization
+
+@available(iOS 10.0, *)
+extension AudioManager: SFSpeechRecognizerDelegate {
+ func speechRecognizer(_ speechRecognizer: SFSpeechRecognizer, availabilityDidChange available: Bool) {
+ speechRecognitionAuthState = AudioManager.checkAuthorization(speechRecognizer: speechRecognizer)
+ }
+
+ /// Checks the current authorization status of the Speech Recognition API. The user can change this status via the native Settings app.
+ ///
+ /// - Parameter speechRecognizer: The SFSpeechRecognizer
+ /// - Returns: The current authorization status
+ fileprivate static func checkAuthorization(speechRecognizer: SFSpeechRecognizer?) -> SpeechRecognitionAuthState {
+ // Check if the speech recognizer init'd successfully
+ guard speechRecognizer != nil else {
+ return .badRegion
+ }
+
+ // Check authorization status
+ switch SFSpeechRecognizer.authorizationStatus() {
+ case .authorized:
+ return .authorized
+ default:
+ return .notAuthorized
+ }
+ }
+
+ /// Asks the user via an alert if they want to authorize this app to access the Speech Recognition API.
+ fileprivate func requestSFSpeechRecognizerAuthorization() {
+ SFSpeechRecognizer.requestAuthorization { authStatus in
+ OperationQueue.main.addOperation {
+ switch authStatus {
+ case .authorized:
+ self.speechRecognitionAuthState = .authorized
+ default:
+ self.speechRecognitionAuthState = .notAuthorized
+ }
+ }
+ }
+ }
+}
+
diff --git a/SmartDeviceLink_Example/Base.lproj/ConnectionTCPTableViewController.storyboard b/SmartDeviceLink_Example/Base.lproj/ConnectionTCPTableViewController.storyboard
index 6f06da1a2..d72ed86c3 100644
--- a/SmartDeviceLink_Example/Base.lproj/ConnectionTCPTableViewController.storyboard
+++ b/SmartDeviceLink_Example/Base.lproj/ConnectionTCPTableViewController.storyboard
@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16F73" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="l5Q-ZP-1BO">
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14109" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="l5Q-ZP-1BO">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
- <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14088"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
@@ -22,14 +22,14 @@
<tableViewSection headerTitle="TCP Server" id="bF6-yi-Ial">
<cells>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="pbJ-oz-jNt">
- <rect key="frame" x="0.0" y="56" width="375" height="44"/>
+ <rect key="frame" x="0.0" y="55.5" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="pbJ-oz-jNt" id="B7X-yY-lwJ">
- <rect key="frame" x="0.0" y="0.0" width="375" height="43"/>
+ <rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="IP Address" clearsOnBeginEditing="YES" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="xqM-s4-9RV">
- <rect key="frame" x="8" y="0.0" width="359" height="44"/>
+ <rect key="frame" x="16" y="0.0" width="343" height="44"/>
<constraints>
<constraint firstAttribute="height" constant="44" id="5Pw-mh-x83"/>
</constraints>
@@ -45,14 +45,14 @@
</tableViewCellContentView>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="C5b-fS-v3d">
- <rect key="frame" x="0.0" y="100" width="375" height="44"/>
+ <rect key="frame" x="0.0" y="99.5" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="C5b-fS-v3d" id="ZD4-xA-og5">
- <rect key="frame" x="0.0" y="0.0" width="375" height="43"/>
+ <rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="Port" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="hsI-ld-8xY">
- <rect key="frame" x="8" y="0.0" width="359" height="44"/>
+ <rect key="frame" x="16" y="0.0" width="343" height="44"/>
<constraints>
<constraint firstAttribute="height" constant="44" id="FpG-5e-MHT"/>
</constraints>
@@ -72,14 +72,14 @@
<tableViewSection headerTitle="" id="rgl-Lm-uDH">
<cells>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="ybX-Eh-Hbx">
- <rect key="frame" x="0.0" y="164" width="375" height="44"/>
+ <rect key="frame" x="0.0" y="163.5" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="ybX-Eh-Hbx" id="uI9-fK-205">
- <rect key="frame" x="0.0" y="0.0" width="375" height="43"/>
+ <rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="tailTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="t37-4W-6F4">
- <rect key="frame" x="8" y="0.0" width="359" height="43"/>
+ <rect key="frame" x="16" y="0.0" width="343" height="43"/>
<fontDescription key="fontDescription" type="system" pointSize="23"/>
<state key="normal" title="Connect">
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
diff --git a/SmartDeviceLink_Example/Base.lproj/Main.storyboard b/SmartDeviceLink_Example/Base.lproj/Main.storyboard
index e7cf57e32..848eb40ab 100644
--- a/SmartDeviceLink_Example/Base.lproj/Main.storyboard
+++ b/SmartDeviceLink_Example/Base.lproj/Main.storyboard
@@ -1,8 +1,12 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15G31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="mM3-m6-I5t">
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14109" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="mM3-m6-I5t">
+ <device id="retina4_7" orientation="portrait">
+ <adaptation id="fullscreen"/>
+ </device>
<dependencies>
<deployment identifier="iOS"/>
- <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14088"/>
+ <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Navigation Controller-->
@@ -11,7 +15,7 @@
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="mM3-m6-I5t" sceneMemberID="viewController">
<toolbarItems/>
<navigationBar key="navigationBar" contentMode="scaleToFill" id="eMh-g9-C8T">
- <rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
+ <rect key="frame" x="0.0" y="20" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<nil name="viewControllers"/>
@@ -32,14 +36,14 @@
<viewControllerLayoutGuide type="bottom" id="fet-m3-F1O"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="jkb-9Y-Hwh">
- <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
+ <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
- <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+ <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</view>
<navigationItem key="navigationItem" id="t1a-s2-nn6">
<nil key="title"/>
<segmentedControl key="titleView" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="bar" selectedSegmentIndex="0" id="RYa-fE-Qek">
- <rect key="frame" x="180" y="7" width="240" height="30"/>
+ <rect key="frame" x="67.5" y="7" width="240" height="30"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<segments>
<segment title="TCP Debug"/>
diff --git a/SmartDeviceLink_Example/ButtonManager.h b/SmartDeviceLink_Example/ButtonManager.h
new file mode 100644
index 000000000..867f50c7c
--- /dev/null
+++ b/SmartDeviceLink_Example/ButtonManager.h
@@ -0,0 +1,31 @@
+//
+// ButtonManager.h
+// SmartDeviceLink
+//
+// Created by Nicole on 5/11/18.
+// Copyright © 2018 smartdevicelink. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@class SDLManager;
+@class SDLSoftButtonObject;
+
+NS_ASSUME_NONNULL_BEGIN
+
+typedef void(^RefreshUIHandler)(void);
+
+@interface ButtonManager : NSObject
+
+@property (assign, nonatomic, getter=isTextEnabled, readonly) BOOL textEnabled;
+@property (assign, nonatomic, getter=isHexagonEnabled, readonly) BOOL toggleEnabled;
+@property (assign, nonatomic, getter=areImagesEnabled, readonly) BOOL imagesEnabled;
+
+- (instancetype)init NS_UNAVAILABLE;
+- (instancetype)initWithManager:(SDLManager *)manager refreshUIHandler:(RefreshUIHandler)refreshUIHandler;
+
+- (NSArray<SDLSoftButtonObject *> *)allScreenSoftButtons;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink_Example/ButtonManager.m b/SmartDeviceLink_Example/ButtonManager.m
new file mode 100644
index 000000000..3aed337b3
--- /dev/null
+++ b/SmartDeviceLink_Example/ButtonManager.m
@@ -0,0 +1,146 @@
+//
+// ButtonManager.m
+// SmartDeviceLink
+//
+// Created by Nicole on 5/11/18.
+// Copyright © 2018 smartdevicelink. All rights reserved.
+//
+
+#import "ButtonManager.h"
+#import "AlertManager.h"
+#import "AppConstants.h"
+#import "SmartDeviceLink.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface ButtonManager ()
+
+@property (copy, nonatomic, nullable) RefreshUIHandler refreshUIHandler;
+@property (strong, nonatomic) SDLManager *sdlManager;
+
+@property (assign, nonatomic, getter=isTextEnabled, readwrite) BOOL textEnabled;
+@property (assign, nonatomic, getter=isHexagonEnabled, readwrite) BOOL toggleEnabled;
+@property (assign, nonatomic, getter=areImagesEnabled, readwrite) BOOL imagesEnabled;
+
+@end
+
+@implementation ButtonManager
+
+- (instancetype)initWithManager:(SDLManager *)manager refreshUIHandler:(RefreshUIHandler)refreshUIHandler {
+ self = [super init];
+ if (!self) {
+ return nil;
+ }
+
+ _sdlManager = manager;
+ _refreshUIHandler = refreshUIHandler;
+
+ _textEnabled = YES;
+ _imagesEnabled = YES;
+ _toggleEnabled = YES;
+
+ return self;
+}
+
+#pragma mark - Setters
+
+- (void)setTextEnabled:(BOOL)textEnabled {
+ _textEnabled = textEnabled;
+ if (self.refreshUIHandler == nil) { return; }
+ self.refreshUIHandler();
+}
+
+- (void)setImagesEnabled:(BOOL)imagesEnabled {
+ _imagesEnabled = imagesEnabled;
+
+ SDLSoftButtonObject *object = [self.sdlManager.screenManager softButtonObjectNamed:AlertSoftButton];
+ [object transitionToNextState];
+
+ if (self.refreshUIHandler == nil) { return; }
+ self.refreshUIHandler();
+}
+
+- (void)setToggleEnabled:(BOOL)toggleEnabled {
+ _toggleEnabled = toggleEnabled;
+ SDLSoftButtonObject *object = [self.sdlManager.screenManager softButtonObjectNamed:ToggleSoftButton];
+ [object transitionToStateNamed:(toggleEnabled ? ToggleSoftButtonImageOnState : ToggleSoftButtonImageOffState)];
+}
+
+#pragma mark - Custom Soft Buttons
+
+- (NSArray<SDLSoftButtonObject *> *)allScreenSoftButtons {
+ return @[[self sdlex_softButtonAlertWithManager:self.sdlManager], [self sdlex_softButtonToggleWithManager:self.sdlManager], [self sdlex_softButtonTextVisibleWithManager:self.sdlManager], [self sdlex_softButtonImagesVisibleWithManager:self.sdlManager]];
+}
+
+- (SDLSoftButtonObject *)sdlex_softButtonAlertWithManager:(SDLManager *)manager {
+ SDLSoftButtonState *alertImageAndTextState = [[SDLSoftButtonState alloc] initWithStateName:AlertSoftButtonImageState text:AlertSoftButtonText image:[UIImage imageNamed:CarIconImageName]];
+ SDLSoftButtonState *alertTextState = [[SDLSoftButtonState alloc] initWithStateName:AlertSoftButtonTextState text:AlertSoftButtonText image:nil];
+
+ __weak typeof(self) weakself = self;
+ SDLSoftButtonObject *alertSoftButton = [[SDLSoftButtonObject alloc] initWithName:AlertSoftButton states:@[alertImageAndTextState, alertTextState] initialStateName:alertImageAndTextState.name handler:^(SDLOnButtonPress * _Nullable buttonPress, SDLOnButtonEvent * _Nullable buttonEvent) {
+ if (buttonPress == nil) { return; }
+
+ [weakself.sdlManager sendRequest:[AlertManager alertWithMessageAndCloseButton:@"You pushed the soft button!" textField2:nil]];
+
+ SDLLogD(@"Star icon soft button press fired");
+ }];
+
+ return alertSoftButton;
+}
+
+- (SDLSoftButtonObject *)sdlex_softButtonToggleWithManager:(SDLManager *)manager {
+ SDLSoftButtonState *toggleImageOnState = [[SDLSoftButtonState alloc] initWithStateName:ToggleSoftButtonImageOnState text:nil image:[UIImage imageNamed:WheelIconImageName]];
+ SDLSoftButtonState *toggleImageOffState = [[SDLSoftButtonState alloc] initWithStateName:ToggleSoftButtonImageOffState text:nil image:[UIImage imageNamed:LaptopIconImageName]];
+
+ __weak typeof(self) weakself = self;
+ SDLSoftButtonObject *toggleButton = [[SDLSoftButtonObject alloc] initWithName:ToggleSoftButton states:@[toggleImageOnState, toggleImageOffState] initialStateName:toggleImageOnState.name handler:^(SDLOnButtonPress * _Nullable buttonPress, SDLOnButtonEvent * _Nullable buttonEvent) {
+ if (buttonPress == nil) { return; }
+ weakself.toggleEnabled = !weakself.toggleEnabled;
+ SDLLogD(@"Toggle icon button press fired %d", self.toggleEnabled);
+ }];
+
+ return toggleButton;
+}
+
+- (SDLSoftButtonObject *)sdlex_softButtonTextVisibleWithManager:(SDLManager *)manager {
+ SDLSoftButtonState *textOnState = [[SDLSoftButtonState alloc] initWithStateName:TextVisibleSoftButtonTextOnState text:TextVisibleSoftButtonTextOnText image:nil];
+ SDLSoftButtonState *textOffState = [[SDLSoftButtonState alloc] initWithStateName:TextVisibleSoftButtonTextOffState text:TextVisibleSoftButtonTextOffText image:nil];
+
+ __weak typeof(self) weakself = self;
+ SDLSoftButtonObject *textButton = [[SDLSoftButtonObject alloc] initWithName:TextVisibleSoftButton states:@[textOnState, textOffState] initialStateName:textOnState.name handler:^(SDLOnButtonPress * _Nullable buttonPress, SDLOnButtonEvent * _Nullable buttonEvent) {
+ if (buttonPress == nil) { return; }
+
+ weakself.textEnabled = !weakself.textEnabled;
+ SDLSoftButtonObject *object = [weakself.sdlManager.screenManager softButtonObjectNamed:TextVisibleSoftButton];
+ [object transitionToNextState];
+
+ SDLLogD(@"Text visibility soft button press fired %d", weakself.textEnabled);
+ }];
+
+ return textButton;
+}
+
+- (SDLSoftButtonObject *)sdlex_softButtonImagesVisibleWithManager:(SDLManager *)manager {
+ SDLSoftButtonState *imagesOnState = [[SDLSoftButtonState alloc] initWithStateName:ImagesVisibleSoftButtonImageOnState text:ImagesVisibleSoftButtonImageOnText image:nil];
+ SDLSoftButtonState *imagesOffState = [[SDLSoftButtonState alloc] initWithStateName:ImagesVisibleSoftButtonImageOffState text:ImagesVisibleSoftButtonImageOffText image:nil];
+
+ __weak typeof(self) weakself = self;
+ SDLSoftButtonObject *imagesButton = [[SDLSoftButtonObject alloc] initWithName:ImagesVisibleSoftButton states:@[imagesOnState, imagesOffState] initialStateName:imagesOnState.name handler:^(SDLOnButtonPress * _Nullable buttonPress, SDLOnButtonEvent * _Nullable buttonEvent) {
+ if (buttonPress == nil) {
+ return;
+ }
+
+ weakself.imagesEnabled = !weakself.imagesEnabled;
+
+ SDLSoftButtonObject *object = [weakself.sdlManager.screenManager softButtonObjectNamed:ImagesVisibleSoftButton];
+ [object transitionToNextState];
+
+ SDLLogD(@"Image visibility soft button press fired %d", weakself.imagesEnabled);
+ }];
+
+ return imagesButton;
+}
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink_Example/ButtonManager.swift b/SmartDeviceLink_Example/ButtonManager.swift
new file mode 100644
index 000000000..617553e0b
--- /dev/null
+++ b/SmartDeviceLink_Example/ButtonManager.swift
@@ -0,0 +1,121 @@
+//
+// ButtonManager.swift
+// SmartDeviceLink
+//
+// Created by Nicole on 4/11/18.
+// Copyright © 2018 smartdevicelink. All rights reserved.
+//
+
+import Foundation
+import SmartDeviceLink
+import SmartDeviceLinkSwift
+
+typealias RefreshUIHandler = (() -> Void)
+
+class ButtonManager: NSObject {
+ fileprivate let sdlManager: SDLManager!
+ fileprivate var refreshUIHandler: RefreshUIHandler?
+
+ /// SDL UI textfields are visible if true; hidden if false
+ public fileprivate(set) var textEnabled: Bool {
+ didSet {
+ guard let refreshUIHandler = refreshUIHandler else { return }
+ refreshUIHandler()
+ }
+ }
+
+ /// SDL UI images are visible if true; hidden if false
+ public fileprivate(set) var imagesEnabled: Bool {
+ didSet {
+ guard let refreshUIHandler = refreshUIHandler, let alertSoftButton = sdlManager.screenManager.softButtonObjectNamed(AlertSoftButton) else { return }
+ alertSoftButton.transitionToNextState()
+ refreshUIHandler()
+ }
+ }
+
+ /// Keeps track of the toggle soft button current state. The image or text changes when the button is selected
+ fileprivate var toggleEnabled: Bool {
+ didSet {
+ guard let hexagonSoftButton = sdlManager.screenManager.softButtonObjectNamed(ToggleSoftButton), hexagonSoftButton.transition(toState: toggleEnabled ? ToggleSoftButtonImageOnState : ToggleSoftButtonImageOffState) else { return }
+ }
+ }
+
+ init(sdlManager: SDLManager, updateScreenHandler: RefreshUIHandler? = nil) {
+ self.sdlManager = sdlManager
+ self.refreshUIHandler = updateScreenHandler
+ textEnabled = true
+ imagesEnabled = true
+ toggleEnabled = true
+ super.init()
+ }
+
+ /// Creates and returns an array of all soft buttons for the UI
+ ///
+ /// - Parameter manager: The SDL Manager
+ /// - Returns: An array of all soft buttons for the UI
+ func allScreenSoftButtons(with manager: SDLManager) -> [SDLSoftButtonObject] {
+ return [softButtonAlert(with: manager), softButtonToggle(), softButtonTextVisible(), softButtonImagesVisible()]
+ }
+}
+
+// MARK: - Custom Soft Buttons
+
+private extension ButtonManager {
+ /// Returns a soft button that shows an alert when tapped.
+ ///
+ /// - Parameter manager: The SDL Manager for showing the alert
+ /// - Returns: A soft button
+ func softButtonAlert(with manager: SDLManager) -> SDLSoftButtonObject {
+ let imageSoftButtonState = SDLSoftButtonState(stateName: AlertSoftButtonImageState, text: nil, image: UIImage(named: CarIconImageName))
+ let textSoftButtonState = SDLSoftButtonState(stateName: AlertSoftButtonTextState, text: AlertSoftButtonText, image: nil)
+ return SDLSoftButtonObject(name: AlertSoftButton, states: [imageSoftButtonState, textSoftButtonState], initialStateName: imageSoftButtonState.name) { (buttonPress, buttonEvent) in
+ guard buttonPress != nil else { return }
+ let alert = AlertManager.alertWithMessageAndCloseButton("You pressed the button!")
+ manager.send(alert)
+ }
+ }
+
+ /// Returns a soft button that toggles between two states: on and off. If images are currently visible, the button image toggles; if images aren't visible, the button text toggles.
+ ///
+ /// - Returns: A soft button
+ func softButtonToggle() -> SDLSoftButtonObject {
+ let imageOnState = SDLSoftButtonState(stateName: ToggleSoftButtonImageOnState, text: nil, image: UIImage(named: WheelIconImageName))
+ let imageOffState = SDLSoftButtonState(stateName: ToggleSoftButtonImageOffState, text: nil, image: UIImage(named: LaptopIconImageName))
+ return SDLSoftButtonObject(name: ToggleSoftButton, states: [imageOnState, imageOffState], initialStateName: imageOnState.name) { [unowned self] (buttonPress, buttonEvent) in
+ guard buttonPress != nil else { return }
+ self.toggleEnabled = !self.toggleEnabled
+ }
+ }
+
+ /// Returns a soft button that toggles the textfield visibility state for the SDL UI. The button's text toggles based on the current text visibility.
+ ///
+ /// - Returns: A soft button
+ func softButtonTextVisible() -> SDLSoftButtonObject {
+ let textVisibleState = SDLSoftButtonState(stateName: TextVisibleSoftButtonTextOnState, text: TextVisibleSoftButtonTextOnText, artwork: nil)
+ let textNotVisibleState = SDLSoftButtonState(stateName: TextVisibleSoftButtonTextOffState, text: TextVisibleSoftButtonTextOffText, image: nil)
+ return SDLSoftButtonObject(name: TextVisibleSoftButton, states: [textVisibleState, textNotVisibleState], initialStateName: textVisibleState.name) { [unowned self] (buttonPress, buttonEvent) in
+ guard buttonPress != nil else { return }
+ self.textEnabled = !self.textEnabled
+
+ // Update the button state
+ let softButton = self.sdlManager.screenManager.softButtonObjectNamed(TextVisibleSoftButton)
+ softButton?.transitionToNextState()
+ }
+ }
+
+ /// Returns a soft button that toggles the image visibility state for the SDL UI. The button's text toggles based on the current image visibility.
+ ///
+ /// - Returns: A soft button
+ func softButtonImagesVisible() -> SDLSoftButtonObject {
+ let imagesVisibleState = SDLSoftButtonState(stateName: ImagesVisibleSoftButtonImageOnState, text: ImagesVisibleSoftButtonImageOnText, image: nil)
+ let imagesNotVisibleState = SDLSoftButtonState(stateName: ImagesVisibleSoftButtonImageOffState, text: ImagesVisibleSoftButtonImageOffText, image: nil)
+ return SDLSoftButtonObject(name: ImagesVisibleSoftButton, states: [imagesVisibleState, imagesNotVisibleState], initialStateName: imagesVisibleState.name) { [unowned self] (buttonPress, buttonEvent) in
+ guard buttonPress != nil else { return }
+ self.imagesEnabled = !self.imagesEnabled
+
+ // Update the button state
+ let softButton = self.sdlManager.screenManager.softButtonObjectNamed(ImagesVisibleSoftButton)
+ softButton?.transitionToNextState()
+ }
+ }
+}
diff --git a/SmartDeviceLink_Example/Classes/ConnectionIAPTableViewController.m b/SmartDeviceLink_Example/Classes/ConnectionIAPTableViewController.m
index 17ee2ae19..31a0f3fdf 100644
--- a/SmartDeviceLink_Example/Classes/ConnectionIAPTableViewController.m
+++ b/SmartDeviceLink_Example/Classes/ConnectionIAPTableViewController.m
@@ -45,7 +45,7 @@
ProxyState state = [ProxyManager sharedManager].state;
switch (state) {
case ProxyStateStopped: {
- [[ProxyManager sharedManager] startIAP];
+ [[ProxyManager sharedManager] startWithProxyTransportType:ProxyTransportTypeIAP];
} break;
case ProxyStateSearchingForConnection: {
[[ProxyManager sharedManager] reset];
diff --git a/SmartDeviceLink_Example/Classes/ConnectionTCPTableViewController.m b/SmartDeviceLink_Example/Classes/ConnectionTCPTableViewController.m
index 94d6ebec4..e567eb44e 100644
--- a/SmartDeviceLink_Example/Classes/ConnectionTCPTableViewController.m
+++ b/SmartDeviceLink_Example/Classes/ConnectionTCPTableViewController.m
@@ -56,7 +56,7 @@
ProxyState state = [ProxyManager sharedManager].state;
switch (state) {
case ProxyStateStopped: {
- [[ProxyManager sharedManager] startTCP];
+ [[ProxyManager sharedManager] startWithProxyTransportType:ProxyTransportTypeTCP];
} break;
case ProxyStateSearchingForConnection: {
[[ProxyManager sharedManager] reset];
diff --git a/SmartDeviceLink_Example/Classes/ProxyManager.h b/SmartDeviceLink_Example/Classes/ProxyManager.h
index 333bb6dbf..59872b335 100644
--- a/SmartDeviceLink_Example/Classes/ProxyManager.h
+++ b/SmartDeviceLink_Example/Classes/ProxyManager.h
@@ -5,11 +5,8 @@
#import <Foundation/Foundation.h>
@class SDLManager;
-@class SDLStreamingMediaManager;
-
typedef NS_ENUM(NSUInteger, ProxyTransportType) {
- ProxyTransportTypeUnknown,
ProxyTransportTypeTCP,
ProxyTransportTypeIAP
};
@@ -20,6 +17,7 @@ typedef NS_ENUM(NSUInteger, ProxyState) {
ProxyStateConnected
};
+NS_ASSUME_NONNULL_BEGIN
@interface ProxyManager : NSObject
@@ -27,8 +25,9 @@ typedef NS_ENUM(NSUInteger, ProxyState) {
@property (strong, nonatomic) SDLManager *sdlManager;
+ (instancetype)sharedManager;
-- (void)startIAP;
-- (void)startTCP;
+- (void)startWithProxyTransportType:(ProxyTransportType)proxyTransportType;
- (void)reset;
@end
+
+NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink_Example/Classes/ProxyManager.m b/SmartDeviceLink_Example/Classes/ProxyManager.m
index 5a54acc9d..bb2ba88c3 100644
--- a/SmartDeviceLink_Example/Classes/ProxyManager.m
+++ b/SmartDeviceLink_Example/Classes/ProxyManager.m
@@ -2,34 +2,28 @@
// ProxyManager.m
// SmartDeviceLink-iOS
-#import "SmartDeviceLink.h"
-#import "ProxyManager.h"
+#import "AppConstants.h"
+#import "AlertManager.h"
+#import "ButtonManager.h"
+#import "MenuManager.h"
+#import "PerformInteractionManager.h"
#import "Preferences.h"
-
-NSString *const SDLAppName = @"SDL Example App";
-NSString *const SDLAppId = @"9999";
-
-
-BOOL const ShouldRestartOnDisconnect = NO;
-
-typedef NS_ENUM(NSUInteger, SDLHMIFirstState) {
- SDLHMIFirstStateNone,
- SDLHMIFirstStateNonNone,
- SDLHMIFirstStateFull
-};
-
+#import "ProxyManager.h"
+#import "RPCPermissionsManager.h"
+#import "SmartDeviceLink.h"
+#import "VehicleDataManager.h"
NS_ASSUME_NONNULL_BEGIN
+
@interface ProxyManager () <SDLManagerDelegate>
// Describes the first time the HMI state goes non-none and full.
-@property (assign, nonatomic) SDLHMIFirstState firstTimeState;
-
-@property (assign, nonatomic, getter=isTextEnabled) BOOL textEnabled;
-@property (assign, nonatomic, getter=isHexagonEnabled) BOOL hexagonEnabled;
-@property (assign, nonatomic, getter=areImagesEnabled) BOOL imagesEnabled;
+@property (assign, nonatomic) SDLHMILevel firstHMILevel;
+@property (strong, nonatomic) VehicleDataManager *vehicleDataManager;
+@property (strong, nonatomic) ButtonManager *buttonManager;
+@property (nonatomic, copy, nullable) RefreshUIHandler refreshUIHandler;
@end
@@ -49,43 +43,16 @@ NS_ASSUME_NONNULL_BEGIN
- (instancetype)init {
self = [super init];
- if (self == nil) {
+ if (!self) {
return nil;
}
-
+
_state = ProxyStateStopped;
- _firstTimeState = SDLHMIFirstStateNone;
+ _firstHMILevel = SDLHMILevelNone;
- _textEnabled = YES;
- _hexagonEnabled = YES;
- _imagesEnabled = YES;
-
return self;
}
-- (void)startIAP {
- [self sdlex_updateProxyState:ProxyStateSearchingForConnection];
- // Check for previous instance of sdlManager
- if (self.sdlManager) { return; }
- SDLLifecycleConfiguration *lifecycleConfig = [self.class sdlex_setLifecycleConfigurationPropertiesOnConfiguration:[SDLLifecycleConfiguration defaultConfigurationWithAppName:SDLAppName appId:SDLAppId]];
- [self sdlex_setupConfigurationWithLifecycleConfiguration:lifecycleConfig];
-}
-
-- (void)startTCP {
- [self sdlex_updateProxyState:ProxyStateSearchingForConnection];
- // Check for previous instance of sdlManager
- if (self.sdlManager) { return; }
- SDLLifecycleConfiguration *lifecycleConfig = [self.class sdlex_setLifecycleConfigurationPropertiesOnConfiguration:[SDLLifecycleConfiguration debugConfigurationWithAppName:SDLAppName appId:SDLAppId ipAddress:[Preferences sharedPreferences].ipAddress port:[Preferences sharedPreferences].port]];
- [self sdlex_setupConfigurationWithLifecycleConfiguration:lifecycleConfig];
-}
-
-- (void)sdlex_setupConfigurationWithLifecycleConfiguration:(SDLLifecycleConfiguration *)lifecycleConfiguration {
- SDLConfiguration *config = [SDLConfiguration configurationWithLifecycle:lifecycleConfiguration lockScreen:[SDLLockScreenConfiguration enabledConfigurationWithAppIcon:[UIImage imageNamed:@"AppIcon60x60@2x"] backgroundColor:nil] logging:[self.class sdlex_logConfiguration]];
- self.sdlManager = [[SDLManager alloc] initWithConfiguration:config delegate:self];
-
- [self startManager];
-}
-
- (void)startManager {
__weak typeof (self) weakSelf = self;
[self.sdlManager startWithReadyHandler:^(BOOL success, NSError * _Nullable error) {
@@ -94,105 +61,69 @@ NS_ASSUME_NONNULL_BEGIN
[weakSelf sdlex_updateProxyState:ProxyStateStopped];
return;
}
-
+
+ self.vehicleDataManager = [[VehicleDataManager alloc] initWithManager:self.sdlManager refreshUIHandler:self.refreshUIHandler];
+ self.buttonManager = [[ButtonManager alloc] initWithManager:self.sdlManager refreshUIHandler:self.refreshUIHandler];
+
[weakSelf sdlex_updateProxyState:ProxyStateConnected];
+ [RPCPermissionsManager setupPermissionsCallbacksWithManager:weakSelf.sdlManager];
+ [weakSelf sdlex_showInitialData];
- [weakSelf sdlex_setupPermissionsCallbacks];
-
- if ([weakSelf.sdlManager.hmiLevel isEqualToEnum:SDLHMILevelFull]) {
- [weakSelf sdlex_showInitialData];
- }
+ SDLLogD(@"SDL file manager storage: %lu mb", self.sdlManager.fileManager.bytesAvailable / 1024 / 1024);
}];
}
- (void)reset {
- [self sdlex_updateProxyState:ProxyStateStopped];
- [self.sdlManager stop];
- // Remove reference
- self.sdlManager = nil;
-}
-
-
-#pragma mark - Helpers
-
-- (void)sdlex_showInitialData {
- if (![self.sdlManager.hmiLevel isEqualToEnum:SDLHMILevelFull]) {
+ if (self.sdlManager == nil) {
+ [self sdlex_updateProxyState:ProxyStateStopped];
return;
}
- SDLSetDisplayLayout *displayLayout = [[SDLSetDisplayLayout alloc] initWithLayout:SDLPredefinedLayoutNonMedia];
- [self.sdlManager sendRequest:displayLayout];
-
- [self sdlex_updateScreen];
-
- self.sdlManager.screenManager.softButtonObjects = [self sdlex_softButtons];
+ [self.sdlManager stop];
}
-- (void)setTextEnabled:(BOOL)textEnabled {
- _textEnabled = textEnabled;
- [self sdlex_updateScreen];
+- (void)sdlex_updateProxyState:(ProxyState)newState {
+ if (self.state != newState) {
+ [self willChangeValueForKey:@"state"];
+ _state = newState;
+ [self didChangeValueForKey:@"state"];
+ }
}
-- (void)setImagesEnabled:(BOOL)imagesEnabled {
- _imagesEnabled = imagesEnabled;
- [self sdlex_updateScreen];
- [self setHexagonButtonIconEnabled:self.isHexagonEnabled imagesEnabled:imagesEnabled];
-}
+#pragma mark - SDL Configuration
-- (void)setHexagonEnabled:(BOOL)hexagonEnabled {
- _hexagonEnabled = hexagonEnabled;
- [self setHexagonButtonIconEnabled:hexagonEnabled imagesEnabled:self.areImagesEnabled];
-}
+- (void)startWithProxyTransportType:(ProxyTransportType)proxyTransportType {
+ [self sdlex_updateProxyState:ProxyStateSearchingForConnection];
-- (void)setHexagonButtonIconEnabled:(BOOL)hexagonEnabled imagesEnabled:(BOOL)imagesEnabled {
- SDLSoftButtonObject *object = [self.sdlManager.screenManager softButtonObjectNamed:@"HexagonButton"];
- imagesEnabled ? [object transitionToStateNamed:(hexagonEnabled ? @"imageOnState" : @"imageOffState")] : [object transitionToStateNamed:(hexagonEnabled ? @"textOnState" : @"textOffState")];
-}
+ // Check for previous instance of sdlManager
+ if (self.sdlManager) { return; }
-- (void)sdlex_updateScreen {
- [self.sdlManager.screenManager beginUpdates];
- self.sdlManager.screenManager.textAlignment = SDLTextAlignmentLeft;
- self.sdlManager.screenManager.textField1 = self.isTextEnabled ? @"SmartDeviceLink" : nil;
- self.sdlManager.screenManager.textField2 = self.isTextEnabled ? @"Example App" : nil;
+ SDLLifecycleConfiguration *lifecycleConfig = proxyTransportType == ProxyTransportTypeIAP ? [self.class sdlex_iapLifecycleConfiguration] : [self.class sdlex_tcpLifecycleConfiguration];
+ [self sdlex_setupConfigurationWithLifecycleConfiguration:lifecycleConfig];
+}
- self.sdlManager.screenManager.primaryGraphic = self.areImagesEnabled ? [SDLArtwork persistentArtworkWithImage:[UIImage imageNamed:@"sdl_logo_green"] asImageFormat:SDLArtworkImageFormatPNG] : nil;
++ (SDLLifecycleConfiguration *)sdlex_iapLifecycleConfiguration {
+ return [self.class sdlex_setLifecycleConfigurationPropertiesOnConfiguration:[SDLLifecycleConfiguration defaultConfigurationWithAppName:ExampleAppName appId:ExampleAppId]];
+}
- [self.sdlManager.screenManager endUpdatesWithCompletionHandler:^(NSError * _Nullable error) {
- NSLog(@"Updated text and graphics, error? %@", error);
- }];
++ (SDLLifecycleConfiguration *)sdlex_tcpLifecycleConfiguration {
+ return [self.class sdlex_setLifecycleConfigurationPropertiesOnConfiguration:[SDLLifecycleConfiguration debugConfigurationWithAppName:ExampleAppName appId:ExampleAppId ipAddress:[Preferences sharedPreferences].ipAddress port:[Preferences sharedPreferences].port]];
}
-- (void)sdlex_setupPermissionsCallbacks {
- // This will tell you whether or not you can use the Show RPC right at this moment
- BOOL isAvailable = [self.sdlManager.permissionManager isRPCAllowed:@"Show"];
- SDLLogD(@"Show is allowed? %@", @(isAvailable));
+- (void)sdlex_setupConfigurationWithLifecycleConfiguration:(SDLLifecycleConfiguration *)lifecycleConfiguration {
+ SDLConfiguration *config = [SDLConfiguration configurationWithLifecycle:lifecycleConfiguration lockScreen:[SDLLockScreenConfiguration enabledConfigurationWithAppIcon:[UIImage imageNamed:ExampleAppLogoName] backgroundColor:nil] logging:[self.class sdlex_logConfiguration]];
+ self.sdlManager = [[SDLManager alloc] initWithConfiguration:config delegate:self];
- // This will set up a block that will tell you whether or not you can use none, all, or some of the RPCs specified, and notifies you when those permissions change
- SDLPermissionObserverIdentifier observerId = [self.sdlManager.permissionManager addObserverForRPCs:@[@"Show", @"Alert"] groupType:SDLPermissionGroupTypeAllAllowed withHandler:^(NSDictionary<SDLPermissionRPCName, NSNumber<SDLBool> *> * _Nonnull change, SDLPermissionGroupStatus status) {
- SDLLogD(@"Show changed permission to status: %@, dict: %@", @(status), change);
- }];
- // The above block will be called immediately, this will then remove the block from being called any more
- [self.sdlManager.permissionManager removeObserverForIdentifier:observerId];
-
- // This will give us the current status of the group of RPCs, as if we had set up an observer, except these are one-shot calls
- NSArray *rpcGroup =@[@"AddCommand", @"PerformInteraction"];
- SDLPermissionGroupStatus commandPICSStatus = [self.sdlManager.permissionManager groupStatusOfRPCs:rpcGroup];
- NSDictionary *commandPICSStatusDict = [self.sdlManager.permissionManager statusOfRPCs:rpcGroup];
- SDLLogD(@"Command / PICS status: %@, dict: %@", @(commandPICSStatus), commandPICSStatusDict);
-
- // This will set up a long-term observer for the RPC group and will tell us when the status of any specified RPC changes (due to the `SDLPermissionGroupTypeAny`) option.
- [self.sdlManager.permissionManager addObserverForRPCs:rpcGroup groupType:SDLPermissionGroupTypeAny withHandler:^(NSDictionary<SDLPermissionRPCName, NSNumber<SDLBool> *> * _Nonnull change, SDLPermissionGroupStatus status) {
- SDLLogD(@"Command / PICS changed permission to status: %@, dict: %@", @(status), change);
- }];
+ [self startManager];
}
+ (SDLLifecycleConfiguration *)sdlex_setLifecycleConfigurationPropertiesOnConfiguration:(SDLLifecycleConfiguration *)config {
- SDLArtwork *appIconArt = [SDLArtwork persistentArtworkWithImage:[UIImage imageNamed:@"AppIcon60x60@2x"] asImageFormat:SDLArtworkImageFormatPNG];
+ SDLArtwork *appIconArt = [SDLArtwork persistentArtworkWithImage:[UIImage imageNamed:ExampleAppLogoName] asImageFormat:SDLArtworkImageFormatPNG];
- config.shortAppName = @"SDL Example";
+ config.shortAppName = ExampleAppNameShort;
config.appIcon = appIconArt;
- config.voiceRecognitionCommandNames = @[@"S D L Example"];
- config.ttsName = [SDLTTSChunk textChunksFromString:config.shortAppName];
+ config.voiceRecognitionCommandNames = @[ExampleAppNameTTS];
+ config.ttsName = [SDLTTSChunk textChunksFromString:ExampleAppName];
config.language = SDLLanguageEnUs;
config.languagesSupported = @[SDLLanguageEnUs, SDLLanguageFrCa, SDLLanguageEsMx];
@@ -200,259 +131,142 @@ NS_ASSUME_NONNULL_BEGIN
}
+ (SDLLogConfiguration *)sdlex_logConfiguration {
- SDLLogConfiguration *logConfig = [SDLLogConfiguration defaultConfiguration];
- SDLLogFileModule *sdlExampleModule = [SDLLogFileModule moduleWithName:@"SDL Example" files:[NSSet setWithArray:@[@"ProxyManager"]]];
+ SDLLogConfiguration *logConfig = [SDLLogConfiguration debugConfiguration];
+ SDLLogFileModule *sdlExampleModule = [SDLLogFileModule moduleWithName:@"SDL Obj-C Example App" files:[NSSet setWithArray:@[@"ProxyManager", @"AlertManager", @"AudioManager", @"ButtonManager", @"MenuManager", @"PerformInteractionManager", @"RPCPermissionsManager", @"VehicleDataManager"]]];
logConfig.modules = [logConfig.modules setByAddingObject:sdlExampleModule];
logConfig.targets = [logConfig.targets setByAddingObject:[SDLLogTargetFile logger]];
- // logConfig.filters = [logConfig.filters setByAddingObject:[SDLLogFilter filterByAllowingModules:[NSSet setWithObject:@"Transport"]]];
+ logConfig.globalLogLevel = SDLLogLevelVerbose;
return logConfig;
}
-- (void)sdlex_updateProxyState:(ProxyState)newState {
- if (self.state != newState) {
- [self willChangeValueForKey:@"state"];
- _state = newState;
- [self didChangeValueForKey:@"state"];
- }
-}
-
-#pragma mark - RPC builders
-
-+ (SDLAddCommand *)sdlex_speakNameCommandWithManager:(SDLManager *)manager {
- NSString *commandName = @"Speak App Name";
-
- SDLMenuParams *commandMenuParams = [[SDLMenuParams alloc] init];
- commandMenuParams.menuName = commandName;
-
- SDLAddCommand *speakNameCommand = [[SDLAddCommand alloc] init];
- speakNameCommand.vrCommands = @[commandName];
- speakNameCommand.menuParams = commandMenuParams;
- speakNameCommand.cmdID = @0;
-
- speakNameCommand.handler = ^void(SDLOnCommand *notification) {
- [manager sendRequest:[self.class sdlex_appNameSpeak]];
- };
-
- return speakNameCommand;
-}
-
-+ (SDLAddCommand *)sdlex_interactionSetCommandWithManager:(SDLManager *)manager {
- NSString *commandName = @"Perform Interaction";
-
- SDLMenuParams *commandMenuParams = [[SDLMenuParams alloc] init];
- commandMenuParams.menuName = commandName;
-
- SDLAddCommand *performInteractionCommand = [[SDLAddCommand alloc] init];
- performInteractionCommand.vrCommands = @[commandName];
- performInteractionCommand.menuParams = commandMenuParams;
- performInteractionCommand.cmdID = @1;
-
- // NOTE: You may want to preload your interaction sets, because they can take a while for the remote system to process. We're going to ignore our own advice here.
- __weak typeof(self) weakSelf = self;
- performInteractionCommand.handler = ^void(SDLOnCommand *notification) {
- [weakSelf sdlex_sendPerformOnlyChoiceInteractionWithManager:manager];
- };
-
- return performInteractionCommand;
-}
-
-+ (SDLAddCommand *)sdlex_vehicleDataCommandWithManager:(SDLManager *)manager {
- SDLMenuParams *commandMenuParams = [[SDLMenuParams alloc] init];
- commandMenuParams.menuName = @"Get Vehicle Data";
-
- SDLAddCommand *getVehicleDataCommand = [[SDLAddCommand alloc] init];
- getVehicleDataCommand.vrCommands = [NSMutableArray arrayWithObject:@"Get Vehicle Data"];
- getVehicleDataCommand.menuParams = commandMenuParams;
- getVehicleDataCommand.cmdID = @2;
-
- getVehicleDataCommand.handler = ^void(SDLOnCommand *notification) {
- [ProxyManager sdlex_sendGetVehicleDataWithManager:manager];
- };
-
- return getVehicleDataCommand;
-}
-
-+ (SDLSpeak *)sdlex_appNameSpeak {
- SDLSpeak *speak = [[SDLSpeak alloc] init];
- speak.ttsChunks = [SDLTTSChunk textChunksFromString:@"S D L Example App"];
-
- return speak;
-}
+#pragma mark - Screen UI Helpers
-+ (SDLSpeak *)sdlex_goodJobSpeak {
- SDLSpeak *speak = [[SDLSpeak alloc] init];
- speak.ttsChunks = [SDLTTSChunk textChunksFromString:@"Good Job"];
-
- return speak;
+- (void)sdlex_createMenus {
+ [self.sdlManager sendRequest:[PerformInteractionManager createInteractionChoiceSet]];
+ self.sdlManager.screenManager.menu = [MenuManager allMenuItemsWithManager:self.sdlManager];
+ self.sdlManager.screenManager.voiceCommands = [MenuManager allVoiceMenuItemsWithManager:self.sdlManager];
}
-+ (SDLSpeak *)sdlex_youMissedItSpeak {
- SDLSpeak *speak = [[SDLSpeak alloc] init];
- speak.ttsChunks = [SDLTTSChunk textChunksFromString:@"You missed it"];
+- (void)sdlex_showInitialData {
+ if (![self.sdlManager.hmiLevel isEqualToEnum:SDLHMILevelFull]) { return; }
- return speak;
+ [self sdlex_updateScreen];
+ self.sdlManager.screenManager.softButtonObjects = [self.buttonManager allScreenSoftButtons];
}
-+ (SDLCreateInteractionChoiceSet *)sdlex_createOnlyChoiceInteractionSet {
- SDLCreateInteractionChoiceSet *createInteractionSet = [[SDLCreateInteractionChoiceSet alloc] init];
- createInteractionSet.interactionChoiceSetID = @0;
-
- NSString *theOnlyChoiceName = @"The Only Choice";
- SDLChoice *theOnlyChoice = [[SDLChoice alloc] init];
- theOnlyChoice.choiceID = @0;
- theOnlyChoice.menuName = theOnlyChoiceName;
- theOnlyChoice.vrCommands = @[theOnlyChoiceName];
-
- createInteractionSet.choiceSet = @[theOnlyChoice];
-
- return createInteractionSet;
-}
+- (nullable RefreshUIHandler)refreshUIHandler {
+ if(!_refreshUIHandler) {
+ __weak typeof(self) weakSelf = self;
+ weakSelf.refreshUIHandler = ^{
+ [weakSelf sdlex_updateScreen];
+ };
+ }
-+ (void)sdlex_sendPerformOnlyChoiceInteractionWithManager:(SDLManager *)manager {
- SDLPerformInteraction *performOnlyChoiceInteraction = [[SDLPerformInteraction alloc] init];
- performOnlyChoiceInteraction.initialText = @"Choose the only one! You have 5 seconds...";
- performOnlyChoiceInteraction.initialPrompt = [SDLTTSChunk textChunksFromString:@"Choose it"];
- performOnlyChoiceInteraction.interactionMode = SDLInteractionModeBoth;
- performOnlyChoiceInteraction.interactionChoiceSetIDList = @[@0];
- performOnlyChoiceInteraction.helpPrompt = [SDLTTSChunk textChunksFromString:@"Do it"];
- performOnlyChoiceInteraction.timeoutPrompt = [SDLTTSChunk textChunksFromString:@"Too late"];
- performOnlyChoiceInteraction.timeout = @5000;
- performOnlyChoiceInteraction.interactionLayout = SDLLayoutModeListOnly;
-
- [manager sendRequest:performOnlyChoiceInteraction withResponseHandler:^(__kindof SDLRPCRequest * _Nullable request, __kindof SDLPerformInteractionResponse * _Nullable response, NSError * _Nullable error) {
- SDLLogD(@"Perform Interaction fired");
- if ((response == nil) || (error != nil)) {
- SDLLogE(@"Something went wrong, no perform interaction response: %@", error);
- }
-
- if ([response.choiceID isEqualToNumber:@0]) {
- [manager sendRequest:[self sdlex_goodJobSpeak]];
- } else {
- [manager sendRequest:[self sdlex_youMissedItSpeak]];
- }
- }];
+ return _refreshUIHandler;
}
-- (NSArray<SDLSoftButtonObject *> *)sdlex_softButtons {
- SDLSoftButtonState *starImageState = [[SDLSoftButtonState alloc] initWithStateName:@"imageState" text:@"Press" image:[UIImage imageNamed:@"star_softbutton_icon"]];
- SDLSoftButtonState *starTextState = [[SDLSoftButtonState alloc] initWithStateName:@"textState" text:@"Press" image:nil];
-
- __weak typeof(self) weakself = self;
- SDLSoftButtonObject *starButton = [[SDLSoftButtonObject alloc] initWithName:@"StarButton" states:@[starImageState, starTextState] initialStateName:@"imageState" handler:^(SDLOnButtonPress * _Nullable buttonPress, SDLOnButtonEvent * _Nullable buttonEvent) {
- if (buttonPress == nil) {
- return;
- }
-
- SDLAlert* alert = [[SDLAlert alloc] init];
- alert.alertText1 = @"You pushed the soft button!";
- [weakself.sdlManager sendRequest:alert];
-
- SDLLogD(@"Star icon soft button press fired");
- }];
-
- SDLSoftButtonState *hexImageOnState = [[SDLSoftButtonState alloc] initWithStateName:@"imageOnState" text:nil image:[UIImage imageNamed:@"hexagon_on_softbutton_icon"]];
- SDLSoftButtonState *hexImageOffState = [[SDLSoftButtonState alloc] initWithStateName:@"imageOffState" text:nil image:[UIImage imageNamed:@"hexagon_off_softbutton_icon"]];
- SDLSoftButtonState *hexTextOnState = [[SDLSoftButtonState alloc] initWithStateName:@"textOnState" text:@"➖Hex" image:nil];
- SDLSoftButtonState *hexTextOffState = [[SDLSoftButtonState alloc] initWithStateName:@"textOffState" text:@"➕Hex" image:nil];
- SDLSoftButtonObject *hexButton = [[SDLSoftButtonObject alloc] initWithName:@"HexagonButton" states:@[hexImageOnState, hexImageOffState, hexTextOnState, hexTextOffState] initialStateName:hexImageOnState.name handler:^(SDLOnButtonPress * _Nullable buttonPress, SDLOnButtonEvent * _Nullable buttonEvent) {
- if (buttonPress == nil) { return; }
-
- weakself.hexagonEnabled = !weakself.hexagonEnabled;
- SDLLogD(@"Hexagon icon button press fired %d", self.hexagonEnabled);
- }];
-
- SDLSoftButtonState *textOnState = [[SDLSoftButtonState alloc] initWithStateName:@"onState" text:@"➖Text" image:nil];
- SDLSoftButtonState *textOffState = [[SDLSoftButtonState alloc] initWithStateName:@"offState" text:@"➕Text" image:nil];
- SDLSoftButtonObject *textButton = [[SDLSoftButtonObject alloc] initWithName:@"TextButton" states:@[textOnState, textOffState] initialStateName:@"onState" handler:^(SDLOnButtonPress * _Nullable buttonPress, SDLOnButtonEvent * _Nullable buttonEvent) {
- if (buttonPress == nil) {
- return;
- }
-
- weakself.textEnabled = !weakself.textEnabled;
- SDLSoftButtonObject *object = [weakself.sdlManager.screenManager softButtonObjectNamed:@"TextButton"];
- [object transitionToNextState];
-
- SDLLogD(@"Text visibility soft button press fired %d", weakself.textEnabled);
- }];
-
- SDLSoftButtonState *imagesOnState = [[SDLSoftButtonState alloc] initWithStateName:@"onState" text:@"➖Icons" image:nil];
- SDLSoftButtonState *imagesOffState = [[SDLSoftButtonState alloc] initWithStateName:@"offState" text:@"➕Icons" image:nil];
- SDLSoftButtonObject *imagesButton = [[SDLSoftButtonObject alloc] initWithName:@"ImagesButton" states:@[imagesOnState, imagesOffState] initialStateName:@"onState" handler:^(SDLOnButtonPress * _Nullable buttonPress, SDLOnButtonEvent * _Nullable buttonEvent) {
- if (buttonPress == nil) {
- return;
- }
-
- weakself.imagesEnabled = !weakself.imagesEnabled;
+- (void)sdlex_updateScreen {
+ if (![self.sdlManager.hmiLevel isEqualToEnum:SDLHMILevelFull]) { return; }
- SDLSoftButtonObject *object = [weakself.sdlManager.screenManager softButtonObjectNamed:@"ImagesButton"];
- [object transitionToNextState];
+ SDLScreenManager *screenManager = self.sdlManager.screenManager;
+ BOOL isTextEnabled = self.buttonManager.isTextEnabled;
+ BOOL areImagesVisible = self.buttonManager.areImagesEnabled;
- SDLLogD(@"Image visibility soft button press fired %d", weakself.imagesEnabled);
- }];
+ [screenManager beginUpdates];
+ screenManager.textAlignment = SDLTextAlignmentLeft;
+ screenManager.textField1 = isTextEnabled ? SmartDeviceLinkText : nil;
+ screenManager.textField2 = isTextEnabled ? [NSString stringWithFormat:@"Obj-C %@", ExampleAppText] : nil;
+ screenManager.textField3 = isTextEnabled ? self.vehicleDataManager.vehicleOdometerData : nil;
- return @[starButton, hexButton, textButton, imagesButton];
-}
-
-+ (void)sdlex_sendGetVehicleDataWithManager:(SDLManager *)manager {
- SDLGetVehicleData *getVehicleData = [[SDLGetVehicleData alloc] initWithAccelerationPedalPosition:YES airbagStatus:YES beltStatus:YES bodyInformation:YES clusterModeStatus:YES deviceStatus:YES driverBraking:YES eCallInfo:YES emergencyEvent:YES engineTorque:YES externalTemperature:YES fuelLevel:YES fuelLevelState:YES gps:YES headLampStatus:YES instantFuelConsumption:YES myKey:YES odometer:YES prndl:YES rpm:YES speed:YES steeringWheelAngle:YES tirePressure:YES vin:YES wiperStatus:YES];
+ if (self.sdlManager.systemCapabilityManager.displayCapabilities.graphicSupported) {
+ screenManager.primaryGraphic = areImagesVisible ? [SDLArtwork persistentArtworkWithImage:[UIImage imageNamed:@"sdl_logo_green"] asImageFormat:SDLArtworkImageFormatPNG] : nil;
+ }
- [manager sendRequest:getVehicleData withResponseHandler:^(__kindof SDLRPCRequest * _Nullable request, __kindof SDLRPCResponse * _Nullable response, NSError * _Nullable error) {
- NSLog(@"vehicle data response: %@", response);
+ [screenManager endUpdatesWithCompletionHandler:^(NSError * _Nullable error) {
+ SDLLogD(@"Updated text and graphics, error? %@", error);
}];
}
-- (void)sdlex_prepareRemoteSystem {
- [self.sdlManager sendRequests:@[[self.class sdlex_speakNameCommandWithManager:self.sdlManager], [self.class sdlex_interactionSetCommandWithManager:self.sdlManager], [self.class sdlex_vehicleDataCommandWithManager:self.sdlManager], [self.class sdlex_createOnlyChoiceInteractionSet]]
- progressHandler:^(__kindof SDLRPCRequest * _Nonnull request, __kindof SDLRPCResponse * _Nullable response, NSError * _Nullable error, float percentComplete) {
- NSLog(@"Commands sent updated, percent complete %f%%", percentComplete * 100);
- }
- completionHandler:nil];
-}
-
#pragma mark - SDLManagerDelegate
- (void)managerDidDisconnect {
- // Reset our state
- self.firstTimeState = SDLHMIFirstStateNone;
[self sdlex_updateProxyState:ProxyStateStopped];
- if (ShouldRestartOnDisconnect) {
+ self.firstHMILevel = SDLHMILevelNone;
+
+ // If desired, automatically start searching for a new connection to Core
+ if (ExampleAppShouldRestartSDLManagerOnDisconnect) {
[self startManager];
}
}
- (void)hmiLevel:(SDLHMILevel)oldLevel didChangeToLevel:(SDLHMILevel)newLevel {
- if (![newLevel isEqualToEnum:SDLHMILevelNone] && (self.firstTimeState == SDLHMIFirstStateNone)) {
+ if (![newLevel isEqualToEnum:SDLHMILevelNone] && ([self.firstHMILevel isEqualToEnum:SDLHMILevelNone])) {
// This is our first time in a non-NONE state
- self.firstTimeState = SDLHMIFirstStateNonNone;
+ self.firstHMILevel = newLevel;
// Send AddCommands
- [self sdlex_prepareRemoteSystem];
+ [self sdlex_createMenus];
+ [self.vehicleDataManager subscribeToVehicleOdometer];
}
-
- if ([newLevel isEqualToEnum:SDLHMILevelFull] && (self.firstTimeState != SDLHMIFirstStateFull)) {
- // This is our first time in a FULL state
- self.firstTimeState = SDLHMIFirstStateFull;
+
+ if ([newLevel isEqualToEnum:SDLHMILevelFull]) {
+ // The SDL app is in the foreground
+ SDLLogD(@"The HMI level is full");
+ } else if ([newLevel isEqualToEnum:SDLHMILevelLimited]) {
+ // An active NAV or MEDIA SDL app is in the background
+ SDLLogD(@"The HMI level is limited");
+ } else if ([newLevel isEqualToEnum:SDLHMILevelBackground]) {
+ // The SDL app is not in the foreground
+ SDLLogD(@"The HMI level is background");
+ } else if ([newLevel isEqualToEnum:SDLHMILevelNone]) {
+ // The SDL app is not yet running
+ SDLLogD(@"The HMI level is none");
}
if ([newLevel isEqualToEnum:SDLHMILevelFull]) {
- // We're always going to try to show the initial state, because if we've already shown it, it won't be shown, and we need to guard against some possible weird states
+ // We're always going to try to show the initial state. because if we've already shown it, it won't be shown, and we need to guard against some possible weird states
[self sdlex_showInitialData];
}
}
+- (void)systemContext:(nullable SDLSystemContext)oldContext didChangeToContext:(SDLSystemContext)newContext {
+ if ([newContext isEqualToEnum:SDLSystemContextAlert]) {
+ SDLLogD(@"The System Context is Alert");
+ } else if ([newContext isEqualToEnum:SDLSystemContextHMIObscured]) {
+ SDLLogD(@"The System Context is HMI Obscured");
+ } else if ([newContext isEqualToEnum:SDLSystemContextMain]) {
+ SDLLogD(@"The System Context is Main");
+ } else if ([newContext isEqualToEnum:SDLSystemContextMenu]) {
+ SDLLogD(@"The System Context is Menu");
+ } else if ([newContext isEqualToEnum:SDLSystemContextVoiceRecognitionSession]) {
+ SDLLogD(@"The System Context is Voice Recognition Session");
+ }
+}
+
+- (void)audioStreamingState:(nullable SDLAudioStreamingState)oldState didChangeToState:(SDLAudioStreamingState)newState {
+ if ([newState isEqualToEnum:SDLAudioStreamingStateAudible]) {
+ // The SDL app's audio can be heard
+ SDLLogD(@"The Audio Streaming State is Audible");
+ } else if ([newState isEqualToEnum:SDLAudioStreamingStateNotAudible]) {
+ // The SDL app's audio cannot be heard
+ SDLLogD(@"The Audio Streaming State is Not Audible");
+ } else if ([newState isEqualToEnum:SDLAudioStreamingStateAttenuated]) {
+ // The SDL app's audio volume has been lowered to let the system speak over the audio. This usually happens with voice recognition commands.
+ SDLLogD(@"The Audio Streaming State is Not Attenuated");
+ }
+}
+
- (nullable SDLLifecycleConfigurationUpdate *)managerShouldUpdateLifecycleToLanguage:(SDLLanguage)language {
SDLLifecycleConfigurationUpdate *update = [[SDLLifecycleConfigurationUpdate alloc] init];
if ([language isEqualToEnum:SDLLanguageEnUs]) {
- update.appName = SDLAppName;
+ update.appName = ExampleAppName;
} else if ([language isEqualToString:SDLLanguageEsMx]) {
- NSString *SDLAppNameSpanish = @"SDL Aplicación de ejemplo";
- update.appName = SDLAppNameSpanish;
+ update.appName = ExampleAppNameSpanish;
} else if ([language isEqualToString:SDLLanguageFrCa]) {
- NSString *SDLAppNameFrench = @"SDL Exemple App";
- update.appName = SDLAppNameFrench;
+ update.appName = ExampleAppNameFrench;
} else {
return nil;
}
diff --git a/SmartDeviceLink_Example/ConnectionContainerViewController.swift b/SmartDeviceLink_Example/ConnectionContainerViewController.swift
new file mode 100644
index 000000000..e990712fa
--- /dev/null
+++ b/SmartDeviceLink_Example/ConnectionContainerViewController.swift
@@ -0,0 +1,82 @@
+//
+// ConnectionContainerViewController.swift
+// SmartDeviceLink-ExampleSwift
+//
+// Copyright © 2017 smartdevicelink. All rights reserved.
+//
+import UIKit
+
+class ConnectionContainerViewController: UIViewController {
+ @IBOutlet weak var segmentedControl: UISegmentedControl!
+ var viewControllers: [UIViewController] = []
+ var currentViewController: UIViewController?
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+
+ navigationController?.navigationBar.isTranslucent = false
+ let tcpControllerStoryboard = UIStoryboard(name: "ConnectionTCPTableViewController", bundle: nil)
+ let iapControllerStoryboard = UIStoryboard(name: "ConnectionIAPTableViewController", bundle: nil)
+ let tcpController = tcpControllerStoryboard.instantiateViewController(withIdentifier :"ConnectionTCPTableViewController")
+ let iapController = iapControllerStoryboard.instantiateViewController(withIdentifier :"ConnectionIAPTableViewController")
+ viewControllers.append(tcpController)
+ viewControllers.append(iapController)
+
+ segmentedControl.selectedSegmentIndex = 0
+ loadChildViewController(index: 0)
+
+ let leftSwipe = UISwipeGestureRecognizer(target: self, action: #selector(slideToLeftWithGestureRecognizer(gestureRecognizer:)))
+ let rightSwipe = UISwipeGestureRecognizer(target: self, action: #selector(slideToRightWithGestureRecognizer(gestureRecognizer:)))
+ leftSwipe.direction = .left
+ rightSwipe.direction = .right
+ view.addGestureRecognizer(leftSwipe)
+ view.addGestureRecognizer(rightSwipe)
+ }
+
+ override func didReceiveMemoryWarning() {
+ super.didReceiveMemoryWarning()
+ // Dispose of any resources that can be recreated.
+ }
+
+ @IBAction func slideToLeftWithGestureRecognizer(gestureRecognizer: UISwipeGestureRecognizer) {
+ if segmentedControl.selectedSegmentIndex == 0 {
+ segmentedControl.selectedSegmentIndex = 1
+ removeFromView()
+ loadChildViewController(index: 1)
+ }
+ }
+
+ @IBAction func slideToRightWithGestureRecognizer(gestureRecognizer: UISwipeGestureRecognizer) {
+ if segmentedControl.selectedSegmentIndex == 1 {
+ segmentedControl.selectedSegmentIndex = 0
+ removeFromView()
+ loadChildViewController(index: 0)
+ }
+ }
+ // Grab changes in segmentedControl
+ @IBAction func indexChanged(_ sender: AnyObject) {
+ switch segmentedControl.selectedSegmentIndex {
+ case 0:
+ removeFromView()
+ loadChildViewController(index: 0)
+ case 1:
+ removeFromView()
+ loadChildViewController(index: 1)
+ default:
+ break
+ }
+ }
+ // Mark: - View functions
+ func removeFromView() {
+ let vc = self.childViewControllers.last
+ vc?.view.removeFromSuperview()
+ vc?.removeFromParentViewController()
+ }
+
+ func loadChildViewController(index: Int?) {
+ let initialViewController: UIViewController = viewControllers[index!] as! UIViewController
+ self.addChildViewController(initialViewController)
+ view.addSubview(initialViewController.view)
+ initialViewController.didMove(toParentViewController: self)
+ }
+}
diff --git a/SmartDeviceLink_Example/ConnectionIAPTableViewController.storyboard b/SmartDeviceLink_Example/ConnectionIAPTableViewController.storyboard
new file mode 100644
index 000000000..ef04daa8e
--- /dev/null
+++ b/SmartDeviceLink_Example/ConnectionIAPTableViewController.storyboard
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14109" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="J12-ul-Tx1">
+ <device id="retina4_7" orientation="portrait">
+ <adaptation id="fullscreen"/>
+ </device>
+ <dependencies>
+ <deployment identifier="iOS"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14088"/>
+ <capability name="Constraints to layout margins" minToolsVersion="6.0"/>
+ <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+ </dependencies>
+ <scenes>
+ <!--ConnectionIAP Table View Controller-->
+ <scene sceneID="kGx-OZ-JDF">
+ <objects>
+ <tableViewController storyboardIdentifier="ConnectionIAPTableViewController" id="J12-ul-Tx1" customClass="ConnectionIAPTableViewController" customModule="SmartDeviceLink_Example_Swift" customModuleProvider="target" sceneMemberID="viewController">
+ <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="grouped" separatorStyle="default" rowHeight="44" sectionHeaderHeight="10" sectionFooterHeight="10" id="MzB-GZ-Ook">
+ <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.95686274509803926" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ <sections>
+ <tableViewSection id="Qz3-D9-j37">
+ <cells>
+ <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="2sd-U1-9xV">
+ <rect key="frame" x="0.0" y="35" width="375" height="44"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="2sd-U1-9xV" id="EhZ-2E-WQ5">
+ <rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <subviews>
+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="rjq-vZ-OjB">
+ <rect key="frame" x="16" y="0.0" width="343" height="44"/>
+ <fontDescription key="fontDescription" type="system" pointSize="23"/>
+ <state key="normal" title="Connect">
+ <color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ </state>
+ <connections>
+ <action selector="connectButtonWasPressed:" destination="J12-ul-Tx1" eventType="touchUpInside" id="OEM-Ca-Pms"/>
+ </connections>
+ </button>
+ </subviews>
+ <constraints>
+ <constraint firstItem="rjq-vZ-OjB" firstAttribute="top" secondItem="EhZ-2E-WQ5" secondAttribute="top" id="8GY-v0-41a"/>
+ <constraint firstAttribute="bottom" secondItem="rjq-vZ-OjB" secondAttribute="bottom" id="FKB-JG-o5G"/>
+ <constraint firstAttribute="trailingMargin" secondItem="rjq-vZ-OjB" secondAttribute="trailing" id="ISQ-6b-S34"/>
+ <constraint firstItem="rjq-vZ-OjB" firstAttribute="leading" secondItem="EhZ-2E-WQ5" secondAttribute="leadingMargin" id="PiJ-h3-NOR"/>
+ </constraints>
+ </tableViewCellContentView>
+ </tableViewCell>
+ </cells>
+ </tableViewSection>
+ </sections>
+ <connections>
+ <outlet property="dataSource" destination="J12-ul-Tx1" id="kTG-wP-6Fl"/>
+ <outlet property="delegate" destination="J12-ul-Tx1" id="gKA-WB-R0A"/>
+ </connections>
+ </tableView>
+ <connections>
+ <outlet property="connectButton" destination="rjq-vZ-OjB" id="Sz8-r7-ddN"/>
+ <outlet property="connectTableViewCell" destination="2sd-U1-9xV" id="UME-sB-vsD"/>
+ <outlet property="table" destination="MzB-GZ-Ook" id="SME-OU-FAK"/>
+ </connections>
+ </tableViewController>
+ <placeholder placeholderIdentifier="IBFirstResponder" id="N5a-E0-fOt" userLabel="First Responder" sceneMemberID="firstResponder"/>
+ </objects>
+ <point key="canvasLocation" x="898" y="630"/>
+ </scene>
+ </scenes>
+</document>
diff --git a/SmartDeviceLink_Example/ConnectionIAPTableViewController.swift b/SmartDeviceLink_Example/ConnectionIAPTableViewController.swift
new file mode 100644
index 000000000..f5bacb922
--- /dev/null
+++ b/SmartDeviceLink_Example/ConnectionIAPTableViewController.swift
@@ -0,0 +1,72 @@
+//
+// ConnectionIAPTableViewController.swift
+// SmartDeviceLink-ExampleSwift
+//
+// Copyright © 2017 smartdevicelink. All rights reserved.
+//
+import UIKit
+
+class ConnectionIAPTableViewController: UITableViewController, ProxyManagerDelegate {
+
+ @IBOutlet weak var connectTableViewCell: UITableViewCell!
+ @IBOutlet weak var table: UITableView!
+ @IBOutlet weak var connectButton: UIButton!
+
+ var state: ProxyState = .stopped
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ ProxyManager.sharedManager.delegate = self
+ table.keyboardDismissMode = .onDrag
+ table.isScrollEnabled = false
+ initButton()
+ }
+
+ override func didReceiveMemoryWarning() {
+ super.didReceiveMemoryWarning()
+ }
+
+ func initButton() {
+ self.connectTableViewCell.backgroundColor = UIColor.red
+ self.connectButton.setTitle("Connect", for: .normal)
+ self.connectButton.setTitleColor(.white, for: .normal)
+ }
+ // MARK: - IBActions
+ @IBAction func connectButtonWasPressed(_ sender: UIButton) {
+
+ switch state {
+ case .stopped:
+ ProxyManager.sharedManager.start(with: .iap)
+ case .searching:
+ ProxyManager.sharedManager.resetConnection()
+ case .connected:
+ ProxyManager.sharedManager.resetConnection()
+ }
+ }
+ // MARK: - Delegate Functions
+ func didChangeProxyState(_ newState: ProxyState) {
+ state = newState
+ var newColor: UIColor? = nil
+ var newTitle: String? = nil
+
+ switch newState {
+ case .stopped:
+ newColor = UIColor.red
+ newTitle = "Connect"
+ case .searching:
+ newColor = UIColor.blue
+ newTitle = "Stop Searching"
+ case .connected:
+ newColor = UIColor.green
+ newTitle = "Disconnect"
+ }
+
+ if (newColor != nil) || (newTitle != nil) {
+ DispatchQueue.main.async(execute: {[weak self]() -> Void in
+ self?.connectTableViewCell.backgroundColor = newColor
+ self?.connectButton.setTitle(newTitle, for: .normal)
+ self?.connectButton.setTitleColor(.white, for: .normal)
+ })
+ }
+ }
+}
diff --git a/SmartDeviceLink_Example/ConnectionTCPTableViewController.storyboard b/SmartDeviceLink_Example/ConnectionTCPTableViewController.storyboard
new file mode 100644
index 000000000..84f74c3b1
--- /dev/null
+++ b/SmartDeviceLink_Example/ConnectionTCPTableViewController.storyboard
@@ -0,0 +1,135 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14109" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="l5Q-ZP-1BO">
+ <device id="retina4_7" orientation="portrait">
+ <adaptation id="fullscreen"/>
+ </device>
+ <dependencies>
+ <deployment identifier="iOS"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14088"/>
+ <capability name="Constraints to layout margins" minToolsVersion="6.0"/>
+ <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+ </dependencies>
+ <scenes>
+ <!--ConnectionTCP Table View Controller-->
+ <scene sceneID="geJ-kX-PTm">
+ <objects>
+ <tableViewController storyboardIdentifier="ConnectionTCPTableViewController" useStoryboardIdentifierAsRestorationIdentifier="YES" id="l5Q-ZP-1BO" customClass="ConnectionTCPTableViewController" customModule="SmartDeviceLink_Example_Swift" customModuleProvider="target" sceneMemberID="viewController">
+ <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="grouped" separatorStyle="default" rowHeight="44" sectionHeaderHeight="10" sectionFooterHeight="10" id="7ZH-AV-Zyf">
+ <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.95686274509803926" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ <sections>
+ <tableViewSection headerTitle="TCP Server" id="bF6-yi-Ial">
+ <cells>
+ <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="pbJ-oz-jNt">
+ <rect key="frame" x="0.0" y="55.5" width="375" height="44"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="pbJ-oz-jNt" id="B7X-yY-lwJ">
+ <rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <subviews>
+ <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="IP Address" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="xqM-s4-9RV">
+ <rect key="frame" x="16" y="0.0" width="343" height="44"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="44" id="5Pw-mh-x83"/>
+ </constraints>
+ <fontDescription key="fontDescription" type="system" pointSize="17"/>
+ <textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no" keyboardType="URL"/>
+ </textField>
+ </subviews>
+ <constraints>
+ <constraint firstAttribute="centerY" secondItem="xqM-s4-9RV" secondAttribute="centerY" id="PcX-lz-oQo"/>
+ <constraint firstItem="xqM-s4-9RV" firstAttribute="trailing" secondItem="B7X-yY-lwJ" secondAttribute="trailingMargin" id="YF9-Uh-Yqm"/>
+ <constraint firstItem="xqM-s4-9RV" firstAttribute="leading" secondItem="B7X-yY-lwJ" secondAttribute="leadingMargin" id="pBt-SK-tuZ"/>
+ </constraints>
+ </tableViewCellContentView>
+ </tableViewCell>
+ <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="C5b-fS-v3d">
+ <rect key="frame" x="0.0" y="99.5" width="375" height="44"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="C5b-fS-v3d" id="ZD4-xA-og5">
+ <rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <subviews>
+ <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="Port" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="hsI-ld-8xY">
+ <rect key="frame" x="16" y="0.0" width="343" height="44"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="44" id="FpG-5e-MHT"/>
+ </constraints>
+ <fontDescription key="fontDescription" type="system" pointSize="17"/>
+ <textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no" keyboardType="numberPad"/>
+ </textField>
+ </subviews>
+ <constraints>
+ <constraint firstAttribute="centerY" secondItem="hsI-ld-8xY" secondAttribute="centerY" id="X1e-g3-RJN"/>
+ <constraint firstItem="hsI-ld-8xY" firstAttribute="leading" secondItem="ZD4-xA-og5" secondAttribute="leadingMargin" id="oeB-5U-tOl"/>
+ <constraint firstItem="hsI-ld-8xY" firstAttribute="trailing" secondItem="ZD4-xA-og5" secondAttribute="trailingMargin" id="wXl-bK-7vU"/>
+ </constraints>
+ </tableViewCellContentView>
+ </tableViewCell>
+ </cells>
+ </tableViewSection>
+ <tableViewSection headerTitle="" id="rgl-Lm-uDH">
+ <cells>
+ <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="ybX-Eh-Hbx">
+ <rect key="frame" x="0.0" y="163.5" width="375" height="44"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="ybX-Eh-Hbx" id="uI9-fK-205">
+ <rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <subviews>
+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="tailTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="t37-4W-6F4">
+ <rect key="frame" x="16" y="0.0" width="343" height="43"/>
+ <fontDescription key="fontDescription" type="system" pointSize="23"/>
+ <state key="normal" title="Connect">
+ <color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ </state>
+ <connections>
+ <action selector="connectButtonWasPressed:" destination="l5Q-ZP-1BO" eventType="touchUpInside" id="4Kr-4D-O7b"/>
+ </connections>
+ </button>
+ </subviews>
+ <constraints>
+ <constraint firstItem="t37-4W-6F4" firstAttribute="top" secondItem="uI9-fK-205" secondAttribute="top" id="IfU-4k-EXx"/>
+ <constraint firstItem="t37-4W-6F4" firstAttribute="leading" secondItem="uI9-fK-205" secondAttribute="leadingMargin" id="cc3-uk-9fL"/>
+ <constraint firstAttribute="bottom" secondItem="t37-4W-6F4" secondAttribute="bottom" id="hnD-4g-xvT"/>
+ <constraint firstAttribute="trailingMargin" secondItem="t37-4W-6F4" secondAttribute="trailing" id="j4p-fi-0LP"/>
+ </constraints>
+ </tableViewCellContentView>
+ </tableViewCell>
+ </cells>
+ </tableViewSection>
+ </sections>
+ <connections>
+ <outlet property="dataSource" destination="l5Q-ZP-1BO" id="r5q-yg-LY6"/>
+ <outlet property="delegate" destination="l5Q-ZP-1BO" id="xFj-yP-z0A"/>
+ </connections>
+ </tableView>
+ <navigationItem key="navigationItem" id="JNL-hN-wDm">
+ <nil key="title"/>
+ <segmentedControl key="titleView" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="bar" selectedSegmentIndex="0" id="rXi-EW-KGG">
+ <rect key="frame" x="180" y="7" width="240" height="30"/>
+ <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+ <segments>
+ <segment title="TCP Debug"/>
+ <segment title="iAP"/>
+ </segments>
+ <connections>
+ <action selector="connectionTypeSegmentedControlDidChange:" destination="l5Q-ZP-1BO" eventType="valueChanged" id="uaO-bf-NQR"/>
+ </connections>
+ </segmentedControl>
+ </navigationItem>
+ <connections>
+ <outlet property="connectButton" destination="t37-4W-6F4" id="f6v-Q4-ggs"/>
+ <outlet property="connectTableViewCell" destination="ybX-Eh-Hbx" id="hyh-CW-oXx"/>
+ <outlet property="ipAddressTextField" destination="xqM-s4-9RV" id="daz-uN-Rxa"/>
+ <outlet property="portTextField" destination="hsI-ld-8xY" id="5pF-XP-Xh3"/>
+ <outlet property="table" destination="7ZH-AV-Zyf" id="4nR-6A-RzX"/>
+ </connections>
+ </tableViewController>
+ <placeholder placeholderIdentifier="IBFirstResponder" id="0fm-wO-kFd" userLabel="First Responder" sceneMemberID="firstResponder"/>
+ </objects>
+ <point key="canvasLocation" x="688" y="499"/>
+ </scene>
+ </scenes>
+</document>
diff --git a/SmartDeviceLink_Example/ConnectionTCPTableViewController.swift b/SmartDeviceLink_Example/ConnectionTCPTableViewController.swift
new file mode 100644
index 000000000..3cf1e91c3
--- /dev/null
+++ b/SmartDeviceLink_Example/ConnectionTCPTableViewController.swift
@@ -0,0 +1,88 @@
+//
+// ConnectionTCPTableViewController.swift
+// SmartDeviceLink-ExampleSwift
+//
+// Copyright © 2017 smartdevicelink. All rights reserved.
+//
+import UIKit
+
+class ConnectionTCPTableViewController: UITableViewController, UINavigationControllerDelegate, ProxyManagerDelegate {
+
+ @IBOutlet weak var ipAddressTextField: UITextField!
+ @IBOutlet weak var portTextField: UITextField!
+ @IBOutlet weak var connectTableViewCell: UITableViewCell!
+ @IBOutlet weak var connectButton: UIButton!
+ @IBOutlet weak var table: UITableView!
+
+ var state: ProxyState = .stopped
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ ProxyManager.sharedManager.delegate = self
+ table.keyboardDismissMode = .onDrag
+ table.isScrollEnabled = false
+ ipAddressTextField.text = AppUserDefaults.shared.ipAddress
+ portTextField.text = AppUserDefaults.shared.port
+ initButton()
+ }
+
+ override func didReceiveMemoryWarning() {
+ super.didReceiveMemoryWarning()
+ }
+
+ func initButton() {
+ self.connectTableViewCell.backgroundColor = UIColor.red
+ self.connectButton.setTitle("Connect", for: .normal)
+ self.connectButton.setTitleColor(.white, for: .normal)
+ }
+ // MARK: - IBActions
+ @IBAction func connectButtonWasPressed(_ sender: UIButton) {
+
+ let ipAddress = ipAddressTextField.text
+ let port = portTextField.text
+
+ if ipAddress != "" || port != "" {
+ AppUserDefaults.shared.ipAddress = ipAddress
+ AppUserDefaults.shared.port = port
+
+ switch state {
+ case .stopped:
+ ProxyManager.sharedManager.start(with: .tcp)
+ case .searching:
+ ProxyManager.sharedManager.resetConnection()
+ case .connected:
+ ProxyManager.sharedManager.resetConnection()
+ }
+ } else {
+ let alertMessage = UIAlertController(title: "Missing Info!", message: "Make sure to set your IP Address and Port", preferredStyle: .alert)
+ alertMessage.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
+ self.present(alertMessage, animated: true, completion: nil)
+ }
+ }
+ // MARK: - Delegate Functions
+ func didChangeProxyState(_ newState: ProxyState) {
+ state = newState
+ var newColor: UIColor? = nil
+ var newTitle: String? = nil
+
+ switch newState {
+ case .stopped:
+ newColor = UIColor.red
+ newTitle = "Connect"
+ case .searching:
+ newColor = UIColor.blue
+ newTitle = "Stop Searching"
+ case .connected:
+ newColor = UIColor.green
+ newTitle = "Disconnect"
+ }
+
+ if (newColor != nil) || (newTitle != nil) {
+ DispatchQueue.main.async(execute: {[weak self]() -> Void in
+ self?.connectTableViewCell.backgroundColor = newColor
+ self?.connectButton.setTitle(newTitle, for: .normal)
+ self?.connectButton.setTitleColor(.white, for: .normal)
+ })
+ }
+ }
+}
diff --git a/SmartDeviceLink_Example/Images.xcassets/star_softbutton_icon.imageset/Contents.json b/SmartDeviceLink_Example/Images.xcassets/car.imageset/Contents.json
index 1a3c6d569..da6fe9437 100644
--- a/SmartDeviceLink_Example/Images.xcassets/star_softbutton_icon.imageset/Contents.json
+++ b/SmartDeviceLink_Example/Images.xcassets/car.imageset/Contents.json
@@ -2,7 +2,7 @@
"images" : [
{
"idiom" : "universal",
- "filename" : "star_black_softbutton_icon.png",
+ "filename" : "iconmonstr-car-1-64.png",
"scale" : "1x"
},
{
diff --git a/SmartDeviceLink_Example/Images.xcassets/car.imageset/iconmonstr-car-1-64.png b/SmartDeviceLink_Example/Images.xcassets/car.imageset/iconmonstr-car-1-64.png
new file mode 100644
index 000000000..c95eaa035
--- /dev/null
+++ b/SmartDeviceLink_Example/Images.xcassets/car.imageset/iconmonstr-car-1-64.png
Binary files differ
diff --git a/SmartDeviceLink_Example/Images.xcassets/hexagon_on_softbutton_icon.imageset/Contents.json b/SmartDeviceLink_Example/Images.xcassets/car_icon.imageset/Contents.json
index 5e22962d4..6e2269ebd 100644
--- a/SmartDeviceLink_Example/Images.xcassets/hexagon_on_softbutton_icon.imageset/Contents.json
+++ b/SmartDeviceLink_Example/Images.xcassets/car_icon.imageset/Contents.json
@@ -2,7 +2,7 @@
"images" : [
{
"idiom" : "universal",
- "filename" : "hexagon_pink_softbutton_icon.png",
+ "filename" : "car.png",
"scale" : "1x"
},
{
diff --git a/SmartDeviceLink_Example/Images.xcassets/car_icon.imageset/car.png b/SmartDeviceLink_Example/Images.xcassets/car_icon.imageset/car.png
new file mode 100644
index 000000000..de2eb2699
--- /dev/null
+++ b/SmartDeviceLink_Example/Images.xcassets/car_icon.imageset/car.png
Binary files differ
diff --git a/SmartDeviceLink_Example/Images.xcassets/hexagon_off_softbutton_icon.imageset/Contents.json b/SmartDeviceLink_Example/Images.xcassets/choice_set.imageset/Contents.json
index 9affc0da6..e784269b3 100644
--- a/SmartDeviceLink_Example/Images.xcassets/hexagon_off_softbutton_icon.imageset/Contents.json
+++ b/SmartDeviceLink_Example/Images.xcassets/choice_set.imageset/Contents.json
@@ -2,7 +2,7 @@
"images" : [
{
"idiom" : "universal",
- "filename" : "hexagon_black_softbutton_icon.png",
+ "filename" : "iconmonstr-text-23-64.png",
"scale" : "1x"
},
{
diff --git a/SmartDeviceLink_Example/Images.xcassets/choice_set.imageset/iconmonstr-text-23-64.png b/SmartDeviceLink_Example/Images.xcassets/choice_set.imageset/iconmonstr-text-23-64.png
new file mode 100644
index 000000000..23a0aa481
--- /dev/null
+++ b/SmartDeviceLink_Example/Images.xcassets/choice_set.imageset/iconmonstr-text-23-64.png
Binary files differ
diff --git a/SmartDeviceLink_Example/Images.xcassets/hexagon_off_softbutton_icon.imageset/hexagon_black_softbutton_icon.png b/SmartDeviceLink_Example/Images.xcassets/hexagon_off_softbutton_icon.imageset/hexagon_black_softbutton_icon.png
deleted file mode 100644
index 2ec628d9e..000000000
--- a/SmartDeviceLink_Example/Images.xcassets/hexagon_off_softbutton_icon.imageset/hexagon_black_softbutton_icon.png
+++ /dev/null
Binary files differ
diff --git a/SmartDeviceLink_Example/Images.xcassets/hexagon_on_softbutton_icon.imageset/hexagon_pink_softbutton_icon.png b/SmartDeviceLink_Example/Images.xcassets/hexagon_on_softbutton_icon.imageset/hexagon_pink_softbutton_icon.png
deleted file mode 100644
index 8e588ebb5..000000000
--- a/SmartDeviceLink_Example/Images.xcassets/hexagon_on_softbutton_icon.imageset/hexagon_pink_softbutton_icon.png
+++ /dev/null
Binary files differ
diff --git a/SmartDeviceLink_Example/Images.xcassets/laptop_icon.imageset/Contents.json b/SmartDeviceLink_Example/Images.xcassets/laptop_icon.imageset/Contents.json
new file mode 100644
index 000000000..616325375
--- /dev/null
+++ b/SmartDeviceLink_Example/Images.xcassets/laptop_icon.imageset/Contents.json
@@ -0,0 +1,21 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "screen.png",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+} \ No newline at end of file
diff --git a/SmartDeviceLink_Example/Images.xcassets/laptop_icon.imageset/screen.png b/SmartDeviceLink_Example/Images.xcassets/laptop_icon.imageset/screen.png
new file mode 100644
index 000000000..33b727eae
--- /dev/null
+++ b/SmartDeviceLink_Example/Images.xcassets/laptop_icon.imageset/screen.png
Binary files differ
diff --git a/SmartDeviceLink_Example/Images.xcassets/microphone.imageset/Contents.json b/SmartDeviceLink_Example/Images.xcassets/microphone.imageset/Contents.json
new file mode 100644
index 000000000..4620dff89
--- /dev/null
+++ b/SmartDeviceLink_Example/Images.xcassets/microphone.imageset/Contents.json
@@ -0,0 +1,21 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "microphone.png",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+} \ No newline at end of file
diff --git a/SmartDeviceLink_Example/Images.xcassets/microphone.imageset/microphone.png b/SmartDeviceLink_Example/Images.xcassets/microphone.imageset/microphone.png
new file mode 100644
index 000000000..8ccae2bcb
--- /dev/null
+++ b/SmartDeviceLink_Example/Images.xcassets/microphone.imageset/microphone.png
Binary files differ
diff --git a/SmartDeviceLink_Example/Images.xcassets/phone.imageset/Contents.json b/SmartDeviceLink_Example/Images.xcassets/phone.imageset/Contents.json
new file mode 100644
index 000000000..feb2dff17
--- /dev/null
+++ b/SmartDeviceLink_Example/Images.xcassets/phone.imageset/Contents.json
@@ -0,0 +1,21 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "phone.png",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+} \ No newline at end of file
diff --git a/SmartDeviceLink_Example/Images.xcassets/phone.imageset/phone.png b/SmartDeviceLink_Example/Images.xcassets/phone.imageset/phone.png
new file mode 100644
index 000000000..7c7eff383
--- /dev/null
+++ b/SmartDeviceLink_Example/Images.xcassets/phone.imageset/phone.png
Binary files differ
diff --git a/SmartDeviceLink_Example/Images.xcassets/speak.imageset/Contents.json b/SmartDeviceLink_Example/Images.xcassets/speak.imageset/Contents.json
new file mode 100644
index 000000000..38dbeb7ed
--- /dev/null
+++ b/SmartDeviceLink_Example/Images.xcassets/speak.imageset/Contents.json
@@ -0,0 +1,21 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "iconmonstr-speech-bubble-5-64.png",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+} \ No newline at end of file
diff --git a/SmartDeviceLink_Example/Images.xcassets/speak.imageset/iconmonstr-speech-bubble-5-64.png b/SmartDeviceLink_Example/Images.xcassets/speak.imageset/iconmonstr-speech-bubble-5-64.png
new file mode 100644
index 000000000..9404acfe5
--- /dev/null
+++ b/SmartDeviceLink_Example/Images.xcassets/speak.imageset/iconmonstr-speech-bubble-5-64.png
Binary files differ
diff --git a/SmartDeviceLink_Example/Images.xcassets/star_softbutton_icon.imageset/star_black_softbutton_icon.png b/SmartDeviceLink_Example/Images.xcassets/star_softbutton_icon.imageset/star_black_softbutton_icon.png
deleted file mode 100644
index 70812b60a..000000000
--- a/SmartDeviceLink_Example/Images.xcassets/star_softbutton_icon.imageset/star_black_softbutton_icon.png
+++ /dev/null
Binary files differ
diff --git a/SmartDeviceLink_Example/Images.xcassets/wheel_icon.imageset/Contents.json b/SmartDeviceLink_Example/Images.xcassets/wheel_icon.imageset/Contents.json
new file mode 100644
index 000000000..e5dbc5bd1
--- /dev/null
+++ b/SmartDeviceLink_Example/Images.xcassets/wheel_icon.imageset/Contents.json
@@ -0,0 +1,21 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "wheel.png",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+} \ No newline at end of file
diff --git a/SmartDeviceLink_Example/Images.xcassets/wheel_icon.imageset/wheel.png b/SmartDeviceLink_Example/Images.xcassets/wheel_icon.imageset/wheel.png
new file mode 100644
index 000000000..bd99c3f49
--- /dev/null
+++ b/SmartDeviceLink_Example/Images.xcassets/wheel_icon.imageset/wheel.png
Binary files differ
diff --git a/SmartDeviceLink_Example/LaunchScreen.xib b/SmartDeviceLink_Example/LaunchScreen.xib
new file mode 100644
index 000000000..fc726aac2
--- /dev/null
+++ b/SmartDeviceLink_Example/LaunchScreen.xib
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="12120" systemVersion="16E195" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES">
+ <device id="retina4_7" orientation="portrait">
+ <adaptation id="fullscreen"/>
+ </device>
+ <dependencies>
+ <deployment identifier="iOS"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12088"/>
+ <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+ </dependencies>
+ <objects>
+ <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
+ <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+ <view contentMode="scaleToFill" id="iN0-l3-epB">
+ <rect key="frame" x="0.0" y="0.0" width="480" height="480"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <subviews>
+ <imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="sdl_logo_green" translatesAutoresizingMaskIntoConstraints="NO" id="poo-xI-0Ul">
+ <rect key="frame" x="135" y="135" width="210" height="210"/>
+ </imageView>
+ </subviews>
+ <color key="backgroundColor" red="0.22352941176470587" green="0.30588235294117649" blue="0.37647058823529411" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ <constraints>
+ <constraint firstAttribute="bottom" secondItem="poo-xI-0Ul" secondAttribute="bottom" constant="135" id="Aoi-5X-ydr"/>
+ <constraint firstItem="poo-xI-0Ul" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" constant="135" id="VYi-CO-nXk"/>
+ <constraint firstAttribute="trailing" secondItem="poo-xI-0Ul" secondAttribute="trailing" constant="135" id="ZvS-nt-v4W"/>
+ <constraint firstItem="poo-xI-0Ul" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="135" id="dyt-I7-yml"/>
+ </constraints>
+ <nil key="simulatedStatusBarMetrics"/>
+ <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+ <point key="canvasLocation" x="548" y="455"/>
+ </view>
+ </objects>
+ <resources>
+ <image name="sdl_logo_green" width="131" height="122"/>
+ </resources>
+</document>
diff --git a/SmartDeviceLink_Example/Main.storyboard b/SmartDeviceLink_Example/Main.storyboard
new file mode 100644
index 000000000..0bb92be82
--- /dev/null
+++ b/SmartDeviceLink_Example/Main.storyboard
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14109" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="mM3-m6-I5t">
+ <device id="retina4_7" orientation="portrait">
+ <adaptation id="fullscreen"/>
+ </device>
+ <dependencies>
+ <deployment identifier="iOS"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14088"/>
+ <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+ </dependencies>
+ <scenes>
+ <!--Navigation Controller-->
+ <scene sceneID="Tfy-dw-box">
+ <objects>
+ <navigationController automaticallyAdjustsScrollViewInsets="NO" id="mM3-m6-I5t" sceneMemberID="viewController">
+ <toolbarItems/>
+ <navigationBar key="navigationBar" contentMode="scaleToFill" id="eMh-g9-C8T">
+ <rect key="frame" x="0.0" y="20" width="375" height="44"/>
+ <autoresizingMask key="autoresizingMask"/>
+ </navigationBar>
+ <nil name="viewControllers"/>
+ <connections>
+ <segue destination="cXb-Co-0MA" kind="relationship" relationship="rootViewController" id="tbn-vJ-YS8"/>
+ </connections>
+ </navigationController>
+ <placeholder placeholderIdentifier="IBFirstResponder" id="eXu-Zc-53v" userLabel="First Responder" sceneMemberID="firstResponder"/>
+ </objects>
+ <point key="canvasLocation" x="896" y="527"/>
+ </scene>
+ <!--Connection Container View Controller-->
+ <scene sceneID="vG9-Hv-OW2">
+ <objects>
+ <viewController id="cXb-Co-0MA" customClass="ConnectionContainerViewController" customModule="SmartDeviceLink_Example_Swift" customModuleProvider="target" sceneMemberID="viewController">
+ <layoutGuides>
+ <viewControllerLayoutGuide type="top" id="bfp-O0-sxl"/>
+ <viewControllerLayoutGuide type="bottom" id="fet-m3-F1O"/>
+ </layoutGuides>
+ <view key="view" contentMode="scaleToFill" id="jkb-9Y-Hwh">
+ <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ </view>
+ <navigationItem key="navigationItem" id="t1a-s2-nn6">
+ <nil key="title"/>
+ <segmentedControl key="titleView" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="bar" selectedSegmentIndex="0" id="RYa-fE-Qek">
+ <rect key="frame" x="67.5" y="7" width="240" height="30"/>
+ <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+ <segments>
+ <segment title="TCP Debug"/>
+ <segment title="iAP"/>
+ </segments>
+ <connections>
+ <action selector="indexChanged:" destination="cXb-Co-0MA" eventType="valueChanged" id="mRP-MF-F8c"/>
+ </connections>
+ </segmentedControl>
+ </navigationItem>
+ <connections>
+ <outlet property="segmentedControl" destination="RYa-fE-Qek" id="Ude-uG-TAL"/>
+ </connections>
+ </viewController>
+ <placeholder placeholderIdentifier="IBFirstResponder" id="ETn-uq-A6g" userLabel="First Responder" sceneMemberID="firstResponder"/>
+ </objects>
+ <point key="canvasLocation" x="1576" y="527"/>
+ </scene>
+ </scenes>
+</document>
diff --git a/SmartDeviceLink_Example/MenuManager.h b/SmartDeviceLink_Example/MenuManager.h
new file mode 100644
index 000000000..dfcc15445
--- /dev/null
+++ b/SmartDeviceLink_Example/MenuManager.h
@@ -0,0 +1,24 @@
+//
+// MenuManager.h
+// SmartDeviceLink-Example-ObjC
+//
+// Created by Nicole on 5/15/18.
+// Copyright © 2018 smartdevicelink. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@class SDLManager;
+@class SDLMenuCell;
+@class SDLVoiceCommand;
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface MenuManager : NSObject
+
++ (NSArray<SDLMenuCell *> *)allMenuItemsWithManager:(SDLManager *)manager;
++ (NSArray<SDLVoiceCommand *> *)allVoiceMenuItemsWithManager:(SDLManager *)manager;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink_Example/MenuManager.m b/SmartDeviceLink_Example/MenuManager.m
new file mode 100644
index 000000000..ccf91cef8
--- /dev/null
+++ b/SmartDeviceLink_Example/MenuManager.m
@@ -0,0 +1,106 @@
+//
+// MenuManager.m
+// SmartDeviceLink-Example-ObjC
+//
+// Created by Nicole on 5/15/18.
+// Copyright © 2018 smartdevicelink. All rights reserved.
+//
+
+#import "MenuManager.h"
+#import "AlertManager.h"
+#import "AudioManager.h"
+#import "AppConstants.h"
+#import "PerformInteractionManager.h"
+#import "RPCPermissionsManager.h"
+#import "SmartDeviceLink.h"
+#import "VehicleDataManager.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@implementation MenuManager
+
++ (NSArray<SDLMenuCell *> *)allMenuItemsWithManager:(SDLManager *)manager {
+ return @[[self sdlex_menuCellSpeakNameWithManager:manager],
+ [self sdlex_menuCellGetVehicleSpeedWithManager:manager],
+ [self sdlex_menuCellShowPerformInteractionWithManager:manager],
+ [self sdlex_menuCellRecordInCarMicrophoneAudioWithManager:manager],
+ [self sdlex_menuCellDialNumberWithManager:manager],
+ [self sdlex_menuCellWithSubmenuWithManager:manager]];
+}
+
++ (NSArray<SDLVoiceCommand *> *)allVoiceMenuItemsWithManager:(SDLManager *)manager {
+ if (!manager.systemCapabilityManager.vrCapability) {
+ SDLLogE(@"The head unit does not support voice recognition");
+ return @[];
+ }
+
+ return @[[self.class sdlex_voiceCommandStartWithManager:manager], [self.class sdlex_voiceCommandStopWithManager:manager]];
+}
+
+#pragma mark - Menu Items
+
++ (SDLMenuCell *)sdlex_menuCellSpeakNameWithManager:(SDLManager *)manager {
+ return [[SDLMenuCell alloc] initWithTitle:ACSpeakAppNameMenuName icon:[SDLArtwork artworkWithImage:[UIImage imageNamed:SpeakBWIconImageName] asImageFormat:SDLArtworkImageFormatPNG] voiceCommands:@[ACSpeakAppNameMenuName] handler:^(SDLTriggerSource _Nonnull triggerSource) {
+ [manager sendRequest:[[SDLSpeak alloc] initWithTTS:ExampleAppNameTTS]];
+ }];
+}
+
++ (SDLMenuCell *)sdlex_menuCellGetVehicleSpeedWithManager:(SDLManager *)manager {
+ return [[SDLMenuCell alloc] initWithTitle:ACGetVehicleDataMenuName icon:[SDLArtwork artworkWithImage:[UIImage imageNamed:CarBWIconImageName] asImageFormat:SDLArtworkImageFormatPNG] voiceCommands:@[ACGetVehicleDataMenuName] handler:^(SDLTriggerSource _Nonnull triggerSource) {
+ [VehicleDataManager getVehicleSpeedWithManager:manager];
+ }];
+}
+
++ (SDLMenuCell *)sdlex_menuCellShowPerformInteractionWithManager:(SDLManager *)manager {
+ return [[SDLMenuCell alloc] initWithTitle:ACShowChoiceSetMenuName icon:[SDLArtwork artworkWithImage:[UIImage imageNamed:MenuBWIconImageName] asImageFormat:SDLArtworkImageFormatPNG] voiceCommands:@[ACShowChoiceSetMenuName] handler:^(SDLTriggerSource _Nonnull triggerSource) {
+ [PerformInteractionManager showPerformInteractionChoiceSetWithManager:manager triggerSource:triggerSource];
+ }];
+}
+
++ (SDLMenuCell *)sdlex_menuCellRecordInCarMicrophoneAudioWithManager:(SDLManager *)manager {
+ AudioManager *audioManager = [[AudioManager alloc] initWithManager:manager];
+ return [[SDLMenuCell alloc] initWithTitle:ACRecordInCarMicrophoneAudioMenuName icon:[SDLArtwork artworkWithImage:[UIImage imageNamed:MicrophoneBWIconImageName] asImageFormat:SDLArtworkImageFormatPNG] voiceCommands:@[ACRecordInCarMicrophoneAudioMenuName] handler:^(SDLTriggerSource _Nonnull triggerSource) {
+ [audioManager startRecording];
+ }];
+}
+
++ (SDLMenuCell *)sdlex_menuCellDialNumberWithManager:(SDLManager *)manager {
+ return [[SDLMenuCell alloc] initWithTitle:ACDialPhoneNumberMenuName icon:[SDLArtwork artworkWithImage:[UIImage imageNamed:PhoneBWIconImageName] asImageFormat:SDLArtworkImageFormatPNG] voiceCommands:@[ACDialPhoneNumberMenuName] handler:^(SDLTriggerSource _Nonnull triggerSource) {
+ if (![RPCPermissionsManager isDialNumberRPCAllowedWithManager:manager]) {
+ [manager sendRequest:[AlertManager alertWithMessageAndCloseButton:@"This app does not have the required permissions to dial a number" textField2:nil]];
+ return;
+ }
+
+ [VehicleDataManager checkPhoneCallCapabilityWithManager:manager phoneNumber:@"555-555-5555"];
+ }];
+}
+
++ (SDLMenuCell *)sdlex_menuCellWithSubmenuWithManager:(SDLManager *)manager {
+ NSMutableArray *submenuItems = [NSMutableArray array];
+ for (int i = 0; i < 75; i++) {
+ SDLMenuCell *cell = [[SDLMenuCell alloc] initWithTitle:[NSString stringWithFormat:@"%@ %i", ACSubmenuItemMenuName, i] icon:[SDLArtwork artworkWithImage:[UIImage imageNamed:MenuBWIconImageName] asImageFormat:SDLArtworkImageFormatPNG] voiceCommands:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {
+ [manager sendRequest:[AlertManager alertWithMessageAndCloseButton:[NSString stringWithFormat:@"You selected %@ %i", ACSubmenuItemMenuName, i] textField2:nil]];
+ }];
+ [submenuItems addObject:cell];
+ }
+
+ return [[SDLMenuCell alloc] initWithTitle:ACSubmenuMenuName subCells:[submenuItems copy]];
+}
+
+#pragma mark - Voice Commands
+
++ (SDLVoiceCommand *)sdlex_voiceCommandStartWithManager:(SDLManager *)manager {
+ return [[SDLVoiceCommand alloc] initWithVoiceCommands:@[VCStop] handler:^{
+ [manager sendRequest:[AlertManager alertWithMessageAndCloseButton:[NSString stringWithFormat:@"%@ voice command selected!", VCStop] textField2:nil]];
+ }];
+}
+
++ (SDLVoiceCommand *)sdlex_voiceCommandStopWithManager:(SDLManager *)manager {
+ return [[SDLVoiceCommand alloc] initWithVoiceCommands:@[VCStart] handler:^{
+ [manager sendRequest:[AlertManager alertWithMessageAndCloseButton:[NSString stringWithFormat:@"%@ voice command selected!", VCStart] textField2:nil]];
+ }];
+}
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink_Example/MenuManager.swift b/SmartDeviceLink_Example/MenuManager.swift
new file mode 100644
index 000000000..cba211043
--- /dev/null
+++ b/SmartDeviceLink_Example/MenuManager.swift
@@ -0,0 +1,154 @@
+//
+// MenuManager.swift
+// SmartDeviceLink-Example-Swift
+//
+// Created by Nicole on 4/11/18.
+// Copyright © 2018 smartdevicelink. All rights reserved.
+//
+
+import Foundation
+import SmartDeviceLink
+import SmartDeviceLinkSwift
+
+class MenuManager: NSObject {
+ /// Creates and returns the menu items
+ ///
+ /// - Parameter manager: The SDL Manager
+ /// - Returns: An array of SDLAddCommand objects
+ class func allMenuItems(with manager: SDLManager) -> [SDLMenuCell] {
+ return [menuCellSpeakName(with: manager),
+ menuCellGetVehicleSpeed(with: manager),
+ menuCellShowPerformInteraction(with: manager),
+ menuCellRecordInCarMicrophoneAudio(with: manager),
+ menuCellDialNumber(with: manager),
+ menuCellWithSubmenu(with: manager)]
+ }
+
+ /// Creates and returns the voice commands. The voice commands are menu items that are selected using the voice recognition system.
+ ///
+ /// - Parameter manager: The SDL Manager
+ /// - Returns: An array of SDLVoiceCommand objects
+ class func allVoiceMenuItems(with manager: SDLManager) -> [SDLVoiceCommand] {
+ guard manager.systemCapabilityManager.vrCapability else {
+ SDLLog.e("The head unit does not support voice recognition")
+ return []
+ }
+ return [voiceCommandStart(with: manager), voiceCommandStop(with: manager)]
+ }
+}
+
+// MARK: - Root Menu
+
+private extension MenuManager {
+ /// Menu item that speaks the app name when selected
+ ///
+ /// - Parameter manager: The SDL Manager
+ /// - Returns: A SDLMenuCell object
+ class func menuCellSpeakName(with manager: SDLManager) -> SDLMenuCell {
+ return SDLMenuCell(title: ACSpeakAppNameMenuName, icon: SDLArtwork(image: UIImage(named: SpeakBWIconImageName)!, persistent: true, as: .PNG), voiceCommands: [ACSpeakAppNameMenuName], handler: { _ in
+ manager.send(request: SDLSpeak(tts: ExampleAppNameTTS), responseHandler: { (_, response, error) in
+ guard response?.resultCode == .success else { return }
+ SDLLog.e("Error sending the Speak RPC: \(error?.localizedDescription ?? "no error message")")
+ })
+ })
+ }
+
+ /// Menu item that requests vehicle data when selected
+ ///
+ /// - Parameter manager: The SDL Manager
+ /// - Returns: A SDLMenuCell object
+ class func menuCellGetVehicleSpeed(with manager: SDLManager) -> SDLMenuCell {
+ return SDLMenuCell(title: ACGetVehicleDataMenuName, icon: SDLArtwork(image: UIImage(named: CarBWIconImageName)!, persistent: true, as: .PNG), voiceCommands: [ACGetVehicleDataMenuName], handler: { _ in
+ VehicleDataManager.getVehicleSpeed(with: manager)
+ })
+ }
+
+ /// Menu item that shows a custom menu (i.e. a Perform Interaction Choice Set) when selected
+ ///
+ /// - Parameter manager: The SDL Manager
+ /// - Returns: A SDLMenuCell object
+ class func menuCellShowPerformInteraction(with manager: SDLManager) -> SDLMenuCell {
+ return SDLMenuCell(title: ACShowChoiceSetMenuName, icon: SDLArtwork(image: UIImage(named: MenuBWIconImageName)!, persistent: true, as: .PNG), voiceCommands: [ACShowChoiceSetMenuName], handler: { triggerSource in
+ PerformInteractionManager.showPerformInteractionChoiceSet(with: manager, triggerSource: triggerSource)
+ })
+ }
+
+ /// Menu item that starts recording sounds via the in-car microphone when selected
+ ///
+ /// - Parameter manager: The SDL Manager
+ /// - Returns: A SDLMenuCell object
+ class func menuCellRecordInCarMicrophoneAudio(with manager: SDLManager) -> SDLMenuCell {
+ if #available(iOS 10.0, *) {
+ let audioManager = AudioManager(sdlManager: manager)
+ return SDLMenuCell(title: ACRecordInCarMicrophoneAudioMenuName, icon: SDLArtwork(image: UIImage(named: MicrophoneBWIconImageName)!, persistent: true, as: .PNG), voiceCommands: [ACRecordInCarMicrophoneAudioMenuName], handler: { _ in
+ audioManager.startRecording()
+ })
+ }
+
+ return SDLMenuCell(title: ACRecordInCarMicrophoneAudioMenuName, icon: SDLArtwork(image: UIImage(named: SpeakBWIconImageName)!, persistent: true, as: .PNG), voiceCommands: [ACRecordInCarMicrophoneAudioMenuName], handler: { _ in
+ manager.send(AlertManager.alertWithMessageAndCloseButton("Speech recognition feature only available on iOS 10+"))
+ })
+ }
+
+ /// Menu item that dials a phone number when selected
+ ///
+ /// - Parameter manager: The SDL Manager
+ /// - Returns: A SDLMenuCell object
+ class func menuCellDialNumber(with manager: SDLManager) -> SDLMenuCell {
+ return SDLMenuCell(title: ACDialPhoneNumberMenuName, icon: SDLArtwork(image: UIImage(named: PhoneBWIconImageName)!, persistent: true, as: .PNG), voiceCommands: [ACDialPhoneNumberMenuName], handler: { _ in
+ guard RPCPermissionsManager.isDialNumberRPCAllowed(with: manager) else {
+ manager.send(AlertManager.alertWithMessageAndCloseButton("This app does not have the required permissions to dial a number"))
+ return
+ }
+
+ VehicleDataManager.checkPhoneCallCapability(manager: manager, phoneNumber:"555-555-5555")
+ })
+ }
+
+ /// Menu item that opens a submenu when selected
+ ///
+ /// - Parameter manager: The SDL Manager
+ /// - Returns: A SDLMenuCell object
+ class func menuCellWithSubmenu(with manager: SDLManager) -> SDLMenuCell {
+ var submenuItems = [SDLMenuCell]()
+ for i in 0..<75 {
+ let submenuTitle = "Submenu Item \(i)"
+ submenuItems.append(SDLMenuCell(title: submenuTitle, icon: SDLArtwork(image: UIImage(named: MenuBWIconImageName)!, persistent: true, as: .PNG), voiceCommands: [submenuTitle, "Item \(i)", "\(i)"], handler: { (triggerSource) in
+ let message = "\(submenuTitle) selected!"
+ switch triggerSource {
+ case .menu:
+ manager.send(AlertManager.alertWithMessageAndCloseButton(message))
+ case .voiceRecognition:
+ manager.send(SDLSpeak(tts: message))
+ default: break
+ }
+ }))
+ }
+
+ return SDLMenuCell(title: "Submenu", subCells: submenuItems)
+ }
+}
+
+// MARK: - Menu Voice Commands
+
+private extension MenuManager {
+ /// Voice command menu item that shows an alert when triggered via the VR system
+ ///
+ /// - Parameter manager: The SDL Manager
+ /// - Returns: A SDLVoiceCommand object
+ class func voiceCommandStart(with manager: SDLManager) -> SDLVoiceCommand {
+ return SDLVoiceCommand(voiceCommands: [VCStart], handler: {
+ manager.send(AlertManager.alertWithMessageAndCloseButton("\(VCStart) voice command selected!"))
+ })
+ }
+
+ /// Voice command menu item that shows an alert when triggered via the VR system
+ ///
+ /// - Parameter manager: The SDL Manager
+ /// - Returns: A SDLVoiceCommand object
+ class func voiceCommandStop(with manager: SDLManager) -> SDLVoiceCommand {
+ return SDLVoiceCommand(voiceCommands: [VCStop], handler: {
+ manager.send(AlertManager.alertWithMessageAndCloseButton("\(VCStop) voice command selected!"))
+ })
+ }
+}
diff --git a/SmartDeviceLink_Example/PerformInteractionManager.h b/SmartDeviceLink_Example/PerformInteractionManager.h
new file mode 100644
index 000000000..73e79e515
--- /dev/null
+++ b/SmartDeviceLink_Example/PerformInteractionManager.h
@@ -0,0 +1,24 @@
+//
+// PerformInteractionManager.h
+// SmartDeviceLink-Example-ObjC
+//
+// Created by Nicole on 5/15/18.
+// Copyright © 2018 smartdevicelink. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import "SDLTriggerSource.h"
+
+@class SDLCreateInteractionChoiceSet;
+@class SDLManager;
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface PerformInteractionManager : NSObject
+
++ (SDLCreateInteractionChoiceSet *)createInteractionChoiceSet;
++ (void)showPerformInteractionChoiceSetWithManager:(SDLManager *)manager triggerSource:(SDLTriggerSource)triggerSource;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink_Example/PerformInteractionManager.m b/SmartDeviceLink_Example/PerformInteractionManager.m
new file mode 100644
index 000000000..6e6523174
--- /dev/null
+++ b/SmartDeviceLink_Example/PerformInteractionManager.m
@@ -0,0 +1,56 @@
+//
+// PerformInteractionManager.m
+// SmartDeviceLink-Example-ObjC
+//
+// Created by Nicole on 5/15/18.
+// Copyright © 2018 smartdevicelink. All rights reserved.
+//
+
+#import "PerformInteractionManager.h"
+#import "AppConstants.h"
+#import "SmartDeviceLink.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@implementation PerformInteractionManager
+
+static UInt32 ChoiceSetId = 100;
+
++ (SDLCreateInteractionChoiceSet *)createInteractionChoiceSet {
+ return [[SDLCreateInteractionChoiceSet alloc] initWithId:ChoiceSetId choiceSet:[self sdlex_createChoiceSet]];
+}
+
++ (void)showPerformInteractionChoiceSetWithManager:(SDLManager *)manager triggerSource:(SDLTriggerSource)triggerSource {
+ [manager sendRequest:[self sdlex_createPerformInteractionWithTriggerSource:triggerSource] withResponseHandler:^(__kindof SDLRPCRequest * _Nullable request, __kindof SDLRPCResponse * _Nullable response, NSError * _Nullable error) {
+ if (response.resultCode != SDLResultSuccess) {
+ SDLLogE(@"The Show Perform Interaction Choice Set request failed: %@", error.localizedDescription);
+ return;
+ }
+
+ if ([response.resultCode isEqualToEnum:SDLResultTimedOut]) {
+ SDLLogD(@"The perform interaction choice set menu timed out before the user could select an item");
+ [manager sendRequest:[[SDLSpeak alloc] initWithTTS:TTSYouMissed]];
+ } else if ([response.resultCode isEqualToEnum:SDLResultSuccess]) {
+ SDLLogD(@"The user selected an item in the perform interaction choice set menu");
+ [manager sendRequest:[[SDLSpeak alloc] initWithTTS:TTSGoodJob]];
+ }
+ }];
+}
+
++ (NSArray<SDLChoice *> *)sdlex_createChoiceSet {
+ SDLChoice *firstChoice = [[SDLChoice alloc] initWithId:1 menuName:PICSFirstChoice vrCommands:@[PICSFirstChoice]];
+ SDLChoice *secondChoice = [[SDLChoice alloc] initWithId:2 menuName:PICSSecondChoice vrCommands:@[PICSSecondChoice]];
+ SDLChoice *thirdChoice = [[SDLChoice alloc] initWithId:3 menuName:PICSThirdChoice vrCommands:@[PICSThirdChoice]];
+ return @[firstChoice, secondChoice, thirdChoice];
+}
+
++ (SDLPerformInteraction *)sdlex_createPerformInteractionWithTriggerSource:(SDLTriggerSource)triggerSource {
+ SDLInteractionMode interactionMode = [triggerSource isEqualToEnum:SDLTriggerSourceVoiceRecognition] ? SDLInteractionModeVoiceRecognitionOnly : SDLInteractionModeManualOnly;
+ SDLPerformInteraction *performInteraction = [[SDLPerformInteraction alloc] initWithInitialPrompt:PICSInitialPrompt initialText:PICSInitialText interactionChoiceSetIDList:@[@(ChoiceSetId)] helpPrompt:PICSHelpPrompt timeoutPrompt:PICSTimeoutPrompt interactionMode:interactionMode timeout:10000];
+ performInteraction.interactionLayout = SDLLayoutModeListOnly;
+ return performInteraction;
+}
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink_Example/PerformInteractionManager.swift b/SmartDeviceLink_Example/PerformInteractionManager.swift
new file mode 100644
index 000000000..021997923
--- /dev/null
+++ b/SmartDeviceLink_Example/PerformInteractionManager.swift
@@ -0,0 +1,65 @@
+//
+// PerformInteractionManager.swift
+// SmartDeviceLink-Example-Swift
+//
+// Created by Nicole on 5/15/18.
+// Copyright © 2018 smartdevicelink. All rights reserved.
+//
+
+import UIKit
+import SmartDeviceLink
+import SmartDeviceLinkSwift
+
+class PerformInteractionManager: NSObject {
+ /// Creates a choice set to be used in a PerformInteraction. The choice set must be sent to SDL Core and a response received before it can be used in a PerformInteraction request.
+ ///
+ /// - Returns: A SDLCreateInteractionChoiceSet request
+ class func createInteractionChoiceSet() -> SDLCreateInteractionChoiceSet {
+ return SDLCreateInteractionChoiceSet(id: UInt32(ChoiceSetId), choiceSet: createChoiceSet())
+ }
+
+ /// Shows a PICS. The handler is called when the user selects a menu item or when the menu times out after a set amount of time. A custom text-to-speech phrase is spoken when the menu is closed.
+ ///
+ /// - Parameter manager: The SDL Manager
+ class func showPerformInteractionChoiceSet(with manager: SDLManager, triggerSource: SDLTriggerSource) {
+ manager.send(request: createPerformInteraction(triggerSource: triggerSource)) { (_, response, error) in
+ guard response?.resultCode == .success else {
+ SDLLog.e("The Show Perform Interaction Choice Set request failed: \(error?.localizedDescription ?? "no error")")
+ return
+ }
+
+ if response?.resultCode == .timedOut {
+ // The menu timed out before the user could select an item
+ manager.send(SDLSpeak(tts: TTSYouMissed))
+ } else if response?.resultCode == .success {
+ // The user selected an item in the menu
+ manager.send(SDLSpeak(tts: TTSGoodJob))
+ }
+ }
+ }
+}
+
+// MARK: - PICS Menu
+
+private extension PerformInteractionManager {
+ static let ChoiceSetId = 100
+ /// The PICS menu items
+ ///
+ /// - Returns: An array of SDLChoice items
+ class func createChoiceSet() -> [SDLChoice] {
+ let firstChoice = SDLChoice(id: 1, menuName: PICSFirstChoice, vrCommands: [PICSFirstChoice])
+ let secondChoice = SDLChoice(id: 2, menuName: PICSSecondChoice, vrCommands: [PICSSecondChoice])
+ let thirdChoice = SDLChoice(id: 3, menuName: PICSThirdChoice, vrCommands: [PICSThirdChoice])
+ return [firstChoice, secondChoice, thirdChoice]
+ }
+
+ /// Creates a PICS with three menu items and customized voice commands
+ ///
+ /// - Returns: A SDLPerformInteraction request
+ class func createPerformInteraction(triggerSource: SDLTriggerSource) -> SDLPerformInteraction {
+ let interactionMode: SDLInteractionMode = triggerSource == .voiceRecognition ? .voiceRecognitionOnly : .manualOnly
+ let performInteraction = SDLPerformInteraction(initialPrompt: PICSInitialPrompt, initialText: PICSInitialText, interactionChoiceSetIDList: [ChoiceSetId as NSNumber], helpPrompt: PICSHelpPrompt, timeoutPrompt: PICSTimeoutPrompt, interactionMode: interactionMode, timeout: 10000)
+ performInteraction.interactionLayout = .listOnly
+ return performInteraction
+ }
+}
diff --git a/SmartDeviceLink_Example/Protocol+ProxyManagerDelegate.swift b/SmartDeviceLink_Example/Protocol+ProxyManagerDelegate.swift
new file mode 100644
index 000000000..ede7b7701
--- /dev/null
+++ b/SmartDeviceLink_Example/Protocol+ProxyManagerDelegate.swift
@@ -0,0 +1,13 @@
+//
+// Protocol+ProxyManagerDelegate.swift
+// SmartDeviceLink
+//
+// Created by Nicole on 4/12/18.
+// Copyright © 2018 smartdevicelink. All rights reserved.
+//
+
+import Foundation
+
+protocol ProxyManagerDelegate: class {
+ func didChangeProxyState(_ newState: ProxyState)
+}
diff --git a/SmartDeviceLink_Example/ProxyManager.swift b/SmartDeviceLink_Example/ProxyManager.swift
new file mode 100644
index 000000000..7ecc28679
--- /dev/null
+++ b/SmartDeviceLink_Example/ProxyManager.swift
@@ -0,0 +1,285 @@
+//
+// ProxyManager.swift
+// SmartDeviceLink-ExampleSwift
+//
+// Copyright © 2017 smartdevicelink. All rights reserved.
+//
+
+import UIKit
+import SmartDeviceLink
+import SmartDeviceLinkSwift
+
+enum ProxyTransportType {
+ case tcp
+ case iap
+}
+
+enum ProxyState {
+ case stopped
+ case searching
+ case connected
+}
+
+class ProxyManager: NSObject {
+ fileprivate var sdlManager: SDLManager!
+ fileprivate var buttonManager: ButtonManager!
+ fileprivate var vehicleDataManager: VehicleDataManager!
+ fileprivate var firstHMILevelState: SDLHMILevel
+ weak var delegate: ProxyManagerDelegate?
+
+ // Singleton
+ static let sharedManager = ProxyManager()
+ private override init() {
+ firstHMILevelState = .none
+ super.init()
+ }
+}
+
+// MARK: - SDL Configuration
+
+extension ProxyManager {
+ /// Configures the SDL Manager that handles data transfer beween this app and the car's head unit and starts searching for a connection to a head unit. There are two possible types of transport layers to use: TCP is used to connect wirelessly to SDL Core and is only available for debugging; iAP is used to connect to MFi (Made for iPhone) hardware and is must be used for production builds.
+ ///
+ /// - Parameter connectionType: The type of transport layer to use.
+ func start(with proxyTransportType: ProxyTransportType) {
+ delegate?.didChangeProxyState(ProxyState.searching)
+ sdlManager = SDLManager(configuration: proxyTransportType == .iap ? ProxyManager.connectIAP() : ProxyManager.connectTCP(), delegate: self)
+ startManager()
+ }
+
+ /// Attempts to close the connection between the this app and the car's head unit. The `SDLManagerDelegate`'s `managerDidDisconnect()` is called when connection is actually closed.
+ func resetConnection() {
+ guard sdlManager != nil else {
+ delegate?.didChangeProxyState(ProxyState.stopped)
+ return
+ }
+
+ sdlManager.stop()
+ }
+}
+
+// MARK: - SDL Configuration Helpers
+
+private extension ProxyManager {
+ /// Configures an iAP transport layer.
+ ///
+ /// - Returns: A SDLConfiguration object
+ class func connectIAP() -> SDLConfiguration {
+ let lifecycleConfiguration = SDLLifecycleConfiguration(appName: ExampleAppName, appId: ExampleAppId)
+ return setupManagerConfiguration(with: lifecycleConfiguration)
+ }
+
+ /// Configures a TCP transport layer with the IP address and port of the remote SDL Core instance.
+ ///
+ /// - Returns: A SDLConfiguration object
+ class func connectTCP() -> SDLConfiguration {
+ let lifecycleConfiguration = SDLLifecycleConfiguration(appName: ExampleAppName, appId: ExampleAppId, ipAddress: AppUserDefaults.shared.ipAddress!, port: UInt16(AppUserDefaults.shared.port!)!)
+ return setupManagerConfiguration(with: lifecycleConfiguration)
+ }
+
+ /// Helper method for setting additional configuration parameters for both TCP and iAP transport layers.
+ ///
+ /// - Parameter lifecycleConfiguration: The transport layer configuration
+ /// - Returns: A SDLConfiguration object
+ class func setupManagerConfiguration(with lifecycleConfiguration: SDLLifecycleConfiguration) -> SDLConfiguration {
+ lifecycleConfiguration.shortAppName = ExampleAppNameShort
+ let appIcon = UIImage(named: ExampleAppLogoName)
+ lifecycleConfiguration.appIcon = appIcon != nil ? SDLArtwork(image: appIcon!, persistent: true, as: .PNG) : nil
+ lifecycleConfiguration.appType = .default
+ lifecycleConfiguration.language = .enUs
+ lifecycleConfiguration.languagesSupported = [.enUs, .esMx, .frCa]
+ lifecycleConfiguration.ttsName = [SDLTTSChunk(text: "S D L", type: .text)]
+
+ let lockScreenConfiguration = appIcon != nil ? SDLLockScreenConfiguration.enabledConfiguration(withAppIcon: appIcon!, backgroundColor: nil) : SDLLockScreenConfiguration.enabled()
+ return SDLConfiguration(lifecycle: lifecycleConfiguration, lockScreen: lockScreenConfiguration, logging: logConfiguration())
+ }
+
+ /// Sets the type of SDL debug logs that are visible and where to port the logs. There are 4 levels of log filtering, verbose, debug, warning and error. Verbose prints all SDL logs; error prints only the error logs. Adding SDLLogTargetFile to the targest will log to a text file on the iOS device. This file can be accessed via: iTunes > Your Device Name > File Sharing > Your App Name. Make sure `UIFileSharingEnabled` has been added to the application's info.plist and is set to `true`.
+ ///
+ /// - Returns: A SDLLogConfiguration object
+ class func logConfiguration() -> SDLLogConfiguration {
+ let logConfig = SDLLogConfiguration.default()
+ let exampleLogFileModule = SDLLogFileModule(name: "SDL Swift Example App", files: ["ProxyManager", "AlertManager", "AudioManager", "ButtonManager", "MenuManager", "PerformInteractionManager", "RPCPermissionsManager", "VehicleDataManager"])
+ logConfig.modules.insert(exampleLogFileModule)
+ _ = logConfig.targets.insert(SDLLogTargetFile()) // Logs to file
+ logConfig.globalLogLevel = .debug // Filters the logs
+ return logConfig
+ }
+
+ /// Searches for a connection to a SDL enabled accessory. When a connection has been established, the ready handler is called. Even though the app is connected to SDL Core, it does not mean that RPCs can be immediately sent to the accessory as there is no guarentee that SDL Core is ready to receive RPCs. Monitor the `SDLManagerDelegate`'s `hmiLevel:didChangeToLevel:` to determine when to send RPCs.
+ func startManager() {
+ sdlManager.start(readyHandler: { [unowned self] (success, error) in
+ guard success else {
+ SDLLog.e("There was an error while starting up: \(String(describing: error))")
+ self.resetConnection()
+ return
+ }
+
+ self.delegate?.didChangeProxyState(ProxyState.connected)
+
+ self.buttonManager = ButtonManager(sdlManager: self.sdlManager, updateScreenHandler: self.refreshUIHandler)
+ self.vehicleDataManager = VehicleDataManager(sdlManager: self.sdlManager, refreshUIHandler: self.refreshUIHandler)
+
+ RPCPermissionsManager.setupPermissionsCallbacks(with: self.sdlManager)
+
+ SDLLog.d("SDL file manager storage: \(self.sdlManager.fileManager.bytesAvailable / 1024 / 1024) mb")
+ })
+ }
+}
+
+// MARK: - SDLManagerDelegate
+
+extension ProxyManager: SDLManagerDelegate {
+ /// Called when the connection beween this app and SDL Core has closed.
+ func managerDidDisconnect() {
+ delegate?.didChangeProxyState(ProxyState.stopped)
+ firstHMILevelState = .none
+
+ // If desired, automatically start searching for a new connection to Core
+ if ExampleAppShouldRestartSDLManagerOnDisconnect.boolValue {
+ startManager()
+ }
+ }
+
+ /// Called when the state of the SDL app has changed. The state limits the type of RPC that can be sent. Refer to the class documentation for each RPC to determine what state(s) the RPC can be sent.
+ ///
+ /// - Parameters:
+ /// - oldLevel: The old SDL HMI Level
+ /// - newLevel: The new SDL HMI Level
+ func hmiLevel(_ oldLevel: SDLHMILevel, didChangeToLevel newLevel: SDLHMILevel) {
+ if newLevel != .none && firstHMILevelState == .none {
+ // This is our first time in a non-NONE state
+ firstHMILevelState = newLevel
+
+ // Send static menu items. Menu related RPCs can be sent at all `hmiLevel`s except `NONE`
+ createStaticMenus()
+ vehicleDataManager.subscribeToVehicleOdometer()
+ }
+
+ if newLevel == .full && firstHMILevelState != .full {
+ // This is our first time in a `FULL` state.
+ firstHMILevelState = newLevel
+ }
+
+ switch newLevel {
+ case .full: // The SDL app is in the foreground
+ // Always try to show the initial state to guard against some possible weird states. Duplicates will be ignored by Core.
+ showInitialData()
+ case .limited: break // An active NAV or MEDIA SDL app is in the background
+ case .background: break // The SDL app is not in the foreground
+ case .none: break // The SDL app is not yet running
+ default: break
+ }
+ }
+
+ func systemContext(_ oldContext: SDLSystemContext?, didChangeToContext newContext: SDLSystemContext) {
+ switch newContext {
+ case SDLSystemContext.alert: break
+ case SDLSystemContext.hmiObscured: break
+ case SDLSystemContext.main: break
+ case SDLSystemContext.menu: break
+ case SDLSystemContext.voiceRecognitionSession: break
+ default: break
+ }
+ }
+
+ /// Called when the audio state of the SDL app has changed. The audio state only needs to be monitored if the app is streaming audio.
+ ///
+ /// - Parameters:
+ /// - oldState: The old SDL audio streaming state
+ /// - newState: The new SDL audio streaming state
+ func audioStreamingState(_ oldState: SDLAudioStreamingState?, didChangeToState newState: SDLAudioStreamingState) {
+ switch newState {
+ case .audible: break // The SDL app's audio can be heard
+ case .notAudible: break // The SDL app's audio cannot be heard
+ case .attenuated: break // The SDL app's audio volume has been lowered to let the system speak over the audio. This usually happens with voice recognition commands.
+ default: break
+ }
+ }
+
+ /// Called when the car's head unit language is different from the default langage set in the SDLConfiguration AND the head unit language is supported by the app (as set in `languagesSupported` of SDLConfiguration). This method is only called when a connection to Core is first established. If desired, you can update the app's name and text-to-speech name to reflect the head unit's language.
+ ///
+ /// - Parameter language: The head unit's current language
+ /// - Returns: A SDLLifecycleConfigurationUpdate object
+ func managerShouldUpdateLifecycle(toLanguage language: SDLLanguage) -> SDLLifecycleConfigurationUpdate? {
+ var appName = ""
+ switch language {
+ case .enUs:
+ appName = ExampleAppName
+ case .esMx:
+ appName = ExampleAppNameSpanish
+ case .frCa:
+ appName = ExampleAppNameFrench
+ default:
+ return nil
+ }
+
+ return SDLLifecycleConfigurationUpdate(appName: appName, shortAppName: nil, ttsName: [SDLTTSChunk(text: appName, type: .text)], voiceRecognitionCommandNames: nil)
+ }
+}
+
+// MARK: - SDL UI
+
+private extension ProxyManager {
+ /// Handler for refreshing the UI
+ var refreshUIHandler: RefreshUIHandler? {
+ return { [unowned self] () in
+ self.updateScreen()
+ }
+ }
+
+ /// Set the template and create the UI
+ func showInitialData() {
+ guard sdlManager.hmiLevel == .full else { return }
+
+ updateScreen()
+ sdlManager.screenManager.softButtonObjects = buttonManager.allScreenSoftButtons(with: sdlManager)
+ }
+
+ /// Update the UI's textfields, images and soft buttons
+ func updateScreen() {
+ guard sdlManager.hmiLevel == .full else { return }
+
+ let screenManager = sdlManager.screenManager
+ let isTextVisible = buttonManager.textEnabled
+ let areImagesVisible = buttonManager.imagesEnabled
+
+ screenManager.beginUpdates()
+ screenManager.textAlignment = .left
+ screenManager.textField1 = isTextVisible ? SmartDeviceLinkText : nil
+ screenManager.textField2 = isTextVisible ? "Swift \(ExampleAppText)" : nil
+ screenManager.textField3 = isTextVisible ? vehicleDataManager.vehicleOdometerData : nil
+
+ if sdlManager.systemCapabilityManager.displayCapabilities?.graphicSupported.boolValue ?? false {
+ screenManager.primaryGraphic = areImagesVisible ? SDLArtwork(image: UIImage(named: ExampleAppLogoName)!, persistent: false, as: .PNG) : nil
+ }
+
+ screenManager.endUpdates(completionHandler: { (error) in
+ guard error != nil else { return }
+ SDLLog.e("Textfields, graphics and soft buttons failed to update: \(error!.localizedDescription)")
+ })
+ }
+
+ /// Send static menu data
+ func createStaticMenus() {
+ // Send the root menu items
+ let screenManager = sdlManager.screenManager
+ let menuItems = MenuManager.allMenuItems(with: sdlManager)
+ let voiceMenuItems = MenuManager.allVoiceMenuItems(with: sdlManager)
+
+ screenManager.beginUpdates()
+ if !menuItems.isEmpty { screenManager.menu = menuItems }
+ if !voiceMenuItems.isEmpty { screenManager.voiceCommands = voiceMenuItems }
+ screenManager.endUpdates { (error) in
+ guard error != nil else { return }
+ SDLLog.e("Menu items and voice commands failed to update: \(error!.localizedDescription)")
+ }
+
+ // Send the choice sets
+ sdlManager.send([PerformInteractionManager.createInteractionChoiceSet()], progressHandler: { (request, response, error, percentComplete) in
+ SDLLog.d("\(request), was sent \(response?.resultCode == .success ? "successfully" : "unsuccessfully"), error: \(error?.localizedDescription ?? "no error message")")
+ }, completionHandler: { (success) in
+ SDLLog.d("All prepare remote system requests sent \(success ? "successfully" : "unsuccessfully")")
+ })
+ }
+}
diff --git a/SmartDeviceLink_Example/RPCPermissionsManager.h b/SmartDeviceLink_Example/RPCPermissionsManager.h
new file mode 100644
index 000000000..09e321f31
--- /dev/null
+++ b/SmartDeviceLink_Example/RPCPermissionsManager.h
@@ -0,0 +1,21 @@
+//
+// RPCPermissionsManager.h
+// SmartDeviceLink-Example-ObjC
+//
+// Created by Nicole on 5/11/18.
+// Copyright © 2018 smartdevicelink. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import "SmartDeviceLink.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface RPCPermissionsManager : NSObject
+
++ (void)setupPermissionsCallbacksWithManager:(SDLManager *)manager;
++ (BOOL)isDialNumberRPCAllowedWithManager:(SDLManager *)manager;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink_Example/RPCPermissionsManager.m b/SmartDeviceLink_Example/RPCPermissionsManager.m
new file mode 100644
index 000000000..dc5cf6dfc
--- /dev/null
+++ b/SmartDeviceLink_Example/RPCPermissionsManager.m
@@ -0,0 +1,138 @@
+//
+// RPCPermissionsManager.m
+// SmartDeviceLink-Example-ObjC
+//
+// Created by Nicole on 5/11/18.
+// Copyright © 2018 smartdevicelink. All rights reserved.
+//
+
+#import "RPCPermissionsManager.h"
+#import "SDLLogMacros.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@implementation RPCPermissionsManager
+
+/**
+ * Examples of how to check the permissions of select RPCs
+ *
+ * @param manager The SDL Manager
+ */
++ (void)setupPermissionsCallbacksWithManager:(SDLManager *)manager {
+ // Checks if the `SDLShow` RPC is allowed right at this moment
+ NSString *showRPCName = @"Show";
+ [self sdlex_checkCurrentPermissionWithManager:manager rpcName:showRPCName];
+
+ // Checks if all the RPCs need to create menus are allowed right at this moment
+ NSArray<NSString *> *menuRPCNames = @[@"AddCommand", @"CreateInteractionChoiceSet", @"PerformInteraction"];
+ [self sdlex_checkCurrentGroupPermissionsWithManager:manager rpcNames:menuRPCNames];
+
+ // Set up an observer for permissions changes to media template releated RPCs. Since the `groupType` is set to all allowed, this block is called when the group permissions changes from all allowed. This block is called immediately when created.
+ NSArray<NSString *> *mediaTemplateRPCs = @[@"SetMediaClockTimer", @"SubscribeButton"];
+ SDLPermissionObserverIdentifier allAllowedObserverId = [self sdlex_subscribeGroupPermissionsWithManager:manager rpcNames:mediaTemplateRPCs groupType:SDLPermissionGroupTypeAllAllowed];
+
+ // Stop observing permissions changes for the media template releated RPCs
+ [self sdlex_unsubscribeGroupPermissionsWithManager:manager observerId:allAllowedObserverId];
+
+ // Set up an observer for permissions changes to media template releated RPCs. Since the `groupType` is set to any, this block is called when the permission status changes for any of the RPCs being observed. This block is called immediately when created.
+ [self sdlex_subscribeGroupPermissionsWithManager:manager rpcNames:mediaTemplateRPCs groupType:SDLPermissionGroupTypeAny];
+}
+
+/**
+ * Checks if the `DialNumber` RPC is allowed
+ *
+ * @param manager The SDL Manager
+ * @return True if allowed, false if not
+ */
++ (BOOL)isDialNumberRPCAllowedWithManager:(SDLManager *)manager {
+ SDLLogD(@"Checking if app has permission to dial a number");
+ return [self sdlex_checkCurrentPermissionWithManager:manager rpcName:@"DialNumber"];
+}
+
+#pragma mark - Check Permissions
+
+#pragma mark Current Permissions
+
+/**
+ * Checks the current permissions of a single RPC
+ *
+ * @param manager The SDL Manager
+ * @param rpcName The name of the RPC
+ * @return True if the RPC can be sent to Core right now, false if not
+ */
++ (BOOL)sdlex_checkCurrentPermissionWithManager:(SDLManager *)manager rpcName:(NSString *)rpcName {
+ BOOL isRPCAllowed = [manager.permissionManager isRPCAllowed:rpcName];
+ [self sdlex_logRPCPermission:rpcName isRPCAllowed:isRPCAllowed];
+ return isRPCAllowed;
+}
+
+/**
+ * Checks the current permissions of a group of RPCs
+ *
+ * @param manager The SDL Manager
+ * @param rpcNames The names of the RPCs
+ * @return The current permission status for all the RPCs in the group
+ */
++ (SDLPermissionGroupStatus)sdlex_checkCurrentGroupPermissionsWithManager:(SDLManager *)manager rpcNames:(NSArray<NSString *> *)rpcNames {
+ SDLPermissionGroupStatus groupPermissionStatus = [manager.permissionManager groupStatusOfRPCs:rpcNames];
+ NSDictionary<NSString *, NSNumber *> *individualPermissionStatuses = [manager.permissionManager statusOfRPCs:rpcNames];
+ [self sdlex_logRPCGroupPermissions:rpcNames groupPermissionStatus:groupPermissionStatus individualPermissionStatuses:individualPermissionStatuses];
+ return groupPermissionStatus;
+}
+
+#pragma mark Subscribe Permissions
+
+/**
+ * Sets up a block for observing permission changes for a group of RPCs. This block is called immediately when created and when the permission status changes for the group of RPCs being observed.
+ *
+ * @param manager The SDL Manager
+ * @param rpcNames The names of the RPCs to be subscribed
+ * @param groupType The type of changes you want to be notified about for the group
+ * @return A unique identifier for the subscription. This can be used to later to unsubscribe from the notifications.
+ */
++ (SDLPermissionObserverIdentifier)sdlex_subscribeGroupPermissionsWithManager:(SDLManager *)manager rpcNames:(NSArray<NSString *> *)rpcNames groupType:(SDLPermissionGroupType)groupType {
+ SDLPermissionObserverIdentifier observerId = [manager.permissionManager addObserverForRPCs:rpcNames groupType:groupType withHandler:^(NSDictionary<SDLPermissionRPCName,NSNumber<SDLBool> *> * _Nonnull change, SDLPermissionGroupStatus status) {
+ [self sdlex_logRPCGroupPermissions:rpcNames groupPermissionStatus:status individualPermissionStatuses:change];
+ }];
+ return observerId;
+}
+
+/**
+ * Unsubscribe to notifications about permissions changes for a group of RPCs
+ *
+ * @param manager The SDL Manager
+ * @param observerId The unique identifier for a group of RPCs
+ */
++ (void)sdlex_unsubscribeGroupPermissionsWithManager:(SDLManager *)manager observerId:(SDLPermissionObserverIdentifier)observerId {
+ [manager.permissionManager removeObserverForIdentifier:observerId];
+}
+
+#pragma mark - Debug Logging
+
+/**
+ * Logs permissions for a single RPC
+ *
+ * @param rpcName The name of the RPC
+ * @param isRPCAllowed The permission status for the RPC
+ */
++ (void)sdlex_logRPCPermission:(NSString *)rpcName isRPCAllowed:(BOOL)isRPCAllowed {
+ SDLLogD(@"%@ RPC can be sent to SDL Core? %@", rpcName, isRPCAllowed ? @"Yes" : @"No");
+}
+
+/**
+ * Logs permissions for a group of RPCs
+ *
+ * @param rpcNames The names of the RPCs
+ * @param groupPermissionStatus The permission status for all RPCs in the group
+ * @param individualPermissionStatuses The permission status for each of the RPCs in the group
+ */
++ (void)sdlex_logRPCGroupPermissions:(NSArray<NSString *> *)rpcNames groupPermissionStatus:(SDLPermissionGroupStatus)groupPermissionStatus individualPermissionStatuses:(NSDictionary<NSString *, NSNumber *> *)individualPermissionStatuses {
+ SDLLogD(@"The group status for %@ has changed to: %lu", rpcNames, (unsigned long)groupPermissionStatus);
+ [individualPermissionStatuses enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSNumber * _Nonnull obj, BOOL * _Nonnull stop) {
+ [self sdlex_logRPCPermission:key isRPCAllowed:obj.boolValue];
+ }];
+}
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink_Example/RPCPermissionsManager.swift b/SmartDeviceLink_Example/RPCPermissionsManager.swift
new file mode 100644
index 000000000..72cdb8019
--- /dev/null
+++ b/SmartDeviceLink_Example/RPCPermissionsManager.swift
@@ -0,0 +1,119 @@
+//
+// RPCPermissionsManager.swift
+// SmartDeviceLink
+//
+// Created by Nicole on 4/13/18.
+// Copyright © 2018 smartdevicelink. All rights reserved.
+//
+
+import Foundation
+import SmartDeviceLink
+import SmartDeviceLinkSwift
+
+class RPCPermissionsManager {
+ /// Checks if an RPC has the required permission to be sent to SDL Core and gets notifications if those permissions change.
+ ///
+ /// - Parameter manager: The SDL Manager
+ class func setupPermissionsCallbacks(with manager: SDLManager) {
+ // Checks if the `SDLShow` RPC is allowed right at this moment
+ let showRPCName = "Show"
+ _ = checkCurrentPermission(with: manager, rpcName: showRPCName)
+
+ // Checks if all the RPCs need to create menus are allowed right at this moment
+ let menuRPCNames = ["AddCommand", "CreateInteractionChoiceSet", "PerformInteraction"]
+ _ = checkCurrentGroupPermissions(with: manager, rpcNames: menuRPCNames)
+
+ // Set up an observer for permissions changes to media template releated RPCs. Since the `groupType` is set to all allowed, this block is called when the group permissions changes from all allowed. This block is called immediately when created.
+ let mediaTemplateRPCs = ["SetMediaClockTimer", "SubscribeButton"]
+ let allAllowedObserverId = subscribeGroupPermissions(with: manager, rpcNames: mediaTemplateRPCs, groupType: .allAllowed)
+
+ // Stop observing permissions changes for the media template releated RPCs
+ unsubscribeGroupPermissions(with: manager, observerId: allAllowedObserverId)
+
+ // Sets up a block for observing permission changes for a group of RPCs. Since the `groupType` is set to any, this block is called when the permission status changes for any of the RPCs being observed. This block is called immediately when created.
+ _ = subscribeGroupPermissions(with: manager, rpcNames: mediaTemplateRPCs, groupType: .any)
+ }
+
+ /// Checks if the `DialNumber` RPC is allowed
+ ///
+ /// - Parameter manager: The SDL Manager
+ /// - Returns: True if allowed, false if not
+ class func isDialNumberRPCAllowed(with manager: SDLManager) -> Bool {
+ SDLLog.d("Checking if app has permission to dial a number")
+ return checkCurrentPermission(with: manager, rpcName: "DialNumber")
+ }
+}
+
+// MARK: - Check Permissions
+
+private extension RPCPermissionsManager {
+ /// Checks if the `Show` RPC is allowed right at this moment
+ ///
+ /// - Parameter manager: The SDL Manager
+ /// - Returns: true if allowed, false if not
+ class func checkCurrentPermission(with manager: SDLManager, rpcName: String) -> Bool {
+ let isRPCAllowed = manager.permissionManager.isRPCAllowed(rpcName)
+ logRPCPermission(rpcName: rpcName, isRPCAllowed: isRPCAllowed)
+ return isRPCAllowed
+ }
+
+ /// Checks if all the RPCs need to create menus are allowed right at this moment
+ ///
+ /// - Parameter manager: The SDL Manager
+ /// - Returns: The rpc names, the group permission status and the permission status for each rpc in the group
+ class func checkCurrentGroupPermissions(with manager: SDLManager, rpcNames: [String]) -> SDLPermissionGroupStatus {
+ let groupPermissionStatus = manager.permissionManager.groupStatus(ofRPCs: rpcNames)
+ let individualPermissionStatuses = manager.permissionManager.status(ofRPCs: rpcNames)
+ logRPCGroupPermissions(rpcNames: rpcNames, groupPermissionStatus: groupPermissionStatus, individualPermissionStatuses: individualPermissionStatuses)
+ return groupPermissionStatus
+ }
+
+ /// Sets up an observer for permissions changes to media template releated RPCs.
+ ///
+ /// - Parameters:
+ /// - manager: The SDL Manager
+ /// - groupType: The type of changes to get notified about
+ /// - Returns: A unique id assigned to observer. Use the id to unsubscribe to notifications
+ class func subscribeGroupPermissions(with manager: SDLManager, rpcNames: [String], groupType: SDLPermissionGroupType) -> UUID {
+ let permissionAllAllowedObserverId = manager.permissionManager.addObserver(forRPCs: rpcNames, groupType: groupType, withHandler: { (individualStatuses, groupStatus) in
+ self.logRPCGroupPermissions(rpcNames: rpcNames, groupPermissionStatus: groupStatus, individualPermissionStatuses: individualStatuses)
+ })
+
+ return permissionAllAllowedObserverId
+ }
+
+ /// Unsubscribe to notifications about permissions changes for a group of RPCs
+ ///
+ /// - Parameters:
+ /// - manager: The SDL Manager
+ /// - observerId: The unique identifier for a group of RPCs
+ class func unsubscribeGroupPermissions(with manager: SDLManager, observerId: UUID) {
+ manager.permissionManager.removeObserver(forIdentifier: observerId)
+ }
+}
+
+// MARK: - Debug Logging
+
+private extension RPCPermissionsManager {
+ /// Logs permissions for a single RPC
+ ///
+ /// - Parameters:
+ /// - rpcName: The name of the RPC
+ /// - isRPCAllowed: The permission status for the RPC
+ class func logRPCPermission(rpcName: String, isRPCAllowed: Bool) {
+ SDLLog.d("\(rpcName) RPC can be sent to SDL Core? \(isRPCAllowed ? "yes" : "no")")
+ }
+
+ /// Logs permissions for a group of RPCs
+ ///
+ /// - Parameters:
+ /// - rpcNames: The names of the RPCs
+ /// - groupPermissionStatus: The permission status for all RPCs in the group
+ /// - individualPermissionStatuses: The permission status for each of the RPCs in the group
+ class func logRPCGroupPermissions(rpcNames: [String], groupPermissionStatus: SDLPermissionGroupStatus, individualPermissionStatuses: [String:NSNumber]) {
+ SDLLog.d("The group status for \(rpcNames) has changed to: \(groupPermissionStatus)")
+ for (rpcName, rpcAllowed) in individualPermissionStatuses {
+ logRPCPermission(rpcName: rpcName as String, isRPCAllowed: rpcAllowed.boolValue)
+ }
+ }
+}
diff --git a/SmartDeviceLink_Example/Info.plist b/SmartDeviceLink_Example/SmartDeviceLink-Example-ObjC-Info.plist
index 87be1458a..95a3acdac 100644
--- a/SmartDeviceLink_Example/Info.plist
+++ b/SmartDeviceLink_Example/SmartDeviceLink-Example-ObjC-Info.plist
@@ -2,6 +2,10 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
+ <key>LSApplicationCategoryType</key>
+ <string></string>
+ <key>NSSpeechRecognitionUsageDescription</key>
+ <string>Requesting access to the speech recognition API</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
diff --git a/SmartDeviceLink_Example/SmartDeviceLink-Example-Swift-Bridging-Header.h b/SmartDeviceLink_Example/SmartDeviceLink-Example-Swift-Bridging-Header.h
new file mode 100644
index 000000000..70ca78854
--- /dev/null
+++ b/SmartDeviceLink_Example/SmartDeviceLink-Example-Swift-Bridging-Header.h
@@ -0,0 +1,5 @@
+//
+// Use this file to import your target's public headers that you would like to expose to Swift.
+//
+
+#import "AppConstants.h"
diff --git a/SmartDeviceLink_Example/VehicleDataManager.h b/SmartDeviceLink_Example/VehicleDataManager.h
new file mode 100644
index 000000000..65f6dd09d
--- /dev/null
+++ b/SmartDeviceLink_Example/VehicleDataManager.h
@@ -0,0 +1,33 @@
+//
+// VehicleDataManager.h
+// SmartDeviceLink-Example-ObjC
+//
+// Created by Nicole on 4/23/18.
+// Copyright © 2018 smartdevicelink. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@class SDLManager;
+
+NS_ASSUME_NONNULL_BEGIN
+
+typedef void(^RefreshUIHandler)(void);
+
+@interface VehicleDataManager : NSObject
+
+@property (copy, nonatomic, readonly) NSString *vehicleOdometerData;
+
+- (instancetype)init NS_UNAVAILABLE;
+- (instancetype)initWithManager:(SDLManager *)manager refreshUIHandler:(RefreshUIHandler)refreshUIHandler;
+
+- (void)subscribeToVehicleOdometer;
+- (void)unsubscribeToVehicleOdometer;
+
++ (void)getVehicleSpeedWithManager:(SDLManager *)manager;
++ (void)checkPhoneCallCapabilityWithManager:(SDLManager *)manager phoneNumber:(NSString *)phoneNumber;
+
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink_Example/VehicleDataManager.m b/SmartDeviceLink_Example/VehicleDataManager.m
new file mode 100644
index 000000000..5615dfe52
--- /dev/null
+++ b/SmartDeviceLink_Example/VehicleDataManager.m
@@ -0,0 +1,216 @@
+//
+// VehicleDataManager.m
+// SmartDeviceLink-Example-ObjC
+//
+// Created by Nicole on 4/23/18.
+// Copyright © 2018 smartdevicelink. All rights reserved.
+//
+
+#import "AlertManager.h"
+#import "VehicleDataManager.h"
+#import "AppConstants.h"
+#import "SmartDeviceLink.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+
+@interface VehicleDataManager ()
+
+@property (strong, nonatomic) SDLManager *sdlManager;
+@property (copy, nonatomic, readwrite) NSString *vehicleOdometerData;
+@property (copy, nonatomic, nullable) RefreshUIHandler refreshUIHandler;
+
+@end
+
+@implementation VehicleDataManager
+
+#pragma mark - Lifecycle
+
+- (instancetype)initWithManager:(SDLManager *)manager refreshUIHandler:(RefreshUIHandler)refreshUIHandler {
+ self = [super init];
+ if (!self) {
+ return nil;
+ }
+
+ _sdlManager = manager;
+ _refreshUIHandler = refreshUIHandler;
+ _vehicleOdometerData = @"";
+
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(vehicleDataNotification:) name:SDLDidReceiveVehicleDataNotification object:nil];
+ [self sdlex_resetOdometer];
+
+ return self;
+}
+
+
+#pragma mark - Subscribe Vehicle Data
+
+/**
+ * Subscribes to odometer data. You must subscribe to a notification with name `SDLDidReceiveVehicleData` to get the new data when the odometer data changes.
+ */
+- (void)subscribeToVehicleOdometer {
+ SDLLogD(@"Subscribing to odometer vehicle data");
+ SDLSubscribeVehicleData *subscribeToVehicleOdometer = [[SDLSubscribeVehicleData alloc] init];
+ subscribeToVehicleOdometer.odometer = @YES;
+ [self.sdlManager sendRequest:subscribeToVehicleOdometer withResponseHandler:^(__kindof SDLRPCRequest * _Nullable request, __kindof SDLRPCResponse * _Nullable response, NSError * _Nullable error) {
+ if (error || ![response isKindOfClass:SDLSubscribeVehicleDataResponse.class]) {
+ SDLLogE(@"Error sending Get Vehicle Data RPC: %@", error);
+ }
+
+ SDLGetVehicleDataResponse* getVehicleDataResponse = (SDLGetVehicleDataResponse *)response;
+ SDLResult resultCode = getVehicleDataResponse.resultCode;
+
+ NSMutableString *message = [NSMutableString stringWithFormat:@"%@: ", VehicleDataOdometerName];
+ if ([resultCode isEqualToEnum:SDLResultSuccess]) {
+ SDLLogD(@"Subscribed to vehicle odometer data");
+ [message appendString:@"Subscribed"];
+ } else if ([resultCode isEqualToEnum:SDLResultDisallowed]) {
+ SDLLogD(@"Access to vehicle data disallowed");
+ [message appendString:@"Disallowed"];
+ } else if ([resultCode isEqualToEnum:SDLResultUserDisallowed]) {
+ SDLLogD(@"Vehicle user disabled access to vehicle data");
+ [message appendString:@"Disabled"];
+ } else if ([resultCode isEqualToEnum:SDLResultIgnored]) {
+ SDLLogD(@"Already subscribed to odometer data");
+ [message appendString:@"Subscribed"];
+ } else if ([resultCode isEqualToEnum:SDLResultDataNotAvailable]) {
+ SDLLogD(@"You have permission to access to vehicle data, but the vehicle you are connected to did not provide any data");
+ [message appendString:@"Unknown"];
+ } else {
+ SDLLogE(@"Unknown reason for failure to get vehicle data: %@", error != nil ? error.localizedDescription : @"no error message");
+ [message appendString:@"Unsubscribed"];
+ }
+
+ self.vehicleOdometerData = message;
+
+ if (!self.refreshUIHandler) { return; }
+ self.refreshUIHandler();
+ }];
+}
+
+/**
+ * Unsubscribes to vehicle odometer data.
+ */
+- (void)unsubscribeToVehicleOdometer {
+ SDLUnsubscribeVehicleData *unsubscribeToVehicleOdometer = [[SDLUnsubscribeVehicleData alloc] init];
+ unsubscribeToVehicleOdometer.odometer = @YES;
+ [self.sdlManager sendRequest:unsubscribeToVehicleOdometer withResponseHandler:^(__kindof SDLRPCRequest * _Nullable request, __kindof SDLRPCResponse * _Nullable response, NSError * _Nullable error) {
+ if (!response.success.boolValue) { return; }
+ [self sdlex_resetOdometer];
+ }];
+}
+
+/**
+ * Notification containing the updated vehicle data.
+ *
+ * @param notification A SDLOnVehicleData notification
+ */
+- (void)vehicleDataNotification:(SDLRPCNotificationNotification *)notification {
+ if (![notification.notification isKindOfClass:SDLOnVehicleData.class]) {
+ return;
+ }
+
+ SDLOnVehicleData *onVehicleData = (SDLOnVehicleData *)notification.notification;
+ self.vehicleOdometerData = [NSString stringWithFormat:@"%@: %@ kph", VehicleDataOdometerName, onVehicleData.odometer];
+
+ if (!self.refreshUIHandler) { return; }
+ self.refreshUIHandler();
+}
+
+/**
+ * Resets the odometer data
+ */
+- (void)sdlex_resetOdometer {
+ self.vehicleOdometerData = [NSString stringWithFormat:@"%@: Unsubscribed", VehicleDataOdometerName];
+}
+
+#pragma mark - Get Vehicle Data
+
+/**
+ * Retreives the current vehicle speed
+ *
+ * @param manager The SDL manager
+ */
++ (void)getVehicleSpeedWithManager:(SDLManager *)manager {
+ SDLLogD(@"Checking if app has permission to access vehicle data...");
+ if (![manager.permissionManager isRPCAllowed:@"GetVehicleData"]) {
+ [manager sendRequest:[AlertManager alertWithMessageAndCloseButton:@"This app does not have the required permissions to access vehicle data" textField2:nil]];
+ return;
+ }
+
+ SDLLogD(@"App has permission to access vehicle data. Requesting vehicle speed data...");
+ SDLGetVehicleData *getVehicleSpeed = [[SDLGetVehicleData alloc] init];
+ getVehicleSpeed.speed = @YES;
+ [manager sendRequest:getVehicleSpeed withResponseHandler:^(__kindof SDLRPCRequest * _Nullable request, __kindof SDLRPCResponse * _Nullable response, NSError * _Nullable error) {
+ if (error || ![response isKindOfClass:SDLGetVehicleDataResponse.class]) {
+ [manager sendRequest:[AlertManager alertWithMessageAndCloseButton:@"Something went wrong while getting vehicle speed" textField2:nil]];
+ return;
+ }
+
+ SDLGetVehicleDataResponse* getVehicleDataResponse = (SDLGetVehicleDataResponse *)response;
+ SDLResult resultCode = getVehicleDataResponse.resultCode;
+
+ NSMutableString *alertMessage = [NSMutableString stringWithFormat:@"%@: ", VehicleDataSpeedName];
+ if ([resultCode isEqualToEnum:SDLResultRejected]) {
+ SDLLogD(@"The request for vehicle speed was rejected");
+ [alertMessage appendString:@"Rejected"];
+ } else if ([resultCode isEqualToEnum:SDLResultDisallowed]) {
+ SDLLogD(@"This app does not have the required permissions to access vehicle data.");
+ [alertMessage appendString:@"Disallowed"];
+ } else if ([resultCode isEqualToEnum:SDLResultSuccess]) {
+ NSNumber *speed = getVehicleDataResponse.speed;
+ if (speed) {
+ SDLLogD(@"Request for vehicle speed successful: %f", speed.floatValue);
+ [alertMessage appendString:[NSString stringWithFormat:@"%f kph", speed.floatValue]];
+ } else {
+ SDLLogD(@"Request for vehicle speed successful but no data returned.");
+ [alertMessage appendString:@"Unknown"];
+ }
+ }
+
+ [manager sendRequest:[AlertManager alertWithMessageAndCloseButton:alertMessage textField2:nil]];
+ }];
+}
+
+#pragma mark - Phone Calls
+
+/**
+ * Checks if the head unit has the ability and/or permissions to make a phone call. If it does, the phone number is dialed.
+ *
+ * @param manager The SDL manager
+ * @param phoneNumber A phone number to dial
+ */
++ (void)checkPhoneCallCapabilityWithManager:(SDLManager *)manager phoneNumber:(NSString *)phoneNumber {
+ SDLLogD(@"Checking phone call capability");
+ [manager.systemCapabilityManager updateCapabilityType:SDLSystemCapabilityTypePhoneCall completionHandler:^(NSError * _Nullable error, SDLSystemCapabilityManager * _Nonnull systemCapabilityManager) {
+ if (!systemCapabilityManager.phoneCapability) {
+ [manager sendRequest:[AlertManager alertWithMessageAndCloseButton:@"The head unit does not support the phone call capability" textField2:nil]];
+ return;
+ }
+
+ if (systemCapabilityManager.phoneCapability.dialNumberEnabled.boolValue) {
+ SDLLogD(@"Dialing phone number %@", phoneNumber);
+ [self sdlex_dialPhoneNumber:phoneNumber manager:manager];
+ } else {
+ [manager sendRequest:[AlertManager alertWithMessageAndCloseButton:@"The dial number feature is unavailable for this head unit" textField2:nil]];
+ }
+ }];
+}
+
+/**
+ * Dials a phone number.
+ *
+ * @param phoneNumber A phone number to dial
+ * @param manager The SDL manager
+ */
++ (void)sdlex_dialPhoneNumber:(NSString *)phoneNumber manager:(SDLManager *)manager {
+ SDLDialNumber *dialNumber = [[SDLDialNumber alloc] initWithNumber:phoneNumber];
+ [manager sendRequest:dialNumber withResponseHandler:^(__kindof SDLRPCRequest * _Nullable request, __kindof SDLRPCResponse * _Nullable response, NSError * _Nullable error) {
+ if (!response.resultCode) { return; }
+ SDLLogD(@"Sent dial number request: %@", response.resultCode == SDLResultSuccess ? @"successfully" : @"unsuccessfully");
+ }];
+}
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink_Example/VehicleDataManager.swift b/SmartDeviceLink_Example/VehicleDataManager.swift
new file mode 100644
index 000000000..1d8c5a52a
--- /dev/null
+++ b/SmartDeviceLink_Example/VehicleDataManager.swift
@@ -0,0 +1,184 @@
+//
+// VehicleDataManager.swift
+// SmartDeviceLink
+//
+// Created by Nicole on 4/13/18.
+// Copyright © 2018 smartdevicelink. All rights reserved.
+//
+
+import Foundation
+import SmartDeviceLink
+import SmartDeviceLinkSwift
+
+class VehicleDataManager: NSObject {
+ fileprivate let sdlManager: SDLManager!
+ fileprivate var refreshUIHandler: RefreshUIHandler?
+ public fileprivate(set) var vehicleOdometerData: String
+
+ init(sdlManager: SDLManager, refreshUIHandler: RefreshUIHandler? = nil) {
+ self.sdlManager = sdlManager
+ self.refreshUIHandler = refreshUIHandler
+ self.vehicleOdometerData = ""
+ super.init()
+
+ resetOdometer()
+ NotificationCenter.default.addObserver(self, selector: #selector(vehicleDataNotification(_:)), name: .SDLDidReceiveVehicleData, object: nil)
+ }
+}
+
+// MARK: - Subscribe Vehicle Data
+
+extension VehicleDataManager {
+ /// Subscribes to odometer data. You must subscribe to a notification with name `SDLDidReceiveVehicleData` to get the new data when the odometer data changes.
+ func subscribeToVehicleOdometer() {
+ let subscribeToVehicleOdometer = SDLSubscribeVehicleData()
+ subscribeToVehicleOdometer.odometer = true
+ sdlManager.send(request: subscribeToVehicleOdometer) { [unowned self] (request, response, error) in
+ guard let result = response?.resultCode else { return }
+
+ if error != nil {
+ SDLLog.e("Error sending Get Vehicle Data RPC: \(error!.localizedDescription)")
+ }
+
+ var message = "\(VehicleDataOdometerName): "
+ switch result {
+ case .success:
+ SDLLog.d("Subscribed to vehicle odometer data")
+ message += "Subscribed"
+ case .disallowed:
+ SDLLog.d("Access to vehicle data disallowed")
+ message += "Disallowed"
+ case .userDisallowed:
+ SDLLog.d("Vehicle user disabled access to vehicle data")
+ message += "Disabled"
+ case .ignored:
+ SDLLog.d("Already subscribed to odometer data")
+ message += "Subscribed"
+ case .dataNotAvailable:
+ SDLLog.d("You have permission to access to vehicle data, but the vehicle you are connected to did not provide any data")
+ message += "Unknown"
+ default:
+ SDLLog.e("Unknown reason for failure to get vehicle data: \(error != nil ? error!.localizedDescription : "no error message")")
+ message += "Unsubscribed"
+ return
+ }
+ self.vehicleOdometerData = message
+
+ guard let handler = self.refreshUIHandler else { return }
+ handler()
+ }
+ }
+
+ /// Unsubscribes to vehicle odometer data.
+ func unsubscribeToVehicleOdometer() {
+ let unsubscribeToVehicleOdometer = SDLUnsubscribeVehicleData()
+ unsubscribeToVehicleOdometer.odometer = true
+ sdlManager.send(request: unsubscribeToVehicleOdometer) { (request, response, error) in
+ guard let response = response, response.resultCode == .success else { return }
+ self.resetOdometer()
+ }
+ }
+
+ /// Notification containing the updated vehicle data.
+ ///
+ /// - Parameter notification: A SDLOnVehicleData notification
+ func vehicleDataNotification(_ notification: SDLRPCNotificationNotification) {
+ guard let handler = refreshUIHandler, let onVehicleData = notification.notification as? SDLOnVehicleData, let odometer = onVehicleData.odometer else {
+ return
+ }
+
+ vehicleOdometerData = "\(VehicleDataOdometerName): \(odometer) km"
+ handler()
+ }
+
+ /// Resets the odometer data
+ fileprivate func resetOdometer() {
+ vehicleOdometerData = "\(VehicleDataOdometerName): Unsubscribed"
+ }
+}
+
+// MARK: - Get Vehicle Data
+
+extension VehicleDataManager {
+ /// Retreives the current vehicle speed
+ ///
+ /// - Parameter manager: The SDL manager
+ class func getVehicleSpeed(with manager: SDLManager) {
+ SDLLog.d("Checking if app has permission to access vehicle data...")
+ guard manager.permissionManager.isRPCAllowed("GetVehicleData") else {
+ let alert = AlertManager.alertWithMessageAndCloseButton("This app does not have the required permissions to access vehicle data")
+ manager.send(request: alert)
+ return
+ }
+
+ SDLLog.d("App has permission to access vehicle data. Requesting vehicle speed data...")
+ let getVehicleSpeed = SDLGetVehicleData()
+ getVehicleSpeed.speed = true
+ manager.send(request: getVehicleSpeed) { (request, response, error) in
+ guard let response = response, error == nil else {
+ let alert = AlertManager.alertWithMessageAndCloseButton("Something went wrong while getting vehicle speed")
+ manager.send(request: alert)
+ return
+ }
+
+ var alertMessage = "\(VehicleDataSpeedName): "
+ switch response.resultCode {
+ case .rejected:
+ SDLLog.d("The request for vehicle speed was rejected")
+ alertMessage += "Rejected"
+ case .disallowed:
+ SDLLog.d("This app does not have the required permissions to access vehicle data")
+ alertMessage += "Disallowed"
+ case .success:
+ if let vehicleData = response as? SDLGetVehicleDataResponse, let speed = vehicleData.speed {
+ SDLLog.d("Request for vehicle speed successful: \(speed)")
+ alertMessage += "\(speed) kph"
+ } else {
+ SDLLog.e("Request for vehicle speed successful but no data returned")
+ alertMessage += "Unknown"
+ }
+ default: break
+ }
+
+ let alert = AlertManager.alertWithMessageAndCloseButton(alertMessage)
+ manager.send(request: alert)
+ }
+ }
+}
+
+// MARK: - Phone Calls
+
+extension VehicleDataManager {
+ /// Checks if the head unit has the ability and/or permissions to make a phone call. If it does, the phone number is dialed.
+ ///
+ /// - Parameter manager: The SDL manager
+ /// - phoneNumber: A phone number to dial
+ class func checkPhoneCallCapability(manager: SDLManager, phoneNumber: String) {
+ SDLLog.d("Checking phone call capability")
+ manager.systemCapabilityManager.updateCapabilityType(.phoneCall, completionHandler: { (error, systemCapabilityManager) in
+ guard let phoneCapability = systemCapabilityManager.phoneCapability else {
+ manager.send(AlertManager.alertWithMessageAndCloseButton("The head unit does not support the phone call capability"))
+ return
+ }
+ if phoneCapability.dialNumberEnabled?.boolValue ?? false {
+ SDLLog.d("Dialing phone number \(phoneNumber)...")
+ dialPhoneNumber(phoneNumber, manager: manager)
+ } else {
+ manager.send(AlertManager.alertWithMessageAndCloseButton("A phone call can not be made"))
+ }
+ })
+ }
+
+ /// Dials a phone number.
+ ///
+ /// - Parameters:
+ /// - phoneNumber: A phone number to dial
+ /// - manager: The SDL manager
+ private class func dialPhoneNumber(_ phoneNumber: String, manager: SDLManager) {
+ let dialNumber = SDLDialNumber(number: phoneNumber)
+ manager.send(request: dialNumber) { (requst, response, error) in
+ guard let success = response?.resultCode else { return }
+ SDLLog.d("Sent dial number request: \(success == .success ? "successfully" : "unsuccessfully").")
+ }
+ }
+}