diff options
author | Joey Grover <joeygrover@gmail.com> | 2017-10-04 15:45:42 -0400 |
---|---|---|
committer | Joey Grover <joeygrover@gmail.com> | 2017-10-04 15:45:42 -0400 |
commit | 8d743df8b19898b34a7c4cbe98971e4ad830b4c3 (patch) | |
tree | c685c7e53890b670f3f68bac64f923297a408c75 | |
parent | f796e725063b539c9ab1563d47061fa6de0d51a2 (diff) | |
parent | bf2f2b405ca10e777832b32eadfe14ed21d6a74d (diff) | |
download | sdl_android-8d743df8b19898b34a7c4cbe98971e4ad830b4c3.tar.gz |
Merge branch 'develop' of https://github.com/smartdevicelink/sdl_android into feature/issue_469_update
# Conflicts:
# sdl_android/src/main/java/com/smartdevicelink/proxy/SdlProxyBase.java
99 files changed, 9547 insertions, 842 deletions
diff --git a/.travis.yml b/.travis.yml index 5df5d6198..fb7fc4dbe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,19 +5,20 @@ android: components: # use the latest revision of Android SDK Tools - tools - - platform-tools - tools + - platform-tools - ndk-bundle # The BuildTools version used by your project - - build-tools-25.0.2 + - build-tools-26.0.1 # The SDK version used to compile your project - - android-22 + - android-26 + - android-22 #For emulator # Specify at least one system image, # if you need to run emulator(s) during your tests - sys-img-armeabi-v7a-android-22 - # - sys-img-x86-android-17 + # - sys-img-x86-android-26 # Android Support Repos - extra-android-m2repository diff --git a/sdl_android/build.gradle b/sdl_android/build.gradle index ad04cab31..13c53c692 100644 --- a/sdl_android/build.gradle +++ b/sdl_android/build.gradle @@ -1,7 +1,7 @@ apply plugin: 'com.android.library' android { - compileSdkVersion 22 + compileSdkVersion 26 buildToolsVersion "25.0.2" defaultConfig { minSdkVersion 8 diff --git a/sdl_android/src/androidTest/assets/json/ButtonPress.json b/sdl_android/src/androidTest/assets/json/ButtonPress.json new file mode 100644 index 000000000..e74e857be --- /dev/null +++ b/sdl_android/src/androidTest/assets/json/ButtonPress.json @@ -0,0 +1,15 @@ +{ + "request":{ + "name":"ButtonPress", + "correlationID":215, + "parameters":{ + "buttonName":"OK", + "buttonPressMode":"LONG", + "moduleType":"CLIMATE" + } + }, + "response":{ + "name":"ButtonPressResponse", + "correlationID":216 + } +}
\ No newline at end of file diff --git a/sdl_android/src/androidTest/assets/json/GetInteriorVehicleData.json b/sdl_android/src/androidTest/assets/json/GetInteriorVehicleData.json new file mode 100644 index 000000000..7000d2918 --- /dev/null +++ b/sdl_android/src/androidTest/assets/json/GetInteriorVehicleData.json @@ -0,0 +1,38 @@ +{ + "request":{ + "name":"GetInteriorVehicleData", + "correlationID":101, + "parameters":{ + "subscribe":true, + "moduleType":"CLIMATE" + } + }, + "response":{ + "name":"GetInteriorVehicleDataResponse", + "correlationID":102, + "parameters":{ + "isSubscribed":true, + "moduleData":{ + "moduleType":"CLIMATE", + "climateControlData":{ + "circulateAirEnable":true, + "ventilationMode":"UPPER", + "acEnable":true, + "currentTemperature":{ + "unit":"CELSIUS", + "value":100.0 + }, + "acMaxEnable":true, + "desiredTemperature":{ + "unit":"CELSIUS", + "value":100.0 + }, + "dualModeEnable":true, + "autoModeEnable":true, + "fanSpeed":100, + "defrostZone":"FRONT" + } + } + } + } +}
\ No newline at end of file diff --git a/sdl_android/src/androidTest/assets/json/SetInteriorVehicleData.json b/sdl_android/src/androidTest/assets/json/SetInteriorVehicleData.json new file mode 100644 index 000000000..9bcdc01dc --- /dev/null +++ b/sdl_android/src/androidTest/assets/json/SetInteriorVehicleData.json @@ -0,0 +1,56 @@ +{ + "request":{ + "name":"SetInteriorVehicleData", + "correlationID":126, + "parameters":{ + "moduleData":{ + "moduleType":"CLIMATE", + "climateControlData":{ + "circulateAirEnable":true, + "ventilationMode":"BOTH", + "acEnable":true, + "currentTemperature":{ + "unit":"CELSIUS", + "value":100.0 + }, + "acMaxEnable":true, + "desiredTemperature":{ + "unit":"CELSIUS", + "value":100.0 + }, + "dualModeEnable":true, + "autoModeEnable":true, + "fanSpeed":100, + "defrostZone":"ALL" + } + } + } + }, + "response":{ + "name":"SetInteriorVehicleDataResponse", + "correlationID":127, + "parameters":{ + "moduleData":{ + "moduleType":"CLIMATE", + "climateControlData":{ + "circulateAirEnable":true, + "ventilationMode":"BOTH", + "acEnable":true, + "currentTemperature":{ + "unit":"CELSIUS", + "value":100.0 + }, + "acMaxEnable":true, + "desiredTemperature":{ + "unit":"CELSIUS", + "value":100.0 + }, + "dualModeEnable":true, + "autoModeEnable":true, + "fanSpeed":100, + "defrostZone":"ALL" + } + } + } + } +}
\ No newline at end of file diff --git a/sdl_android/src/androidTest/java/com/smartdevicelink/protocol/WiProProtocolTests.java b/sdl_android/src/androidTest/java/com/smartdevicelink/protocol/WiProProtocolTests.java index f8cae95f4..1055f5deb 100644 --- a/sdl_android/src/androidTest/java/com/smartdevicelink/protocol/WiProProtocolTests.java +++ b/sdl_android/src/androidTest/java/com/smartdevicelink/protocol/WiProProtocolTests.java @@ -16,6 +16,7 @@ import junit.framework.Assert; import java.io.ByteArrayOutputStream; import java.lang.reflect.Method; +import java.util.List; /** * This is a unit test class for the SmartDeviceLink library project class : @@ -37,7 +38,7 @@ public class WiProProtocolTests extends AndroidTestCase { @Override public void onProtocolSessionStarted(SessionType sessionType,byte sessionID, byte version, String correlationID, int hashID,boolean isEncrypted){} @Override - public void onProtocolSessionNACKed(SessionType sessionType,byte sessionID, byte version, String correlationID) {} + public void onProtocolSessionNACKed(SessionType sessionType,byte sessionID, byte version, String correlationID, List<String> rejectedParams) {} @Override public void onProtocolSessionEnded(SessionType sessionType,byte sessionID, String correlationID) {} @Override @@ -76,7 +77,7 @@ public class WiProProtocolTests extends AndroidTestCase { @Override public void onProtocolSessionStarted(SessionType sessionType,byte sessionID, byte version, String correlationID, int hashID,boolean isEncrypted){} @Override - public void onProtocolSessionNACKed(SessionType sessionType,byte sessionID, byte version, String correlationID) {} + public void onProtocolSessionNACKed(SessionType sessionType,byte sessionID, byte version, String correlationID, List<String> rejectedParams) {} @Override public void onProtocolSessionEnded(SessionType sessionType,byte sessionID, String correlationID) {} @Override diff --git a/sdl_android/src/androidTest/java/com/smartdevicelink/test/Test.java b/sdl_android/src/androidTest/java/com/smartdevicelink/test/Test.java index 782692d69..46f4e89be 100644 --- a/sdl_android/src/androidTest/java/com/smartdevicelink/test/Test.java +++ b/sdl_android/src/androidTest/java/com/smartdevicelink/test/Test.java @@ -6,6 +6,8 @@ import com.smartdevicelink.proxy.TTSChunkFactory; import com.smartdevicelink.proxy.rpc.AudioPassThruCapabilities; import com.smartdevicelink.proxy.rpc.ButtonCapabilities; import com.smartdevicelink.proxy.rpc.Choice; +import com.smartdevicelink.proxy.rpc.ClimateControlCapabilities; +import com.smartdevicelink.proxy.rpc.ClimateControlData; import com.smartdevicelink.proxy.rpc.Coordinate; import com.smartdevicelink.proxy.rpc.DIDResult; import com.smartdevicelink.proxy.rpc.DeviceInfo; @@ -19,11 +21,18 @@ import com.smartdevicelink.proxy.rpc.ImageResolution; import com.smartdevicelink.proxy.rpc.KeyboardProperties; import com.smartdevicelink.proxy.rpc.LocationDetails; import com.smartdevicelink.proxy.rpc.MenuParams; +import com.smartdevicelink.proxy.rpc.ModuleData; +import com.smartdevicelink.proxy.rpc.NavigationCapability; import com.smartdevicelink.proxy.rpc.MetadataTags; import com.smartdevicelink.proxy.rpc.OasisAddress; import com.smartdevicelink.proxy.rpc.ParameterPermissions; import com.smartdevicelink.proxy.rpc.PermissionItem; +import com.smartdevicelink.proxy.rpc.PhoneCapability; import com.smartdevicelink.proxy.rpc.PresetBankCapabilities; +import com.smartdevicelink.proxy.rpc.RadioControlCapabilities; +import com.smartdevicelink.proxy.rpc.RadioControlData; +import com.smartdevicelink.proxy.rpc.RdsData; +import com.smartdevicelink.proxy.rpc.RemoteControlCapabilities; import com.smartdevicelink.proxy.rpc.Rectangle; import com.smartdevicelink.proxy.rpc.ScreenParams; import com.smartdevicelink.proxy.rpc.SdlMsgVersion; @@ -32,6 +41,7 @@ import com.smartdevicelink.proxy.rpc.SoftButtonCapabilities; import com.smartdevicelink.proxy.rpc.StartTime; import com.smartdevicelink.proxy.rpc.SystemCapability; import com.smartdevicelink.proxy.rpc.TTSChunk; +import com.smartdevicelink.proxy.rpc.Temperature; import com.smartdevicelink.proxy.rpc.TextField; import com.smartdevicelink.proxy.rpc.TouchCoord; import com.smartdevicelink.proxy.rpc.TouchEvent; @@ -55,6 +65,7 @@ import com.smartdevicelink.proxy.rpc.enums.CarModeStatus; import com.smartdevicelink.proxy.rpc.enums.CharacterSet; import com.smartdevicelink.proxy.rpc.enums.CompassDirection; import com.smartdevicelink.proxy.rpc.enums.ComponentVolumeStatus; +import com.smartdevicelink.proxy.rpc.enums.DefrostZone; import com.smartdevicelink.proxy.rpc.enums.DeviceLevelStatus; import com.smartdevicelink.proxy.rpc.enums.Dimension; import com.smartdevicelink.proxy.rpc.enums.DisplayType; @@ -77,10 +88,13 @@ import com.smartdevicelink.proxy.rpc.enums.Language; import com.smartdevicelink.proxy.rpc.enums.LayoutMode; import com.smartdevicelink.proxy.rpc.enums.LockScreenStatus; import com.smartdevicelink.proxy.rpc.enums.MediaClockFormat; +import com.smartdevicelink.proxy.rpc.enums.ModuleType; import com.smartdevicelink.proxy.rpc.enums.PowerModeQualificationStatus; import com.smartdevicelink.proxy.rpc.enums.PowerModeStatus; import com.smartdevicelink.proxy.rpc.enums.PrerecordedSpeech; import com.smartdevicelink.proxy.rpc.enums.PrimaryAudioSource; +import com.smartdevicelink.proxy.rpc.enums.RadioBand; +import com.smartdevicelink.proxy.rpc.enums.RadioState; import com.smartdevicelink.proxy.rpc.enums.RequestType; import com.smartdevicelink.proxy.rpc.enums.SamplingRate; import com.smartdevicelink.proxy.rpc.enums.SoftButtonType; @@ -89,6 +103,7 @@ import com.smartdevicelink.proxy.rpc.enums.SystemAction; import com.smartdevicelink.proxy.rpc.enums.SystemCapabilityType; import com.smartdevicelink.proxy.rpc.enums.SystemContext; import com.smartdevicelink.proxy.rpc.enums.TBTState; +import com.smartdevicelink.proxy.rpc.enums.TemperatureUnit; import com.smartdevicelink.proxy.rpc.enums.TextAlignment; import com.smartdevicelink.proxy.rpc.enums.TextFieldName; import com.smartdevicelink.proxy.rpc.enums.MetadataType; @@ -100,6 +115,7 @@ import com.smartdevicelink.proxy.rpc.enums.VehicleDataNotificationStatus; import com.smartdevicelink.proxy.rpc.enums.VehicleDataResultCode; import com.smartdevicelink.proxy.rpc.enums.VehicleDataStatus; import com.smartdevicelink.proxy.rpc.enums.VehicleDataType; +import com.smartdevicelink.proxy.rpc.enums.VentilationMode; import com.smartdevicelink.proxy.rpc.enums.VideoStreamingCodec; import com.smartdevicelink.proxy.rpc.enums.VideoStreamingProtocol; import com.smartdevicelink.proxy.rpc.enums.VrCapabilities; @@ -215,13 +231,30 @@ public class Test { public static final VehicleDataNotificationStatus GENERAL_VEHICLEDATANOTIFICATIONSTATUS = VehicleDataNotificationStatus.NORMAL; public static final AppInterfaceUnregisteredReason GENERAL_APPINTERFACEUNREGISTEREDREASON = AppInterfaceUnregisteredReason.BLUETOOTH_OFF; public static final SystemCapabilityType GENERAL_SYSTEMCAPABILITYTYPE = SystemCapabilityType.NAVIGATION; + public static final NavigationCapability GENERAL_NAVIGATIONCAPABILITY = new NavigationCapability(); + public static final PhoneCapability GENERAL_PHONECAPABILITY = new PhoneCapability(); + public static final RemoteControlCapabilities GENERAL_REMOTECONTROLCAPABILITIES = new RemoteControlCapabilities(); public static final SystemCapability GENERAL_SYSTEMCAPABILITY = new SystemCapability(); public static final VideoStreamingProtocol GENERAL_VIDEOSTREAMINGPROTOCOL = VideoStreamingProtocol.RAW; public static final VideoStreamingCodec GENERAL_VIDEOSTREAMINGCODEC = VideoStreamingCodec.H264; public static final VideoStreamingCapability GENERAL_VIDEOSTREAMINGCAPABILITY = new VideoStreamingCapability(); public static final VideoStreamingFormat GENERAL_VIDEOSTREAMINGFORMAT = new VideoStreamingFormat(); + + public static final ModuleType GENERAL_MODULETYPE = ModuleType.CLIMATE; + public static final Temperature GENERAL_TEMPERATURE = new Temperature(); + public static final TemperatureUnit GENERAL_TEMPERATUREUNIT = TemperatureUnit.CELSIUS; + public static final DefrostZone GENERAL_DEFROSTZONE = DefrostZone.ALL; + public static final VentilationMode GENERAL_VENTILATIONMODE = VentilationMode.BOTH; + public static final RadioBand GENERAL_RADIOBAND = RadioBand.AM; + public static final ClimateControlData GENERAL_CLIMATECONTROLDATA = new ClimateControlData(); + public static final RdsData GENERAL_RDSDATA = new RdsData(); + public static final RadioState GENERAL_RADIOSTATE = RadioState.ACQUIRED; + public static final RadioControlData GENERAL_RADIOCONTROLDATA = new RadioControlData(); + public static final ModuleData GENERAL_MODULEDATA = new ModuleData(); + public static final ClimateControlCapabilities GENERAL_CLIMATECONTROLCAPABILITIES = new ClimateControlCapabilities(); + public static final RadioControlCapabilities GENERAL_RADIOCONTROLCAPABILITIES = new RadioControlCapabilities(); + public static final HMICapabilities GENERAL_HMICAPABILITIES = new HMICapabilities(); - public static final MetadataTags GENERAL_METADATASTRUCT = new MetadataTags(); public static final Rectangle GENERAL_RECTANGLE = new Rectangle(); @@ -255,7 +288,11 @@ public class Test { public static final List<SoftButtonCapabilities> GENERAL_SOFTBUTTONCAPABILITIES_LIST = new ArrayList<SoftButtonCapabilities>(1); public static final List<AudioPassThruCapabilities> GENERAL_AUDIOPASSTHRUCAPABILITIES_LIST = new ArrayList<AudioPassThruCapabilities>(1); public static final List<VideoStreamingFormat> GENERAL_VIDEOSTREAMINGFORMAT_LIST = new ArrayList<VideoStreamingFormat>(2); - + public static final List<DefrostZone> GENERAL_DEFROSTZONE_LIST = Arrays.asList(new DefrostZone[]{DefrostZone.FRONT, DefrostZone.REAR}); + public static final List<VentilationMode> GENERAL_VENTILATIONMODE_LIST = Arrays.asList(new VentilationMode[]{VentilationMode.LOWER, VentilationMode.UPPER}); + public static final List<ClimateControlCapabilities> GENERAL_CLIMATECONTROLCAPABILITIES_LIST = new ArrayList<ClimateControlCapabilities>(1); + public static final List<RadioControlCapabilities> GENERAL_RADIOCONTROLCAPABILITIES_LIST = new ArrayList<RadioControlCapabilities>(1); + public static final JSONArray JSON_TURNS = new JSONArray(); public static final JSONArray JSON_CHOICES = new JSONArray(); public static final JSONArray JSON_HMILEVELS = new JSONArray(); @@ -271,8 +308,9 @@ public class Test { public static final JSONArray JSON_BUTTONCAPABILITIES = new JSONArray(); public static final JSONArray JSON_SOFTBUTTONCAPABILITIES = new JSONArray(); public static final JSONArray JSON_AUDIOPASSTHRUCAPABILITIES = new JSONArray(); + public static final JSONArray JSON_RADIOCONTROLCAPABILITIES = new JSONArray(); + public static final JSONArray JSON_CLIMATECONTROLCAPABILITIES = new JSONArray(); public static final JSONArray JSON_TEXTFIELDTYPES = new JSONArray(); - public static final JSONObject JSON_TURN = new JSONObject(); public static final JSONObject JSON_IMAGE = new JSONObject(); public static final JSONObject JSON_CHOICE = new JSONObject(); @@ -296,15 +334,52 @@ public class Test { public static final JSONObject JSON_PARAMETERPERMISSIONS = new JSONObject(); public static final JSONObject JSON_PRESETBANKCAPABILITIES = new JSONObject(); public static final JSONObject JSON_TOUCHEVENTCAPABILITIES = new JSONObject(); - + static { GENERAL_TOUCHEVENTCAPABILITIES.setDoublePressAvailable(GENERAL_BOOLEAN); GENERAL_TOUCHEVENTCAPABILITIES.setMultiTouchAvailable(GENERAL_BOOLEAN); GENERAL_TOUCHEVENTCAPABILITIES.setPressAvailable(GENERAL_BOOLEAN); GENERAL_IMAGERESOLUTION.setResolutionHeight(GENERAL_INT); - GENERAL_IMAGERESOLUTION.setResolutionWidth(GENERAL_INT); - + GENERAL_IMAGERESOLUTION.setResolutionWidth(GENERAL_INT); + + GENERAL_TEMPERATURE.setUnit(GENERAL_TEMPERATUREUNIT); + GENERAL_TEMPERATURE.setValue(GENERAL_FLOAT); + + GENERAL_CLIMATECONTROLDATA.setFanSpeed(GENERAL_INT); + GENERAL_CLIMATECONTROLDATA.setCurrentTemperature(GENERAL_TEMPERATURE); + GENERAL_CLIMATECONTROLDATA.setDesiredTemperature(GENERAL_TEMPERATURE); + GENERAL_CLIMATECONTROLDATA.setAcEnable(GENERAL_BOOLEAN); + GENERAL_CLIMATECONTROLDATA.setCirculateAirEnable(GENERAL_BOOLEAN); + GENERAL_CLIMATECONTROLDATA.setAutoModeEnable(GENERAL_BOOLEAN); + GENERAL_CLIMATECONTROLDATA.setDualModeEnable(GENERAL_BOOLEAN); + GENERAL_CLIMATECONTROLDATA.setAcMaxEnable(GENERAL_BOOLEAN); + GENERAL_CLIMATECONTROLDATA.setDefrostZone(GENERAL_DEFROSTZONE); + GENERAL_CLIMATECONTROLDATA.setVentilationMode(GENERAL_VENTILATIONMODE); + + GENERAL_RDSDATA.setProgramService(GENERAL_STRING); + GENERAL_RDSDATA.setRadioText(GENERAL_STRING); + GENERAL_RDSDATA.setClockText(GENERAL_STRING); + GENERAL_RDSDATA.setProgramIdentification(GENERAL_STRING); + GENERAL_RDSDATA.setRegion(GENERAL_STRING); + GENERAL_RDSDATA.setTrafficProgram(GENERAL_BOOLEAN); + GENERAL_RDSDATA.setTrafficAnnouncement(GENERAL_BOOLEAN); + GENERAL_RDSDATA.setProgramType(GENERAL_INT); + + GENERAL_RADIOCONTROLDATA.setFrequencyInteger(GENERAL_INT); + GENERAL_RADIOCONTROLDATA.setFrequencyFraction(GENERAL_INT); + GENERAL_RADIOCONTROLDATA.setBand(GENERAL_RADIOBAND); + GENERAL_RADIOCONTROLDATA.setRdsData(GENERAL_RDSDATA); + GENERAL_RADIOCONTROLDATA.setAvailableHDs(GENERAL_INT); + GENERAL_RADIOCONTROLDATA.setHdChannel(GENERAL_INT); + GENERAL_RADIOCONTROLDATA.setSignalStrength(GENERAL_INT); + GENERAL_RADIOCONTROLDATA.setSignalChangeThreshold(GENERAL_INT); + GENERAL_RADIOCONTROLDATA.setRadioEnable(GENERAL_BOOLEAN); + GENERAL_RADIOCONTROLDATA.setState(GENERAL_RADIOSTATE); + + GENERAL_MODULEDATA.setModuleType(GENERAL_MODULETYPE); + GENERAL_MODULEDATA.setClimateControlData(GENERAL_CLIMATECONTROLDATA); + GENERAL_CHOICE.setMenuName(GENERAL_STRING); GENERAL_CHOICE.setSecondaryText(GENERAL_STRING); GENERAL_CHOICE.setTertiaryText(GENERAL_STRING); @@ -486,6 +561,11 @@ public class Test { GENERAL_SYSTEMCAPABILITY.setSystemCapabilityType(GENERAL_SYSTEMCAPABILITYTYPE); + GENERAL_NAVIGATIONCAPABILITY.setSendLocationEnabled(GENERAL_BOOLEAN); + GENERAL_NAVIGATIONCAPABILITY.setWayPointsEnabled(GENERAL_BOOLEAN); + + GENERAL_PHONECAPABILITY.setDialNumberEnabled(GENERAL_BOOLEAN); + GENERAL_VIDEOSTREAMINGFORMAT.setProtocol(GENERAL_VIDEOSTREAMINGPROTOCOL); GENERAL_VIDEOSTREAMINGFORMAT.setCodec(GENERAL_VIDEOSTREAMINGCODEC); @@ -496,6 +576,36 @@ public class Test { GENERAL_VIDEOSTREAMINGCAPABILITY.setPreferredResolution(GENERAL_IMAGERESOLUTION); GENERAL_VIDEOSTREAMINGCAPABILITY.setSupportedFormats(GENERAL_VIDEOSTREAMINGFORMAT_LIST); + GENERAL_CLIMATECONTROLCAPABILITIES.setModuleName(GENERAL_STRING); + GENERAL_CLIMATECONTROLCAPABILITIES.setFanSpeedAvailable(GENERAL_BOOLEAN); + GENERAL_CLIMATECONTROLCAPABILITIES.setDesiredTemperatureAvailable(GENERAL_BOOLEAN); + GENERAL_CLIMATECONTROLCAPABILITIES.setAcEnableAvailable(GENERAL_BOOLEAN); + GENERAL_CLIMATECONTROLCAPABILITIES.setAcMaxEnableAvailable(GENERAL_BOOLEAN); + GENERAL_CLIMATECONTROLCAPABILITIES.setCirculateAirEnableAvailable(GENERAL_BOOLEAN); + GENERAL_CLIMATECONTROLCAPABILITIES.setAutoModeEnableAvailable(GENERAL_BOOLEAN); + GENERAL_CLIMATECONTROLCAPABILITIES.setDualModeEnableAvailable(GENERAL_BOOLEAN); + GENERAL_CLIMATECONTROLCAPABILITIES.setDefrostZoneAvailable(GENERAL_BOOLEAN); + GENERAL_CLIMATECONTROLCAPABILITIES.setDefrostZone(GENERAL_DEFROSTZONE_LIST); + GENERAL_CLIMATECONTROLCAPABILITIES.setVentilationModeAvailable(GENERAL_BOOLEAN); + GENERAL_CLIMATECONTROLCAPABILITIES.setVentilationMode(GENERAL_VENTILATIONMODE_LIST); + GENERAL_CLIMATECONTROLCAPABILITIES_LIST.add(GENERAL_CLIMATECONTROLCAPABILITIES); + + GENERAL_RADIOCONTROLCAPABILITIES.setModuleName(GENERAL_STRING); + GENERAL_RADIOCONTROLCAPABILITIES.setRadioEnableAvailable(GENERAL_BOOLEAN); + GENERAL_RADIOCONTROLCAPABILITIES.setRadioBandAvailable(GENERAL_BOOLEAN); + GENERAL_RADIOCONTROLCAPABILITIES.setRadioFrequencyAvailable(GENERAL_BOOLEAN); + GENERAL_RADIOCONTROLCAPABILITIES.setHdChannelAvailable(GENERAL_BOOLEAN); + GENERAL_RADIOCONTROLCAPABILITIES.setRdsDataAvailable(GENERAL_BOOLEAN); + GENERAL_RADIOCONTROLCAPABILITIES.setAvailableHDsAvailable(GENERAL_BOOLEAN); + GENERAL_RADIOCONTROLCAPABILITIES.setStateAvailable(GENERAL_BOOLEAN); + GENERAL_RADIOCONTROLCAPABILITIES.setSignalStrengthAvailable(GENERAL_BOOLEAN); + GENERAL_RADIOCONTROLCAPABILITIES.setSignalChangeThresholdAvailable(GENERAL_BOOLEAN); + GENERAL_RADIOCONTROLCAPABILITIES_LIST.add(GENERAL_RADIOCONTROLCAPABILITIES); + + GENERAL_REMOTECONTROLCAPABILITIES.setButtonCapabilities(GENERAL_BUTTONCAPABILITIES_LIST); + GENERAL_REMOTECONTROLCAPABILITIES.setClimateControlCapabilities(GENERAL_CLIMATECONTROLCAPABILITIES_LIST); + GENERAL_REMOTECONTROLCAPABILITIES.setRadioControlCapabilities(GENERAL_RADIOCONTROLCAPABILITIES_LIST); + GENERAL_HMICAPABILITIES.setNavigationAvilable(GENERAL_BOOLEAN); GENERAL_HMICAPABILITIES.setVideoStreamingAvailable(GENERAL_BOOLEAN); GENERAL_HMICAPABILITIES.setPhoneCallAvilable(GENERAL_BOOLEAN); @@ -620,7 +730,35 @@ public class Test { jsonButton.put(ButtonCapabilities.KEY_UP_DOWN_AVAILABLE, GENERAL_BOOLEAN); jsonButton.put(ButtonCapabilities.KEY_NAME, ButtonName.SEEKRIGHT); JSON_BUTTONCAPABILITIES.put(jsonButton); - + + JSONObject jsonRadioControlCapabilities = new JSONObject(); + jsonRadioControlCapabilities.put(RadioControlCapabilities.KEY_MODULE_NAME, GENERAL_STRING); + jsonRadioControlCapabilities.put(RadioControlCapabilities.KEY_RADIO_ENABLE_AVAILABLE, GENERAL_BOOLEAN); + jsonRadioControlCapabilities.put(RadioControlCapabilities.KEY_RADIO_BAND_AVAILABLE, GENERAL_BOOLEAN); + jsonRadioControlCapabilities.put(RadioControlCapabilities.KEY_RADIO_FREQUENCY_AVAILABLE, GENERAL_BOOLEAN); + jsonRadioControlCapabilities.put(RadioControlCapabilities.KEY_HD_CHANNEL_AVAILABLE, GENERAL_BOOLEAN); + jsonRadioControlCapabilities.put(RadioControlCapabilities.KEY_RDS_DATA_AVAILABLE, GENERAL_BOOLEAN); + jsonRadioControlCapabilities.put(RadioControlCapabilities.KEY_AVAILABLE_HDS_AVAILABLE, GENERAL_BOOLEAN); + jsonRadioControlCapabilities.put(RadioControlCapabilities.KEY_STATE_AVAILABLE, GENERAL_BOOLEAN); + jsonRadioControlCapabilities.put(RadioControlCapabilities.KEY_SIGNAL_STRENGTH_AVAILABLE, GENERAL_BOOLEAN); + jsonRadioControlCapabilities.put(RadioControlCapabilities.KEY_SIGNAL_CHANGE_THRESHOLD_AVAILABLE, GENERAL_BOOLEAN); + JSON_RADIOCONTROLCAPABILITIES.put(jsonRadioControlCapabilities); + + JSONObject jsonClimateControlCapabilities = new JSONObject(); + jsonClimateControlCapabilities.put(ClimateControlCapabilities.KEY_MODULE_NAME, GENERAL_STRING); + jsonClimateControlCapabilities.put(ClimateControlCapabilities.KEY_FAN_SPEED_AVAILABLE, GENERAL_BOOLEAN); + jsonClimateControlCapabilities.put(ClimateControlCapabilities.KEY_DESIRED_TEMPERATURE_AVAILABLE, GENERAL_BOOLEAN); + jsonClimateControlCapabilities.put(ClimateControlCapabilities.KEY_AC_ENABLE_AVAILABLE, GENERAL_BOOLEAN); + jsonClimateControlCapabilities.put(ClimateControlCapabilities.KEY_AC_MAX_ENABLE_AVAILABLE, GENERAL_BOOLEAN); + jsonClimateControlCapabilities.put(ClimateControlCapabilities.KEY_CIRCULATE_AIR_ENABLE_AVAILABLE, GENERAL_BOOLEAN); + jsonClimateControlCapabilities.put(ClimateControlCapabilities.KEY_AUTO_MODE_ENABLE_AVAILABLE, GENERAL_BOOLEAN); + jsonClimateControlCapabilities.put(ClimateControlCapabilities.KEY_DUAL_MODE_ENABLE_AVAILABLE, GENERAL_BOOLEAN); + jsonClimateControlCapabilities.put(ClimateControlCapabilities.KEY_DEFROST_ZONE_AVAILABLE, GENERAL_BOOLEAN); + jsonClimateControlCapabilities.put(ClimateControlCapabilities.KEY_DEFROST_ZONE, GENERAL_DEFROSTZONE_LIST); + jsonClimateControlCapabilities.put(ClimateControlCapabilities.KEY_VENTILATION_MODE_AVAILABLE, GENERAL_BOOLEAN); + jsonClimateControlCapabilities.put(ClimateControlCapabilities.KEY_VENTILATION_MODE, GENERAL_VENTILATIONMODE_LIST); + JSON_CLIMATECONTROLCAPABILITIES.put(jsonClimateControlCapabilities); + jsonButton = new JSONObject(); jsonButton.put(SoftButtonCapabilities.KEY_LONG_PRESS_AVAILABLE, GENERAL_BOOLEAN); jsonButton.put(SoftButtonCapabilities.KEY_SHORT_PRESS_AVAILABLE, GENERAL_BOOLEAN); diff --git a/sdl_android/src/androidTest/java/com/smartdevicelink/test/Validator.java b/sdl_android/src/androidTest/java/com/smartdevicelink/test/Validator.java index 090dce405..1e99e96a5 100644 --- a/sdl_android/src/androidTest/java/com/smartdevicelink/test/Validator.java +++ b/sdl_android/src/androidTest/java/com/smartdevicelink/test/Validator.java @@ -13,6 +13,8 @@ import com.smartdevicelink.proxy.rpc.BeltStatus; import com.smartdevicelink.proxy.rpc.BodyInformation; import com.smartdevicelink.proxy.rpc.ButtonCapabilities; import com.smartdevicelink.proxy.rpc.Choice; +import com.smartdevicelink.proxy.rpc.ClimateControlCapabilities; +import com.smartdevicelink.proxy.rpc.ClimateControlData; import com.smartdevicelink.proxy.rpc.ClusterModeStatus; import com.smartdevicelink.proxy.rpc.Coordinate; import com.smartdevicelink.proxy.rpc.DIDResult; @@ -31,11 +33,18 @@ import com.smartdevicelink.proxy.rpc.ImageField; import com.smartdevicelink.proxy.rpc.ImageResolution; import com.smartdevicelink.proxy.rpc.KeyboardProperties; import com.smartdevicelink.proxy.rpc.MenuParams; +import com.smartdevicelink.proxy.rpc.ModuleData; import com.smartdevicelink.proxy.rpc.MyKey; +import com.smartdevicelink.proxy.rpc.NavigationCapability; import com.smartdevicelink.proxy.rpc.OasisAddress; import com.smartdevicelink.proxy.rpc.ParameterPermissions; import com.smartdevicelink.proxy.rpc.PermissionItem; +import com.smartdevicelink.proxy.rpc.PhoneCapability; import com.smartdevicelink.proxy.rpc.PresetBankCapabilities; +import com.smartdevicelink.proxy.rpc.RadioControlCapabilities; +import com.smartdevicelink.proxy.rpc.RadioControlData; +import com.smartdevicelink.proxy.rpc.RdsData; +import com.smartdevicelink.proxy.rpc.RemoteControlCapabilities; import com.smartdevicelink.proxy.rpc.Rectangle; import com.smartdevicelink.proxy.rpc.ScreenParams; import com.smartdevicelink.proxy.rpc.SdlMsgVersion; @@ -44,6 +53,7 @@ import com.smartdevicelink.proxy.rpc.SoftButton; import com.smartdevicelink.proxy.rpc.SoftButtonCapabilities; import com.smartdevicelink.proxy.rpc.StartTime; import com.smartdevicelink.proxy.rpc.TTSChunk; +import com.smartdevicelink.proxy.rpc.Temperature; import com.smartdevicelink.proxy.rpc.TextField; import com.smartdevicelink.proxy.rpc.TireStatus; import com.smartdevicelink.proxy.rpc.TouchCoord; @@ -55,8 +65,10 @@ import com.smartdevicelink.proxy.rpc.VehicleType; import com.smartdevicelink.proxy.rpc.VideoStreamingCapability; import com.smartdevicelink.proxy.rpc.VideoStreamingFormat; import com.smartdevicelink.proxy.rpc.VrHelpItem; +import com.smartdevicelink.proxy.rpc.enums.DefrostZone; import com.smartdevicelink.proxy.rpc.enums.FileType; import com.smartdevicelink.proxy.rpc.enums.HMILevel; +import com.smartdevicelink.proxy.rpc.enums.VentilationMode; import com.smartdevicelink.proxy.rpc.enums.HmiZoneCapabilities; import com.smartdevicelink.proxy.rpc.enums.SpeechCapabilities; @@ -526,6 +538,342 @@ public class Validator{ return true; } + public static boolean validateTemperature(Temperature temperature1, Temperature temperature2){ + if(temperature1 == null){ + return ( temperature2 == null ); + } + if(temperature2 == null){ + return ( temperature1 == null ); + } + + if((float) temperature1.getValue() != (float) temperature2.getValue()){ + log("validateTemperature", + "Value " + temperature1.getValue() + " didn't match value " + temperature2.getValue() + + "."); + return false; + } + + if(temperature1.getUnit() != temperature2.getUnit()){ + log("validateTemperature", + "Unit " + temperature1.getUnit() + " didn't match unit " + temperature2.getUnit() + "."); + return false; + } + + return true; + } + + public static boolean validateRdsData(RdsData rdsData1, RdsData rdsData2){ + if(rdsData1 == null){ + return ( rdsData2 == null ); + } + if(rdsData2 == null){ + return ( rdsData1 == null ); + } + + if(rdsData1.getProgramService() != rdsData2.getProgramService()){ + log("validateRdsData", + "Ps " + rdsData1.getProgramService() + " didn't match Ps " + rdsData2.getProgramService() + + "."); + return false; + } + + if(rdsData1.getRadioText() != rdsData2.getRadioText()){ + log("validateRdsData", + "Rt " + rdsData1.getRadioText() + " didn't match Rt " + rdsData2.getRadioText() + + "."); + return false; + } + + if(rdsData1.getClockText() != rdsData2.getClockText()){ + log("validateRdsData", + "Ct " + rdsData1.getClockText() + " didn't match Ct " + rdsData2.getClockText() + + "."); + return false; + } + + if(rdsData1.getProgramIdentification() != rdsData2.getProgramIdentification()){ + log("validateRdsData", + "Pi " + rdsData1.getProgramIdentification() + " didn't match Pi " + rdsData2.getProgramIdentification() + + "."); + return false; + } + + if(rdsData1.getRegion() != rdsData2.getRegion()){ + log("validateRdsData", + "Reg " + rdsData1.getRegion() + " didn't match Reg " + rdsData2.getRegion() + + "."); + return false; + } + + if(rdsData1.getTrafficProgram() != rdsData2.getTrafficProgram()){ + log("validateRdsData", + "Tp " + rdsData1.getTrafficProgram() + " didn't match Tp " + rdsData2.getTrafficProgram() + + "."); + return false; + } + + if(rdsData1.getTrafficAnnouncement() != rdsData2.getTrafficAnnouncement()){ + log("validateRdsData", + "Ta " + rdsData1.getTrafficAnnouncement() + " didn't match Ta " + rdsData2.getTrafficAnnouncement() + + "."); + return false; + } + + if(rdsData1.getProgramType() != rdsData2.getProgramType()){ + log("validateRdsData", + "Pty " + rdsData1.getProgramType() + " didn't match Pty " + rdsData2.getProgramType() + + "."); + return false; + } + + return true; + } + + public static boolean validateClimateControlData(ClimateControlData climateControlData1, ClimateControlData climateControlData2){ + if(climateControlData1 == null){ + return ( climateControlData2 == null ); + } + if(climateControlData2 == null){ + return ( climateControlData1 == null ); + } + + if(climateControlData1.getFanSpeed() != climateControlData2.getFanSpeed()){ + log("validateClimateControlData", + "FanSpeed " + climateControlData1.getFanSpeed() + " didn't match fanSpeed " + climateControlData2.getFanSpeed() + + "."); + return false; + } + + if(!( validateTemperature(climateControlData1.getCurrentTemperature(), climateControlData2.getCurrentTemperature()) )){ + return false; + } + + if(!( validateTemperature(climateControlData1.getDesiredTemperature(), climateControlData2.getDesiredTemperature()) )){ + return false; + } + + if(climateControlData1.getAcEnable() != climateControlData2.getAcEnable()){ + log("validateClimateControlData", + "AcEnable " + climateControlData1.getAcEnable() + " didn't match AcEnable " + climateControlData2.getAcEnable() + + "."); + return false; + } + + if(climateControlData1.getCirculateAirEnable() != climateControlData2.getCirculateAirEnable()){ + log("validateClimateControlData", + "CirculateAirEnable " + climateControlData1.getCirculateAirEnable() + " didn't match CirculateAirEnable " + climateControlData2.getCirculateAirEnable() + + "."); + return false; + } + + if(climateControlData1.getAutoModeEnable() != climateControlData2.getAutoModeEnable()){ + log("validateClimateControlData", + "AutoModeEnable " + climateControlData1.getAutoModeEnable() + " didn't match AutoModeEnable " + climateControlData2.getAutoModeEnable() + + "."); + return false; + } + + if(climateControlData1.getDefrostZone() != climateControlData2.getDefrostZone()){ + log("validateClimateControlData", + "DefrostZone " + climateControlData1.getDefrostZone() + " didn't match DefrostZone " + climateControlData2.getDefrostZone() + + "."); + return false; + } + + if(climateControlData1.getDualModeEnable() != climateControlData2.getDualModeEnable()){ + log("validateClimateControlData", + "DualModeEnable " + climateControlData1.getDualModeEnable() + " didn't match DualModeEnable " + climateControlData2.getDualModeEnable() + + "."); + return false; + } + + if(climateControlData1.getAcMaxEnable() != climateControlData2.getAcMaxEnable()){ + log("validateClimateControlData", + "AcMaxEnable " + climateControlData1.getAcMaxEnable() + " didn't match AcMaxEnable " + climateControlData2.getAcMaxEnable() + + "."); + return false; + } + + if(climateControlData1.getVentilationMode() != climateControlData2.getVentilationMode()){ + log("validateClimateControlData", + "VentilationMode " + climateControlData1.getVentilationMode() + " didn't match VentilationMode " + climateControlData2.getVentilationMode() + + "."); + return false; + } + + + return true; + } + + public static boolean validateModuleData(ModuleData moduleData1, ModuleData moduleData2){ + if(moduleData1 == null){ + return ( moduleData2 == null ); + } + if(moduleData2 == null){ + return ( moduleData1 == null ); + } + + if(moduleData1.getModuleType() != moduleData2.getModuleType()){ + log("validateModuleData", + "ModuleType " + moduleData1.getModuleType() + " didn't match ModuleType " + moduleData2.getModuleType() + + "."); + return false; + } + + if(!( validateRadioControlData(moduleData1.getRadioControlData(), moduleData2.getRadioControlData()) )){ + return false; + } + + if(!( validateClimateControlData(moduleData1.getClimateControlData(), moduleData2.getClimateControlData()) )){ + return false; + } + + return true; + } + + public static boolean validateRemoteControlCapabilities(RemoteControlCapabilities remoteControlCapabilities1, RemoteControlCapabilities remoteControlCapabilities2){ + if(remoteControlCapabilities1 == null){ + return ( remoteControlCapabilities2 == null ); + } + if(remoteControlCapabilities2 == null){ + return ( remoteControlCapabilities1 == null ); + } + + if(!( validateButtonCapabilities(remoteControlCapabilities1.getButtonCapabilities(), remoteControlCapabilities2.getButtonCapabilities()) )){ + return false; + } + + if(!( validateRadioControlCapabilities(remoteControlCapabilities1.getRadioControlCapabilities(), remoteControlCapabilities2.getRadioControlCapabilities()) )){ + return false; + } + + if(!( validateClimateControlCapabilities(remoteControlCapabilities1.getClimateControlCapabilities(), remoteControlCapabilities2.getClimateControlCapabilities()) )){ + return false; + } + + return true; + } + + public static boolean validateRadioControlData(RadioControlData radioControlData1, RadioControlData radioControlData2){ + if(radioControlData1 == null){ + return ( radioControlData2 == null ); + } + if(radioControlData2 == null){ + return ( radioControlData1 == null ); + } + + if(radioControlData1.getFrequencyInteger() != radioControlData2.getFrequencyInteger()){ + log("validateRadioControlData", + "FrequencyInteger " + radioControlData1.getFrequencyInteger() + " didn't match FrequencyInteger " + radioControlData2.getFrequencyInteger() + + "."); + return false; + } + + if(radioControlData1.getFrequencyFraction() != radioControlData2.getFrequencyFraction()){ + log("validateRadioControlData", + "FrequencyFraction " + radioControlData1.getFrequencyFraction() + " didn't match FrequencyFraction " + radioControlData2.getFrequencyFraction() + + "."); + return false; + } + + if(radioControlData1.getBand() != radioControlData2.getBand()){ + log("validateRadioControlData", + "Band " + radioControlData1.getBand() + " didn't match Band " + radioControlData2.getBand() + + "."); + return false; + } + + if(!( validateRdsData(radioControlData1.getRdsData(), radioControlData2.getRdsData()) )){ + return false; + } + + if(radioControlData1.getAvailableHDs() != radioControlData2.getAvailableHDs()){ + log("validateRadioControlData", + "AvailableHDs " + radioControlData1.getAvailableHDs() + " didn't match AvailableHDs " + radioControlData2.getAvailableHDs() + + "."); + return false; + } + + if(radioControlData1.getHdChannel() != radioControlData2.getHdChannel()){ + log("validateRadioControlData", + "HdChannel " + radioControlData1.getHdChannel() + " didn't match HdChannel " + radioControlData2.getHdChannel() + + "."); + return false; + } + + if(radioControlData1.getSignalStrength() != radioControlData2.getSignalStrength()){ + log("validateRadioControlData", + "SignalStrength " + radioControlData1.getSignalStrength() + " didn't match SignalStrength " + radioControlData2.getSignalStrength() + + "."); + return false; + } + + if(radioControlData1.getSignalChangeThreshold() != radioControlData2.getSignalChangeThreshold()){ + log("validateRadioControlData", + "SignalChangeThreshold " + radioControlData1.getSignalChangeThreshold() + " didn't match SignalChangeThreshold " + radioControlData2.getSignalChangeThreshold() + + "."); + return false; + } + + if(radioControlData1.getRadioEnable() != radioControlData2.getRadioEnable()){ + log("validateRadioControlData", + "RadioEnable " + radioControlData1.getRadioEnable() + " didn't match RadioEnable " + radioControlData2.getRadioEnable() + + "."); + return false; + } + + if(radioControlData1.getState() != radioControlData2.getState()){ + log("validateRadioControlData", + "State " + radioControlData1.getState() + " didn't match State " + radioControlData2.getState() + + "."); + return false; + } + + return true; + } + + public static boolean validateNavigationCapability(NavigationCapability navigationCapability1, NavigationCapability navigationCapability2){ + if(navigationCapability1 == null){ + return ( navigationCapability2 == null ); + } + if(navigationCapability2 == null){ + return ( navigationCapability1 == null ); + } + + if(navigationCapability1.getSendLocationEnabled() != navigationCapability2.getSendLocationEnabled()){ + log("validateNavigationCapability", + "SendLocationEnabled " + navigationCapability1.getSendLocationEnabled() + " didn't match SendLocationEnabled " + navigationCapability2.getSendLocationEnabled() + + "."); + return false; + } + + if(navigationCapability1.getWayPointsEnabled() != navigationCapability2.getWayPointsEnabled()){ + log("validateNavigationCapability", + "WayPointsEnabled " + navigationCapability1.getWayPointsEnabled() + " didn't match WayPointsEnabled " + navigationCapability2.getWayPointsEnabled() + "."); + return false; + } + + return true; + } + + public static boolean validatePhoneCapability(PhoneCapability phoneCapability1, PhoneCapability phoneCapability2){ + if(phoneCapability1 == null){ + return ( phoneCapability2 == null ); + } + if(phoneCapability2 == null){ + return ( phoneCapability1 == null ); + } + + if(phoneCapability1.getDialNumberEnabled() != phoneCapability2.getDialNumberEnabled()){ + log("validatePhoneCapability", + "DialNumberEnabled " + phoneCapability1.getDialNumberEnabled() + " didn't match DialNumberEnabled " + phoneCapability1.getDialNumberEnabled() + + "."); + return false; + } + + return true; + } + public static boolean validateTouchEventCapabilities(TouchEventCapabilities item1, TouchEventCapabilities item2){ if(item1 == null){ return ( item2 == null ); @@ -1369,7 +1717,154 @@ public class Validator{ return true; } - + + public static boolean validateRadioControlCapabilities (List<RadioControlCapabilities> item1, List<RadioControlCapabilities> item2) { + if (item1 == null) { + return ( item2 == null ); + } + if (item2 == null) { + return ( item1 == null ); + } + + if (item1.size() != item2.size()) { + return false; + } + + for (int i = 0; i < item1.size(); i++) { + if (item1.get(i).getModuleName() != item2.get(i).getModuleName()) { + return false; + } + if (item1.get(i).getRadioEnableAvailable() != item2.get(i).getRadioEnableAvailable()) { + return false; + } + if (item1.get(i).getRadioBandAvailable() != item2.get(i).getRadioBandAvailable()) { + return false; + } + if (item1.get(i).getRadioFrequencyAvailable() != item2.get(i).getRadioFrequencyAvailable()) { + return false; + } + if (item1.get(i).getHdChannelAvailable() != item2.get(i).getHdChannelAvailable()) { + return false; + } + if (item1.get(i).getRdsDataAvailable() != item2.get(i).getRdsDataAvailable()) { + return false; + } + if (item1.get(i).getAvailableHDsAvailable() != item2.get(i).getAvailableHDsAvailable()) { + return false; + } + if (item1.get(i).getStateAvailable() != item2.get(i).getStateAvailable()) { + return false; + } + if (item1.get(i).getSignalStrengthAvailable() != item2.get(i).getSignalStrengthAvailable()) { + return false; + } + if (item1.get(i).getSignalChangeThresholdAvailable() != item2.get(i).getSignalChangeThresholdAvailable()) { + return false; + } + } + + return true; + } + + public static boolean validateClimateControlCapabilities (List<ClimateControlCapabilities> item1, List<ClimateControlCapabilities> item2) { + if (item1 == null) { + return ( item2 == null ); + } + if (item2 == null) { + return ( item1 == null ); + } + + if (item1.size() != item2.size()) { + return false; + } + + for (int i = 0; i < item1.size(); i++) { + if (item1.get(i).getModuleName() != item2.get(i).getModuleName()) { + return false; + } + if (item1.get(i).getFanSpeedAvailable() != item2.get(i).getFanSpeedAvailable()) { + return false; + } + if (item1.get(i).getDesiredTemperatureAvailable() != item2.get(i).getDesiredTemperatureAvailable()) { + return false; + } + if (item1.get(i).getAcEnableAvailable() != item2.get(i).getAcEnableAvailable()) { + return false; + } + if (item1.get(i).getAcMaxEnableAvailable() != item2.get(i).getAcMaxEnableAvailable()) { + return false; + } + if (item1.get(i).getCirculateAirEnableAvailable() != item2.get(i).getCirculateAirEnableAvailable()) { + return false; + } + if (item1.get(i).getAutoModeEnableAvailable() != item2.get(i).getAutoModeEnableAvailable()) { + return false; + } + if (item1.get(i).getDualModeEnableAvailable() != item2.get(i).getDualModeEnableAvailable()) { + return false; + } + if (item1.get(i).getDefrostZoneAvailable() != item2.get(i).getDefrostZoneAvailable()) { + return false; + } + + if(! (validateDefrostZones(item1.get(i).getDefrostZone(), item2.get(i).getDefrostZone()) )){ + return false; + } + + if (item1.get(i).getVentilationModeAvailable() != item2.get(i).getVentilationModeAvailable()) { + return false; + } + + if(! (validateVentilationModes(item1.get(i).getVentilationMode(), item2.get(i).getVentilationMode()) )){ + return false; + } + } + + return true; + } + + public static boolean validateDefrostZones (List<DefrostZone> item1, List<DefrostZone> item2) { + if (item1 == null) { + return ( item2 == null ); + } + if (item2 == null) { + return ( item1 == null ); + } + + if (item1.size() != item2.size()) { + return false; + } + + for (int i = 0; i < item1.size(); i++) { + if (item1.get(i) != item2.get(i)) { + return false; + } + } + + return true; + } + + public static boolean validateVentilationModes (List<VentilationMode> item1, List<VentilationMode> item2) { + if (item1 == null) { + return ( item2 == null ); + } + if (item2 == null) { + return ( item1 == null ); + } + + if (item1.size() != item2.size()) { + return false; + } + + for (int i = 0; i < item1.size(); i++) { + if (item1.get(i) != item2.get(i)) { + return false; + } + } + + return true; + } + public static boolean validateTurnList (List<Turn> item1, List<Turn> item2) { if (item1 == null) { return (item2 == null); diff --git a/sdl_android/src/androidTest/java/com/smartdevicelink/test/encoder/EncoderUtilsTest.java b/sdl_android/src/androidTest/java/com/smartdevicelink/test/encoder/EncoderUtilsTest.java new file mode 100644 index 000000000..083a5dd3f --- /dev/null +++ b/sdl_android/src/androidTest/java/com/smartdevicelink/test/encoder/EncoderUtilsTest.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2017, Xevo Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.smartdevicelink.test.encoder; + +import android.annotation.TargetApi; +import android.media.MediaFormat; +import android.os.Build; + +import com.smartdevicelink.encoder.EncoderUtils; + +import junit.framework.TestCase; + +import java.nio.ByteBuffer; +import java.util.Arrays; + +/** + * This is a unit test class for the SmartDeviceLink library project class : + * {@link com.smartdevicelink.encoder.EncoderUtils} + */ +@TargetApi(Build.VERSION_CODES.JELLY_BEAN) +public class EncoderUtilsTest extends TestCase { + public void testGetCodecSpecificDataWithNull() { + byte[] result = EncoderUtils.getCodecSpecificData(null); + assertNull(result); + } + + public void testGetCodecSpecificDataForAVC() { + // example of SPS NAL unit with 4-byte start code + byte[] sps = new byte[] { + 0x00, 0x00, 0x00, 0x01, + 0x67, 0x42, (byte)0xC0, 0x0A, (byte)0xA6, 0x11, 0x11, (byte)0xE8, + 0x40, 0x00, 0x00, (byte)0xFA, 0x40, 0x00, 0x3A, (byte)0x98, + 0x23, (byte)0xC4, (byte)0x89, (byte)0x84, 0x60 + }; + // example of PPS NAL unit with 4-byte start code + byte[] pps = new byte[] { + 0x00, 0x00, 0x00, 0x01, + 0x68, (byte)0xC8, 0x42, 0x0F, 0x13, 0x20 + }; + + ByteBuffer spsByteBuffer = ByteBuffer.allocate(sps.length); + spsByteBuffer.put(sps); + spsByteBuffer.flip(); + + ByteBuffer ppsByteBuffer = ByteBuffer.allocate(pps.length); + ppsByteBuffer.put(pps); + ppsByteBuffer.flip(); + + MediaFormat format = MediaFormat.createVideoFormat("video/avc", 16, 16); + format.setByteBuffer("csd-0", spsByteBuffer); + format.setByteBuffer("csd-1", ppsByteBuffer); + + byte[] result = EncoderUtils.getCodecSpecificData(format); + assertNotNull(result); + + byte[] expected = new byte[sps.length + pps.length]; + System.arraycopy(sps, 0, expected, 0, sps.length); + System.arraycopy(pps, 0, expected, sps.length, pps.length); + assertTrue("Output codec specific data doesn't match", Arrays.equals(expected, result)); + } + + public void testGetCodecSpecificDataWithInvalidAVCData() { + // testing an error case when the encoder emits SPS only (which should not happen) + byte[] sps = new byte[] { + 0x00, 0x00, 0x00, 0x01, + 0x67, 0x42, (byte)0xC0, 0x0A, (byte)0xA6, 0x11, 0x11, (byte)0xE8, + 0x40, 0x00, 0x00, (byte)0xFA, 0x40, 0x00, 0x3A, (byte)0x98, + 0x23, (byte)0xC4, (byte)0x89, (byte)0x84, 0x60 + }; + + ByteBuffer spsByteBuffer = ByteBuffer.allocate(sps.length); + spsByteBuffer.put(sps); + spsByteBuffer.flip(); + + MediaFormat format = MediaFormat.createVideoFormat("video/avc", 16, 16); + format.setByteBuffer("csd-0", spsByteBuffer); + // no PPS + + byte[] result = EncoderUtils.getCodecSpecificData(format); + assertNull(result); + } + + public void testGetCodecSpecificDataForUnknownCodec() { + MediaFormat format = MediaFormat.createVideoFormat("video/raw", 16, 16); + byte[] result = EncoderUtils.getCodecSpecificData(format); + assertNull("For unsupported codec, getCodecSpecificData should return null", result); + } +} diff --git a/sdl_android/src/androidTest/java/com/smartdevicelink/test/proxy/SdlProxyBaseTests.java b/sdl_android/src/androidTest/java/com/smartdevicelink/test/proxy/SdlProxyBaseTests.java index ee8d7d0ee..678a4e95b 100644 --- a/sdl_android/src/androidTest/java/com/smartdevicelink/test/proxy/SdlProxyBaseTests.java +++ b/sdl_android/src/androidTest/java/com/smartdevicelink/test/proxy/SdlProxyBaseTests.java @@ -17,6 +17,7 @@ import com.smartdevicelink.proxy.rpc.AddCommandResponse; import com.smartdevicelink.proxy.rpc.AddSubMenuResponse; import com.smartdevicelink.proxy.rpc.AlertManeuverResponse; import com.smartdevicelink.proxy.rpc.AlertResponse; +import com.smartdevicelink.proxy.rpc.ButtonPressResponse; import com.smartdevicelink.proxy.rpc.ChangeRegistrationResponse; import com.smartdevicelink.proxy.rpc.CreateInteractionChoiceSetResponse; import com.smartdevicelink.proxy.rpc.DeleteCommandResponse; @@ -28,6 +29,7 @@ import com.smartdevicelink.proxy.rpc.DialNumberResponse; import com.smartdevicelink.proxy.rpc.EndAudioPassThruResponse; import com.smartdevicelink.proxy.rpc.GenericResponse; import com.smartdevicelink.proxy.rpc.GetDTCsResponse; +import com.smartdevicelink.proxy.rpc.GetInteriorVehicleDataResponse; import com.smartdevicelink.proxy.rpc.GetSystemCapabilityResponse; import com.smartdevicelink.proxy.rpc.GetVehicleDataResponse; import com.smartdevicelink.proxy.rpc.GetWayPointsResponse; @@ -39,6 +41,7 @@ import com.smartdevicelink.proxy.rpc.OnCommand; import com.smartdevicelink.proxy.rpc.OnDriverDistraction; import com.smartdevicelink.proxy.rpc.OnHMIStatus; import com.smartdevicelink.proxy.rpc.OnHashChange; +import com.smartdevicelink.proxy.rpc.OnInteriorVehicleData; import com.smartdevicelink.proxy.rpc.OnKeyboardInput; import com.smartdevicelink.proxy.rpc.OnLanguageChange; import com.smartdevicelink.proxy.rpc.OnLockScreenStatus; @@ -60,6 +63,7 @@ import com.smartdevicelink.proxy.rpc.SendLocationResponse; import com.smartdevicelink.proxy.rpc.SetAppIconResponse; import com.smartdevicelink.proxy.rpc.SetDisplayLayoutResponse; import com.smartdevicelink.proxy.rpc.SetGlobalPropertiesResponse; +import com.smartdevicelink.proxy.rpc.SetInteriorVehicleDataResponse; import com.smartdevicelink.proxy.rpc.SetMediaClockTimerResponse; import com.smartdevicelink.proxy.rpc.ShowConstantTbtResponse; import com.smartdevicelink.proxy.rpc.ShowResponse; @@ -439,6 +443,26 @@ public class SdlProxyBaseTests extends AndroidTestCase{ } @Override + public void onGetInteriorVehicleDataResponse(GetInteriorVehicleDataResponse response) { + Log.i(TAG, "GetInteriorVehicleData response from SDL: " + response); + } + + @Override + public void onButtonPressResponse(ButtonPressResponse response) { + Log.i(TAG, "ButtonPress response from SDL: " + response); + } + + @Override + public void onSetInteriorVehicleDataResponse(SetInteriorVehicleDataResponse response) { + Log.i(TAG, "SetInteriorVehicleData response from SDL: " + response); + } + + @Override + public void onOnInteriorVehicleData(OnInteriorVehicleData notification) { + + } + + @Override public void onOnDriverDistraction(OnDriverDistraction notification) { // Some RPCs (depending on region) cannot be sent when driver distraction is active. } diff --git a/sdl_android/src/androidTest/java/com/smartdevicelink/test/proxy/SystemCapabilityManagerTests.java b/sdl_android/src/androidTest/java/com/smartdevicelink/test/proxy/SystemCapabilityManagerTests.java index 89c15ab16..702b83cad 100644 --- a/sdl_android/src/androidTest/java/com/smartdevicelink/test/proxy/SystemCapabilityManagerTests.java +++ b/sdl_android/src/androidTest/java/com/smartdevicelink/test/proxy/SystemCapabilityManagerTests.java @@ -2,8 +2,12 @@ package com.smartdevicelink.test.proxy; import android.test.AndroidTestCase; +import com.smartdevicelink.protocol.enums.FunctionID; +import com.smartdevicelink.protocol.enums.SessionType; import com.smartdevicelink.proxy.RPCRequest; import com.smartdevicelink.proxy.SystemCapabilityManager; +import com.smartdevicelink.proxy.interfaces.ISdl; +import com.smartdevicelink.proxy.interfaces.ISdlServiceListener; import com.smartdevicelink.proxy.interfaces.OnSystemCapabilityListener; import com.smartdevicelink.proxy.rpc.AudioPassThruCapabilities; import com.smartdevicelink.proxy.rpc.ButtonCapabilities; @@ -19,6 +23,8 @@ import com.smartdevicelink.proxy.rpc.VideoStreamingCapability; import com.smartdevicelink.proxy.rpc.enums.HmiZoneCapabilities; import com.smartdevicelink.proxy.rpc.enums.SpeechCapabilities; import com.smartdevicelink.proxy.rpc.enums.SystemCapabilityType; +import com.smartdevicelink.proxy.rpc.listeners.OnRPCNotificationListener; +import com.smartdevicelink.streaming.VideoStreamingParameters; import com.smartdevicelink.test.Test; import com.smartdevicelink.test.Validator; import com.smartdevicelink.util.CorrelationIdGenerator; @@ -26,6 +32,8 @@ import com.smartdevicelink.util.CorrelationIdGenerator; import java.util.List; import static android.R.id.list; +import static android.R.id.message; +import static com.smartdevicelink.proxy.constants.Names.parameters; public class SystemCapabilityManagerTests extends AndroidTestCase { public static final String TAG = "SystemCapabilityManagerTests"; @@ -42,12 +50,7 @@ public class SystemCapabilityManagerTests extends AndroidTestCase { } public SystemCapabilityManager createSampleManager(){ - SystemCapabilityManager systemCapabilityManager = new SystemCapabilityManager(new SystemCapabilityManager.ISystemCapabilityManager() { - @Override - public void onSendPacketRequest(RPCRequest message) { - - } - }); + SystemCapabilityManager systemCapabilityManager = new SystemCapabilityManager(new InternalSDLInterface()); RegisterAppInterfaceResponse raiResponse = new RegisterAppInterfaceResponse(); @@ -98,9 +101,9 @@ public class SystemCapabilityManagerTests extends AndroidTestCase { final SystemCapability referenceCapability = cap; - systemCapabilityManager = new SystemCapabilityManager(new SystemCapabilityManager.ISystemCapabilityManager() { + systemCapabilityManager = new SystemCapabilityManager(new InternalSDLInterface() { @Override - public void onSendPacketRequest(RPCRequest message) { + public void sendRPCRequest(RPCRequest message) { GetSystemCapabilityResponse response = new GetSystemCapabilityResponse(); response.setSystemCapability(referenceCapability); response.setSuccess(true); @@ -131,7 +134,44 @@ public class SystemCapabilityManagerTests extends AndroidTestCase { List<SoftButtonCapabilities> list = SystemCapabilityManager.convertToList(capability, SoftButtonCapabilities.class); assertNotNull(list); + } + + private class InternalSDLInterface implements ISdl{ + @Override + public void start(){} + + @Override + public void stop() {} + + @Override + public boolean isConnected() {return false; } + + @Override + public void addServiceListener(SessionType serviceType, ISdlServiceListener sdlServiceListener) {} + + @Override + public void removeServiceListener(SessionType serviceType, ISdlServiceListener sdlServiceListener) {} + + @Override + public void startVideoService(VideoStreamingParameters parameters, boolean encrypted) { } + + @Override + public void stopVideoService() {} + + @Override + public void startAudioService(boolean encrypted) {} + + @Override + public void stopAudioService() {} + + @Override + public void sendRPCRequest(RPCRequest message) {} + + @Override + public void addOnRPCNotificationListener(FunctionID notificationId, OnRPCNotificationListener listener) {} + @Override + public boolean removeOnRPCNotificationListener(FunctionID notificationId, OnRPCNotificationListener listener) {return false;} } diff --git a/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/ClimateControlCapabilitiesTests.java b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/ClimateControlCapabilitiesTests.java new file mode 100644 index 000000000..33f9d2631 --- /dev/null +++ b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/ClimateControlCapabilitiesTests.java @@ -0,0 +1,160 @@ +package com.smartdevicelink.test.rpc.datatypes; + +import com.smartdevicelink.proxy.rpc.ClimateControlCapabilities; +import com.smartdevicelink.proxy.rpc.enums.DefrostZone; +import com.smartdevicelink.proxy.rpc.enums.VentilationMode; +import com.smartdevicelink.test.JsonUtils; +import com.smartdevicelink.test.Test; + +import junit.framework.TestCase; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * This is a unit test class for the SmartDeviceLink library project class : + * {@link com.smartdevicelink.rpc.ClimateControlCapabilities} + */ +public class ClimateControlCapabilitiesTests extends TestCase{ + + private ClimateControlCapabilities msg; + + @Override + public void setUp(){ + msg = new ClimateControlCapabilities(); + + msg.setModuleName(Test.GENERAL_STRING); + msg.setFanSpeedAvailable(Test.GENERAL_BOOLEAN); + msg.setDesiredTemperatureAvailable(Test.GENERAL_BOOLEAN); + msg.setAcEnableAvailable(Test.GENERAL_BOOLEAN); + msg.setAcMaxEnableAvailable(Test.GENERAL_BOOLEAN); + msg.setCirculateAirEnableAvailable(Test.GENERAL_BOOLEAN); + msg.setAutoModeEnableAvailable(Test.GENERAL_BOOLEAN); + msg.setDualModeEnableAvailable(Test.GENERAL_BOOLEAN); + msg.setDefrostZoneAvailable(Test.GENERAL_BOOLEAN); + msg.setDefrostZone(Test.GENERAL_DEFROSTZONE_LIST); + msg.setVentilationModeAvailable(Test.GENERAL_BOOLEAN); + msg.setVentilationMode(Test.GENERAL_VENTILATIONMODE_LIST); + } + + /** + * Tests the expected values of the RPC message. + */ + public void testRpcValues () { + // Test Values + String moduleName = msg.getModuleName(); + boolean fanSpeedAvailable = msg.getFanSpeedAvailable(); + boolean desiredTemperatureAvailable = msg.getDesiredTemperatureAvailable(); + boolean acEnableAvailable = msg.getAcEnableAvailable(); + boolean acMaxEnableAvailable = msg.getAcMaxEnableAvailable(); + boolean circulateAirEnableAvailable = msg.getCirculateAirEnableAvailable(); + boolean autoModeEnableAvailable = msg.getAutoModeEnableAvailable(); + boolean dualModeEnableAvailable = msg.getDualModeEnableAvailable(); + boolean defrostZoneAvailable = msg.getDefrostZoneAvailable(); + List<DefrostZone> defrostZone = msg.getDefrostZone(); + boolean ventilationModeAvailable = msg.getVentilationModeAvailable(); + List<VentilationMode> ventilationMode = msg.getVentilationMode(); + + // Valid Tests + assertEquals(Test.MATCH, Test.GENERAL_STRING, moduleName); + assertEquals(Test.MATCH, Test.GENERAL_BOOLEAN, fanSpeedAvailable); + assertEquals(Test.MATCH, Test.GENERAL_BOOLEAN, desiredTemperatureAvailable); + assertEquals(Test.MATCH, Test.GENERAL_BOOLEAN, acEnableAvailable); + assertEquals(Test.MATCH, Test.GENERAL_BOOLEAN, acMaxEnableAvailable); + assertEquals(Test.MATCH, Test.GENERAL_BOOLEAN, circulateAirEnableAvailable); + assertEquals(Test.MATCH, Test.GENERAL_BOOLEAN, autoModeEnableAvailable); + assertEquals(Test.MATCH, Test.GENERAL_BOOLEAN, dualModeEnableAvailable); + assertEquals(Test.MATCH, Test.GENERAL_BOOLEAN, defrostZoneAvailable); + assertEquals(Test.MATCH, Test.GENERAL_BOOLEAN, ventilationModeAvailable); + + assertEquals(Test.MATCH, Test.GENERAL_DEFROSTZONE_LIST.size(), defrostZone.size()); + assertEquals(Test.MATCH, Test.GENERAL_VENTILATIONMODE_LIST.size(), ventilationMode.size()); + + for(int i = 0; i < Test.GENERAL_DEFROSTZONE_LIST.size(); i++){ + assertEquals(Test.MATCH, Test.GENERAL_DEFROSTZONE_LIST.get(i), defrostZone.get(i)); + } + for(int i = 0; i < Test.GENERAL_VENTILATIONMODE_LIST.size(); i++){ + assertEquals(Test.MATCH, Test.GENERAL_VENTILATIONMODE_LIST.get(i), ventilationMode.get(i)); + } + + // Invalid/Null Tests + ClimateControlCapabilities msg = new ClimateControlCapabilities(); + assertNotNull(Test.NOT_NULL, msg); + + assertNull(Test.NULL, msg.getModuleName()); + assertNull(Test.NULL, msg.getFanSpeedAvailable()); + assertNull(Test.NULL, msg.getDesiredTemperatureAvailable()); + assertNull(Test.NULL, msg.getAcEnableAvailable()); + assertNull(Test.NULL, msg.getAcMaxEnableAvailable()); + assertNull(Test.NULL, msg.getAutoModeEnableAvailable()); + assertNull(Test.NULL, msg.getDualModeEnableAvailable()); + assertNull(Test.NULL, msg.getDefrostZoneAvailable()); + assertNull(Test.NULL, msg.getDefrostZone()); + assertNull(Test.NULL, msg.getVentilationModeAvailable()); + assertNull(Test.NULL, msg.getVentilationMode()); + } + + public void testJson(){ + JSONObject reference = new JSONObject(); + + try{ + reference.put(ClimateControlCapabilities.KEY_MODULE_NAME, Test.GENERAL_STRING); + reference.put(ClimateControlCapabilities.KEY_FAN_SPEED_AVAILABLE, Test.GENERAL_BOOLEAN); + reference.put(ClimateControlCapabilities.KEY_DESIRED_TEMPERATURE_AVAILABLE, Test.GENERAL_BOOLEAN); + reference.put(ClimateControlCapabilities.KEY_AC_ENABLE_AVAILABLE, Test.GENERAL_BOOLEAN); + reference.put(ClimateControlCapabilities.KEY_AC_MAX_ENABLE_AVAILABLE, Test.GENERAL_BOOLEAN); + reference.put(ClimateControlCapabilities.KEY_CIRCULATE_AIR_ENABLE_AVAILABLE, Test.GENERAL_BOOLEAN); + reference.put(ClimateControlCapabilities.KEY_AUTO_MODE_ENABLE_AVAILABLE, Test.GENERAL_BOOLEAN); + reference.put(ClimateControlCapabilities.KEY_DUAL_MODE_ENABLE_AVAILABLE, Test.GENERAL_BOOLEAN); + reference.put(ClimateControlCapabilities.KEY_DEFROST_ZONE_AVAILABLE, Test.GENERAL_BOOLEAN); + reference.put(ClimateControlCapabilities.KEY_VENTILATION_MODE_AVAILABLE, Test.GENERAL_BOOLEAN); + reference.put(ClimateControlCapabilities.KEY_DEFROST_ZONE, JsonUtils.createJsonArray(Test.GENERAL_DEFROSTZONE_LIST)); + reference.put(ClimateControlCapabilities.KEY_VENTILATION_MODE, JsonUtils.createJsonArray(Test.GENERAL_VENTILATIONMODE_LIST)); + + JSONObject underTest = msg.serializeJSON(); + assertEquals(Test.MATCH, reference.length(), underTest.length()); + + Iterator<?> iterator = reference.keys(); + while(iterator.hasNext()){ + String key = (String) iterator.next(); + + if(key.equals(ClimateControlCapabilities.KEY_DEFROST_ZONE)) { + JSONArray defrostZoneArrayReference = JsonUtils.readJsonArrayFromJsonObject(reference, key); + JSONArray defrostZoneArrayTest = JsonUtils.readJsonArrayFromJsonObject(underTest, key); + List<DefrostZone> defrostZoneListReference = new ArrayList<DefrostZone>(); + List<DefrostZone> defrostZoneListTest = new ArrayList<DefrostZone>(); + + assertEquals(Test.MATCH, defrostZoneArrayReference.length(), defrostZoneArrayTest.length()); + + for (int index = 0 ; index < defrostZoneArrayReference.length(); index++) { + defrostZoneListReference.add( (DefrostZone)defrostZoneArrayReference.get(index) ); + defrostZoneListTest.add( (DefrostZone)defrostZoneArrayTest.get(index) ); + } + assertTrue(Test.TRUE, defrostZoneListReference.containsAll(defrostZoneListTest) && defrostZoneListTest.containsAll(defrostZoneListReference)); + } else if(key.equals(ClimateControlCapabilities.KEY_VENTILATION_MODE)) { + JSONArray ventilationModeArrayReference = JsonUtils.readJsonArrayFromJsonObject(reference, key); + JSONArray ventilationModeArrayTest = JsonUtils.readJsonArrayFromJsonObject(underTest, key); + List<VentilationMode> ventilationModeListReference = new ArrayList<VentilationMode>(); + List<VentilationMode> ventilationModeListTest = new ArrayList<VentilationMode>(); + + assertEquals(Test.MATCH, ventilationModeArrayReference.length(), ventilationModeArrayTest.length()); + + for (int index = 0 ; index < ventilationModeArrayReference.length(); index++) { + ventilationModeListReference.add( (VentilationMode)ventilationModeArrayReference.get(index) ); + ventilationModeListTest.add( (VentilationMode)ventilationModeArrayTest.get(index) ); + } + assertTrue(Test.TRUE, ventilationModeListReference.containsAll(ventilationModeListTest) && ventilationModeListTest.containsAll(ventilationModeListReference)); + } else{ + assertEquals(Test.MATCH, JsonUtils.readObjectFromJsonObject(reference, key), JsonUtils.readObjectFromJsonObject(underTest, key)); + } + } + } catch(JSONException e){ + fail(Test.JSON_FAIL); + } + } +}
\ No newline at end of file diff --git a/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/ClimateControlDataTests.java b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/ClimateControlDataTests.java new file mode 100644 index 000000000..5b0eefa9f --- /dev/null +++ b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/ClimateControlDataTests.java @@ -0,0 +1,130 @@ +package com.smartdevicelink.test.rpc.datatypes; + +import com.smartdevicelink.marshal.JsonRPCMarshaller; +import com.smartdevicelink.proxy.rpc.ClimateControlData; +import com.smartdevicelink.proxy.rpc.Temperature; +import com.smartdevicelink.proxy.rpc.enums.DefrostZone; +import com.smartdevicelink.proxy.rpc.enums.VentilationMode; +import com.smartdevicelink.test.JsonUtils; +import com.smartdevicelink.test.Test; +import com.smartdevicelink.test.Validator; + +import junit.framework.TestCase; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.Hashtable; +import java.util.Iterator; + +/** + * This is a unit test class for the SmartDeviceLink library project class : + * {@link com.smartdevicelink.rpc.ClimateControlData} + */ +public class ClimateControlDataTests extends TestCase{ + + private ClimateControlData msg; + + @Override + public void setUp(){ + msg = new ClimateControlData(); + + msg.setFanSpeed(Test.GENERAL_INT); + msg.setCurrentTemperature(Test.GENERAL_TEMPERATURE); + msg.setDesiredTemperature(Test.GENERAL_TEMPERATURE); + msg.setAcEnable(Test.GENERAL_BOOLEAN); + msg.setCirculateAirEnable(Test.GENERAL_BOOLEAN); + msg.setAutoModeEnable(Test.GENERAL_BOOLEAN); + msg.setDefrostZone(Test.GENERAL_DEFROSTZONE); + msg.setDualModeEnable(Test.GENERAL_BOOLEAN); + msg.setAcMaxEnable(Test.GENERAL_BOOLEAN); + msg.setVentilationMode(Test.GENERAL_VENTILATIONMODE); + } + + /** + * Tests the expected values of the RPC message. + */ + public void testRpcValues () { + // Test Values + int fanSpeed = msg.getFanSpeed(); + Temperature currentTemperature = msg.getCurrentTemperature(); + Temperature desiredTemperature = msg.getDesiredTemperature(); + boolean acEnable = msg.getAcEnable(); + boolean circulateAirEnable = msg.getCirculateAirEnable(); + boolean autoModeEnable = msg.getAutoModeEnable(); + DefrostZone defrostZone = msg.getDefrostZone(); + boolean dualModeEnable = msg.getDualModeEnable(); + boolean acMaxEnable = msg.getAcMaxEnable(); + VentilationMode ventilationMode = msg.getVentilationMode(); + + // Valid Tests + assertEquals(Test.MATCH, Test.GENERAL_INT, fanSpeed); + assertTrue(Test.TRUE, Validator.validateTemperature(Test.GENERAL_TEMPERATURE, currentTemperature)); + assertTrue(Test.TRUE, Validator.validateTemperature(Test.GENERAL_TEMPERATURE, desiredTemperature)); + assertEquals(Test.MATCH, Test.GENERAL_BOOLEAN, acEnable); + assertEquals(Test.MATCH, Test.GENERAL_BOOLEAN, circulateAirEnable); + assertEquals(Test.MATCH, Test.GENERAL_BOOLEAN, autoModeEnable); + assertEquals(Test.MATCH, Test.GENERAL_DEFROSTZONE, defrostZone); + assertEquals(Test.MATCH, Test.GENERAL_BOOLEAN, dualModeEnable); + assertEquals(Test.MATCH, Test.GENERAL_BOOLEAN, acMaxEnable); + assertEquals(Test.MATCH, Test.GENERAL_VENTILATIONMODE, ventilationMode); + + // Invalid/Null Tests + ClimateControlData msg = new ClimateControlData(); + assertNotNull(Test.NOT_NULL, msg); + + assertNull(Test.NULL, msg.getFanSpeed()); + assertNull(Test.NULL, msg.getCurrentTemperature()); + assertNull(Test.NULL, msg.getDesiredTemperature()); + assertNull(Test.NULL, msg.getAcEnable()); + assertNull(Test.NULL, msg.getCirculateAirEnable()); + assertNull(Test.NULL, msg.getAutoModeEnable()); + assertNull(Test.NULL, msg.getDefrostZone()); + assertNull(Test.NULL, msg.getDualModeEnable()); + assertNull(Test.NULL, msg.getAcMaxEnable()); + assertNull(Test.NULL, msg.getVentilationMode()); + } + + public void testJson(){ + JSONObject reference = new JSONObject(); + + try{ + reference.put(ClimateControlData.KEY_FAN_SPEED, Test.GENERAL_INT); + reference.put(ClimateControlData.KEY_CURRENT_TEMPERATURE, JsonRPCMarshaller.serializeHashtable(Test.GENERAL_TEMPERATURE.getStore())); + reference.put(ClimateControlData.KEY_DESIRED_TEMPERATURE, JsonRPCMarshaller.serializeHashtable(Test.GENERAL_TEMPERATURE.getStore())); + reference.put(ClimateControlData.KEY_AC_ENABLE, Test.GENERAL_BOOLEAN); + reference.put(ClimateControlData.KEY_CIRCULATE_AIR_ENABLE, Test.GENERAL_BOOLEAN); + reference.put(ClimateControlData.KEY_AUTO_MODE_ENABLE, Test.GENERAL_BOOLEAN); + reference.put(ClimateControlData.KEY_DUAL_MODE_ENABLE, Test.GENERAL_BOOLEAN); + reference.put(ClimateControlData.KEY_AC_MAX_ENABLE, Test.GENERAL_BOOLEAN); + reference.put(ClimateControlData.KEY_DEFROST_ZONE, Test.GENERAL_DEFROSTZONE); + reference.put(ClimateControlData.KEY_VENTILATION_MODE, Test.GENERAL_VENTILATIONMODE); + + JSONObject underTest = msg.serializeJSON(); + assertEquals(Test.MATCH, reference.length(), underTest.length()); + + Iterator<?> iterator = reference.keys(); + while(iterator.hasNext()){ + String key = (String) iterator.next(); + + if(key.equals(ClimateControlData.KEY_CURRENT_TEMPERATURE)){ + JSONObject objectEquals = (JSONObject) JsonUtils.readObjectFromJsonObject(reference, key); + JSONObject testEquals = (JSONObject) JsonUtils.readObjectFromJsonObject(underTest, key); + Hashtable<String, Object> hashReference = JsonRPCMarshaller.deserializeJSONObject(objectEquals); + Hashtable<String, Object> hashTest = JsonRPCMarshaller.deserializeJSONObject(testEquals); + assertTrue(Test.TRUE, Validator.validateTemperature( new Temperature(hashReference), new Temperature(hashTest))); + } else if(key.equals(ClimateControlData.KEY_DESIRED_TEMPERATURE)){ + JSONObject objectEquals = (JSONObject) JsonUtils.readObjectFromJsonObject(reference, key); + JSONObject testEquals = (JSONObject) JsonUtils.readObjectFromJsonObject(underTest, key); + Hashtable<String, Object> hashReference = JsonRPCMarshaller.deserializeJSONObject(objectEquals); + Hashtable<String, Object> hashTest = JsonRPCMarshaller.deserializeJSONObject(testEquals); + assertTrue(Test.TRUE, Validator.validateTemperature( new Temperature(hashReference), new Temperature(hashTest))); + } else{ + assertEquals(Test.MATCH, JsonUtils.readObjectFromJsonObject(reference, key), JsonUtils.readObjectFromJsonObject(underTest, key)); + } + } + } catch(JSONException e){ + fail(Test.JSON_FAIL); + } + } +}
\ No newline at end of file diff --git a/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/ModuleDataTests.java b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/ModuleDataTests.java new file mode 100644 index 000000000..ea71dfc8a --- /dev/null +++ b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/ModuleDataTests.java @@ -0,0 +1,95 @@ +package com.smartdevicelink.test.rpc.datatypes; + +import com.smartdevicelink.marshal.JsonRPCMarshaller; +import com.smartdevicelink.proxy.rpc.ClimateControlData; +import com.smartdevicelink.proxy.rpc.ModuleData; +import com.smartdevicelink.proxy.rpc.RadioControlData; +import com.smartdevicelink.proxy.rpc.enums.ModuleType; +import com.smartdevicelink.test.JsonUtils; +import com.smartdevicelink.test.Test; +import com.smartdevicelink.test.Validator; + +import junit.framework.TestCase; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.Hashtable; +import java.util.Iterator; + +/** + * This is a unit test class for the SmartDeviceLink library project class : + * {@link com.smartdevicelink.rpc.ModuleData} + */ +public class ModuleDataTests extends TestCase{ + + private ModuleData msg; + + @Override + public void setUp(){ + msg = new ModuleData(); + + msg.setModuleType(Test.GENERAL_MODULETYPE); + msg.setRadioControlData(Test.GENERAL_RADIOCONTROLDATA); + msg.setClimateControlData(Test.GENERAL_CLIMATECONTROLDATA); + } + + /** + * Tests the expected values of the RPC message. + */ + public void testRpcValues () { + // Test Values + ModuleType moduleType = msg.getModuleType(); + RadioControlData radioControlData = msg.getRadioControlData(); + ClimateControlData climateControlData = msg.getClimateControlData(); + + // Valid Tests + assertEquals(Test.MATCH, Test.GENERAL_MODULETYPE, moduleType); + assertTrue(Test.TRUE, Validator.validateRadioControlData(Test.GENERAL_RADIOCONTROLDATA, radioControlData)); + assertTrue(Test.TRUE, Validator.validateClimateControlData(Test.GENERAL_CLIMATECONTROLDATA, climateControlData)); + + // Invalid/Null Tests + ModuleData msg = new ModuleData(); + assertNotNull(Test.NOT_NULL, msg); + + assertNull(Test.NULL, msg.getModuleType()); + assertNull(Test.NULL, msg.getRadioControlData()); + assertNull(Test.NULL, msg.getClimateControlData()); + } + + public void testJson(){ + JSONObject reference = new JSONObject(); + + try{ + reference.put(ModuleData.KEY_MODULE_TYPE, Test.GENERAL_MODULETYPE); + reference.put(ModuleData.KEY_RADIO_CONTROL_DATA, JsonRPCMarshaller.serializeHashtable(Test.GENERAL_RADIOCONTROLDATA.getStore())); + reference.put(ModuleData.KEY_CLIMATE_CONTROL_DATA, JsonRPCMarshaller.serializeHashtable(Test.GENERAL_CLIMATECONTROLDATA.getStore())); + + JSONObject underTest = msg.serializeJSON(); + assertEquals(Test.MATCH, reference.length(), underTest.length()); + + Iterator<?> iterator = reference.keys(); + while(iterator.hasNext()){ + String key = (String) iterator.next(); + + if(key.equals(ModuleData.KEY_RADIO_CONTROL_DATA)){ + JSONObject objectEquals = (JSONObject) JsonUtils.readObjectFromJsonObject(reference, key); + JSONObject testEquals = (JSONObject) JsonUtils.readObjectFromJsonObject(underTest, key); + Hashtable<String, Object> hashReference = JsonRPCMarshaller.deserializeJSONObject(objectEquals); + Hashtable<String, Object> hashTest = JsonRPCMarshaller.deserializeJSONObject(testEquals); + assertTrue(Test.TRUE, Validator.validateRadioControlData( new RadioControlData(hashReference), new RadioControlData(hashTest))); + } else if(key.equals(ModuleData.KEY_CLIMATE_CONTROL_DATA)){ + JSONObject objectEquals = (JSONObject) JsonUtils.readObjectFromJsonObject(reference, key); + JSONObject testEquals = (JSONObject) JsonUtils.readObjectFromJsonObject(underTest, key); + Hashtable<String, Object> hashReference = JsonRPCMarshaller.deserializeJSONObject(objectEquals); + Hashtable<String, Object> hashTest = JsonRPCMarshaller.deserializeJSONObject(testEquals); + assertTrue(Test.TRUE, Validator.validateClimateControlData( new ClimateControlData(hashReference), new ClimateControlData(hashTest))); + } else{ + assertEquals(Test.MATCH, JsonUtils.readObjectFromJsonObject(reference, key), JsonUtils.readObjectFromJsonObject(underTest, key)); + } + } + } catch(JSONException e){ + fail(Test.JSON_FAIL); + } + } +}
\ No newline at end of file diff --git a/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/NavigationCapabilityTests.java b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/NavigationCapabilityTests.java new file mode 100644 index 000000000..efbf7e30d --- /dev/null +++ b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/NavigationCapabilityTests.java @@ -0,0 +1,69 @@ +package com.smartdevicelink.test.rpc.datatypes; + +import com.smartdevicelink.proxy.rpc.NavigationCapability; +import com.smartdevicelink.test.JsonUtils; +import com.smartdevicelink.test.Test; + +import junit.framework.TestCase; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.Iterator; + +/** + * This is a unit test class for the SmartDeviceLink library project class : + * {@link com.smartdevicelink.rpc.NavigationCapability} + */ +public class NavigationCapabilityTests extends TestCase{ + + private NavigationCapability msg; + + @Override + public void setUp(){ + msg = new NavigationCapability(); + + msg.setSendLocationEnabled(Test.GENERAL_BOOLEAN); + msg.setWayPointsEnabled(Test.GENERAL_BOOLEAN); + } + + /** + * Tests the expected values of the RPC message. + */ + public void testRpcValues () { + // Test Values + boolean sendLocationEnabled = msg.getSendLocationEnabled(); + boolean getWayPointsEnabled = msg.getWayPointsEnabled(); + + // Valid Tests + assertEquals(Test.MATCH, Test.GENERAL_BOOLEAN, sendLocationEnabled); + assertEquals(Test.MATCH, Test.GENERAL_BOOLEAN, getWayPointsEnabled); + + // Invalid/Null Tests + NavigationCapability msg = new NavigationCapability(); + assertNotNull(Test.NOT_NULL, msg); + + assertNull(Test.NULL, msg.getSendLocationEnabled()); + assertNull(Test.NULL, msg.getWayPointsEnabled()); + } + + public void testJson(){ + JSONObject reference = new JSONObject(); + + try{ + reference.put(NavigationCapability.KEY_GETWAYPOINTS_ENABLED, Test.GENERAL_BOOLEAN); + reference.put(NavigationCapability.KEY_LOCATION_ENABLED, Test.GENERAL_BOOLEAN); + + JSONObject underTest = msg.serializeJSON(); + assertEquals(Test.MATCH, reference.length(), underTest.length()); + + Iterator<?> iterator = reference.keys(); + while(iterator.hasNext()){ + String key = (String) iterator.next(); + assertEquals(Test.MATCH, JsonUtils.readObjectFromJsonObject(reference, key), JsonUtils.readObjectFromJsonObject(underTest, key)); + } + }catch(JSONException e){ + fail(Test.JSON_FAIL); + } + } +}
\ No newline at end of file diff --git a/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/PhoneCapabilityTests.java b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/PhoneCapabilityTests.java new file mode 100644 index 000000000..2614db0fd --- /dev/null +++ b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/PhoneCapabilityTests.java @@ -0,0 +1,64 @@ +package com.smartdevicelink.test.rpc.datatypes; + +import com.smartdevicelink.proxy.rpc.PhoneCapability; +import com.smartdevicelink.test.JsonUtils; +import com.smartdevicelink.test.Test; + +import junit.framework.TestCase; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.Iterator; + +/** + * This is a unit test class for the SmartDeviceLink library project class : + * {@link com.smartdevicelink.rpc.PhoneCapability} + */ +public class PhoneCapabilityTests extends TestCase{ + + private PhoneCapability msg; + + @Override + public void setUp(){ + msg = new PhoneCapability(); + + msg.setDialNumberEnabled(Test.GENERAL_BOOLEAN); + } + + /** + * Tests the expected values of the RPC message. + */ + public void testRpcValues () { + // Test Values + boolean dialNumberEnabled = msg.getDialNumberEnabled(); + + // Valid Tests + assertEquals(Test.MATCH, Test.GENERAL_BOOLEAN, dialNumberEnabled); + + // Invalid/Null Tests + PhoneCapability msg = new PhoneCapability(); + assertNotNull(Test.NOT_NULL, msg); + + assertNull(Test.NULL, msg.getDialNumberEnabled()); + } + + public void testJson(){ + JSONObject reference = new JSONObject(); + + try{ + reference.put(PhoneCapability.KEY_DIALNUMBER_ENABLED, Test.GENERAL_BOOLEAN); + + JSONObject underTest = msg.serializeJSON(); + assertEquals(Test.MATCH, reference.length(), underTest.length()); + + Iterator<?> iterator = reference.keys(); + while(iterator.hasNext()){ + String key = (String) iterator.next(); + assertEquals(Test.MATCH, JsonUtils.readObjectFromJsonObject(reference, key), JsonUtils.readObjectFromJsonObject(underTest, key)); + } + }catch(JSONException e){ + fail(Test.JSON_FAIL); + } + } +}
\ No newline at end of file diff --git a/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/RadioControlCapabilitiesTests.java b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/RadioControlCapabilitiesTests.java new file mode 100644 index 000000000..28c1d2c5b --- /dev/null +++ b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/RadioControlCapabilitiesTests.java @@ -0,0 +1,112 @@ +package com.smartdevicelink.test.rpc.datatypes; + +import com.smartdevicelink.proxy.rpc.RadioControlCapabilities; +import com.smartdevicelink.test.JsonUtils; +import com.smartdevicelink.test.Test; + +import junit.framework.TestCase; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.Iterator; + +/** + * This is a unit test class for the SmartDeviceLink library project class : + * {@link com.smartdevicelink.rpc.RadioControlCapabilities} + */ +public class RadioControlCapabilitiesTests extends TestCase{ + + private RadioControlCapabilities msg; + + @Override + public void setUp(){ + msg = new RadioControlCapabilities(); + + msg.setModuleName(Test.GENERAL_STRING); + msg.setRadioEnableAvailable(Test.GENERAL_BOOLEAN); + msg.setRadioBandAvailable(Test.GENERAL_BOOLEAN); + msg.setRadioFrequencyAvailable(Test.GENERAL_BOOLEAN); + msg.setHdChannelAvailable(Test.GENERAL_BOOLEAN); + msg.setRdsDataAvailable(Test.GENERAL_BOOLEAN); + msg.setAvailableHDsAvailable(Test.GENERAL_BOOLEAN); + msg.setStateAvailable(Test.GENERAL_BOOLEAN); + msg.setSignalStrengthAvailable(Test.GENERAL_BOOLEAN); + msg.setSignalChangeThresholdAvailable(Test.GENERAL_BOOLEAN); + } + + /** + * Tests the expected values of the RPC message. + */ + public void testRpcValues () { + // Test Values + String moduleName = msg.getModuleName(); + boolean radioEnableAvailable = msg.getRadioEnableAvailable(); + boolean radioBandAvailable = msg.getRadioBandAvailable(); + boolean radioFrequencyAvailable = msg.getRadioFrequencyAvailable(); + boolean hdChannelAvailable = msg.getHdChannelAvailable(); + boolean rdsDataAvailable = msg.getRdsDataAvailable(); + boolean availableHDsAvailable = msg.getAvailableHDsAvailable(); + boolean stateAvailable = msg.getStateAvailable(); + boolean signalStrengthAvailable = msg.getSignalStrengthAvailable(); + boolean signalChangeThresholdAvailable = msg.getSignalChangeThresholdAvailable(); + + + // Valid Tests + assertEquals(Test.MATCH, Test.GENERAL_STRING, moduleName); + assertEquals(Test.MATCH, Test.GENERAL_BOOLEAN, radioEnableAvailable); + assertEquals(Test.MATCH, Test.GENERAL_BOOLEAN, radioBandAvailable); + assertEquals(Test.MATCH, Test.GENERAL_BOOLEAN, radioFrequencyAvailable); + assertEquals(Test.MATCH, Test.GENERAL_BOOLEAN, hdChannelAvailable); + assertEquals(Test.MATCH, Test.GENERAL_BOOLEAN, rdsDataAvailable); + assertEquals(Test.MATCH, Test.GENERAL_BOOLEAN, availableHDsAvailable); + assertEquals(Test.MATCH, Test.GENERAL_BOOLEAN, stateAvailable); + assertEquals(Test.MATCH, Test.GENERAL_BOOLEAN, signalStrengthAvailable); + assertEquals(Test.MATCH, Test.GENERAL_BOOLEAN, signalChangeThresholdAvailable); + + // Invalid/Null Tests + RadioControlCapabilities msg = new RadioControlCapabilities(); + assertNotNull(Test.NOT_NULL, msg); + + assertNull(Test.NULL, msg.getModuleName()); + assertNull(Test.NULL, msg.getRadioEnableAvailable()); + assertNull(Test.NULL, msg.getRadioBandAvailable()); + assertNull(Test.NULL, msg.getRadioFrequencyAvailable()); + assertNull(Test.NULL, msg.getHdChannelAvailable()); + assertNull(Test.NULL, msg.getRdsDataAvailable()); + assertNull(Test.NULL, msg.getAvailableHDsAvailable()); + assertNull(Test.NULL, msg.getStateAvailable()); + assertNull(Test.NULL, msg.getSignalStrengthAvailable()); + assertNull(Test.NULL, msg.getSignalChangeThresholdAvailable()); + } + + public void testJson(){ + JSONObject reference = new JSONObject(); + + try{ + reference.put(RadioControlCapabilities.KEY_MODULE_NAME, Test.GENERAL_STRING); + reference.put(RadioControlCapabilities.KEY_RADIO_ENABLE_AVAILABLE, Test.GENERAL_BOOLEAN); + reference.put(RadioControlCapabilities.KEY_RADIO_BAND_AVAILABLE, Test.GENERAL_BOOLEAN); + reference.put(RadioControlCapabilities.KEY_RADIO_FREQUENCY_AVAILABLE, Test.GENERAL_BOOLEAN); + reference.put(RadioControlCapabilities.KEY_HD_CHANNEL_AVAILABLE, Test.GENERAL_BOOLEAN); + reference.put(RadioControlCapabilities.KEY_RDS_DATA_AVAILABLE, Test.GENERAL_BOOLEAN); + reference.put(RadioControlCapabilities.KEY_AVAILABLE_HDS_AVAILABLE, Test.GENERAL_BOOLEAN); + reference.put(RadioControlCapabilities.KEY_STATE_AVAILABLE, Test.GENERAL_BOOLEAN); + reference.put(RadioControlCapabilities.KEY_SIGNAL_STRENGTH_AVAILABLE, Test.GENERAL_BOOLEAN); + reference.put(RadioControlCapabilities.KEY_SIGNAL_CHANGE_THRESHOLD_AVAILABLE, Test.GENERAL_BOOLEAN); + + JSONObject underTest = msg.serializeJSON(); + assertEquals(Test.MATCH, reference.length(), underTest.length()); + + Iterator<?> iterator = reference.keys(); + while(iterator.hasNext()){ + String key = (String) iterator.next(); + + assertEquals(Test.MATCH, JsonUtils.readObjectFromJsonObject(reference, key), JsonUtils.readObjectFromJsonObject(underTest, key)); + + } + } catch(JSONException e){ + fail(Test.JSON_FAIL); + } + } +}
\ No newline at end of file diff --git a/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/RadioControlDataTests.java b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/RadioControlDataTests.java new file mode 100644 index 000000000..b42145e8f --- /dev/null +++ b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/RadioControlDataTests.java @@ -0,0 +1,124 @@ +package com.smartdevicelink.test.rpc.datatypes; + +import com.smartdevicelink.marshal.JsonRPCMarshaller; +import com.smartdevicelink.proxy.rpc.RadioControlData; +import com.smartdevicelink.proxy.rpc.RdsData; +import com.smartdevicelink.proxy.rpc.enums.RadioBand; +import com.smartdevicelink.proxy.rpc.enums.RadioState; +import com.smartdevicelink.test.JsonUtils; +import com.smartdevicelink.test.Test; +import com.smartdevicelink.test.Validator; + +import junit.framework.TestCase; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.Hashtable; +import java.util.Iterator; + +/** + * This is a unit test class for the SmartDeviceLink library project class : + * {@link com.smartdevicelink.rpc.RadioControlData} + */ +public class RadioControlDataTests extends TestCase{ + + private RadioControlData msg; + + @Override + public void setUp(){ + msg = new RadioControlData(); + + msg.setFrequencyInteger(Test.GENERAL_INT); + msg.setFrequencyFraction(Test.GENERAL_INT); + msg.setBand(Test.GENERAL_RADIOBAND); + msg.setRdsData(Test.GENERAL_RDSDATA); + msg.setAvailableHDs(Test.GENERAL_INT); + msg.setHdChannel(Test.GENERAL_INT); + msg.setSignalStrength(Test.GENERAL_INT); + msg.setSignalChangeThreshold(Test.GENERAL_INT); + msg.setRadioEnable(Test.GENERAL_BOOLEAN); + msg.setState(Test.GENERAL_RADIOSTATE); + } + + /** + * Tests the expected values of the RPC message. + */ + public void testRpcValues () { + // Test Values + int frequencyInteger = msg.getFrequencyInteger(); + int frequencyFraction = msg.getFrequencyFraction(); + RadioBand band = msg.getBand(); + RdsData rdsData = msg.getRdsData(); + int availableHDs = msg.getAvailableHDs(); + int hdChannel = msg.getHdChannel(); + int signalStrength = msg.getSignalStrength(); + int signalChangeThreshold = msg.getSignalChangeThreshold(); + boolean radioEnable = msg.getRadioEnable(); + RadioState state = msg.getState(); + + // Valid Tests + assertEquals(Test.MATCH, Test.GENERAL_INT, frequencyInteger); + assertEquals(Test.MATCH, Test.GENERAL_INT, frequencyFraction); + assertEquals(Test.MATCH, Test.GENERAL_RADIOBAND, band); + assertTrue(Test.TRUE, Validator.validateRdsData(Test.GENERAL_RDSDATA, rdsData)); + assertEquals(Test.MATCH, Test.GENERAL_INT, availableHDs); + assertEquals(Test.MATCH, Test.GENERAL_INT, hdChannel); + assertEquals(Test.MATCH, Test.GENERAL_INT, signalStrength); + assertEquals(Test.MATCH, Test.GENERAL_INT, signalChangeThreshold); + assertEquals(Test.MATCH, Test.GENERAL_BOOLEAN, radioEnable); + assertEquals(Test.MATCH, Test.GENERAL_RADIOSTATE, state); + + // Invalid/Null Tests + RadioControlData msg = new RadioControlData(); + assertNotNull(Test.NOT_NULL, msg); + + assertNull(Test.NULL, msg.getFrequencyInteger()); + assertNull(Test.NULL, msg.getFrequencyFraction()); + assertNull(Test.NULL, msg.getBand()); + assertNull(Test.NULL, msg.getRdsData()); + assertNull(Test.NULL, msg.getAvailableHDs()); + assertNull(Test.NULL, msg.getHdChannel()); + assertNull(Test.NULL, msg.getSignalStrength()); + assertNull(Test.NULL, msg.getSignalChangeThreshold()); + assertNull(Test.NULL, msg.getRadioEnable()); + assertNull(Test.NULL, msg.getState()); + } + + public void testJson(){ + JSONObject reference = new JSONObject(); + + try{ + reference.put(RadioControlData.KEY_FREQUENCY_INTEGER, Test.GENERAL_INT); + reference.put(RadioControlData.KEY_FREQUENCY_FRACTION, Test.GENERAL_INT); + reference.put(RadioControlData.KEY_BAND, Test.GENERAL_RADIOBAND); + reference.put(RadioControlData.KEY_RDS_DATA, JsonRPCMarshaller.serializeHashtable(Test.GENERAL_RDSDATA.getStore())); + reference.put(RadioControlData.KEY_AVAILABLE_HDS, Test.GENERAL_INT); + reference.put(RadioControlData.KEY_HD_CHANNEL, Test.GENERAL_INT); + reference.put(RadioControlData.KEY_SIGNAL_STRENGTH, Test.GENERAL_INT); + reference.put(RadioControlData.KEY_SIGNAL_CHANGE_THRESHOLD, Test.GENERAL_INT); + reference.put(RadioControlData.KEY_RADIO_ENABLE, Test.GENERAL_BOOLEAN); + reference.put(RadioControlData.KEY_STATE, Test.GENERAL_RADIOSTATE); + + JSONObject underTest = msg.serializeJSON(); + assertEquals(Test.MATCH, reference.length(), underTest.length()); + + Iterator<?> iterator = reference.keys(); + while(iterator.hasNext()){ + String key = (String) iterator.next(); + + if(key.equals(RadioControlData.KEY_RDS_DATA)){ + JSONObject objectEquals = (JSONObject) JsonUtils.readObjectFromJsonObject(reference, key); + JSONObject testEquals = (JSONObject) JsonUtils.readObjectFromJsonObject(underTest, key); + Hashtable<String, Object> hashReference = JsonRPCMarshaller.deserializeJSONObject(objectEquals); + Hashtable<String, Object> hashTest = JsonRPCMarshaller.deserializeJSONObject(testEquals); + assertTrue(Test.TRUE, Validator.validateRadioControlData( new RadioControlData(hashReference), new RadioControlData(hashTest))); + } else{ + assertEquals(Test.MATCH, JsonUtils.readObjectFromJsonObject(reference, key), JsonUtils.readObjectFromJsonObject(underTest, key)); + } + } + } catch(JSONException e){ + fail(Test.JSON_FAIL); + } + } +}
\ No newline at end of file diff --git a/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/RdsDataTests.java b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/RdsDataTests.java new file mode 100644 index 000000000..7414304b0 --- /dev/null +++ b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/RdsDataTests.java @@ -0,0 +1,101 @@ +package com.smartdevicelink.test.rpc.datatypes; + +import com.smartdevicelink.proxy.rpc.RdsData; +import com.smartdevicelink.test.JsonUtils; +import com.smartdevicelink.test.Test; + +import junit.framework.TestCase; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.Iterator; + +/** + * This is a unit test class for the SmartDeviceLink library project class : + * {@link com.smartdevicelink.rpc.RdsData} + */ +public class RdsDataTests extends TestCase{ + + private RdsData msg; + + @Override + public void setUp(){ + msg = new RdsData(); + + msg.setProgramService(Test.GENERAL_STRING); + msg.setRadioText(Test.GENERAL_STRING); + msg.setClockText(Test.GENERAL_STRING); + msg.setProgramIdentification(Test.GENERAL_STRING); + msg.setRegion(Test.GENERAL_STRING); + msg.setTrafficProgram(Test.GENERAL_BOOLEAN); + msg.setTrafficAnnouncement(Test.GENERAL_BOOLEAN); + msg.setProgramType(Test.GENERAL_INT); + } + + /** + * Tests the expected values of the RPC message. + */ + public void testRpcValues () { + // Test Values + String ps = msg.getProgramService(); + String rt = msg.getRadioText(); + String ct = msg.getClockText(); + String pi = msg.getProgramIdentification(); + int pty = msg.getProgramType(); + boolean tp = msg.getTrafficProgram(); + boolean ta = msg.getTrafficAnnouncement(); + String reg = msg.getRegion(); + + // Valid Tests + assertEquals(Test.MATCH, Test.GENERAL_STRING, ps); + assertEquals(Test.MATCH, Test.GENERAL_STRING, rt); + assertEquals(Test.MATCH, Test.GENERAL_STRING, ct); + assertEquals(Test.MATCH, Test.GENERAL_STRING, pi); + assertEquals(Test.MATCH, Test.GENERAL_INT, pty); + assertEquals(Test.MATCH, Test.GENERAL_BOOLEAN, tp); + assertEquals(Test.MATCH, Test.GENERAL_BOOLEAN, ta); + assertEquals(Test.MATCH, Test.GENERAL_STRING, reg); + + // Invalid/Null Tests + RdsData msg = new RdsData(); + assertNotNull(Test.NOT_NULL, msg); + + assertNull(Test.NULL, msg.getProgramService()); + assertNull(Test.NULL, msg.getRadioText()); + assertNull(Test.NULL, msg.getClockText()); + assertNull(Test.NULL, msg.getProgramIdentification()); + assertNull(Test.NULL, msg.getRegion()); + assertNull(Test.NULL, msg.getTrafficProgram()); + assertNull(Test.NULL, msg.getTrafficAnnouncement()); + assertNull(Test.NULL, msg.getProgramType()); + } + + public void testJson(){ + JSONObject reference = new JSONObject(); + + try{ + reference.put(RdsData.KEY_PS, Test.GENERAL_STRING); + reference.put(RdsData.KEY_RT, Test.GENERAL_STRING); + reference.put(RdsData.KEY_CT, Test.GENERAL_STRING); + reference.put(RdsData.KEY_PI, Test.GENERAL_STRING); + reference.put(RdsData.KEY_PTY, Test.GENERAL_INT); + reference.put(RdsData.KEY_TP, Test.GENERAL_BOOLEAN); + reference.put(RdsData.KEY_TA, Test.GENERAL_BOOLEAN); + reference.put(RdsData.KEY_REG, Test.GENERAL_STRING); + + JSONObject underTest = msg.serializeJSON(); + assertEquals(Test.MATCH, reference.length(), underTest.length()); + + Iterator<?> iterator = reference.keys(); + while(iterator.hasNext()){ + String key = (String) iterator.next(); + + assertEquals(Test.MATCH, JsonUtils.readObjectFromJsonObject(reference, key), JsonUtils.readObjectFromJsonObject(underTest, key)); + + } + } catch(JSONException e){ + fail(Test.JSON_FAIL); + } + } +}
\ No newline at end of file diff --git a/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/RemoteControlCapabilitiesTests.java b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/RemoteControlCapabilitiesTests.java new file mode 100644 index 000000000..a15179b8f --- /dev/null +++ b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/RemoteControlCapabilitiesTests.java @@ -0,0 +1,131 @@ +package com.smartdevicelink.test.rpc.datatypes; + +import com.smartdevicelink.marshal.JsonRPCMarshaller; +import com.smartdevicelink.proxy.rpc.ButtonCapabilities; +import com.smartdevicelink.proxy.rpc.ClimateControlCapabilities; +import com.smartdevicelink.proxy.rpc.RadioControlCapabilities; +import com.smartdevicelink.proxy.rpc.RemoteControlCapabilities; +import com.smartdevicelink.test.JsonUtils; +import com.smartdevicelink.test.Test; +import com.smartdevicelink.test.Validator; + +import junit.framework.TestCase; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.List; + +/** + * This is a unit test class for the SmartDeviceLink library project class : + * {@link com.smartdevicelink.rpc.RemoteControlCapabilities} + */ +public class RemoteControlCapabilitiesTests extends TestCase{ + + private RemoteControlCapabilities msg; + + @Override + public void setUp(){ + msg = new RemoteControlCapabilities(); + + msg.setButtonCapabilities(Test.GENERAL_BUTTONCAPABILITIES_LIST); + msg.setRadioControlCapabilities(Test.GENERAL_RADIOCONTROLCAPABILITIES_LIST); + msg.setClimateControlCapabilities(Test.GENERAL_CLIMATECONTROLCAPABILITIES_LIST); + } + + /** + * Tests the expected values of the RPC message. + */ + public void testRpcValues () { + // Test Values + List<ButtonCapabilities> buttonCapabilities = msg.getButtonCapabilities(); + List<RadioControlCapabilities> radioControlCapabilities = msg.getRadioControlCapabilities(); + List<ClimateControlCapabilities> climateControlCapabilities = msg.getClimateControlCapabilities(); + + // Valid Tests + assertEquals(Test.MATCH, Test.GENERAL_BUTTONCAPABILITIES_LIST.size(), buttonCapabilities.size()); + assertEquals(Test.MATCH, Test.GENERAL_RADIOCONTROLCAPABILITIES_LIST.size(), radioControlCapabilities.size()); + assertEquals(Test.MATCH, Test.GENERAL_CLIMATECONTROLCAPABILITIES_LIST.size(), climateControlCapabilities.size()); + + assertTrue(Test.TRUE, Validator.validateButtonCapabilities(Test.GENERAL_BUTTONCAPABILITIES_LIST, buttonCapabilities)); + assertTrue(Test.TRUE, Validator.validateRadioControlCapabilities(Test.GENERAL_RADIOCONTROLCAPABILITIES_LIST, radioControlCapabilities)); + assertTrue(Test.TRUE, Validator.validateClimateControlCapabilities(Test.GENERAL_CLIMATECONTROLCAPABILITIES_LIST, climateControlCapabilities)); + + // Invalid/Null Tests + RemoteControlCapabilities msg = new RemoteControlCapabilities(); + assertNotNull(Test.NOT_NULL, msg); + + assertNull(Test.NULL, msg.getButtonCapabilities()); + assertNull(Test.NULL, msg.getRadioControlCapabilities()); + assertNull(Test.NULL, msg.getClimateControlCapabilities()); + + } + + public void testJson(){ + JSONObject reference = new JSONObject(); + + try{ + reference.put(RemoteControlCapabilities.KEY_BUTTON_CAPABILITIES, Test.JSON_BUTTONCAPABILITIES); + reference.put(RemoteControlCapabilities.KEY_RADIO_CONTROL_CAPABILITIES, Test.JSON_RADIOCONTROLCAPABILITIES); + reference.put(RemoteControlCapabilities.KEY_CLIMATE_CONTROL_CAPABILITIES, Test.JSON_CLIMATECONTROLCAPABILITIES); + + JSONObject underTest = msg.serializeJSON(); + assertEquals(Test.MATCH, reference.length(), underTest.length()); + + Iterator<?> iterator = reference.keys(); + while(iterator.hasNext()){ + String key = (String) iterator.next(); + + if(key.equals(RemoteControlCapabilities.KEY_BUTTON_CAPABILITIES)){ + JSONArray referenceArray = JsonUtils.readJsonArrayFromJsonObject(reference, key); + JSONArray underTestArray = JsonUtils.readJsonArrayFromJsonObject(underTest, key); + assertEquals(Test.MATCH, referenceArray.length(), underTestArray.length()); + + List<ButtonCapabilities> referenceList = new ArrayList<ButtonCapabilities>(); + List<ButtonCapabilities> testList = new ArrayList<ButtonCapabilities>(); + for(int i = 0; i < referenceArray.length(); i++){ + Hashtable<String, Object> hashReference = JsonRPCMarshaller.deserializeJSONObject(referenceArray.getJSONObject(i)); + referenceList.add(new ButtonCapabilities(hashReference)); + Hashtable<String, Object> hashTest= JsonRPCMarshaller.deserializeJSONObject(underTestArray.getJSONObject(i)); + testList.add(new ButtonCapabilities(hashTest)); + } + assertTrue(Test.TRUE, Validator.validateButtonCapabilities(referenceList, testList)); + } else if(key.equals(RemoteControlCapabilities.KEY_RADIO_CONTROL_CAPABILITIES)){ + JSONArray referenceArray = JsonUtils.readJsonArrayFromJsonObject(reference, key); + JSONArray underTestArray = JsonUtils.readJsonArrayFromJsonObject(underTest, key); + assertEquals(Test.MATCH, referenceArray.length(), underTestArray.length()); + + List<RadioControlCapabilities> referenceList = new ArrayList<RadioControlCapabilities>(); + List<RadioControlCapabilities> testList = new ArrayList<RadioControlCapabilities>(); + for(int i = 0; i < referenceArray.length(); i++){ + Hashtable<String, Object> hashReference = JsonRPCMarshaller.deserializeJSONObject(referenceArray.getJSONObject(i)); + referenceList.add(new RadioControlCapabilities(hashReference)); + Hashtable<String, Object> hashTest= JsonRPCMarshaller.deserializeJSONObject(underTestArray.getJSONObject(i)); + testList.add(new RadioControlCapabilities(hashTest)); + } + assertTrue(Test.TRUE, Validator.validateRadioControlCapabilities(referenceList, testList)); + } else if(key.equals(RemoteControlCapabilities.KEY_CLIMATE_CONTROL_CAPABILITIES)){ + JSONArray referenceArray = JsonUtils.readJsonArrayFromJsonObject(reference, key); + JSONArray underTestArray = JsonUtils.readJsonArrayFromJsonObject(underTest, key); + assertEquals(Test.MATCH, referenceArray.length(), underTestArray.length()); + + List<ClimateControlCapabilities> referenceList = new ArrayList<ClimateControlCapabilities>(); + List<ClimateControlCapabilities> testList = new ArrayList<ClimateControlCapabilities>(); + for(int i = 0; i < referenceArray.length(); i++){ + Hashtable<String, Object> hashReference = JsonRPCMarshaller.deserializeJSONObject(referenceArray.getJSONObject(i)); + referenceList.add(new ClimateControlCapabilities(hashReference)); + Hashtable<String, Object> hashTest= JsonRPCMarshaller.deserializeJSONObject(underTestArray.getJSONObject(i)); + testList.add(new ClimateControlCapabilities(hashTest)); + } + assertTrue(Test.TRUE, Validator.validateClimateControlCapabilities(referenceList, testList)); + } + } + } catch(JSONException e){ + fail(Test.JSON_FAIL); + } + } +}
\ No newline at end of file diff --git a/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/SystemCapabilityTests.java b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/SystemCapabilityTests.java index 566b2733e..aa0d75c07 100644 --- a/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/SystemCapabilityTests.java +++ b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/SystemCapabilityTests.java @@ -1,17 +1,27 @@ package com.smartdevicelink.test.rpc.datatypes; +import com.smartdevicelink.marshal.JsonRPCMarshaller; +import com.smartdevicelink.proxy.rpc.NavigationCapability; +import com.smartdevicelink.proxy.rpc.PhoneCapability; +import com.smartdevicelink.proxy.rpc.RemoteControlCapabilities; import com.smartdevicelink.proxy.rpc.SystemCapability; import com.smartdevicelink.proxy.rpc.enums.SystemCapabilityType; import com.smartdevicelink.test.JsonUtils; import com.smartdevicelink.test.Test; +import com.smartdevicelink.test.Validator; import junit.framework.TestCase; import org.json.JSONException; import org.json.JSONObject; +import java.util.Hashtable; import java.util.Iterator; +/** + * This is a unit test class for the SmartDeviceLink library project class : + * {@link com.smartdevicelink.rpc.SystemCapability} + */ public class SystemCapabilityTests extends TestCase { private SystemCapability msg; @@ -21,6 +31,10 @@ public class SystemCapabilityTests extends TestCase { msg = new SystemCapability(); msg.setSystemCapabilityType(Test.GENERAL_SYSTEMCAPABILITYTYPE); + msg.setCapabilityForType(SystemCapabilityType.NAVIGATION, Test.GENERAL_NAVIGATIONCAPABILITY); + msg.setCapabilityForType(SystemCapabilityType.PHONE_CALL, Test.GENERAL_PHONECAPABILITY); + msg.setCapabilityForType(SystemCapabilityType.REMOTE_CONTROL, Test.GENERAL_REMOTECONTROLCAPABILITIES); + } /** @@ -29,15 +43,24 @@ public class SystemCapabilityTests extends TestCase { public void testRpcValues () { // Test Values SystemCapabilityType testType = msg.getSystemCapabilityType(); + NavigationCapability testNavigationCapability = (NavigationCapability) msg.getCapabilityForType(SystemCapabilityType.NAVIGATION); + PhoneCapability testPhoneCapability = (PhoneCapability) msg.getCapabilityForType(SystemCapabilityType.PHONE_CALL); + RemoteControlCapabilities testRemoteControlCapabilities = (RemoteControlCapabilities) msg.getCapabilityForType(SystemCapabilityType.REMOTE_CONTROL); // Valid Tests - assertEquals(Test.MATCH, (SystemCapabilityType) Test.GENERAL_SYSTEMCAPABILITYTYPE, testType); + assertEquals(Test.MATCH, Test.GENERAL_SYSTEMCAPABILITYTYPE, testType); + assertTrue(Test.TRUE, Validator.validateNavigationCapability(Test.GENERAL_NAVIGATIONCAPABILITY, testNavigationCapability)); + assertTrue(Test.TRUE, Validator.validatePhoneCapability(Test.GENERAL_PHONECAPABILITY, testPhoneCapability)); + assertTrue(Test.TRUE, Validator.validateRemoteControlCapabilities(Test.GENERAL_REMOTECONTROLCAPABILITIES, testRemoteControlCapabilities)); // Invalid/Null Tests SystemCapability msg = new SystemCapability(); assertNotNull(Test.NOT_NULL, msg); assertNull(Test.NULL, msg.getSystemCapabilityType()); + assertNull(Test.NULL, msg.getCapabilityForType(SystemCapabilityType.NAVIGATION)); + assertNull(Test.NULL, msg.getCapabilityForType(SystemCapabilityType.PHONE_CALL)); + assertNull(Test.NULL, msg.getCapabilityForType(SystemCapabilityType.REMOTE_CONTROL)); } public void testJson() { @@ -45,6 +68,9 @@ public class SystemCapabilityTests extends TestCase { try { reference.put(SystemCapability.KEY_SYSTEM_CAPABILITY_TYPE, Test.GENERAL_SYSTEMCAPABILITYTYPE); + reference.put(SystemCapability.KEY_NAVIGATION_CAPABILITY, JsonRPCMarshaller.serializeHashtable(Test.GENERAL_NAVIGATIONCAPABILITY.getStore())); + reference.put(SystemCapability.KEY_PHONE_CAPABILITY, JsonRPCMarshaller.serializeHashtable(Test.GENERAL_PHONECAPABILITY.getStore())); + reference.put(SystemCapability.KEY_REMOTE_CONTROL_CAPABILITY, JsonRPCMarshaller.serializeHashtable(Test.GENERAL_REMOTECONTROLCAPABILITIES.getStore())); JSONObject underTest = msg.serializeJSON(); assertEquals(Test.MATCH, reference.length(), underTest.length()); @@ -52,7 +78,28 @@ public class SystemCapabilityTests extends TestCase { Iterator<?> iterator = reference.keys(); while (iterator.hasNext()) { String key = (String) iterator.next(); - assertEquals(Test.MATCH, JsonUtils.readObjectFromJsonObject(reference, key), JsonUtils.readObjectFromJsonObject(underTest, key)); + + if(key.equals(SystemCapability.KEY_NAVIGATION_CAPABILITY)){ + JSONObject objectEquals = (JSONObject) JsonUtils.readObjectFromJsonObject(reference, key); + JSONObject testEquals = (JSONObject) JsonUtils.readObjectFromJsonObject(underTest, key); + Hashtable<String, Object> hashReference = JsonRPCMarshaller.deserializeJSONObject(objectEquals); + Hashtable<String, Object> hashTest = JsonRPCMarshaller.deserializeJSONObject(testEquals); + assertTrue(Test.TRUE, Validator.validateNavigationCapability( new NavigationCapability(hashReference), new NavigationCapability(hashTest))); + } else if(key.equals(SystemCapability.KEY_PHONE_CAPABILITY)){ + JSONObject objectEquals = (JSONObject) JsonUtils.readObjectFromJsonObject(reference, key); + JSONObject testEquals = (JSONObject) JsonUtils.readObjectFromJsonObject(underTest, key); + Hashtable<String, Object> hashReference = JsonRPCMarshaller.deserializeJSONObject(objectEquals); + Hashtable<String, Object> hashTest = JsonRPCMarshaller.deserializeJSONObject(testEquals); + assertTrue(Test.TRUE, Validator.validatePhoneCapability( new PhoneCapability(hashReference), new PhoneCapability(hashTest))); + } else if(key.equals(SystemCapability.KEY_REMOTE_CONTROL_CAPABILITY)){ + JSONObject objectEquals = (JSONObject) JsonUtils.readObjectFromJsonObject(reference, key); + JSONObject testEquals = (JSONObject) JsonUtils.readObjectFromJsonObject(underTest, key); + Hashtable<String, Object> hashReference = JsonRPCMarshaller.deserializeJSONObject(objectEquals); + Hashtable<String, Object> hashTest = JsonRPCMarshaller.deserializeJSONObject(testEquals); + assertTrue(Test.TRUE, Validator.validateRemoteControlCapabilities( new RemoteControlCapabilities(hashReference), new RemoteControlCapabilities(hashTest))); + } else{ + assertEquals(Test.MATCH, JsonUtils.readObjectFromJsonObject(reference, key), JsonUtils.readObjectFromJsonObject(underTest, key)); + } } } catch (JSONException e) { fail(Test.JSON_FAIL); diff --git a/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/TemperatureTests.java b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/TemperatureTests.java new file mode 100644 index 000000000..090f5a235 --- /dev/null +++ b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/TemperatureTests.java @@ -0,0 +1,72 @@ +package com.smartdevicelink.test.rpc.datatypes; + +import com.smartdevicelink.proxy.rpc.Temperature; +import com.smartdevicelink.proxy.rpc.enums.TemperatureUnit; +import com.smartdevicelink.test.JsonUtils; +import com.smartdevicelink.test.Test; + +import junit.framework.TestCase; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.Iterator; + +/** + * This is a unit test class for the SmartDeviceLink library project class : + * {@link com.smartdevicelink.rpc.Temperature} + */ +public class TemperatureTests extends TestCase{ + + private Temperature msg; + + @Override + public void setUp(){ + msg = new Temperature(); + + msg.setUnit(Test.GENERAL_TEMPERATUREUNIT); + msg.setValue(Test.GENERAL_FLOAT); + } + + /** + * Tests the expected values of the RPC message. + */ + public void testRpcValues () { + // Test Values + TemperatureUnit unit = msg.getUnit(); + float value = msg.getValue(); + + // Valid Tests + assertEquals(Test.MATCH, Test.GENERAL_FLOAT, value); + assertEquals(Test.MATCH, Test.GENERAL_TEMPERATUREUNIT, unit); + + // Invalid/Null Tests + Temperature msg = new Temperature(); + assertNotNull(Test.NOT_NULL, msg); + + assertNull(Test.NULL, msg.getUnit()); + assertNull(Test.NULL, msg.getValue()); + } + + public void testJson(){ + JSONObject reference = new JSONObject(); + + try{ + reference.put(Temperature.KEY_VALUE, (Float) Test.GENERAL_FLOAT); + reference.put(Temperature.KEY_UNIT, Test.GENERAL_TEMPERATUREUNIT); + + JSONObject underTest = msg.serializeJSON(); + assertEquals(Test.MATCH, reference.length(), underTest.length()); + + Iterator<?> iterator = reference.keys(); + while(iterator.hasNext()){ + String key = (String) iterator.next(); + + assertEquals(Test.MATCH, JsonUtils.readObjectFromJsonObject(reference, key), JsonUtils.readObjectFromJsonObject(underTest, key)); + + } + } catch(JSONException e){ + fail(Test.JSON_FAIL); + } + } +}
\ No newline at end of file diff --git a/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/AppHmiTypeTests.java b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/AppHmiTypeTests.java index bcaeae93d..6446cb914 100644 --- a/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/AppHmiTypeTests.java +++ b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/AppHmiTypeTests.java @@ -40,6 +40,8 @@ public class AppHmiTypeTests extends TestCase { AppHMIType enumTesting = AppHMIType.valueForString(example); example = "SYSTEM"; AppHMIType enumSystem = AppHMIType.valueForString(example); + example = "REMOTE_CONTROL"; + AppHMIType enumRemoteControl = AppHMIType.valueForString(example); assertNotNull("DEFAULT returned null", enumDefault); assertNotNull("COMMUNICATION returned null", enumCommunication); @@ -52,6 +54,7 @@ public class AppHmiTypeTests extends TestCase { assertNotNull("PROJECTION returned null", enumProjection); assertNotNull("TESTING returned null", enumTesting); assertNotNull("SYSTEM returned null", enumSystem); + assertNotNull("REMOTE_CONTROL returned null", enumRemoteControl); } /** @@ -99,7 +102,8 @@ public class AppHmiTypeTests extends TestCase { enumTestList.add(AppHMIType.BACKGROUND_PROCESS); enumTestList.add(AppHMIType.PROJECTION); enumTestList.add(AppHMIType.TESTING); - enumTestList.add(AppHMIType.SYSTEM); + enumTestList.add(AppHMIType.SYSTEM); + enumTestList.add(AppHMIType.REMOTE_CONTROL); assertTrue("Enum value list does not match enum class list", enumValueList.containsAll(enumTestList) && enumTestList.containsAll(enumValueList)); diff --git a/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/ButtonNameTests.java b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/ButtonNameTests.java index 1db7c4580..e37eb2fd1 100644 --- a/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/ButtonNameTests.java +++ b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/ButtonNameTests.java @@ -52,7 +52,44 @@ public class ButtonNameTests extends TestCase { ButtonName enumCustomButton = ButtonName.valueForString(example); example = "SEARCH"; ButtonName enumSearch = ButtonName.valueForString(example); - + example = "AC_MAX"; + ButtonName enumAcMax = ButtonName.valueForString(example); + example = "AC"; + ButtonName enumAc = ButtonName.valueForString(example); + example = "RECIRCULATE"; + ButtonName enumRecirculate = ButtonName.valueForString(example); + example = "FAN_UP"; + ButtonName enumFanUp = ButtonName.valueForString(example); + example = "FAN_DOWN"; + ButtonName enumFanDown = ButtonName.valueForString(example); + example = "TEMP_UP"; + ButtonName enumTempUp = ButtonName.valueForString(example); + example = "TEMP_DOWN"; + ButtonName enumTempDown = ButtonName.valueForString(example); + example = "DEFROST_MAX"; + ButtonName enumDefrostMax = ButtonName.valueForString(example); + example = "DEFROST"; + ButtonName enumDefrost = ButtonName.valueForString(example); + example = "DEFROST_REAR"; + ButtonName enumDefrostRear = ButtonName.valueForString(example); + example = "UPPER_VENT"; + ButtonName enumUpperVent = ButtonName.valueForString(example); + example = "LOWER_VENT"; + ButtonName enumLowerVent = ButtonName.valueForString(example); + example = "VOLUME_UP"; + ButtonName enumVolumeUp = ButtonName.valueForString(example); + example = "VOLUME_DOWN"; + ButtonName enumVolumeDown = ButtonName.valueForString(example); + example = "EJECT"; + ButtonName enumEject = ButtonName.valueForString(example); + example = "SOURCE"; + ButtonName enumSource = ButtonName.valueForString(example); + example = "SHUFFLE"; + ButtonName enumShuffle = ButtonName.valueForString(example); + example = "REPEAT"; + ButtonName enumRepeat = ButtonName.valueForString(example); + + assertNotNull("OK returned null", enumOk); assertNotNull("SEEKLEFT returned null", enumSeekLeft); @@ -71,6 +108,24 @@ public class ButtonNameTests extends TestCase { assertNotNull("PRESET_9 returned null", enumPreset9); assertNotNull("CUSTOM_BUTTON returned null", enumCustomButton); assertNotNull("SEARCH returned null", enumSearch); + assertNotNull("AC_MAX returned null", enumAcMax); + assertNotNull("AC returned null", enumAc); + assertNotNull("RECIRCULATE returned null", enumRecirculate); + assertNotNull("FAN_UP returned null", enumFanUp); + assertNotNull("FAN_DOWN returned null", enumFanDown); + assertNotNull("TEMP_UP returned null", enumTempUp); + assertNotNull("TEMP_DOWN returned null", enumTempDown); + assertNotNull("DEFROST_MAX returned null", enumDefrostMax); + assertNotNull("DEFROST returned null", enumDefrost); + assertNotNull("DEFROST_REAR returned null", enumDefrostRear); + assertNotNull("UPPER_VENT returned null", enumUpperVent); + assertNotNull("LOWER_VENT returned null", enumLowerVent); + assertNotNull("VOLUME_UP returned null", enumVolumeUp); + assertNotNull("VOLUME_DOWN returned null", enumVolumeDown); + assertNotNull("EJECT returned null", enumEject); + assertNotNull("SOURCE returned null", enumSource); + assertNotNull("SHUFFLE returned null", enumShuffle); + assertNotNull("REPEAT returned null", enumRepeat); } /** @@ -125,7 +180,25 @@ public class ButtonNameTests extends TestCase { enumTestList.add(ButtonName.PRESET_8); enumTestList.add(ButtonName.PRESET_9); enumTestList.add(ButtonName.CUSTOM_BUTTON); - enumTestList.add(ButtonName.SEARCH); + enumTestList.add(ButtonName.SEARCH); + enumTestList.add(ButtonName.AC_MAX); + enumTestList.add(ButtonName.AC); + enumTestList.add(ButtonName.RECIRCULATE); + enumTestList.add(ButtonName.FAN_UP); + enumTestList.add(ButtonName.FAN_DOWN); + enumTestList.add(ButtonName.TEMP_UP); + enumTestList.add(ButtonName.TEMP_DOWN); + enumTestList.add(ButtonName.DEFROST_MAX); + enumTestList.add(ButtonName.DEFROST); + enumTestList.add(ButtonName.DEFROST_REAR); + enumTestList.add(ButtonName.UPPER_VENT); + enumTestList.add(ButtonName.LOWER_VENT); + enumTestList.add(ButtonName.VOLUME_UP); + enumTestList.add(ButtonName.VOLUME_DOWN); + enumTestList.add(ButtonName.EJECT); + enumTestList.add(ButtonName.SOURCE); + enumTestList.add(ButtonName.SHUFFLE); + enumTestList.add(ButtonName.REPEAT); assertTrue("Enum value list does not match enum class list", enumValueList.containsAll(enumTestList) && enumTestList.containsAll(enumValueList)); diff --git a/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/DefrostZoneTests.java b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/DefrostZoneTests.java new file mode 100644 index 000000000..f1f375623 --- /dev/null +++ b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/DefrostZoneTests.java @@ -0,0 +1,79 @@ +package com.smartdevicelink.test.rpc.enums; + +import com.smartdevicelink.proxy.rpc.enums.DefrostZone; + +import junit.framework.TestCase; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * This is a unit test class for the SmartDeviceLink library project class : + * {@link com.smartdevicelink.rpc.enums.DefrostZone} + */ +public class DefrostZoneTests extends TestCase { + + /** + * Verifies that the enum values are not null upon valid assignment. + */ + public void testValidEnums () { + String example = "FRONT"; + DefrostZone enumFront = DefrostZone.valueForString(example); + example = "REAR"; + DefrostZone enumRear = DefrostZone.valueForString(example); + example = "ALL"; + DefrostZone enumAll = DefrostZone.valueForString(example); + example = "NONE"; + DefrostZone enumNone = DefrostZone.valueForString(example); + + assertNotNull("FRONT returned null", enumFront); + assertNotNull("REAR returned null", enumRear); + assertNotNull("ALL returned null", enumAll); + assertNotNull("NONE returned null", enumNone); + } + + /** + * Verifies that an invalid assignment is null. + */ + public void testInvalidEnum () { + String example = "fRONT"; + try { + DefrostZone temp = DefrostZone.valueForString(example); + assertNull("Result of valueForString should be null.", temp); + } + catch (IllegalArgumentException exception) { + fail("Invalid enum throws IllegalArgumentException."); + } + } + + /** + * Verifies that a null assignment is invalid. + */ + public void testNullEnum () { + String example = null; + try { + DefrostZone temp = DefrostZone.valueForString(example); + assertNull("Result of valueForString should be null.", temp); + } + catch (NullPointerException exception) { + fail("Null string throws NullPointerException."); + } + } + + /** + * Verifies the possible enum values of DefrostZone. + */ + public void testListEnum() { + List<DefrostZone> enumValueList = Arrays.asList(DefrostZone.values()); + + List<DefrostZone> enumTestList = new ArrayList<DefrostZone>(); + enumTestList.add(DefrostZone.FRONT); + enumTestList.add(DefrostZone.REAR); + enumTestList.add(DefrostZone.ALL); + enumTestList.add(DefrostZone.NONE); + + assertTrue("Enum value list does not match enum class list", + enumValueList.containsAll(enumTestList) && enumTestList.containsAll(enumValueList)); + } +}
\ No newline at end of file diff --git a/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/ModuleTypeTests.java b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/ModuleTypeTests.java new file mode 100644 index 000000000..18a47b79d --- /dev/null +++ b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/ModuleTypeTests.java @@ -0,0 +1,71 @@ +package com.smartdevicelink.test.rpc.enums; + +import com.smartdevicelink.proxy.rpc.enums.ModuleType; + +import junit.framework.TestCase; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * This is a unit test class for the SmartDeviceLink library project class : + * {@link com.smartdevicelink.rpc.enums.ModuleType} + */ +public class ModuleTypeTests extends TestCase { + + /** + * Verifies that the enum values are not null upon valid assignment. + */ + public void testValidEnums () { + String example = "CLIMATE"; + ModuleType enumClimate = ModuleType.valueForString(example); + example = "RADIO"; + ModuleType enumRadio = ModuleType.valueForString(example); + + assertNotNull("CLIMATE returned null", enumClimate); + assertNotNull("RADIO returned null", enumRadio); + } + + /** + * Verifies that an invalid assignment is null. + */ + public void testInvalidEnum () { + String example = "cLIMATE"; + try { + ModuleType temp = ModuleType.valueForString(example); + assertNull("Result of valueForString should be null.", temp); + } + catch (IllegalArgumentException exception) { + fail("Invalid enum throws IllegalArgumentException."); + } + } + + /** + * Verifies that a null assignment is invalid. + */ + public void testNullEnum () { + String example = null; + try { + ModuleType temp = ModuleType.valueForString(example); + assertNull("Result of valueForString should be null.", temp); + } + catch (NullPointerException exception) { + fail("Null string throws NullPointerException."); + } + } + + /** + * Verifies the possible enum values of ModuleType. + */ + public void testListEnum() { + List<ModuleType> enumValueList = Arrays.asList(ModuleType.values()); + + List<ModuleType> enumTestList = new ArrayList<ModuleType>(); + enumTestList.add(ModuleType.CLIMATE); + enumTestList.add(ModuleType.RADIO); + + assertTrue("Enum value list does not match enum class list", + enumValueList.containsAll(enumTestList) && enumTestList.containsAll(enumValueList)); + } +}
\ No newline at end of file diff --git a/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/RadioBandTests.java b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/RadioBandTests.java new file mode 100644 index 000000000..cc5d5b700 --- /dev/null +++ b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/RadioBandTests.java @@ -0,0 +1,75 @@ +package com.smartdevicelink.test.rpc.enums; + +import com.smartdevicelink.proxy.rpc.enums.RadioBand; + +import junit.framework.TestCase; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * This is a unit test class for the SmartDeviceLink library project class : + * {@link com.smartdevicelink.rpc.enums.RadioBand} + */ +public class RadioBandTests extends TestCase { + + /** + * Verifies that the enum values are not null upon valid assignment. + */ + public void testValidEnums () { + String example = "AM"; + RadioBand enumAm = RadioBand.valueForString(example); + example = "FM"; + RadioBand enumFm = RadioBand.valueForString(example); + example = "XM"; + RadioBand enumXm = RadioBand.valueForString(example); + + assertNotNull("AM returned null", enumAm); + assertNotNull("FM returned null", enumFm); + assertNotNull("XM returned null", enumXm); + } + + /** + * Verifies that an invalid assignment is null. + */ + public void testInvalidEnum () { + String example = "aM"; + try { + RadioBand temp = RadioBand.valueForString(example); + assertNull("Result of valueForString should be null.", temp); + } + catch (IllegalArgumentException exception) { + fail("Invalid enum throws IllegalArgumentException."); + } + } + + /** + * Verifies that a null assignment is invalid. + */ + public void testNullEnum () { + String example = null; + try { + RadioBand temp = RadioBand.valueForString(example); + assertNull("Result of valueForString should be null.", temp); + } + catch (NullPointerException exception) { + fail("Null string throws NullPointerException."); + } + } + + /** + * Verifies the possible enum values of RadioBand. + */ + public void testListEnum() { + List<RadioBand> enumValueList = Arrays.asList(RadioBand.values()); + + List<RadioBand> enumTestList = new ArrayList<RadioBand>(); + enumTestList.add(RadioBand.AM); + enumTestList.add(RadioBand.FM); + enumTestList.add(RadioBand.XM); + + assertTrue("Enum value list does not match enum class list", + enumValueList.containsAll(enumTestList) && enumTestList.containsAll(enumValueList)); + } +}
\ No newline at end of file diff --git a/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/RadioStateTests.java b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/RadioStateTests.java new file mode 100644 index 000000000..d16f00599 --- /dev/null +++ b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/RadioStateTests.java @@ -0,0 +1,79 @@ +package com.smartdevicelink.test.rpc.enums; + +import com.smartdevicelink.proxy.rpc.enums.RadioState; + +import junit.framework.TestCase; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * This is a unit test class for the SmartDeviceLink library project class : + * {@link com.smartdevicelink.rpc.enums.RadioState} + */ +public class RadioStateTests extends TestCase { + + /** + * Verifies that the enum values are not null upon valid assignment. + */ + public void testValidEnums () { + String example = "ACQUIRING"; + RadioState enumAcquiring = RadioState.valueForString(example); + example = "ACQUIRED"; + RadioState enumAcquired = RadioState.valueForString(example); + example = "MULTICAST"; + RadioState enumMultiCast = RadioState.valueForString(example); + example = "NOT_FOUND"; + RadioState enumNotFound = RadioState.valueForString(example); + + assertNotNull("ACQUIRING returned null", enumAcquiring); + assertNotNull("ACQUIRED returned null", enumAcquired); + assertNotNull("MULTICAST returned null", enumMultiCast); + assertNotNull("NOT_FOUND returned null", enumNotFound); + } + + /** + * Verifies that an invalid assignment is null. + */ + public void testInvalidEnum () { + String example = "aCQUIRING"; + try { + RadioState temp = RadioState.valueForString(example); + assertNull("Result of valueForString should be null.", temp); + } + catch (IllegalArgumentException exception) { + fail("Invalid enum throws IllegalArgumentException."); + } + } + + /** + * Verifies that a null assignment is invalid. + */ + public void testNullEnum () { + String example = null; + try { + RadioState temp = RadioState.valueForString(example); + assertNull("Result of valueForString should be null.", temp); + } + catch (NullPointerException exception) { + fail("Null string throws NullPointerException."); + } + } + + /** + * Verifies the possible enum values of RadioState. + */ + public void testListEnum() { + List<RadioState> enumValueList = Arrays.asList(RadioState.values()); + + List<RadioState> enumTestList = new ArrayList<RadioState>(); + enumTestList.add(RadioState.ACQUIRING); + enumTestList.add(RadioState.ACQUIRED); + enumTestList.add(RadioState.MULTICAST); + enumTestList.add(RadioState.NOT_FOUND); + + assertTrue("Enum value list does not match enum class list", + enumValueList.containsAll(enumTestList) && enumTestList.containsAll(enumValueList)); + } +}
\ No newline at end of file diff --git a/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/ResultTests.java b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/ResultTests.java index 3eaae9937..5156c4f44 100644 --- a/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/ResultTests.java +++ b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/ResultTests.java @@ -82,6 +82,10 @@ public class ResultTests extends TestCase { Result enumExpiredCert = Result.valueForString(example); example = "RESUME_FAILED"; Result enumResumeFailed = Result.valueForString(example); + example = "DATA_NOT_AVAILABLE"; + Result enumDataNotAvailable = Result.valueForString(example); + example = "READ_ONLY"; + Result enumReadOnly = Result.valueForString(example); assertNotNull("SUCCESS returned null", enumSuccess); assertNotNull("INVALID_DATA returned null", enumInvalidData); @@ -115,6 +119,8 @@ public class ResultTests extends TestCase { assertNotNull("INVALID_CERT returned null", enumInvalidCert); assertNotNull("EXPIRED_CERT returned null", enumExpiredCert); assertNotNull("RESUME_FAILED returned null", enumResumeFailed); + assertNotNull("DATA_NOT_AVAILABLE returned null", enumDataNotAvailable); + assertNotNull("READ_ONLY returned null", enumReadOnly); } /** @@ -183,7 +189,9 @@ public class ResultTests extends TestCase { enumTestList.add(Result.SAVED); enumTestList.add(Result.INVALID_CERT); enumTestList.add(Result.EXPIRED_CERT); - enumTestList.add(Result.RESUME_FAILED); + enumTestList.add(Result.RESUME_FAILED); + enumTestList.add(Result.DATA_NOT_AVAILABLE); + enumTestList.add(Result.READ_ONLY); assertTrue("Enum value list does not match enum class list", enumValueList.containsAll(enumTestList) && enumTestList.containsAll(enumValueList)); diff --git a/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/SystemCapabilityTypeTests.java b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/SystemCapabilityTypeTests.java new file mode 100644 index 000000000..f17f3cbd3 --- /dev/null +++ b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/SystemCapabilityTypeTests.java @@ -0,0 +1,115 @@ +package com.smartdevicelink.test.rpc.enums; + +import com.smartdevicelink.proxy.rpc.enums.SystemCapabilityType; + +import junit.framework.TestCase; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * This is a unit test class for the SmartDeviceLink library project class : + * {@link com.smartdevicelink.rpc.enums.SystemCapabilityType} + */ +public class SystemCapabilityTypeTests extends TestCase { + + /** + * Verifies that the enum values are not null upon valid assignment. + */ + public void testValidEnums () { + String example = "NAVIGATION"; + SystemCapabilityType enumNavigation = SystemCapabilityType.valueForString(example); + example = "PHONE_CALL"; + SystemCapabilityType enumPhoneCall = SystemCapabilityType.valueForString(example); + example = "VIDEO_STREAMING"; + SystemCapabilityType enumVideoStreaming = SystemCapabilityType.valueForString(example); + example = "REMOTE_CONTROL"; + SystemCapabilityType enumRemoteControl = SystemCapabilityType.valueForString(example); + example = "HMI"; + SystemCapabilityType enumHmi = SystemCapabilityType.valueForString(example); + example = "DISPLAY"; + SystemCapabilityType enumDisplay = SystemCapabilityType.valueForString(example); + example = "AUDIO_PASSTHROUGH"; + SystemCapabilityType enumAudioPassThrough = SystemCapabilityType.valueForString(example); + example = "BUTTON"; + SystemCapabilityType enumButton = SystemCapabilityType.valueForString(example); + example = "HMI_ZONE"; + SystemCapabilityType enumHmiZone = SystemCapabilityType.valueForString(example); + example = "PRESET_BANK"; + SystemCapabilityType enumPresetBank = SystemCapabilityType.valueForString(example); + example = "SOFTBUTTON"; + SystemCapabilityType enumSoftButton = SystemCapabilityType.valueForString(example); + example = "SPEECH"; + SystemCapabilityType enumSpeech = SystemCapabilityType.valueForString(example); + example = "VOICE_RECOGNITION"; + SystemCapabilityType enumVoiceRecognition = SystemCapabilityType.valueForString(example); + + assertNotNull("NAVIGATION returned null", enumNavigation); + assertNotNull("PHONE_CALL returned null", enumPhoneCall); + assertNotNull("VIDEO_STREAMING returned null", enumVideoStreaming); + assertNotNull("REMOTE_CONTROL returned null", enumRemoteControl); + assertNotNull("HMI returned null", enumHmi); + assertNotNull("DISPLAY returned null", enumDisplay); + assertNotNull("AUDIO_PASSTHROUGH returned null", enumAudioPassThrough); + assertNotNull("BUTTON returned null", enumButton); + assertNotNull("HMI_ZONE returned null", enumHmiZone); + assertNotNull("PRESET_BANK returned null", enumPresetBank); + assertNotNull("SOFTBUTTON returned null", enumSoftButton); + assertNotNull("SPEECH returned null", enumSpeech); + assertNotNull("VOICE_RECOGNITION returned null", enumVoiceRecognition); + } + + /** + * Verifies that an invalid assignment is null. + */ + public void testInvalidEnum () { + String example = "nAVIGATION"; + try { + SystemCapabilityType temp = SystemCapabilityType.valueForString(example); + assertNull("Result of valueForString should be null.", temp); + } + catch (IllegalArgumentException exception) { + fail("Invalid enum throws IllegalArgumentException."); + } + } + + /** + * Verifies that a null assignment is invalid. + */ + public void testNullEnum () { + String example = null; + try { + SystemCapabilityType temp = SystemCapabilityType.valueForString(example); + assertNull("Result of valueForString should be null.", temp); + } + catch (NullPointerException exception) { + fail("Null string throws NullPointerException."); + } + } + + /** + * Verifies the possible enum values of SystemCapabilityType. + */ + public void testListEnum() { + List<SystemCapabilityType> enumValueList = Arrays.asList(SystemCapabilityType.values()); + + List<SystemCapabilityType> enumTestList = new ArrayList<SystemCapabilityType>(); + enumTestList.add(SystemCapabilityType.NAVIGATION); + enumTestList.add(SystemCapabilityType.PHONE_CALL); + enumTestList.add(SystemCapabilityType.VIDEO_STREAMING); + enumTestList.add(SystemCapabilityType.REMOTE_CONTROL); + enumTestList.add(SystemCapabilityType.HMI); + enumTestList.add(SystemCapabilityType.DISPLAY); + enumTestList.add(SystemCapabilityType.AUDIO_PASSTHROUGH); + enumTestList.add(SystemCapabilityType.BUTTON); + enumTestList.add(SystemCapabilityType.HMI_ZONE); + enumTestList.add(SystemCapabilityType.PRESET_BANK); + enumTestList.add(SystemCapabilityType.SOFTBUTTON); + enumTestList.add(SystemCapabilityType.SPEECH); + enumTestList.add(SystemCapabilityType.VOICE_RECOGNITION); + + assertTrue("Enum value list does not match enum class list", + enumValueList.containsAll(enumTestList) && enumTestList.containsAll(enumValueList)); + } +}
\ No newline at end of file diff --git a/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/VentilationModeTests.java b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/VentilationModeTests.java new file mode 100644 index 000000000..561e66a77 --- /dev/null +++ b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/VentilationModeTests.java @@ -0,0 +1,79 @@ +package com.smartdevicelink.test.rpc.enums; + +import com.smartdevicelink.proxy.rpc.enums.VentilationMode; + +import junit.framework.TestCase; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * This is a unit test class for the SmartDeviceLink library project class : + * {@link com.smartdevicelink.rpc.enums.VentilationMode} + */ +public class VentilationModeTests extends TestCase { + + /** + * Verifies that the enum values are not null upon valid assignment. + */ + public void testValidEnums () { + String example = "UPPER"; + VentilationMode enumUpper = VentilationMode.valueForString(example); + example = "LOWER"; + VentilationMode enumLower = VentilationMode.valueForString(example); + example = "BOTH"; + VentilationMode enumBoth = VentilationMode.valueForString(example); + example = "NONE"; + VentilationMode enumNone = VentilationMode.valueForString(example); + + assertNotNull("UPPER returned null", enumUpper); + assertNotNull("LOWER returned null", enumLower); + assertNotNull("BOTH returned null", enumBoth); + assertNotNull("NONE returned null", enumNone); + } + + /** + * Verifies that an invalid assignment is null. + */ + public void testInvalidEnum () { + String example = "uPPER"; + try { + VentilationMode temp = VentilationMode.valueForString(example); + assertNull("Result of valueForString should be null.", temp); + } + catch (IllegalArgumentException exception) { + fail("Invalid enum throws IllegalArgumentException."); + } + } + + /** + * Verifies that a null assignment is invalid. + */ + public void testNullEnum () { + String example = null; + try { + VentilationMode temp = VentilationMode.valueForString(example); + assertNull("Result of valueForString should be null.", temp); + } + catch (NullPointerException exception) { + fail("Null string throws NullPointerException."); + } + } + + /** + * Verifies the possible enum values of VentilationMode. + */ + public void testListEnum() { + List<VentilationMode> enumValueList = Arrays.asList(VentilationMode.values()); + + List<VentilationMode> enumTestList = new ArrayList<VentilationMode>(); + enumTestList.add(VentilationMode.UPPER); + enumTestList.add(VentilationMode.LOWER); + enumTestList.add(VentilationMode.BOTH); + enumTestList.add(VentilationMode.NONE); + + assertTrue("Enum value list does not match enum class list", + enumValueList.containsAll(enumTestList) && enumTestList.containsAll(enumValueList)); + } +}
\ No newline at end of file diff --git a/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/notifications/OnInteriorVehicleDataTests.java b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/notifications/OnInteriorVehicleDataTests.java new file mode 100644 index 000000000..4fded53fe --- /dev/null +++ b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/notifications/OnInteriorVehicleDataTests.java @@ -0,0 +1,69 @@ +package com.smartdevicelink.test.rpc.notifications; + +import com.smartdevicelink.marshal.JsonRPCMarshaller; +import com.smartdevicelink.protocol.enums.FunctionID; +import com.smartdevicelink.proxy.RPCMessage; +import com.smartdevicelink.proxy.rpc.ModuleData; +import com.smartdevicelink.proxy.rpc.OnInteriorVehicleData; +import com.smartdevicelink.test.BaseRpcTests; +import com.smartdevicelink.test.Test; +import com.smartdevicelink.test.Validator; + +import org.json.JSONException; +import org.json.JSONObject; + +/** + * This is a unit test class for the SmartDeviceLink library project class : + * {@link com.smartdevicelink.rpc.OnInteriorVehicleData} + */ +public class OnInteriorVehicleDataTests extends BaseRpcTests{ + + @Override + protected RPCMessage createMessage(){ + OnInteriorVehicleData msg = new OnInteriorVehicleData(); + msg.setModuleData(Test.GENERAL_MODULEDATA); + + return msg; + } + + @Override + protected String getMessageType(){ + return RPCMessage.KEY_NOTIFICATION; + } + + @Override + protected String getCommandType(){ + return FunctionID.ON_INTERIOR_VEHICLE_DATA.toString(); + } + + @Override + protected JSONObject getExpectedParameters(int sdlVersion){ + JSONObject result = new JSONObject(); + + try{ + result.put(OnInteriorVehicleData.KEY_MODULE_DATA, JsonRPCMarshaller.serializeHashtable(Test.GENERAL_MODULEDATA.getStore())); + }catch(JSONException e){ + fail(Test.JSON_FAIL); + } + + return result; + } + + /** + * Tests the expected values of the RPC message. + */ + public void testRpcValues () { + // Test Values + ModuleData moduleData = ( (OnInteriorVehicleData) msg ).getModuleData(); + + // Valid Tests + assertTrue(Test.TRUE, Validator.validateModuleData(Test.GENERAL_MODULEDATA, moduleData)); + + // Invalid/Null Tests + OnInteriorVehicleData msg = new OnInteriorVehicleData(); + assertNotNull(Test.NOT_NULL, msg); + testNullBase(msg); + + assertNull(Test.NULL, msg.getModuleData()); + } +}
\ No newline at end of file diff --git a/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/requests/ButtonPressTests.java b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/requests/ButtonPressTests.java new file mode 100644 index 000000000..f16a3a87c --- /dev/null +++ b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/requests/ButtonPressTests.java @@ -0,0 +1,113 @@ +package com.smartdevicelink.test.rpc.requests; + +import com.smartdevicelink.marshal.JsonRPCMarshaller; +import com.smartdevicelink.protocol.enums.FunctionID; +import com.smartdevicelink.proxy.RPCMessage; +import com.smartdevicelink.proxy.rpc.ButtonPress; +import com.smartdevicelink.proxy.rpc.enums.ButtonName; +import com.smartdevicelink.proxy.rpc.enums.ButtonPressMode; +import com.smartdevicelink.proxy.rpc.enums.ModuleType; +import com.smartdevicelink.test.BaseRpcTests; +import com.smartdevicelink.test.JsonUtils; +import com.smartdevicelink.test.Test; +import com.smartdevicelink.test.json.rpc.JsonFileReader; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.Hashtable; + +/** + * This is a unit test class for the SmartDeviceLink library project class : + * {@link com.smartdevicelink.rpc.ButtonPress} + */ +public class ButtonPressTests extends BaseRpcTests { + + @Override + protected RPCMessage createMessage(){ + ButtonPress msg = new ButtonPress(); + + msg.setModuleType(Test.GENERAL_MODULETYPE); + msg.setButtonPressMode(Test.GENERAL_BUTTONPRESSMODE); + msg.setButtonName(Test.GENERAL_BUTTONNAME); + + return msg; + } + + @Override + protected String getMessageType(){ + return RPCMessage.KEY_REQUEST; + } + + @Override + protected String getCommandType(){ + return FunctionID.BUTTON_PRESS.toString(); + } + + @Override + protected JSONObject getExpectedParameters(int sdlVersion){ + JSONObject result = new JSONObject(); + + try{ + result.put(ButtonPress.KEY_MODULE_TYPE, Test.GENERAL_MODULETYPE); + result.put(ButtonPress.KEY_BUTTON_NAME, Test.GENERAL_BUTTONNAME); + result.put(ButtonPress.KEY_BUTTON_PRESS_MODE, Test.GENERAL_BUTTONPRESSMODE); + }catch(JSONException e){ + fail(Test.JSON_FAIL); + } + + return result; + } + + /** + * Tests the expected values of the RPC message. + */ + public void testRpcValues () { + // Test Values + ModuleType testModuleType = ( (ButtonPress) msg ).getModuleType(); + ButtonName testButtonName = ( (ButtonPress) msg ).getButtonName(); + ButtonPressMode testButtonPressMode = ( (ButtonPress) msg ).getButtonPressMode(); + + // Valid Tests + assertEquals(Test.MATCH, Test.GENERAL_MODULETYPE, testModuleType); + assertEquals(Test.MATCH, Test.GENERAL_BUTTONNAME, testButtonName); + assertEquals(Test.MATCH, Test.GENERAL_BUTTONPRESSMODE, testButtonPressMode); + + // Invalid/Null Tests + ButtonPress msg = new ButtonPress(); + assertNotNull(Test.NOT_NULL, msg); + testNullBase(msg); + + assertNull(Test.NULL, msg.getModuleType()); + assertNull(Test.NULL, msg.getButtonName()); + assertNull(Test.NULL, msg.getButtonPressMode()); + } + + /** + * Tests a valid JSON construction of this RPC message. + */ + public void testJsonConstructor () { + JSONObject commandJson = JsonFileReader.readId(this.mContext, getCommandType(), getMessageType()); + assertNotNull(Test.NOT_NULL, commandJson); + + try { + Hashtable<String, Object> hash = JsonRPCMarshaller.deserializeJSONObject(commandJson); + ButtonPress cmd = new ButtonPress(hash); + + JSONObject body = JsonUtils.readJsonObjectFromJsonObject(commandJson, getMessageType()); + assertNotNull(Test.NOT_NULL, body); + + // Test everything in the json body. + assertEquals(Test.MATCH, JsonUtils.readStringFromJsonObject(body, RPCMessage.KEY_FUNCTION_NAME), cmd.getFunctionName()); + assertEquals(Test.MATCH, JsonUtils.readIntegerFromJsonObject(body, RPCMessage.KEY_CORRELATION_ID), cmd.getCorrelationID()); + + JSONObject parameters = JsonUtils.readJsonObjectFromJsonObject(body, RPCMessage.KEY_PARAMETERS); + + assertEquals(Test.MATCH, JsonUtils.readObjectFromJsonObject(parameters, ButtonPress.KEY_MODULE_TYPE).toString(), cmd.getModuleType().toString()); + assertEquals(Test.MATCH, JsonUtils.readObjectFromJsonObject(parameters, ButtonPress.KEY_BUTTON_NAME).toString(), cmd.getButtonName().toString()); + assertEquals(Test.MATCH, JsonUtils.readObjectFromJsonObject(parameters, ButtonPress.KEY_BUTTON_PRESS_MODE).toString(), cmd.getButtonPressMode().toString()); + }catch (JSONException e) { + fail(Test.JSON_FAIL); + } + } +}
\ No newline at end of file diff --git a/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/requests/GetInteriorVehicleDataTests.java b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/requests/GetInteriorVehicleDataTests.java new file mode 100644 index 000000000..5a08d4266 --- /dev/null +++ b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/requests/GetInteriorVehicleDataTests.java @@ -0,0 +1,105 @@ +package com.smartdevicelink.test.rpc.requests; + +import com.smartdevicelink.marshal.JsonRPCMarshaller; +import com.smartdevicelink.protocol.enums.FunctionID; +import com.smartdevicelink.proxy.RPCMessage; +import com.smartdevicelink.proxy.rpc.GetInteriorVehicleData; +import com.smartdevicelink.proxy.rpc.enums.ModuleType; +import com.smartdevicelink.test.BaseRpcTests; +import com.smartdevicelink.test.JsonUtils; +import com.smartdevicelink.test.Test; +import com.smartdevicelink.test.json.rpc.JsonFileReader; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.Hashtable; + +/** + * This is a unit test class for the SmartDeviceLink library project class : + * {@link com.smartdevicelink.rpc.GetInteriorVehicleData} + */ +public class GetInteriorVehicleDataTests extends BaseRpcTests { + + @Override + protected RPCMessage createMessage(){ + GetInteriorVehicleData msg = new GetInteriorVehicleData(); + + msg.setModuleType(Test.GENERAL_MODULETYPE); + msg.setSubscribe(Test.GENERAL_BOOLEAN); + + return msg; + } + + @Override + protected String getMessageType(){ + return RPCMessage.KEY_REQUEST; + } + + @Override + protected String getCommandType(){ + return FunctionID.GET_INTERIOR_VEHICLE_DATA.toString(); + } + + @Override + protected JSONObject getExpectedParameters(int sdlVersion){ + JSONObject result = new JSONObject(); + + try{ + result.put(GetInteriorVehicleData.KEY_MODULE_TYPE, Test.GENERAL_MODULETYPE); + result.put(GetInteriorVehicleData.KEY_SUBSCRIBE, Test.GENERAL_BOOLEAN); + }catch(JSONException e){ + fail(Test.JSON_FAIL); + } + + return result; + } + + /** + * Tests the expected values of the RPC message. + */ + public void testRpcValues () { + // Test Values + ModuleType testModuleType = ( (GetInteriorVehicleData) msg ).getModuleType(); + boolean testSubscribed = ( (GetInteriorVehicleData) msg ).getSubscribe(); + + // Valid Tests + assertEquals(Test.MATCH, Test.GENERAL_MODULETYPE, testModuleType); + assertEquals(Test.MATCH, Test.GENERAL_BOOLEAN, testSubscribed); + + // Invalid/Null Tests + GetInteriorVehicleData msg = new GetInteriorVehicleData(); + assertNotNull(Test.NOT_NULL, msg); + testNullBase(msg); + + assertNull(Test.NULL, msg.getModuleType()); + assertNull(Test.NULL, msg.getSubscribe()); + } + + /** + * Tests a valid JSON construction of this RPC message. + */ + public void testJsonConstructor () { + JSONObject commandJson = JsonFileReader.readId(this.mContext, getCommandType(), getMessageType()); + assertNotNull(Test.NOT_NULL, commandJson); + + try { + Hashtable<String, Object> hash = JsonRPCMarshaller.deserializeJSONObject(commandJson); + GetInteriorVehicleData cmd = new GetInteriorVehicleData(hash); + + JSONObject body = JsonUtils.readJsonObjectFromJsonObject(commandJson, getMessageType()); + assertNotNull(Test.NOT_NULL, body); + + // Test everything in the json body. + assertEquals(Test.MATCH, JsonUtils.readStringFromJsonObject(body, RPCMessage.KEY_FUNCTION_NAME), cmd.getFunctionName()); + assertEquals(Test.MATCH, JsonUtils.readIntegerFromJsonObject(body, RPCMessage.KEY_CORRELATION_ID), cmd.getCorrelationID()); + + JSONObject parameters = JsonUtils.readJsonObjectFromJsonObject(body, RPCMessage.KEY_PARAMETERS); + + assertEquals(Test.MATCH, JsonUtils.readObjectFromJsonObject(parameters, GetInteriorVehicleData.KEY_MODULE_TYPE).toString(), cmd.getModuleType().toString()); + assertEquals(Test.MATCH, JsonUtils.readObjectFromJsonObject(parameters, GetInteriorVehicleData.KEY_SUBSCRIBE), cmd.getSubscribe()); + }catch (JSONException e) { + fail(Test.JSON_FAIL); + } + } +}
\ No newline at end of file diff --git a/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/requests/SetInteriorVehicleDataTests.java b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/requests/SetInteriorVehicleDataTests.java new file mode 100644 index 000000000..f5ecb0d06 --- /dev/null +++ b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/requests/SetInteriorVehicleDataTests.java @@ -0,0 +1,102 @@ +package com.smartdevicelink.test.rpc.requests; + +import com.smartdevicelink.marshal.JsonRPCMarshaller; +import com.smartdevicelink.protocol.enums.FunctionID; +import com.smartdevicelink.proxy.RPCMessage; +import com.smartdevicelink.proxy.rpc.ModuleData; +import com.smartdevicelink.proxy.rpc.SetInteriorVehicleData; +import com.smartdevicelink.test.BaseRpcTests; +import com.smartdevicelink.test.JsonUtils; +import com.smartdevicelink.test.Test; +import com.smartdevicelink.test.Validator; +import com.smartdevicelink.test.json.rpc.JsonFileReader; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.Hashtable; + +/** + * This is a unit test class for the SmartDeviceLink library project class : + * {@link com.smartdevicelink.rpc.SetInteriorVehicleData} + */ +public class SetInteriorVehicleDataTests extends BaseRpcTests { + + @Override + protected RPCMessage createMessage(){ + SetInteriorVehicleData msg = new SetInteriorVehicleData(); + + msg.setModuleData(Test.GENERAL_MODULEDATA); + + return msg; + } + + @Override + protected String getMessageType(){ + return RPCMessage.KEY_REQUEST; + } + + @Override + protected String getCommandType(){ + return FunctionID.SET_INTERIOR_VEHICLE_DATA.toString(); + } + + @Override + protected JSONObject getExpectedParameters(int sdlVersion){ + JSONObject result = new JSONObject(); + + try{ + result.put(SetInteriorVehicleData.KEY_MODULE_DATA, JsonRPCMarshaller.serializeHashtable(Test.GENERAL_MODULEDATA.getStore())); + }catch(JSONException e){ + fail(Test.JSON_FAIL); + } + + return result; + } + + /** + * Tests the expected values of the RPC message. + */ + public void testRpcValues () { + // Test Values + ModuleData testModuleData = ( (SetInteriorVehicleData) msg ).getModuleData(); + + // Valid Tests + assertTrue(Test.TRUE, Validator.validateModuleData(Test.GENERAL_MODULEDATA, testModuleData)); + + // Invalid/Null Tests + SetInteriorVehicleData msg = new SetInteriorVehicleData(); + assertNotNull(Test.NOT_NULL, msg); + testNullBase(msg); + + assertNull(Test.NULL, msg.getModuleData()); + } + + /** + * Tests a valid JSON construction of this RPC message. + */ + public void testJsonConstructor () { + JSONObject commandJson = JsonFileReader.readId(this.mContext, getCommandType(), getMessageType()); + assertNotNull(Test.NOT_NULL, commandJson); + + try { + Hashtable<String, Object> hash = JsonRPCMarshaller.deserializeJSONObject(commandJson); + SetInteriorVehicleData cmd = new SetInteriorVehicleData(hash); + + JSONObject body = JsonUtils.readJsonObjectFromJsonObject(commandJson, getMessageType()); + assertNotNull(Test.NOT_NULL, body); + + // Test everything in the json body. + assertEquals(Test.MATCH, JsonUtils.readStringFromJsonObject(body, RPCMessage.KEY_FUNCTION_NAME), cmd.getFunctionName()); + assertEquals(Test.MATCH, JsonUtils.readIntegerFromJsonObject(body, RPCMessage.KEY_CORRELATION_ID), cmd.getCorrelationID()); + + JSONObject parameters = JsonUtils.readJsonObjectFromJsonObject(body, RPCMessage.KEY_PARAMETERS); + + ModuleData referenceModuleData = new ModuleData(JsonRPCMarshaller.deserializeJSONObject((JSONObject) JsonUtils.readObjectFromJsonObject(parameters, SetInteriorVehicleData.KEY_MODULE_DATA))); + + assertTrue(Test.TRUE, Validator.validateModuleData(referenceModuleData, cmd.getModuleData())); + }catch (JSONException e) { + fail(Test.JSON_FAIL); + } + } +}
\ No newline at end of file diff --git a/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/responses/ButtonPressResponseTest.java b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/responses/ButtonPressResponseTest.java new file mode 100644 index 000000000..64f5b0c75 --- /dev/null +++ b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/responses/ButtonPressResponseTest.java @@ -0,0 +1,74 @@ +package com.smartdevicelink.test.rpc.responses; + +import com.smartdevicelink.marshal.JsonRPCMarshaller; +import com.smartdevicelink.protocol.enums.FunctionID; +import com.smartdevicelink.proxy.RPCMessage; +import com.smartdevicelink.proxy.rpc.ButtonPressResponse; +import com.smartdevicelink.test.BaseRpcTests; +import com.smartdevicelink.test.JsonUtils; +import com.smartdevicelink.test.Test; +import com.smartdevicelink.test.json.rpc.JsonFileReader; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.Hashtable; + +/** + * This is a unit test class for the SmartDeviceLink library project class : + * {@link com.smartdevicelink.rpc.ButtonPressResponse} + */ +public class ButtonPressResponseTest extends BaseRpcTests { + + @Override + protected RPCMessage createMessage(){ + return new ButtonPressResponse(); + } + + @Override + protected String getMessageType(){ + return RPCMessage.KEY_RESPONSE; + } + + @Override + protected String getCommandType(){ + return FunctionID.BUTTON_PRESS.toString(); + } + + @Override + protected JSONObject getExpectedParameters(int sdlVersion){ + return new JSONObject(); + } + + /** + * Tests the expected values of the RPC message. + */ + public void testRpcValues () { + // Invalid/Null Tests + ButtonPressResponse msg = new ButtonPressResponse(); + assertNotNull(Test.NOT_NULL, msg); + testNullBase(msg); + } + + /** + * Tests a valid JSON construction of this RPC message. + */ + public void testJsonConstructor () { + JSONObject commandJson = JsonFileReader.readId(this.mContext, getCommandType(), getMessageType()); + assertNotNull(Test.NOT_NULL, commandJson); + + try { + Hashtable<String, Object> hash = JsonRPCMarshaller.deserializeJSONObject(commandJson); + ButtonPressResponse cmd = new ButtonPressResponse(hash); + + JSONObject body = JsonUtils.readJsonObjectFromJsonObject(commandJson, getMessageType()); + assertNotNull(Test.NOT_NULL, body); + + // Test everything in the json body. + assertEquals(Test.MATCH, JsonUtils.readStringFromJsonObject(body, RPCMessage.KEY_FUNCTION_NAME), cmd.getFunctionName()); + assertEquals(Test.MATCH, JsonUtils.readIntegerFromJsonObject(body, RPCMessage.KEY_CORRELATION_ID), cmd.getCorrelationID()); + } catch (JSONException e) { + e.printStackTrace(); + } + } +}
\ No newline at end of file diff --git a/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/responses/GetInteriorVehicleDataResponseTests.java b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/responses/GetInteriorVehicleDataResponseTests.java new file mode 100644 index 000000000..c76388c69 --- /dev/null +++ b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/responses/GetInteriorVehicleDataResponseTests.java @@ -0,0 +1,110 @@ +package com.smartdevicelink.test.rpc.responses; + +import com.smartdevicelink.marshal.JsonRPCMarshaller; +import com.smartdevicelink.protocol.enums.FunctionID; +import com.smartdevicelink.proxy.RPCMessage; +import com.smartdevicelink.proxy.rpc.GetInteriorVehicleDataResponse; +import com.smartdevicelink.proxy.rpc.ModuleData; +import com.smartdevicelink.test.BaseRpcTests; +import com.smartdevicelink.test.JsonUtils; +import com.smartdevicelink.test.Test; +import com.smartdevicelink.test.Validator; +import com.smartdevicelink.test.json.rpc.JsonFileReader; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.Hashtable; + +/** + * This is a unit test class for the SmartDeviceLink library project class : + * {@link com.smartdevicelink.rpc.GetInteriorVehicleDataResponse} + */ +public class GetInteriorVehicleDataResponseTests extends BaseRpcTests { + + @Override + protected RPCMessage createMessage(){ + + GetInteriorVehicleDataResponse msg = new GetInteriorVehicleDataResponse(); + + msg.setIsSubscribed(Test.GENERAL_BOOLEAN); + msg.setModuleData(Test.GENERAL_MODULEDATA); + + return msg; + } + + @Override + protected String getMessageType(){ + return RPCMessage.KEY_RESPONSE; + } + + @Override + protected String getCommandType(){ + return FunctionID.GET_INTERIOR_VEHICLE_DATA.toString(); + } + + @Override + protected JSONObject getExpectedParameters(int sdlVersion){ + JSONObject result = new JSONObject(); + + try{ + result.put(GetInteriorVehicleDataResponse.KEY_IS_SUBSCRIBED, Test.GENERAL_BOOLEAN); + result.put(GetInteriorVehicleDataResponse.KEY_MODULE_DATA, JsonRPCMarshaller.serializeHashtable(Test.GENERAL_MODULEDATA.getStore())); + }catch(JSONException e){ + fail(Test.JSON_FAIL); + } + + return result; + } + + /** + * Tests the expected values of the RPC message. + */ + public void testRpcValues () { + // Test Values + boolean testIsSubscribed = ( (GetInteriorVehicleDataResponse) msg ).getIsSubscribed(); + ModuleData testModuleData = ( (GetInteriorVehicleDataResponse) msg ).getModuleData(); + + // Valid Tests + assertEquals(Test.MATCH, Test.GENERAL_BOOLEAN, testIsSubscribed); + assertTrue(Test.TRUE, Validator.validateModuleData(Test.GENERAL_MODULEDATA, testModuleData)); + + // Invalid/Null Tests + GetInteriorVehicleDataResponse msg = new GetInteriorVehicleDataResponse(); + assertNotNull(Test.NOT_NULL, msg); + testNullBase(msg); + + assertNull(Test.NULL, msg.getIsSubscribed()); + assertNull(Test.NULL, msg.getModuleData()); + } + + /** + * Tests a valid JSON construction of this RPC message. + */ + public void testJsonConstructor () { + JSONObject commandJson = JsonFileReader.readId(this.mContext, getCommandType(), getMessageType()); + assertNotNull(Test.NOT_NULL, commandJson); + + try { + Hashtable<String, Object> hash = JsonRPCMarshaller.deserializeJSONObject(commandJson); + GetInteriorVehicleDataResponse cmd = new GetInteriorVehicleDataResponse (hash); + + JSONObject body = JsonUtils.readJsonObjectFromJsonObject(commandJson, getMessageType()); + assertNotNull(Test.NOT_NULL, body); + + // Test everything in the json body. + assertEquals(Test.MATCH, JsonUtils.readStringFromJsonObject(body, RPCMessage.KEY_FUNCTION_NAME), cmd.getFunctionName()); + assertEquals(Test.MATCH, JsonUtils.readIntegerFromJsonObject(body, RPCMessage.KEY_CORRELATION_ID), cmd.getCorrelationID()); + + JSONObject parameters = JsonUtils.readJsonObjectFromJsonObject(body, RPCMessage.KEY_PARAMETERS); + + ModuleData testModuleData = new ModuleData(JsonRPCMarshaller.deserializeJSONObject((JSONObject) JsonUtils.readObjectFromJsonObject(parameters, GetInteriorVehicleDataResponse.KEY_MODULE_DATA))); + ModuleData cmdModuleData = cmd.getModuleData(); + + assertTrue(Test.TRUE, Validator.validateModuleData(testModuleData, cmdModuleData) ); + assertEquals(Test.MATCH, JsonUtils.readObjectFromJsonObject(parameters, GetInteriorVehicleDataResponse.KEY_IS_SUBSCRIBED), cmd.getIsSubscribed()); + } catch (JSONException e) { + e.printStackTrace(); + } + } +} diff --git a/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/responses/SetInteriorVehicleDataResponseTests.java b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/responses/SetInteriorVehicleDataResponseTests.java new file mode 100644 index 000000000..c25685157 --- /dev/null +++ b/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/responses/SetInteriorVehicleDataResponseTests.java @@ -0,0 +1,104 @@ +package com.smartdevicelink.test.rpc.responses; + +import com.smartdevicelink.marshal.JsonRPCMarshaller; +import com.smartdevicelink.protocol.enums.FunctionID; +import com.smartdevicelink.proxy.RPCMessage; +import com.smartdevicelink.proxy.rpc.ModuleData; +import com.smartdevicelink.proxy.rpc.SetInteriorVehicleDataResponse; +import com.smartdevicelink.test.BaseRpcTests; +import com.smartdevicelink.test.JsonUtils; +import com.smartdevicelink.test.Test; +import com.smartdevicelink.test.Validator; +import com.smartdevicelink.test.json.rpc.JsonFileReader; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.Hashtable; + +/** + * This is a unit test class for the SmartDeviceLink library project class : + * {@link com.smartdevicelink.rpc.SetInteriorVehicleDataResponse} + */ +public class SetInteriorVehicleDataResponseTests extends BaseRpcTests { + + @Override + protected RPCMessage createMessage(){ + + SetInteriorVehicleDataResponse msg = new SetInteriorVehicleDataResponse(); + + msg.setModuleData(Test.GENERAL_MODULEDATA); + + return msg; + } + + @Override + protected String getMessageType(){ + return RPCMessage.KEY_RESPONSE; + } + + @Override + protected String getCommandType(){ + return FunctionID.SET_INTERIOR_VEHICLE_DATA.toString(); + } + + @Override + protected JSONObject getExpectedParameters(int sdlVersion){ + JSONObject result = new JSONObject(); + + try{ + result.put(SetInteriorVehicleDataResponse.KEY_MODULE_DATA, JsonRPCMarshaller.serializeHashtable(Test.GENERAL_MODULEDATA.getStore())); + }catch(JSONException e){ + fail(Test.JSON_FAIL); + } + + return result; + } + + /** + * Tests the expected values of the RPC message. + */ + public void testRpcValues () { + // Test Values + ModuleData testModuleData = ( (SetInteriorVehicleDataResponse) msg ).getModuleData(); + + // Valid Tests + assertTrue(Test.TRUE, Validator.validateModuleData(Test.GENERAL_MODULEDATA, testModuleData)); + + // Invalid/Null Tests + SetInteriorVehicleDataResponse msg = new SetInteriorVehicleDataResponse(); + assertNotNull(Test.NOT_NULL, msg); + testNullBase(msg); + + assertNull(Test.NULL, msg.getModuleData()); + } + + /** + * Tests a valid JSON construction of this RPC message. + */ + public void testJsonConstructor () { + JSONObject commandJson = JsonFileReader.readId(this.mContext, getCommandType(), getMessageType()); + assertNotNull(Test.NOT_NULL, commandJson); + + try { + Hashtable<String, Object> hash = JsonRPCMarshaller.deserializeJSONObject(commandJson); + SetInteriorVehicleDataResponse cmd = new SetInteriorVehicleDataResponse (hash); + + JSONObject body = JsonUtils.readJsonObjectFromJsonObject(commandJson, getMessageType()); + assertNotNull(Test.NOT_NULL, body); + + // Test everything in the json body. + assertEquals(Test.MATCH, JsonUtils.readStringFromJsonObject(body, RPCMessage.KEY_FUNCTION_NAME), cmd.getFunctionName()); + assertEquals(Test.MATCH, JsonUtils.readIntegerFromJsonObject(body, RPCMessage.KEY_CORRELATION_ID), cmd.getCorrelationID()); + + JSONObject parameters = JsonUtils.readJsonObjectFromJsonObject(body, RPCMessage.KEY_PARAMETERS); + + ModuleData testModuleData = new ModuleData(JsonRPCMarshaller.deserializeJSONObject((JSONObject) JsonUtils.readObjectFromJsonObject(parameters, SetInteriorVehicleDataResponse.KEY_MODULE_DATA))); + ModuleData cmdModuleData = cmd.getModuleData(); + + assertTrue(Test.TRUE, Validator.validateModuleData(testModuleData, cmdModuleData) ); + } catch (JSONException e) { + e.printStackTrace(); + } + } +} diff --git a/sdl_android/src/androidTest/java/com/smartdevicelink/test/security/SdlSecurityBaseTest.java b/sdl_android/src/androidTest/java/com/smartdevicelink/test/security/SdlSecurityBaseTest.java index 56a482804..2bf6136fa 100644 --- a/sdl_android/src/androidTest/java/com/smartdevicelink/test/security/SdlSecurityBaseTest.java +++ b/sdl_android/src/androidTest/java/com/smartdevicelink/test/security/SdlSecurityBaseTest.java @@ -74,7 +74,7 @@ public class SdlSecurityBaseTest extends AndroidTestCase { } @Override public void onProtocolSessionStartedNACKed(SessionType sessionType, - byte sessionID, byte version, String correlationID) { + byte sessionID, byte version, String correlationID, List<String> rejectedParams) { } @Override diff --git a/sdl_android/src/androidTest/java/com/smartdevicelink/test/streaming/AbstractPacketizerTests.java b/sdl_android/src/androidTest/java/com/smartdevicelink/test/streaming/AbstractPacketizerTests.java index e05091c44..80126c67c 100644 --- a/sdl_android/src/androidTest/java/com/smartdevicelink/test/streaming/AbstractPacketizerTests.java +++ b/sdl_android/src/androidTest/java/com/smartdevicelink/test/streaming/AbstractPacketizerTests.java @@ -6,6 +6,7 @@ import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.net.URLConnection; +import java.util.List; import junit.framework.TestCase; @@ -118,7 +119,7 @@ class MockInterfaceBroker implements ISdlConnectionListener { } @Override public void onProtocolSessionStartedNACKed(SessionType sessionType, - byte sessionID, byte version, String correlationID) { + byte sessionID, byte version, String correlationID, List<String> rejectedParams) { } @Override diff --git a/sdl_android/src/androidTest/java/com/smartdevicelink/test/streaming/RTPH264PacketizerTest.java b/sdl_android/src/androidTest/java/com/smartdevicelink/test/streaming/RTPH264PacketizerTest.java new file mode 100644 index 000000000..70274444c --- /dev/null +++ b/sdl_android/src/androidTest/java/com/smartdevicelink/test/streaming/RTPH264PacketizerTest.java @@ -0,0 +1,881 @@ +/* + * Copyright (c) 2017, Xevo Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.smartdevicelink.test.streaming; + +import com.smartdevicelink.SdlConnection.SdlSession; +import com.smartdevicelink.protocol.ProtocolMessage; +import com.smartdevicelink.protocol.enums.SessionType; +import com.smartdevicelink.proxy.interfaces.IVideoStreamListener; +import com.smartdevicelink.streaming.IStreamListener; +import com.smartdevicelink.streaming.RTPH264Packetizer; +import com.smartdevicelink.transport.BTTransportConfig; + +import junit.framework.TestCase; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +/** + * This class includes a unit test for {@link com.smartdevicelink.streaming.RTPH264Packetizer}. + * + * @author Sho Amano + */ +public class RTPH264PacketizerTest extends TestCase { + + private static final int FRAME_LENGTH_LEN = 2; + private static final int RTP_HEADER_LEN = 12; + + private static final byte WIPRO_VERSION = 0x0B; + private static final byte SESSION_ID = 0x0A; + + private class ByteStreamNALUnit { + byte[] startCode; + byte[] nalUnit; + int frameNum; + + ByteStreamNALUnit(byte[] startCode, byte[] nalUnit, int frameNum) { + this.startCode = startCode; + this.nalUnit = nalUnit; + this.frameNum = frameNum; + } + + byte[] createArray() { + byte[] array = new byte[startCode.length + nalUnit.length]; + System.arraycopy(startCode, 0, array, 0, startCode.length); + System.arraycopy(nalUnit, 0, array, startCode.length, nalUnit.length); + return array; + } + + public int getLength() { + return startCode.length + nalUnit.length; + } + } + + private static final byte[] START_CODE_3 = {0x00, 0x00, 0x01}; + private static final byte[] START_CODE_4 = {0x00, 0x00, 0x00, 0x01}; + + /* a sample H.264 stream, including 33 frames of 16px white square */ + private final ByteStreamNALUnit[] SAMPLE_STREAM = new ByteStreamNALUnit[] { + // SPS + new ByteStreamNALUnit(START_CODE_4, new byte[]{0x67, 0x42, (byte)0xC0, 0x0A, (byte)0xA6, 0x11, 0x11, (byte)0xE8, + 0x40, 0x00, 0x00, (byte)0xFA, 0x40, 0x00, 0x3A, (byte)0x98, + 0x23, (byte)0xC4, (byte)0x89, (byte)0x84, 0x60}, 0), + // PPS + new ByteStreamNALUnit(START_CODE_4, new byte[]{0x68, (byte)0xC8, 0x42, 0x0F, 0x13, 0x20}, 0), + // I + new ByteStreamNALUnit(START_CODE_3, new byte[]{0x65, (byte)0x88, (byte)0x82, 0x07, 0x67, 0x39, 0x31, 0x40, + 0x00, 0x5E, 0x0A, (byte)0xFB, (byte)0xEF, (byte)0xAE, (byte)0xBA, (byte)0xEB, + (byte)0xAE, (byte)0xBA, (byte)0xEB, (byte)0xC0}, 0), + // P + new ByteStreamNALUnit(START_CODE_4, new byte[]{0x41, (byte)0x9A, 0x1C, 0x0E, (byte)0xCE, 0x71, (byte)0xB0}, 1), + new ByteStreamNALUnit(START_CODE_4, new byte[]{0x41, (byte)0x9A, 0x2A, 0x03, (byte)0xB3, (byte)0x9C, 0x6C}, 2), + new ByteStreamNALUnit(START_CODE_4, new byte[]{0x41, (byte)0x9A, 0x3B, 0x03, (byte)0xB3, (byte)0x9C, 0x6C}, 3), + new ByteStreamNALUnit(START_CODE_4, new byte[]{0x41, (byte)0x9A, 0x49, 0x00, (byte)0xEC, (byte)0xE7, 0x1B}, 4), + new ByteStreamNALUnit(START_CODE_4, new byte[]{0x41, (byte)0x9A, 0x59, 0x40, (byte)0xEC, (byte)0xE7, 0x1B}, 5), + new ByteStreamNALUnit(START_CODE_4, new byte[]{0x41, (byte)0x9A, 0x69, (byte)0x80, (byte)0xEC, (byte)0xE7, 0x1B}, 6), + new ByteStreamNALUnit(START_CODE_4, new byte[]{0x41, (byte)0x9A, 0x79, (byte)0xC0, (byte)0xEC, (byte)0xE7, 0x1B}, 7), + new ByteStreamNALUnit(START_CODE_4, new byte[]{0x41, (byte)0x9A, (byte)0x88, (byte)0x80, 0x3B, 0x39, (byte)0xC6, (byte)0xC0}, 8), + new ByteStreamNALUnit(START_CODE_4, new byte[]{0x41, (byte)0x9A, (byte)0x98, (byte)0x90, 0x3B, 0x39, (byte)0xC6, (byte)0xC0}, 9), + new ByteStreamNALUnit(START_CODE_4, new byte[]{0x41, (byte)0x9A, (byte)0xA8, (byte)0xA0, 0x3B, 0x39, (byte)0xC6, (byte)0xC0}, 10), + new ByteStreamNALUnit(START_CODE_4, new byte[]{0x41, (byte)0x9A, (byte)0xB8, (byte)0xB0, 0x3B, 0x39, (byte)0xC6, (byte)0xC0}, 11), + new ByteStreamNALUnit(START_CODE_4, new byte[]{0x41, (byte)0x9A, (byte)0xC8, (byte)0xC0, 0x3B, 0x39, (byte)0xC6, (byte)0xC0}, 12), + new ByteStreamNALUnit(START_CODE_4, new byte[]{0x41, (byte)0x9A, (byte)0xD8, (byte)0xD0, 0x3B, 0x39, (byte)0xC6, (byte)0xC0}, 13), + new ByteStreamNALUnit(START_CODE_4, new byte[]{0x41, (byte)0x9A, (byte)0xE8, (byte)0xE0, 0x3B, 0x39, (byte)0xC6, (byte)0xC0}, 14), + new ByteStreamNALUnit(START_CODE_4, new byte[]{0x41, (byte)0x9A, (byte)0xF8, (byte)0xF0, 0x3B, 0x39, (byte)0xC6, (byte)0xC0}, 15), + new ByteStreamNALUnit(START_CODE_4, new byte[]{0x41, (byte)0x9B, 0x00, 0x1D, (byte)0x9C, (byte)0xE3, 0x60}, 16), + new ByteStreamNALUnit(START_CODE_4, new byte[]{0x41, (byte)0x9B, 0x10, 0x1D, (byte)0x9C, (byte)0xE3, 0x60}, 17), + new ByteStreamNALUnit(START_CODE_4, new byte[]{0x41, (byte)0x9B, 0x20, 0x1D, (byte)0x9C, (byte)0xE3, 0x60}, 18), + new ByteStreamNALUnit(START_CODE_4, new byte[]{0x41, (byte)0x9B, 0x30, 0x1D, (byte)0x9C, (byte)0xE3, 0x60}, 19), + new ByteStreamNALUnit(START_CODE_4, new byte[]{0x41, (byte)0x9B, 0x40, 0x1D, (byte)0x9C, (byte)0xE3, 0x60}, 20), + new ByteStreamNALUnit(START_CODE_4, new byte[]{0x41, (byte)0x9B, 0x50, 0x1D, (byte)0x9C, (byte)0xE3, 0x60}, 21), + new ByteStreamNALUnit(START_CODE_4, new byte[]{0x41, (byte)0x9B, 0x60, 0x1D, (byte)0x9C, (byte)0xE3, 0x60}, 22), + new ByteStreamNALUnit(START_CODE_4, new byte[]{0x41, (byte)0x9B, 0x70, 0x1D, (byte)0x9C, (byte)0xE3, 0x60}, 23), + new ByteStreamNALUnit(START_CODE_4, new byte[]{0x41, (byte)0x9B, (byte)0x80, 0x1D, (byte)0x9C, (byte)0xE3, 0x60}, 24), + new ByteStreamNALUnit(START_CODE_4, new byte[]{0x41, (byte)0x9B, (byte)0x90, 0x1D, (byte)0x9C, (byte)0xE3, 0x60}, 25), + new ByteStreamNALUnit(START_CODE_4, new byte[]{0x41, (byte)0x9B, (byte)0xA0, 0x1D, (byte)0x9C, (byte)0xE3, 0x60}, 26), + new ByteStreamNALUnit(START_CODE_4, new byte[]{0x41, (byte)0x9B, (byte)0xB0, 0x1D, (byte)0x9C, (byte)0xE3, 0x60}, 27), + new ByteStreamNALUnit(START_CODE_4, new byte[]{0x41, (byte)0x9B, (byte)0xC0, 0x1D, (byte)0x9C, (byte)0xE3, 0x60}, 28), + new ByteStreamNALUnit(START_CODE_4, new byte[]{0x41, (byte)0x9B, (byte)0xD0, 0x1D, (byte)0x9C, (byte)0xE3, 0x60}, 29), + // SPS + new ByteStreamNALUnit(START_CODE_4, new byte[]{0x67, 0x42, (byte)0xC0, 0x0A, (byte)0xA6, 0x11, 0x11, (byte)0xE8, + 0x40, 0x00, 0x00, (byte)0xFA, 0x40, 0x00, 0x3A, (byte)0x98, + 0x23, (byte)0xC4, (byte)0x89, (byte)0x84, 0x60}, 30), + // PPS + new ByteStreamNALUnit(START_CODE_4, new byte[]{0x68, (byte)0xC8, 0x42, 0x0F, 0x13, 0x20}, 30), + // I + new ByteStreamNALUnit(START_CODE_3, new byte[]{0x65, (byte)0x88, (byte)0x81, 0x00, (byte)0x8E, 0x73, (byte)0x93, 0x14, + 0x00, 0x06, (byte)0xA4, 0x2F, (byte)0xBE, (byte)0xFA, (byte)0xEB, (byte)0xAE, + (byte)0xBA, (byte)0xEB, (byte)0xAE, (byte)0xBC}, 30), + // P + new ByteStreamNALUnit(START_CODE_4, new byte[]{0x41, (byte)0x9A, 0x1C, 0x0D, (byte)0xCE, 0x71, (byte)0xB0}, 31), + new ByteStreamNALUnit(START_CODE_4, new byte[]{0x41, (byte)0x9A, 0x2A, 0x03, 0x33, (byte)0x9C, 0x6C}, 32), + }; + + /** + * Test for creating Single Frame RTP packets from H.264 byte stream + */ + public void testSingleFrames() { + StreamVerifier verifier = new StreamVerifier(SAMPLE_STREAM); + SdlSession session = createTestSession(); + RTPH264Packetizer packetizer = null; + try { + packetizer = new RTPH264Packetizer(verifier, SessionType.NAV, SESSION_ID, session); + } catch (IOException e) { + fail(); + } + MockVideoApp encoder = new MockVideoApp(packetizer); + + try { + packetizer.start(); + } catch (IOException e) { + fail(); + } + + encoder.inputByteStreamWithArray(SAMPLE_STREAM); + try { + Thread.sleep(1000, 0); + } catch (InterruptedException e) {} + + packetizer.stop(); + assertEquals(SAMPLE_STREAM.length, verifier.getPacketCount()); + } + + /** + * Test for creating Single Frame RTP packets then splitting into multiple SDL frames + */ + public void testSingleFramesIntoMultipleMessages() { + StreamVerifier verifier = new StreamVerifier(SAMPLE_STREAM); + SdlSession session = createTestSession(); + RTPH264Packetizer packetizer = null; + try { + packetizer = new RTPH264Packetizer(verifier, SessionType.NAV, SESSION_ID, session); + } catch (IOException e) { + fail(); + } + + // try to modify "bufferSize" variable (in AbstractPacketizer) + Class packetizerClass = RTPH264Packetizer.class; + String fieldName = "bufferSize"; + java.lang.reflect.Field bufferSizeField = null; + while (packetizerClass != null) { + try { + bufferSizeField = packetizerClass.getDeclaredField(fieldName); + break; + } catch (NoSuchFieldException e) { + packetizerClass = packetizerClass.getSuperclass(); + } + } + if (bufferSizeField != null) { + try { + bufferSizeField.setAccessible(true); + // use small MTU and make some RTP packets split into multiple SDL frames + bufferSizeField.set(packetizer, FRAME_LENGTH_LEN + RTP_HEADER_LEN + 16); + } catch (IllegalAccessException e) { + fail("Cannot access to private field \"" + fieldName + "\"."); + } + } else { + fail("Cannot find private field \"" + fieldName + "\"."); + } + + MockVideoApp encoder = new MockVideoApp(packetizer); + + try { + packetizer.start(); + } catch (IOException e) { + fail(); + } + + encoder.inputByteStreamWithArray(SAMPLE_STREAM); + try { + Thread.sleep(1000, 0); + } catch (InterruptedException e) {} + + packetizer.stop(); + assertEquals(SAMPLE_STREAM.length, verifier.getPacketCount()); + } + + /** + * Test for creating Fragmentation Units from H.264 byte stream + */ + public void testFragmentationUnits() { + ByteStreamNALUnit[] stream = new ByteStreamNALUnit[] { + SAMPLE_STREAM[0], SAMPLE_STREAM[1], null, null, null, SAMPLE_STREAM[5] + }; + byte[] fakeNALUnit1 = new byte[65535 - RTP_HEADER_LEN]; // not fragmented + byte[] fakeNALUnit2 = new byte[65536 - RTP_HEADER_LEN]; // will be fragmented + byte[] fakeNALUnit3 = new byte[65537 - RTP_HEADER_LEN]; // ditto + + for (int i = 0; i < fakeNALUnit1.length; i++) { + fakeNALUnit1[i] = (byte)(i % 256); + } + for (int i = 0; i < fakeNALUnit2.length; i++) { + fakeNALUnit2[i] = (byte)(i % 256); + } + for (int i = 0; i < fakeNALUnit3.length; i++) { + fakeNALUnit3[i] = (byte)(i % 256); + } + + stream[2] = new ByteStreamNALUnit(START_CODE_3, fakeNALUnit1, 0); + stream[3] = new ByteStreamNALUnit(START_CODE_4, fakeNALUnit2, 1); + stream[4] = new ByteStreamNALUnit(START_CODE_4, fakeNALUnit3, 2); + + StreamVerifier verifier = new StreamVerifier(stream); + SdlSession session = createTestSession(); + RTPH264Packetizer packetizer = null; + try { + packetizer = new RTPH264Packetizer(verifier, SessionType.NAV, SESSION_ID, session); + } catch (IOException e) { + fail(); + } + MockVideoApp encoder = new MockVideoApp(packetizer); + + try { + packetizer.start(); + } catch (IOException e) { + fail(); + } + + encoder.inputByteStreamWithArray(stream); + try { + Thread.sleep(1000, 0); + } catch (InterruptedException e) {} + + packetizer.stop(); + assertEquals(stream.length + 2, verifier.getPacketCount()); + } + + /** + * Test for RTP sequence number gets wrap-around correctly + */ + public void testSequenceNumWrapAround() { + ByteStreamNALUnit[] stream = new ByteStreamNALUnit[70000]; + for (int i = 0; i < stream.length; i++) { + stream[i] = new ByteStreamNALUnit(START_CODE_4, SAMPLE_STREAM[3].nalUnit, i); + } + + StreamVerifier verifier = new StreamVerifier(stream); + SdlSession session = createTestSession(); + RTPH264Packetizer packetizer = null; + try { + packetizer = new RTPH264Packetizer(verifier, SessionType.NAV, SESSION_ID, session); + } catch (IOException e) { + fail(); + } + MockVideoApp encoder = new MockVideoApp(packetizer); + + try { + packetizer.start(); + } catch (IOException e) { + fail(); + } + + encoder.inputByteStreamWithArray(stream); + try { + Thread.sleep(2000, 0); + } catch (InterruptedException e) {} + + packetizer.stop(); + assertEquals(stream.length, verifier.getPacketCount()); + } + + /** + * Test for {@link com.smartdevicelink.streaming.RTPH264Packetizer#setPayloadType(byte)} + */ + public void testSetPayloadType() { + byte pt = (byte)123; + StreamVerifier verifier = new StreamVerifier(SAMPLE_STREAM, pt); + SdlSession session = createTestSession(); + RTPH264Packetizer packetizer = null; + try { + packetizer = new RTPH264Packetizer(verifier, SessionType.NAV, SESSION_ID, session); + } catch (IOException e) { + fail(); + } + packetizer.setPayloadType(pt); + MockVideoApp encoder = new MockVideoApp(packetizer); + + try { + packetizer.start(); + } catch (IOException e) { + fail(); + } + + encoder.inputByteStreamWithArray(SAMPLE_STREAM); + try { + Thread.sleep(1000, 0); + } catch (InterruptedException e) {} + + packetizer.stop(); + assertEquals(SAMPLE_STREAM.length, verifier.getPacketCount()); + } + + /** + * Test for {@link com.smartdevicelink.streaming.RTPH264Packetizer#setSSRC(int)} + */ + public void testSetSSRC() { + int ssrc = 0xFEDCBA98; + StreamVerifier verifier = new StreamVerifier(SAMPLE_STREAM); + verifier.setExpectedSSRC(ssrc); + SdlSession session = createTestSession(); + RTPH264Packetizer packetizer = null; + try { + packetizer = new RTPH264Packetizer(verifier, SessionType.NAV, SESSION_ID, session); + } catch (IOException e) { + fail(); + } + packetizer.setSSRC(ssrc); + MockVideoApp encoder = new MockVideoApp(packetizer); + + try { + packetizer.start(); + } catch (IOException e) { + fail(); + } + + encoder.inputByteStreamWithArray(SAMPLE_STREAM); + try { + Thread.sleep(1000, 0); + } catch (InterruptedException e) {} + + packetizer.stop(); + assertEquals(SAMPLE_STREAM.length, verifier.getPacketCount()); + } + + /** + * Test for {@link com.smartdevicelink.streaming.RTPH264Packetizer#pause()} and + * {@link com.smartdevicelink.streaming.RTPH264Packetizer#resume()} + */ + public void testPauseResume() { + int index = 0; + // split SAMPLE_STREAM into three parts + ByteStreamNALUnit[] inputStream1 = new ByteStreamNALUnit[8]; + ByteStreamNALUnit[] inputStream2 = new ByteStreamNALUnit[19]; + ByteStreamNALUnit[] inputStream3 = new ByteStreamNALUnit[10]; + for (int i = 0; i < inputStream1.length; i++) { + inputStream1[i] = SAMPLE_STREAM[index++]; + } + for (int i = 0; i < inputStream2.length; i++) { + inputStream2[i] = SAMPLE_STREAM[index++]; + } + for (int i = 0; i < inputStream3.length; i++) { + inputStream3[i] = SAMPLE_STREAM[index++]; + } + + index = 0; + // expected output is "all NAL units in inputStream1" plus "I frame and onwards in inputStream3" + ByteStreamNALUnit[] expectedStream = new ByteStreamNALUnit[inputStream1.length + 3]; + for (int i = 0; i < inputStream1.length; i++) { + expectedStream[index++] = inputStream1[i]; + } + expectedStream[index++] = SAMPLE_STREAM[34]; + expectedStream[index++] = SAMPLE_STREAM[35]; + expectedStream[index] = SAMPLE_STREAM[36]; + + StreamVerifier verifier = new StreamVerifier(expectedStream); + SdlSession session = createTestSession(); + RTPH264Packetizer packetizer = null; + try { + packetizer = new RTPH264Packetizer(verifier, SessionType.NAV, SESSION_ID, session); + } catch (IOException e) { + fail(); + } + MockVideoApp encoder = new MockVideoApp(packetizer); + + try { + packetizer.start(); + } catch (IOException e) { + fail(); + } + + encoder.inputByteStreamWithArray(inputStream1); + try { + Thread.sleep(1000, 0); + } catch (InterruptedException e) {} + + packetizer.pause(); + + // this input stream should be disposed + encoder.inputByteStreamWithArray(inputStream2); + try { + Thread.sleep(1000, 0); + } catch (InterruptedException e) {} + + packetizer.resume(); + + // packetizer should resume from a I frame + encoder.inputByteStreamWithArray(inputStream3); + try { + Thread.sleep(1000, 0); + } catch (InterruptedException e) {} + + packetizer.stop(); + assertEquals(expectedStream.length, verifier.getPacketCount()); + } + + /** + * Test for {@link com.smartdevicelink.streaming.RTPH264Packetizer#sendFrame(byte[], int, int, long)} + */ + public void testSendFrameInterfaceWithArray() { + StreamVerifier verifier = new StreamVerifier(SAMPLE_STREAM); + SdlSession session = createTestSession(); + RTPH264Packetizer packetizer = null; + try { + packetizer = new RTPH264Packetizer(verifier, SessionType.NAV, SESSION_ID, session); + } catch (IOException e) { + fail(); + } + MockVideoApp mockApp = new MockVideoApp(packetizer); + + try { + packetizer.start(); + } catch (IOException e) { + fail(); + } + + mockApp.inputByteStreamWithArrayOffset(SAMPLE_STREAM); + try { + Thread.sleep(1000, 0); + } catch (InterruptedException e) {} + + packetizer.stop(); + assertEquals(SAMPLE_STREAM.length, verifier.getPacketCount()); + } + + /** + * Test for {@link com.smartdevicelink.streaming.RTPH264Packetizer#sendFrame(ByteBuffer, long)} + */ + public void testSendFrameInterfaceWithByteBuffer() { + StreamVerifier verifier = new StreamVerifier(SAMPLE_STREAM); + SdlSession session = createTestSession(); + RTPH264Packetizer packetizer = null; + try { + packetizer = new RTPH264Packetizer(verifier, SessionType.NAV, SESSION_ID, session); + } catch (IOException e) { + fail(); + } + MockVideoApp mockApp = new MockVideoApp(packetizer); + + try { + packetizer.start(); + } catch (IOException e) { + fail(); + } + + mockApp.inputByteStreamWithByteBuffer(SAMPLE_STREAM); + try { + Thread.sleep(1000, 0); + } catch (InterruptedException e) {} + + packetizer.stop(); + assertEquals(SAMPLE_STREAM.length, verifier.getPacketCount()); + } + + /** + * Test for {@link com.smartdevicelink.streaming.RTPH264Packetizer#sendFrame(ByteBuffer, long)} + * with direct ByteBuffer + */ + public void testSendFrameInterfaceWithDirectByteBuffer() { + StreamVerifier verifier = new StreamVerifier(SAMPLE_STREAM); + SdlSession session = createTestSession(); + RTPH264Packetizer packetizer = null; + try { + packetizer = new RTPH264Packetizer(verifier, SessionType.NAV, SESSION_ID, session); + } catch (IOException e) { + fail(); + } + MockVideoApp mockApp = new MockVideoApp(packetizer); + + try { + packetizer.start(); + } catch (IOException e) { + fail(); + } + + mockApp.inputByteStreamWithDirectByteBuffer(SAMPLE_STREAM); + try { + Thread.sleep(1000, 0); + } catch (InterruptedException e) {} + + packetizer.stop(); + assertEquals(SAMPLE_STREAM.length, verifier.getPacketCount()); + } + + private SdlSession createTestSession() { + return SdlSession.createSession(WIPRO_VERSION, new MockInterfaceBroker(), new BTTransportConfig(true)); + } + + private class StreamVerifier implements IStreamListener { + private static final int STATE_LENGTH = 0; + private static final int STATE_PACKET = 1; + + private ByteStreamNALUnit[] mStream; + private byte[] mExpectedNALUnit; + private ByteBuffer mReceiveBuffer; + private int mPacketLen; + private int mState; + private int mNALCount; + private int mTotalPacketCount; + private boolean mFragmented; + private int mOffsetInNALUnit; + private byte mPayloadType; + private boolean mVerifySSRC; + private int mExpectedSSRC; + private boolean mFirstPacketReceived; + private short mFirstSequenceNum; + private int mFirstTimestamp; + + StreamVerifier(ByteStreamNALUnit[] stream) { + this(stream, (byte)96); + } + + StreamVerifier(ByteStreamNALUnit[] stream, byte payloadType) { + mStream = stream; + mReceiveBuffer = ByteBuffer.allocate(256 * 1024); + mReceiveBuffer.order(ByteOrder.BIG_ENDIAN); + mPacketLen = 0; + mState = STATE_LENGTH; + + mNALCount = 0; + mTotalPacketCount = 0; + mFragmented = false; + mOffsetInNALUnit = 1; // Used when verifying FUs. The first byte is skipped. + + mPayloadType = payloadType; + mVerifySSRC = false; + mExpectedSSRC = 0; + mFirstPacketReceived = false; + mFirstSequenceNum = 0; + mFirstTimestamp = 0; + } + + void setExpectedSSRC(int ssrc) { + mVerifySSRC = true; + mExpectedSSRC = ssrc; + } + + int getPacketCount() { + return mTotalPacketCount; + } + + @Override + public void sendStreamPacket(ProtocolMessage pm) { + mExpectedNALUnit = mStream[mNALCount].nalUnit; + // should be same as MockVideoApp's configuration (29.97 FPS) + int expectedPTSDelta = mStream[mNALCount].frameNum * 1001 * 3; + boolean isLast = shouldBeLast(); + + verifyProtocolMessage(pm, SESSION_ID); + + mReceiveBuffer.put(pm.getData()); + mReceiveBuffer.flip(); + + if (mState == STATE_LENGTH) { + if (mReceiveBuffer.remaining() >= 2) { + mPacketLen = mReceiveBuffer.getShort() & 0xFFFF; + mState = STATE_PACKET; + } + } + + if (mState == STATE_PACKET) { + if (mReceiveBuffer.remaining() >= mPacketLen) { + byte[] packet = new byte[mPacketLen]; + mReceiveBuffer.get(packet); + + verifyRTPPacket(packet, mPayloadType, expectedPTSDelta, + mVerifySSRC, mExpectedSSRC, isLast); + mFirstPacketReceived = true; + + mState = STATE_LENGTH; + mPacketLen = 0; + mTotalPacketCount++; + } + } + + mReceiveBuffer.compact(); + } + + private void verifyProtocolMessage(ProtocolMessage pm, byte sessionId) { + assertEquals(true, pm != null); + assertEquals(sessionId, pm.getSessionID()); + assertEquals(SessionType.NAV, pm.getSessionType()); + assertEquals(0, pm.getFunctionID()); + assertEquals(0, pm.getCorrID()); + assertEquals(false, pm.getPayloadProtected()); + } + + private void verifyRTPPacket(byte[] packet, byte payloadType, int expectedPTSDelta, + boolean verifySSRC, int expectedSSRC, boolean isLast) { + assertTrue(packet.length > RTP_HEADER_LEN); + verifyRTPHeader(packet, false, isLast, payloadType, (short)(mTotalPacketCount % 65536), + expectedPTSDelta, verifySSRC, expectedSSRC); + + byte type = (byte)(packet[RTP_HEADER_LEN] & 0x1F); + if (type == 28) { // FU-A frame + boolean fuEnd = verifyFUTypeA(packet); + if (fuEnd) { + mNALCount++; + } + } else if (type == 29) { // FU-B frame + fail("Fragmentation Unit B is not supported by this test"); + } else if (type == 24 || type == 25 || type == 26 || type == 27) { + fail("STAP and MTAP are not supported by this test"); + } else { + // Single Frame + verifySingleFrame(packet); + mNALCount++; + } + } + + private void verifyRTPHeader(byte[] packet, + boolean hasPadding, boolean isLast, byte payloadType, + short seqNumDelta, int ptsDelta, boolean checkSSRC, int ssrc) { + int byte0 = packet[0] & 0xFF; + assertEquals((byte)2, (byte)((byte0 >> 6) & 3)); // version + assertEquals((byte)(hasPadding ? 1 : 0), (byte)((byte0 >> 5) & 1)); // padding + assertEquals((byte)0, (byte)((byte0 >> 4) & 1)); // extension + assertEquals((byte)0, (byte)(byte0 & 0xF)); // CSRC count + + int byte1 = packet[1] & 0xFF; + assertEquals((byte)(isLast ? 1 : 0), (byte)((byte1 >> 7) & 1)); // marker + assertEquals(payloadType, (byte)(byte1 & 0x7F)); // Payload Type + + short actualSeq = (short)(((packet[2] & 0xFF) << 8) | (packet[3] & 0xFF)); + if (!mFirstPacketReceived) { + mFirstSequenceNum = actualSeq; + } else { + assertEquals((short)(mFirstSequenceNum + seqNumDelta), actualSeq); + } + + int actualPTS = ((packet[4] & 0xFF) << 24) | ((packet[5] & 0xFF) << 16) | + ((packet[6] & 0xFF) << 8) | (packet[7] & 0xFF); + if (!mFirstPacketReceived) { + mFirstTimestamp = actualPTS; + } else { + // accept calculation error + assertTrue(mFirstTimestamp + ptsDelta - 1 <= actualPTS && + actualPTS <= mFirstTimestamp + ptsDelta + 1); + } + + if (checkSSRC) { + int actualSSRC = ((packet[8] & 0xFF) << 24) | ((packet[9] & 0xFF) << 16) | + ((packet[10] & 0xFF) << 8) | (packet[11] & 0xFF); + assertEquals(ssrc, actualSSRC); + } + } + + private void verifySingleFrame(byte[] packet) { + assertEquals(true, arrayCompare(packet, RTP_HEADER_LEN, packet.length - RTP_HEADER_LEN, + mExpectedNALUnit, 0, mExpectedNALUnit.length)); + } + + private boolean verifyFUTypeA(byte[] packet) { + int firstByte = mExpectedNALUnit[0] & 0xFF; + + int byte0 = packet[RTP_HEADER_LEN] & 0xFF; + assertEquals((byte)((firstByte >> 7) & 1), (byte)((byte0 >> 7) & 1)); // F bit + assertEquals((byte)((firstByte >> 5) & 3), (byte)((byte0 >> 5) & 3)); // NRI + assertEquals((byte)28, (byte)(byte0 & 0x1F)); // Type + + int byte1 = packet[RTP_HEADER_LEN+1] & 0xFF; + boolean isFirstFU = ((byte1 >> 7) & 1) == 1; // Start bit + boolean isLastFU = ((byte1 >> 6) & 1) == 1; // End bit + assertEquals((byte)0, (byte)((byte1 >> 5) & 1)); // Reserved bit + assertEquals((byte)(firstByte & 0x1F), (byte)(byte1 & 0x1F)); // Type + + int len = packet.length - (RTP_HEADER_LEN + 2); + assertEquals(true, arrayCompare(packet, RTP_HEADER_LEN + 2, len, mExpectedNALUnit, mOffsetInNALUnit, len)); + mOffsetInNALUnit += len; + + if (!mFragmented) { + // this should be the first fragmentation unit + assertEquals(true, isFirstFU); + assertEquals(false, isLastFU); + mFragmented = true; + } else { + assertEquals(false, isFirstFU); + if (mExpectedNALUnit.length == mOffsetInNALUnit) { + // this is the last fragmentation unit + assertEquals(true, isLastFU); + + mFragmented = false; + mOffsetInNALUnit = 1; + return true; + } else { + assertEquals(false, isLastFU); + } + } + return false; + } + + private boolean shouldBeLast() { + if (mNALCount + 1 >= mStream.length) { + return true; + } + ByteStreamNALUnit current = mStream[mNALCount]; + ByteStreamNALUnit next = mStream[mNALCount + 1]; + if (next.frameNum != current.frameNum) { + return true; + } else { + return false; + } + } + + private boolean arrayCompare(byte[] a1, int start1, int len1, byte[] a2, int start2, int len2) { + assertTrue(start1 + len1 <= a1.length); + assertTrue(start2 + len2 <= a2.length); + + if (len1 != len2) { + return false; + } + + for (int i = 0; i < len1; i++) { + if (a1[start1 + i] != a2[start2 + i]) { + return false; + } + } + return true; + } + } + + private interface IVideoFrameSender { + void onVideoFrame(byte[] data, long timestampUs); + } + + private class MockVideoApp { + private IVideoStreamListener mListener; + private int mFPSNum; + private int mFPSDen; + + MockVideoApp(IVideoStreamListener listener) { + mListener = listener; + // 29.97 fps + mFPSNum = 30000; + mFPSDen = 1001; + } + + void inputByteStreamWithArray(ByteStreamNALUnit[] stream) { + generateFramesFromStream(stream, new IVideoFrameSender() { + @Override + public void onVideoFrame(byte[] data, long timestampUs) { + byte[] buffer = new byte[data.length]; + System.arraycopy(data, 0, buffer, 0, data.length); + mListener.sendFrame(buffer, 0, data.length, timestampUs); + } + }); + } + + void inputByteStreamWithArrayOffset(ByteStreamNALUnit[] stream) { + generateFramesFromStream(stream, new IVideoFrameSender() { + private int mDummyOffset = 0; + + @Override + public void onVideoFrame(byte[] data, long timestampUs) { + // to test 'offset' param, create a buffer with a dummy offset + byte[] buffer = new byte[mDummyOffset + data.length]; + System.arraycopy(data, 0, buffer, mDummyOffset, data.length); + + mListener.sendFrame(buffer, mDummyOffset, data.length, timestampUs); + mDummyOffset++; + } + }); + } + + void inputByteStreamWithByteBuffer(ByteStreamNALUnit[] stream) { + generateFramesFromStream(stream, new IVideoFrameSender() { + private int mDummyOffset = 0; + + @Override + public void onVideoFrame(byte[] data, long timestampUs) { + // add a dummy offset inside byteBuffer for testing + ByteBuffer byteBuffer = ByteBuffer.allocate(mDummyOffset + data.length); + byteBuffer.position(mDummyOffset); + + byteBuffer.put(data); + byteBuffer.flip(); + byteBuffer.position(mDummyOffset); + + mListener.sendFrame(byteBuffer, timestampUs); + mDummyOffset++; + } + }); + } + + void inputByteStreamWithDirectByteBuffer(ByteStreamNALUnit[] stream) { + generateFramesFromStream(stream, new IVideoFrameSender() { + private int mDummyOffset = 0; + + @Override + public void onVideoFrame(byte[] data, long timestampUs) { + // add a dummy offset inside byteBuffer for testing + ByteBuffer byteBuffer = ByteBuffer.allocateDirect(mDummyOffset + data.length); + byteBuffer.position(mDummyOffset); + + byteBuffer.put(data); + byteBuffer.flip(); + byteBuffer.position(mDummyOffset); + + mListener.sendFrame(byteBuffer, timestampUs); + mDummyOffset++; + } + }); + } + + private void generateFramesFromStream(ByteStreamNALUnit[] stream, IVideoFrameSender callback) { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + + for (int i = 0; i < stream.length; i++) { + ByteStreamNALUnit bs = stream[i]; + byte[] array = bs.createArray(); + os.write(array, 0, array.length); + + if (i < stream.length - 1) { + ByteStreamNALUnit next = stream[i + 1]; + if (bs.frameNum == next.frameNum) { + // enqueue it and send at once + continue; + } + } + + long timestampUs = bs.frameNum * 1000L * 1000L * mFPSDen / mFPSNum; + byte[] data = os.toByteArray(); + callback.onVideoFrame(data, timestampUs); + os.reset(); + } + + try { + os.close(); + } catch (IOException e) { + } + } + } +} diff --git a/sdl_android/src/androidTest/java/com/smartdevicelink/test/streaming/StreamPacketizerTests.java b/sdl_android/src/androidTest/java/com/smartdevicelink/test/streaming/StreamPacketizerTests.java index 218e904b3..5f5bd6d2b 100644 --- a/sdl_android/src/androidTest/java/com/smartdevicelink/test/streaming/StreamPacketizerTests.java +++ b/sdl_android/src/androidTest/java/com/smartdevicelink/test/streaming/StreamPacketizerTests.java @@ -2,13 +2,18 @@ package com.smartdevicelink.test.streaming; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.net.URLConnection; +import java.nio.ByteBuffer; +import java.util.Arrays; import com.smartdevicelink.SdlConnection.SdlSession; +import com.smartdevicelink.protocol.ProtocolMessage; import com.smartdevicelink.protocol.enums.SessionType; +import com.smartdevicelink.proxy.interfaces.IVideoStreamListener; import com.smartdevicelink.streaming.IStreamListener; import com.smartdevicelink.streaming.StreamPacketizer; import com.smartdevicelink.test.Test; @@ -22,7 +27,96 @@ import junit.framework.TestCase; * {@link com.smartdevicelink.streaming.StreamPacketizer} */ public class StreamPacketizerTests extends TestCase { - + + private static final byte WIPRO_VERSION = 0x0B; + private static final byte SESSION_ID = 0x0A; + + private final byte[][] SAMPLE_H264_VIDEO_STREAM = { + // one byte array represents a frame + new byte[]{0x00, 0x00, 0x00, 0x01, + 0x67, 0x42, (byte)0xC0, 0x0A, (byte)0xA6, 0x11, 0x11, (byte)0xE8, + 0x40, 0x00, 0x00, (byte)0xFA, 0x40, 0x00, 0x3A, (byte)0x98, + 0x23, (byte)0xC4, (byte)0x89, (byte)0x84, 0x60, + 0x00, 0x00, 0x00, 0x01, + 0x68, (byte)0xC8, 0x42, 0x0F, 0x13, 0x20, + 0x00, 0x00, 0x01, + 0x65, (byte)0x88, (byte)0x82, 0x07, 0x67, 0x39, 0x31, 0x40, + 0x00, 0x5E, 0x0A, (byte)0xFB, (byte)0xEF, (byte)0xAE, (byte)0xBA, (byte)0xEB, + (byte)0xAE, (byte)0xBA, (byte)0xEB, (byte)0xC0}, + new byte[]{0x00, 0x00, 0x00, 0x01, + 0x41, (byte)0x9A, 0x1C, 0x0E, (byte)0xCE, 0x71, (byte)0xB0}, + new byte[]{0x00, 0x00, 0x00, 0x01, + 0x41, (byte)0x9A, 0x2A, 0x03, (byte)0xB3, (byte)0x9C, 0x6C}, + new byte[]{0x00, 0x00, 0x00, 0x01, + 0x41, (byte)0x9A, 0x3B, 0x03, (byte)0xB3, (byte)0x9C, 0x6C}, + new byte[]{0x00, 0x00, 0x00, 0x01, + 0x41, (byte)0x9A, 0x49, 0x00, (byte)0xEC, (byte)0xE7, 0x1B}, + new byte[]{0x00, 0x00, 0x00, 0x01, + 0x41, (byte)0x9A, 0x59, 0x40, (byte)0xEC, (byte)0xE7, 0x1B}, + new byte[]{0x00, 0x00, 0x00, 0x01, + 0x41, (byte)0x9A, 0x69, (byte)0x80, (byte)0xEC, (byte)0xE7, 0x1B}, + new byte[]{0x00, 0x00, 0x00, 0x01, + 0x41, (byte)0x9A, 0x79, (byte)0xC0, (byte)0xEC, (byte)0xE7, 0x1B}, + new byte[]{0x00, 0x00, 0x00, 0x01, + 0x41, (byte)0x9A, (byte)0x88, (byte)0x80, 0x3B, 0x39, (byte)0xC6, (byte)0xC0}, + new byte[]{0x00, 0x00, 0x00, 0x01, + 0x41, (byte)0x9A, (byte)0x98, (byte)0x90, 0x3B, 0x39, (byte)0xC6, (byte)0xC0}, + new byte[]{0x00, 0x00, 0x00, 0x01, + 0x41, (byte)0x9A, (byte)0xA8, (byte)0xA0, 0x3B, 0x39, (byte)0xC6, (byte)0xC0}, + new byte[]{0x00, 0x00, 0x00, 0x01, + 0x41, (byte)0x9A, (byte)0xB8, (byte)0xB0, 0x3B, 0x39, (byte)0xC6, (byte)0xC0}, + new byte[]{0x00, 0x00, 0x00, 0x01, + 0x41, (byte)0x9A, (byte)0xC8, (byte)0xC0, 0x3B, 0x39, (byte)0xC6, (byte)0xC0}, + new byte[]{0x00, 0x00, 0x00, 0x01, + 0x41, (byte)0x9A, (byte)0xD8, (byte)0xD0, 0x3B, 0x39, (byte)0xC6, (byte)0xC0}, + new byte[]{0x00, 0x00, 0x00, 0x01, + 0x41, (byte)0x9A, (byte)0xE8, (byte)0xE0, 0x3B, 0x39, (byte)0xC6, (byte)0xC0}, + new byte[]{0x00, 0x00, 0x00, 0x01, + 0x41, (byte)0x9A, (byte)0xF8, (byte)0xF0, 0x3B, 0x39, (byte)0xC6, (byte)0xC0}, + new byte[]{0x00, 0x00, 0x00, 0x01, + 0x41, (byte)0x9B, 0x00, 0x1D, (byte)0x9C, (byte)0xE3, 0x60}, + new byte[]{0x00, 0x00, 0x00, 0x01, + 0x41, (byte)0x9B, 0x10, 0x1D, (byte)0x9C, (byte)0xE3, 0x60}, + new byte[]{0x00, 0x00, 0x00, 0x01, + 0x41, (byte)0x9B, 0x20, 0x1D, (byte)0x9C, (byte)0xE3, 0x60}, + new byte[]{0x00, 0x00, 0x00, 0x01, + 0x41, (byte)0x9B, 0x30, 0x1D, (byte)0x9C, (byte)0xE3, 0x60}, + new byte[]{0x00, 0x00, 0x00, 0x01, + 0x41, (byte)0x9B, 0x40, 0x1D, (byte)0x9C, (byte)0xE3, 0x60}, + new byte[]{0x00, 0x00, 0x00, 0x01, + 0x41, (byte)0x9B, 0x50, 0x1D, (byte)0x9C, (byte)0xE3, 0x60}, + new byte[]{0x00, 0x00, 0x00, 0x01, + 0x41, (byte)0x9B, 0x60, 0x1D, (byte)0x9C, (byte)0xE3, 0x60}, + new byte[]{0x00, 0x00, 0x00, 0x01, + 0x41, (byte)0x9B, 0x70, 0x1D, (byte)0x9C, (byte)0xE3, 0x60}, + new byte[]{0x00, 0x00, 0x00, 0x01, + 0x41, (byte)0x9B, (byte)0x80, 0x1D, (byte)0x9C, (byte)0xE3, 0x60}, + new byte[]{0x00, 0x00, 0x00, 0x01, + 0x41, (byte)0x9B, (byte)0x90, 0x1D, (byte)0x9C, (byte)0xE3, 0x60}, + new byte[]{0x00, 0x00, 0x00, 0x01, + 0x41, (byte)0x9B, (byte)0xA0, 0x1D, (byte)0x9C, (byte)0xE3, 0x60}, + new byte[]{0x00, 0x00, 0x00, 0x01, + 0x41, (byte)0x9B, (byte)0xB0, 0x1D, (byte)0x9C, (byte)0xE3, 0x60}, + new byte[]{0x00, 0x00, 0x00, 0x01, + 0x41, (byte)0x9B, (byte)0xC0, 0x1D, (byte)0x9C, (byte)0xE3, 0x60}, + new byte[]{0x00, 0x00, 0x00, 0x01, + 0x41, (byte)0x9B, (byte)0xD0, 0x1D, (byte)0x9C, (byte)0xE3, 0x60}, + new byte[]{0x00, 0x00, 0x00, 0x01, + 0x67, 0x42, (byte)0xC0, 0x0A, (byte)0xA6, 0x11, 0x11, (byte)0xE8, + 0x40, 0x00, 0x00, (byte)0xFA, 0x40, 0x00, 0x3A, (byte)0x98, + 0x23, (byte)0xC4, (byte)0x89, (byte)0x84, 0x60, + 0x00, 0x00, 0x00, 0x01, + 0x68, (byte)0xC8, 0x42, 0x0F, 0x13, 0x20, + 0x00, 0x00, 0x01, + 0x65, (byte)0x88, (byte)0x81, 0x00, (byte)0x8E, 0x73, (byte)0x93, 0x14, + 0x00, 0x06, (byte)0xA4, 0x2F, (byte)0xBE, (byte)0xFA, (byte)0xEB, (byte)0xAE, + (byte)0xBA, (byte)0xEB, (byte)0xAE, (byte)0xBC}, + new byte[]{0x00, 0x00, 0x00, 0x01, + 0x41, (byte)0x9A, 0x1C, 0x0D, (byte)0xCE, 0x71, (byte)0xB0}, + new byte[]{0x00, 0x00, 0x00, 0x01, + 0x41, (byte)0x9A, 0x2A, 0x03, 0x33, (byte)0x9C, 0x6C}, + }; + /** * This is a unit test for the following methods : * {@link com.smartdevicelink.streaming.StreamPacketizer#StreamPacketizer(IStreamListener, InputStream, SessionType, byte)} @@ -49,4 +143,369 @@ public class StreamPacketizerTests extends TestCase { fail("IOException was thrown."); } } + + /** + * Test for {@link com.smartdevicelink.streaming.StreamPacketizer#sendFrame(byte[], int, int, long)} + */ + public void testSendFrameInterfaceWithArray() { + StreamReceiver mockReceiver = new StreamReceiver(); + SdlSession session = createTestSession(); + StreamPacketizer packetizer = null; + try { + packetizer = new StreamPacketizer(mockReceiver, null, SessionType.NAV, SESSION_ID, session); + } catch (IOException e) { + fail(); + } + MockVideoApp mockApp = new MockVideoApp(packetizer); + + try { + packetizer.start(); + } catch (IOException e) { + fail(); + } + + mockApp.inputByteStreamWithArray(SAMPLE_H264_VIDEO_STREAM); + try { + Thread.sleep(1000, 0); + } catch (InterruptedException e) {} + + packetizer.stop(); + assertTrue(mockReceiver.verify(SAMPLE_H264_VIDEO_STREAM)); + } + + /** + * Test for {@link com.smartdevicelink.streaming.StreamPacketizer#sendFrame(byte[], int, int, long)} + * with offset parameter + */ + public void testSendFrameInterfaceWithArrayOffset() { + StreamReceiver mockReceiver = new StreamReceiver(); + SdlSession session = createTestSession(); + StreamPacketizer packetizer = null; + try { + packetizer = new StreamPacketizer(mockReceiver, null, SessionType.NAV, SESSION_ID, session); + } catch (IOException e) { + fail(); + } + MockVideoApp mockApp = new MockVideoApp(packetizer); + + try { + packetizer.start(); + } catch (IOException e) { + fail(); + } + + mockApp.inputByteStreamWithArrayOffset(SAMPLE_H264_VIDEO_STREAM); + try { + Thread.sleep(1000, 0); + } catch (InterruptedException e) {} + + packetizer.stop(); + assertTrue(mockReceiver.verify(SAMPLE_H264_VIDEO_STREAM)); + } + + /** + * Test for {@link com.smartdevicelink.streaming.StreamPacketizer#sendFrame(ByteBuffer, long)} + */ + public void testSendFrameInterfaceWithByteBuffer() { + StreamReceiver mockReceiver = new StreamReceiver(); + SdlSession session = createTestSession(); + StreamPacketizer packetizer = null; + try { + packetizer = new StreamPacketizer(mockReceiver, null, SessionType.NAV, SESSION_ID, session); + } catch (IOException e) { + fail(); + } + MockVideoApp mockApp = new MockVideoApp(packetizer); + + try { + packetizer.start(); + } catch (IOException e) { + fail(); + } + + mockApp.inputByteStreamWithByteBuffer(SAMPLE_H264_VIDEO_STREAM); + try { + Thread.sleep(1000, 0); + } catch (InterruptedException e) {} + + packetizer.stop(); + assertTrue(mockReceiver.verify(SAMPLE_H264_VIDEO_STREAM)); + } + + /** + * Test for {@link com.smartdevicelink.streaming.StreamPacketizer#sendFrame(ByteBuffer, long)} + * with direct ByteBuffer + */ + public void testSendFrameInterfaceWithDirectByteBuffer() { + StreamReceiver mockReceiver = new StreamReceiver(); + SdlSession session = createTestSession(); + StreamPacketizer packetizer = null; + try { + packetizer = new StreamPacketizer(mockReceiver, null, SessionType.NAV, SESSION_ID, session); + } catch (IOException e) { + fail(); + } + MockVideoApp mockApp = new MockVideoApp(packetizer); + + try { + packetizer.start(); + } catch (IOException e) { + fail(); + } + + mockApp.inputByteStreamWithDirectByteBuffer(SAMPLE_H264_VIDEO_STREAM); + try { + Thread.sleep(1000, 0); + } catch (InterruptedException e) {} + + packetizer.stop(); + assertTrue(mockReceiver.verify(SAMPLE_H264_VIDEO_STREAM)); + } + + /** + * Test for {@link com.smartdevicelink.streaming.StreamPacketizer#sendAudio(byte[], int, int, long)} + */ + public void testSendAudioInterfaceWithArray() { + // assume 100 data of 16kHz / 16bits audio for 10 msecs + int dataCount = 100; + byte[][] sampleAudio = new byte[dataCount][]; + for (int i = 0; i < dataCount; i++) { + sampleAudio[i] = new byte[4 * 160]; + Arrays.fill(sampleAudio[i], (byte)0); + } + + StreamReceiver mockReceiver = new StreamReceiver(); + SdlSession session = createTestSession(); + StreamPacketizer packetizer = null; + try { + packetizer = new StreamPacketizer(mockReceiver, null, SessionType.NAV, SESSION_ID, session); + } catch (IOException e) { + fail(); + } + MockVideoApp mockApp = new MockVideoApp(packetizer); + + try { + packetizer.start(); + } catch (IOException e) { + fail(); + } + + mockApp.inputByteStreamWithArray(sampleAudio); + try { + Thread.sleep(1000, 0); + } catch (InterruptedException e) {} + + packetizer.stop(); + assertTrue(mockReceiver.verify(sampleAudio)); + } + + /** + * Test for {@link com.smartdevicelink.streaming.StreamPacketizer#sendAudio(byte[], int, int, long)} + */ + public void testSendAudioInterfaceWithArrayOffset() { + // assume 100 data of 16kHz / 16bits audio for 10 msecs + int dataCount = 100; + byte[][] sampleAudio = new byte[dataCount][]; + for (int i = 0; i < dataCount; i++) { + sampleAudio[i] = new byte[4 * 160]; + Arrays.fill(sampleAudio[i], (byte)0); + } + + StreamReceiver mockReceiver = new StreamReceiver(); + SdlSession session = createTestSession(); + StreamPacketizer packetizer = null; + try { + packetizer = new StreamPacketizer(mockReceiver, null, SessionType.NAV, SESSION_ID, session); + } catch (IOException e) { + fail(); + } + MockVideoApp mockApp = new MockVideoApp(packetizer); + + try { + packetizer.start(); + } catch (IOException e) { + fail(); + } + + mockApp.inputByteStreamWithArrayOffset(sampleAudio); + try { + Thread.sleep(1000, 0); + } catch (InterruptedException e) {} + + packetizer.stop(); + assertTrue(mockReceiver.verify(sampleAudio)); + } + + /** + * Test for {@link com.smartdevicelink.streaming.StreamPacketizer#sendAudio(ByteBuffer, long)} + */ + public void testSendAudioInterfaceWithByteBuffer() { + // assume 100 data of 16kHz / 16bits audio for 10 msecs + int dataCount = 100; + byte[][] sampleAudio = new byte[dataCount][]; + for (int i = 0; i < dataCount; i++) { + sampleAudio[i] = new byte[4 * 160]; + Arrays.fill(sampleAudio[i], (byte)0); + } + + StreamReceiver mockReceiver = new StreamReceiver(); + SdlSession session = createTestSession(); + StreamPacketizer packetizer = null; + try { + packetizer = new StreamPacketizer(mockReceiver, null, SessionType.NAV, SESSION_ID, session); + } catch (IOException e) { + fail(); + } + MockVideoApp mockApp = new MockVideoApp(packetizer); + + try { + packetizer.start(); + } catch (IOException e) { + fail(); + } + + mockApp.inputByteStreamWithByteBuffer(sampleAudio); + try { + Thread.sleep(1000, 0); + } catch (InterruptedException e) {} + + packetizer.stop(); + assertTrue(mockReceiver.verify(sampleAudio)); + } + + /** + * Test for {@link com.smartdevicelink.streaming.StreamPacketizer#sendAudio(ByteBuffer, long)} + * with direct ByteBuffer + */ + public void testSendAudioInterfaceWithDirectByteBuffer() { + // assume 100 data of 16kHz / 16bits audio for 10 msecs + int dataCount = 100; + byte[][] sampleAudio = new byte[dataCount][]; + for (int i = 0; i < dataCount; i++) { + sampleAudio[i] = new byte[4 * 160]; + Arrays.fill(sampleAudio[i], (byte)0); + } + + StreamReceiver mockReceiver = new StreamReceiver(); + SdlSession session = createTestSession(); + StreamPacketizer packetizer = null; + try { + packetizer = new StreamPacketizer(mockReceiver, null, SessionType.NAV, SESSION_ID, session); + } catch (IOException e) { + fail(); + } + MockVideoApp mockApp = new MockVideoApp(packetizer); + + try { + packetizer.start(); + } catch (IOException e) { + fail(); + } + + mockApp.inputByteStreamWithDirectByteBuffer(sampleAudio); + try { + Thread.sleep(1000, 0); + } catch (InterruptedException e) {} + + packetizer.stop(); + assertTrue(mockReceiver.verify(sampleAudio)); + } + + + private SdlSession createTestSession() { + return SdlSession.createSession(WIPRO_VERSION, new MockInterfaceBroker(), new BTTransportConfig(true)); + } + + private class StreamReceiver implements IStreamListener { + private ByteArrayOutputStream mReceiveBuffer; + + StreamReceiver() { + mReceiveBuffer = new ByteArrayOutputStream(); + } + + @Override + public void sendStreamPacket(ProtocolMessage pm) { + try { + mReceiveBuffer.write(pm.getData()); + } catch (IOException e) { + fail(); + } + } + + boolean verify(byte[][] expectedStream) { + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + for (byte[] frame : expectedStream) { + try { + buffer.write(frame); + } catch (IOException e) { + fail(); + } + } + boolean result = Arrays.equals(buffer.toByteArray(), mReceiveBuffer.toByteArray()); + try { + buffer.close(); + } catch (IOException e) { + fail(); + } + return result; + } + } + + private class MockVideoApp { + private IVideoStreamListener mListener; + + MockVideoApp(IVideoStreamListener listener) { + mListener = listener; + } + + void inputByteStreamWithArray(byte[][] stream) { + for (byte[] data : stream) { + mListener.sendFrame(data, 0, data.length, -1); + } + } + + void inputByteStreamWithArrayOffset(byte[][] stream) { + int dummyOffset = 0; + for (byte[] data : stream) { + // to test 'offset' param, create a buffer with a dummy offset + byte[] buffer = new byte[dummyOffset + data.length]; + System.arraycopy(data, 0, buffer, dummyOffset, data.length); + + mListener.sendFrame(buffer, dummyOffset, data.length, -1); + dummyOffset++; + } + } + + void inputByteStreamWithByteBuffer(byte[][] stream) { + int dummyOffset = 0; + for (byte[] data : stream) { + // add a dummy offset inside byteBuffer for testing + ByteBuffer byteBuffer = ByteBuffer.allocate(dummyOffset + data.length); + byteBuffer.position(dummyOffset); + + byteBuffer.put(data); + byteBuffer.flip(); + byteBuffer.position(dummyOffset); + + mListener.sendFrame(byteBuffer, -1); + dummyOffset++; + } + } + + void inputByteStreamWithDirectByteBuffer(byte[][] stream) { + int dummyOffset = 0; + for (byte[] data : stream) { + // add a dummy offset inside byteBuffer for testing + ByteBuffer byteBuffer = ByteBuffer.allocateDirect(dummyOffset + data.length); + byteBuffer.position(dummyOffset); + + byteBuffer.put(data); + byteBuffer.flip(); + byteBuffer.position(dummyOffset); + + mListener.sendFrame(byteBuffer, -1); + dummyOffset++; + } + } + } }
\ No newline at end of file diff --git a/sdl_android/src/main/java/com/smartdevicelink/SdlConnection/ISdlConnectionListener.java b/sdl_android/src/main/java/com/smartdevicelink/SdlConnection/ISdlConnectionListener.java index f4b4c43d9..16350da4b 100644 --- a/sdl_android/src/main/java/com/smartdevicelink/SdlConnection/ISdlConnectionListener.java +++ b/sdl_android/src/main/java/com/smartdevicelink/SdlConnection/ISdlConnectionListener.java @@ -3,6 +3,8 @@ package com.smartdevicelink.SdlConnection; import com.smartdevicelink.protocol.ProtocolMessage;
import com.smartdevicelink.protocol.enums.SessionType;
+import java.util.List;
+
public interface ISdlConnectionListener {
public void onTransportDisconnected(String info);
@@ -12,7 +14,7 @@ public interface ISdlConnectionListener { public void onProtocolMessageReceived(ProtocolMessage msg);
public void onProtocolSessionStartedNACKed(SessionType sessionType,
- byte sessionID, byte version, String correlationID);
+ byte sessionID, byte version, String correlationID, List<String> rejectedParams);
public void onProtocolSessionStarted(SessionType sessionType,
byte sessionID, byte version, String correlationID, int hashID, boolean isEncrypted);
diff --git a/sdl_android/src/main/java/com/smartdevicelink/SdlConnection/SdlConnection.java b/sdl_android/src/main/java/com/smartdevicelink/SdlConnection/SdlConnection.java index 272c1878d..b346884aa 100644 --- a/sdl_android/src/main/java/com/smartdevicelink/SdlConnection/SdlConnection.java +++ b/sdl_android/src/main/java/com/smartdevicelink/SdlConnection/SdlConnection.java @@ -1,6 +1,7 @@ package com.smartdevicelink.SdlConnection;
+import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import android.content.ComponentName;
@@ -263,8 +264,9 @@ public class SdlConnection implements IProtocolListener, ITransportListener { @Override
public void onProtocolSessionNACKed(SessionType sessionType,
- byte sessionID, byte version, String correlationID) {
- _connectionListener.onProtocolSessionStartedNACKed(sessionType, sessionID, version, correlationID);
+ byte sessionID, byte version, String correlationID, List<String> rejectedParams) {
+ _connectionListener.onProtocolSessionStartedNACKed(sessionType,
+ sessionID, version, correlationID, rejectedParams);
}
@Override
@@ -433,10 +435,11 @@ public class SdlConnection implements IProtocolListener, ITransportListener { @Override
public void onProtocolSessionStartedNACKed(SessionType sessionType,
- byte sessionID, byte version, String correlationID) {
+ byte sessionID, byte version, String correlationID, List<String> rejectedParams) {
SdlSession session = findSessionById(sessionID);
if (session != null) {
- session.onProtocolSessionStartedNACKed(sessionType, sessionID, version, correlationID);
+ session.onProtocolSessionStartedNACKed(sessionType,
+ sessionID, version, correlationID, rejectedParams);
}
}
diff --git a/sdl_android/src/main/java/com/smartdevicelink/SdlConnection/SdlSession.java b/sdl_android/src/main/java/com/smartdevicelink/SdlConnection/SdlSession.java index 23521f4bb..f4a9fb97f 100644 --- a/sdl_android/src/main/java/com/smartdevicelink/SdlConnection/SdlSession.java +++ b/sdl_android/src/main/java/com/smartdevicelink/SdlConnection/SdlSession.java @@ -23,10 +23,16 @@ import com.smartdevicelink.protocol.heartbeat.IHeartbeatMonitor; import com.smartdevicelink.protocol.heartbeat.IHeartbeatMonitorListener;
import com.smartdevicelink.proxy.LockScreenManager;
import com.smartdevicelink.proxy.RPCRequest;
+import com.smartdevicelink.proxy.interfaces.IAudioStreamListener;
import com.smartdevicelink.proxy.interfaces.ISdlServiceListener;
+import com.smartdevicelink.proxy.interfaces.IVideoStreamListener;
+import com.smartdevicelink.proxy.rpc.VideoStreamingFormat;
+import com.smartdevicelink.proxy.rpc.enums.VideoStreamingProtocol;
import com.smartdevicelink.security.ISecurityInitializedListener;
import com.smartdevicelink.security.SdlSecurityBase;
+import com.smartdevicelink.streaming.AbstractPacketizer;
import com.smartdevicelink.streaming.IStreamListener;
+import com.smartdevicelink.streaming.RTPH264Packetizer;
import com.smartdevicelink.streaming.StreamPacketizer;
import com.smartdevicelink.streaming.StreamRPCPacketizer;
import com.smartdevicelink.streaming.VideoStreamingParameters;
@@ -49,7 +55,7 @@ public class SdlSession implements ISdlConnectionListener, IHeartbeatMonitorList private LockScreenManager lockScreenMan = new LockScreenManager();
private SdlSecurityBase sdlSecurity = null;
StreamRPCPacketizer mRPCPacketizer = null;
- StreamPacketizer mVideoPacketizer = null;
+ AbstractPacketizer mVideoPacketizer = null;
StreamPacketizer mAudioPacketizer = null;
SdlEncoder mSdlEncoder = null;
private final static int BUFF_READ_SIZE = 1024;
@@ -119,6 +125,14 @@ public class SdlSession implements ISdlConnectionListener, IHeartbeatMonitorList }
}
+ public long getMtu(SessionType type) {
+ if (this._sdlConnection != null) {
+ return this._sdlConnection.getWiProProtocol().getMtu(type);
+ } else {
+ return 0;
+ }
+ }
+
public void close() {
if (sdlSecurity != null)
{
@@ -140,8 +154,10 @@ public class SdlSession implements ISdlConnectionListener, IHeartbeatMonitorList public void startStream(InputStream is, SessionType sType, byte rpcSessionID) throws IOException {
if (sType.equals(SessionType.NAV))
{
- mVideoPacketizer = new StreamPacketizer(this, is, sType, rpcSessionID, this);
- mVideoPacketizer.sdlConnection = this.getSdlConnection();
+ // protocol is fixed to RAW
+ StreamPacketizer packetizer = new StreamPacketizer(this, is, sType, rpcSessionID, this);
+ packetizer.sdlConnection = this.getSdlConnection();
+ mVideoPacketizer = packetizer;
mVideoPacketizer.start();
}
else if (sType.equals(SessionType.PCM))
@@ -163,8 +179,10 @@ public class SdlSession implements ISdlConnectionListener, IHeartbeatMonitorList }
if (sType.equals(SessionType.NAV))
{
- mVideoPacketizer = new StreamPacketizer(this, is, sType, rpcSessionID, this);
- mVideoPacketizer.sdlConnection = this.getSdlConnection();
+ // protocol is fixed to RAW
+ StreamPacketizer packetizer = new StreamPacketizer(this, is, sType, rpcSessionID, this);
+ packetizer.sdlConnection = this.getSdlConnection();
+ mVideoPacketizer = packetizer;
mVideoPacketizer.start();
}
else if (sType.equals(SessionType.PCM))
@@ -181,7 +199,47 @@ public class SdlSession implements ISdlConnectionListener, IHeartbeatMonitorList }
return os;
}
-
+
+ public IVideoStreamListener startVideoStream() {
+ byte rpcSessionID = getSessionId();
+ VideoStreamingProtocol protocol = getAcceptedProtocol();
+ try {
+ switch (protocol) {
+ case RAW: {
+ StreamPacketizer packetizer = new StreamPacketizer(this, null, SessionType.NAV, rpcSessionID, this);
+ packetizer.sdlConnection = this.getSdlConnection();
+ mVideoPacketizer = packetizer;
+ mVideoPacketizer.start();
+ return packetizer;
+ }
+ case RTP: {
+ RTPH264Packetizer packetizer = new RTPH264Packetizer(this, SessionType.NAV, rpcSessionID, this);
+ mVideoPacketizer = packetizer;
+ mVideoPacketizer.start();
+ return packetizer;
+ }
+ default:
+ Log.e(TAG, "Protocol " + protocol + " is not supported.");
+ return null;
+ }
+ } catch (IOException e) {
+ return null;
+ }
+ }
+
+ public IAudioStreamListener startAudioStream() {
+ byte rpcSessionID = getSessionId();
+ try {
+ StreamPacketizer packetizer = new StreamPacketizer(this, null, SessionType.PCM, rpcSessionID, this);
+ packetizer.sdlConnection = this.getSdlConnection();
+ mAudioPacketizer = packetizer;
+ mAudioPacketizer.start();
+ return packetizer;
+ } catch (IOException e) {
+ return null;
+ }
+ }
+
public void startRPCStream(InputStream is, RPCRequest request, SessionType sType, byte rpcSessionID, byte wiproVersion) {
try {
mRPCPacketizer = new StreamRPCPacketizer(null, this, is, request, sType, rpcSessionID, wiproVersion, 0, this);
@@ -290,19 +348,18 @@ public class SdlSession implements ISdlConnectionListener, IHeartbeatMonitorList public Surface createOpenGLInputSurface(int frameRate, int iFrameInterval, int width,
int height, int bitrate, SessionType sType, byte rpcSessionID) {
- try {
- PipedOutputStream stream = (PipedOutputStream) startStream(sType, rpcSessionID);
- if (stream == null) return null;
- mSdlEncoder = new SdlEncoder();
- mSdlEncoder.setFrameRate(frameRate);
- mSdlEncoder.setFrameInterval(iFrameInterval);
- mSdlEncoder.setFrameWidth(width);
- mSdlEncoder.setFrameHeight(height);
- mSdlEncoder.setBitrate(bitrate);
- mSdlEncoder.setOutputStream(stream);
- } catch (IOException e) {
+ IVideoStreamListener encoderListener = startVideoStream();
+ if (encoderListener == null) {
return null;
}
+
+ mSdlEncoder = new SdlEncoder();
+ mSdlEncoder.setFrameRate(frameRate);
+ mSdlEncoder.setFrameInterval(iFrameInterval);
+ mSdlEncoder.setFrameWidth(width);
+ mSdlEncoder.setFrameHeight(height);
+ mSdlEncoder.setBitrate(bitrate);
+ mSdlEncoder.setOutputListener(encoderListener);
return mSdlEncoder.prepareEncoder();
}
@@ -551,8 +608,9 @@ public class SdlSession implements ISdlConnectionListener, IHeartbeatMonitorList @Override
public void onProtocolSessionStartedNACKed(SessionType sessionType,
- byte sessionID, byte version, String correlationID) {
- this.sessionListener.onProtocolSessionStartedNACKed(sessionType, sessionID, version, correlationID);
+ byte sessionID, byte version, String correlationID, List<String> rejectedParams) {
+ this.sessionListener.onProtocolSessionStartedNACKed(sessionType,
+ sessionID, version, correlationID, rejectedParams);
if(serviceListeners != null && serviceListeners.containsKey(sessionType)){
CopyOnWriteArrayList<ISdlServiceListener> listeners = serviceListeners.get(sessionType);
for(ISdlServiceListener listener:listeners){
@@ -673,4 +731,18 @@ public class SdlSession implements ISdlConnectionListener, IHeartbeatMonitorList public VideoStreamingParameters getAcceptedVideoParams(){
return acceptedVideoParams;
}
+
+ private VideoStreamingProtocol getAcceptedProtocol() {
+ // acquire default protocol (RAW)
+ VideoStreamingProtocol protocol = new VideoStreamingParameters().getFormat().getProtocol();
+
+ if (acceptedVideoParams != null) {
+ VideoStreamingFormat format = acceptedVideoParams.getFormat();
+ if (format != null && format.getProtocol() != null) {
+ protocol = format.getProtocol();
+ }
+ }
+
+ return protocol;
+ }
}
diff --git a/sdl_android/src/main/java/com/smartdevicelink/encoder/EncoderUtils.java b/sdl_android/src/main/java/com/smartdevicelink/encoder/EncoderUtils.java new file mode 100644 index 000000000..362564da8 --- /dev/null +++ b/sdl_android/src/main/java/com/smartdevicelink/encoder/EncoderUtils.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2017, Xevo Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.smartdevicelink.encoder; + +import android.annotation.TargetApi; +import android.media.MediaFormat; +import android.os.Build; +import android.util.Log; + +import java.nio.ByteBuffer; + +@TargetApi(Build.VERSION_CODES.JELLY_BEAN) +public final class EncoderUtils { + private final static String TAG = "EncoderUtils"; + + /** + * Extracts codec-specific data from MediaFormat instance + * + * Currently, only AVC is supported. + * + * @param format MediaFormat instance retrieved from MediaCodec + * @return byte array containing codec-specific data, or null if an error occurred + */ + public static byte[] getCodecSpecificData(MediaFormat format) { + if (format == null) { + return null; + } + + String name = format.getString(MediaFormat.KEY_MIME); + if (name == null) { + return null; + } + + // same as MediaFormat.MIMETYPE_VIDEO_AVC but it requires API level 21 + if (name.equals("video/avc")) { + return getAVCCodecSpecificData(format); + } else { + Log.w(TAG, "Retrieving codec-specific data for " + name + " is not supported"); + return null; + } + } + + /** + * Extracts H.264 codec-specific data (SPS and PPS) from MediaFormat instance + * + * The codec-specific data is in byte-stream format; 4-byte start codes (0x00 0x00 0x00 0x01) + * are added in front of SPS and PPS NAL units. + * + * @param format MediaFormat instance retrieved from MediaCodec + * @return byte array containing codec-specific data, or null if an error occurred + */ + private static byte[] getAVCCodecSpecificData(MediaFormat format) { + // For H.264, "csd-0" contains SPS and "csd-1" contains PPS. Refer to the documentation + // of MediaCodec. + if (!(format.containsKey("csd-0") && format.containsKey("csd-1"))) { + Log.w(TAG, "H264 codec specific data not found"); + return null; + } + + ByteBuffer sps = format.getByteBuffer("csd-0"); + int spsLen = sps.remaining(); + ByteBuffer pps = format.getByteBuffer("csd-1"); + int ppsLen = pps.remaining(); + + byte[] output = new byte[spsLen + ppsLen]; + try { + sps.get(output, 0, spsLen); + pps.get(output, spsLen, ppsLen); + } catch (Exception e) { + // should not happen + Log.w(TAG, "Error while copying H264 codec specific data: " + e); + return null; + } + + return output; + } + + private EncoderUtils() {} +} diff --git a/sdl_android/src/main/java/com/smartdevicelink/encoder/SdlEncoder.java b/sdl_android/src/main/java/com/smartdevicelink/encoder/SdlEncoder.java index 81e344840..196f5d98c 100644 --- a/sdl_android/src/main/java/com/smartdevicelink/encoder/SdlEncoder.java +++ b/sdl_android/src/main/java/com/smartdevicelink/encoder/SdlEncoder.java @@ -9,11 +9,16 @@ import android.media.MediaCodec; import android.media.MediaCodecInfo; import android.media.MediaFormat; import android.os.Build; +import android.util.Log; import android.view.Surface; +import com.smartdevicelink.proxy.interfaces.IVideoStreamListener; + @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) public class SdlEncoder { - + + private static final String TAG = "SdlEncoder"; + // parameters for the encoder private static final String _MIME_TYPE = "video/avc"; // H.264/AVC video // private static final String MIME_TYPE = "video/mp4v-es"; //MPEG4 video @@ -26,10 +31,13 @@ public class SdlEncoder { // encoder state private MediaCodec mEncoder; private PipedOutputStream mOutputStream; + private IVideoStreamListener mOutputListener; // allocate one of these up front so we don't need to do it every time private MediaCodec.BufferInfo mBufferInfo; - + + // Codec-specific data (SPS and PPS) + private byte[] mH264CodecSpecificData = null; public SdlEncoder () { } @@ -51,6 +59,9 @@ public class SdlEncoder { public void setOutputStream(PipedOutputStream mStream){ mOutputStream = mStream; } + public void setOutputListener(IVideoStreamListener listener) { + mOutputListener = listener; + } public Surface prepareEncoder () { mBufferInfo = new MediaCodec.BufferInfo(); @@ -114,6 +125,7 @@ public class SdlEncoder { } mOutputStream = null; } + mH264CodecSpecificData = null; } /** @@ -127,7 +139,7 @@ public class SdlEncoder { public void drainEncoder(boolean endOfStream) { final int TIMEOUT_USEC = 10000; - if(mEncoder == null || mOutputStream == null) { + if(mEncoder == null || (mOutputStream == null && mOutputListener == null)) { return; } if (endOfStream) { @@ -147,15 +159,45 @@ public class SdlEncoder { // not expected for an encoder encoderOutputBuffers = mEncoder.getOutputBuffers(); } else if (encoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) { + if (mH264CodecSpecificData == null) { + MediaFormat format = mEncoder.getOutputFormat(); + mH264CodecSpecificData = EncoderUtils.getCodecSpecificData(format); + } else { + Log.w(TAG, "Output format change notified more than once, ignoring."); + } } else if (encoderStatus < 0) { } else { + if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) { + // If we already retrieve codec specific data via OUTPUT_FORMAT_CHANGED event, + // we do not need this data. + if (mH264CodecSpecificData != null) { + mBufferInfo.size = 0; + } else { + Log.i(TAG, "H264 codec specific data not retrieved yet."); + } + } + // append SPS and PPS in front of every IDR NAL unit + if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_KEY_FRAME) != 0 + && mBufferInfo.size != 0 + && mH264CodecSpecificData != null) { + try { + mOutputStream.write(mH264CodecSpecificData, 0, + mH264CodecSpecificData.length); + } catch (Exception e) {} + } + if (mBufferInfo.size != 0) { byte[] dataToWrite = new byte[mBufferInfo.size]; encoderOutputBuffers[encoderStatus].get(dataToWrite, mBufferInfo.offset, mBufferInfo.size); try { - mOutputStream.write(dataToWrite, 0, mBufferInfo.size); + if (mOutputStream != null) { + mOutputStream.write(dataToWrite, 0, mBufferInfo.size); + } else if (mOutputListener != null) { + mOutputListener.sendFrame( + dataToWrite, 0, dataToWrite.length, mBufferInfo.presentationTimeUs); + } } catch (Exception e) {} } diff --git a/sdl_android/src/main/java/com/smartdevicelink/protocol/AbstractProtocol.java b/sdl_android/src/main/java/com/smartdevicelink/protocol/AbstractProtocol.java index 8acc709e1..bb8c7fb6c 100644 --- a/sdl_android/src/main/java/com/smartdevicelink/protocol/AbstractProtocol.java +++ b/sdl_android/src/main/java/com/smartdevicelink/protocol/AbstractProtocol.java @@ -3,6 +3,8 @@ package com.smartdevicelink.protocol; import com.smartdevicelink.protocol.WiProProtocol.MessageFrameAssembler;
import com.smartdevicelink.protocol.enums.SessionType;
+import java.util.List;
+
public abstract class AbstractProtocol {
private static final String SDL_LIB_TRACE_KEY = "42baba60-eb57-11df-98cf-0800200c9a66";
@@ -31,6 +33,7 @@ public abstract class AbstractProtocol { public abstract void SendMessage(ProtocolMessage msg);
public abstract int getMtu();
+ public abstract long getMtu(SessionType type);
public abstract void handlePacketReceived(SdlPacket packet);
@@ -128,8 +131,8 @@ public abstract class AbstractProtocol { }
protected void handleProtocolSessionNACKed(SessionType sessionType,
- byte sessionID, byte version, String correlationID) {
- _protocolListener.onProtocolSessionNACKed(sessionType, sessionID, version, correlationID);
+ byte sessionID, byte version, String correlationID, List<String> rejectedParams) {
+ _protocolListener.onProtocolSessionNACKed(sessionType, sessionID, version, correlationID, rejectedParams);
}
// This method handles protocol errors. A callback is sent to the protocol
diff --git a/sdl_android/src/main/java/com/smartdevicelink/protocol/IProtocolListener.java b/sdl_android/src/main/java/com/smartdevicelink/protocol/IProtocolListener.java index b54ff66c8..04397b935 100644 --- a/sdl_android/src/main/java/com/smartdevicelink/protocol/IProtocolListener.java +++ b/sdl_android/src/main/java/com/smartdevicelink/protocol/IProtocolListener.java @@ -2,6 +2,8 @@ package com.smartdevicelink.protocol; import com.smartdevicelink.protocol.enums.*;
+import java.util.List;
+
public interface IProtocolListener {
// Called to indicate that these bytes are to be sent as part of a message.
// This call includes the part of the message.
@@ -14,7 +16,8 @@ public interface IProtocolListener { // Called to indicate that a protocol session has been started (from either side)
void onProtocolSessionStarted(SessionType sessionType, byte sessionID, byte version, String correlationID, int hashID, boolean isEncrypted);
- void onProtocolSessionNACKed(SessionType sessionType, byte sessionID, byte version, String correlationID);
+ void onProtocolSessionNACKed(SessionType sessionType, byte sessionID, byte version,
+ String correlationID, List<String> rejectedParams);
// Called to indicate that a protocol session has ended (from either side)
void onProtocolSessionEnded(SessionType sessionType, byte sessionID, String correlationID /*, String info, Exception ex*/);
diff --git a/sdl_android/src/main/java/com/smartdevicelink/protocol/ProtocolMessage.java b/sdl_android/src/main/java/com/smartdevicelink/protocol/ProtocolMessage.java index 99b34aff6..cb5ad3a74 100644 --- a/sdl_android/src/main/java/com/smartdevicelink/protocol/ProtocolMessage.java +++ b/sdl_android/src/main/java/com/smartdevicelink/protocol/ProtocolMessage.java @@ -45,12 +45,16 @@ public class ProtocolMessage { this._data = data;
this._jsonSize = data.length;
}
-
+
public void setData(byte[] data, int length) {
+ setData(data, 0, length);
+ }
+
+ public void setData(byte[] data, int offset, int length) {
if (this._data != null)
this._data = null;
this._data = new byte[length];
- System.arraycopy(data, 0, this._data, 0, length);
+ System.arraycopy(data, offset, this._data, 0, length);
this._jsonSize = 0;
}
diff --git a/sdl_android/src/main/java/com/smartdevicelink/protocol/WiProProtocol.java b/sdl_android/src/main/java/com/smartdevicelink/protocol/WiProProtocol.java index b5aca82dc..d79dbe27f 100644 --- a/sdl_android/src/main/java/com/smartdevicelink/protocol/WiProProtocol.java +++ b/sdl_android/src/main/java/com/smartdevicelink/protocol/WiProProtocol.java @@ -150,10 +150,17 @@ public class WiProProtocol extends AbstractProtocol { } // end-method
public void EndProtocolSession(SessionType sessionType, byte sessionID, int hashId) {
- SdlPacket header = SdlPacketFactory.createEndSession(sessionType, sessionID, hashID, getMajorVersionByte(), BitConverter.intToByteArray(hashId));
- if(sessionType.equals(SessionType.RPC)){ // check for RPC session
- header.putTag(ControlFrameTags.RPC.EndService.HASH_ID, hashID);
- }
+ SdlPacket header;
+ if (sessionType.equals(SessionType.RPC)) { // check for RPC session
+ if(_version < 5){
+ header = SdlPacketFactory.createEndSession(sessionType, sessionID, hashID, getMajorVersionByte(), BitConverter.intToByteArray(hashID));
+ }else{
+ header = SdlPacketFactory.createEndSession(sessionType, sessionID, hashID, getMajorVersionByte(), new byte[0]);
+ header.putTag(ControlFrameTags.RPC.EndService.HASH_ID, hashID);
+ }
+ }else{ //Any other service type we don't include the hash id
+ header = SdlPacketFactory.createEndSession(sessionType, sessionID, hashID, getMajorVersionByte(), new byte[0]);
+ }
handlePacketToSend(header);
} // end-method
@@ -497,6 +504,7 @@ public class WiProProtocol extends AbstractProtocol { }
handleProtocolSessionStarted(serviceType,(byte) packet.getSessionId(), getMajorVersionByte(), "", hashID, packet.isEncrypted());
} else if (frameInfo == FrameDataControlFrameType.StartSessionNACK.getValue()) {
+ List<String> rejectedParams = null;
if(packet.version >= 5){
String rejectedTag = null;
if(serviceType.equals(SessionType.RPC)){
@@ -506,11 +514,10 @@ public class WiProProtocol extends AbstractProtocol { }else if(serviceType.equals(SessionType.NAV)){
rejectedTag = ControlFrameTags.Video.StartServiceNAK.REJECTED_PARAMS;
}
- List<String> rejectedParams = (List<String>) packet.getTag(rejectedTag);
- // TODO: Pass these back
+ rejectedParams = (List<String>) packet.getTag(rejectedTag);
}
if (serviceType.eq(SessionType.NAV) || serviceType.eq(SessionType.PCM)) {
- handleProtocolSessionNACKed(serviceType, (byte)packet.getSessionId(), getMajorVersionByte(), "");
+ handleProtocolSessionNACKed(serviceType, (byte)packet.getSessionId(), getMajorVersionByte(), "", rejectedParams);
} else {
handleProtocolError("Got StartSessionNACK for protocol sessionID=" + packet.getSessionId(), null);
}
@@ -637,8 +644,12 @@ public class WiProProtocol extends AbstractProtocol { @Override
public void EndProtocolService(SessionType serviceType, byte sessionID) {
- SdlPacket header = SdlPacketFactory.createEndSession(serviceType, sessionID, hashID, getMajorVersionByte(), new byte[4]);
- handlePacketToSend(header);
+ if(serviceType.equals(SessionType.RPC)){ //RPC session will close all other sessions so we want to make sure we use the correct EndProtocolSession method
+ EndProtocolSession(serviceType,sessionID,hashID);
+ }else {
+ SdlPacket header = SdlPacketFactory.createEndSession(serviceType, sessionID, hashID, getMajorVersionByte(), new byte[0]);
+ handlePacketToSend(header);
+ }
}
} // end-class
diff --git a/sdl_android/src/main/java/com/smartdevicelink/protocol/enums/FunctionID.java b/sdl_android/src/main/java/com/smartdevicelink/protocol/enums/FunctionID.java index 06116c5b9..412d3f857 100644 --- a/sdl_android/src/main/java/com/smartdevicelink/protocol/enums/FunctionID.java +++ b/sdl_android/src/main/java/com/smartdevicelink/protocol/enums/FunctionID.java @@ -53,6 +53,11 @@ public enum FunctionID{ SYSTEM_REQUEST(38, "SystemRequest"),
SEND_LOCATION(39, "SendLocation"),
DIAL_NUMBER(40, "DialNumber"),
+
+ BUTTON_PRESS(41, "ButtonPress"),
+ GET_INTERIOR_VEHICLE_DATA(43, "GetInteriorVehicleData"),
+ SET_INTERIOR_VEHICLE_DATA(44, "SetInteriorVehicleData"),
+
GET_WAY_POINTS(45, "GetWayPoints"),
SUBSCRIBE_WAY_POINTS(46, "SubscribeWayPoints"),
UNSUBSCRIBE_WAY_POINTS(47, "UnsubscribeWayPoints"),
@@ -75,6 +80,7 @@ public enum FunctionID{ ON_TOUCH_EVENT(32780, "OnTouchEvent"),
ON_SYSTEM_REQUEST(32781, "OnSystemRequest"),
ON_HASH_CHANGE(32782, "OnHashChange"),
+ ON_INTERIOR_VEHICLE_DATA(32783, "OnInteriorVehicleData"),
ON_WAY_POINT_CHANGE(32784, "OnWayPointChange"),
// MOCKED FUNCTIONS (NOT SENT FROM HEAD-UNIT)
diff --git a/sdl_android/src/main/java/com/smartdevicelink/proxy/SdlProxyBase.java b/sdl_android/src/main/java/com/smartdevicelink/proxy/SdlProxyBase.java index a8e184517..8614791d0 100644 --- a/sdl_android/src/main/java/com/smartdevicelink/proxy/SdlProxyBase.java +++ b/sdl_android/src/main/java/com/smartdevicelink/proxy/SdlProxyBase.java @@ -12,6 +12,7 @@ import java.net.HttpURLConnection; import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
+import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Vector;
@@ -45,6 +46,7 @@ import com.smartdevicelink.exception.SdlException; import com.smartdevicelink.exception.SdlExceptionCause;
import com.smartdevicelink.marshal.JsonRPCMarshaller;
import com.smartdevicelink.protocol.ProtocolMessage;
+import com.smartdevicelink.protocol.enums.ControlFrameTags;
import com.smartdevicelink.protocol.enums.FunctionID;
import com.smartdevicelink.protocol.enums.MessageType;
import com.smartdevicelink.protocol.enums.SessionType;
@@ -55,10 +57,12 @@ import com.smartdevicelink.proxy.callbacks.OnError; import com.smartdevicelink.proxy.callbacks.OnProxyClosed;
import com.smartdevicelink.proxy.callbacks.OnServiceEnded;
import com.smartdevicelink.proxy.callbacks.OnServiceNACKed;
-import com.smartdevicelink.proxy.interfaces.IProxyListenerALM;
+import com.smartdevicelink.proxy.interfaces.IAudioStreamListener;
import com.smartdevicelink.proxy.interfaces.IProxyListenerBase;
import com.smartdevicelink.proxy.interfaces.IPutFileResponseListener;
+import com.smartdevicelink.proxy.interfaces.ISdl;
import com.smartdevicelink.proxy.interfaces.ISdlServiceListener;
+import com.smartdevicelink.proxy.interfaces.IVideoStreamListener;
import com.smartdevicelink.proxy.interfaces.OnSystemCapabilityListener;
import com.smartdevicelink.proxy.rpc.*;
import com.smartdevicelink.proxy.rpc.enums.AppHMIType;
@@ -70,7 +74,6 @@ import com.smartdevicelink.proxy.rpc.enums.DriverDistractionState; import com.smartdevicelink.proxy.rpc.enums.FileType;
import com.smartdevicelink.proxy.rpc.enums.GlobalProperty;
import com.smartdevicelink.proxy.rpc.enums.HMILevel;
-import com.smartdevicelink.proxy.rpc.enums.HmiZoneCapabilities;
import com.smartdevicelink.proxy.rpc.enums.ImageType;
import com.smartdevicelink.proxy.rpc.enums.InteractionMode;
import com.smartdevicelink.proxy.rpc.enums.Language;
@@ -81,16 +84,17 @@ import com.smartdevicelink.proxy.rpc.enums.SamplingRate; import com.smartdevicelink.proxy.rpc.enums.SdlConnectionState;
import com.smartdevicelink.proxy.rpc.enums.SdlDisconnectedReason;
import com.smartdevicelink.proxy.rpc.enums.SdlInterfaceAvailability;
-import com.smartdevicelink.proxy.rpc.enums.SpeechCapabilities;
import com.smartdevicelink.proxy.rpc.enums.SystemCapabilityType;
-import com.smartdevicelink.proxy.rpc.enums.SystemContext;
import com.smartdevicelink.proxy.rpc.enums.TextAlignment;
import com.smartdevicelink.proxy.rpc.enums.UpdateMode;
-import com.smartdevicelink.proxy.rpc.enums.VrCapabilities;
+import com.smartdevicelink.proxy.rpc.enums.VideoStreamingCodec;
+import com.smartdevicelink.proxy.rpc.enums.VideoStreamingProtocol;
import com.smartdevicelink.proxy.rpc.listeners.OnPutFileUpdateListener;
import com.smartdevicelink.proxy.rpc.listeners.OnRPCNotificationListener;
import com.smartdevicelink.proxy.rpc.listeners.OnRPCResponseListener;
import com.smartdevicelink.security.SdlSecurityBase;
+import com.smartdevicelink.streaming.AudioStreamingCodec;
+import com.smartdevicelink.streaming.AudioStreamingParams;
import com.smartdevicelink.streaming.StreamRPCPacketizer;
import com.smartdevicelink.streaming.VideoStreamingParameters;
import com.smartdevicelink.trace.SdlTrace;
@@ -101,6 +105,7 @@ import com.smartdevicelink.transport.SiphonServer; import com.smartdevicelink.transport.enums.TransportType;
import com.smartdevicelink.util.DebugTool;
+@SuppressWarnings({"WeakerAccess", "Convert2Diamond"})
public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> {
// Used for calls to Android Log class.
public static final String TAG = "SdlProxy";
@@ -108,6 +113,9 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> private static final int PROX_PROT_VER_ONE = 1;
private static final int RESPONSE_WAIT_TIME = 2000;
+ private static final VideoStreamingFormat VIDEO_STREAMING_FORMAT_H264_RAW = new VideoStreamingFormat(VideoStreamingCodec.H264,VideoStreamingProtocol.RAW);
+ private static final VideoStreamingFormat VIDEO_STREAMING_FORMAT_H264_RTP = new VideoStreamingFormat(VideoStreamingCodec.H264,VideoStreamingProtocol.RTP);
+
private SdlSession sdlSession = null;
private proxyListenerType _proxyListener = null;
@@ -127,14 +135,17 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> ON_UPDATE_LISTENER_LOCK = new Object(),
ON_NOTIFICATION_LISTENER_LOCK = new Object();
- private Object APP_INTERFACE_REGISTERED_LOCK = new Object();
+ private final Object APP_INTERFACE_REGISTERED_LOCK = new Object();
private int iFileCount = 0;
private boolean navServiceStartResponseReceived = false;
private boolean navServiceStartResponse = false;
+ private List<String> navServiceStartRejectedParams = null;
private boolean pcmServiceStartResponseReceived = false;
private boolean pcmServiceStartResponse = false;
+ @SuppressWarnings("FieldCanBeLocal")
+ private List<String> pcmServiceStartRejectedParams = null;
private boolean navServiceEndResponseReceived = false;
private boolean navServiceEndResponse = false;
private boolean pcmServiceEndResponseReceived = false;
@@ -160,7 +171,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> protected Boolean _advancedLifecycleManagementEnabled = false;
// Parameters passed to the constructor from the app to register an app interface
private String _applicationName = null;
- private long instanceDateTime = System.currentTimeMillis();
+ private final long instanceDateTime = System.currentTimeMillis();
private String sConnectionDetails = "N/A";
private Vector<TTSChunk> _ttsName = null;
private String _ngnMediaScreenAppName = null;
@@ -169,8 +180,9 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> private Language _hmiDisplayLanguageDesired = null;
private Vector<AppHMIType> _appType = null;
private String _appID = null;
+ @SuppressWarnings({"FieldCanBeLocal", "unused"}) //Need to understand what this is used for
private String _autoActivateIdDesired = null;
- private String _lastHashID = null;
+ private String _lastHashID = null;
private SdlMsgVersion _sdlMsgVersionRequest = null;
private Vector<String> _vrSynonyms = null;
private boolean _bAppResumeEnabled = false;
@@ -186,7 +198,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> // Proxy State Variables
protected Boolean _appInterfaceRegisterd = false;
protected Boolean _preRegisterd = false;
- @SuppressWarnings("unused")
+ @SuppressWarnings({"unused", "FieldCanBeLocal"})
private Boolean _haveReceivedFirstNonNoneHMILevel = false;
protected Boolean _haveReceivedFirstFocusLevel = false;
protected Boolean _haveReceivedFirstFocusLevelFull = false;
@@ -194,10 +206,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> protected SdlConnectionState _sdlConnectionState = null;
protected SdlInterfaceAvailability _sdlIntefaceAvailablity = null;
protected HMILevel _hmiLevel = null;
- private HMILevel _priorHmiLevel = null;
protected AudioStreamingState _audioStreamingState = null;
- private AudioStreamingState _priorAudioStreamingState = null;
- protected SystemContext _systemContext = null;
// Variables set by RegisterAppInterfaceResponse
protected SdlMsgVersion _sdlMsgVersion = null;
protected String _autoActivateIdReturned = null;
@@ -213,15 +222,102 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> protected List<Class<? extends SdlSecurityBase>> _secList = null;
protected SystemCapabilityManager _systemCapabilityManager;
- private CopyOnWriteArrayList<IPutFileResponseListener> _putFileListenerList = new CopyOnWriteArrayList<IPutFileResponseListener>();
+ private final CopyOnWriteArrayList<IPutFileResponseListener> _putFileListenerList = new CopyOnWriteArrayList<IPutFileResponseListener>();
protected byte _wiproVersion = 1;
protected SparseArray<OnRPCResponseListener> rpcResponseListeners = null;
- protected SparseArray<OnRPCNotificationListener> rpcNotificationListeners = null;
-
+ protected SparseArray<CopyOnWriteArrayList<OnRPCNotificationListener>> rpcNotificationListeners = null;
+
+
// Interface broker
private SdlInterfaceBroker _interfaceBroker = null;
+ //We create an easily passable anonymous class of the interface so that we don't expose the internal interface to developers
+ private ISdl _internalInterface = new ISdl() {
+ @Override
+ public void start() {
+ try{
+ initializeProxy();
+ }catch (SdlException e){
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void stop() {
+ try{
+ dispose();
+ }catch (SdlException e){
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public boolean isConnected() {
+ return getIsConnected();
+ }
+
+ @Override
+ public void addServiceListener(SessionType serviceType, ISdlServiceListener sdlServiceListener) {
+ if(sdlSession!=null){
+ sdlSession.addServiceListener(serviceType,sdlServiceListener);
+ }
+ }
+
+ @Override
+ public void removeServiceListener(SessionType serviceType, ISdlServiceListener sdlServiceListener) {
+ if(sdlSession!=null){
+ sdlSession.removeServiceListener(serviceType,sdlServiceListener);
+ }
+ }
+
+ @Override
+ public void startVideoService(VideoStreamingParameters parameters, boolean encrypted) {
+ if(isConnected()){
+ sdlSession.startService(SessionType.NAV,sdlSession.getSessionId(),encrypted);
+ }
+ }
+
+ @Override
+ public void stopVideoService() {
+ if(isConnected()){
+ sdlSession.endService(SessionType.NAV,sdlSession.getSessionId());
+ }
+ }
+
+ @Override
+ public void startAudioService(boolean encrypted) {
+ if(isConnected()){
+ sdlSession.startService(SessionType.PCM,sdlSession.getSessionId(),encrypted);
+ }
+ }
+
+ @Override
+ public void stopAudioService() {
+ if(isConnected()){
+ sdlSession.endService(SessionType.PCM,sdlSession.getSessionId());
+ }
+ }
+
+ @Override
+ public void sendRPCRequest(RPCRequest message){
+ try {
+ SdlProxyBase.this.sendRPCRequest(message);
+ } catch (SdlException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void addOnRPCNotificationListener(FunctionID notificationId, OnRPCNotificationListener listener) {
+ SdlProxyBase.this.addOnRPCNotificationListener(notificationId,listener);
+ }
+
+ @Override
+ public boolean removeOnRPCNotificationListener(FunctionID notificationId, OnRPCNotificationListener listener) {
+ return SdlProxyBase.this.removeOnRPCNotificationListener(notificationId,listener);
+ }
+ };
private void notifyPutFileStreamError(Exception e, String info)
{
@@ -256,12 +352,11 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> // disconnect has completed
notifyPutFileStreamError(null, info);
- if (_advancedLifecycleManagementEnabled) {
- // If ALM, nothing is required to be done here
- } else {
+ if (!_advancedLifecycleManagementEnabled) {
// If original model, notify app the proxy is closed so it will delete and reinstanciate
notifyProxyClosed(info, new SdlException("Transport disconnected.", SdlExceptionCause.SDL_UNAVAILABLE), SdlDisconnectedReason.TRANSPORT_DISCONNECT);
- }
+ }// else If ALM, nothing is required to be done here
+
}
@Override
@@ -322,7 +417,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> sdlSession.setIncomingHeartbeatMonitor(incomingHeartbeatMonitor);
}
- startRPCProtocolSession(sessionID, correlationID);
+ startRPCProtocolSession();
}
else
{
@@ -337,15 +432,14 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> }
else if (_wiproVersion > 1) {
//If version is 2 or above then don't need to specify a Session Type
- startRPCProtocolSession(sessionID, correlationID);
- } else {
- // Handle other protocol session types here
- }
+ startRPCProtocolSession();
+ } //else{} Handle other protocol session types here
+
}
@Override
public void onProtocolSessionStartedNACKed(SessionType sessionType,
- byte sessionID, byte version, String correlationID) {
+ byte sessionID, byte version, String correlationID, List<String> rejectedParams) {
OnServiceNACKed message = new OnServiceNACKed(sessionType);
queueInternalMessage(message);
@@ -357,7 +451,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> updateBroadcastIntent(sendIntent, "COMMENT2", " NACK ServiceType: " + sessionType.getName());
sendBroadcastIntent(sendIntent);
- NavServiceStartedNACK();
+ NavServiceStartedNACK(rejectedParams);
}
else if (sessionType.eq(SessionType.PCM)) {
Intent sendIntent = createBroadcastIntent();
@@ -366,7 +460,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> updateBroadcastIntent(sendIntent, "COMMENT2", " NACK ServiceType: " + sessionType.getName());
sendBroadcastIntent(sendIntent);
- AudioServiceStartedNACK();
+ AudioServiceStartedNACK(rejectedParams);
}
}
@@ -476,7 +570,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * @param autoActivateID Auto activation identifier.
* @param callbackToUIThread Flag that indicates that this proxy should send callback to UI thread or not.
* @param transportConfig Configuration of transport to be used by underlying connection.
- * @throws SdlException
+ * @throws SdlException if there is an unrecoverable error class might throw an exception.
*/
protected SdlProxyBase(proxyListenerType listener, SdlProxyConfigurationResources sdlProxyConfigurationResources,
boolean enableAdvancedLifecycleManagement, String appName, Vector<TTSChunk> ttsName,
@@ -489,12 +583,13 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> sdlMsgVersion, languageDesired, hmiDisplayLanguageDesired, appType, appID, autoActivateID, callbackToUIThread, null, null, null, transportConfig);
}
- private void performBaseCommon(proxyListenerType listener, SdlProxyConfigurationResources sdlProxyConfigurationResources,
- boolean enableAdvancedLifecycleManagement, String appName, Vector<TTSChunk> ttsName,
- String ngnMediaScreenAppName, Vector<String> vrSynonyms, Boolean isMediaApp, SdlMsgVersion sdlMsgVersion,
- Language languageDesired, Language hmiDisplayLanguageDesired, Vector<AppHMIType> appType, String appID,
- String autoActivateID, boolean callbackToUIThread, Boolean preRegister, String sHashID, Boolean bAppResumeEnab,
- BaseTransportConfig transportConfig) throws SdlException
+ @SuppressWarnings("ConstantConditions")
+ private void performBaseCommon(proxyListenerType listener, SdlProxyConfigurationResources sdlProxyConfigurationResources,
+ boolean enableAdvancedLifecycleManagement, String appName, Vector<TTSChunk> ttsName,
+ String ngnMediaScreenAppName, Vector<String> vrSynonyms, Boolean isMediaApp, SdlMsgVersion sdlMsgVersion,
+ Language languageDesired, Language hmiDisplayLanguageDesired, Vector<AppHMIType> appType, String appID,
+ String autoActivateID, boolean callbackToUIThread, Boolean preRegister, String sHashID, Boolean bAppResumeEnab,
+ BaseTransportConfig transportConfig) throws SdlException
{
setWiProVersion((byte)PROX_PROT_VER_ONE);
@@ -578,7 +673,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> @Override
public void dispatch(InternalProxyMessage message) {
- dispatchInternalMessage((InternalProxyMessage)message);
+ dispatchInternalMessage(message);
}
@Override
@@ -604,7 +699,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _incomingProxyMessageDispatcher = new ProxyMessageDispatcher<ProtocolMessage>("INCOMING_MESSAGE_DISPATCHER",new IDispatchingStrategy<ProtocolMessage>() {
@Override
public void dispatch(ProtocolMessage message) {
- dispatchIncomingMessage((ProtocolMessage)message);
+ dispatchIncomingMessage(message);
}
@Override
@@ -630,7 +725,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _outgoingProxyMessageDispatcher = new ProxyMessageDispatcher<ProtocolMessage>("OUTGOING_MESSAGE_DISPATCHER",new IDispatchingStrategy<ProtocolMessage>() {
@Override
public void dispatch(ProtocolMessage message) {
- dispatchOutgoingMessage((ProtocolMessage)message);
+ dispatchOutgoingMessage(message);
}
@Override
@@ -646,19 +741,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> }
rpcResponseListeners = new SparseArray<OnRPCResponseListener>();
- rpcNotificationListeners = new SparseArray<OnRPCNotificationListener>();
-
- //Initialize _systemCapabilityManager here.
- _systemCapabilityManager = new SystemCapabilityManager(new SystemCapabilityManager.ISystemCapabilityManager() {
- @Override
- public void onSendPacketRequest(RPCRequest message) {
- try {
- sendRPCRequest(message);
- } catch (SdlException e) {
- e.printStackTrace();
- }
- }
- });
+ rpcNotificationListeners = new SparseArray<CopyOnWriteArrayList<OnRPCNotificationListener>>();
// Initialize the proxy
try {
@@ -719,7 +802,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * @param callbackToUIThread Flag that indicates that this proxy should send callback to UI thread or not.
* @param preRegister Flag that indicates that this proxy should be pre-registerd or not.
* @param transportConfig Configuration of transport to be used by underlying connection.
- * @throws SdlException
+ * @throws SdlException if there is an unrecoverable error class might throw an exception.
*/
protected SdlProxyBase(proxyListenerType listener, SdlProxyConfigurationResources sdlProxyConfigurationResources,
boolean enableAdvancedLifecycleManagement, String appName, Vector<TTSChunk> ttsName,
@@ -799,7 +882,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> private void sendBroadcastIntent(Intent sendIntent)
{
- Service myService = null;
+ Service myService;
if (_proxyListener != null && _proxyListener instanceof Service)
{
myService = (Service) _proxyListener;
@@ -837,8 +920,8 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> String sCharSet = "utf-8";
int iContentLength = iContentLen;
- URL url = null;
- HttpURLConnection urlConnection = null;
+ URL url;
+ HttpURLConnection urlConnection;
Intent sendIntent = createBroadcastIntent();
updateBroadcastIntent(sendIntent, "FUNCTION_NAME", "getURLConnection");
@@ -912,7 +995,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> Headers myHeader = msg.getHeader();
- updateBroadcastIntent(sendIntent, "FUNCTION_NAME", "sendOnSystemRequestToUrl");
+ updateBroadcastIntent(sendIntent, "FUNCTION_NAME", "sendOnSystemRequestToUrl");
updateBroadcastIntent(sendIntent, "COMMENT5", "\r\nCloud URL: " + sURLString);
try
@@ -975,9 +1058,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> wr.close();
- long BeforeTime = System.currentTimeMillis();
- @SuppressWarnings("unused")
- String sResponseMsg = urlConnection.getResponseMessage();
+ long BeforeTime = System.currentTimeMillis();
long AfterTime = System.currentTimeMillis();
final long roundtriptime = AfterTime - BeforeTime;
@@ -1014,7 +1095,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> updateBroadcastIntent(sendIntent, "DATA", "Data from cloud response: " + response.toString());
sendRPCRequestPrivate(putFile);
- Log.i("sendOnSystemRequestToUrl", "sent to sdl");
+ Log.i("sendSystemRequestToUrl", "sent to sdl");
updateBroadcastIntent(sendIntent2, "RPC_NAME", FunctionID.PUT_FILE.toString());
updateBroadcastIntent(sendIntent2, "TYPE", RPCMessage.KEY_REQUEST);
@@ -1034,20 +1115,20 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> if (jsonArray.get(i) instanceof String)
{
cloudDataReceived.add(jsonArray.getString(i));
- //Log.i("sendOnSystemRequestToUrl", "jsonArray.getString(i): " + jsonArray.getString(i));
+ //Log.i("sendSystemRequestToUrl", "jsonArray.getString(i): " + jsonArray.getString(i));
}
}
}
else if (jsonResponse.get(dataKey) instanceof String)
{
cloudDataReceived.add(jsonResponse.getString(dataKey));
- //Log.i("sendOnSystemRequestToUrl", "jsonResponse.getString(data): " + jsonResponse.getString("data"));
+ //Log.i("sendSystemRequestToUrl", "jsonResponse.getString(data): " + jsonResponse.getString("data"));
}
}
else
{
- DebugTool.logError("sendOnSystemRequestToUrl: Data in JSON Object neither an array nor a string.");
- //Log.i("sendOnSystemRequestToUrl", "sendOnSystemRequestToUrl: Data in JSON Object neither an array nor a string.");
+ DebugTool.logError("sendSystemRequestToUrl: Data in JSON Object neither an array nor a string.");
+ //Log.i("sendSystemRequestToUrl", "sendSystemRequestToUrl: Data in JSON Object neither an array nor a string.");
return;
}
@@ -1069,10 +1150,10 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> mySystemRequest = RPCRequestFactory.buildSystemRequest(response.toString(), getPoliciesReservedCorrelationID());
}
- if (getIsConnected())
+ if (getIsConnected())
{
sendRPCRequestPrivate(mySystemRequest);
- Log.i("sendOnSystemRequestToUrl", "sent to sdl");
+ Log.i("sendSystemRequestToUrl", "sent to sdl");
updateBroadcastIntent(sendIntent2, "RPC_NAME", FunctionID.SYSTEM_REQUEST.toString());
updateBroadcastIntent(sendIntent2, "TYPE", RPCMessage.KEY_REQUEST);
@@ -1082,45 +1163,45 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> }
catch (SdlException e)
{
- DebugTool.logError("sendOnSystemRequestToUrl: Could not get data from JSONObject received.", e);
+ DebugTool.logError("sendSystemRequestToUrl: Could not get data from JSONObject received.", e);
updateBroadcastIntent(sendIntent, "COMMENT3", " SdlException encountered sendOnSystemRequestToUrl: "+ e);
- //Log.i("pt", "sendOnSystemRequestToUrl: Could not get data from JSONObject received."+ e);
+ //Log.i("pt", "sendSystemRequestToUrl: Could not get data from JSONObject received."+ e);
}
catch (JSONException e)
{
- DebugTool.logError("sendOnSystemRequestToUrl: JSONException: ", e);
+ DebugTool.logError("sendSystemRequestToUrl: JSONException: ", e);
updateBroadcastIntent(sendIntent, "COMMENT3", " JSONException encountered sendOnSystemRequestToUrl: "+ e);
- //Log.i("pt", "sendOnSystemRequestToUrl: JSONException: "+ e);
+ //Log.i("pt", "sendSystemRequestToUrl: JSONException: "+ e);
}
catch (UnsupportedEncodingException e)
{
- DebugTool.logError("sendOnSystemRequestToUrl: Could not encode string.", e);
+ DebugTool.logError("sendSystemRequestToUrl: Could not encode string.", e);
updateBroadcastIntent(sendIntent, "COMMENT3", " UnsupportedEncodingException encountered sendOnSystemRequestToUrl: "+ e);
- //Log.i("pt", "sendOnSystemRequestToUrl: Could not encode string."+ e);
+ //Log.i("pt", "sendSystemRequestToUrl: Could not encode string."+ e);
}
catch (ProtocolException e)
{
- DebugTool.logError("sendOnSystemRequestToUrl: Could not set request method to post.", e);
+ DebugTool.logError("sendSystemRequestToUrl: Could not set request method to post.", e);
updateBroadcastIntent(sendIntent, "COMMENT3", " ProtocolException encountered sendOnSystemRequestToUrl: "+ e);
- //Log.i("pt", "sendOnSystemRequestToUrl: Could not set request method to post."+ e);
+ //Log.i("pt", "sendSystemRequestToUrl: Could not set request method to post."+ e);
}
catch (MalformedURLException e)
{
- DebugTool.logError("sendOnSystemRequestToUrl: URL Exception when sending SystemRequest to an external server.", e);
+ DebugTool.logError("sendSystemRequestToUrl: URL Exception when sending SystemRequest to an external server.", e);
updateBroadcastIntent(sendIntent, "COMMENT3", " MalformedURLException encountered sendOnSystemRequestToUrl: "+ e);
- //Log.i("pt", "sendOnSystemRequestToUrl: URL Exception when sending SystemRequest to an external server."+ e);
+ //Log.i("pt", "sendSystemRequestToUrl: URL Exception when sending SystemRequest to an external server."+ e);
}
catch (IOException e)
{
- DebugTool.logError("sendOnSystemRequestToUrl: IOException: ", e);
+ DebugTool.logError("sendSystemRequestToUrl: IOException: ", e);
updateBroadcastIntent(sendIntent, "COMMENT3", " IOException while sending to cloud: IOException: "+ e);
- //Log.i("pt", "sendOnSystemRequestToUrl: IOException: "+ e);
+ //Log.i("pt", "sendSystemRequestToUrl: IOException: "+ e);
}
catch (Exception e)
{
- DebugTool.logError("sendOnSystemRequestToUrl: Unexpected Exception: ", e);
+ DebugTool.logError("sendSystemRequestToUrl: Unexpected Exception: ", e);
updateBroadcastIntent(sendIntent, "COMMENT3", " Exception encountered sendOnSystemRequestToUrl: "+ e);
- //Log.i("pt", "sendOnSystemRequestToUrl: Unexpected Exception: " + e);
+ //Log.i("pt", "sendSystemRequestToUrl: Unexpected Exception: " + e);
}
finally
{
@@ -1145,23 +1226,19 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> // Test correlationID
private boolean isCorrelationIDProtected(Integer correlationID) {
- if (correlationID != null &&
- (HEARTBEAT_CORRELATION_ID == correlationID
+ return correlationID != null &&
+ (HEARTBEAT_CORRELATION_ID == correlationID
|| REGISTER_APP_INTERFACE_CORRELATION_ID == correlationID
|| UNREGISTER_APP_INTERFACE_CORRELATION_ID == correlationID
- || POLICIES_CORRELATION_ID == correlationID)) {
- return true;
- }
-
- return false;
+ || POLICIES_CORRELATION_ID == correlationID);
+
}
// Protected isConnected method to allow legacy proxy to poll isConnected state
public Boolean getIsConnected() {
- if (sdlSession == null) return false;
-
- return sdlSession.getIsConnected();
+ return sdlSession != null && sdlSession.getIsConnected();
}
+
/**
* Returns whether the application is registered in SDL. Note: for testing
@@ -1180,15 +1257,14 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _haveReceivedFirstNonNoneHMILevel = false;
_haveReceivedFirstFocusLevel = false;
_haveReceivedFirstFocusLevelFull = false;
- if (_preRegisterd)
- _appInterfaceRegisterd = true;
- else
- _appInterfaceRegisterd = false;
+ _appInterfaceRegisterd = _preRegisterd;
_putFileListenerList.clear();
_sdlIntefaceAvailablity = SdlInterfaceAvailability.SDL_INTERFACE_UNAVAILABLE;
-
+
+ //Initialize _systemCapabilityManager here.
+ _systemCapabilityManager = new SystemCapabilityManager(_internalInterface);
// Setup SdlConnection
synchronized(CONNECTION_REFERENCE_LOCK) {
this.sdlSession = SdlSession.createSession(_wiproVersion,_interfaceBroker, _transportConfig);
@@ -1201,8 +1277,8 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> }
/**
* This method will fake the multiplex connection event
- * @param action
*/
+ @SuppressWarnings("unused")
public void forceOnConnected(){
synchronized(CONNECTION_REFERENCE_LOCK) {
if (sdlSession != null) {
@@ -1237,6 +1313,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> /**
* Public method to enable the siphon transport
*/
+ @SuppressWarnings("unused")
public void enableSiphonDebug() {
short enabledPortNumber = SiphonServer.enableSiphonServer();
@@ -1252,6 +1329,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> /**
* Public method to disable the Siphon Trace Server
*/
+ @SuppressWarnings("unused")
public void disableSiphonDebug() {
short disabledPortNumber = SiphonServer.disableSiphonServer();
@@ -1283,16 +1361,19 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> /**
* Public method to determine Debug Tool enabled
*/
+ @SuppressWarnings("BooleanMethodIsAlwaysInverted")
public static boolean isDebugEnabled() {
return DebugTool.isDebugEnabled();
}
+ @SuppressWarnings("unused")
@Deprecated
public void close() throws SdlException {
dispose();
}
+ @SuppressWarnings("UnusedParameters")
private void cleanProxy(SdlDisconnectedReason disconnectedReason) throws SdlException {
try {
@@ -1306,7 +1387,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> Boolean waitForInterfaceUnregistered = false;
// Unregister app interface
synchronized(CONNECTION_REFERENCE_LOCK) {
- if (sdlSession != null && sdlSession.getIsConnected() && getAppInterfaceRegistered()) {
+ if (getIsConnected() && getAppInterfaceRegistered()) {
waitForInterfaceUnregistered = true;
unregisterAppInterfacePrivate(UNREGISTER_APP_INTERFACE_CORRELATION_ID);
}
@@ -1328,15 +1409,13 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> rpcResponseListeners.clear();
}
if(rpcNotificationListeners != null){
- rpcNotificationListeners.clear(); //TODO make sure we want to clear this
+ rpcNotificationListeners.clear();
}
// Clean up SDL Connection
synchronized(CONNECTION_REFERENCE_LOCK) {
if (sdlSession != null) sdlSession.close();
}
- } catch (SdlException e) {
- throw e;
} finally {
SdlTrace.logProxyEvent("SdlProxy cleaned.", SDL_LIB_TRACE_KEY);
}
@@ -1387,15 +1466,13 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> rpcResponseListeners = null;
- } catch (SdlException e) {
- throw e;
} finally {
SdlTrace.logProxyEvent("SdlProxy disposed.", SDL_LIB_TRACE_KEY);
}
} // end-method
- private static Object CYCLE_LOCK = new Object();
+ private final static Object CYCLE_LOCK = new Object();
private boolean _cycling = false;
@@ -1479,17 +1556,14 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> if (message.getBulkData() != null) hash.put(RPCStruct.KEY_BULK_DATA, message.getBulkData());
if (message.getPayloadProtected()) hash.put(RPCStruct.KEY_PROTECTED, true);
} else {
- final Hashtable<String, Object> mhash = JsonRPCMarshaller.unmarshall(message.getData());
- hash = mhash;
+ hash = JsonRPCMarshaller.unmarshall(message.getData());
}
handleRPCMessage(hash);
} catch (final Exception excp) {
DebugTool.logError("Failure handling protocol message: " + excp.toString(), excp);
passErrorToProxyListener("Error handing incoming protocol message.", excp);
} // end-catch
- } else {
- // Handle other protocol message types here
- }
+ } //else { Handle other protocol message types here}
} catch (final Exception e) {
// Pass error to application through listener
DebugTool.logError("Error handing proxy event.", e);
@@ -1507,7 +1581,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> public String serializeJSON(RPCMessage msg)
{
- String sReturn = null;
+ String sReturn;
try
{
sReturn = msg.serializeJSON(getWiProVersion()).toString(2);
@@ -1540,77 +1614,88 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> void dispatchInternalMessage(final InternalProxyMessage message) {
try{
- if (message.getFunctionName().equals(InternalProxyMessage.OnProxyError)) {
- final OnError msg = (OnError)message;
- if (_callbackToUIThread) {
- // Run in UI thread
- _mainUIHandler.post(new Runnable() {
- @Override
- public void run() {
- _proxyListener.onError(msg.getInfo(), msg.getException());
- }
- });
- } else {
- _proxyListener.onError(msg.getInfo(), msg.getException());
- }
- } else if (message.getFunctionName().equals(InternalProxyMessage.OnServiceEnded)) {
- final OnServiceEnded msg = (OnServiceEnded)message;
- if (_callbackToUIThread) {
- // Run in UI thread
- _mainUIHandler.post(new Runnable() {
- @Override
- public void run() {
- _proxyListener.onServiceEnded(msg);
- }
- });
- } else {
- _proxyListener.onServiceEnded(msg);
+ switch (message.getFunctionName()) {
+ case InternalProxyMessage.OnProxyError: {
+ final OnError msg = (OnError) message;
+ if (_callbackToUIThread) {
+ // Run in UI thread
+ _mainUIHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ _proxyListener.onError(msg.getInfo(), msg.getException());
+ }
+ });
+ } else {
+ _proxyListener.onError(msg.getInfo(), msg.getException());
+ }
+ break;
}
- } else if (message.getFunctionName().equals(InternalProxyMessage.OnServiceNACKed)) {
- final OnServiceNACKed msg = (OnServiceNACKed)message;
- if (_callbackToUIThread) {
- // Run in UI thread
- _mainUIHandler.post(new Runnable() {
- @Override
- public void run() {
- _proxyListener.onServiceNACKed(msg);
- }
- });
- } else {
- _proxyListener.onServiceNACKed(msg);
+ case InternalProxyMessage.OnServiceEnded: {
+ final OnServiceEnded msg = (OnServiceEnded) message;
+ if (_callbackToUIThread) {
+ // Run in UI thread
+ _mainUIHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ _proxyListener.onServiceEnded(msg);
+ }
+ });
+ } else {
+ _proxyListener.onServiceEnded(msg);
+ }
+ break;
}
+ case InternalProxyMessage.OnServiceNACKed: {
+ final OnServiceNACKed msg = (OnServiceNACKed) message;
+ if (_callbackToUIThread) {
+ // Run in UI thread
+ _mainUIHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ _proxyListener.onServiceNACKed(msg);
+ }
+ });
+ } else {
+ _proxyListener.onServiceNACKed(msg);
+ }
- /**************Start Legacy Specific Call-backs************/
- } else if (message.getFunctionName().equals(InternalProxyMessage.OnProxyOpened)) {
- if (_callbackToUIThread) {
- // Run in UI thread
- _mainUIHandler.post(new Runnable() {
- @Override
- public void run() {
- ((IProxyListener)_proxyListener).onProxyOpened();
- }
- });
- } else {
- ((IProxyListener)_proxyListener).onProxyOpened();
+ /* *************Start Legacy Specific Call-backs************/
+ break;
}
- } else if (message.getFunctionName().equals(InternalProxyMessage.OnProxyClosed)) {
- final OnProxyClosed msg = (OnProxyClosed)message;
- if (_callbackToUIThread) {
- // Run in UI thread
- _mainUIHandler.post(new Runnable() {
- @Override
- public void run() {
- _proxyListener.onProxyClosed(msg.getInfo(), msg.getException(), msg.getReason());
- }
- });
- } else {
- _proxyListener.onProxyClosed(msg.getInfo(), msg.getException(), msg.getReason());
+ case InternalProxyMessage.OnProxyOpened:
+ if (_callbackToUIThread) {
+ // Run in UI thread
+ _mainUIHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ ((IProxyListener) _proxyListener).onProxyOpened();
+ }
+ });
+ } else {
+ ((IProxyListener) _proxyListener).onProxyOpened();
+ }
+ break;
+ case InternalProxyMessage.OnProxyClosed: {
+ final OnProxyClosed msg = (OnProxyClosed) message;
+ if (_callbackToUIThread) {
+ // Run in UI thread
+ _mainUIHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ _proxyListener.onProxyClosed(msg.getInfo(), msg.getException(), msg.getReason());
+ }
+ });
+ } else {
+ _proxyListener.onProxyClosed(msg.getInfo(), msg.getException(), msg.getReason());
+ }
+ /* ***************End Legacy Specific Call-backs************/
+ break;
}
- /****************End Legacy Specific Call-backs************/
- } else {
- // Diagnostics
- SdlTrace.logProxyEvent("Unknown RPC Message encountered. Check for an updated version of the SDL Proxy.", SDL_LIB_TRACE_KEY);
- DebugTool.logError("Unknown RPC Message encountered. Check for an updated version of the SDL Proxy.");
+ default:
+ // Diagnostics
+ SdlTrace.logProxyEvent("Unknown RPC Message encountered. Check for an updated version of the SDL Proxy.", SDL_LIB_TRACE_KEY);
+ DebugTool.logError("Unknown RPC Message encountered. Check for an updated version of the SDL Proxy.");
+ break;
}
SdlTrace.logProxyEvent("Proxy fired callback: " + message.getFunctionName(), SDL_LIB_TRACE_KEY);
@@ -1694,10 +1779,11 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> /**
* Only call this method for a PutFile response. It will cause a class cast exception if not.
- * @param correlationId
- * @param bytesWritten
- * @param totalSize
+ * @param correlationId correlation id of the packet being updated
+ * @param bytesWritten how many bytes were written
+ * @param totalSize the total size in bytes
*/
+ @SuppressWarnings("unused")
public void onPacketProgress(int correlationId, long bytesWritten, long totalSize){
synchronized(ON_UPDATE_LISTENER_LOCK){
if(rpcResponseListeners !=null
@@ -1711,9 +1797,10 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> /**
* Will provide callback to the listener either onFinish or onError depending on the RPCResponses result code,
* <p>Will automatically remove the listener for the list of listeners on completion.
- * @param msg
+ * @param msg The RPCResponse message that was received
* @return if a listener was called or not
*/
+ @SuppressWarnings("UnusedReturnValue")
private boolean onRPCResponseReceived(RPCResponse msg){
synchronized(ON_UPDATE_LISTENER_LOCK){
int correlationId = msg.getCorrelationID();
@@ -1733,9 +1820,9 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> }
/**
- *
- * @param listener
- * @param correlationId
+ * Add a listener that will receive the response to the specific RPCRequest sent with the corresponding correlation id
+ * @param listener that will get called back when a response is received
+ * @param correlationId of the RPCRequest that was sent
* @param totalSize only include if this is an OnPutFileUpdateListener. Otherwise it will be ignored.
*/
public void addOnRPCResponseListener(OnRPCResponseListener listener,int correlationId, int totalSize){
@@ -1751,17 +1838,21 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> }
}
+ @SuppressWarnings("unused")
public SparseArray<OnRPCResponseListener> getResponseListeners(){
synchronized(ON_UPDATE_LISTENER_LOCK){
return this.rpcResponseListeners;
}
}
+ @SuppressWarnings("UnusedReturnValue")
public boolean onRPCNotificationReceived(RPCNotification notification){
synchronized(ON_NOTIFICATION_LISTENER_LOCK){
- OnRPCNotificationListener listener = rpcNotificationListeners.get(FunctionID.getFunctionId(notification.getFunctionName()));
- if(listener!=null){
- listener.onNotified(notification);
+ CopyOnWriteArrayList<OnRPCNotificationListener> listeners = rpcNotificationListeners.get(FunctionID.getFunctionId(notification.getFunctionName()));
+ if(listeners!=null && listeners.size()>0) {
+ for (OnRPCNotificationListener listener : listeners) {
+ listener.onNotified(notification);
+ }
return true;
}
return false;
@@ -1771,20 +1862,45 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> /**
* This will ad a listener for the specific type of notification. As of now it will only allow
* a single listener per notification function id
- * @param notification The notification type that this listener is designated for
+ * @param notificationId The notification type that this listener is designated for
* @param listener The listener that will be called when a notification of the provided type is received
*/
- public void addOnRPCNotificationListener(FunctionID notificationId,OnRPCNotificationListener listener){
+ @SuppressWarnings("unused")
+ public void addOnRPCNotificationListener(FunctionID notificationId, OnRPCNotificationListener listener){
synchronized(ON_NOTIFICATION_LISTENER_LOCK){
- rpcNotificationListeners.put(notificationId.getId(), listener);
+ if(notificationId != null && listener != null){
+ if(rpcNotificationListeners.indexOfKey(notificationId.getId()) < 0 ){
+ rpcNotificationListeners.put(notificationId.getId(),new CopyOnWriteArrayList<OnRPCNotificationListener>());
+ }
+ rpcNotificationListeners.get(notificationId.getId()).add(listener);
+ }
}
}
-
+
+ /**
+ * This method is no longer valid and will not remove the listener for the supplied notificaiton id
+ * @param notificationId n/a
+ * @see #removeOnRPCNotificationListener(FunctionID, OnRPCNotificationListener)
+ */
+ @SuppressWarnings("unused")
+ @Deprecated
public void removeOnRPCNotificationListener(FunctionID notificationId){
synchronized(ON_NOTIFICATION_LISTENER_LOCK){
- rpcNotificationListeners.delete(notificationId.getId());
+ //rpcNotificationListeners.delete(notificationId.getId());
}
}
+
+ public boolean removeOnRPCNotificationListener(FunctionID notificationId, OnRPCNotificationListener listener){
+ synchronized(ON_NOTIFICATION_LISTENER_LOCK){
+ if(rpcNotificationListeners!= null
+ && notificationId != null
+ && listener != null
+ && rpcNotificationListeners.indexOfKey(notificationId.getId()) >= 0){
+ return rpcNotificationListeners.get(notificationId.getId()).remove(listener);
+ }
+ }
+ return false;
+ }
private void processRaiResponse(RegisterAppInterfaceResponse rai)
{
@@ -1798,7 +1914,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> if (_secList == null) return;
- SdlSecurityBase sec = null;
+ SdlSecurityBase sec;
Service svc = getService();
SdlSecurityBase.setAppService(svc);
@@ -1818,12 +1934,9 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> if (sec.getMakeList().contains(make))
{
setSdlSecurity(sec);
- if (sec != null)
- {
sec.setAppId(_appID);
if (sdlSession != null)
sec.handleSdlSession(sdlSession);
- }
return;
}
}
@@ -1920,8 +2033,6 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> public void run() {
if (_proxyListener instanceof IProxyListener) {
((IProxyListener)_proxyListener).onRegisterAppInterfaceResponse(msg);
- } else if (_proxyListener instanceof IProxyListenerALM) {
- //((IProxyListenerALM)_proxyListener).onRegisterAppInterfaceResponse(msg);
}
onRPCResponseReceived(msg);
}
@@ -1929,8 +2040,6 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> } else {
if (_proxyListener instanceof IProxyListener) {
((IProxyListener)_proxyListener).onRegisterAppInterfaceResponse(msg);
- } else if (_proxyListener instanceof IProxyListenerALM) {
- //((IProxyListenerALM)_proxyListener).onRegisterAppInterfaceResponse(msg);
}
onRPCResponseReceived(msg);
}
@@ -2064,8 +2173,6 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> public void run() {
if (_proxyListener instanceof IProxyListener) {
((IProxyListener)_proxyListener).onRegisterAppInterfaceResponse(msg);
- } else if (_proxyListener instanceof IProxyListenerALM) {
- //((IProxyListenerALM)_proxyListener).onRegisterAppInterfaceResponse(msg);
}
onRPCResponseReceived(msg);
}
@@ -2073,8 +2180,6 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> } else {
if (_proxyListener instanceof IProxyListener) {
((IProxyListener)_proxyListener).onRegisterAppInterfaceResponse(msg);
- } else if (_proxyListener instanceof IProxyListenerALM) {
- //((IProxyListenerALM)_proxyListener).onRegisterAppInterfaceResponse(msg);
}
onRPCResponseReceived(msg);
}
@@ -2122,12 +2227,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onShowResponse((ShowResponse)msg);
+ _proxyListener.onShowResponse(msg);
onRPCResponseReceived(msg);
}
});
} else {
- _proxyListener.onShowResponse((ShowResponse)msg);
+ _proxyListener.onShowResponse(msg);
onRPCResponseReceived(msg);
}
} else if (functionName.equals(FunctionID.ADD_COMMAND.toString())) {
@@ -2139,12 +2244,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onAddCommandResponse((AddCommandResponse)msg);
+ _proxyListener.onAddCommandResponse(msg);
onRPCResponseReceived(msg);
}
});
} else {
- _proxyListener.onAddCommandResponse((AddCommandResponse)msg);
+ _proxyListener.onAddCommandResponse(msg);
onRPCResponseReceived(msg);
}
} else if (functionName.equals(FunctionID.DELETE_COMMAND.toString())) {
@@ -2156,12 +2261,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onDeleteCommandResponse((DeleteCommandResponse)msg);
+ _proxyListener.onDeleteCommandResponse(msg);
onRPCResponseReceived(msg);
}
});
} else {
- _proxyListener.onDeleteCommandResponse((DeleteCommandResponse)msg);
+ _proxyListener.onDeleteCommandResponse(msg);
onRPCResponseReceived(msg);
}
} else if (functionName.equals(FunctionID.ADD_SUB_MENU.toString())) {
@@ -2173,12 +2278,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onAddSubMenuResponse((AddSubMenuResponse)msg);
+ _proxyListener.onAddSubMenuResponse(msg);
onRPCResponseReceived(msg);
}
});
} else {
- _proxyListener.onAddSubMenuResponse((AddSubMenuResponse)msg);
+ _proxyListener.onAddSubMenuResponse(msg);
onRPCResponseReceived(msg);
}
} else if (functionName.equals(FunctionID.DELETE_SUB_MENU.toString())) {
@@ -2190,12 +2295,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onDeleteSubMenuResponse((DeleteSubMenuResponse)msg);
+ _proxyListener.onDeleteSubMenuResponse(msg);
onRPCResponseReceived(msg);
}
});
} else {
- _proxyListener.onDeleteSubMenuResponse((DeleteSubMenuResponse)msg);
+ _proxyListener.onDeleteSubMenuResponse(msg);
onRPCResponseReceived(msg);
}
} else if (functionName.equals(FunctionID.SUBSCRIBE_BUTTON.toString())) {
@@ -2207,12 +2312,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onSubscribeButtonResponse((SubscribeButtonResponse)msg);
+ _proxyListener.onSubscribeButtonResponse(msg);
onRPCResponseReceived(msg);
}
});
} else {
- _proxyListener.onSubscribeButtonResponse((SubscribeButtonResponse)msg);
+ _proxyListener.onSubscribeButtonResponse(msg);
onRPCResponseReceived(msg);
}
} else if (functionName.equals(FunctionID.UNSUBSCRIBE_BUTTON.toString())) {
@@ -2224,12 +2329,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onUnsubscribeButtonResponse((UnsubscribeButtonResponse)msg);
+ _proxyListener.onUnsubscribeButtonResponse(msg);
onRPCResponseReceived(msg);
}
});
} else {
- _proxyListener.onUnsubscribeButtonResponse((UnsubscribeButtonResponse)msg);
+ _proxyListener.onUnsubscribeButtonResponse(msg);
onRPCResponseReceived(msg);
}
} else if (functionName.equals(FunctionID.SET_MEDIA_CLOCK_TIMER.toString())) {
@@ -2241,12 +2346,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onSetMediaClockTimerResponse((SetMediaClockTimerResponse)msg);
+ _proxyListener.onSetMediaClockTimerResponse(msg);
onRPCResponseReceived(msg);
}
});
} else {
- _proxyListener.onSetMediaClockTimerResponse((SetMediaClockTimerResponse)msg);
+ _proxyListener.onSetMediaClockTimerResponse(msg);
onRPCResponseReceived(msg);
}
} else if (functionName.equals(FunctionID.ENCODED_SYNC_P_DATA.toString())) {
@@ -2284,12 +2389,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onCreateInteractionChoiceSetResponse((CreateInteractionChoiceSetResponse)msg);
+ _proxyListener.onCreateInteractionChoiceSetResponse(msg);
onRPCResponseReceived(msg);
}
});
} else {
- _proxyListener.onCreateInteractionChoiceSetResponse((CreateInteractionChoiceSetResponse)msg);
+ _proxyListener.onCreateInteractionChoiceSetResponse(msg);
onRPCResponseReceived(msg);
}
} else if (functionName.equals(FunctionID.DELETE_INTERACTION_CHOICE_SET.toString())) {
@@ -2301,12 +2406,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onDeleteInteractionChoiceSetResponse((DeleteInteractionChoiceSetResponse)msg);
+ _proxyListener.onDeleteInteractionChoiceSetResponse(msg);
onRPCResponseReceived(msg);
}
});
} else {
- _proxyListener.onDeleteInteractionChoiceSetResponse((DeleteInteractionChoiceSetResponse)msg);
+ _proxyListener.onDeleteInteractionChoiceSetResponse(msg);
onRPCResponseReceived(msg);
}
} else if (functionName.equals(FunctionID.PERFORM_INTERACTION.toString())) {
@@ -2318,12 +2423,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onPerformInteractionResponse((PerformInteractionResponse)msg);
+ _proxyListener.onPerformInteractionResponse(msg);
onRPCResponseReceived(msg);
}
});
} else {
- _proxyListener.onPerformInteractionResponse((PerformInteractionResponse)msg);
+ _proxyListener.onPerformInteractionResponse(msg);
onRPCResponseReceived(msg);
}
} else if (functionName.equals(FunctionID.SET_GLOBAL_PROPERTIES.toString())) {
@@ -2335,12 +2440,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onSetGlobalPropertiesResponse((SetGlobalPropertiesResponse)msg);
+ _proxyListener.onSetGlobalPropertiesResponse(msg);
onRPCResponseReceived(msg);
}
});
} else {
- _proxyListener.onSetGlobalPropertiesResponse((SetGlobalPropertiesResponse)msg);
+ _proxyListener.onSetGlobalPropertiesResponse(msg);
onRPCResponseReceived(msg);
}
} else if (functionName.equals(FunctionID.RESET_GLOBAL_PROPERTIES.toString())) {
@@ -2352,12 +2457,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onResetGlobalPropertiesResponse((ResetGlobalPropertiesResponse)msg);
+ _proxyListener.onResetGlobalPropertiesResponse(msg);
onRPCResponseReceived(msg);
}
});
} else {
- _proxyListener.onResetGlobalPropertiesResponse((ResetGlobalPropertiesResponse)msg);
+ _proxyListener.onResetGlobalPropertiesResponse(msg);
onRPCResponseReceived(msg);
}
} else if (functionName.equals(FunctionID.UNREGISTER_APP_INTERFACE.toString())) {
@@ -2387,8 +2492,6 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> public void run() {
if (_proxyListener instanceof IProxyListener) {
((IProxyListener)_proxyListener).onUnregisterAppInterfaceResponse(msg);
- } else if (_proxyListener instanceof IProxyListenerALM) {
- //((IProxyListenerALM)_proxyListener).onUnregisterAppInterfaceResponse(msg);
}
onRPCResponseReceived(msg);
}
@@ -2396,8 +2499,6 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> } else {
if (_proxyListener instanceof IProxyListener) {
((IProxyListener)_proxyListener).onUnregisterAppInterfaceResponse(msg);
- } else if (_proxyListener instanceof IProxyListenerALM) {
- //((IProxyListenerALM)_proxyListener).onUnregisterAppInterfaceResponse(msg);
}
onRPCResponseReceived(msg);
}
@@ -2411,12 +2512,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onGenericResponse((GenericResponse)msg);
+ _proxyListener.onGenericResponse(msg);
onRPCResponseReceived(msg);
}
});
} else {
- _proxyListener.onGenericResponse((GenericResponse)msg);
+ _proxyListener.onGenericResponse(msg);
onRPCResponseReceived(msg);
}
} else if (functionName.equals(FunctionID.SLIDER.toString())) {
@@ -2427,12 +2528,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onSliderResponse((SliderResponse)msg);
+ _proxyListener.onSliderResponse(msg);
onRPCResponseReceived(msg);
}
});
} else {
- _proxyListener.onSliderResponse((SliderResponse)msg);
+ _proxyListener.onSliderResponse(msg);
onRPCResponseReceived(msg);
}
} else if (functionName.equals(FunctionID.PUT_FILE.toString())) {
@@ -2443,13 +2544,13 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onPutFileResponse((PutFileResponse)msg);
+ _proxyListener.onPutFileResponse(msg);
onRPCResponseReceived(msg);
notifyPutFileStreamResponse(msg);
}
});
} else {
- _proxyListener.onPutFileResponse((PutFileResponse)msg);
+ _proxyListener.onPutFileResponse(msg);
onRPCResponseReceived(msg);
notifyPutFileStreamResponse(msg);
}
@@ -2461,12 +2562,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onDeleteFileResponse((DeleteFileResponse)msg);
+ _proxyListener.onDeleteFileResponse(msg);
onRPCResponseReceived(msg);
}
});
} else {
- _proxyListener.onDeleteFileResponse((DeleteFileResponse)msg);
+ _proxyListener.onDeleteFileResponse(msg);
onRPCResponseReceived(msg);
}
} else if (functionName.equals(FunctionID.LIST_FILES.toString())) {
@@ -2477,12 +2578,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onListFilesResponse((ListFilesResponse)msg);
+ _proxyListener.onListFilesResponse(msg);
onRPCResponseReceived(msg);
}
});
} else {
- _proxyListener.onListFilesResponse((ListFilesResponse)msg);
+ _proxyListener.onListFilesResponse(msg);
onRPCResponseReceived(msg);
}
} else if (functionName.equals(FunctionID.SET_APP_ICON.toString())) {
@@ -2493,12 +2594,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onSetAppIconResponse((SetAppIconResponse)msg);
+ _proxyListener.onSetAppIconResponse(msg);
onRPCResponseReceived(msg);
}
});
} else {
- _proxyListener.onSetAppIconResponse((SetAppIconResponse)msg);
+ _proxyListener.onSetAppIconResponse(msg);
onRPCResponseReceived(msg);
}
} else if (functionName.equals(FunctionID.SCROLLABLE_MESSAGE.toString())) {
@@ -2509,12 +2610,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onScrollableMessageResponse((ScrollableMessageResponse)msg);
+ _proxyListener.onScrollableMessageResponse(msg);
onRPCResponseReceived(msg);
}
});
} else {
- _proxyListener.onScrollableMessageResponse((ScrollableMessageResponse)msg);
+ _proxyListener.onScrollableMessageResponse(msg);
onRPCResponseReceived(msg);
}
} else if (functionName.equals(FunctionID.CHANGE_REGISTRATION.toString())) {
@@ -2525,12 +2626,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onChangeRegistrationResponse((ChangeRegistrationResponse)msg);
+ _proxyListener.onChangeRegistrationResponse(msg);
onRPCResponseReceived(msg);
}
});
} else {
- _proxyListener.onChangeRegistrationResponse((ChangeRegistrationResponse)msg);
+ _proxyListener.onChangeRegistrationResponse(msg);
onRPCResponseReceived(msg);
}
} else if (functionName.equals(FunctionID.SET_DISPLAY_LAYOUT.toString())) {
@@ -2550,12 +2651,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onSetDisplayLayoutResponse((SetDisplayLayoutResponse)msg);
+ _proxyListener.onSetDisplayLayoutResponse(msg);
onRPCResponseReceived(msg);
}
});
} else {
- _proxyListener.onSetDisplayLayoutResponse((SetDisplayLayoutResponse)msg);
+ _proxyListener.onSetDisplayLayoutResponse(msg);
onRPCResponseReceived(msg);
}
} else if (functionName.equals(FunctionID.PERFORM_AUDIO_PASS_THRU.toString())) {
@@ -2566,12 +2667,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onPerformAudioPassThruResponse((PerformAudioPassThruResponse)msg);
+ _proxyListener.onPerformAudioPassThruResponse(msg);
onRPCResponseReceived(msg);
}
});
} else {
- _proxyListener.onPerformAudioPassThruResponse((PerformAudioPassThruResponse)msg);
+ _proxyListener.onPerformAudioPassThruResponse(msg);
onRPCResponseReceived(msg);
}
} else if (functionName.equals(FunctionID.END_AUDIO_PASS_THRU.toString())) {
@@ -2582,12 +2683,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onEndAudioPassThruResponse((EndAudioPassThruResponse)msg);
+ _proxyListener.onEndAudioPassThruResponse(msg);
onRPCResponseReceived(msg);
}
});
} else {
- _proxyListener.onEndAudioPassThruResponse((EndAudioPassThruResponse)msg);
+ _proxyListener.onEndAudioPassThruResponse(msg);
onRPCResponseReceived(msg);
}
} else if (functionName.equals(FunctionID.SUBSCRIBE_VEHICLE_DATA.toString())) {
@@ -2598,12 +2699,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onSubscribeVehicleDataResponse((SubscribeVehicleDataResponse)msg);
+ _proxyListener.onSubscribeVehicleDataResponse(msg);
onRPCResponseReceived(msg);
}
});
} else {
- _proxyListener.onSubscribeVehicleDataResponse((SubscribeVehicleDataResponse)msg);
+ _proxyListener.onSubscribeVehicleDataResponse(msg);
onRPCResponseReceived(msg);
}
} else if (functionName.equals(FunctionID.UNSUBSCRIBE_VEHICLE_DATA.toString())) {
@@ -2614,12 +2715,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onUnsubscribeVehicleDataResponse((UnsubscribeVehicleDataResponse)msg);
+ _proxyListener.onUnsubscribeVehicleDataResponse(msg);
onRPCResponseReceived(msg);
}
});
} else {
- _proxyListener.onUnsubscribeVehicleDataResponse((UnsubscribeVehicleDataResponse)msg);
+ _proxyListener.onUnsubscribeVehicleDataResponse(msg);
onRPCResponseReceived(msg);
}
} else if (functionName.equals(FunctionID.GET_VEHICLE_DATA.toString())) {
@@ -2630,12 +2731,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onGetVehicleDataResponse((GetVehicleDataResponse)msg);
+ _proxyListener.onGetVehicleDataResponse(msg);
onRPCResponseReceived(msg);
}
});
} else {
- _proxyListener.onGetVehicleDataResponse((GetVehicleDataResponse)msg);
+ _proxyListener.onGetVehicleDataResponse(msg);
onRPCResponseReceived(msg);
}
} else if (functionName.equals(FunctionID.SUBSCRIBE_WAY_POINTS.toString())) {
@@ -2646,12 +2747,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onSubscribeWayPointsResponse((SubscribeWayPointsResponse)msg);
+ _proxyListener.onSubscribeWayPointsResponse(msg);
onRPCResponseReceived(msg);
}
});
} else {
- _proxyListener.onSubscribeWayPointsResponse((SubscribeWayPointsResponse)msg);
+ _proxyListener.onSubscribeWayPointsResponse(msg);
onRPCResponseReceived(msg);
}
} else if (functionName.equals(FunctionID.UNSUBSCRIBE_WAY_POINTS.toString())) {
@@ -2662,12 +2763,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onUnsubscribeWayPointsResponse((UnsubscribeWayPointsResponse)msg);
+ _proxyListener.onUnsubscribeWayPointsResponse(msg);
onRPCResponseReceived(msg);
}
});
} else {
- _proxyListener.onUnsubscribeWayPointsResponse((UnsubscribeWayPointsResponse)msg);
+ _proxyListener.onUnsubscribeWayPointsResponse(msg);
onRPCResponseReceived(msg);
}
} else if (functionName.equals(FunctionID.GET_WAY_POINTS.toString())) {
@@ -2678,12 +2779,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onGetWayPointsResponse((GetWayPointsResponse)msg);
+ _proxyListener.onGetWayPointsResponse(msg);
onRPCResponseReceived(msg);
}
});
} else {
- _proxyListener.onGetWayPointsResponse((GetWayPointsResponse)msg);
+ _proxyListener.onGetWayPointsResponse(msg);
onRPCResponseReceived(msg);
}
} else if (functionName.equals(FunctionID.READ_DID.toString())) {
@@ -2693,12 +2794,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onReadDIDResponse((ReadDIDResponse)msg);
+ _proxyListener.onReadDIDResponse(msg);
onRPCResponseReceived(msg);
}
});
} else {
- _proxyListener.onReadDIDResponse((ReadDIDResponse)msg);
+ _proxyListener.onReadDIDResponse(msg);
onRPCResponseReceived(msg);
}
} else if (functionName.equals(FunctionID.GET_DTCS.toString())) {
@@ -2708,12 +2809,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onGetDTCsResponse((GetDTCsResponse)msg);
+ _proxyListener.onGetDTCsResponse(msg);
onRPCResponseReceived(msg);
}
});
} else {
- _proxyListener.onGetDTCsResponse((GetDTCsResponse)msg);
+ _proxyListener.onGetDTCsResponse(msg);
onRPCResponseReceived(msg);
}
} else if (functionName.equals(FunctionID.DIAGNOSTIC_MESSAGE.toString())) {
@@ -2723,12 +2824,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onDiagnosticMessageResponse((DiagnosticMessageResponse)msg);
+ _proxyListener.onDiagnosticMessageResponse(msg);
onRPCResponseReceived(msg);
}
});
} else {
- _proxyListener.onDiagnosticMessageResponse((DiagnosticMessageResponse)msg);
+ _proxyListener.onDiagnosticMessageResponse(msg);
onRPCResponseReceived(msg);
}
}
@@ -2740,12 +2841,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onSystemRequestResponse((SystemRequestResponse)msg);
+ _proxyListener.onSystemRequestResponse(msg);
onRPCResponseReceived(msg);
}
});
} else {
- _proxyListener.onSystemRequestResponse((SystemRequestResponse)msg);
+ _proxyListener.onSystemRequestResponse(msg);
onRPCResponseReceived(msg);
}
}
@@ -2826,6 +2927,34 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _proxyListener.onUpdateTurnListResponse(msg);
onRPCResponseReceived(msg);
}
+ } else if (functionName.equals(FunctionID.SET_INTERIOR_VEHICLE_DATA.toString())) {
+ final SetInteriorVehicleDataResponse msg = new SetInteriorVehicleDataResponse(hash);
+ if (_callbackToUIThread) {
+ _mainUIHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ _proxyListener.onSetInteriorVehicleDataResponse(msg);
+ onRPCResponseReceived(msg);
+ }
+ });
+ } else {
+ _proxyListener.onSetInteriorVehicleDataResponse(msg);
+ onRPCResponseReceived(msg);
+ }
+ } else if (functionName.equals(FunctionID.GET_INTERIOR_VEHICLE_DATA.toString())) {
+ final GetInteriorVehicleDataResponse msg = new GetInteriorVehicleDataResponse(hash);
+ if (_callbackToUIThread) {
+ _mainUIHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ _proxyListener.onGetInteriorVehicleDataResponse(msg);
+ onRPCResponseReceived(msg);
+ }
+ });
+ } else {
+ _proxyListener.onGetInteriorVehicleDataResponse(msg);
+ onRPCResponseReceived(msg);
+ }
} else if (functionName.equals(FunctionID.GET_SYSTEM_CAPABILITY.toString())) {
// GetSystemCapabilityResponse
final GetSystemCapabilityResponse msg = new GetSystemCapabilityResponse(hash);
@@ -2841,29 +2970,42 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _proxyListener.onGetSystemCapabilityResponse(msg);
onRPCResponseReceived(msg);
}
- }
- else if (functionName.equals(FunctionID.SEND_HAPTIC_DATA.toString())) {
+ } else if (functionName.equals(FunctionID.BUTTON_PRESS.toString())) {
+ final ButtonPressResponse msg = new ButtonPressResponse(hash);
+ if (_callbackToUIThread) {
+ _mainUIHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ _proxyListener.onButtonPressResponse(msg);
+ onRPCResponseReceived(msg);
+ }
+ });
+ } else {
+ _proxyListener.onButtonPressResponse(msg);
+ onRPCResponseReceived(msg);
+ }
+ } else if (functionName.equals(FunctionID.SEND_HAPTIC_DATA.toString())) {
final SendHapticDataResponse msg = new SendHapticDataResponse(hash);
if (_callbackToUIThread) {
// Run in UI thread
_mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onSendHapticDataResponse((SendHapticDataResponse) msg);
+ _proxyListener.onSendHapticDataResponse( msg);
onRPCResponseReceived(msg);
}
});
} else {
- _proxyListener.onSendHapticDataResponse((SendHapticDataResponse) msg);
+ _proxyListener.onSendHapticDataResponse( msg);
onRPCResponseReceived(msg);
}
}
else {
if (_sdlMsgVersion != null) {
- DebugTool.logError("Unrecognized response Message: " + functionName.toString() +
+ DebugTool.logError("Unrecognized response Message: " + functionName +
" SDL Message Version = " + _sdlMsgVersion);
} else {
- DebugTool.logError("Unrecognized response Message: " + functionName.toString());
+ DebugTool.logError("Unrecognized response Message: " + functionName);
}
} // end-if
@@ -2880,22 +3022,25 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> sdlSession.getLockScreenMan().setHMILevel(msg.getHmiLevel());
}
- msg.setFirstRun(Boolean.valueOf(firstTimeFull));
+ msg.setFirstRun(firstTimeFull);
if (msg.getHmiLevel() == HMILevel.HMI_FULL) firstTimeFull = false;
- if (msg.getHmiLevel() != _priorHmiLevel && msg.getAudioStreamingState() != _priorAudioStreamingState) {
+ if (msg.getHmiLevel() != _hmiLevel || msg.getAudioStreamingState() != _audioStreamingState) {
+ _hmiLevel = msg.getHmiLevel();
+ _audioStreamingState = msg.getAudioStreamingState();
+
if (_callbackToUIThread) {
// Run in UI thread
_mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onOnHMIStatus((OnHMIStatus)msg);
+ _proxyListener.onOnHMIStatus(msg);
_proxyListener.onOnLockScreenNotification(sdlSession.getLockScreenMan().getLockObj());
onRPCNotificationReceived(msg);
}
});
} else {
- _proxyListener.onOnHMIStatus((OnHMIStatus)msg);
+ _proxyListener.onOnHMIStatus(msg);
_proxyListener.onOnLockScreenNotification(sdlSession.getLockScreenMan().getLockObj());
onRPCNotificationReceived(msg);
}
@@ -2909,12 +3054,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onOnCommand((OnCommand)msg);
+ _proxyListener.onOnCommand(msg);
onRPCNotificationReceived(msg);
}
});
} else {
- _proxyListener.onOnCommand((OnCommand)msg);
+ _proxyListener.onOnCommand(msg);
onRPCNotificationReceived(msg);
}
} else if (functionName.equals(FunctionID.ON_DRIVER_DISTRACTION.toString())) {
@@ -2926,12 +3071,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> if (sdlSession != null)
{
DriverDistractionState drDist = msg.getState();
- boolean bVal = false;
- if (drDist == DriverDistractionState.DD_ON)
- bVal = true;
- else
- bVal = false;
- sdlSession.getLockScreenMan().setDriverDistStatus(bVal);
+ sdlSession.getLockScreenMan().setDriverDistStatus(drDist == DriverDistractionState.DD_ON);
}
if (_callbackToUIThread) {
@@ -3035,12 +3175,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onOnButtonPress((OnButtonPress)msg);
+ _proxyListener.onOnButtonPress(msg);
onRPCNotificationReceived(msg);
}
});
} else {
- _proxyListener.onOnButtonPress((OnButtonPress)msg);
+ _proxyListener.onOnButtonPress(msg);
onRPCNotificationReceived(msg);
}
} else if (functionName.equals(FunctionID.ON_BUTTON_EVENT.toString())) {
@@ -3052,12 +3192,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onOnButtonEvent((OnButtonEvent)msg);
+ _proxyListener.onOnButtonEvent(msg);
onRPCNotificationReceived(msg);
}
});
} else {
- _proxyListener.onOnButtonEvent((OnButtonEvent)msg);
+ _proxyListener.onOnButtonEvent(msg);
onRPCNotificationReceived(msg);
}
} else if (functionName.equals(FunctionID.ON_LANGUAGE_CHANGE.toString())) {
@@ -3069,12 +3209,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onOnLanguageChange((OnLanguageChange)msg);
+ _proxyListener.onOnLanguageChange(msg);
onRPCNotificationReceived(msg);
}
});
} else {
- _proxyListener.onOnLanguageChange((OnLanguageChange)msg);
+ _proxyListener.onOnLanguageChange(msg);
onRPCNotificationReceived(msg);
}
} else if (functionName.equals(FunctionID.ON_HASH_CHANGE.toString())) {
@@ -3086,7 +3226,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onOnHashChange((OnHashChange)msg);
+ _proxyListener.onOnHashChange(msg);
onRPCNotificationReceived(msg);
if (_bAppResumeEnabled)
{
@@ -3095,7 +3235,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> }
});
} else {
- _proxyListener.onOnHashChange((OnHashChange)msg);
+ _proxyListener.onOnHashChange(msg);
onRPCNotificationReceived(msg);
if (_bAppResumeEnabled)
{
@@ -3131,12 +3271,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onOnSystemRequest((OnSystemRequest)msg);
+ _proxyListener.onOnSystemRequest(msg);
onRPCNotificationReceived(msg);
}
});
} else {
- _proxyListener.onOnSystemRequest((OnSystemRequest)msg);
+ _proxyListener.onOnSystemRequest(msg);
onRPCNotificationReceived(msg);
}
} else if (functionName.equals(FunctionID.ON_AUDIO_PASS_THRU.toString())) {
@@ -3147,12 +3287,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onOnAudioPassThru((OnAudioPassThru)msg);
+ _proxyListener.onOnAudioPassThru(msg);
onRPCNotificationReceived(msg);
}
});
} else {
- _proxyListener.onOnAudioPassThru((OnAudioPassThru)msg);
+ _proxyListener.onOnAudioPassThru(msg);
onRPCNotificationReceived(msg);
}
} else if (functionName.equals(FunctionID.ON_VEHICLE_DATA.toString())) {
@@ -3163,12 +3303,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onOnVehicleData((OnVehicleData)msg);
+ _proxyListener.onOnVehicleData(msg);
onRPCNotificationReceived(msg);
}
});
} else {
- _proxyListener.onOnVehicleData((OnVehicleData)msg);
+ _proxyListener.onOnVehicleData(msg);
onRPCNotificationReceived(msg);
}
}
@@ -3215,12 +3355,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onOnKeyboardInput((OnKeyboardInput)msg);
+ _proxyListener.onOnKeyboardInput(msg);
onRPCNotificationReceived(msg);
}
});
} else {
- _proxyListener.onOnKeyboardInput((OnKeyboardInput)msg);
+ _proxyListener.onOnKeyboardInput(msg);
onRPCNotificationReceived(msg);
}
}
@@ -3231,12 +3371,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onOnTouchEvent((OnTouchEvent)msg);
+ _proxyListener.onOnTouchEvent(msg);
onRPCNotificationReceived(msg);
}
});
} else {
- _proxyListener.onOnTouchEvent((OnTouchEvent)msg);
+ _proxyListener.onOnTouchEvent(msg);
onRPCNotificationReceived(msg);
}
}
@@ -3247,21 +3387,37 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onOnWayPointChange((OnWayPointChange)msg);
+ _proxyListener.onOnWayPointChange(msg);
+ onRPCNotificationReceived(msg);
+ }
+ });
+ } else {
+ _proxyListener.onOnWayPointChange(msg);
+ onRPCNotificationReceived(msg);
+ }
+ }
+ else if (functionName.equals(FunctionID.ON_INTERIOR_VEHICLE_DATA.toString())) {
+ final OnInteriorVehicleData msg = new OnInteriorVehicleData(hash);
+ if (_callbackToUIThread) {
+ // Run in UI thread
+ _mainUIHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ _proxyListener.onOnInteriorVehicleData(msg);
onRPCNotificationReceived(msg);
}
});
} else {
- _proxyListener.onOnWayPointChange((OnWayPointChange)msg);
+ _proxyListener.onOnInteriorVehicleData(msg);
onRPCNotificationReceived(msg);
}
}
else {
if (_sdlMsgVersion != null) {
- DebugTool.logInfo("Unrecognized notification Message: " + functionName.toString() +
+ DebugTool.logInfo("Unrecognized notification Message: " + functionName +
" connected to SDL using message version: " + _sdlMsgVersion.getMajorVersion() + "." + _sdlMsgVersion.getMinorVersion());
} else {
- DebugTool.logInfo("Unrecognized notification Message: " + functionName.toString());
+ DebugTool.logInfo("Unrecognized notification Message: " + functionName);
}
} // end-if
} // end-if notification
@@ -3272,8 +3428,8 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> /**
* Takes an RPCRequest and sends it to SDL. Responses are captured through callback on IProxyListener.
*
- * @param request
- * @throws SdlException
+ * @param request is the RPCRequest being sent
+ * @throws SdlException if an unrecoverable error is encountered if an unrecoverable error is encountered
*/
public void sendRPCRequest(RPCRequest request) throws SdlException {
if (_proxyDisposed) {
@@ -3290,7 +3446,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> // Test if SdlConnection is null
synchronized(CONNECTION_REFERENCE_LOCK) {
- if (sdlSession == null || !sdlSession.getIsConnected()) {
+ if (!getIsConnected()) {
SdlTrace.logProxyEvent("Application attempted to send and RPCRequest without a connected transport.", SDL_LIB_TRACE_KEY);
throw new SdlException("There is no valid connection to SDL. sendRPCRequest cannot be called until SDL has been connected.", SdlExceptionCause.SDL_UNAVAILABLE);
}
@@ -3336,7 +3492,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> queueInternalMessage(message);
}
- private void startRPCProtocolSession(byte sessionID, String correlationID) {
+ private void startRPCProtocolSession() {
// Set Proxy Lifecyclek Available
if (_advancedLifecycleManagementEnabled) {
@@ -3353,7 +3509,6 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _hmiDisplayLanguageDesired,
_appType,
_appID,
- _autoActivateIdDesired,
REGISTER_APP_INTERFACE_CORRELATION_ID);
} catch (Exception e) {
@@ -3442,15 +3597,14 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> try {
StreamRPCPacketizer rpcPacketizer = new StreamRPCPacketizer((SdlProxyBase<IProxyListenerBase>) this, sdlSession, is, request, sType, rpcSessionID, wiproVersion, lSize, sdlSession);
rpcPacketizer.start();
- RPCStreamController streamController = new RPCStreamController(rpcPacketizer, request.getCorrelationID());
- return streamController;
+ return new RPCStreamController(rpcPacketizer, request.getCorrelationID());
} catch (Exception e) {
Log.e("SyncConnection", "Unable to start streaming:" + e.toString());
return null;
}
}
- @SuppressWarnings("unchecked")
+ @SuppressWarnings({"unchecked", "UnusedReturnValue"})
private RPCStreamController startRPCStream(InputStream is, PutFile request, SessionType sType, byte rpcSessionID, byte wiproVersion)
{
if (sdlSession == null) return null;
@@ -3464,8 +3618,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> try {
StreamRPCPacketizer rpcPacketizer = new StreamRPCPacketizer((SdlProxyBase<IProxyListenerBase>) this, sdlSession, is, request, sType, rpcSessionID, wiproVersion, lSize, sdlSession);
rpcPacketizer.start();
- RPCStreamController streamController = new RPCStreamController(rpcPacketizer, request.getCorrelationID());
- return streamController;
+ return new RPCStreamController(rpcPacketizer, request.getCorrelationID());
} catch (Exception e) {
Log.e("SyncConnection", "Unable to start streaming:" + e.toString());
return null;
@@ -3480,10 +3633,10 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> private RPCStreamController startPutFileStream(InputStream is, PutFile msg) {
if (sdlSession == null) return null;
if (is == null) return null;
- startRPCStream(is, msg, SessionType.RPC, sdlSession.getSessionId(), _wiproVersion);
- return null;
+ return startRPCStream(is, msg, SessionType.RPC, sdlSession.getSessionId(), _wiproVersion);
}
+ @SuppressWarnings("UnusedReturnValue")
public boolean startRPCStream(InputStream is, RPCRequest msg) {
if (sdlSession == null) return false;
sdlSession.startRPCStream(is, msg, SessionType.RPC, sdlSession.getSessionId(), _wiproVersion);
@@ -3501,7 +3654,8 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> }
private class CallableMethod implements Callable<Void> {
- private long waitTime;
+
+ private final long waitTime;
public CallableMethod(int timeInMillis){
this.waitTime=timeInMillis;
@@ -3542,12 +3696,23 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> *Opens the video service (serviceType 11) and subsequently streams raw H264 video from an InputStream provided by the app
*@return true if service is opened successfully and stream is started, return false otherwise
*/
+ @SuppressWarnings("unused")
+ @Deprecated
public boolean startH264(InputStream is, boolean isEncrypted) {
if (sdlSession == null) return false;
navServiceStartResponseReceived = false;
navServiceStartResponse = false;
+ navServiceStartRejectedParams = null;
+
+ // When startH264() API is used, we will not send video format / width / height information
+ // with StartService. (Reasons: InputStream does not provide timestamp information so RTP
+ // cannot be used. startH264() does not provide with/height information.)
+ VideoStreamingParameters emptyParam = new VideoStreamingParameters();
+ emptyParam.setResolution(null);
+ emptyParam.setFormat(null);
+ sdlSession.setDesiredVideoParams(emptyParam);
sdlSession.startService(SessionType.NAV, sdlSession.getSessionId(), isEncrypted);
@@ -3555,10 +3720,9 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> ScheduledExecutorService scheduler = createScheduler();
scheduler.execute(fTask);
+ //noinspection StatementWithEmptyBody
while (!navServiceStartResponseReceived && !fTask.isDone());
scheduler.shutdown();
- scheduler = null;
- fTask = null;
if (navServiceStartResponse) {
try {
@@ -3576,22 +3740,33 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> *Opens the video service (serviceType 11) and subsequently provides an OutputStream to the app to use for a raw H264 video stream
*@return OutputStream if service is opened successfully and stream is started, return null otherwise
*/
+ @SuppressWarnings("unused")
+ @Deprecated
public OutputStream startH264(boolean isEncrypted) {
if (sdlSession == null) return null;
navServiceStartResponseReceived = false;
navServiceStartResponse = false;
+ navServiceStartRejectedParams = null;
+
+ // When startH264() API is used, we will not send video format / width / height information
+ // with StartService. (Reasons: OutputStream does not provide timestamp information so RTP
+ // cannot be used. startH264() does not provide with/height information.)
+ VideoStreamingParameters emptyParam = new VideoStreamingParameters();
+ emptyParam.setResolution(null);
+ emptyParam.setFormat(null);
+ sdlSession.setDesiredVideoParams(emptyParam);
+
sdlSession.startService(SessionType.NAV, sdlSession.getSessionId(), isEncrypted);
FutureTask<Void> fTask = createFutureTask(new CallableMethod(RESPONSE_WAIT_TIME));
ScheduledExecutorService scheduler = createScheduler();
scheduler.execute(fTask);
+ //noinspection StatementWithEmptyBody
while (!navServiceStartResponseReceived && !fTask.isDone());
scheduler.shutdown();
- scheduler = null;
- fTask = null;
if (navServiceStartResponse) {
try {
@@ -3608,66 +3783,49 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> *Closes the opened video service (serviceType 11)
*@return true if the video service is closed successfully, return false otherwise
*/
+ @SuppressWarnings("unused")
+ @Deprecated
public boolean endH264() {
- if (sdlSession == null) return false;
-
- navServiceEndResponseReceived = false;
- navServiceEndResponse = false;
- sdlSession.stopVideoStream();
-
- FutureTask<Void> fTask = createFutureTask(new CallableMethod(RESPONSE_WAIT_TIME));
- ScheduledExecutorService scheduler = createScheduler();
- scheduler.execute(fTask);
-
- while (!navServiceEndResponseReceived && !fTask.isDone());
- scheduler.shutdown();
- scheduler = null;
- fTask = null;
-
- if (navServiceEndResponse) {
- return true;
- } else {
- return false;
- }
+ return endVideoStream();
}
/**
*Pauses the stream for the opened audio service (serviceType 10)
*@return true if the audio service stream is paused successfully, return false otherwise
*/
- public boolean pausePCM()
- {
- if (sdlSession == null) return false;
- return sdlSession.pauseAudioStream();
+ @SuppressWarnings("unused")
+ @Deprecated
+ public boolean pausePCM() {
+ return pauseAudioStream();
}
/**
*Pauses the stream for the opened video service (serviceType 11)
*@return true if the video service stream is paused successfully, return false otherwise
*/
- public boolean pauseH264()
- {
- if (sdlSession == null) return false;
- return sdlSession.pauseVideoStream();
+ @SuppressWarnings("unused")
+ @Deprecated
+ public boolean pauseH264() {
+ return pauseVideoStream();
}
/**
*Resumes the stream for the opened audio service (serviceType 10)
*@return true if the audio service stream is resumed successfully, return false otherwise
*/
- public boolean resumePCM()
- {
- if (sdlSession == null) return false;
- return sdlSession.resumeAudioStream();
+ @SuppressWarnings("unused")
+ @Deprecated
+ public boolean resumePCM() {
+ return resumeAudioStream();
}
/**
*Resumes the stream for the opened video service (serviceType 11)
*@return true if the video service is resumed successfully, return false otherwise
*/
- public boolean resumeH264()
- {
- if (sdlSession == null) return false;
- return sdlSession.resumeVideoStream();
+ @SuppressWarnings("unused")
+ @Deprecated
+ public boolean resumeH264() {
+ return resumeVideoStream();
}
@@ -3675,6 +3833,8 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> *Opens the audio service (serviceType 10) and subsequently streams raw PCM audio from an InputStream provided by the app
*@return true if service is opened successfully and stream is started, return false otherwise
*/
+ @SuppressWarnings("unused")
+ @Deprecated
public boolean startPCM(InputStream is, boolean isEncrypted) {
if (sdlSession == null) return false;
@@ -3686,10 +3846,9 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> ScheduledExecutorService scheduler = createScheduler();
scheduler.execute(fTask);
+ //noinspection StatementWithEmptyBody
while (!pcmServiceStartResponseReceived && !fTask.isDone());
scheduler.shutdown();
- scheduler = null;
- fTask = null;
if (pcmServiceStartResponse) {
try {
@@ -3707,6 +3866,8 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> *Opens the audio service (serviceType 10) and subsequently provides an OutputStream to the app
*@return OutputStream if service is opened successfully and stream is started, return null otherwise
*/
+ @SuppressWarnings("unused")
+ @Deprecated
public OutputStream startPCM(boolean isEncrypted) {
if (sdlSession == null) return null;
@@ -3718,10 +3879,9 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> ScheduledExecutorService scheduler = createScheduler();
scheduler.execute(fTask);
+ //noinspection StatementWithEmptyBody
while (!pcmServiceStartResponseReceived && !fTask.isDone());
scheduler.shutdown();
- scheduler = null;
- fTask = null;
if (pcmServiceStartResponse) {
try {
@@ -3730,6 +3890,19 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> return null;
}
} else {
+ if (pcmServiceStartRejectedParams != null) {
+ StringBuilder builder = new StringBuilder();
+ for (String paramName : pcmServiceStartRejectedParams) {
+ if (builder.length() > 0) {
+ builder.append(", ");
+ }
+ builder.append(paramName);
+ }
+ DebugTool.logWarning("StartService for nav failed. Rejected params: " + builder.toString());
+
+ } else {
+ DebugTool.logWarning("StartService for nav failed (rejected params not supplied)");
+ }
return null;
}
}
@@ -3738,31 +3911,88 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> *Closes the opened audio service (serviceType 10)
*@return true if the audio service is closed successfully, return false otherwise
*/
+ @SuppressWarnings("unused")
+ @Deprecated
public boolean endPCM() {
- if (sdlSession == null) return false;
- SdlConnection sdlConn = sdlSession.getSdlConnection();
- if (sdlConn == null) return false;
-
- pcmServiceEndResponseReceived = false;
- pcmServiceEndResponse = false;
- sdlSession.stopAudioStream();
-
- FutureTask<Void> fTask = createFutureTask(new CallableMethod(RESPONSE_WAIT_TIME));
- ScheduledExecutorService scheduler = createScheduler();
- scheduler.execute(fTask);
+ return endAudioStream();
+ }
+
+ /**
+ * Opens a video service (service type 11) and subsequently provides an IVideoStreamListener
+ * to the app to send video data.
+ *
+ * @param isEncrypted Specify true if packets on this service have to be encrypted
+ * @param codec Video codec which will be used for streaming. Currently, only
+ * VideoStreamingCodec.H264 is accepted.
+ * @param width Width of the video in pixels
+ * @param height Height of the video in pixels
+ *
+ * @return IVideoStreamListener interface if service is opened successfully and streaming is
+ * started, null otherwise
+ */
+ @SuppressWarnings("unused")
+ public IVideoStreamListener startVideoStream(boolean isEncrypted, VideoStreamingCodec codec,
+ int width, int height) {
+ if (sdlSession == null) {
+ DebugTool.logWarning("SdlSession is not created yet.");
+ return null;
+ }
+ if (sdlSession.getSdlConnection() == null) {
+ DebugTool.logWarning("SdlConnection is not available.");
+ return null;
+ }
- while (!pcmServiceEndResponseReceived && !fTask.isDone());
- scheduler.shutdown();
- scheduler = null;
- fTask = null;
+ VideoStreamingCodec[] codecs = {codec};
+ VideoStreamingParameters acceptedParams = tryStartVideoStream(codecs, width, height, -1, -1,
+ -1, isEncrypted);
+ if (acceptedParams != null) {
+ return sdlSession.startVideoStream();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ *Closes the opened video service (serviceType 11)
+ *@return true if the video service is closed successfully, return false otherwise
+ */
+ @SuppressWarnings("unused")
+ public boolean endVideoStream() {
+ if (sdlSession == null) return false;
+
+ navServiceEndResponseReceived = false;
+ navServiceEndResponse = false;
+ sdlSession.stopVideoStream();
+
+ FutureTask<Void> fTask = createFutureTask(new CallableMethod(RESPONSE_WAIT_TIME));
+ ScheduledExecutorService scheduler = createScheduler();
+ scheduler.execute(fTask);
+
+ //noinspection StatementWithEmptyBody
+ while (!navServiceEndResponseReceived && !fTask.isDone());
+ scheduler.shutdown();
+
+ return navServiceEndResponse;
+ }
+
+ /**
+ *Pauses the stream for the opened video service (serviceType 11)
+ *@return true if the video service stream is paused successfully, return false otherwise
+ */
+ @SuppressWarnings("unused")
+ public boolean pauseVideoStream() {
+ return sdlSession != null && sdlSession.pauseVideoStream();
+ }
+
+ /**
+ *Resumes the stream for the opened video service (serviceType 11)
+ *@return true if the video service is resumed successfully, return false otherwise
+ */
+ @SuppressWarnings("unused")
+ public boolean resumeVideoStream() {
+ return sdlSession != null && sdlSession.resumeVideoStream();
+ }
- if (pcmServiceEndResponse) {
- return true;
- } else {
- return false;
- }
- }
-
/**
* Opens the video service (serviceType 11) and creates a Surface (used for streaming video) with input parameters provided by the app
* @param frameRate - specified rate of frames to utilize for creation of Surface
@@ -3772,38 +4002,196 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * @param bitrate - specified bitrate to utilize for creation of Surface
*@return Surface if service is opened successfully and stream is started, return null otherwise
*/
- public Surface createOpenGLInputSurface(int frameRate, int iFrameInterval, int width,
- int height, int bitrate, boolean isEncrypted) {
+ @SuppressWarnings("unused")
+ public Surface createOpenGLInputSurface(int frameRate, int iFrameInterval, int width,
+ int height, int bitrate, boolean isEncrypted) {
if (sdlSession == null) return null;
SdlConnection sdlConn = sdlSession.getSdlConnection();
if (sdlConn == null) return null;
-
- navServiceStartResponseReceived = false;
- navServiceStartResponse = false;
- sdlSession.startService(SessionType.NAV, sdlSession.getSessionId(), isEncrypted);
-
- FutureTask<Void> fTask = createFutureTask(new CallableMethod(RESPONSE_WAIT_TIME));
- ScheduledExecutorService scheduler = createScheduler();
- scheduler.execute(fTask);
-
- while (!navServiceStartResponseReceived && !fTask.isDone());
- scheduler.shutdown();
- scheduler = null;
- fTask = null;
-
- if (navServiceStartResponse) {
+
+ VideoStreamingCodec[] codecs = {VideoStreamingCodec.H264};
+ VideoStreamingParameters acceptedParams = tryStartVideoStream(codecs, width, height, bitrate,
+ frameRate, iFrameInterval, isEncrypted);
+ if (acceptedParams != null) {
return sdlSession.createOpenGLInputSurface(frameRate, iFrameInterval, width,
- height, bitrate, SessionType.NAV, sdlSession.getSessionId());
+ height, bitrate, SessionType.NAV, sdlSession.getSessionId());
} else {
return null;
}
}
-
+
+ /**
+ * Try to open a video service by trying all available codec/protocols one by one.
+ *
+ * Only information from codecs, width and height are used during video format negotiation.
+ *
+ * @param codecs List of video codecs which app or proxy would like to use
+ * @param width Width of the video in pixels
+ * @param height Height of the video in pixels
+ * @param bitrate Specified bitrate of the video
+ * @param frameRate Specified rate of frames
+ * @param iFrameInterval Specified interval
+ * @param isEncrypted Specify true if packets on this service have to be encrypted
+ *
+ * @return If the service is opened successfully, an instance of VideoStreamingParams is
+ * returned which contains accepted video format. If the service is opened with legacy
+ * mode (i.e. without any negotiation) then an instance of VideoStreamingParams is
+ * returned, but its video format and resolution are null.
+ * If the service was not opened then null is returned.
+ */
+ @SuppressWarnings("unused")
+ private VideoStreamingParameters tryStartVideoStream(VideoStreamingCodec[] codecs,
+ int width, int height,
+ int bitrate, int frameRate, int iFrameInterval,
+ boolean isEncrypted) {
+ if (sdlSession == null) {
+ DebugTool.logWarning("SdlSession is not created yet.");
+ return null;
+ }
+ if (codecs == null || codecs.length == 0) {
+ DebugTool.logWarning("Video codec list is not supplied.");
+ return null;
+ }
+
+ List<VideoStreamingFormat> availableFormats = new ArrayList<>();
+ for (VideoStreamingCodec codec : codecs) {
+ if (codec == VideoStreamingCodec.H264) {
+ availableFormats.add(VIDEO_STREAMING_FORMAT_H264_RTP);
+ availableFormats.add(VIDEO_STREAMING_FORMAT_H264_RAW);
+ } else {
+ DebugTool.logInfo("Video codec " + codec +" is not supported.");
+ }
+ }
+
+ VideoStreamingCapability videoStreamingCapabilities = null;
+ if (_systemCapabilityManager != null) {
+ videoStreamingCapabilities = (VideoStreamingCapability) _systemCapabilityManager.getCapability(
+ SystemCapabilityType.VIDEO_STREAMING);
+ }
+
+ List<VideoStreamingParameters> desiredParamsList = createDesiredVideoParams(
+ videoStreamingCapabilities, frameRate, iFrameInterval, width, height, bitrate,
+ availableFormats.toArray(new VideoStreamingFormat[0]));
+
+ // If none of video formats are accepted then try StartService without parameter at last.
+ // This also applies to the case where the system is legacy and capability isn't available.
+ VideoStreamingParameters emptyParam = new VideoStreamingParameters();
+ emptyParam.setResolution(null);
+ emptyParam.setFormat(null);
+ desiredParamsList.add(emptyParam);
+
+ for (VideoStreamingParameters params : desiredParamsList) {
+ sdlSession.setDesiredVideoParams(params);
+
+ navServiceStartResponseReceived = false;
+ navServiceStartResponse = false;
+ navServiceStartRejectedParams = null;
+
+ sdlSession.startService(SessionType.NAV, sdlSession.getSessionId(), isEncrypted);
+
+ FutureTask<Void> fTask = createFutureTask(new CallableMethod(RESPONSE_WAIT_TIME));
+ ScheduledExecutorService scheduler = createScheduler();
+ scheduler.execute(fTask);
+
+ //noinspection StatementWithEmptyBody
+ while (!navServiceStartResponseReceived && !fTask.isDone());
+ scheduler.shutdown();
+
+ if (navServiceStartResponse) {
+ if (!params.equals(emptyParam)) {
+ DebugTool.logInfo("StartService for nav succeeded with params: " + params);
+ } else {
+ DebugTool.logInfo("StartService for nav succeeded in legacy mode.");
+ }
+ return params;
+ }
+
+ if (navServiceStartRejectedParams != null) {
+ StringBuilder builder = new StringBuilder();
+ for (String paramName : navServiceStartRejectedParams) {
+ if (builder.length() > 0) {
+ builder.append(", ");
+ }
+ builder.append(paramName);
+ }
+ DebugTool.logWarning("StartService for nav failed. Rejected params: " + builder.toString());
+
+ if (!navServiceStartRejectedParams.contains(ControlFrameTags.Video.StartService.VIDEO_PROTOCOL)
+ && !navServiceStartRejectedParams.contains(ControlFrameTags.Video.StartService.VIDEO_CODEC)) {
+ // The reason of NACK is not protocol nor codec. There is no point retrying with
+ // another video format, so we simply fail here.
+ break;
+ }
+ } else {
+ DebugTool.logWarning("StartService for nav failed (rejected params not supplied)");
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Creates a list of VideoStreamingParams with video formats that are supported by both HMI and proxy
+ *
+ * Note: this method does not take care of matching video resolution. App should look into
+ * HMI capability's preferredResolution and adjust width and height accordingly.
+ *
+ * @param hmiCapability HMI's capability information
+ * @param frameRate specified rate of frames
+ * @param frameInterval specified interval
+ * @param width specified width of the video
+ * @param height specified height of the video
+ * @param bitrate specified bitrate of the video
+ * @param availableFormats list of video formats supported by proxy
+ * @return list of VideoStreamingParams instance. This list can be empty.
+ */
+ private static List<VideoStreamingParameters> createDesiredVideoParams(
+ VideoStreamingCapability hmiCapability,
+ int frameRate, int frameInterval, int width, int height, int bitrate,
+ VideoStreamingFormat[] availableFormats) {
+ ArrayList<VideoStreamingFormat> formats = new ArrayList<>();
+ if (hmiCapability != null && hmiCapability.getSupportedFormats() != null
+ && availableFormats != null) {
+ // supportedFormat is listed in HMI's preferred order
+ for (VideoStreamingFormat supportedFormat : hmiCapability.getSupportedFormats()) {
+ for (VideoStreamingFormat availableFormat : availableFormats) {
+ if (supportedFormat.getProtocol() == availableFormat.getProtocol()
+ && supportedFormat.getCodec() == availableFormat.getCodec()) {
+ formats.add(supportedFormat);
+ break;
+ }
+ }
+ }
+ }
+
+ ArrayList<VideoStreamingParameters> list = new ArrayList<>();
+ for (VideoStreamingFormat format : formats) {
+ VideoStreamingParameters params = new VideoStreamingParameters();
+ ImageResolution resolution = new ImageResolution();
+ resolution.setResolutionWidth(width);
+ resolution.setResolutionHeight(height);
+ params.setResolution(resolution);
+ if (frameRate >= 0) {
+ params.setFrameRate(frameRate);
+ }
+ if (bitrate >= 0) {
+ params.setBitrate(bitrate);
+ }
+ if (frameInterval >= 0) {
+ params.setInterval(frameInterval);
+ }
+ params.setFormat(format);
+ list.add(params);
+ }
+
+ return list;
+ }
+
/**
*Starts the MediaCodec encoder utilized in conjunction with the Surface returned via the createOpenGLInputSurface method
*/
- public void startEncoder () {
+ @SuppressWarnings("unused")
+ public void startEncoder () {
if (sdlSession == null) return;
SdlConnection sdlConn = sdlSession.getSdlConnection();
if (sdlConn == null) return;
@@ -3814,7 +4202,8 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> /**
*Releases the MediaCodec encoder utilized in conjunction with the Surface returned via the createOpenGLInputSurface method
*/
- public void releaseEncoder() {
+ @SuppressWarnings("unused")
+ public void releaseEncoder() {
if (sdlSession == null) return;
SdlConnection sdlConn = sdlSession.getSdlConnection();
if (sdlConn == null) return;
@@ -3825,22 +4214,134 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> /**
*Releases the MediaCodec encoder utilized in conjunction with the Surface returned via the createOpenGLInputSurface method
*/
- public void drainEncoder(boolean endOfStream) {
+ @SuppressWarnings("unused")
+ public void drainEncoder(boolean endOfStream) {
if (sdlSession == null) return;
SdlConnection sdlConn = sdlSession.getSdlConnection();
if (sdlConn == null) return;
sdlSession.drainEncoder(endOfStream);
}
-
+
+ /**
+ * Opens a audio service (service type 10) and subsequently provides an IAudioStreamListener
+ * to the app to send audio data.
+ *
+ * Currently information passed by "params" are ignored, since Audio Streaming feature lacks
+ * capability negotiation mechanism. App should configure audio stream data to align with
+ * head unit's capability by checking (upcoming) pcmCapabilities. The default format is in
+ * 16kHz and 16 bits.
+ *
+ * @param isEncrypted Specify true if packets on this service have to be encrypted
+ * @param codec Audio codec which will be used for streaming. Currently, only
+ * AudioStreamingCodec.LPCM is accepted.
+ * @param params (Reserved for future use) Additional configuration information for each
+ * codec. If "codec" is AudioStreamingCodec.LPCM, "params" must be an
+ * instance of LPCMParams class.
+ *
+ * @return IAudioStreamListener interface if service is opened successfully and streaming is
+ * started, null otherwise
+ */
+ @SuppressWarnings("unused")
+ public IAudioStreamListener startAudioStream(boolean isEncrypted, AudioStreamingCodec codec,
+ AudioStreamingParams params) {
+ if (sdlSession == null) {
+ DebugTool.logWarning("SdlSession is not created yet.");
+ return null;
+ }
+ if (sdlSession.getSdlConnection() == null) {
+ DebugTool.logWarning("SdlConnection is not available.");
+ return null;
+ }
+ if (codec != AudioStreamingCodec.LPCM) {
+ DebugTool.logWarning("Audio codec " + codec + " is not supported.");
+ return null;
+ }
+
+ pcmServiceStartResponseReceived = false;
+ pcmServiceStartResponse = false;
+ sdlSession.startService(SessionType.PCM, sdlSession.getSessionId(), isEncrypted);
+
+ FutureTask<Void> fTask = createFutureTask(new CallableMethod(RESPONSE_WAIT_TIME));
+ ScheduledExecutorService scheduler = createScheduler();
+ scheduler.execute(fTask);
+
+ //noinspection StatementWithEmptyBody
+ while (!pcmServiceStartResponseReceived && !fTask.isDone());
+ scheduler.shutdown();
+
+ if (pcmServiceStartResponse) {
+ DebugTool.logInfo("StartService for audio succeeded");
+ return sdlSession.startAudioStream();
+ } else {
+ if (pcmServiceStartRejectedParams != null) {
+ StringBuilder builder = new StringBuilder();
+ for (String paramName : pcmServiceStartRejectedParams) {
+ if (builder.length() > 0) {
+ builder.append(", ");
+ }
+ builder.append(paramName);
+ }
+ DebugTool.logWarning("StartService for audio failed. Rejected params: " + builder.toString());
+ } else {
+ DebugTool.logWarning("StartService for audio failed (rejected params not supplied)");
+ }
+ return null;
+ }
+ }
+
+ /**
+ *Closes the opened audio service (serviceType 10)
+ *@return true if the audio service is closed successfully, return false otherwise
+ */
+ @SuppressWarnings("unused")
+ public boolean endAudioStream() {
+ if (sdlSession == null) return false;
+ SdlConnection sdlConn = sdlSession.getSdlConnection();
+ if (sdlConn == null) return false;
+
+ pcmServiceEndResponseReceived = false;
+ pcmServiceEndResponse = false;
+ sdlSession.stopAudioStream();
+
+ FutureTask<Void> fTask = createFutureTask(new CallableMethod(RESPONSE_WAIT_TIME));
+ ScheduledExecutorService scheduler = createScheduler();
+ scheduler.execute(fTask);
+
+ //noinspection StatementWithEmptyBody
+ while (!pcmServiceEndResponseReceived && !fTask.isDone());
+ scheduler.shutdown();
+
+ return pcmServiceEndResponse;
+ }
+
+ /**
+ *Pauses the stream for the opened audio service (serviceType 10)
+ *@return true if the audio service stream is paused successfully, return false otherwise
+ */
+ @SuppressWarnings("unused")
+ public boolean pauseAudioStream() {
+ return sdlSession != null && sdlSession.pauseAudioStream();
+ }
+
+ /**
+ *Resumes the stream for the opened audio service (serviceType 10)
+ *@return true if the audio service stream is resumed successfully, return false otherwise
+ */
+ @SuppressWarnings("unused")
+ public boolean resumeAudioStream() {
+ return sdlSession != null && sdlSession.resumeAudioStream();
+ }
+
private void NavServiceStarted() {
navServiceStartResponseReceived = true;
navServiceStartResponse = true;
}
- private void NavServiceStartedNACK() {
+ private void NavServiceStartedNACK(List<String> rejectedParams) {
navServiceStartResponseReceived = true;
navServiceStartResponse = false;
+ navServiceStartRejectedParams = rejectedParams;
}
private void AudioServiceStarted() {
@@ -3852,9 +4353,10 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> rpcProtectedResponseReceived = true;
rpcProtectedStartResponse = true;
}
- private void AudioServiceStartedNACK() {
+ private void AudioServiceStartedNACK(List<String> rejectedParams) {
pcmServiceStartResponseReceived = true;
pcmServiceStartResponse = false;
+ pcmServiceStartRejectedParams = rejectedParams;
}
private void NavServiceEnded() {
@@ -3882,6 +4384,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _appService = mService;
}
+ @SuppressWarnings("unused")
public boolean startProtectedRPCService() {
rpcProtectedResponseReceived = false;
rpcProtectedStartResponse = false;
@@ -3891,18 +4394,14 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> ScheduledExecutorService scheduler = createScheduler();
scheduler.execute(fTask);
+ //noinspection StatementWithEmptyBody
while (!rpcProtectedResponseReceived && !fTask.isDone());
scheduler.shutdown();
- scheduler = null;
- fTask = null;
- if (rpcProtectedStartResponse) {
- return true;
- } else {
- return false;
- }
- }
-
+ return rpcProtectedStartResponse;
+ }
+
+ @SuppressWarnings("unused")
public void getLockScreenIcon(final OnLockScreenIconDownloadedListener l){
if(lockScreenIconRequest == null){
l.onLockScreenIconDownloadError(new SdlException("This version of SDL core may not support lock screen icons.",
@@ -3923,7 +4422,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> }
}
- /******************** Public Helper Methods *************************/
+ /* ******************* Public Helper Methods *************************/
/*Begin V1 Enhanced helper*/
@@ -3938,11 +4437,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> *@param IconValue -A static hex icon value or the binary image file name identifier (sent by the PutFile RPC).
*@param IconType -Describes whether the image is static or dynamic
*@param correlationID -A unique ID that correlates each RPCRequest and RPCResponse
- *@throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("SameParameterValue")
public void addCommand(Integer commandID,
- String menuText, Integer parentID, Integer position,
- Vector<String> vrCommands, String IconValue, ImageType IconType, Integer correlationID)
+ String menuText, Integer parentID, Integer position,
+ Vector<String> vrCommands, String IconValue, ImageType IconType, Integer correlationID)
throws SdlException {
AddCommand msg = RPCRequestFactory.buildAddCommand(commandID, menuText, parentID, position,
@@ -3961,11 +4461,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> *@param IconValue -A static hex icon value or the binary image file name identifier (sent by the PutFile RPC).
*@param IconType -Describes whether the image is static or dynamic
*@param correlationID -A unique ID that correlates each RPCRequest and RPCResponse
- *@throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void addCommand(Integer commandID,
- String menuText, Integer position,
- Vector<String> vrCommands, String IconValue, ImageType IconType, Integer correlationID)
+ String menuText, Integer position,
+ Vector<String> vrCommands, String IconValue, ImageType IconType, Integer correlationID)
throws SdlException {
addCommand(commandID, menuText, null, position, vrCommands, IconValue, IconType, correlationID);
@@ -3980,11 +4481,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> *@param IconValue -A static hex icon value or the binary image file name identifier (sent by the PutFile RPC).
*@param IconType -Describes whether the image is static or dynamic
*@param correlationID -A unique ID that correlates each RPCRequest and RPCResponse
- *@throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void addCommand(Integer commandID,
- String menuText, Integer position, String IconValue, ImageType IconType,
- Integer correlationID)
+ String menuText, Integer position, String IconValue, ImageType IconType,
+ Integer correlationID)
throws SdlException {
addCommand(commandID, menuText, null, position, null, IconValue, IconType, correlationID);
@@ -3998,10 +4500,11 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> *@param IconValue -A static hex icon value or the binary image file name identifier (sent by the PutFile RPC).
*@param IconType -Describes whether the image is static or dynamic
*@param correlationID -A unique ID that correlates each RPCRequest and RPCResponse
- *@throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void addCommand(Integer commandID,
- String menuText, String IconValue, ImageType IconType, Integer correlationID)
+ String menuText, String IconValue, ImageType IconType, Integer correlationID)
throws SdlException {
addCommand(commandID, menuText, null, null, null, IconValue, IconType, correlationID);
@@ -4016,10 +4519,11 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * @param IconValue -A static hex icon value or the binary image file name identifier (sent by the PutFile RPC).
* @param IconType -Describes whether the image is static or dynamic
* @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void addCommand(Integer commandID,
- String menuText, Vector<String> vrCommands, String IconValue, ImageType IconType, Integer correlationID)
+ String menuText, Vector<String> vrCommands, String IconValue, ImageType IconType, Integer correlationID)
throws SdlException {
addCommand(commandID, menuText, null, null, vrCommands, IconValue, IconType, correlationID);
@@ -4033,10 +4537,11 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * @param IconValue -A static hex icon value or the binary image file name identifier (sent by the PutFile RPC).
* @param IconType -Describes whether the image is static or dynamic
* @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void addCommand(Integer commandID,
- Vector<String> vrCommands, String IconValue, ImageType IconType, Integer correlationID)
+ Vector<String> vrCommands, String IconValue, ImageType IconType, Integer correlationID)
throws SdlException {
addCommand(commandID, null, null, null, vrCommands, IconValue, IconType, correlationID);
@@ -4053,11 +4558,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> *@param position -Menu position for optional sub value containing menu parameters.
*@param vrCommands -VR synonyms for this AddCommand.
*@param correlationID -A unique ID that correlates each RPCRequest and RPCResponse
- *@throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("SameParameterValue")
public void addCommand(Integer commandID,
- String menuText, Integer parentID, Integer position,
- Vector<String> vrCommands, Integer correlationID)
+ String menuText, Integer parentID, Integer position,
+ Vector<String> vrCommands, Integer correlationID)
throws SdlException {
AddCommand msg = RPCRequestFactory.buildAddCommand(commandID, menuText, parentID, position,
@@ -4074,11 +4580,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> *@param position -Menu position for optional sub value containing menu parameters.
*@param vrCommands -VR synonyms for this AddCommand.
*@param correlationID -A unique ID that correlates each RPCRequest and RPCResponse
- *@throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void addCommand(Integer commandID,
- String menuText, Integer position,
- Vector<String> vrCommands, Integer correlationID)
+ String menuText, Integer position,
+ Vector<String> vrCommands, Integer correlationID)
throws SdlException {
addCommand(commandID, menuText, null, position, vrCommands, correlationID);
@@ -4091,11 +4598,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> *@param menuText -Menu text for optional sub value containing menu parameters.
*@param position -Menu position for optional sub value containing menu parameters.
*@param correlationID -A unique ID that correlates each RPCRequest and RPCResponse
- *@throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void addCommand(Integer commandID,
- String menuText, Integer position,
- Integer correlationID)
+ String menuText, Integer position,
+ Integer correlationID)
throws SdlException {
addCommand(commandID, menuText, null, position, null, correlationID);
@@ -4107,14 +4615,13 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> *@param commandID -Unique command ID of the command to add.
*@param menuText -Menu text for optional sub value containing menu parameters.
*@param correlationID -A unique ID that correlates each RPCRequest and RPCResponse
- *@throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void addCommand(Integer commandID,
- String menuText, Integer correlationID)
+ String menuText, Integer correlationID)
throws SdlException {
- Vector<String> vrCommands = null;
-
- addCommand(commandID, menuText, null, null, vrCommands, correlationID);
+ addCommand(commandID, menuText, null, null, (Vector<String>)null, correlationID);
}
/**
@@ -4124,10 +4631,11 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> *@param menuText -Menu text for optional sub value containing menu parameters.
*@param vrCommands -VR synonyms for this AddCommand.
*@param correlationID -A unique ID that correlates each RPCRequest and RPCResponse
- *@throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void addCommand(Integer commandID,
- String menuText, Vector<String> vrCommands, Integer correlationID)
+ String menuText, Vector<String> vrCommands, Integer correlationID)
throws SdlException {
addCommand(commandID, menuText, null, null, vrCommands, correlationID);
@@ -4139,10 +4647,11 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> *@param commandID -Unique command ID of the command to add.
*@param vrCommands -VR synonyms for this AddCommand.
*@param correlationID -A unique ID that correlates each RPCRequest and RPCResponse
- *@throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void addCommand(Integer commandID,
- Vector<String> vrCommands, Integer correlationID)
+ Vector<String> vrCommands, Integer correlationID)
throws SdlException {
addCommand(commandID, null, null, null, vrCommands, correlationID);
@@ -4156,10 +4665,11 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * @param menuName -Text to show in the menu for this sub menu.
* @param position -Position within the items that are are at top level of the in application menu.
* @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("SameParameterValue")
public void addSubMenu(Integer menuID, String menuName,
- Integer position, Integer correlationID)
+ Integer position, Integer correlationID)
throws SdlException {
AddSubMenu msg = RPCRequestFactory.buildAddSubMenu(menuID, menuName,
@@ -4174,10 +4684,11 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * @param menuID -Unique ID of the sub menu to add.
* @param menuName -Text to show in the menu for this sub menu.
* @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void addSubMenu(Integer menuID, String menuName,
- Integer correlationID) throws SdlException {
+ Integer correlationID) throws SdlException {
addSubMenu(menuID, menuName, null, correlationID);
}
@@ -4194,11 +4705,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * @param duration -Timeout in milliseconds.
* @param softButtons -A list of App defined SoftButtons.
* @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("SameParameterValue")
public void alert(String ttsText, String alertText1,
- String alertText2, String alertText3, Boolean playTone, Integer duration, Vector<SoftButton> softButtons,
- Integer correlationID) throws SdlException {
+ String alertText2, String alertText3, Boolean playTone, Integer duration, Vector<SoftButton> softButtons,
+ Integer correlationID) throws SdlException {
Alert msg = RPCRequestFactory.buildAlert(ttsText, alertText1, alertText2, alertText3, playTone, duration, softButtons, correlationID);
@@ -4216,7 +4728,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * @param duration -Timeout in milliseconds.
* @param softButtons -A list of App defined SoftButtons.
* @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
public void alert(Vector<TTSChunk> ttsChunks,
String alertText1, String alertText2, String alertText3, Boolean playTone,
@@ -4234,10 +4746,11 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * @param playTone -Defines if tone should be played.
* @param softButtons -A list of App defined SoftButtons.
* @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void alert(String ttsText, Boolean playTone, Vector<SoftButton> softButtons,
- Integer correlationID) throws SdlException {
+ Integer correlationID) throws SdlException {
alert(ttsText, null, null, null, playTone, null, softButtons, correlationID);
}
@@ -4249,10 +4762,11 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * @param playTone -Defines if tone should be played.
* @param softButtons -A list of App defined SoftButtons.
* @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void alert(Vector<TTSChunk> chunks, Boolean playTone, Vector<SoftButton> softButtons,
- Integer correlationID) throws SdlException {
+ Integer correlationID) throws SdlException {
alert(chunks, null, null, null, playTone, null, softButtons, correlationID);
}
@@ -4267,10 +4781,11 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * @param duration -Timeout in milliseconds.
* @param softButtons -A list of App defined SoftButtons.
* @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void alert(String alertText1, String alertText2, String alertText3,
- Boolean playTone, Integer duration, Vector<SoftButton> softButtons, Integer correlationID)
+ Boolean playTone, Integer duration, Vector<SoftButton> softButtons, Integer correlationID)
throws SdlException {
alert((Vector<TTSChunk>)null, alertText1, alertText2, alertText3, playTone, duration, softButtons, correlationID);
@@ -4287,11 +4802,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * @param playTone -Defines if tone should be played.
* @param duration -Timeout in milliseconds.
* @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("SameParameterValue")
public void alert(String ttsText, String alertText1,
- String alertText2, Boolean playTone, Integer duration,
- Integer correlationID) throws SdlException {
+ String alertText2, Boolean playTone, Integer duration,
+ Integer correlationID) throws SdlException {
Alert msg = RPCRequestFactory.buildAlert(ttsText, alertText1, alertText2,
playTone, duration, correlationID);
@@ -4308,7 +4824,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * @param playTone -Defines if tone should be played.
* @param duration -Timeout in milliseconds.
* @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
public void alert(Vector<TTSChunk> ttsChunks,
String alertText1, String alertText2, Boolean playTone,
@@ -4326,10 +4842,11 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * @param ttsText -The text to speech message in the form of a string.
* @param playTone -Defines if tone should be played.
* @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void alert(String ttsText, Boolean playTone,
- Integer correlationID) throws SdlException {
+ Integer correlationID) throws SdlException {
alert(ttsText, null, null, playTone, null, correlationID);
}
@@ -4340,10 +4857,11 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * @param chunks -A list of text/phonemes to speak in the form of ttsChunks.
* @param playTone -Defines if tone should be played.
* @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void alert(Vector<TTSChunk> chunks, Boolean playTone,
- Integer correlationID) throws SdlException {
+ Integer correlationID) throws SdlException {
alert(chunks, null, null, playTone, null, correlationID);
}
@@ -4356,10 +4874,11 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * @param playTone -Defines if tone should be played.
* @param duration -Timeout in milliseconds.
* @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void alert(String alertText1, String alertText2,
- Boolean playTone, Integer duration, Integer correlationID)
+ Boolean playTone, Integer duration, Integer correlationID)
throws SdlException {
alert((Vector<TTSChunk>)null, alertText1, alertText2, playTone, duration, correlationID);
@@ -4368,11 +4887,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> /**
* Sends a CreateInteractionChoiceSet RPCRequest to SDL. Responses are captured through callback on IProxyListener.
*
- * @param choiceSet
- * @param interactionChoiceSetID
- * @param correlationID
- * @throws SdlException
+ * @param choiceSet to be sent to the module
+ * @param interactionChoiceSetID to be used in reference to the supplied choiceSet
+ * @param correlationID to be set to the RPCRequest
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void createInteractionChoiceSet(
Vector<Choice> choiceSet, Integer interactionChoiceSetID,
Integer correlationID) throws SdlException {
@@ -4388,10 +4908,11 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> *
* @param commandID -ID of the command(s) to delete.
* @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void deleteCommand(Integer commandID,
- Integer correlationID) throws SdlException {
+ Integer correlationID) throws SdlException {
DeleteCommand msg = RPCRequestFactory.buildDeleteCommand(commandID, correlationID);
@@ -4403,8 +4924,9 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> *
* @param interactionChoiceSetID -ID of the interaction choice set to delete.
* @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void deleteInteractionChoiceSet(
Integer interactionChoiceSetID, Integer correlationID)
throws SdlException {
@@ -4420,10 +4942,11 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> *
* @param menuID -The menuID of the submenu to delete.
* @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void deleteSubMenu(Integer menuID,
- Integer correlationID) throws SdlException {
+ Integer correlationID) throws SdlException {
DeleteSubMenu msg = RPCRequestFactory.buildDeleteSubMenu(menuID, correlationID);
@@ -4442,11 +4965,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * @param interactionChoiceSetID -Interaction choice set IDs to use with an interaction.
* @param vrHelp -Suggested VR Help Items to display on-screen during Perform Interaction.
* @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse.
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void performInteraction(String initPrompt,
- String displayText, Integer interactionChoiceSetID, Vector<VrHelpItem> vrHelp,
- Integer correlationID) throws SdlException {
+ String displayText, Integer interactionChoiceSetID, Vector<VrHelpItem> vrHelp,
+ Integer correlationID) throws SdlException {
PerformInteraction msg = RPCRequestFactory.buildPerformInteraction(initPrompt,
displayText, interactionChoiceSetID, vrHelp, correlationID);
@@ -4466,13 +4990,14 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * @param timeout -Timeout in milliseconds.
* @param vrHelp -Suggested VR Help Items to display on-screen during Perform Interaction.
* @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse.
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void performInteraction(String initPrompt,
- String displayText, Integer interactionChoiceSetID,
- String helpPrompt, String timeoutPrompt,
- InteractionMode interactionMode, Integer timeout, Vector<VrHelpItem> vrHelp,
- Integer correlationID) throws SdlException {
+ String displayText, Integer interactionChoiceSetID,
+ String helpPrompt, String timeoutPrompt,
+ InteractionMode interactionMode, Integer timeout, Vector<VrHelpItem> vrHelp,
+ Integer correlationID) throws SdlException {
PerformInteraction msg = RPCRequestFactory.buildPerformInteraction(
initPrompt, displayText, interactionChoiceSetID,
@@ -4494,13 +5019,14 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * @param timeout -Timeout in milliseconds.
* @param vrHelp -Suggested VR Help Items to display on-screen during Perform Interaction.
* @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse.
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void performInteraction(String initPrompt,
- String displayText, Vector<Integer> interactionChoiceSetIDList,
- String helpPrompt, String timeoutPrompt,
- InteractionMode interactionMode, Integer timeout, Vector<VrHelpItem> vrHelp,
- Integer correlationID) throws SdlException {
+ String displayText, Vector<Integer> interactionChoiceSetIDList,
+ String helpPrompt, String timeoutPrompt,
+ InteractionMode interactionMode, Integer timeout, Vector<VrHelpItem> vrHelp,
+ Integer correlationID) throws SdlException {
PerformInteraction msg = RPCRequestFactory.buildPerformInteraction(initPrompt,
displayText, interactionChoiceSetIDList,
@@ -4522,8 +5048,9 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * @param timeout -Timeout in milliseconds.
* @param vrHelp -Suggested VR Help Items to display on-screen during Perform Interaction.
* @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse.
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void performInteraction(
Vector<TTSChunk> initChunks, String displayText,
Vector<Integer> interactionChoiceSetIDList,
@@ -4548,11 +5075,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * @param displayText -Text to be displayed first.
* @param interactionChoiceSetID -Interaction choice set IDs to use with an interaction.
* @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse.
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void performInteraction(String initPrompt,
- String displayText, Integer interactionChoiceSetID,
- Integer correlationID) throws SdlException {
+ String displayText, Integer interactionChoiceSetID,
+ Integer correlationID) throws SdlException {
PerformInteraction msg = RPCRequestFactory.buildPerformInteraction(initPrompt,
displayText, interactionChoiceSetID, correlationID);
@@ -4571,13 +5099,14 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * @param interactionMode - The method in which the user is notified and uses the interaction (Manual,VR,Both).
* @param timeout -Timeout in milliseconds.
* @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse.
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void performInteraction(String initPrompt,
- String displayText, Integer interactionChoiceSetID,
- String helpPrompt, String timeoutPrompt,
- InteractionMode interactionMode, Integer timeout,
- Integer correlationID) throws SdlException {
+ String displayText, Integer interactionChoiceSetID,
+ String helpPrompt, String timeoutPrompt,
+ InteractionMode interactionMode, Integer timeout,
+ Integer correlationID) throws SdlException {
PerformInteraction msg = RPCRequestFactory.buildPerformInteraction(
initPrompt, displayText, interactionChoiceSetID,
@@ -4598,13 +5127,14 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * @param interactionMode - The method in which the user is notified and uses the interaction (Manual,VR,Both).
* @param timeout -Timeout in milliseconds.
* @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse.
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void performInteraction(String initPrompt,
- String displayText, Vector<Integer> interactionChoiceSetIDList,
- String helpPrompt, String timeoutPrompt,
- InteractionMode interactionMode, Integer timeout,
- Integer correlationID) throws SdlException {
+ String displayText, Vector<Integer> interactionChoiceSetIDList,
+ String helpPrompt, String timeoutPrompt,
+ InteractionMode interactionMode, Integer timeout,
+ Integer correlationID) throws SdlException {
PerformInteraction msg = RPCRequestFactory.buildPerformInteraction(initPrompt,
displayText, interactionChoiceSetIDList,
@@ -4625,8 +5155,9 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * @param interactionMode - The method in which the user is notified and uses the interaction (Manual,VR,Both).
* @param timeout -Timeout in milliseconds.
* @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse.
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void performInteraction(
Vector<TTSChunk> initChunks, String displayText,
Vector<Integer> interactionChoiceSetIDList,
@@ -4648,7 +5179,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> SdlMsgVersion sdlMsgVersion, String appName, Vector<TTSChunk> ttsName,
String ngnMediaScreenAppName, Vector<String> vrSynonyms, Boolean isMediaApp,
Language languageDesired, Language hmiDisplayLanguageDesired, Vector<AppHMIType> appType,
- String appID, String autoActivateID, Integer correlationID)
+ String appID, Integer correlationID)
throws SdlException {
String carrierName = null;
if(telephonyManager != null){
@@ -4680,13 +5211,14 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> /**
* Sends a SetGlobalProperties RPCRequest to SDL. Responses are captured through callback on IProxyListener.
*
- * @param helpPrompt
- * @param timeoutPrompt
- * @param vrHelpTitle
- * @param vrHelp
- * @param correlationID
- * @throws SdlException
+ * @param helpPrompt that will be used for the VR screen
+ * @param timeoutPrompt string to be displayed after timeout
+ * @param vrHelpTitle string that may be displayed on VR prompt dialog
+ * @param vrHelp a list of VR synonyms that may be displayed to user
+ * @param correlationID to be attached to the request
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void setGlobalProperties(
String helpPrompt, String timeoutPrompt, String vrHelpTitle, Vector<VrHelpItem> vrHelp, Integer correlationID)
throws SdlException {
@@ -4700,13 +5232,14 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> /**
* Sends a SetGlobalProperties RPCRequest to SDL. Responses are captured through callback on IProxyListener.
*
- * @param helpChunks
- * @param timeoutChunks
- * @param vrHelpTitle
- * @param vrHelp
- * @param correlationID
- * @throws SdlException
+ * @param helpChunks tts chunks that should be used when prompting the user
+ * @param timeoutChunks tts chunks that will be used when a timeout occurs
+ * @param vrHelpTitle string that may be displayed on VR prompt dialog
+ * @param vrHelp a list of VR synonyms that may be displayed to user
+ * @param correlationID ID to be attached to the RPCRequest that correlates the RPCResponse
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void setGlobalProperties(
Vector<TTSChunk> helpChunks, Vector<TTSChunk> timeoutChunks, String vrHelpTitle, Vector<VrHelpItem> vrHelp,
Integer correlationID) throws SdlException {
@@ -4721,12 +5254,13 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> /**
* Sends a SetGlobalProperties RPCRequest to SDL. Responses are captured through callback on IProxyListener.
- *
- * @param helpPrompt
- * @param timeoutPrompt
- * @param correlationID
- * @throws SdlException
+ *
+ * @param helpPrompt that will be used for the VR screen
+ * @param timeoutPrompt string to be displayed after timeout
+ * @param correlationID ID to be attached to the RPCRequest that correlates the RPCResponse
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void setGlobalProperties(
String helpPrompt, String timeoutPrompt, Integer correlationID)
throws SdlException {
@@ -4739,12 +5273,13 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> /**
* Sends a SetGlobalProperties RPCRequest to SDL. Responses are captured through callback on IProxyListener.
- *
- * @param helpChunks
- * @param timeoutChunks
- * @param correlationID
- * @throws SdlException
+ *
+ * @param helpChunks tts chunks that should be used when prompting the user
+ * @param timeoutChunks tts chunks that will be used when a timeout occurs
+ * @param correlationID ID to be attached to the RPCRequest that correlates the RPCResponse
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void setGlobalProperties(
Vector<TTSChunk> helpChunks, Vector<TTSChunk> timeoutChunks,
Integer correlationID) throws SdlException {
@@ -4755,8 +5290,9 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> sendRPCRequest(req);
}
+ @SuppressWarnings("unused")
public void resetGlobalProperties(Vector<GlobalProperty> properties,
- Integer correlationID) throws SdlException {
+ Integer correlationID) throws SdlException {
ResetGlobalProperties req = new ResetGlobalProperties();
@@ -4770,16 +5306,17 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> /**
* Sends a SetMediaClockTimer RPCRequest to SDL. Responses are captured through callback on IProxyListener.
*
- * @param hours
- * @param minutes
- * @param seconds
- * @param updateMode
- * @param correlationID
- * @throws SdlException
+ * @param hours integer for hours
+ * @param minutes integer for minutes
+ * @param seconds integer for seconds
+ * @param updateMode mode in which the media clock timer should be updated
+ * @param correlationID ID to be attached to the RPCRequest that correlates the RPCResponse
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void setMediaClockTimer(Integer hours,
- Integer minutes, Integer seconds, UpdateMode updateMode,
- Integer correlationID) throws SdlException {
+ Integer minutes, Integer seconds, UpdateMode updateMode,
+ Integer correlationID) throws SdlException {
SetMediaClockTimer msg = RPCRequestFactory.buildSetMediaClockTimer(hours,
minutes, seconds, updateMode, correlationID);
@@ -4790,10 +5327,11 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> /**
* Pauses the media clock. Responses are captured through callback on IProxyListener.
*
- * @param correlationID
- * @throws SdlException
+ * @param correlationID ID to be attached to the RPCRequest that correlates the RPCResponse
+ * @throws SdlException if an unrecoverable error is encountered
*/
- public void pauseMediaClockTimer(Integer correlationID)
+ @SuppressWarnings("unused")
+ public void pauseMediaClockTimer(Integer correlationID)
throws SdlException {
SetMediaClockTimer msg = RPCRequestFactory.buildSetMediaClockTimer(0,
@@ -4805,10 +5343,11 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> /**
* Resumes the media clock. Responses are captured through callback on IProxyListener.
*
- * @param correlationID
- * @throws SdlException
+ * @param correlationID ID to be attached to the RPCRequest that correlates the RPCResponse
+ * @throws SdlException if an unrecoverable error is encountered
*/
- public void resumeMediaClockTimer(Integer correlationID)
+ @SuppressWarnings("unused")
+ public void resumeMediaClockTimer(Integer correlationID)
throws SdlException {
SetMediaClockTimer msg = RPCRequestFactory.buildSetMediaClockTimer(0,
@@ -4820,10 +5359,11 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> /**
* Clears the media clock. Responses are captured through callback on IProxyListener.
*
- * @param correlationID
- * @throws SdlException
+ * @param correlationID ID to be attached to the RPCRequest that correlates the RPCResponse
+ * @throws SdlException if an unrecoverable error is encountered
*/
- public void clearMediaClockTimer(Integer correlationID)
+ @SuppressWarnings("unused")
+ public void clearMediaClockTimer(Integer correlationID)
throws SdlException {
Show msg = RPCRequestFactory.buildShow(null, null, null, " ", null, null, correlationID);
@@ -4835,24 +5375,25 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> /**
* Sends a Show RPCRequest to SDL. Responses are captured through callback on IProxyListener.
*
- * @param mainText1 -Text displayed in a single or upper display line.
- * @param mainText2 -Text displayed on the second display line.
- * @param mainText3 -Text displayed on the second "page" first display line.
- * @param mainText4 -Text displayed on the second "page" second display line.
- * @param statusBar
- * @param mediaClock -Text value for MediaClock field.
- * @param mediaTrack -Text displayed in the track field.
- * @param graphic -Image struct determining whether static or dynamic image to display in app.
- * @param softButtons -App defined SoftButtons.
- * @param customPresets -App labeled on-screen presets.
- * @param alignment -Specifies how mainText1 and mainText2s texts should be aligned on display.
- * @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse.
- * @throws SdlException
+ * @param mainText1 text displayed in a single or upper display line.
+ * @param mainText2 text displayed on the second display line.
+ * @param mainText3 text displayed on the second "page" first display line.
+ * @param mainText4 text displayed on the second "page" second display line.
+ * @param statusBar text is placed in the status bar area (Only valid for NAVIGATION apps)
+ * @param mediaClock text value for MediaClock field.
+ * @param mediaTrack text displayed in the track field.
+ * @param graphic image struct determining whether static or dynamic image to display in app.
+ * @param softButtons app defined SoftButtons.
+ * @param customPresets app labeled on-screen presets.
+ * @param alignment specifies how mainText1 and mainText2s texts should be aligned on display.
+ * @param correlationID ID to be attached to the RPCRequest that correlates the RPCResponse -A unique ID that correlates each RPCRequest and RPCResponse.
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("SameParameterValue")
public void show(String mainText1, String mainText2, String mainText3, String mainText4,
- String statusBar, String mediaClock, String mediaTrack,
- Image graphic, Vector<SoftButton> softButtons, Vector <String> customPresets,
- TextAlignment alignment, Integer correlationID)
+ String statusBar, String mediaClock, String mediaTrack,
+ Image graphic, Vector<SoftButton> softButtons, Vector <String> customPresets,
+ TextAlignment alignment, Integer correlationID)
throws SdlException {
Show msg = RPCRequestFactory.buildShow(mainText1, mainText2, mainText3, mainText4,
@@ -4874,11 +5415,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * @param customPresets -App labeled on-screen presets.
* @param alignment -Specifies how mainText1 and mainText2s texts should be aligned on display.
* @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse.
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void show(String mainText1, String mainText2, String mainText3, String mainText4,
- Image graphic, Vector<SoftButton> softButtons, Vector <String> customPresets,
- TextAlignment alignment, Integer correlationID)
+ Image graphic, Vector<SoftButton> softButtons, Vector <String> customPresets,
+ TextAlignment alignment, Integer correlationID)
throws SdlException {
show(mainText1, mainText2, mainText3, mainText4, null, null, null, graphic, softButtons, customPresets, alignment, correlationID);
@@ -4888,18 +5430,19 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> /**
* Sends a Show RPCRequest to SDL. Responses are captured through callback on IProxyListener.
*
- * @param mainText1 -Text displayed in a single or upper display line.
- * @param mainText2 -Text displayed on the second display line.
- * @param statusBar
- * @param mediaClock -Text value for MediaClock field.
- * @param mediaTrack -Text displayed in the track field.
- * @param alignment -Specifies how mainText1 and mainText2s texts should be aligned on display.
- * @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse.
- * @throws SdlException
+ * @param mainText1 text displayed in a single or upper display line.
+ * @param mainText2 text displayed on the second display line.
+ * @param statusBar text is placed in the status bar area (Only valid for NAVIGATION apps)
+ * @param mediaClock text value for MediaClock field.
+ * @param mediaTrack text displayed in the track field.
+ * @param alignment specifies how mainText1 and mainText2s texts should be aligned on display.
+ * @param correlationID unique ID that correlates each RPCRequest and RPCResponse.
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("SameParameterValue")
public void show(String mainText1, String mainText2,
- String statusBar, String mediaClock, String mediaTrack,
- TextAlignment alignment, Integer correlationID)
+ String statusBar, String mediaClock, String mediaTrack,
+ TextAlignment alignment, Integer correlationID)
throws SdlException {
Show msg = RPCRequestFactory.buildShow(mainText1, mainText2,
@@ -4916,10 +5459,11 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * @param mainText2 -Text displayed on the second display line.
* @param alignment -Specifies how mainText1 and mainText2s texts should be aligned on display.
* @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse.
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void show(String mainText1, String mainText2,
- TextAlignment alignment, Integer correlationID)
+ TextAlignment alignment, Integer correlationID)
throws SdlException {
show(mainText1, mainText2, null, null, null, alignment, correlationID);
@@ -4930,9 +5474,10 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> *
* @param ttsText -The text to speech message in the form of a string.
* @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse.
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
- public void speak(String ttsText, Integer correlationID)
+ @SuppressWarnings("unused")
+ public void speak(String ttsText, Integer correlationID)
throws SdlException {
Speak msg = RPCRequestFactory.buildSpeak(TTSChunkFactory.createSimpleTTSChunks(ttsText),
@@ -4946,10 +5491,11 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> *
* @param ttsChunks -Text/phonemes to speak in the form of ttsChunks.
* @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse.
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void speak(Vector<TTSChunk> ttsChunks,
- Integer correlationID) throws SdlException {
+ Integer correlationID) throws SdlException {
Speak msg = RPCRequestFactory.buildSpeak(ttsChunks, correlationID);
@@ -4961,10 +5507,11 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> *
* @param buttonName -Name of the button to subscribe.
* @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse.
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void subscribeButton(ButtonName buttonName,
- Integer correlationID) throws SdlException {
+ Integer correlationID) throws SdlException {
SubscribeButton msg = RPCRequestFactory.buildSubscribeButton(buttonName,
correlationID);
@@ -4995,10 +5542,11 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> *
* @param buttonName -Name of the button to unsubscribe.
* @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse.
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
- public void unsubscribeButton(ButtonName buttonName,
- Integer correlationID) throws SdlException {
+ @SuppressWarnings("unused")
+ public void unsubscribeButton(ButtonName buttonName,
+ Integer correlationID) throws SdlException {
UnsubscribeButton msg = RPCRequestFactory.buildUnsubscribeButton(
buttonName, correlationID);
@@ -5014,10 +5562,10 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * @param choiceVrCommands -Vector of vrCommands used to select this choice by voice. Must contain
* at least one non-empty element.
* @return Choice created.
- * @throws SdlException
*/
+ @SuppressWarnings("unused")
public Choice createChoiceSetChoice(Integer choiceID, String choiceMenuName,
- Vector<String> choiceVrCommands) {
+ Vector<String> choiceVrCommands) {
Choice returnChoice = new Choice();
returnChoice.setChoiceID(choiceID);
@@ -5039,11 +5587,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * @param audioType -Specifies the type of audio data being requested.
* @param muteAudio -Defines if the current audio source should be muted during the APT session.
* @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse.
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void performaudiopassthru(String initialPrompt, String audioPassThruDisplayText1, String audioPassThruDisplayText2,
- SamplingRate samplingRate, Integer maxDuration, BitsPerSample bitsPerSample,
- AudioType audioType, Boolean muteAudio, Integer correlationID) throws SdlException {
+ SamplingRate samplingRate, Integer maxDuration, BitsPerSample bitsPerSample,
+ AudioType audioType, Boolean muteAudio, Integer correlationID) throws SdlException {
PerformAudioPassThru msg = RPCRequestFactory.BuildPerformAudioPassThru(initialPrompt, audioPassThruDisplayText1, audioPassThruDisplayText2,
samplingRate, maxDuration, bitsPerSample, audioType, muteAudio, correlationID);
@@ -5053,10 +5602,11 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> /**
* Ends audio pass thru session. Responses are captured through callback on IProxyListener.
*
- * @param correlationID
- * @throws SdlException
+ * @param correlationID ID to be attached to the RPCRequest that correlates the RPCResponse
+ * @throws SdlException if an unrecoverable error is encountered
*/
- public void endaudiopassthru(Integer correlationID) throws SdlException
+ @SuppressWarnings("unused")
+ public void endaudiopassthru(Integer correlationID) throws SdlException
{
EndAudioPassThru msg = RPCRequestFactory.BuildEndAudioPassThru(correlationID);
sendRPCRequest(msg);
@@ -5081,10 +5631,11 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * @param deviceStatus -Subscribes to device status including signal and battery strength.
* @param driverBraking -Subscribes to the status of the brake pedal.
* @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse.
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void subscribevehicledata(boolean gps, boolean speed, boolean rpm, boolean fuelLevel, boolean fuelLevel_State,
- boolean instantFuelConsumption, boolean externalTemperature, boolean prndl, boolean tirePressure,
+ boolean instantFuelConsumption, boolean externalTemperature, boolean prndl, boolean tirePressure,
boolean odometer, boolean beltStatus, boolean bodyInformation, boolean deviceStatus,
boolean driverBraking, Integer correlationID) throws SdlException
{
@@ -5113,13 +5664,14 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * @param deviceStatus -Unsubscribes to device status including signal and battery strength.
* @param driverBraking -Unsubscribes to the status of the brake pedal.
* @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse.
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void unsubscribevehicledata(boolean gps, boolean speed, boolean rpm, boolean fuelLevel, boolean fuelLevel_State,
- boolean instantFuelConsumption, boolean externalTemperature, boolean prndl, boolean tirePressure,
- boolean odometer, boolean beltStatus, boolean bodyInformation, boolean deviceStatus,
- boolean driverBraking, Integer correlationID) throws SdlException
+ boolean instantFuelConsumption, boolean externalTemperature, boolean prndl, boolean tirePressure,
+ boolean odometer, boolean beltStatus, boolean bodyInformation, boolean deviceStatus,
+ boolean driverBraking, Integer correlationID) throws SdlException
{
UnsubscribeVehicleData msg = RPCRequestFactory.BuildUnsubscribeVehicleData(gps, speed, rpm, fuelLevel, fuelLevel_State, instantFuelConsumption, externalTemperature, prndl, tirePressure,
odometer, beltStatus, bodyInformation, deviceStatus, driverBraking, correlationID);
@@ -5147,12 +5699,13 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * @param deviceStatus -Performs an ad-hoc request for device status including signal and battery strength.
* @param driverBraking -Performs an ad-hoc request for the status of the brake pedal.
* @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse.
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void getvehicledata(boolean gps, boolean speed, boolean rpm, boolean fuelLevel, boolean fuelLevel_State,
- boolean instantFuelConsumption, boolean externalTemperature, boolean vin, boolean prndl, boolean tirePressure,
- boolean odometer, boolean beltStatus, boolean bodyInformation, boolean deviceStatus,
- boolean driverBraking, Integer correlationID) throws SdlException
+ boolean instantFuelConsumption, boolean externalTemperature, boolean vin, boolean prndl, boolean tirePressure,
+ boolean odometer, boolean beltStatus, boolean bodyInformation, boolean deviceStatus,
+ boolean driverBraking, Integer correlationID) throws SdlException
{
GetVehicleData msg = RPCRequestFactory.BuildGetVehicleData(gps, speed, rpm, fuelLevel, fuelLevel_State, instantFuelConsumption, externalTemperature, vin, prndl, tirePressure, odometer,
@@ -5169,8 +5722,9 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * @param timeout -App defined timeout. Indicates how long of a timeout from the last action.
* @param softButtons -App defined SoftButtons.
* @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse.
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void scrollablemessage(String scrollableMessageBody, Integer timeout, Vector<SoftButton> softButtons, Integer correlationID) throws SdlException
{
ScrollableMessage msg = RPCRequestFactory.BuildScrollableMessage(scrollableMessageBody, timeout, softButtons, correlationID);
@@ -5188,8 +5742,9 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * @param sliderFooter - Text footer to display (meant to display min/max threshold descriptors).
* @param timeout -App defined timeout. Indicates how long of a timeout from the last action.
* @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse.
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void slider(Integer numTicks, Integer position, String sliderHeader, Vector<String> sliderFooter, Integer timeout, Integer correlationID) throws SdlException
{
Slider msg = RPCRequestFactory.BuildSlider(numTicks, position, sliderHeader, sliderFooter, timeout, correlationID);
@@ -5199,11 +5754,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> /**
* Responses are captured through callback on IProxyListener.
*
- * @param language
- * @param hmiDisplayLanguage
- * @param correlationID
- * @throws SdlException
+ * @param language requested SDL voice engine (VR+TTS) language registration
+ * @param hmiDisplayLanguage request display language registration.
+ * @param correlationID ID to be attached to the RPCRequest that correlates the RPCResponse
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void changeregistration(Language language, Language hmiDisplayLanguage, Integer correlationID) throws SdlException
{
ChangeRegistration msg = RPCRequestFactory.BuildChangeRegistration(language, hmiDisplayLanguage, correlationID);
@@ -5219,13 +5775,14 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * @param iOffset - The data offset in bytes, a value of zero is used to indicate data starting from the beginging of the file.
* A value greater than zero is used for resuming partial data chunks.
* @param iLength - The total length of the file being sent.
- * @throws SdlException
- * @see {@link#putFileStream(InputStream, String, Long, Long)}
+ * @throws SdlException if an unrecoverable error is encountered
+ * @see #putFileStream(InputStream, String, Long, Long)
*/
+ @SuppressWarnings("unused")
@Deprecated
public void putFileStream(InputStream is, String sdlFileName, Integer iOffset, Integer iLength) throws SdlException
{
- PutFile msg = RPCRequestFactory.buildPutFile(sdlFileName, iOffset, iLength);
+ @SuppressWarnings("deprecation") PutFile msg = RPCRequestFactory.buildPutFile(sdlFileName, iOffset, iLength);
startRPCStream(is, msg);
}
@@ -5239,8 +5796,9 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * indicate data starting from the beginning of the file and a value greater
* than zero is used for resuming partial data chunks.
* @param length The total length of the file being sent.
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void putFileStream(InputStream inputStream, String fileName, Long offset, Long length) throws SdlException {
PutFile msg = RPCRequestFactory.buildPutFile(fileName, offset, length);
startRPCStream(inputStream, msg);
@@ -5256,13 +5814,14 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * @param iLength - The total length of the file being sent.
*
* @return OutputStream - The output stream of byte data that is written to by the app developer
- * @throws SdlException
- * @see {@link#putFileStream(String, Long, Long)}
+ * @throws SdlException if an unrecoverable error is encountered
+ * @see #putFileStream(String, Long, Long)
*/
+ @SuppressWarnings("unused")
@Deprecated
public OutputStream putFileStream(String sdlFileName, Integer iOffset, Integer iLength) throws SdlException
{
- PutFile msg = RPCRequestFactory.buildPutFile(sdlFileName, iOffset, iLength);
+ @SuppressWarnings("deprecation") PutFile msg = RPCRequestFactory.buildPutFile(sdlFileName, iOffset, iLength);
return startRPCStream(msg);
}
@@ -5275,8 +5834,9 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * indicate data starting from the beginning of the file and a value greater
* than zero is used for resuming partial data chunks.
* @param length The total length of the file being sent.
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public OutputStream putFileStream(String fileName, Long offset, Long length) throws SdlException {
PutFile msg = RPCRequestFactory.buildPutFile(fileName, offset, length);
return startRPCStream(msg);
@@ -5294,13 +5854,14 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * @param fileType - The selected file type -- see the FileType enumeration for details
* @param bPersistentFile - Indicates if the file is meant to persist between sessions / ignition cycles.
* @param bSystemFile - Indicates if the file is meant to be passed thru core to elsewhere on the system.
- * @throws SdlException
- * @see {@link#putFileStream(InputStream, String, Long, Long, FileType, Boolean, Boolean)}
+ * @throws SdlException if an unrecoverable error is encountered
+ * @see #putFileStream(InputStream, String, Long, Long, FileType, Boolean, Boolean, OnPutFileUpdateListener)
*/
+ @SuppressWarnings("unused")
@Deprecated
public void putFileStream(InputStream is, String sdlFileName, Integer iOffset, Integer iLength, FileType fileType, Boolean bPersistentFile, Boolean bSystemFile) throws SdlException
{
- PutFile msg = RPCRequestFactory.buildPutFile(sdlFileName, iOffset, iLength, fileType, bPersistentFile, bSystemFile);
+ @SuppressWarnings("deprecation") PutFile msg = RPCRequestFactory.buildPutFile(sdlFileName, iOffset, iLength, fileType, bPersistentFile, bSystemFile);
startRPCStream(is, msg);
}
@@ -5320,8 +5881,9 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * sessions / ignition cycles.
* @param isSystemFile Indicates if the file is meant to be passed through
* core to elsewhere in the system.
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void putFileStream(InputStream inputStream, String fileName, Long offset, Long length, FileType fileType, Boolean isPersistentFile, Boolean isSystemFile, OnPutFileUpdateListener cb) throws SdlException {
PutFile msg = RPCRequestFactory.buildPutFile(fileName, offset, length);
msg.setOnPutFileUpdateListener(cb);
@@ -5340,13 +5902,14 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * @param bPersistentFile - Indicates if the file is meant to persist between sessions / ignition cycles.
* @param bSystemFile - Indicates if the file is meant to be passed thru core to elsewhere on the system.
* @return OutputStream - The output stream of byte data that is written to by the app developer
- * @throws SdlException
- * @see {@link#putFileStream(String, Long, Long, FileType, Boolean, Boolean)}
+ * @throws SdlException if an unrecoverable error is encountered
+ * @see #putFileStream(String, Long, Long, FileType, Boolean, Boolean, OnPutFileUpdateListener)
*/
+ @SuppressWarnings("unused")
@Deprecated
public OutputStream putFileStream(String sdlFileName, Integer iOffset, Integer iLength, FileType fileType, Boolean bPersistentFile, Boolean bSystemFile) throws SdlException
{
- PutFile msg = RPCRequestFactory.buildPutFile(sdlFileName, iOffset, iLength, fileType, bPersistentFile, bSystemFile);
+ @SuppressWarnings("deprecation") PutFile msg = RPCRequestFactory.buildPutFile(sdlFileName, iOffset, iLength, fileType, bPersistentFile, bSystemFile);
return startRPCStream(msg);
}
@@ -5365,8 +5928,9 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * sessions / ignition cycles.
* @param isSystemFile Indicates if the file is meant to be passed through
* core to elsewhere in the system.
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public OutputStream putFileStream(String fileName, Long offset, Long length, FileType fileType, Boolean isPersistentFile, Boolean isSystemFile, OnPutFileUpdateListener cb) throws SdlException {
PutFile msg = RPCRequestFactory.buildPutFile(fileName, offset, length);
msg.setOnPutFileUpdateListener(cb);
@@ -5384,15 +5948,16 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * @param fileType - The selected file type -- see the FileType enumeration for details
* @param bPersistentFile - Indicates if the file is meant to persist between sessions / ignition cycles.
* @param bSystemFile - Indicates if the file is meant to be passed thru core to elsewhere on the system.
- * @param correlationID - A unique ID that correlates each RPCRequest and RPCResponse.
+ * @param iCorrelationID - A unique ID that correlates each RPCRequest and RPCResponse.
* @return RPCStreamController - If the putFileStream was not started successfully null is returned, otherwise a valid object reference is returned
- * @throws SdlException
- * @see {@link#putFileStream(String, String, Long, FileType, Boolean, Boolean, Integer)}
+ * @throws SdlException if an unrecoverable error is encountered
+ * @see #putFileStream(String, String, Long, FileType, Boolean, Boolean, Boolean, Integer, OnPutFileUpdateListener)
*/
+ @SuppressWarnings("unused")
@Deprecated
public RPCStreamController putFileStream(String sPath, String sdlFileName, Integer iOffset, FileType fileType, Boolean bPersistentFile, Boolean bSystemFile, Integer iCorrelationID) throws SdlException
{
- PutFile msg = RPCRequestFactory.buildPutFile(sdlFileName, iOffset, 0, fileType, bPersistentFile, bSystemFile, iCorrelationID);
+ @SuppressWarnings("deprecation") PutFile msg = RPCRequestFactory.buildPutFile(sdlFileName, iOffset, 0, fileType, bPersistentFile, bSystemFile, iCorrelationID);
return startPutFileStream(sPath, msg);
}
@@ -5416,8 +5981,9 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * @return RPCStreamController If the putFileStream was not started
* successfully null is returned, otherwise a valid object reference is
* returned .
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public RPCStreamController putFileStream(String path, String fileName, Long offset, FileType fileType, Boolean isPersistentFile, Boolean isSystemFile, Boolean isPayloadProtected, Integer correlationId, OnPutFileUpdateListener cb ) throws SdlException {
PutFile msg = RPCRequestFactory.buildPutFile(fileName, offset, 0L, fileType, isPersistentFile, isSystemFile, isPayloadProtected, correlationId);
msg.setOnPutFileUpdateListener(cb);
@@ -5435,15 +6001,16 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * @param fileType - The selected file type -- see the FileType enumeration for details
* @param bPersistentFile - Indicates if the file is meant to persist between sessions / ignition cycles.
* @param bSystemFile - Indicates if the file is meant to be passed thru core to elsewhere on the system.
- * @param correlationID - A unique ID that correlates each RPCRequest and RPCResponse.
+ * @param iCorrelationID - A unique ID that correlates each RPCRequest and RPCResponse.
* @return RPCStreamController - If the putFileStream was not started successfully null is returned, otherwise a valid object reference is returned
- * @throws SdlException
- * @see {@link#putFileStream(InputStream, String, Long, Long, FileType, Boolean, Boolean, Integer)}
+ * @throws SdlException if an unrecoverable error is encountered
+ * @see #putFileStream(InputStream, String, Long, Long, FileType, Boolean, Boolean, Boolean, Integer)
*/
+ @SuppressWarnings("unused")
@Deprecated
public RPCStreamController putFileStream(InputStream is, String sdlFileName, Integer iOffset, Integer iLength, FileType fileType, Boolean bPersistentFile, Boolean bSystemFile, Integer iCorrelationID) throws SdlException
{
- PutFile msg = RPCRequestFactory.buildPutFile(sdlFileName, iOffset, iLength, fileType, bPersistentFile, bSystemFile, iCorrelationID);
+ @SuppressWarnings("deprecation") PutFile msg = RPCRequestFactory.buildPutFile(sdlFileName, iOffset, iLength, fileType, bPersistentFile, bSystemFile, iCorrelationID);
return startPutFileStream(is, msg);
}
@@ -5465,8 +6032,9 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * core to elsewhere in the system.
* @param correlationId A unique id that correlates each RPCRequest and
* RPCResponse.
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public RPCStreamController putFileStream(InputStream inputStream, String fileName, Long offset, Long length, FileType fileType, Boolean isPersistentFile, Boolean isSystemFile, Boolean isPayloadProtected, Integer correlationId) throws SdlException {
PutFile msg = RPCRequestFactory.buildPutFile(fileName, offset, length, fileType, isPersistentFile, isSystemFile, isPayloadProtected, correlationId);
return startPutFileStream(inputStream, msg);
@@ -5477,6 +6045,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * Used to end an existing putFileStream that was previously initiated with any putFileStream method.
*
*/
+ @SuppressWarnings("unused")
public void endPutFileStream()
{
endRPCStream();
@@ -5490,11 +6059,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * @param sdlFileName -File reference name.
* @param fileType -Selected file type.
* @param persistentFile -Indicates if the file is meant to persist between sessions / ignition cycles.
- * @param fileData
+ * @param fileData byte array of data of the file that is to be sent
* @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse.
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
- public void putfile(String sdlFileName, FileType fileType, Boolean persistentFile, byte[] fileData, Integer correlationID) throws SdlException
+ @SuppressWarnings("unused")
+ public void putfile(String sdlFileName, FileType fileType, Boolean persistentFile, byte[] fileData, Integer correlationID) throws SdlException
{
PutFile msg = RPCRequestFactory.buildPutFile(sdlFileName, fileType, persistentFile, fileData, correlationID);
sendRPCRequest(msg);
@@ -5506,9 +6076,10 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> *
* @param sdlFileName -File reference name.
* @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse.
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
- public void deletefile(String sdlFileName, Integer correlationID) throws SdlException
+ @SuppressWarnings("unused")
+ public void deletefile(String sdlFileName, Integer correlationID) throws SdlException
{
DeleteFile msg = RPCRequestFactory.buildDeleteFile(sdlFileName, correlationID);
sendRPCRequest(msg);
@@ -5519,8 +6090,9 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> * Responses are captured through callback on IProxyListener.
*
* @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse.
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void listfiles(Integer correlationID) throws SdlException
{
ListFiles msg = RPCRequestFactory.buildListFiles(correlationID);
@@ -5533,9 +6105,10 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> *
* @param sdlFileName -File reference name.
* @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse.
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
- public void setappicon(String sdlFileName, Integer correlationID) throws SdlException
+ @SuppressWarnings("unused")
+ public void setappicon(String sdlFileName, Integer correlationID) throws SdlException
{
SetAppIcon msg = RPCRequestFactory.buildSetAppIcon(sdlFileName, correlationID);
sendRPCRequest(msg);
@@ -5547,23 +6120,26 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> *
* @param displayLayout -Predefined or dynamically created screen layout.
* @param correlationID -A unique ID that correlates each RPCRequest and RPCResponse.
- * @throws SdlException
+ * @throws SdlException if an unrecoverable error is encountered
*/
+ @SuppressWarnings("unused")
public void setdisplaylayout(String displayLayout, Integer correlationID) throws SdlException
{
SetDisplayLayout msg = RPCRequestFactory.BuildSetDisplayLayout(displayLayout, correlationID);
sendRPCRequest(msg);
}
+ @SuppressWarnings("unused")
public void getCapability(SystemCapabilityType systemCapabilityType, OnSystemCapabilityListener scListener){
_systemCapabilityManager.getCapability(systemCapabilityType, scListener);
}
+ @SuppressWarnings("unused")
public Object getCapability(SystemCapabilityType systemCapabilityType){
return _systemCapabilityManager.getCapability(systemCapabilityType);
}
- /******************** END Public Helper Methods *************************/
+ /* ******************* END Public Helper Methods *************************/
/**
* Gets type of transport currently used by this SdlProxy.
@@ -5572,6 +6148,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> *
* @see TransportType
*/
+ @SuppressWarnings("unused")
public TransportType getCurrentTransportType() throws IllegalStateException {
if (sdlSession == null) {
throw new IllegalStateException("Incorrect state of SdlProxyBase: Calling for getCurrentTransportType() while connection is not initialized");
@@ -5591,12 +6168,10 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> }
}
- public boolean isServiceTypeProtected(SessionType sType)
- {
- if (sdlSession == null)
- return false;
-
- return sdlSession.isServiceProtected(sType);
+ @SuppressWarnings("unused")
+ public boolean isServiceTypeProtected(SessionType sType) {
+ return sdlSession != null && sdlSession.isServiceProtected(sType);
+
}
@@ -5621,37 +6196,45 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> return _proxyListener;
}
+ @SuppressWarnings("unused")
public String getAppName()
{
return _applicationName;
}
+ @SuppressWarnings("unused")
public String getNgnAppName()
{
return _ngnMediaScreenAppName;
}
+ @SuppressWarnings("unused")
public String getAppID()
{
return _appID;
}
+ @SuppressWarnings("unused")
public DeviceInfo getDeviceInfo()
{
return deviceInfo;
}
+ @SuppressWarnings("unused")
public long getInstanceDT()
{
return instanceDateTime;
}
+ @SuppressWarnings("unused")
public void setConnectionDetails(String sDetails)
{
sConnectionDetails = sDetails;
}
+ @SuppressWarnings("unused")
public String getConnectionDetails()
{
return sConnectionDetails;
}
//for testing only
+ @SuppressWarnings("unused")
public void setPoliciesURL(String sText)
{
sPoliciesURL = sText;
diff --git a/sdl_android/src/main/java/com/smartdevicelink/proxy/SystemCapabilityManager.java b/sdl_android/src/main/java/com/smartdevicelink/proxy/SystemCapabilityManager.java index bd0edb48b..b5dac4768 100644 --- a/sdl_android/src/main/java/com/smartdevicelink/proxy/SystemCapabilityManager.java +++ b/sdl_android/src/main/java/com/smartdevicelink/proxy/SystemCapabilityManager.java @@ -1,5 +1,7 @@ package com.smartdevicelink.proxy; +import com.smartdevicelink.exception.SdlException; +import com.smartdevicelink.proxy.interfaces.ISdl; import com.smartdevicelink.proxy.interfaces.OnSystemCapabilityListener; import com.smartdevicelink.proxy.rpc.GetSystemCapability; import com.smartdevicelink.proxy.rpc.GetSystemCapabilityResponse; @@ -17,13 +19,9 @@ import java.util.List; public class SystemCapabilityManager { HashMap<SystemCapabilityType, Object> cachedSystemCapabilities = new HashMap<>(); - ISystemCapabilityManager callback; + ISdl callback; - public interface ISystemCapabilityManager{ - void onSendPacketRequest(RPCRequest message); - } - - public SystemCapabilityManager(ISystemCapabilityManager callback){ + public SystemCapabilityManager(ISdl callback){ this.callback = callback; } @@ -69,6 +67,8 @@ public class SystemCapabilityManager { return hmiCapabilities.isPhoneCallAvailable(); case VIDEO_STREAMING: return hmiCapabilities.isVideoStreamingAvailable(); + case REMOTE_CONTROL: + return hmiCapabilities.isRemoteControlAvailable(); default: return false; } @@ -133,7 +133,7 @@ public class SystemCapabilityManager { request.setCorrelationID(CorrelationIdGenerator.generateId()); if(callback!=null){ - callback.onSendPacketRequest(request); + callback.sendRPCRequest(request); } } diff --git a/sdl_android/src/main/java/com/smartdevicelink/proxy/interfaces/IAudioStreamListener.java b/sdl_android/src/main/java/com/smartdevicelink/proxy/interfaces/IAudioStreamListener.java new file mode 100644 index 000000000..8d21b7615 --- /dev/null +++ b/sdl_android/src/main/java/com/smartdevicelink/proxy/interfaces/IAudioStreamListener.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2017, Xevo Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.smartdevicelink.proxy.interfaces; + +import java.nio.ByteBuffer; + +/** + * A listener that receives audio streaming data from app. + */ +public interface IAudioStreamListener { + /** + * Sends a chunk of audio data to SDL Core. + * <p> + * Note: this method must not be called after SdlProxyBase.endAudioStream() is called. + * + * @param data Byte array containing audio data + * @param offset Starting offset in 'data' + * @param length Length of the data + * @param presentationTimeUs (Reserved for future use) Presentation timestamp (PTS) of the + * last audio sample data included in this chunk, in microseconds. + * It must be greater than the previous timestamp. + * Specify -1 if unknown. + * @throws ArrayIndexOutOfBoundsException When offset does not satisfy + * {@code 0 <= offset && offset <= data.length} + * or length does not satisfy + * {@code 0 < length && offset + length <= data.length} + */ + void sendAudio(byte[] data, int offset, int length, long presentationTimeUs) + throws ArrayIndexOutOfBoundsException; + + /** + * Sends a chunk of audio data to SDL Core. + * <p> + * Note: this method must not be called after SdlProxyBase.endAudioStream() is called. + * + * @param data Data chunk to send. Its position will be updated upon return. + * @param presentationTimeUs (Reserved for future use) Presentation timestamp (PTS) of the + * last audio sample data included in this chunk, in microseconds. + * It must be greater than the previous timestamp. + * Specify -1 if unknown. + */ + void sendAudio(ByteBuffer data, long presentationTimeUs); +} diff --git a/sdl_android/src/main/java/com/smartdevicelink/proxy/interfaces/IProxyListenerBase.java b/sdl_android/src/main/java/com/smartdevicelink/proxy/interfaces/IProxyListenerBase.java index 80842cfc2..618819f20 100644 --- a/sdl_android/src/main/java/com/smartdevicelink/proxy/interfaces/IProxyListenerBase.java +++ b/sdl_android/src/main/java/com/smartdevicelink/proxy/interfaces/IProxyListenerBase.java @@ -6,6 +6,7 @@ import com.smartdevicelink.proxy.rpc.AddCommandResponse; import com.smartdevicelink.proxy.rpc.AddSubMenuResponse;
import com.smartdevicelink.proxy.rpc.AlertManeuverResponse;
import com.smartdevicelink.proxy.rpc.AlertResponse;
+import com.smartdevicelink.proxy.rpc.ButtonPressResponse;
import com.smartdevicelink.proxy.rpc.ChangeRegistrationResponse;
import com.smartdevicelink.proxy.rpc.CreateInteractionChoiceSetResponse;
import com.smartdevicelink.proxy.rpc.DeleteCommandResponse;
@@ -17,6 +18,7 @@ import com.smartdevicelink.proxy.rpc.DialNumberResponse; import com.smartdevicelink.proxy.rpc.EndAudioPassThruResponse;
import com.smartdevicelink.proxy.rpc.GenericResponse;
import com.smartdevicelink.proxy.rpc.GetDTCsResponse;
+import com.smartdevicelink.proxy.rpc.GetInteriorVehicleDataResponse;
import com.smartdevicelink.proxy.rpc.GetSystemCapabilityResponse;
import com.smartdevicelink.proxy.rpc.GetVehicleDataResponse;
import com.smartdevicelink.proxy.rpc.GetWayPointsResponse;
@@ -28,6 +30,7 @@ import com.smartdevicelink.proxy.rpc.OnCommand; import com.smartdevicelink.proxy.rpc.OnDriverDistraction;
import com.smartdevicelink.proxy.rpc.OnHMIStatus;
import com.smartdevicelink.proxy.rpc.OnHashChange;
+import com.smartdevicelink.proxy.rpc.OnInteriorVehicleData;
import com.smartdevicelink.proxy.rpc.OnKeyboardInput;
import com.smartdevicelink.proxy.rpc.OnLanguageChange;
import com.smartdevicelink.proxy.rpc.OnLockScreenStatus;
@@ -49,6 +52,7 @@ import com.smartdevicelink.proxy.rpc.SendLocationResponse; import com.smartdevicelink.proxy.rpc.SetAppIconResponse;
import com.smartdevicelink.proxy.rpc.SetDisplayLayoutResponse;
import com.smartdevicelink.proxy.rpc.SetGlobalPropertiesResponse;
+import com.smartdevicelink.proxy.rpc.SetInteriorVehicleDataResponse;
import com.smartdevicelink.proxy.rpc.SetMediaClockTimerResponse;
import com.smartdevicelink.proxy.rpc.ShowConstantTbtResponse;
import com.smartdevicelink.proxy.rpc.ShowResponse;
@@ -340,5 +344,13 @@ public interface IProxyListenerBase { public void onGetSystemCapabilityResponse(GetSystemCapabilityResponse response);
+ public void onGetInteriorVehicleDataResponse(GetInteriorVehicleDataResponse response);
+
+ public void onButtonPressResponse(ButtonPressResponse response);
+
+ public void onSetInteriorVehicleDataResponse(SetInteriorVehicleDataResponse response);
+
+ public void onOnInteriorVehicleData(OnInteriorVehicleData notification);
+
public void onSendHapticDataResponse(SendHapticDataResponse response);
}
diff --git a/sdl_android/src/main/java/com/smartdevicelink/proxy/interfaces/ISdl.java b/sdl_android/src/main/java/com/smartdevicelink/proxy/interfaces/ISdl.java new file mode 100644 index 000000000..2d67f93d7 --- /dev/null +++ b/sdl_android/src/main/java/com/smartdevicelink/proxy/interfaces/ISdl.java @@ -0,0 +1,116 @@ +package com.smartdevicelink.proxy.interfaces; + +import com.smartdevicelink.protocol.enums.FunctionID; +import com.smartdevicelink.protocol.enums.SessionType; +import com.smartdevicelink.proxy.RPCRequest; +import com.smartdevicelink.proxy.rpc.listeners.OnRPCNotificationListener; +import com.smartdevicelink.streaming.VideoStreamingParameters; + +/* + * Copyright (c) 2017 Livio, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Livio Inc. nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +@SuppressWarnings("unused") +public interface ISdl { + + /** + * Starts the connection with the module + */ + void start(); + + /** + * Ends connection with the module + */ + void stop(); + + /** + * Method to check if the session is connected + * @return if there is a connected session + */ + boolean isConnected(); + + /** + * Add a service listener for a specific service type + * @param serviceType service type that the listener will be attached to + * @param sdlServiceListener listener for events that happen to the service + */ + void addServiceListener(SessionType serviceType, ISdlServiceListener sdlServiceListener); + + /** + * Remote a service listener for a specific service type + * @param serviceType service type that the listener was attached to + * @param sdlServiceListener service listener that was previously added for the service type + */ + void removeServiceListener(SessionType serviceType, ISdlServiceListener sdlServiceListener); + + /** + * Starts the video streaming service + * @param parameters desired video streaming params for this sevice to be started with + * @param encrypted flag to start this service with encryption or not + */ + void startVideoService(VideoStreamingParameters parameters, boolean encrypted); + + /** + * Stops the video service if open + */ + void stopVideoService(); + + /** + * Starts the Audio streaming service + * @param encrypted flag to start this service with encryption or not + */ + void startAudioService(boolean encrypted); + + /** + * Stops the audio service if open + */ + void stopAudioService(); + + /** + * Pass an RPC message through the proxy to be sent to the connected module + * @param message RPCRequest that should be sent to the module + */ + void sendRPCRequest(RPCRequest message); + + /** + * Add an OnRPCNotificationListener for specified notification + * @param notificationId FunctionID of the notification that is to be listened for + * @param listener listener that should be added for the notification ID + */ + void addOnRPCNotificationListener(FunctionID notificationId, OnRPCNotificationListener listener); + + /** + * Removes an OnRPCNotificationListener for specified notification + * @param notificationId FunctionID of the notification that was to be listened for + * @param listener listener that was previously added for the notification ID + */ + boolean removeOnRPCNotificationListener(FunctionID notificationId, OnRPCNotificationListener listener); + +} diff --git a/sdl_android/src/main/java/com/smartdevicelink/proxy/interfaces/IVideoStreamListener.java b/sdl_android/src/main/java/com/smartdevicelink/proxy/interfaces/IVideoStreamListener.java new file mode 100644 index 000000000..f645b0d55 --- /dev/null +++ b/sdl_android/src/main/java/com/smartdevicelink/proxy/interfaces/IVideoStreamListener.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2017, Xevo Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.smartdevicelink.proxy.interfaces; + +import java.nio.ByteBuffer; + +/** + * A listener that receives video streaming data from app. + */ +public interface IVideoStreamListener { + + /** + * Sends a chunk of data which represents a frame to SDL Core. + * <p> + * The format of the chunk should align with MediaCodec's "Compressed Buffer" format, i.e. it + * should contain a single video frame, and it should start and end on frame boundaries. + * Please refer to https://developer.android.com/reference/android/media/MediaCodec.html + * Also, for H.264 codec case the stream must be in byte-stream format (also known as Annex-B + * format). This isn't explained in the document above, but MediaCodec does output in this + * format. + * <p> + * In short, you can just provide MediaCodec's data outputs to this method without tweaking + * any data. + * <p> + * Note: this method must not be called after SdlProxyBase.endVideoStream() is called. + * + * @param data Byte array containing a video frame + * @param offset Starting offset in 'data' + * @param length Length of the data + * @param presentationTimeUs Presentation timestamp (PTS) of this frame, in microseconds. + * It must be greater than the previous timestamp. + * Specify -1 if unknown. + * @throws ArrayIndexOutOfBoundsException When offset does not satisfy + * {@code 0 <= offset && offset <= data.length} + * or length does not satisfy + * {@code 0 < length && offset + length <= data.length} + */ + void sendFrame(byte[] data, int offset, int length, long presentationTimeUs) + throws ArrayIndexOutOfBoundsException; + + /** + * Sends chunks of data which represent a frame to SDL Core. + * <p> + * The format of the chunk should align with MediaCodec's "Compressed Buffer" format, i.e. it + * should contain a single video frame, and it should start and end on frame boundaries. + * Please refer to https://developer.android.com/reference/android/media/MediaCodec.html + * Also, for H.264 codec case the stream must be in byte-stream format (also known as Annex-B + * format). This isn't explained in the document above, but MediaCodec does output in this + * format. + * <p> + * In short, you can just provide MediaCodec's data outputs to this method without tweaking + * any data. + * <p> + * Note: this method must not be called after SdlProxyBase.endVideoStream() is called. + * + * @param data Data chunk to send. Its position will be updated upon return. + * @param presentationTimeUs Presentation timestamp (PTS) of this frame, in microseconds. + * It must be greater than the previous timestamp. + * Specify -1 if unknown. + */ + void sendFrame(ByteBuffer data, long presentationTimeUs); +} diff --git a/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/ButtonPress.java b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/ButtonPress.java new file mode 100644 index 000000000..d0162e7ac --- /dev/null +++ b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/ButtonPress.java @@ -0,0 +1,94 @@ +package com.smartdevicelink.proxy.rpc; + +import com.smartdevicelink.protocol.enums.FunctionID; +import com.smartdevicelink.proxy.RPCRequest; +import com.smartdevicelink.proxy.rpc.enums.ButtonName; +import com.smartdevicelink.proxy.rpc.enums.ButtonPressMode; +import com.smartdevicelink.proxy.rpc.enums.ModuleType; +import java.util.Hashtable; + +/** + * This function allows a remote control type mobile application + * simulate a hardware button press event. + */ +public class ButtonPress extends RPCRequest { + public static final String KEY_MODULE_TYPE = "moduleType"; + public static final String KEY_BUTTON_NAME = "buttonName"; + public static final String KEY_BUTTON_PRESS_MODE = "buttonPressMode"; + + /** + * Constructs a new ButtonPress object + */ + public ButtonPress() { + super(FunctionID.BUTTON_PRESS.toString()); + } + + /** + * <p>Constructs a new ButtonPress object indicated by the + * Hashtable parameter</p> + * + * + * @param hash + * The Hashtable to use + */ + public ButtonPress(Hashtable<String, Object> hash) { + super(hash); + } + + /** + * Gets the ModuleType + * + * @return ModuleType - The module where the button should be pressed + */ + public ModuleType getModuleType() { + return (ModuleType) getObject(ModuleType.class, KEY_MODULE_TYPE); + } + + /** + * Sets a ModuleType + * + * @param moduleType + * Represents module where the button should be pressed + */ + public void setModuleType(ModuleType moduleType) { + setParameters(KEY_MODULE_TYPE, moduleType); + } + + /** + * Gets the ButtonName + * + * @return ButtonName - The name of supported RC climate or radio button + */ + public ButtonName getButtonName() { + return (ButtonName) getObject(ButtonName.class, KEY_BUTTON_NAME); + } + + /** + * Sets a ButtonName + * + * @param buttonName + * Represents name of supported RC climate or radio button + */ + public void setButtonName(ButtonName buttonName) { + setParameters(KEY_BUTTON_NAME, buttonName); + } + + /** + * Gets the ButtonPressMode + * + * @return ButtonPressMode - Indicates whether this is a LONG or SHORT button press event. + */ + public ButtonPressMode getButtonPressMode() { + return (ButtonPressMode) getObject(ButtonPressMode.class, KEY_BUTTON_PRESS_MODE); + } + + /** + * Sets a ButtonPressMode + * + * @param buttonPressMode + * Indicates whether this is a LONG or SHORT button press event. + */ + public void setButtonPressMode(ButtonPressMode buttonPressMode) { + setParameters(KEY_BUTTON_PRESS_MODE, buttonPressMode); + } +} diff --git a/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/ButtonPressResponse.java b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/ButtonPressResponse.java new file mode 100644 index 000000000..94ccd61a6 --- /dev/null +++ b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/ButtonPressResponse.java @@ -0,0 +1,28 @@ +package com.smartdevicelink.proxy.rpc; + +import com.smartdevicelink.protocol.enums.FunctionID; +import com.smartdevicelink.proxy.RPCResponse; + +import java.util.Hashtable; + +public class ButtonPressResponse extends RPCResponse { + + /** + * Constructs a new ButtonPressResponse object + */ + public ButtonPressResponse() { + super(FunctionID.BUTTON_PRESS.toString()); + } + + /** + * <p>Constructs a new ButtonPressResponse object indicated by the + * Hashtable parameter</p> + * + * + * @param hash + * The Hashtable to use + */ + public ButtonPressResponse(Hashtable<String, Object> hash) { + super(hash); + } +} diff --git a/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/ClimateControlCapabilities.java b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/ClimateControlCapabilities.java new file mode 100644 index 000000000..ac9c3fc1c --- /dev/null +++ b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/ClimateControlCapabilities.java @@ -0,0 +1,280 @@ +package com.smartdevicelink.proxy.rpc; + +import com.smartdevicelink.proxy.RPCStruct; +import com.smartdevicelink.proxy.rpc.enums.DefrostZone; +import com.smartdevicelink.proxy.rpc.enums.VentilationMode; +import java.util.Hashtable; +import java.util.List; + +/** + * Contains information about a climate control module's capabilities. + */ + +public class ClimateControlCapabilities extends RPCStruct{ + public static final String KEY_MODULE_NAME= "moduleName"; + public static final String KEY_FAN_SPEED_AVAILABLE= "fanSpeedAvailable"; + public static final String KEY_DESIRED_TEMPERATURE_AVAILABLE= "desiredTemperatureAvailable"; + public static final String KEY_AC_ENABLE_AVAILABLE= "acEnableAvailable"; + public static final String KEY_AC_MAX_ENABLE_AVAILABLE= "acMaxEnableAvailable"; + public static final String KEY_CIRCULATE_AIR_ENABLE_AVAILABLE= "circulateAirEnableAvailable"; + public static final String KEY_AUTO_MODE_ENABLE_AVAILABLE= "autoModeEnableAvailable"; + public static final String KEY_DUAL_MODE_ENABLE_AVAILABLE= "dualModeEnableAvailable"; + public static final String KEY_DEFROST_ZONE_AVAILABLE= "defrostZoneAvailable"; + public static final String KEY_DEFROST_ZONE= "defrostZone"; + public static final String KEY_VENTILATION_MODE_AVAILABLE= "ventilationModeAvailable"; + public static final String KEY_VENTILATION_MODE= "ventilationMode"; + + public ClimateControlCapabilities() { + } + + public ClimateControlCapabilities(Hashtable<String, Object> hash) { + super(hash); + } + + /** + * Sets the moduleName portion of the ClimateControlCapabilities class + * + * @param moduleName + * The short friendly name of the climate control module. + * It should not be used to identify a module by mobile application. + */ + public void setModuleName(String moduleName) { + setValue(KEY_MODULE_NAME, moduleName); + } + + /** + * Gets the moduleName portion of the ClimateControlCapabilities class + * + * @return String - Short friendly name of the climate control module. + */ + public String getModuleName() { + return getString(KEY_MODULE_NAME); + } + + /** + * Sets the fanSpeedAvailable portion of the ClimateControlCapabilities class + * + * @param fanSpeedAvailable + * Availability of the control of fan speed. + * True: Available, False: Not Available, Not present: Not Available. + */ + public void setFanSpeedAvailable(Boolean fanSpeedAvailable) { + setValue(KEY_FAN_SPEED_AVAILABLE, fanSpeedAvailable); + } + + /** + * Gets the fanSpeedAvailable portion of the ClimateControlCapabilities class + * + * @return Boolean - Availability of the control of fan speed. + * True: Available, False: Not Available, Not present: Not Available. + */ + public Boolean getFanSpeedAvailable() { + return getBoolean(KEY_FAN_SPEED_AVAILABLE); + } + + /** + * Sets the desiredTemperatureAvailable portion of the ClimateControlCapabilities class + * + * @param desiredTemperatureAvailable + * Availability of the control of desired temperature. + * True: Available, False: Not Available, Not present: Not Available. + */ + public void setDesiredTemperatureAvailable(Boolean desiredTemperatureAvailable) { + setValue(KEY_DESIRED_TEMPERATURE_AVAILABLE, desiredTemperatureAvailable); + } + + /** + * Gets the desiredTemperatureAvailable portion of the ClimateControlCapabilities class + * + * @return Boolean - Availability of the control of desired temperature. + * True: Available, False: Not Available, Not present: Not Available. + */ + public Boolean getDesiredTemperatureAvailable() { + return getBoolean(KEY_DESIRED_TEMPERATURE_AVAILABLE); + } + + /** + * Sets the acEnableAvailable portion of the ClimateControlCapabilities class + * + * @param acEnableAvailable + * Availability of the control of turn on/off AC. + * True: Available, False: Not Available, Not present: Not Available. + */ + public void setAcEnableAvailable(Boolean acEnableAvailable) { + setValue(KEY_AC_ENABLE_AVAILABLE, acEnableAvailable); + } + + /** + * Gets the acEnableAvailable portion of the ClimateControlCapabilities class + * + * @return Boolean - Availability of the control of turn on/off AC. + * True: Available, False: Not Available, Not present: Not Available. + */ + public Boolean getAcEnableAvailable() { + return getBoolean(KEY_AC_ENABLE_AVAILABLE); + } + + /** + * Sets the acMaxEnableAvailable portion of the ClimateControlCapabilities class + * + * @param acMaxEnableAvailable + * Availability of the control of enable/disable air conditioning is ON on the maximum level. + * True: Available, False: Not Available, Not present: Not Available. + */ + public void setAcMaxEnableAvailable(Boolean acMaxEnableAvailable) { + setValue(KEY_AC_MAX_ENABLE_AVAILABLE, acMaxEnableAvailable); + } + + /** + * Gets the acMaxEnableAvailable portion of the ClimateControlCapabilities class + * + * @return Boolean - Availability of the control of enable/disable air conditioning is ON on the maximum level. + * True: Available, False: Not Available, Not present: Not Available. + */ + public Boolean getAcMaxEnableAvailable() { + return getBoolean(KEY_AC_MAX_ENABLE_AVAILABLE); + } + + /** + * Sets the circulateAirEnableAvailable portion of the ClimateControlCapabilities class + * + * @param circulateAirEnableAvailable + * Availability of the control of enable/disable circulate Air mode. + * True: Available, False: Not Available, Not present: Not Available. + */ + public void setCirculateAirEnableAvailable(Boolean circulateAirEnableAvailable) { + setValue(KEY_CIRCULATE_AIR_ENABLE_AVAILABLE, circulateAirEnableAvailable); + } + + /** + * Gets the circulateAirEnableAvailable portion of the ClimateControlCapabilities class + * + * @return Boolean - Availability of the control of enable/disable circulate Air mode. + * True: Available, False: Not Available, Not present: Not Available. + */ + public Boolean getCirculateAirEnableAvailable() { + return getBoolean(KEY_CIRCULATE_AIR_ENABLE_AVAILABLE); + } + + /** + * Sets the autoModeEnableAvailable portion of the ClimateControlCapabilities class + * + * @param autoModeEnableAvailable + * Availability of the control of enable/disable auto mode. + * True: Available, False: Not Available, Not present: Not Available. + */ + public void setAutoModeEnableAvailable(Boolean autoModeEnableAvailable) { + setValue(KEY_AUTO_MODE_ENABLE_AVAILABLE, autoModeEnableAvailable); + } + + /** + * Gets the autoModeEnableAvailable portion of the ClimateControlCapabilities class + * + * @return Boolean - Availability of the control of enable/disable auto mode. + * True: Available, False: Not Available, Not present: Not Available. + */ + public Boolean getAutoModeEnableAvailable() { + return getBoolean(KEY_AUTO_MODE_ENABLE_AVAILABLE); + } + + /** + * Sets the dualModeEnableAvailable portion of the ClimateControlCapabilities class + * + * @param dualModeEnableAvailable + * Availability of the control of enable/disable dual mode. + * True: Available, False: Not Available, Not present: Not Available. + */ + public void setDualModeEnableAvailable(Boolean dualModeEnableAvailable) { + setValue(KEY_DUAL_MODE_ENABLE_AVAILABLE, dualModeEnableAvailable); + } + + /** + * Gets the dualModeEnableAvailable portion of the ClimateControlCapabilities class + * + * @return Boolean - Availability of the control of enable/disable dual mode. + * True: Available, False: Not Available, Not present: Not Available. + */ + public Boolean getDualModeEnableAvailable() { + return getBoolean(KEY_DUAL_MODE_ENABLE_AVAILABLE); + } + + /** + * Sets the defrostZoneAvailable portion of the ClimateControlCapabilities class + * + * @param defrostZoneAvailable + * Availability of the control of defrost zones. + * True: Available, False: Not Available, Not present: Not Available. + */ + public void setDefrostZoneAvailable(Boolean defrostZoneAvailable) { + setValue(KEY_DEFROST_ZONE_AVAILABLE, defrostZoneAvailable); + } + + /** + * Gets the defrostZoneAvailable portion of the ClimateControlCapabilities class + * + * @return Boolean - Availability of the control of defrost zones. + * True: Available, False: Not Available, Not present: Not Available. + */ + public Boolean getDefrostZoneAvailable() { + return getBoolean(KEY_DEFROST_ZONE_AVAILABLE); + } + + /** + * Gets the List<DefrostZone> portion of the ClimateControlCapabilities class + * + * @return List<DefrostZone> - A set of all defrost zones that are controllable. + */ + public List<DefrostZone> getDefrostZone() { + return (List<DefrostZone>) getObject(DefrostZone.class, KEY_DEFROST_ZONE); + } + + /** + * Sets the defrostZone portion of the ClimateControlCapabilities class + * + * @param defrostZone + * A set of all defrost zones that are controllable. + */ + public void setDefrostZone(List<DefrostZone> defrostZone) { + setValue(KEY_DEFROST_ZONE, defrostZone); + } + + /** + * Sets the ventilationModeAvailable portion of the ClimateControlCapabilities class + * + * @param ventilationModeAvailable + * Availability of the control of air ventilation mode. + * True: Available, False: Not Available, Not present: Not Available. + */ + public void setVentilationModeAvailable(Boolean ventilationModeAvailable) { + setValue(KEY_VENTILATION_MODE_AVAILABLE, ventilationModeAvailable); + } + + /** + * Gets the ventilationModeAvailable portion of the ClimateControlCapabilities class + * + * @return Boolean - Availability of the control of air ventilation mode. + * True: Available, False: Not Available, Not present: Not Available. + */ + public Boolean getVentilationModeAvailable() { + return getBoolean(KEY_VENTILATION_MODE_AVAILABLE); + } + + /** + * Gets the List<VentilationMode> portion of the ClimateControlCapabilities class + * + * @return List<VentilationMode> - A set of all ventilation modes that are controllable. + */ + public List<VentilationMode> getVentilationMode() { + return (List<VentilationMode>) getObject(VentilationMode.class, KEY_VENTILATION_MODE); + } + + /** + * Sets the ventilationMode portion of the ClimateControlCapabilities class + * + * @param ventilationMode + * A set of all ventilation modes that are controllable. + */ + public void setVentilationMode(List<VentilationMode> ventilationMode) { + setValue(KEY_VENTILATION_MODE, ventilationMode); + } +} diff --git a/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/ClimateControlData.java b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/ClimateControlData.java new file mode 100644 index 000000000..0da8060f3 --- /dev/null +++ b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/ClimateControlData.java @@ -0,0 +1,106 @@ +package com.smartdevicelink.proxy.rpc; + +import com.smartdevicelink.proxy.RPCStruct; +import com.smartdevicelink.proxy.rpc.enums.DefrostZone; +import com.smartdevicelink.proxy.rpc.enums.VentilationMode; +import java.util.Hashtable; + +public class ClimateControlData extends RPCStruct{ + public static final String KEY_FAN_SPEED= "fanSpeed"; + public static final String KEY_CURRENT_TEMPERATURE= "currentTemperature"; + public static final String KEY_DESIRED_TEMPERATURE= "desiredTemperature"; + public static final String KEY_AC_ENABLE= "acEnable"; + public static final String KEY_CIRCULATE_AIR_ENABLE= "circulateAirEnable"; + public static final String KEY_AUTO_MODE_ENABLE= "autoModeEnable"; + public static final String KEY_DEFROST_ZONE= "defrostZone"; + public static final String KEY_DUAL_MODE_ENABLE= "dualModeEnable"; + public static final String KEY_AC_MAX_ENABLE= "acMaxEnable"; + public static final String KEY_VENTILATION_MODE= "ventilationMode"; + + public ClimateControlData() { + } + + public ClimateControlData(Hashtable<String, Object> hash) { + super(hash); + } + + public void setFanSpeed(Integer fanSpeed) { + setValue(KEY_FAN_SPEED, fanSpeed); + } + + public Integer getFanSpeed() { + return getInteger(KEY_FAN_SPEED); + } + + public void setCurrentTemperature(Temperature currentTemperature) { + setValue(KEY_CURRENT_TEMPERATURE, currentTemperature); + } + + public Temperature getCurrentTemperature() { + return (Temperature) getObject(Temperature.class, KEY_CURRENT_TEMPERATURE); + } + + public void setDesiredTemperature(Temperature desiredTemperature) { + setValue(KEY_DESIRED_TEMPERATURE, desiredTemperature); + } + + public Temperature getDesiredTemperature() { + return (Temperature) getObject(Temperature.class, KEY_DESIRED_TEMPERATURE); + } + + public void setAcEnable(Boolean acEnable) { + setValue(KEY_AC_ENABLE, acEnable); + } + + public Boolean getAcEnable() { + return getBoolean(KEY_AC_ENABLE); + } + + public void setCirculateAirEnable(Boolean circulateAirEnable) { + setValue(KEY_CIRCULATE_AIR_ENABLE, circulateAirEnable); + } + + public Boolean getCirculateAirEnable() { + return getBoolean(KEY_CIRCULATE_AIR_ENABLE); + } + + public void setAutoModeEnable(Boolean autoModeEnable) { + setValue(KEY_AUTO_MODE_ENABLE, autoModeEnable); + } + + public Boolean getAutoModeEnable() { + return getBoolean(KEY_AUTO_MODE_ENABLE); + } + + public void setDefrostZone(DefrostZone defrostZone) { + setValue(KEY_DEFROST_ZONE, defrostZone); + } + + public DefrostZone getDefrostZone() { + return (DefrostZone) getObject(DefrostZone.class, KEY_DEFROST_ZONE); + } + + public void setDualModeEnable(Boolean dualModeEnable) { + setValue(KEY_DUAL_MODE_ENABLE, dualModeEnable); + } + + public Boolean getDualModeEnable() { + return getBoolean(KEY_DUAL_MODE_ENABLE); + } + + public void setAcMaxEnable(Boolean acMaxEnable) { + setValue(KEY_AC_MAX_ENABLE, acMaxEnable); + } + + public Boolean getAcMaxEnable() { + return getBoolean(KEY_AC_MAX_ENABLE); + } + + public void setVentilationMode(VentilationMode ventilationMode) { + setValue(KEY_VENTILATION_MODE, ventilationMode); + } + + public VentilationMode getVentilationMode() { + return (VentilationMode) getObject(VentilationMode.class, KEY_VENTILATION_MODE); + } +} diff --git a/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/GetInteriorVehicleData.java b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/GetInteriorVehicleData.java new file mode 100644 index 000000000..53108b4fb --- /dev/null +++ b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/GetInteriorVehicleData.java @@ -0,0 +1,79 @@ +package com.smartdevicelink.proxy.rpc; + +import com.smartdevicelink.protocol.enums.FunctionID; +import com.smartdevicelink.proxy.RPCRequest; +import com.smartdevicelink.proxy.rpc.enums.ModuleType; +import java.util.Hashtable; + +/** + * Read the current status value of specified remote control module (type). In addition, + * When subscribe=true, subscribes for specific remote control module data items; + * When subscribe=false, un-subscribes for specific remote control module data items. + * Once subscribed, the application will be notified by the onInteriorVehicleData notification + * whenever new data is available for the module. + */ +public class GetInteriorVehicleData extends RPCRequest { + public static final String KEY_MODULE_TYPE = "moduleType"; + public static final String KEY_SUBSCRIBE = "subscribe"; + + /** + * Constructs a new GetInteriorVehicleData object + */ + public GetInteriorVehicleData() { + super(FunctionID.GET_INTERIOR_VEHICLE_DATA.toString()); + } + + /** + * <p>Constructs a new GetInteriorVehicleData object indicated by the + * Hashtable parameter</p> + * + * + * @param hash + * The Hashtable to use + */ + public GetInteriorVehicleData(Hashtable<String, Object> hash) { + super(hash); + } + + /** + * Gets the ModuleType + * + * @return ModuleType - The type of a RC module to retrieve module data from the vehicle. + * In the future, this should be the Identification of a module. + */ + public ModuleType getModuleType() { + return (ModuleType) getObject(ModuleType.class, KEY_MODULE_TYPE); + } + + /** + * Sets a ModuleType + * + * @param moduleType + * The type of a RC module to retrieve module data from the vehicle. + * In the future, this should be the Identification of a module. + */ + public void setModuleType(ModuleType moduleType) { + setParameters(KEY_MODULE_TYPE, moduleType); + } + + /** + * Sets subscribe parameter + * + * @param subscribe + * If subscribe is true, the head unit will register onInteriorVehicleData notifications for the requested moduelType. + * If subscribe is false, the head unit will unregister onInteriorVehicleData notifications for the requested moduelType. + */ + public void setSubscribe(Boolean subscribe) { + setParameters(KEY_SUBSCRIBE, subscribe); + } + + /** + * Gets subscribe parameter + * + * @return Boolean - If subscribe is true, the head unit will register onInteriorVehicleData notifications for the requested moduelType. + * If subscribe is false, the head unit will unregister onInteriorVehicleData notifications for the requested moduelType. + */ + public Boolean getSubscribe() { + return getBoolean(KEY_SUBSCRIBE); + } +} diff --git a/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/GetInteriorVehicleDataResponse.java b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/GetInteriorVehicleDataResponse.java new file mode 100644 index 000000000..0e74001f6 --- /dev/null +++ b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/GetInteriorVehicleDataResponse.java @@ -0,0 +1,70 @@ +package com.smartdevicelink.proxy.rpc; + +import com.smartdevicelink.protocol.enums.FunctionID; +import com.smartdevicelink.proxy.RPCResponse; +import java.util.Hashtable; + +public class GetInteriorVehicleDataResponse extends RPCResponse { + public static final String KEY_MODULE_DATA = "moduleData"; + public static final String KEY_IS_SUBSCRIBED = "isSubscribed"; + + /** + * Constructs a new GetInteriorVehicleDataResponse object + */ + public GetInteriorVehicleDataResponse() { + super(FunctionID.GET_INTERIOR_VEHICLE_DATA.toString()); + } + + /** + * <p>Constructs a new GetInteriorVehicleDataResponse object indicated by the + * Hashtable parameter</p> + * + * + * @param hash + * The Hashtable to use + */ + public GetInteriorVehicleDataResponse(Hashtable<String, Object> hash) { + super(hash); + } + + /** + * Gets the moduleData + * + * @return ModuleData + */ + public ModuleData getModuleData() { + return (ModuleData) getObject(ModuleData.class, KEY_MODULE_DATA); + } + + /** + * Sets the moduleData + * + * @param moduleData + */ + public void setModuleData(ModuleData moduleData) { + setParameters(KEY_MODULE_DATA, moduleData); + } + + /** + * Sets isSubscribed parameter + * + * @param isSubscribed + * It is a conditional-mandatory parameter: must be returned in case "subscribe" parameter was present in the related request. + * If "true" - the "moduleType" from request is successfully subscribed and the head unit will send onInteriorVehicleData notifications for the moduleType. + * If "false" - the "moduleType" from request is either unsubscribed or failed to subscribe. + * */ + public void setIsSubscribed(Boolean isSubscribed) { + setParameters(KEY_IS_SUBSCRIBED, isSubscribed); + } + + /** + * Gets isSubscribed parameter + * + * @return Boolean - It is a conditional-mandatory parameter: must be returned in case "subscribe" parameter was present in the related request. + * If "true" - the "moduleType" from request is successfully subscribed and the head unit will send onInteriorVehicleData notifications for the moduleType. + * If "false" - the "moduleType" from request is either unsubscribed or failed to subscribe. + * */ + public Boolean getIsSubscribed() { + return getBoolean(KEY_IS_SUBSCRIBED); + } +} diff --git a/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/HMICapabilities.java b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/HMICapabilities.java index 77c534c9f..8f4cdfe66 100644 --- a/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/HMICapabilities.java +++ b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/HMICapabilities.java @@ -8,6 +8,7 @@ public class HMICapabilities extends RPCStruct{ public static final String KEY_NAVIGATION = "navigation"; public static final String KEY_PHONE_CALL = "phoneCall"; public static final String KEY_VIDEO_STREAMING = "videoStreaming"; + public static final String KEY_REMOTE_CONTROL = "remoteControl"; public HMICapabilities() { } @@ -51,5 +52,17 @@ public class HMICapabilities extends RPCStruct{ setValue(KEY_VIDEO_STREAMING, available); } + public boolean isRemoteControlAvailable(){ + Object available = getValue(KEY_REMOTE_CONTROL); + if(available == null){ + return false; + } + return (Boolean)available; + } + + public void setRemoteControlAvailable(Boolean available){ + setValue(KEY_REMOTE_CONTROL, available); + } + } diff --git a/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/ImageResolution.java b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/ImageResolution.java index d9c85eb8f..5858a45d0 100644 --- a/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/ImageResolution.java +++ b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/ImageResolution.java @@ -76,4 +76,10 @@ public class ImageResolution extends RPCStruct { public Integer getResolutionHeight() {
return getInteger(KEY_RESOLUTION_HEIGHT);
}
+
+ @Override
+ public String toString() {
+ return "width=" + String.valueOf(getResolutionWidth()) +
+ ", height=" + String.valueOf(getResolutionHeight());
+ }
}
diff --git a/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/ModuleData.java b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/ModuleData.java new file mode 100644 index 000000000..e04ab1ad5 --- /dev/null +++ b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/ModuleData.java @@ -0,0 +1,75 @@ +package com.smartdevicelink.proxy.rpc; + +import com.smartdevicelink.proxy.RPCStruct; +import com.smartdevicelink.proxy.rpc.enums.ModuleType; +import java.util.Hashtable; + +public class ModuleData extends RPCStruct{ + public static final String KEY_MODULE_TYPE= "moduleType"; + public static final String KEY_RADIO_CONTROL_DATA = "radioControlData"; + public static final String KEY_CLIMATE_CONTROL_DATA = "climateControlData"; + + public ModuleData() { + } + + public ModuleData(Hashtable<String, Object> hash) { + super(hash); + } + + /** + * Sets the moduleType portion of the ModuleData class + * + * @param moduleType + * The moduleType indicates which type of data should be changed and identifies which data object exists in this struct. + * For example, if the moduleType is CLIMATE then a "climateControlData" should exist + */ + public void setModuleType(ModuleType moduleType) { + setValue(KEY_MODULE_TYPE, moduleType); + } + + /** + * Gets the moduleType portion of the ModuleData class + * + * @return ModuleType - The moduleType indicates which type of data should be changed and identifies which data object exists in this struct. + * For example, if the moduleType is CLIMATE then a "climateControlData" should exist. + */ + public ModuleType getModuleType() { + return (ModuleType) getObject(ModuleType.class, KEY_MODULE_TYPE); + } + + /** + * Sets the radioControlData portion of the ModuleData class + * + * @param radioControlData + */ + public void setRadioControlData(RadioControlData radioControlData) { + setValue(KEY_RADIO_CONTROL_DATA, radioControlData); + } + + /** + * Gets the radioControlData portion of the ModuleData class + * + * @return RadioControlData + */ + public RadioControlData getRadioControlData() { + return (RadioControlData) getObject(RadioControlData.class, KEY_RADIO_CONTROL_DATA); + } + + /** + * Sets the climateControlData portion of the ModuleData class + * + * @param climateControlData + */ + public void setClimateControlData(ClimateControlData climateControlData) { + setValue(KEY_CLIMATE_CONTROL_DATA, climateControlData); + } + + /** + * Gets the climateControlData portion of the ModuleData class + * + * @return ClimateControlData + */ + public ClimateControlData getClimateControlData() { + return (ClimateControlData) getObject(ClimateControlData.class, KEY_CLIMATE_CONTROL_DATA); + } +} diff --git a/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/OnInteriorVehicleData.java b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/OnInteriorVehicleData.java new file mode 100644 index 000000000..61e9ee17a --- /dev/null +++ b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/OnInteriorVehicleData.java @@ -0,0 +1,47 @@ +package com.smartdevicelink.proxy.rpc; + +import com.smartdevicelink.protocol.enums.FunctionID; +import com.smartdevicelink.proxy.RPCNotification; + +import java.util.Hashtable; + +public class OnInteriorVehicleData extends RPCNotification { + public static final String KEY_MODULE_DATA = "moduleData"; + + /** + * Constructs a new OnInteriorVehicleData object + */ + public OnInteriorVehicleData() { + super(FunctionID.ON_INTERIOR_VEHICLE_DATA.toString()); + } + + /** + * <p>Constructs a new OnInteriorVehicleData object indicated by the + * Hashtable parameter</p> + * + * + * @param hash + * The Hashtable to use + */ + public OnInteriorVehicleData(Hashtable<String, Object> hash) { + super(hash); + } + + /** + * Gets the moduleData + * + * @return ModuleData + */ + public ModuleData getModuleData() { + return (ModuleData) getObject(ModuleData.class, KEY_MODULE_DATA); + } + + /** + * Sets the moduleData + * + * @param moduleData + */ + public void setModuleData(ModuleData moduleData) { + setParameters(KEY_MODULE_DATA, moduleData); + } +} diff --git a/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/RadioControlCapabilities.java b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/RadioControlCapabilities.java new file mode 100644 index 000000000..3acfe77a9 --- /dev/null +++ b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/RadioControlCapabilities.java @@ -0,0 +1,236 @@ +package com.smartdevicelink.proxy.rpc; + +import com.smartdevicelink.proxy.RPCStruct; +import java.util.Hashtable; + +/** + * Contains information about a radio control module's capabilities. + */ +public class RadioControlCapabilities extends RPCStruct{ + public static final String KEY_MODULE_NAME= "moduleName"; + public static final String KEY_RADIO_ENABLE_AVAILABLE= "radioEnableAvailable"; + public static final String KEY_RADIO_BAND_AVAILABLE= "radioBandAvailable"; + public static final String KEY_RADIO_FREQUENCY_AVAILABLE= "radioFrequencyAvailable"; + public static final String KEY_HD_CHANNEL_AVAILABLE= "hdChannelAvailable"; + public static final String KEY_RDS_DATA_AVAILABLE= "rdsDataAvailable"; + public static final String KEY_AVAILABLE_HDS_AVAILABLE= "availableHDsAvailable"; + public static final String KEY_STATE_AVAILABLE= "stateAvailable"; + public static final String KEY_SIGNAL_STRENGTH_AVAILABLE= "signalStrengthAvailable"; + public static final String KEY_SIGNAL_CHANGE_THRESHOLD_AVAILABLE= "signalChangeThresholdAvailable"; + + public RadioControlCapabilities() { + } + + public RadioControlCapabilities(Hashtable<String, Object> hash) { + super(hash); + } + + /** + * Sets the moduleName portion of the RadioControlCapabilities class + * + * @param moduleName + * The short friendly name of the climate control module. + * It should not be used to identify a module by mobile application. + */ + public void setModuleName(String moduleName) { + setValue(KEY_MODULE_NAME, moduleName); + } + + /** + * Gets the moduleName portion of the RadioControlCapabilities class + * + * @return String - Short friendly name of the climate control module. + */ + public String getModuleName() { + return getString(KEY_MODULE_NAME); + } + + /** + * Sets the radioEnableAvailable portion of the RadioControlCapabilities class + * + * @param radioEnableAvailable + * Availability of the control of enable/disable radio. + * True: Available, False: Not Available, Not present: Not Available. + */ + public void setRadioEnableAvailable(Boolean radioEnableAvailable) { + setValue(KEY_RADIO_ENABLE_AVAILABLE, radioEnableAvailable); + } + + /** + * Gets the radioEnableAvailable portion of the RadioControlCapabilities class + * + * @return Boolean - Availability of the control of enable/disable radio. + * True: Available, False: Not Available, Not present: Not Available. + */ + public Boolean getRadioEnableAvailable() { + return getBoolean(KEY_RADIO_ENABLE_AVAILABLE); + } + + /** + * Sets the radioBandAvailable portion of the RadioControlCapabilities class + * + * @param radioBandAvailable + * Availability of the control of radio band. + * True: Available, False: Not Available, Not present: Not Available. + */ + public void setRadioBandAvailable(Boolean radioBandAvailable) { + setValue(KEY_RADIO_BAND_AVAILABLE, radioBandAvailable); + } + + /** + * Gets the radioBandAvailable portion of the RadioControlCapabilities class + * + * @return Boolean - Availability of the control of radio band. + * True: Available, False: Not Available, Not present: Not Available. + */ + public Boolean getRadioBandAvailable() { + return getBoolean(KEY_RADIO_BAND_AVAILABLE); + } + + /** + * Sets the radioFrequencyAvailable portion of the RadioControlCapabilities class + * + * @param radioFrequencyAvailable + * Availability of the control of radio frequency. + * True: Available, False: Not Available, Not present: Not Available. + */ + public void setRadioFrequencyAvailable(Boolean radioFrequencyAvailable) { + setValue(KEY_RADIO_FREQUENCY_AVAILABLE, radioFrequencyAvailable); + } + + /** + * Gets the radioFrequencyAvailable portion of the RadioControlCapabilities class + * + * @return Boolean - Availability of the control of radio frequency. + * True: Available, False: Not Available, Not present: Not Available. + */ + public Boolean getRadioFrequencyAvailable() { + return getBoolean(KEY_RADIO_FREQUENCY_AVAILABLE); + } + + /** + * Sets the hdChannelAvailable portion of the RadioControlCapabilities class + * + * @param hdChannelAvailable + * Availability of the control of HD radio channel. + * True: Available, False: Not Available, Not present: Not Available. + */ + public void setHdChannelAvailable(Boolean hdChannelAvailable) { + setValue(KEY_HD_CHANNEL_AVAILABLE, hdChannelAvailable); + } + + /** + * Gets the hdChannelAvailable portion of the RadioControlCapabilities class + * + * @return Boolean - Availability of the control of HD radio channel. + * True: Available, False: Not Available, Not present: Not Available. + */ + public Boolean getHdChannelAvailable() { + return getBoolean(KEY_HD_CHANNEL_AVAILABLE); + } + + /** + * Sets the rdsDataAvailable portion of the RadioControlCapabilities class + * + * @param rdsDataAvailable + * Availability of the getting Radio Data System (RDS) data. + * True: Available, False: Not Available, Not present: Not Available. + */ + public void setRdsDataAvailable(Boolean rdsDataAvailable) { + setValue(KEY_RDS_DATA_AVAILABLE, rdsDataAvailable); + } + + /** + * Gets the rdsDataAvailable portion of the RadioControlCapabilities class + * + * @return Boolean - Availability of the getting Radio Data System (RDS) data. + * True: Available, False: Not Available, Not present: Not Available. + */ + public Boolean getRdsDataAvailable() { + return getBoolean(KEY_RDS_DATA_AVAILABLE); + } + + /** + * Sets the availableHDsAvailable portion of the RadioControlCapabilities class + * + * @param availableHDsAvailable + * Availability of the getting the number of available HD channels. + * True: Available, False: Not Available, Not present: Not Available. + */ + public void setAvailableHDsAvailable(Boolean availableHDsAvailable) { + setValue(KEY_AVAILABLE_HDS_AVAILABLE, availableHDsAvailable); + } + + /** + * Gets the availableHDsAvailable portion of the RadioControlCapabilities class + * + * @return Boolean - Availability of the getting the number of available HD channels. + * True: Available, False: Not Available, Not present: Not Available. + */ + public Boolean getAvailableHDsAvailable() { + return getBoolean(KEY_AVAILABLE_HDS_AVAILABLE); + } + + /** + * Sets the stateAvailable portion of the RadioControlCapabilities class + * + * @param stateAvailable + * Availability of the getting the Radio state. + * True: Available, False: Not Available, Not present: Not Available. + */ + public void setStateAvailable(Boolean stateAvailable) { + setValue(KEY_STATE_AVAILABLE, stateAvailable); + } + + /** + * Gets the stateAvailable portion of the RadioControlCapabilities class + * + * @return Boolean - Availability of the getting the Radio state. + * True: Available, False: Not Available, Not present: Not Available. + */ + public Boolean getStateAvailable() { + return getBoolean(KEY_STATE_AVAILABLE); + } + + /** + * Sets the signalStrengthAvailable portion of the RadioControlCapabilities class + * + * @param signalStrengthAvailable + * Availability of the getting the signal strength. + * True: Available, False: Not Available, Not present: Not Available. + */ + public void setSignalStrengthAvailable(Boolean signalStrengthAvailable) { + setValue(KEY_SIGNAL_STRENGTH_AVAILABLE, signalStrengthAvailable); + } + + /** + * Gets the signalStrengthAvailable portion of the RadioControlCapabilities class + * + * @return Boolean - Availability of the getting the signal strength. + * True: Available, False: Not Available, Not present: Not Available. + */ + public Boolean getSignalStrengthAvailable() { + return getBoolean(KEY_SIGNAL_STRENGTH_AVAILABLE); + } + + /** + * Sets the signalChangeThresholdAvailable portion of the RadioControlCapabilities class + * + * @param signalChangeThresholdAvailable + * Availability of the getting the signal Change Threshold. + * True: Available, False: Not Available, Not present: Not Available. + */ + public void setSignalChangeThresholdAvailable(Boolean signalChangeThresholdAvailable) { + setValue(KEY_SIGNAL_CHANGE_THRESHOLD_AVAILABLE, signalChangeThresholdAvailable); + } + + /** + * Gets the signalChangeThresholdAvailable portion of the RadioControlCapabilities class + * + * @return Boolean - Availability of the getting the signal Change Threshold. + * True: Available, False: Not Available, Not present: Not Available. + */ + public Boolean getSignalChangeThresholdAvailable() { + return getBoolean(KEY_SIGNAL_CHANGE_THRESHOLD_AVAILABLE); + } +} diff --git a/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/RadioControlData.java b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/RadioControlData.java new file mode 100644 index 000000000..90d8a9de0 --- /dev/null +++ b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/RadioControlData.java @@ -0,0 +1,220 @@ +package com.smartdevicelink.proxy.rpc; + +import com.smartdevicelink.proxy.RPCStruct; +import com.smartdevicelink.proxy.rpc.enums.RadioBand; +import com.smartdevicelink.proxy.rpc.enums.RadioState; +import java.util.Hashtable; + +/** + * Include information (both read-only and changeable data) about a + * remote control radio module. + */ +public class RadioControlData extends RPCStruct{ + public static final String KEY_FREQUENCY_INTEGER= "frequencyInteger"; + public static final String KEY_FREQUENCY_FRACTION= "frequencyFraction"; + public static final String KEY_BAND= "band"; + public static final String KEY_RDS_DATA= "rdsData"; + public static final String KEY_AVAILABLE_HDS= "availableHDs"; + public static final String KEY_HD_CHANNEL= "hdChannel"; + public static final String KEY_SIGNAL_STRENGTH= "signalStrength"; + public static final String KEY_SIGNAL_CHANGE_THRESHOLD= "signalChangeThreshold"; + public static final String KEY_RADIO_ENABLE= "radioEnable"; + public static final String KEY_STATE= "state"; + + public RadioControlData() { + } + + public RadioControlData(Hashtable<String, Object> hash) { + super(hash); + } + + /** + * Sets the frequencyInteger portion of the RadioControlData class + * + * @param frequencyInteger + * The integer part of the frequency i.e. for 101.7 this value should be 101 + */ + public void setFrequencyInteger(Integer frequencyInteger) { + setValue(KEY_FREQUENCY_INTEGER, frequencyInteger); + } + + /** + * Gets the frequencyInteger portion of the RadioControlData class + * + * @return Integer - The integer part of the frequency i.e. for 101.7 this value should be 101. + */ + public Integer getFrequencyInteger() { + return getInteger(KEY_FREQUENCY_INTEGER); + } + + /** + * Sets the frequencyFraction portion of the RadioControlData class + * + * @param frequencyFraction + * The fractional part of the frequency i.e. for 101.7 is 7. + */ + public void setFrequencyFraction(Integer frequencyFraction) { + setValue(KEY_FREQUENCY_FRACTION, frequencyFraction); + } + + /** + * Gets the frequencyFraction portion of the RadioControlData class + * + * @return Integer - The fractional part of the frequency i.e. for 101.7 is 7. + */ + public Integer getFrequencyFraction() { + return getInteger(KEY_FREQUENCY_FRACTION); + } + + /** + * Sets the band portion of the RadioControlData class + * + * @param band + * The radio band (AM|FM|XM) of the radio tuner. + */ + public void setBand(RadioBand band) { + setValue(KEY_BAND, band); + } + + /** + * Gets the band portion of the RadioControlData class + * + * @return RadioBand - The radio band (AM|FM|XM) of the radio tuner. + */ + public RadioBand getBand() { + return (RadioBand) getObject(RadioBand.class, KEY_BAND); + } + + /** + * Sets the rdsData portion of the RadioControlData class + * + * @param rdsData + * Read only parameter. See RdsData data type for details. + */ + public void setRdsData(RdsData rdsData) { + setValue(KEY_RDS_DATA, rdsData); + } + + /** + * Gets the rdsData portion of the RadioControlData class + * + * @return RdsData - Read only parameter. See RdsData data type for details. + */ + public RdsData getRdsData() { + return (RdsData) getObject(RdsData.class, KEY_RDS_DATA); + } + + /** + * Sets the availableHDs portion of the RadioControlData class + * + * @param availableHDs + * Number of HD sub-channels if available. + */ + public void setAvailableHDs(Integer availableHDs) { + setValue(KEY_AVAILABLE_HDS, availableHDs); + } + + /** + * Gets the availableHDs portion of the RadioControlData class + * + * @return Integer - Number of HD sub-channels if available. + */ + public Integer getAvailableHDs() { + return getInteger(KEY_AVAILABLE_HDS); + } + + /** + * Sets the hdChannel portion of the RadioControlData class + * + * @param hdChannel + * Current HD sub-channel if available. + */ + public void setHdChannel(Integer hdChannel) { + setValue(KEY_HD_CHANNEL, hdChannel); + } + + /** + * Gets the hdChannel portion of the RadioControlData class + * + * @return Integer - Current HD sub-channel if available. + */ + public Integer getHdChannel() { + return getInteger(KEY_HD_CHANNEL); + } + + /** + * Sets the signalStrength portion of the RadioControlData class + * + * @param signalStrength + * Read only parameter. Indicates the strength of receiving radio signal in current frequency. + */ + public void setSignalStrength(Integer signalStrength) { + setValue(KEY_SIGNAL_STRENGTH, signalStrength); + } + + /** + * Gets the signalStrength portion of the RadioControlData class + * + * @return Integer - Read only parameter. Indicates the strength of receiving radio signal in current frequency. + */ + public Integer getSignalStrength() { + return getInteger(KEY_SIGNAL_STRENGTH); + } + + /** + * Sets the signalChangeThreshold portion of the RadioControlData class + * + * @param signalChangeThreshold + * If the signal strength falls below the set value for this parameter, the radio will tune to an alternative frequency. + */ + public void setSignalChangeThreshold(Integer signalChangeThreshold) { + setValue(KEY_SIGNAL_CHANGE_THRESHOLD, signalChangeThreshold); + } + + /** + * Gets the signalChangeThreshold portion of the RadioControlData class + * + * @return Integer - If the signal strength falls below the set value for this parameter, the radio will tune to an alternative frequency. + */ + public Integer getSignalChangeThreshold() { + return getInteger(KEY_SIGNAL_CHANGE_THRESHOLD); + } + + /** + * Sets the radioEnable portion of the RadioControlData class + * + * @param radioEnable + * True if the radio is on, false is the radio is off. + */ + public void setRadioEnable(Boolean radioEnable) { + setValue(KEY_RADIO_ENABLE, radioEnable); + } + + /** + * Gets the radioEnable portion of the RadioControlData class + * + * @return Boolean - True if the radio is on, false is the radio is off. + */ + public Boolean getRadioEnable() { + return getBoolean(KEY_RADIO_ENABLE); + } + + /** + * Sets the state portion of the RadioControlData class + * + * @param state + * Read only parameter. See RadioState data type for details. + */ + public void setState(RadioState state) { + setValue(KEY_STATE, state); + } + + /** + * Gets the state portion of the RadioControlData class + * + * @return RadioState - Read only parameter. See RadioState data type for details. + */ + public RadioState getState() { + return (RadioState) getObject(RadioState.class, KEY_STATE); + } +} diff --git a/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/RdsData.java b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/RdsData.java new file mode 100644 index 000000000..2ed934865 --- /dev/null +++ b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/RdsData.java @@ -0,0 +1,180 @@ +package com.smartdevicelink.proxy.rpc; + +import com.smartdevicelink.proxy.RPCStruct; + +import java.util.Hashtable; + +/** + * Include the data defined in Radio Data System, which is a communications protocol standard + * for embedding small amounts of digital information in conventional FM radio broadcasts. + */ +public class RdsData extends RPCStruct{ + public static final String KEY_PS= "PS"; + public static final String KEY_RT= "RT"; + public static final String KEY_CT= "CT"; + public static final String KEY_PI= "PI"; + public static final String KEY_PTY= "PTY"; + public static final String KEY_TP= "TP"; + public static final String KEY_TA= "TA"; + public static final String KEY_REG= "REG"; + + public RdsData() { + } + + public RdsData(Hashtable<String, Object> hash) { + super(hash); + } + + /** + * Sets the programService portion of the RdsData class + * + * @param programService + * Program Service Name. + */ + public void setProgramService(String programService) { + setValue(KEY_PS, programService); + } + + /** + * Gets the programService portion of the RdsData class + * + * @return String - Program Service Name. + */ + public String getProgramService() { + return getString(KEY_PS); + } + + /** + * Sets the radioText portion of the RdsData class + * + * @param radioText + * Radio Text. + */ + public void setRadioText(String radioText) { + setValue(KEY_RT, radioText); + } + + /** + * Gets the radioText portion of the RdsData class + * + * @return String - Radio Text. + */ + public String getRadioText() { + return getString(KEY_RT); + } + + /** + * Sets the clockText portion of the RdsData class + * + * @param clockText + * The clock text in UTC format as YYYY-MM-DDThh:mm:ss.sTZD. + */ + public void setClockText(String clockText) { + setValue(KEY_CT, clockText); + } + + /** + * Gets the clockText portion of the RdsData class + * + * @return String - The clock text in UTC format as YYYY-MM-DDThh:mm:ss.sTZD. + */ + public String getClockText() { + return getString(KEY_CT); + } + + /** + * Sets the programIdentification portion of the RdsData class + * + * @param programIdentification + * Program Identification - the call sign for the radio station. + */ + public void setProgramIdentification(String programIdentification) { + setValue(KEY_PI, programIdentification); + } + + /** + * Gets the programIdentification portion of the RdsData class + * + * @return String - Program Identification - the call sign for the radio station. + */ + public String getProgramIdentification() { + return getString(KEY_PI); + } + + /** + * Sets the region portion of the RdsData class + * + * @param region + * Region. + */ + public void setRegion(String region) { + setValue(KEY_REG, region); + } + + /** + * Gets the region portion of the RdsData class + * + * @return String - Region. + */ + public String getRegion() { + return getString(KEY_REG); + } + + /** + * Sets the trafficProgram portion of the RdsData class + * + * @param trafficProgram + * Traffic Program Identification - Identifies a station that offers traffic. + */ + public void setTrafficProgram(Boolean trafficProgram) { + setValue(KEY_TP, trafficProgram); + } + + /** + * Gets the trafficProgram portion of the RdsData class + * + * @return Boolean - Traffic Program Identification - Identifies a station that offers traffic. + */ + public Boolean getTrafficProgram() { + return getBoolean(KEY_TP); + } + + /** + * Sets the trafficAnnouncement portion of the RdsData class + * + * @param trafficAnnouncement + * Traffic Announcement Identification - Indicates an ongoing traffic announcement. + */ + public void setTrafficAnnouncement(Boolean trafficAnnouncement) { + setValue(KEY_TA, trafficAnnouncement); + } + + /** + * Gets the trafficAnnouncement portion of the RdsData class + * + * @return Boolean - Traffic Announcement Identification - Indicates an ongoing traffic announcement. + */ + public Boolean getTrafficAnnouncement() { + return getBoolean(KEY_TA); + } + + /** + * Sets the programType portion of the RdsData class + * + * @param programType + * The program type - The region should be used to differentiate between EU and North America program types. + */ + public void setProgramType(Integer programType) { + setValue(KEY_PTY, programType); + } + + /** + * Gets the programType portion of the RdsData class + * + * @return Integer - The program type. + * The region should be used to differentiate between EU and North America program types. + */ + public Integer getProgramType() { + return getInteger(KEY_PTY); + } +} diff --git a/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/RemoteControlCapabilities.java b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/RemoteControlCapabilities.java new file mode 100644 index 000000000..ec51aa633 --- /dev/null +++ b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/RemoteControlCapabilities.java @@ -0,0 +1,82 @@ +package com.smartdevicelink.proxy.rpc; + +import com.smartdevicelink.proxy.RPCStruct; +import java.util.Hashtable; +import java.util.List; + +public class RemoteControlCapabilities extends RPCStruct{ + public static final String KEY_CLIMATE_CONTROL_CAPABILITIES= "climateControlCapabilities"; + public static final String KEY_RADIO_CONTROL_CAPABILITIES = "radioControlCapabilities"; + public static final String KEY_BUTTON_CAPABILITIES = "buttonCapabilities"; + + public RemoteControlCapabilities() { + } + + public RemoteControlCapabilities(Hashtable<String, Object> hash) { + super(hash); + } + + /** + * Sets the climateControlCapabilities portion of the RemoteControlCapabilities class + * + * @param climateControlCapabilities + * If included, the platform supports RC climate controls. + * For this baseline version, maxsize=1. i.e. only one climate control module is supported. + */ + public void setClimateControlCapabilities(List<ClimateControlCapabilities> climateControlCapabilities) { + setValue(KEY_CLIMATE_CONTROL_CAPABILITIES, climateControlCapabilities); + } + + /** + * Gets the climateControlCapabilities portion of the RemoteControlCapabilities class + * + * @return List<ClimateControlCapabilities> + * If included, the platform supports RC climate controls. + * For this baseline version, maxsize=1. i.e. only one climate control module is supported. + */ + public List<ClimateControlCapabilities> getClimateControlCapabilities() { + return (List<ClimateControlCapabilities>) getObject(ClimateControlCapabilities.class, KEY_CLIMATE_CONTROL_CAPABILITIES); + } + + /** + * Sets the radioControlCapabilities portion of the RemoteControlCapabilities class + * + * @param radioControlCapabilities + * If included, the platform supports RC climate controls. + * For this baseline version, maxsize=1. i.e. only one radio control module is supported. + */ + public void setRadioControlCapabilities(List<RadioControlCapabilities> radioControlCapabilities) { + setValue(KEY_RADIO_CONTROL_CAPABILITIES, radioControlCapabilities); + } + + /** + * Gets the radioControlCapabilities portion of the RemoteControlCapabilities class + * + * @return List<RadioControlCapabilities> + * If included, the platform supports RC climate controls. + * For this baseline version, maxsize=1. i.e. only one radio control module is supported. + */ + public List<RadioControlCapabilities> getRadioControlCapabilities() { + return (List<RadioControlCapabilities>) getObject(RadioControlCapabilities.class, KEY_RADIO_CONTROL_CAPABILITIES); + } + + /** + * Sets the buttonCapabilities portion of the RemoteControlCapabilities class + * + * @param buttonCapabilities + * If included, the platform supports RC button controls with the included button names. + */ + public void setButtonCapabilities(List<ButtonCapabilities> buttonCapabilities) { + setValue(KEY_BUTTON_CAPABILITIES, buttonCapabilities); + } + + /** + * Gets the buttonCapabilities portion of the RemoteControlCapabilities class + * + * @return List<ButtonCapabilities> + * If included, the platform supports RC button controls with the included button names. + */ + public List<ButtonCapabilities> getButtonCapabilities() { + return (List<ButtonCapabilities>) getObject(ButtonCapabilities.class, KEY_BUTTON_CAPABILITIES); + } +} diff --git a/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/SetInteriorVehicleData.java b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/SetInteriorVehicleData.java new file mode 100644 index 000000000..75077e3cb --- /dev/null +++ b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/SetInteriorVehicleData.java @@ -0,0 +1,51 @@ +package com.smartdevicelink.proxy.rpc; + +import com.smartdevicelink.protocol.enums.FunctionID; +import com.smartdevicelink.proxy.RPCRequest; + +import java.util.Hashtable; + +/** + * This function allows a remote control type mobile application change the settings + * of a specific remote control module. + */ +public class SetInteriorVehicleData extends RPCRequest { + public static final String KEY_MODULE_DATA = "moduleData"; + + /** + * Constructs a new SetInteriorVehicleData object + */ + public SetInteriorVehicleData() { + super(FunctionID.SET_INTERIOR_VEHICLE_DATA.toString()); + } + + /** + * <p>Constructs a new SetInteriorVehicleData object indicated by the + * Hashtable parameter</p> + * + * + * @param hash + * The Hashtable to use + */ + public SetInteriorVehicleData(Hashtable<String, Object> hash) { + super(hash); + } + + /** + * Sets the moduleData + * + * @param moduleData + */ + public void setModuleData(ModuleData moduleData) { + setParameters(KEY_MODULE_DATA, moduleData); + } + + /** + * Gets the moduleData + * + * @return ModuleData + */ + public ModuleData getModuleData() { + return (ModuleData) getObject(ModuleData.class, KEY_MODULE_DATA); + } +} diff --git a/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/SetInteriorVehicleDataResponse.java b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/SetInteriorVehicleDataResponse.java new file mode 100644 index 000000000..6a7079735 --- /dev/null +++ b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/SetInteriorVehicleDataResponse.java @@ -0,0 +1,47 @@ +package com.smartdevicelink.proxy.rpc; + +import com.smartdevicelink.protocol.enums.FunctionID; +import com.smartdevicelink.proxy.RPCResponse; + +import java.util.Hashtable; + +public class SetInteriorVehicleDataResponse extends RPCResponse { + public static final String KEY_MODULE_DATA = "moduleData"; + + /** + * Constructs a new SetInteriorVehicleDataResponse object + */ + public SetInteriorVehicleDataResponse() { + super(FunctionID.SET_INTERIOR_VEHICLE_DATA.toString()); + } + + /** + * <p>Constructs a new SetInteriorVehicleDataResponse object indicated by the + * Hashtable parameter</p> + * + * + * @param hash + * The Hashtable to use + */ + public SetInteriorVehicleDataResponse(Hashtable<String, Object> hash) { + super(hash); + } + + /** + * Gets the moduleData + * + * @return ModuleData + */ + public ModuleData getModuleData() { + return (ModuleData) getObject(ModuleData.class, KEY_MODULE_DATA); + } + + /** + * Sets the moduleData + * + * @param moduleData + */ + public void setModuleData(ModuleData moduleData) { + setParameters(KEY_MODULE_DATA, moduleData); + } +} diff --git a/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/SystemCapability.java b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/SystemCapability.java index c7ea47ce6..386f28b45 100644 --- a/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/SystemCapability.java +++ b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/SystemCapability.java @@ -14,6 +14,7 @@ public class SystemCapability extends RPCStruct { public static final String KEY_NAVIGATION_CAPABILITY = "navigationCapability"; public static final String KEY_PHONE_CAPABILITY = "phoneCapability"; public static final String KEY_VIDEO_STREAMING_CAPABILITY = "videoStreamingCapability"; + public static final String KEY_REMOTE_CONTROL_CAPABILITY = "remoteControlCapability"; public SystemCapability(){} @@ -43,6 +44,8 @@ public class SystemCapability extends RPCStruct { return (RPCStruct) getObject(PhoneCapability.class, KEY_PHONE_CAPABILITY); } else if (type.equals(SystemCapabilityType.VIDEO_STREAMING)){ return (RPCStruct) getObject(VideoStreamingCapability.class, KEY_VIDEO_STREAMING_CAPABILITY); + }else if(type.equals(SystemCapabilityType.REMOTE_CONTROL)){ + return (RPCStruct) getObject(RemoteControlCapabilities.class, KEY_REMOTE_CONTROL_CAPABILITY); }else{ return null; } @@ -55,6 +58,8 @@ public class SystemCapability extends RPCStruct { setValue(KEY_PHONE_CAPABILITY, capability); }else if(type.equals(SystemCapabilityType.VIDEO_STREAMING)){ setValue(KEY_VIDEO_STREAMING_CAPABILITY, capability); + }else if(type.equals(SystemCapabilityType.REMOTE_CONTROL)){ + setValue(KEY_REMOTE_CONTROL_CAPABILITY, capability); }else{ return; } diff --git a/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/Temperature.java b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/Temperature.java new file mode 100644 index 000000000..29fea734f --- /dev/null +++ b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/Temperature.java @@ -0,0 +1,56 @@ +package com.smartdevicelink.proxy.rpc; + +import com.smartdevicelink.proxy.RPCStruct; +import com.smartdevicelink.proxy.rpc.enums.TemperatureUnit; +import com.smartdevicelink.util.SdlDataTypeConverter; + +import java.util.Hashtable; + +public class Temperature extends RPCStruct{ + public static final String KEY_UNIT = "unit"; + public static final String KEY_VALUE = "value"; + + public Temperature() { } + public Temperature(Hashtable<String, Object> hash) { + super(hash); + } + + /** + * Sets the unit portion of the Temperature class + * + * @param unit + * Temperature Unit. + */ + public void setUnit(TemperatureUnit unit) { + setValue(KEY_UNIT, unit); + } + + /** + * Gets the unit portion of the Temperature class + * + * @return TemperatureUnit - Temperature Unit. + */ + public TemperatureUnit getUnit() { + return (TemperatureUnit) getObject(TemperatureUnit.class, KEY_UNIT); + } + + /** + * Gets the value portion of the Temperature class + * + * @return Float - Temperature Value in TemperatureUnit specified unit. Range depends on OEM and is not checked by SDL. + */ + public Float getValue() { + Object value = getValue(KEY_VALUE); + return SdlDataTypeConverter.objectToFloat(value); + } + + /** + * Sets the value portion of the Temperature class + * + * @param value + * Temperature Value in TemperatureUnit specified unit. Range depends on OEM and is not checked by SDL. + */ + public void setValue(Float value) { + setValue(KEY_VALUE, value); + } +} diff --git a/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/VideoStreamingFormat.java b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/VideoStreamingFormat.java index 274c076c5..8f88b3ea8 100644 --- a/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/VideoStreamingFormat.java +++ b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/VideoStreamingFormat.java @@ -17,6 +17,11 @@ public class VideoStreamingFormat extends RPCStruct { public VideoStreamingFormat(){} public VideoStreamingFormat(Hashtable<String, Object> hash){super(hash);} + public VideoStreamingFormat(VideoStreamingCodec codec,VideoStreamingProtocol protocol){ + setCodec(codec); + setProtocol(protocol); + } + public void setProtocol(VideoStreamingProtocol protocol){ setValue(KEY_PROTOCOL, protocol); } @@ -32,4 +37,10 @@ public class VideoStreamingFormat extends RPCStruct { public VideoStreamingCodec getCodec(){ return (VideoStreamingCodec) getObject(VideoStreamingCodec.class, KEY_CODEC); } + + @Override + public String toString() { + return "codec=" + String.valueOf(getCodec()) + + ", protocol=" + String.valueOf(getProtocol()); + } } diff --git a/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/enums/AppHMIType.java b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/enums/AppHMIType.java index 2a12bec1e..0a4f56255 100644 --- a/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/enums/AppHMIType.java +++ b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/enums/AppHMIType.java @@ -45,7 +45,12 @@ public enum AppHMIType { /**
* System App
*/
- SYSTEM;
+ SYSTEM,
+ /**
+ * Remote Control
+ */
+ REMOTE_CONTROL,
+ ;
/**
* Convert String to AppHMIType
diff --git a/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/enums/ButtonName.java b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/enums/ButtonName.java index 1391a9d44..f478a78ee 100644 --- a/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/enums/ButtonName.java +++ b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/enums/ButtonName.java @@ -115,7 +115,28 @@ public enum ButtonName{ *
* @since SmartDeviceLink 1.0
*/
- PRESET_9, CUSTOM_BUTTON, SEARCH;
+ PRESET_9,
+ CUSTOM_BUTTON,
+ SEARCH,
+ AC_MAX,
+ AC,
+ RECIRCULATE,
+ FAN_UP,
+ FAN_DOWN,
+ TEMP_UP,
+ TEMP_DOWN,
+ DEFROST_MAX,
+ DEFROST,
+ DEFROST_REAR,
+ UPPER_VENT,
+ LOWER_VENT,
+ VOLUME_UP,
+ VOLUME_DOWN,
+ EJECT,
+ SOURCE,
+ SHUFFLE,
+ REPEAT,
+ ;
public static ButtonName valueForString(String value) {
try{
diff --git a/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/enums/DefrostZone.java b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/enums/DefrostZone.java new file mode 100644 index 000000000..4c6b15e85 --- /dev/null +++ b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/enums/DefrostZone.java @@ -0,0 +1,17 @@ +package com.smartdevicelink.proxy.rpc.enums; + +public enum DefrostZone { + FRONT, + REAR, + ALL, + NONE, + ; + + public static DefrostZone valueForString(String value) { + try{ + return valueOf(value); + }catch(Exception e){ + return null; + } + } +} diff --git a/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/enums/ModuleType.java b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/enums/ModuleType.java new file mode 100644 index 000000000..faef92d36 --- /dev/null +++ b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/enums/ModuleType.java @@ -0,0 +1,15 @@ +package com.smartdevicelink.proxy.rpc.enums; + +public enum ModuleType { + CLIMATE, + RADIO, + ; + + public static ModuleType valueForString(String value) { + try{ + return valueOf(value); + }catch(Exception e){ + return null; + } + } +} diff --git a/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/enums/RadioBand.java b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/enums/RadioBand.java new file mode 100644 index 000000000..2b2c862d8 --- /dev/null +++ b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/enums/RadioBand.java @@ -0,0 +1,16 @@ +package com.smartdevicelink.proxy.rpc.enums; + +public enum RadioBand { + AM, + FM, + XM, + ; + + public static RadioBand valueForString(String value) { + try{ + return valueOf(value); + }catch(Exception e){ + return null; + } + } +} diff --git a/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/enums/RadioState.java b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/enums/RadioState.java new file mode 100644 index 000000000..533c86dca --- /dev/null +++ b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/enums/RadioState.java @@ -0,0 +1,20 @@ +package com.smartdevicelink.proxy.rpc.enums; + +/** + * List possible states of a remote control radio module. + */ +public enum RadioState { + ACQUIRING, + ACQUIRED, + MULTICAST, + NOT_FOUND, + ; + + public static RadioState valueForString(String value) { + try{ + return valueOf(value); + }catch(Exception e){ + return null; + } + } +} diff --git a/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/enums/Result.java b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/enums/Result.java index 870e4115e..c0a15f235 100644 --- a/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/enums/Result.java +++ b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/enums/Result.java @@ -168,7 +168,16 @@ public enum Result { /**
* The provided hash ID does not match the hash of the current set of registered data or the core could not resume the previous data.
*/
- RESUME_FAILED;
+ RESUME_FAILED,
+ /**
+ * The requested data is not available on this vehicle or is not published for the connected app.
+ */
+ DATA_NOT_AVAILABLE,
+ /**
+ * The requested data is read only thus cannot be change via remote control
+ */
+ READ_ONLY,
+ ;
/**
* Convert String to Result
* @param value String
diff --git a/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/enums/TemperatureUnit.java b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/enums/TemperatureUnit.java new file mode 100644 index 000000000..6c9b04875 --- /dev/null +++ b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/enums/TemperatureUnit.java @@ -0,0 +1,14 @@ +package com.smartdevicelink.proxy.rpc.enums; + +public enum TemperatureUnit { + CELSIUS, + FAHRENHEIT; + + public static TemperatureUnit valueForString(String value) { + try{ + return valueOf(value); + }catch(Exception e){ + return null; + } + } +} diff --git a/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/enums/VentilationMode.java b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/enums/VentilationMode.java new file mode 100644 index 000000000..b7a2ae9a2 --- /dev/null +++ b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/enums/VentilationMode.java @@ -0,0 +1,17 @@ +package com.smartdevicelink.proxy.rpc.enums; + +public enum VentilationMode { + UPPER, + LOWER, + BOTH, + NONE, + ; + + public static VentilationMode valueForString(String value) { + try{ + return valueOf(value); + }catch(Exception e){ + return null; + } + } +} diff --git a/sdl_android/src/main/java/com/smartdevicelink/streaming/AudioStreamingCodec.java b/sdl_android/src/main/java/com/smartdevicelink/streaming/AudioStreamingCodec.java new file mode 100644 index 000000000..8e8cb3857 --- /dev/null +++ b/sdl_android/src/main/java/com/smartdevicelink/streaming/AudioStreamingCodec.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2017, Xevo Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.smartdevicelink.streaming; + +/** + * Enum for each type of audio streaming codec. + */ +public enum AudioStreamingCodec { + /** + * Linear-PCM without any compression. + */ + LPCM; + + public static AudioStreamingCodec valueForString(String value) { + try { + return valueOf(value); + } catch (Exception e) { + return null; + } + } +} diff --git a/sdl_android/src/main/java/com/smartdevicelink/streaming/AudioStreamingLPCMParams.java b/sdl_android/src/main/java/com/smartdevicelink/streaming/AudioStreamingLPCMParams.java new file mode 100644 index 000000000..551a1f032 --- /dev/null +++ b/sdl_android/src/main/java/com/smartdevicelink/streaming/AudioStreamingLPCMParams.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2017, Xevo Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.smartdevicelink.streaming; + +/** + * A struct to hold LPCM specific audio format information. + */ +public class AudioStreamingLPCMParams extends AudioStreamingParams { + /** + * Sample format of linear PCM data. + */ + public enum SampleFormat { + /** + * LPCM data is represented by 8-bit unsigned integers. Centerpoint is 128. + */ + LPCM_8BIT_UNSIGNED, + + /** + * LPCM data is represented by 16-bit signed integers, in little endian. + */ + LPCM_16BIT_SIGNED_LITTLE_ENDIAN, + } + + /** + * Sample format in which app will provide LPCM data to + * IAudioStreamListener.sendAudio() + * <p> + * This is reserved for future and not used right now. + */ + public SampleFormat sampleFormat; + + public AudioStreamingLPCMParams(SampleFormat sampleFormat, int samplingRate, int channels) { + super(samplingRate, channels); + this.sampleFormat = sampleFormat; + } +} diff --git a/sdl_android/src/main/java/com/smartdevicelink/streaming/AudioStreamingParams.java b/sdl_android/src/main/java/com/smartdevicelink/streaming/AudioStreamingParams.java new file mode 100644 index 000000000..cd95ed95a --- /dev/null +++ b/sdl_android/src/main/java/com/smartdevicelink/streaming/AudioStreamingParams.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2017, Xevo Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.smartdevicelink.streaming; + +/** + * A struct to hold audio format information that are common to codecs. + */ +public class AudioStreamingParams { + /** + * Sampling rate in Hz, e.g. 44100 + * <p> + * This is reserved for future and not used right now. + */ + public int samplingRate; + + /** + * Number of channels in the audio stream + * <p> + * This is reserved for future and not used right now. + */ + public int channels; + + public AudioStreamingParams(int samplingRate, int channels) { + this.samplingRate = samplingRate; + this.channels = channels; + } +} diff --git a/sdl_android/src/main/java/com/smartdevicelink/streaming/RTPH264Packetizer.java b/sdl_android/src/main/java/com/smartdevicelink/streaming/RTPH264Packetizer.java new file mode 100644 index 000000000..2a7646579 --- /dev/null +++ b/sdl_android/src/main/java/com/smartdevicelink/streaming/RTPH264Packetizer.java @@ -0,0 +1,505 @@ +/* + * Copyright (c) 2017, Xevo Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.smartdevicelink.streaming; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.Random; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; + +import com.smartdevicelink.SdlConnection.SdlConnection; +import com.smartdevicelink.SdlConnection.SdlSession; +import com.smartdevicelink.protocol.ProtocolMessage; +import com.smartdevicelink.protocol.enums.SessionType; +import com.smartdevicelink.proxy.interfaces.IVideoStreamListener; +import com.smartdevicelink.proxy.rpc.enums.VideoStreamingCodec; +import com.smartdevicelink.proxy.rpc.enums.VideoStreamingProtocol; + +/* + * Note for testing. + * The RTP stream generated by this packetizer can be tested with GStreamer (1.4 or later). + * Assuming that "VideoStreamPort" is configured as 5050 in smartDeviceLink.ini, here is the + * GStreamer pipeline that receives the stream, decode it and render it: + * + * $ gst-launch-1.0 souphttpsrc location=http://127.0.0.1:5050 ! "application/x-rtp-stream" ! rtpstreamdepay ! "application/x-rtp,media=(string)video,clock-rate=90000,encoding-name=(string)H264" ! rtph264depay ! "video/x-h264, stream-format=(string)avc, alignment=(string)au" ! avdec_h264 ! autovideosink sync=false + */ + +/** + * This class receives H.264 byte stream (in Annex-B format), parses it, construct RTP packets + * from it based on RFC 6184, then frame the packets based on RFC 4571. + * The primary purpose of using RTP is to carry timestamp information along with the data. + * + * @author Sho Amano + */ +public class RTPH264Packetizer extends AbstractPacketizer implements IVideoStreamListener, Runnable { + + // Approximate size of data that mOutputQueue can hold in bytes. + // By adding a buffer, we accept underlying transport being stuck for a short time. By setting + // a limit of the buffer size, we avoid buffer overflows when underlying transport is too slow. + private static final int MAX_QUEUE_SIZE = 256 * 1024; + + private static final int FRAME_LENGTH_LEN = 2; + private static final int MAX_RTP_PACKET_SIZE = 65535; // because length field is two bytes (RFC 4571) + private static final int RTP_HEADER_LEN = 12; + private static final byte DEFAULT_RTP_PAYLOAD_TYPE = 96; + private static final int FU_INDICATOR_LEN = 1; + private static final int FU_HEADER_LEN = 1; + private static final byte TYPE_FU_A = 28; + + // To align with StreamPacketizer class + private final static int TLS_MAX_RECORD_SIZE = 16384; + private final static int TLS_RECORD_HEADER_SIZE = 5; + private final static int TLS_RECORD_MES_AUTH_CDE_SIZE = 32; + private final static int TLS_MAX_RECORD_PADDING_SIZE = 256; + + private final static int MAX_DATA_SIZE_FOR_ENCRYPTED_SERVICE = + TLS_MAX_RECORD_SIZE - TLS_RECORD_HEADER_SIZE - TLS_RECORD_MES_AUTH_CDE_SIZE- TLS_MAX_RECORD_PADDING_SIZE; + + private boolean mServiceProtected; + private Thread mThread; + private BlockingQueue<ByteBuffer> mOutputQueue; + private volatile boolean mPaused; + private boolean mWaitForIDR; + private NALUnitReader mNALUnitReader; + private byte mPayloadType = 0; + private int mSSRC = 0; + private char mSequenceNum = 0; + private int mInitialPTS = 0; + + /** + * Constructor + * + * @param streamListener The listener which this packetizer outputs SDL frames to + * @param serviceType The value of "Service Type" field in SDL frames + * @param sessionID The value of "Session ID" field in SDL frames + * @param session The SdlSession instance that this packetizer belongs to + */ + public RTPH264Packetizer(IStreamListener streamListener, + SessionType serviceType, byte sessionID, SdlSession session) throws IOException { + + super(streamListener, null, serviceType, sessionID, session); + + mServiceProtected = session.isServiceProtected(_serviceType); + + bufferSize = (int)this._session.getMtu(SessionType.NAV); + if (bufferSize == 0) { + // fail safe + bufferSize = MAX_DATA_SIZE_FOR_ENCRYPTED_SERVICE; + } + if (mServiceProtected && bufferSize > MAX_DATA_SIZE_FOR_ENCRYPTED_SERVICE) { + bufferSize = MAX_DATA_SIZE_FOR_ENCRYPTED_SERVICE; + } + + mOutputQueue = new LinkedBlockingQueue<ByteBuffer>(MAX_QUEUE_SIZE / bufferSize); + mNALUnitReader = new NALUnitReader(); + mPayloadType = DEFAULT_RTP_PAYLOAD_TYPE; + + Random r = new Random(); + mSSRC = r.nextInt(); + + // initial value of the sequence number and timestamp should be random ([5.1] in RFC3550) + mSequenceNum = (char)r.nextInt(65536); + mInitialPTS = r.nextInt(); + } + + /** + * Sets the Payload Type (PT) of RTP header field. + * + * Use this method if PT needs to be specified. The value should be between 0 and 127. + * Otherwise, a default value (96) is used. + * + * @param type A value indicating the Payload Type + */ + public void setPayloadType(byte type) { + if (type >= 0 && type <= 127) { + mPayloadType = type; + } else { + mPayloadType = DEFAULT_RTP_PAYLOAD_TYPE; + } + } + + /** + * Sets the SSRC of RTP header field. + * + * Use this method if SSRC needs to be specified. Otherwise, a random value is generated and + * used. + * + * @param ssrc An integer value representing SSRC + */ + public void setSSRC(int ssrc) { + mSSRC = ssrc; + } + + /** + * Starts this packetizer. + * + * It is recommended that the video encoder is started after the packetizer is started. + */ + @Override + public void start() throws IOException { + if (mThread != null) { + return; + } + + mThread = new Thread(this); + mThread.start(); + } + + /** + * Stops this packetizer. + * + * It is recommended that the video encoder is stopped prior to the packetizer. + */ + @Override + public void stop() { + if (mThread == null) { + return; + } + + mThread.interrupt(); + mThread = null; + + mPaused = false; + mWaitForIDR = false; + mOutputQueue.clear(); + } + + /** + * Pauses this packetizer. + * + * This pauses the packetizer but does not pause the video encoder. + */ + @Override + public void pause() { + mPaused = true; + } + + /** + * Resumes this packetizer. + */ + @Override + public void resume() { + mWaitForIDR = true; + mPaused = false; + } + + /** + * The thread routine. + */ + public void run() { + SdlConnection connection = _session.getSdlConnection(); + + while (mThread != null && !mThread.isInterrupted()) { + ByteBuffer frame; + try { + frame = mOutputQueue.take(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + break; + } + + while (frame.hasRemaining()) { + int len = frame.remaining() > bufferSize ? bufferSize : frame.remaining(); + + ProtocolMessage pm = new ProtocolMessage(); + pm.setSessionID(_rpcSessionID); + pm.setSessionType(_serviceType); + pm.setFunctionID(0); + pm.setCorrID(0); + pm.setData(frame.array(), frame.arrayOffset() + frame.position(), len); + pm.setPayloadProtected(mServiceProtected); + + _streamListener.sendStreamPacket(pm); + + frame.position(frame.position() + len); + } + } + + // XXX: This is added to sync with StreamPacketizer. Actually it shouldn't be here since + // it's confusing that a packetizer takes care of End Service request. + if (connection != null) { + connection.endService(_serviceType, _rpcSessionID); + } + } + + /** + * Called by the app and encoder. + * + * @see com.smartdevicelink.proxy.interfaces.IVideoStreamListener#sendFrame(byte[], int, int, long) + */ + @Override + public void sendFrame(byte[] data, int offset, int length, long presentationTimeUs) + throws ArrayIndexOutOfBoundsException { + mNALUnitReader.init(data, offset, length); + onEncoderOutput(mNALUnitReader, presentationTimeUs); + } + + /** + * Called by the app and encoder. + * + * @see com.smartdevicelink.proxy.interfaces.IVideoStreamListener#sendFrame(ByteBuffer, long) + */ + @Override + public void sendFrame(ByteBuffer data, long presentationTimeUs) { + mNALUnitReader.init(data); + onEncoderOutput(mNALUnitReader, presentationTimeUs); + } + + private void onEncoderOutput(NALUnitReader nalUnitReader, long ptsInUs) { + if (mPaused) { + return; + } + + ByteBuffer nalUnit; + + while ((nalUnit = nalUnitReader.getNalUnit()) != null) { + if (mWaitForIDR) { + if (isIDR(nalUnit)) { + mWaitForIDR = false; + } else { + continue; + } + } + outputRTPFrames(nalUnit, ptsInUs, nalUnitReader.hasConsumedAll()); + } + } + + private boolean outputRTPFrames(ByteBuffer nalUnit, long ptsInUs, boolean isLast) { + if (RTP_HEADER_LEN + nalUnit.remaining() > MAX_RTP_PACKET_SIZE) { + // Split into multiple Fragmentation Units ([5.8] in RFC 6184) + byte firstByte = nalUnit.get(); + boolean firstFragment = true; + boolean lastFragment = false; + + while (nalUnit.remaining() > 0) { + int payloadLength = MAX_RTP_PACKET_SIZE - (RTP_HEADER_LEN + FU_INDICATOR_LEN + FU_HEADER_LEN); + if (nalUnit.remaining() <= payloadLength) { + payloadLength = nalUnit.remaining(); + lastFragment = true; + } + + ByteBuffer frame = allocateRTPFrame(FU_INDICATOR_LEN + FU_HEADER_LEN + payloadLength, + false, isLast, ptsInUs); + // FU indicator + frame.put((byte)((firstByte & 0xE0) | TYPE_FU_A)); + // FU header + frame.put((byte)((firstFragment ? 0x80 : lastFragment ? 0x40 : 0) | (firstByte & 0x1F))); + // FU payload + frame.put(nalUnit.array(), nalUnit.position(), payloadLength); + nalUnit.position(nalUnit.position() + payloadLength); + frame.flip(); + + try { + mOutputQueue.put(frame); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + return false; + } + + firstFragment = false; + } + } else { + // Use Single NAL Unit Packet ([5.6] in RFC 6184) + ByteBuffer frame = allocateRTPFrame(nalUnit.remaining(), false, isLast, ptsInUs); + frame.put(nalUnit); + frame.flip(); + + try { + mOutputQueue.put(frame); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + return false; + } + } + + return true; + } + + private ByteBuffer allocateRTPFrame(int rtpPayloadLen, + boolean hasPadding, boolean isLast, long ptsInUs) { + if (rtpPayloadLen <= 0) { + throw new IllegalArgumentException("Invalid rtpPayloadLen value: " + rtpPayloadLen); + } + if (ptsInUs < 0) { + throw new IllegalArgumentException("Invalid ptsInUs value: " + ptsInUs); + } + + int packetLength = RTP_HEADER_LEN + rtpPayloadLen; + if (packetLength > MAX_RTP_PACKET_SIZE) { + throw new IllegalArgumentException("Invalid rtpPayloadLen value: " + rtpPayloadLen); + } + int ptsIn90kHz = (int)(ptsInUs * 9 / 100) + mInitialPTS; + + ByteBuffer frame = ByteBuffer.allocate(FRAME_LENGTH_LEN + packetLength); + frame.order(ByteOrder.BIG_ENDIAN); + frame.putShort((short)packetLength); + + // Version = 2, Padding = hasPadding, Extension = 0, CSRC count = 0 + frame.put((byte)(0x80 | (hasPadding ? 0x20 : 0))) + // Marker = isLast, Payload type = mPayloadType + .put((byte)((isLast ? 0x80 : 0) | (mPayloadType & 0x7F))) + .putChar(mSequenceNum) + .putInt(ptsIn90kHz) + .putInt(mSSRC); + + if (frame.position() != FRAME_LENGTH_LEN + RTP_HEADER_LEN) { + throw new RuntimeException("Data size in ByteBuffer mismatch"); + } + + mSequenceNum++; + return frame; + } + + private static boolean isIDR(ByteBuffer nalUnit) { + if (nalUnit == null || !nalUnit.hasRemaining()) { + throw new IllegalArgumentException("Invalid nalUnit arg"); + } + + byte nalUnitType = (byte)(nalUnit.get(nalUnit.position()) & 0x1F); + return nalUnitType == 5; + } + + + private static int SKIP_TABLE[] = new int[256]; + static { + // Sunday's quick search algorithm is used to find the start code. + // Prepare the table (SKIP_TABLE[0] = 2, SKIP_TABLE[1] = 1 and other elements will be 4). + byte[] NAL_UNIT_START_CODE = {0, 0, 1}; + int searchStringLen = NAL_UNIT_START_CODE.length; + for (int i = 0; i < SKIP_TABLE.length; i++) { + SKIP_TABLE[i] = searchStringLen + 1; + } + for (int i = 0; i < searchStringLen; i++) { + SKIP_TABLE[NAL_UNIT_START_CODE[i] & 0xFF] = searchStringLen - i; + } + } + + private class NALUnitReader { + private byte[] mData; + private int mOffset; + private int mLimit; + + NALUnitReader() { + } + + void init(byte[] data) { + mData = data; + mOffset = 0; + mLimit = data.length; + } + + void init(byte[] data, int offset, int length) throws ArrayIndexOutOfBoundsException { + if (offset < 0 || offset > data.length || length <= 0 || offset + length > data.length) { + throw new ArrayIndexOutOfBoundsException(); + } + mData = data; + mOffset = offset; + mLimit = offset + length; + } + + void init(ByteBuffer data) { + if (data == null || data.remaining() == 0) { + mData = null; + mOffset = 0; + mLimit = 0; + return; + } + + if (data.hasArray()) { + mData = data.array(); + mOffset = data.position() + data.arrayOffset(); + mLimit = mOffset + data.remaining(); + + // mark the buffer as consumed + data.position(data.position() + data.remaining()); + } else { + byte[] buffer = new byte[data.remaining()]; + data.get(buffer); + + mData = buffer; + mOffset = 0; + mLimit = buffer.length; + } + } + + ByteBuffer getNalUnit() { + if (hasConsumedAll()) { + return null; + } + + int pos = mOffset; + int start = -1; + + while (mLimit - pos >= 3) { + if (mData[pos] == 0 && mData[pos+1] == 0 && mData[pos+2] == 1) { + if (start != -1) { + // We've found a start code, a NAL unit and then another start code. + mOffset = pos; + // remove 0x00s in front of the start code + while (pos > start && mData[pos-1] == 0) { + pos--; + } + if (pos > start) { + return ByteBuffer.wrap(mData, start, pos - start); + } else { + // No NAL unit between two start codes?! Forget it and search for + // another start code. + pos = mOffset; + } + } + // This is the first start code. + pos += 3; + start = pos; + } else { + try { + pos += SKIP_TABLE[mData[pos+3] & 0xFF]; + } catch (ArrayIndexOutOfBoundsException e) { + break; + } + } + } + + mOffset = mLimit; + if (start != -1 && mLimit > start) { + // We've found a start code and then reached to the end of array. + return ByteBuffer.wrap(mData, start, mLimit - start); + } + // A start code was not found + return null; + } + + boolean hasConsumedAll() { + return (mData == null) || (mLimit - mOffset < 4); + } + } +} diff --git a/sdl_android/src/main/java/com/smartdevicelink/streaming/StreamPacketizer.java b/sdl_android/src/main/java/com/smartdevicelink/streaming/StreamPacketizer.java index 40cc7d5ed..f6a668279 100644 --- a/sdl_android/src/main/java/com/smartdevicelink/streaming/StreamPacketizer.java +++ b/sdl_android/src/main/java/com/smartdevicelink/streaming/StreamPacketizer.java @@ -2,13 +2,18 @@ package com.smartdevicelink.streaming; import java.io.IOException;
import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
import com.smartdevicelink.SdlConnection.SdlConnection;
import com.smartdevicelink.SdlConnection.SdlSession;
import com.smartdevicelink.protocol.ProtocolMessage;
import com.smartdevicelink.protocol.enums.SessionType;
+import com.smartdevicelink.proxy.interfaces.IAudioStreamListener;
+import com.smartdevicelink.proxy.interfaces.IVideoStreamListener;
-public class StreamPacketizer extends AbstractPacketizer implements Runnable{
+public class StreamPacketizer extends AbstractPacketizer implements IVideoStreamListener, IAudioStreamListener, Runnable{
public final static String TAG = "StreamPacketizer";
@@ -23,21 +28,31 @@ public class StreamPacketizer extends AbstractPacketizer implements Runnable{ private final static int BUFF_READ_SIZE = TLS_MAX_RECORD_SIZE - TLS_RECORD_HEADER_SIZE - TLS_RECORD_MES_AUTH_CDE_SIZE - TLS_MAX_RECORD_PADDING_SIZE;
+ // Approximate size of data that mOutputQueue can hold in bytes.
+ // By adding a buffer, we accept underlying transport being stuck for a short time. By setting
+ // a limit of the buffer size, we avoid buffer overflows when underlying transport is too slow.
+ private static final int MAX_QUEUE_SIZE = 256 * 1024;
+
public SdlConnection sdlConnection = null;
private Object mPauseLock;
private boolean mPaused;
private boolean isServiceProtected = false;
-
+ private BlockingQueue<ByteBuffer> mOutputQueue;
+
public StreamPacketizer(IStreamListener streamListener, InputStream is, SessionType sType, byte rpcSessionID, SdlSession session) throws IOException {
super(streamListener, is, sType, rpcSessionID, session);
mPauseLock = new Object();
mPaused = false;
isServiceProtected = _session.isServiceProtected(_serviceType);
+ if (bufferSize == 0) {
+ // fail safe
+ bufferSize = BUFF_READ_SIZE;
+ }
if(isServiceProtected){ //If our service is encrypted we can only use 1024 as the max buffer size.
bufferSize = BUFF_READ_SIZE;
buffer = new byte[bufferSize];
}
-
+ mOutputQueue = new LinkedBlockingQueue<ByteBuffer>(MAX_QUEUE_SIZE / bufferSize);
}
public void start() throws IOException {
@@ -75,20 +90,48 @@ public class StreamPacketizer extends AbstractPacketizer implements Runnable{ }
}
- length = is.read(buffer, 0, bufferSize);
-
- if (length >= 0)
- {
- ProtocolMessage pm = new ProtocolMessage();
- pm.setSessionID(_rpcSessionID);
- pm.setSessionType(_serviceType);
- pm.setFunctionID(0);
- pm.setCorrID(0);
- pm.setData(buffer, length);
- pm.setPayloadProtected(isServiceProtected);
-
- if (t != null && !t.isInterrupted())
- _streamListener.sendStreamPacket(pm);
+ if (is != null) { // using InputStream interface
+ length = is.read(buffer, 0, bufferSize);
+
+ if (length >= 0) {
+ ProtocolMessage pm = new ProtocolMessage();
+ pm.setSessionID(_rpcSessionID);
+ pm.setSessionType(_serviceType);
+ pm.setFunctionID(0);
+ pm.setCorrID(0);
+ pm.setData(buffer, length);
+ pm.setPayloadProtected(isServiceProtected);
+
+ if (t != null && !t.isInterrupted()) {
+ _streamListener.sendStreamPacket(pm);
+ }
+ }
+ } else { // using sendFrame interface
+ ByteBuffer frame;
+ try {
+ frame = mOutputQueue.take();
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ break;
+ }
+
+ while (frame.hasRemaining()) {
+ int len = frame.remaining() > bufferSize ? bufferSize : frame.remaining();
+
+ ProtocolMessage pm = new ProtocolMessage();
+ pm.setSessionID(_rpcSessionID);
+ pm.setSessionType(_serviceType);
+ pm.setFunctionID(0);
+ pm.setCorrID(0);
+ pm.setData(frame.array(), frame.arrayOffset() + frame.position(), len);
+ pm.setPayloadProtected(isServiceProtected);
+
+ if (t != null && !t.isInterrupted()) {
+ _streamListener.sendStreamPacket(pm);
+ }
+
+ frame.position(frame.position() + len);
+ }
}
}
} catch (IOException e)
@@ -119,4 +162,82 @@ public class StreamPacketizer extends AbstractPacketizer implements Runnable{ mPauseLock.notifyAll();
}
}
+
+ /**
+ * Called by the app.
+ *
+ * @see com.smartdevicelink.proxy.interfaces.IVideoStreamListener#sendFrame(byte[], int, int, long)
+ */
+ @Override
+ public void sendFrame(byte[] data, int offset, int length, long presentationTimeUs)
+ throws ArrayIndexOutOfBoundsException {
+ sendArrayData(data, offset, length);
+ }
+
+ /**
+ * Called by the app.
+ *
+ * @see com.smartdevicelink.proxy.interfaces.IVideoStreamListener#sendFrame(ByteBuffer, long)
+ */
+ @Override
+ public void sendFrame(ByteBuffer data, long presentationTimeUs) {
+ sendByteBufferData(data);
+ }
+
+ /**
+ * Called by the app.
+ *
+ * @see com.smartdevicelink.proxy.interfaces.IAudioStreamListener#sendAudio(byte[], int, int, long)
+ */
+ @Override
+ public void sendAudio(byte[] data, int offset, int length, long presentationTimeUs)
+ throws ArrayIndexOutOfBoundsException {
+ sendArrayData(data, offset, length);
+ }
+
+ /**
+ * Called by the app.
+ *
+ * @see com.smartdevicelink.proxy.interfaces.IAudioStreamListener#sendAudio(ByteBuffer, long)
+ */
+ @Override
+ public void sendAudio(ByteBuffer data, long presentationTimeUs) {
+ sendByteBufferData(data);
+ }
+
+ private void sendArrayData(byte[] data, int offset, int length)
+ throws ArrayIndexOutOfBoundsException {
+ if (offset < 0 || offset > data.length || length <= 0 || offset + length > data.length) {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+
+ // StreamPacketizer does not need to split a video frame into NAL units
+ ByteBuffer buffer = ByteBuffer.allocate(length);
+ buffer.put(data, offset, length);
+ buffer.flip();
+
+ try {
+ mOutputQueue.put(buffer);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ private void sendByteBufferData(ByteBuffer data) {
+ if (data == null || data.remaining() == 0) {
+ return;
+ }
+
+ // copy the whole buffer, so that even if the app modifies original ByteBuffer after
+ // sendFrame() or sendAudio() call, our buffer will stay intact
+ ByteBuffer buffer = ByteBuffer.allocate(data.remaining());
+ buffer.put(data);
+ buffer.flip();
+
+ try {
+ mOutputQueue.put(buffer);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
}
diff --git a/sdl_android/src/main/java/com/smartdevicelink/streaming/VideoStreamingParameters.java b/sdl_android/src/main/java/com/smartdevicelink/streaming/VideoStreamingParameters.java index c8c17d8bc..cac4ebbb8 100644 --- a/sdl_android/src/main/java/com/smartdevicelink/streaming/VideoStreamingParameters.java +++ b/sdl_android/src/main/java/com/smartdevicelink/streaming/VideoStreamingParameters.java @@ -96,4 +96,10 @@ public class VideoStreamingParameters { public ImageResolution getResolution() { return resolution; } + + @Override + public String toString() { + return "format: {" + String.valueOf(format) + + "}, resolution: {" + String.valueOf(resolution) + "}"; + } }
\ No newline at end of file diff --git a/sdl_android/src/main/java/com/smartdevicelink/transport/RouterServiceValidator.java b/sdl_android/src/main/java/com/smartdevicelink/transport/RouterServiceValidator.java index 66e415f29..92dce9dbe 100644 --- a/sdl_android/src/main/java/com/smartdevicelink/transport/RouterServiceValidator.java +++ b/sdl_android/src/main/java/com/smartdevicelink/transport/RouterServiceValidator.java @@ -22,6 +22,7 @@ import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; +import android.os.Build; import android.util.Log; import com.smartdevicelink.util.HttpRequestTask; @@ -117,7 +118,7 @@ public class RouterServiceValidator { if(this.service != null){ Log.d(TAG, "Supplied service name of " + this.service.getClassName()); - if(!isServiceRunning(context,this.service)){ + if(Build.VERSION.SDK_INT < Build.VERSION_CODES.O && !isServiceRunning(context,this.service)){ //This means our service isn't actually running, so set to null. Hopefully we can find a real router service after this. service = null; Log.w(TAG, "Supplied service is not actually running."); @@ -129,11 +130,17 @@ public class RouterServiceValidator { } } if(this.service == null){ - this.service= componentNameForServiceRunning(pm); //Change this to an array if multiple services are started? - if(this.service == null){ //if this is still null we know there is no service running so we can return false + if(Build.VERSION.SDK_INT < Build.VERSION_CODES.O ) { + this.service = componentNameForServiceRunning(pm); //Change this to an array if multiple services are started? + if (this.service == null) { //if this is still null we know there is no service running so we can return false + wakeUpRouterServices(); + return false; + } + }else{ wakeUpRouterServices(); return false; } + } //Log.d(TAG, "Checking app package: " + service.getClassName()); diff --git a/sdl_android/src/main/java/com/smartdevicelink/transport/SdlBroadcastReceiver.java b/sdl_android/src/main/java/com/smartdevicelink/transport/SdlBroadcastReceiver.java index cfcd486b2..94bb3c51e 100644 --- a/sdl_android/src/main/java/com/smartdevicelink/transport/SdlBroadcastReceiver.java +++ b/sdl_android/src/main/java/com/smartdevicelink/transport/SdlBroadcastReceiver.java @@ -1,22 +1,39 @@ package com.smartdevicelink.transport; -import java.util.List; -import java.util.Locale; -import java.util.Vector; -import java.util.concurrent.ConcurrentLinkedQueue; - -import com.smartdevicelink.util.AndroidTools; -import com.smartdevicelink.transport.RouterServiceValidator.TrustedListCallback; - +import android.annotation.TargetApi; import android.app.ActivityManager; import android.app.ActivityManager.RunningServiceInfo; +import android.app.usage.UsageStats; +import android.app.usage.UsageStatsManager; import android.bluetooth.BluetoothAdapter; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.os.Build; import android.util.Log; +import com.smartdevicelink.transport.RouterServiceValidator.TrustedListCallback; +import com.smartdevicelink.util.AndroidTools; +import com.smartdevicelink.util.ServiceFinder; + +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Vector; +import java.util.concurrent.ConcurrentLinkedQueue; + +import static com.smartdevicelink.transport.TransportConstants.BIND_LOCATION_CLASS_NAME_EXTRA; +import static com.smartdevicelink.transport.TransportConstants.BIND_LOCATION_PACKAGE_NAME_EXTRA; +import static com.smartdevicelink.transport.TransportConstants.FOREGROUND_EXTRA; +import static com.smartdevicelink.transport.TransportConstants.SEND_PACKET_TO_APP_LOCATION_EXTRA_NAME; + public abstract class SdlBroadcastReceiver extends BroadcastReceiver{ private static final String TAG = "Sdl Broadcast Receiver"; @@ -74,8 +91,10 @@ public abstract class SdlBroadcastReceiver extends BroadcastReceiver{ return; } - boolean didStart = false; - localRouterClass = defineLocalSdlRouterClass(); + boolean didStart = false; + if (localRouterClass == null){ + localRouterClass = defineLocalSdlRouterClass(); + } //This will only be true if we are being told to reopen our SDL service because SDL is enabled if(action.equalsIgnoreCase(TransportConstants.START_ROUTER_SERVICE_ACTION)){ @@ -127,10 +146,10 @@ public abstract class SdlBroadcastReceiver extends BroadcastReceiver{ return; } } - + Log.d(TAG, "Check for local router"); if(localRouterClass!=null){ //If there is a supplied router service lets run some logic regarding starting one - if(!didStart){ + if(!didStart){Log.d(TAG, "attempting to wake up router service"); didStart = wakeUpRouterService(context, true,false); } @@ -145,42 +164,109 @@ public abstract class SdlBroadcastReceiver extends BroadcastReceiver{ context.sendBroadcast(restart); } } - - private boolean wakeUpRouterService(Context context, boolean ping, boolean altTransportWake){ - if(!isRouterServiceRunning(context, ping)){ - //If there isn't a service running we should try to start one - //The under class should have implemented this.... - - //So let's start up our service since no copy is running - Intent serviceIntent = new Intent(context, localRouterClass); - if(altTransportWake){ - serviceIntent.setAction(TransportConstants.BIND_REQUEST_TYPE_ALT_TRANSPORT); - } - try { - context.startService(serviceIntent); - }catch (SecurityException e){ - Log.e(TAG, "Security exception, process is bad"); - return false; // Let's exit, we can't start the service - } - return true; - }else{ - if(altTransportWake && runningBluetoothServicePackage!=null && runningBluetoothServicePackage.size()>0){ - Intent serviceIntent = new Intent(); - serviceIntent.setAction(TransportConstants.BIND_REQUEST_TYPE_ALT_TRANSPORT); - //context.startService(serviceIntent); - for(ComponentName compName: runningBluetoothServicePackage){ - serviceIntent.setComponent(compName); - context.startService(serviceIntent); - } - return true; - } - return false; - } + @TargetApi(Build.VERSION_CODES.O) + private boolean wakeUpRouterService(final Context context, final boolean ping, final boolean altTransportWake){ + if(Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { + if (!isRouterServiceRunning(context, ping)) { + //If there isn't a service running we should try to start one + //The under class should have implemented this.... + Log.d(TAG, "No router service running, starting ours"); + //So let's start up our service since no copy is running + Intent serviceIntent = new Intent(context, localRouterClass); + if (altTransportWake) { + serviceIntent.setAction(TransportConstants.BIND_REQUEST_TYPE_ALT_TRANSPORT); + } + try { + context.startService(serviceIntent); + } catch (SecurityException e) { + Log.e(TAG, "Security exception, process is bad"); + return false; // Let's exit, we can't start the service + } + return true; + } else { + if (altTransportWake && runningBluetoothServicePackage != null && runningBluetoothServicePackage.size() > 0) { + wakeRouterServiceAltTransport(context); + return true; + } + return false; + } + }else{ //We are android Oreo or newer + ServiceFinder finder = new ServiceFinder(context, context.getPackageName(), new ServiceFinder.ServiceFinderCallback() { + @Override + public void onComplete(Vector<ComponentName> routerServices) { + runningBluetoothServicePackage = new Vector<ComponentName>(); + runningBluetoothServicePackage.addAll(routerServices); + if (runningBluetoothServicePackage.isEmpty()) { + //If there isn't a service running we should try to start one + //We will try to sort the SDL enabled apps and find the one that's been installed the longest + Intent serviceIntent; + final PackageManager packageManager = context.getPackageManager(); + Vector<ResolveInfo> apps = new Vector(AndroidTools.getSdlEnabledApps(context, "").values()); //we want our package + if (apps != null && !apps.isEmpty()) { + Collections.sort(apps, new Comparator<ResolveInfo>() { + @Override + public int compare(ResolveInfo resolveInfo, ResolveInfo t1) { + try { + PackageInfo thisPack = packageManager.getPackageInfo(resolveInfo.activityInfo.packageName, 0); + PackageInfo itPack = packageManager.getPackageInfo(t1.activityInfo.packageName, 0); + if (thisPack.lastUpdateTime < itPack.lastUpdateTime) { + return -1; + } else if (thisPack.lastUpdateTime > itPack.lastUpdateTime) { + return 1; + } + + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + return 0; + } + }); + String packageName = apps.get(0).activityInfo.packageName; + serviceIntent = new Intent(); + serviceIntent.setComponent(new ComponentName(packageName, packageName +".SdlRouterService")); + } else{ + Log.d(TAG, "No router service running, starting ours"); + //So let's start up our service since no copy is running + serviceIntent = new Intent(context, localRouterClass); + + } + if (altTransportWake) { + serviceIntent.setAction(TransportConstants.BIND_REQUEST_TYPE_ALT_TRANSPORT); + } + try { + serviceIntent.putExtra(FOREGROUND_EXTRA, true); + context.startForegroundService(serviceIntent); + + } catch (SecurityException e) { + Log.e(TAG, "Security exception, process is bad"); + } + } else { + if (altTransportWake && runningBluetoothServicePackage != null && runningBluetoothServicePackage.size() > 0) { + wakeRouterServiceAltTransport(context); + return; + } + return; + } + } + }); + return true; + } + } + + private void wakeRouterServiceAltTransport(Context context){ + Intent serviceIntent = new Intent(); + serviceIntent.setAction(TransportConstants.BIND_REQUEST_TYPE_ALT_TRANSPORT); + for (ComponentName compName : runningBluetoothServicePackage) { + serviceIntent.setComponent(compName); + context.startService(serviceIntent); + + } } /** - * Determines if an instance of the Router Service is currently running on the device. + * Determines if an instance of the Router Service is currently running on the device.<p> + * <b>Note:</b> This method no longer works on Android Oreo or newer * @param context A context to access Android system services through. * @param pingService Set this to true if you want to make sure the service is up and listening to bluetooth * @return True if a SDL Router Service is currently running, false otherwise. @@ -190,31 +276,30 @@ public abstract class SdlBroadcastReceiver extends BroadcastReceiver{ Log.e(TAG, "Can't look for router service, context supplied was null"); return false; } - ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); - if(runningBluetoothServicePackage==null){ + if (runningBluetoothServicePackage == null) { runningBluetoothServicePackage = new Vector<ComponentName>(); - }else{ + } else { runningBluetoothServicePackage.clear(); } + ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); + manager.getRunningAppProcesses(); List<RunningServiceInfo> runningServices = null; - try{ + try { runningServices = manager.getRunningServices(Integer.MAX_VALUE); - }catch(NullPointerException e){ + } catch (NullPointerException e) { Log.e(TAG, "Can't get list of running services"); return false; } - for (RunningServiceInfo service : runningServices) { + for (RunningServiceInfo service : runningServices) { //We will check to see if it contains this name, should be pretty specific - //Log.d(TAG, "Found Service: "+ service.service.getClassName()); - if ((service.service.getClassName()).toLowerCase(Locale.US).contains(SDL_ROUTER_SERVICE_CLASS_NAME) && AndroidTools.isServiceExported(context, service.service)) { - - runningBluetoothServicePackage.add(service.service); //Store which instance is running - if(pingService){ + //Log.d(TAG, "Found Service: "+ service.service.getClassName()); + if ((service.service.getClassName()).toLowerCase(Locale.US).contains(SDL_ROUTER_SERVICE_CLASS_NAME) && AndroidTools.isServiceExported(context, service.service)) { + runningBluetoothServicePackage.add(service.service); //Store which instance is running + if (pingService) { pingRouterService(context, service.service.getPackageName(), service.service.getClassName()); - } - } - } - + } + } + } return runningBluetoothServicePackage.size() > 0; } @@ -239,33 +324,46 @@ public abstract class SdlBroadcastReceiver extends BroadcastReceiver{ // This service could not be started } } - + /** * This call will reach out to all SDL related router services to check if they're connected. If a the router service is connected, it will react by pinging all clients. This receiver will then * receive that ping and if the router service is trusted, the onSdlEnabled method will be called. * @param context */ - public static void queryForConnectedService(Context context){ + public static void queryForConnectedService(final Context context){ //Leverage existing call. Include ping bit - requestTransportStatus(context,null,true); + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){ + ServiceFinder finder = new ServiceFinder(context, context.getPackageName(), new ServiceFinder.ServiceFinderCallback() { + @Override + public void onComplete(Vector<ComponentName> routerServices) { + runningBluetoothServicePackage = new Vector<ComponentName>(); + runningBluetoothServicePackage.addAll(routerServices); + requestTransportStatus(context,null,true,false); + } + }); + + }else{ + requestTransportStatus(context,null,true,true); + } } /** * If a Router Service is running, this method determines if that service is connected to a device over some form of transport. * @param context A context to access Android system services through. If null is passed, this will always return false * @param callback Use this callback to find out if the router service is connected or not. */ + @Deprecated public static void requestTransportStatus(Context context, final SdlRouterStatusProvider.ConnectedStatusCallback callback){ - requestTransportStatus(context,callback,false); + requestTransportStatus(context,callback,false, true); } - private static void requestTransportStatus(Context context, final SdlRouterStatusProvider.ConnectedStatusCallback callback, final boolean triggerRouterServicePing){ + private static void requestTransportStatus(Context context, final SdlRouterStatusProvider.ConnectedStatusCallback callback, final boolean triggerRouterServicePing, final boolean lookForServices){ if(context == null){ if(callback!=null){ callback.onConnectionStatusUpdate(false, null,context); } return; } - if(isRouterServiceRunning(context,false) && !runningBluetoothServicePackage.isEmpty()){ //So there is a service up, let's see if it's connected + if((!lookForServices || isRouterServiceRunning(context,false)) && !runningBluetoothServicePackage.isEmpty()){ //So there is a service up, let's see if it's connected final ConcurrentLinkedQueue<ComponentName> list = new ConcurrentLinkedQueue<ComponentName>(runningBluetoothServicePackage); final SdlRouterStatusProvider.ConnectedStatusCallback sdlBrCallback = new SdlRouterStatusProvider.ConnectedStatusCallback() { diff --git a/sdl_android/src/main/java/com/smartdevicelink/transport/SdlRouterService.java b/sdl_android/src/main/java/com/smartdevicelink/transport/SdlRouterService.java index d3a4fd051..5ca8cec0e 100644 --- a/sdl_android/src/main/java/com/smartdevicelink/transport/SdlRouterService.java +++ b/sdl_android/src/main/java/com/smartdevicelink/transport/SdlRouterService.java @@ -1,6 +1,5 @@ package com.smartdevicelink.transport; -import static com.smartdevicelink.proxy.constants.Names.info; import static com.smartdevicelink.transport.TransportConstants.CONNECTED_DEVICE_STRING_EXTRA_NAME; import static com.smartdevicelink.transport.TransportConstants.FORMED_PACKET_EXTRA_NAME; import static com.smartdevicelink.transport.TransportConstants.HARDWARE_DISCONNECTED; @@ -23,11 +22,14 @@ import org.json.JSONException; import org.json.JSONObject; import android.Manifest; + import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.app.ActivityManager; import android.app.ActivityManager.RunningAppProcessInfo; import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; import android.app.Service; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; @@ -72,6 +74,30 @@ import com.smartdevicelink.transport.utl.ByteAraryMessageAssembler; import com.smartdevicelink.transport.utl.ByteArrayMessageSpliter; import com.smartdevicelink.util.AndroidTools; import com.smartdevicelink.util.BitConverter; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.lang.ref.WeakReference; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Set; +import java.util.Vector; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import static com.smartdevicelink.transport.TransportConstants.CONNECTED_DEVICE_STRING_EXTRA_NAME; +import static com.smartdevicelink.transport.TransportConstants.FOREGROUND_EXTRA; +import static com.smartdevicelink.transport.TransportConstants.FORMED_PACKET_EXTRA_NAME; +import static com.smartdevicelink.transport.TransportConstants.HARDWARE_DISCONNECTED; +import static com.smartdevicelink.transport.TransportConstants.SDL_NOTIFICATION_CHANNEL_ID; +import static com.smartdevicelink.transport.TransportConstants.SDL_NOTIFICATION_CHANNEL_NAME; +import static com.smartdevicelink.transport.TransportConstants.SEND_PACKET_TO_APP_LOCATION_EXTRA_NAME; /** * <b>This class should not be modified by anyone outside of the approved contributors of the SmartDeviceLink project.</b> * This service is a central point of communication between hardware and the registered clients. It will multiplex a single transport @@ -181,6 +207,7 @@ public class SdlRouterService extends Service{ registrationIntent.setAction(action); registrationIntent.putExtra(TransportConstants.BIND_LOCATION_PACKAGE_NAME_EXTRA, this.getPackageName()); registrationIntent.putExtra(TransportConstants.BIND_LOCATION_CLASS_NAME_EXTRA, this.getClass().getName()); + registrationIntent.setFlags((Intent.FLAG_RECEIVER_FOREGROUND)); return registrationIntent; } @@ -889,6 +916,9 @@ public class SdlRouterService extends Service{ } } if(intent != null ){ + if(intent.getBooleanExtra(FOREGROUND_EXTRA, false)){ + enterForeground(); + } if(intent.hasExtra(TransportConstants.PING_ROUTER_SERVICE_EXTRA)){ //Make sure we are listening on RFCOMM if(startSequenceComplete){ //We only check if we are sure we are already through the start up process @@ -1029,18 +1059,37 @@ public class SdlRouterService extends Service{ notification = builder.getNotification(); }else{ + if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.O) { + //Now we need to add a notification channel + NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + String channelId = SDL_NOTIFICATION_CHANNEL_ID; + CharSequence channelName = SDL_NOTIFICATION_CHANNEL_NAME; + int importance = NotificationManager.IMPORTANCE_DEFAULT; + NotificationChannel notificationChannel = new NotificationChannel(channelId, channelName, importance); + notificationChannel.enableLights(false); + notificationChannel.enableVibration(false); + notificationManager.createNotificationChannel(notificationChannel); + builder.setChannelId(channelId); + + } notification = builder.build(); } if(notification == null){ Log.e(TAG, "Notification was null"); + return; } startForeground(FOREGROUND_SERVICE_ID, notification); isForeground = true; } - + private void exitForeground(){ if(isForeground){ + if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){ + NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + notificationManager.deleteNotificationChannel(TransportConstants.SDL_NOTIFICATION_CHANNEL_ID); + } + this.stopForeground(true); } } @@ -1741,7 +1790,7 @@ public class SdlRouterService extends Service{ } } - @TargetApi(Build.VERSION_CODES.HONEYCOMB) + @TargetApi(Build.VERSION_CODES.HONEYCOMB) private boolean removeAllSessionsWithAppId(String appId){ synchronized(SESSION_LOCK){ if(sessionMap!=null){ diff --git a/sdl_android/src/main/java/com/smartdevicelink/transport/TransportBroker.java b/sdl_android/src/main/java/com/smartdevicelink/transport/TransportBroker.java index 89187d524..1d1b3b792 100644 --- a/sdl_android/src/main/java/com/smartdevicelink/transport/TransportBroker.java +++ b/sdl_android/src/main/java/com/smartdevicelink/transport/TransportBroker.java @@ -7,6 +7,7 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; +import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; @@ -488,7 +489,7 @@ public class TransportBroker { } //Make sure we know where to bind to if(this.routerService==null){ - if(!isRouterServiceRunning(getContext())){//We should be able to ignore this case because of the validation now + if((Build.VERSION.SDK_INT < Build.VERSION_CODES.O) && !isRouterServiceRunning(getContext())){//We should be able to ignore this case because of the validation now Log.d(TAG,whereToReply + " found no router service. Shutting down."); this.onHardwareDisconnected(null); return false; diff --git a/sdl_android/src/main/java/com/smartdevicelink/transport/TransportConstants.java b/sdl_android/src/main/java/com/smartdevicelink/transport/TransportConstants.java index 6203aa3e7..8db44f500 100644 --- a/sdl_android/src/main/java/com/smartdevicelink/transport/TransportConstants.java +++ b/sdl_android/src/main/java/com/smartdevicelink/transport/TransportConstants.java @@ -10,6 +10,7 @@ package com.smartdevicelink.transport; */ public class TransportConstants { public static final String START_ROUTER_SERVICE_ACTION ="sdl.router.startservice"; + public static final String FOREGROUND_EXTRA = "foreground"; public static final String BIND_LOCATION_PACKAGE_NAME_EXTRA = "BIND_LOCATION_PACKAGE_NAME_EXTRA"; public static final String BIND_LOCATION_CLASS_NAME_EXTRA = "BIND_LOCATION_CLASS_NAME_EXTRA"; @@ -54,6 +55,12 @@ public class TransportConstants { public static final String PING_ROUTER_SERVICE_EXTRA = "ping.router.service"; + public static final String SDL_NOTIFICATION_CHANNEL_ID = "sdl_notification_channel"; + public static final String SDL_NOTIFICATION_CHANNEL_NAME = "SmartDeviceLink"; + + + + /** * This class houses all important router service versions */ diff --git a/sdl_android/src/main/java/com/smartdevicelink/util/AndroidTools.java b/sdl_android/src/main/java/com/smartdevicelink/util/AndroidTools.java index ff8819ec3..bc55dcb07 100644 --- a/sdl_android/src/main/java/com/smartdevicelink/util/AndroidTools.java +++ b/sdl_android/src/main/java/com/smartdevicelink/util/AndroidTools.java @@ -2,9 +2,16 @@ package com.smartdevicelink.util; import android.content.ComponentName; import android.content.Context; +import android.content.Intent; import android.content.pm.PackageManager; -import android.content.pm.ServiceInfo; import android.content.pm.PackageManager.NameNotFoundException; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; + +import com.smartdevicelink.transport.TransportConstants; + +import java.util.HashMap; +import java.util.List; public class AndroidTools { /** @@ -22,4 +29,24 @@ public class AndroidTools { } return false; } + /** + * Get all SDL enabled apps. If the package name is null, it will return all apps. However, if the package name is included, the + * resulting hash map will not include the app with that package name. + * @param context + * @param myPackageName + * @return + */ + public static HashMap<String,ResolveInfo> getSdlEnabledApps(Context context, String myPackageName){ + Intent intent = new Intent(TransportConstants.START_ROUTER_SERVICE_ACTION); + List<ResolveInfo> infos = context.getPackageManager().queryBroadcastReceivers(intent, 0); + HashMap<String,ResolveInfo> sdlMultiList = new HashMap<String,ResolveInfo>(); + for(ResolveInfo info: infos){ + if(info.activityInfo.applicationInfo.packageName.equals(myPackageName)){ + continue; //Ignoring my own package + } + sdlMultiList.put(info.activityInfo.packageName, info); + } + return sdlMultiList; + } + } diff --git a/sdl_android/src/main/java/com/smartdevicelink/util/ServiceFinder.java b/sdl_android/src/main/java/com/smartdevicelink/util/ServiceFinder.java new file mode 100644 index 000000000..c115d046c --- /dev/null +++ b/sdl_android/src/main/java/com/smartdevicelink/util/ServiceFinder.java @@ -0,0 +1,141 @@ +package com.smartdevicelink.util; + +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.ResolveInfo; +import android.os.Handler; +import android.util.Log; + +import com.smartdevicelink.transport.SdlRouterService; + +import java.util.HashMap; +import java.util.Vector; + +import static com.smartdevicelink.transport.TransportConstants.BIND_LOCATION_CLASS_NAME_EXTRA; +import static com.smartdevicelink.transport.TransportConstants.BIND_LOCATION_PACKAGE_NAME_EXTRA; +import static com.smartdevicelink.transport.TransportConstants.SEND_PACKET_TO_APP_LOCATION_EXTRA_NAME; + +/** + * Created by Joey Grover on 8/18/17. + */ + +public class ServiceFinder { + public static final String TAG = ServiceFinder.class.getSimpleName(); + + private static final int TIMEOUT = 1000; + final String receiverLocation; + final Context context; + final ServiceFinderCallback callback; + final Vector<ComponentName> services; + final HashMap<String, ResolveInfo> sdlMultiMap; + final Handler timeoutHandler; + final Runnable timeoutRunnable; + + + public ServiceFinder(Context context, String packageName, final ServiceFinderCallback callback) { + this.receiverLocation = packageName + ".ServiceFinder"; + this.context = context.getApplicationContext(); + this.callback = callback; + this.services = new Vector<>(); + + this.sdlMultiMap = AndroidTools.getSdlEnabledApps(context, packageName); + + this.context.registerReceiver(mainServiceReceiver, new IntentFilter(this.receiverLocation)); + + timeoutRunnable = new Runnable() { + @Override + public void run() { + onFinished(); + } + }; + timeoutHandler = new Handler(); + timeoutHandler.postDelayed(timeoutRunnable, TIMEOUT + (50 * packageName.length())); + + //Send out our broadcast + context.sendBroadcast(createQueryIntent(this.receiverLocation)); + + + } + + BroadcastReceiver mainServiceReceiver = new BroadcastReceiver() { + private final Object LIST_LOCK = new Object(); + + @Override + public void onReceive(Context context, Intent intent) { + Log.d(TAG, "Received intent " + intent); + if (intent != null) { + String packageName = intent.getStringExtra(BIND_LOCATION_PACKAGE_NAME_EXTRA); + String className = intent.getStringExtra(BIND_LOCATION_CLASS_NAME_EXTRA); + Log.d(TAG, "Received intent from package: " + packageName + ". Classname: " + className); + synchronized (LIST_LOCK) { + //Add to running services + services.add(new ComponentName(packageName, className)); + //Remove from our waiting for response list + sdlMultiMap.remove(packageName); + + //If list is empty, return to callback and unregister + if (sdlMultiMap.isEmpty() && callback != null) { + timeoutHandler.removeCallbacks(timeoutRunnable); + onFinished(); + } + } + } + } + }; + + private void onFinished() { + if (callback != null) { + callback.onComplete(services); + } + context.unregisterReceiver(mainServiceReceiver); + + } + +// /** +// * Get all SDL enabled apps. If the package name is null, it will return all apps. However, if the package name is included, the +// * resulting hash map will not include the app with that package name. +// * +// * @param context +// * @param packageName +// * @return +// */ +// public static HashMap<String, ResolveInfo> getSdlEnabledApps(Context context, String packageName) { +// Intent intent = new Intent(TransportConstants.START_ROUTER_SERVICE_ACTION); +// PackageManager manager = context.getPackageManager(); +// List<ResolveInfo> infos = manager.queryBroadcastReceivers(intent, 0); +// HashMap<String, ResolveInfo> sdlMultiMap = new HashMap<String, ResolveInfo>(); +// for (ResolveInfo info : infos) { +// //Log.d(TAG, "Sdl enabled app: " + info.activityInfo.packageName); +// if (info.activityInfo.applicationInfo.packageName.equals(packageName)) { +// //Log.d(TAG, "Ignoring my own package"); +// continue; +// } +// +// sdlMultiMap.put(info.activityInfo.packageName, info); +// try { +// ServiceInfo[] services = manager.getPackageInfo(info.activityInfo.applicationInfo.packageName, PackageManager.GET_SERVICES).services; +// for (int i = 0; i < services.length; i++) { +// Log.d(TAG, "Found : " + services[i].name); +// } +// } catch (PackageManager.NameNotFoundException e) { +// e.printStackTrace(); +// } +// } +// return sdlMultiMap; +// } + + private static Intent createQueryIntent(String receiverLocation) { + Intent intent = new Intent(); + intent.setAction(SdlRouterService.REGISTER_WITH_ROUTER_ACTION); + intent.putExtra(SEND_PACKET_TO_APP_LOCATION_EXTRA_NAME, receiverLocation); + intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND); + return intent; + } + + public interface ServiceFinderCallback { + void onComplete(Vector<ComponentName> routerServices); + } +} |