diff options
author | Joey Grover <joeygrover@gmail.com> | 2019-10-11 09:48:41 -0400 |
---|---|---|
committer | Joey Grover <joeygrover@gmail.com> | 2019-10-11 09:48:41 -0400 |
commit | d1ec82d968823edbfea450ae9c33561f6f348e01 (patch) | |
tree | 649dd4ca1081693d9a3de3e57ad02dbc3c32c387 | |
parent | 1ac694277dac36257ef3febc225dfeee435caab8 (diff) | |
parent | ac66a7929e61274efb3faa1c0746a654051c7d41 (diff) | |
download | sdl_android-d1ec82d968823edbfea450ae9c33561f6f348e01.tar.gz |
Merge branch 'develop' of https://github.com/smartdevicelink/sdl_android into bugfix/issue_1193
# Conflicts:
# android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuCellTests.java
63 files changed, 1294 insertions, 409 deletions
diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/file/FileManagerTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/file/FileManagerTests.java index 96d78584d..b1a0ba26e 100644 --- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/file/FileManagerTests.java +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/file/FileManagerTests.java @@ -20,8 +20,6 @@ import com.smartdevicelink.proxy.rpc.enums.StaticIconName; import com.smartdevicelink.proxy.rpc.listeners.OnMultipleRequestListener; import com.smartdevicelink.test.Test; -import junit.framework.Assert; - import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/SoftButtonManagerTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/SoftButtonManagerTests.java index 3664d416f..514549080 100644 --- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/SoftButtonManagerTests.java +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/SoftButtonManagerTests.java @@ -12,6 +12,8 @@ import com.smartdevicelink.proxy.rpc.Image; import com.smartdevicelink.proxy.rpc.OnHMIStatus; import com.smartdevicelink.proxy.rpc.Show; import com.smartdevicelink.proxy.rpc.SoftButton; +import com.smartdevicelink.proxy.rpc.SoftButtonCapabilities; +import com.smartdevicelink.proxy.rpc.WindowCapability; import com.smartdevicelink.proxy.rpc.enums.FileType; import com.smartdevicelink.proxy.rpc.enums.HMILevel; import com.smartdevicelink.proxy.rpc.enums.ImageType; @@ -131,6 +133,12 @@ public class SoftButtonManagerTests extends AndroidTestCase2 { internalInterfaceSendRPCGotCalled = false; softButtonMangerUpdateCompleted = false; + SoftButtonCapabilities softCap = new SoftButtonCapabilities(); + softCap.setImageSupported(true); + WindowCapability defaultCap = new WindowCapability(); + defaultCap.setSoftButtonCapabilities(Collections.singletonList(softCap)); + softButtonManager.defaultMainWindowCapability = defaultCap; + // Test batch update softButtonManager.setBatchUpdates(true); @@ -151,7 +159,8 @@ public class SoftButtonManagerTests extends AndroidTestCase2 { // Check that everything got called as expected - assertTrue("FileManager.uploadArtworks() did not get called", fileManagerUploadArtworksGotCalled); + + assertTrue("FileManager.uploadArtworks() did get called", fileManagerUploadArtworksGotCalled); assertTrue("InternalInterface.sendRPC() did not get called", internalInterfaceSendRPCGotCalled); assertTrue("SoftButtonManger update onComplete() did not get called", softButtonMangerUpdateCompleted); diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/TextAndGraphicManagerTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/TextAndGraphicManagerTests.java index d7b788a90..3597c33f5 100644 --- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/TextAndGraphicManagerTests.java +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/TextAndGraphicManagerTests.java @@ -8,10 +8,10 @@ import com.smartdevicelink.managers.BaseSubManager; import com.smartdevicelink.managers.file.FileManager; import com.smartdevicelink.managers.file.filetypes.SdlArtwork; import com.smartdevicelink.proxy.interfaces.ISdl; -import com.smartdevicelink.proxy.rpc.DisplayCapabilities; import com.smartdevicelink.proxy.rpc.MetadataTags; import com.smartdevicelink.proxy.rpc.Show; import com.smartdevicelink.proxy.rpc.TextField; +import com.smartdevicelink.proxy.rpc.WindowCapability; import com.smartdevicelink.proxy.rpc.enums.FileType; import com.smartdevicelink.proxy.rpc.enums.HMILevel; import com.smartdevicelink.proxy.rpc.enums.MetadataType; @@ -58,7 +58,7 @@ public class TextAndGraphicManagerTests extends AndroidTestCase2 { super.tearDown(); } - private DisplayCapabilities getDisplayCapability(int numberOfMainFields){ + private WindowCapability getWindowCapability(int numberOfMainFields){ TextField mainField1 = new TextField(); mainField1.setName(TextFieldName.mainField1); @@ -84,10 +84,10 @@ public class TextAndGraphicManagerTests extends AndroidTestCase2 { } } - DisplayCapabilities displayCapabilities = new DisplayCapabilities(); - displayCapabilities.setTextFields(returnList); + WindowCapability windowCapability = new WindowCapability(); + windowCapability.setTextFields(returnList); - return displayCapabilities; + return windowCapability; } public void testInstantiation(){ @@ -110,7 +110,7 @@ public class TextAndGraphicManagerTests extends AndroidTestCase2 { assertNull(textAndGraphicManager.inProgressUpdate); assertNull(textAndGraphicManager.queuedImageUpdate); assertFalse(textAndGraphicManager.hasQueuedUpdate); - assertNull(textAndGraphicManager.displayCapabilities); + assertNull(textAndGraphicManager.defaultMainWindowCapability); assertEquals(textAndGraphicManager.currentHMILevel, HMILevel.HMI_NONE); assertFalse(textAndGraphicManager.isDirty); assertEquals(textAndGraphicManager.getState(), BaseSubManager.SETTING_UP); @@ -126,7 +126,7 @@ public class TextAndGraphicManagerTests extends AndroidTestCase2 { // The tests.java class has an example of this, but we must build it to do what // we need it to do. Build display cap w/ 3 main fields and test that it returns 3 - textAndGraphicManager.displayCapabilities = getDisplayCapability(3); + textAndGraphicManager.defaultMainWindowCapability = getWindowCapability(3); assertEquals(textAndGraphicManager.getNumberOfLines(), 3); } @@ -135,7 +135,7 @@ public class TextAndGraphicManagerTests extends AndroidTestCase2 { Show inputShow = new Show(); // Force it to return display with support for only 1 line of text - textAndGraphicManager.displayCapabilities = getDisplayCapability(1); + textAndGraphicManager.defaultMainWindowCapability = getWindowCapability(1); textAndGraphicManager.setTextField1("It is"); textAndGraphicManager.setTextField1Type(MetadataType.HUMIDITY); @@ -185,7 +185,7 @@ public class TextAndGraphicManagerTests extends AndroidTestCase2 { Show inputShow = new Show(); // Force it to return display with support for only 2 lines of text - textAndGraphicManager.displayCapabilities = getDisplayCapability(2); + textAndGraphicManager.defaultMainWindowCapability = getWindowCapability(2); textAndGraphicManager.setTextField1("It is"); textAndGraphicManager.setTextField1Type(MetadataType.HUMIDITY); @@ -282,7 +282,7 @@ public class TextAndGraphicManagerTests extends AndroidTestCase2 { Show inputShow = new Show(); // Force it to return display with support for only 3 lines of text - textAndGraphicManager.displayCapabilities = getDisplayCapability(3); + textAndGraphicManager.defaultMainWindowCapability = getWindowCapability(3); textAndGraphicManager.setTextField1("It is"); textAndGraphicManager.setTextField1Type(MetadataType.HUMIDITY); @@ -375,7 +375,7 @@ public class TextAndGraphicManagerTests extends AndroidTestCase2 { Show inputShow = new Show(); // Force it to return display with support for only 4 lines of text - textAndGraphicManager.displayCapabilities = getDisplayCapability(4); + textAndGraphicManager.defaultMainWindowCapability = getWindowCapability(4); textAndGraphicManager.setTextField1("It is"); textAndGraphicManager.setTextField1Type(MetadataType.HUMIDITY); @@ -548,7 +548,7 @@ public class TextAndGraphicManagerTests extends AndroidTestCase2 { assertNull(textAndGraphicManager.inProgressUpdate); assertNull(textAndGraphicManager.queuedImageUpdate); assertFalse(textAndGraphicManager.hasQueuedUpdate); - assertNull(textAndGraphicManager.displayCapabilities); + assertNull(textAndGraphicManager.defaultMainWindowCapability); assertFalse(textAndGraphicManager.isDirty); assertEquals(textAndGraphicManager.getState(), BaseSubManager.SHUTDOWN); } diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/CheckChoiceVROptionalOperationTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/CheckChoiceVROptionalOperationTests.java index a47528348..7b9696151 100644 --- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/CheckChoiceVROptionalOperationTests.java +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/CheckChoiceVROptionalOperationTests.java @@ -36,8 +36,6 @@ package com.smartdevicelink.managers.screen.choiceset; import com.smartdevicelink.AndroidTestCase2; -import com.smartdevicelink.managers.screen.choiceset.CheckChoiceVROptionalInterface; -import com.smartdevicelink.managers.screen.choiceset.CheckChoiceVROptionalOperation; import com.smartdevicelink.proxy.interfaces.ISdl; import com.smartdevicelink.proxy.rpc.Choice; import com.smartdevicelink.proxy.rpc.CreateInteractionChoiceSet; diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/ChoiceSetManagerTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/ChoiceSetManagerTests.java index b8af1a68c..1a9efffbe 100644 --- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/ChoiceSetManagerTests.java +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/ChoiceSetManagerTests.java @@ -85,7 +85,7 @@ public class ChoiceSetManagerTests extends AndroidTestCase2 { assertNotNull(csm.operationQueue); assertNotNull(csm.executor); assertNotNull(csm.hmiListener); - assertNotNull(csm.displayListener); + assertNotNull(csm.onDisplayCapabilityListener); assertNull(csm.pendingPresentOperation); } @@ -96,7 +96,7 @@ public class ChoiceSetManagerTests extends AndroidTestCase2 { assertNull(csm.currentHMILevel); assertNull(csm.currentSystemContext); - assertNull(csm.displayCapabilities); + assertNull(csm.defaultMainWindowCapability); assertNull(csm.pendingPresentationSet); assertNull(csm.pendingPresentOperation); diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/DeleteChoicesOperationTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/DeleteChoicesOperationTests.java index 3a9eed394..67200d0fe 100644 --- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/DeleteChoicesOperationTests.java +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/DeleteChoicesOperationTests.java @@ -36,8 +36,6 @@ package com.smartdevicelink.managers.screen.choiceset; import com.smartdevicelink.AndroidTestCase2; -import com.smartdevicelink.managers.screen.choiceset.ChoiceCell; -import com.smartdevicelink.managers.screen.choiceset.DeleteChoicesOperation; import com.smartdevicelink.proxy.interfaces.ISdl; import com.smartdevicelink.proxy.rpc.DeleteInteractionChoiceSet; diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/PreloadChoicesOperationTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/PreloadChoicesOperationTests.java index 514d88bca..b29863110 100644 --- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/PreloadChoicesOperationTests.java +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/PreloadChoicesOperationTests.java @@ -38,15 +38,14 @@ package com.smartdevicelink.managers.screen.choiceset; import com.smartdevicelink.AndroidTestCase2; import com.smartdevicelink.managers.file.FileManager; import com.smartdevicelink.managers.file.filetypes.SdlArtwork; -import com.smartdevicelink.managers.screen.choiceset.ChoiceCell; -import com.smartdevicelink.managers.screen.choiceset.PreloadChoicesOperation; import com.smartdevicelink.proxy.interfaces.ISdl; -import com.smartdevicelink.proxy.rpc.DisplayCapabilities; import com.smartdevicelink.proxy.rpc.ImageField; import com.smartdevicelink.proxy.rpc.TextField; +import com.smartdevicelink.proxy.rpc.WindowCapability; import com.smartdevicelink.proxy.rpc.enums.CharacterSet; import com.smartdevicelink.proxy.rpc.enums.FileType; import com.smartdevicelink.proxy.rpc.enums.ImageFieldName; +import com.smartdevicelink.proxy.rpc.enums.ImageType; import com.smartdevicelink.proxy.rpc.enums.TextFieldName; import com.smartdevicelink.test.Test; @@ -75,14 +74,14 @@ public class PreloadChoicesOperationTests extends AndroidTestCase2 { ImageField imageField = new ImageField(ImageFieldName.choiceImage, Arrays.asList(FileType.GRAPHIC_PNG, FileType.GRAPHIC_JPEG)); TextField textField = new TextField(TextFieldName.menuName, CharacterSet.CID1SET, 2, 2); - DisplayCapabilities displayCapabilities = new DisplayCapabilities(); - displayCapabilities.setGraphicSupported(true); - displayCapabilities.setImageFields(Collections.singletonList(imageField)); - displayCapabilities.setTextFields(Collections.singletonList(textField)); + WindowCapability windowCapability = new WindowCapability(); + windowCapability.setImageFields(Collections.singletonList(imageField)); + windowCapability.setImageTypeSupported(Arrays.asList(ImageType.STATIC, ImageType.DYNAMIC)); + windowCapability.setTextFields(Collections.singletonList(textField)); ISdl internalInterface = mock(ISdl.class); FileManager fileManager = mock(FileManager.class); - preloadChoicesOperation = new PreloadChoicesOperation(internalInterface, fileManager, displayCapabilities, true, cellsToPreload, null); + preloadChoicesOperation = new PreloadChoicesOperation(internalInterface, fileManager, windowCapability, true, cellsToPreload, null); } @Override @@ -91,13 +90,6 @@ public class PreloadChoicesOperationTests extends AndroidTestCase2 { } public void testHasTextFieldOfName(){ - - TextField textField = new TextField(); - textField.setName(TextFieldName.secondaryText); - - DisplayCapabilities capabilities = new DisplayCapabilities(); - capabilities.setTextFields(Collections.singletonList(textField)); - boolean test = preloadChoicesOperation.hasTextFieldOfName(TextFieldName.secondaryText); assertFalse(test); @@ -106,13 +98,6 @@ public class PreloadChoicesOperationTests extends AndroidTestCase2 { } public void testHasImageFieldOfName(){ - - ImageField imageField = new ImageField(); - imageField.setName(ImageFieldName.choiceImage); - - DisplayCapabilities capabilities = new DisplayCapabilities(); - capabilities.setImageFields(Collections.singletonList(imageField)); - boolean test = preloadChoicesOperation.hasImageFieldOfName(ImageFieldName.choiceImage); assertTrue(test); diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuManagerTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuManagerTests.java index fe20383a0..a5dfa9037 100644 --- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuManagerTests.java +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuManagerTests.java @@ -142,7 +142,7 @@ public class MenuManagerTests extends AndroidTestCase2 { assertNull(menuManager.menuConfiguration); assertNotNull(menuManager.hmiListener); assertNotNull(menuManager.commandListener); - assertNotNull(menuManager.displayListener); + assertNotNull(menuManager.onDisplaysCapabilityListener); } @@ -157,7 +157,7 @@ public class MenuManagerTests extends AndroidTestCase2 { assertNull(menuManager.menuCells); assertNull(menuManager.oldMenuCells); assertNull(menuManager.currentHMILevel); - assertNull(menuManager.displayCapabilities); + assertNull(menuManager.defaultMainWindowCapability); assertNull(menuManager.inProgressUpdate); assertNull(menuManager.waitingUpdateMenuCells); assertNull(menuManager.keepsNew); diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/video/VideoStreamManagerTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/video/VideoStreamManagerTests.java index f456b33b3..34a452f06 100644 --- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/video/VideoStreamManagerTests.java +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/video/VideoStreamManagerTests.java @@ -34,7 +34,6 @@ import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import java.nio.ByteBuffer; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/Test.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/Test.java index 793b2b035..0f87878e2 100644 --- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/Test.java +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/Test.java @@ -861,6 +861,7 @@ public class Test { GENERAL_PERMISSIONITEM.setRpcName(GENERAL_STRING); GENERAL_PERMISSIONITEM.setHMIPermissions(GENERAL_HMIPERMISSIONS); GENERAL_PERMISSIONITEM.setParameterPermissions(GENERAL_PARAMETERPERMISSIONS); + GENERAL_PERMISSIONITEM.setRequireEncryption(GENERAL_BOOLEAN); GENERAL_PERMISSIONITEM_LIST.add(GENERAL_PERMISSIONITEM); GENERAL_SYSTEMCAPABILITY.setSystemCapabilityType(GENERAL_SYSTEMCAPABILITYTYPE); @@ -1148,6 +1149,7 @@ public class Test { JSON_PERMISSIONITEM.put(PermissionItem.KEY_HMI_PERMISSIONS, JSON_HMIPERMISSIONS); JSON_PERMISSIONITEM.put(PermissionItem.KEY_PARAMETER_PERMISSIONS, JSON_PARAMETERPERMISSIONS); JSON_PERMISSIONITEM.put(PermissionItem.KEY_RPC_NAME, GENERAL_STRING); + JSON_PERMISSIONITEM.put(PermissionItem.KEY_REQUIRE_ENCRYPTION, GENERAL_BOOLEAN); JSON_PERMISSIONITEMS.put(JSON_PERMISSIONITEM); JSON_IMAGE.put(Image.KEY_IMAGE_TYPE, GENERAL_IMAGETYPE); diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/Validator.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/Validator.java index 965098c3f..09c0631b9 100644 --- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/Validator.java +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/Validator.java @@ -5,105 +5,7 @@ import com.smartdevicelink.protocol.enums.FrameData; import com.smartdevicelink.protocol.enums.FrameDataControlFrameType; import com.smartdevicelink.protocol.enums.FrameType; import com.smartdevicelink.protocol.enums.SessionType; -import com.smartdevicelink.proxy.rpc.AirbagStatus; -import com.smartdevicelink.proxy.rpc.AppServiceCapability; -import com.smartdevicelink.proxy.rpc.AppServiceManifest; -import com.smartdevicelink.proxy.rpc.AppServiceRecord; -import com.smartdevicelink.proxy.rpc.AppServicesCapabilities; -import com.smartdevicelink.proxy.rpc.AudioControlCapabilities; -import com.smartdevicelink.proxy.rpc.AudioControlData; -import com.smartdevicelink.proxy.rpc.AudioPassThruCapabilities; -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; -import com.smartdevicelink.proxy.rpc.DateTime; -import com.smartdevicelink.proxy.rpc.DeviceInfo; -import com.smartdevicelink.proxy.rpc.DeviceStatus; -import com.smartdevicelink.proxy.rpc.DisplayCapabilities; -import com.smartdevicelink.proxy.rpc.DisplayCapability; -import com.smartdevicelink.proxy.rpc.ECallInfo; -import com.smartdevicelink.proxy.rpc.EmergencyEvent; -import com.smartdevicelink.proxy.rpc.EqualizerSettings; -import com.smartdevicelink.proxy.rpc.FuelRange; -import com.smartdevicelink.proxy.rpc.GPSData; -import com.smartdevicelink.proxy.rpc.Grid; -import com.smartdevicelink.proxy.rpc.HMICapabilities; -import com.smartdevicelink.proxy.rpc.HMIPermissions; -import com.smartdevicelink.proxy.rpc.HMISettingsControlCapabilities; -import com.smartdevicelink.proxy.rpc.HMISettingsControlData; -import com.smartdevicelink.proxy.rpc.HeadLampStatus; -import com.smartdevicelink.proxy.rpc.Headers; -import com.smartdevicelink.proxy.rpc.Image; -import com.smartdevicelink.proxy.rpc.ImageField; -import com.smartdevicelink.proxy.rpc.ImageResolution; -import com.smartdevicelink.proxy.rpc.KeyboardProperties; -import com.smartdevicelink.proxy.rpc.LightCapabilities; -import com.smartdevicelink.proxy.rpc.LightControlCapabilities; -import com.smartdevicelink.proxy.rpc.LightControlData; -import com.smartdevicelink.proxy.rpc.LightState; -import com.smartdevicelink.proxy.rpc.LocationDetails; -import com.smartdevicelink.proxy.rpc.MassageCushionFirmness; -import com.smartdevicelink.proxy.rpc.MassageModeData; -import com.smartdevicelink.proxy.rpc.MediaServiceData; -import com.smartdevicelink.proxy.rpc.MediaServiceManifest; -import com.smartdevicelink.proxy.rpc.MenuParams; -import com.smartdevicelink.proxy.rpc.ModuleData; -import com.smartdevicelink.proxy.rpc.ModuleInfo; -import com.smartdevicelink.proxy.rpc.MyKey; -import com.smartdevicelink.proxy.rpc.NavigationCapability; -import com.smartdevicelink.proxy.rpc.NavigationInstruction; -import com.smartdevicelink.proxy.rpc.NavigationServiceData; -import com.smartdevicelink.proxy.rpc.NavigationServiceManifest; -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.RGBColor; -import com.smartdevicelink.proxy.rpc.RadioControlCapabilities; -import com.smartdevicelink.proxy.rpc.RadioControlData; -import com.smartdevicelink.proxy.rpc.RdsData; -import com.smartdevicelink.proxy.rpc.Rectangle; -import com.smartdevicelink.proxy.rpc.RemoteControlCapabilities; -import com.smartdevicelink.proxy.rpc.ScreenParams; -import com.smartdevicelink.proxy.rpc.SdlMsgVersion; -import com.smartdevicelink.proxy.rpc.SeatControlCapabilities; -import com.smartdevicelink.proxy.rpc.SeatControlData; -import com.smartdevicelink.proxy.rpc.SeatLocation; -import com.smartdevicelink.proxy.rpc.SeatMemoryAction; -import com.smartdevicelink.proxy.rpc.SingleTireStatus; -import com.smartdevicelink.proxy.rpc.SisData; -import com.smartdevicelink.proxy.rpc.SoftButton; -import com.smartdevicelink.proxy.rpc.SoftButtonCapabilities; -import com.smartdevicelink.proxy.rpc.StartTime; -import com.smartdevicelink.proxy.rpc.StationIDNumber; -import com.smartdevicelink.proxy.rpc.TTSChunk; -import com.smartdevicelink.proxy.rpc.Temperature; -import com.smartdevicelink.proxy.rpc.TemplateColorScheme; -import com.smartdevicelink.proxy.rpc.TemplateConfiguration; -import com.smartdevicelink.proxy.rpc.TextField; -import com.smartdevicelink.proxy.rpc.TireStatus; -import com.smartdevicelink.proxy.rpc.TouchCoord; -import com.smartdevicelink.proxy.rpc.TouchEvent; -import com.smartdevicelink.proxy.rpc.TouchEventCapabilities; -import com.smartdevicelink.proxy.rpc.Turn; -import com.smartdevicelink.proxy.rpc.VehicleDataResult; -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.WeatherAlert; -import com.smartdevicelink.proxy.rpc.WeatherData; -import com.smartdevicelink.proxy.rpc.WeatherServiceData; -import com.smartdevicelink.proxy.rpc.WeatherServiceManifest; -import com.smartdevicelink.proxy.rpc.WindowCapability; -import com.smartdevicelink.proxy.rpc.WindowTypeCapabilities; +import com.smartdevicelink.proxy.rpc.*; import com.smartdevicelink.proxy.rpc.enums.AppServiceType; import com.smartdevicelink.proxy.rpc.enums.DefrostZone; import com.smartdevicelink.proxy.rpc.enums.FileType; @@ -2447,6 +2349,10 @@ public class Validator{ return false; } + if(item1.getRequireEncryption() != item2.getRequireEncryption()) { + return false; + } + return true; } @@ -2842,6 +2748,24 @@ public class Validator{ return true; } + public static boolean validateDisplayCapabilityList(List<DisplayCapability> list1, List<DisplayCapability> list2) { + if (list1 == null || list2 == null) { + return false; + } + + if (list1.size() != list2.size()) { + return false; + } + + for (int i = 0; i < list1.size(); i++) { + if (!validateDisplayCapability(list1.get(i), list2.get(i))) { + return false; + } + } + + return true; + } + public static boolean validateDisplayCapability(DisplayCapability item1, DisplayCapability item2) { if (item1 == null) { return (item2 == null); diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/proxy/SystemCapabilityManagerTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/proxy/SystemCapabilityManagerTests.java index bb6488941..0d1fa04bf 100644 --- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/proxy/SystemCapabilityManagerTests.java +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/proxy/SystemCapabilityManagerTests.java @@ -18,6 +18,7 @@ import com.smartdevicelink.proxy.rpc.AppServicesCapabilities; import com.smartdevicelink.proxy.rpc.AudioPassThruCapabilities; import com.smartdevicelink.proxy.rpc.ButtonCapabilities; import com.smartdevicelink.proxy.rpc.DisplayCapabilities; +import com.smartdevicelink.proxy.rpc.DisplayCapability; import com.smartdevicelink.proxy.rpc.GetSystemCapabilityResponse; import com.smartdevicelink.proxy.rpc.HMICapabilities; import com.smartdevicelink.proxy.rpc.OnSystemCapabilityUpdated; @@ -25,15 +26,24 @@ import com.smartdevicelink.proxy.rpc.PhoneCapability; import com.smartdevicelink.proxy.rpc.PresetBankCapabilities; import com.smartdevicelink.proxy.rpc.RegisterAppInterfaceResponse; import com.smartdevicelink.proxy.rpc.SdlMsgVersion; +import com.smartdevicelink.proxy.rpc.SetDisplayLayoutResponse; import com.smartdevicelink.proxy.rpc.SoftButtonCapabilities; import com.smartdevicelink.proxy.rpc.SystemCapability; import com.smartdevicelink.proxy.rpc.VideoStreamingCapability; +import com.smartdevicelink.proxy.rpc.WindowCapability; +import com.smartdevicelink.proxy.rpc.WindowTypeCapabilities; import com.smartdevicelink.proxy.rpc.enums.AppServiceType; +import com.smartdevicelink.proxy.rpc.enums.DisplayType; import com.smartdevicelink.proxy.rpc.enums.HmiZoneCapabilities; +import com.smartdevicelink.proxy.rpc.enums.ImageType; +import com.smartdevicelink.proxy.rpc.enums.MediaClockFormat; +import com.smartdevicelink.proxy.rpc.enums.PredefinedWindows; import com.smartdevicelink.proxy.rpc.enums.PrerecordedSpeech; +import com.smartdevicelink.proxy.rpc.enums.Result; import com.smartdevicelink.proxy.rpc.enums.ServiceUpdateReason; import com.smartdevicelink.proxy.rpc.enums.SpeechCapabilities; import com.smartdevicelink.proxy.rpc.enums.SystemCapabilityType; +import com.smartdevicelink.proxy.rpc.enums.WindowType; import com.smartdevicelink.proxy.rpc.listeners.OnMultipleRequestListener; import com.smartdevicelink.proxy.rpc.listeners.OnRPCListener; import com.smartdevicelink.proxy.rpc.listeners.OnRPCNotificationListener; @@ -47,6 +57,7 @@ import com.smartdevicelink.test.utl.AppServiceFactory; import com.smartdevicelink.util.CorrelationIdGenerator; import com.smartdevicelink.util.Version; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; @@ -89,9 +100,58 @@ public class SystemCapabilityManagerTests extends AndroidTestCase2 { return systemCapabilityManager; } + private List<DisplayCapability> createDisplayCapabilityList(DisplayCapabilities display, List<ButtonCapabilities> button, List<SoftButtonCapabilities> softButton) { + WindowTypeCapabilities windowTypeCapabilities = new WindowTypeCapabilities(WindowType.MAIN, 1); + + DisplayCapability displayCapability = new DisplayCapability(); + displayCapability.setDisplayName(display != null ? display.getDisplayName() : null); + displayCapability.setWindowTypeSupported(Collections.singletonList(windowTypeCapabilities)); + + WindowCapability defaultWindowCapability = new WindowCapability(); + defaultWindowCapability.setWindowID(PredefinedWindows.DEFAULT_WINDOW.getValue()); + defaultWindowCapability.setButtonCapabilities(button); + defaultWindowCapability.setSoftButtonCapabilities(softButton); + + if (display == null) { + displayCapability.setWindowCapabilities(Collections.singletonList(defaultWindowCapability)); + return Collections.singletonList(displayCapability); + } + + defaultWindowCapability.setTemplatesAvailable(display.getTemplatesAvailable()); + defaultWindowCapability.setNumCustomPresetsAvailable(display.getNumCustomPresetsAvailable()); + defaultWindowCapability.setTextFields(display.getTextFields()); + defaultWindowCapability.setImageFields(display.getImageFields()); + ArrayList<ImageType> imageTypeSupported = new ArrayList<>(); + imageTypeSupported.add(ImageType.STATIC); + if (display.getGraphicSupported()) { + imageTypeSupported.add(ImageType.DYNAMIC); + } + defaultWindowCapability.setImageTypeSupported(imageTypeSupported); + + displayCapability.setWindowCapabilities(Collections.singletonList(defaultWindowCapability)); + return Collections.singletonList(displayCapability); + } + + private DisplayCapabilities createDisplayCapabilities(String displayName, WindowCapability defaultMainWindow) { + DisplayCapabilities convertedCapabilities = new DisplayCapabilities(); + convertedCapabilities.setDisplayType(DisplayType.SDL_GENERIC); //deprecated but it is mandatory... + convertedCapabilities.setDisplayName(displayName); + convertedCapabilities.setTextFields(defaultMainWindow.getTextFields()); + convertedCapabilities.setImageFields(defaultMainWindow.getImageFields()); + convertedCapabilities.setTemplatesAvailable(defaultMainWindow.getTemplatesAvailable()); + convertedCapabilities.setNumCustomPresetsAvailable(defaultMainWindow.getNumCustomPresetsAvailable()); + convertedCapabilities.setMediaClockFormats(new ArrayList<MediaClockFormat>()); // mandatory field but can be empty + convertedCapabilities.setGraphicSupported(defaultMainWindow.getImageTypeSupported().contains(ImageType.DYNAMIC)); + + return convertedCapabilities; + } + public void testParseRAI() { systemCapabilityManager = createSampleManager(); + List<DisplayCapability> displayCapabilityList = createDisplayCapabilityList(Test.GENERAL_DISPLAYCAPABILITIES, Test.GENERAL_BUTTONCAPABILITIES_LIST, Test.GENERAL_SOFTBUTTONCAPABILITIES_LIST); + assertTrue(Test.TRUE, + Validator.validateDisplayCapabilityList(displayCapabilityList, (List<DisplayCapability>) systemCapabilityManager.getCapability(SystemCapabilityType.DISPLAYS))); assertTrue(Test.TRUE, Validator.validateHMICapabilities(Test.GENERAL_HMICAPABILITIES, (HMICapabilities) systemCapabilityManager.getCapability(SystemCapabilityType.HMI))); assertTrue(Test.TRUE, @@ -189,7 +249,36 @@ public class SystemCapabilityManagerTests extends AndroidTestCase2 { scmRpcListener.onReceived(onSystemCapabilityUpdated); assertNotNull(systemCapabilityManager.getCapability(SystemCapabilityType.APP_SERVICES)); + } + + public void testOnSystemCapabilityUpdatedForDISPLAYS() { + InternalSDLInterface iSDL = new InternalSDLInterface(); + SystemCapabilityManager systemCapabilityManager = createSampleManager(iSDL); + OnRPCListener scmRpcListener = iSDL.rpcListeners.get(FunctionID.ON_SYSTEM_CAPABILITY_UPDATED.getId()).get(0); + assertNotNull(scmRpcListener); + + assertNotNull(systemCapabilityManager.getCapability(SystemCapabilityType.DISPLAYS)); + assertNotNull(systemCapabilityManager.getCapability(SystemCapabilityType.DISPLAY)); + + List<DisplayCapability> newCaps = createDisplayCapabilityList(Test.GENERAL_DISPLAYCAPABILITIES, Test.GENERAL_BUTTONCAPABILITIES_LIST, Test.GENERAL_SOFTBUTTONCAPABILITIES_LIST);; + + SystemCapability systemCapability = new SystemCapability(); + systemCapability.setSystemCapabilityType(SystemCapabilityType.DISPLAYS); + systemCapability.setCapabilityForType(SystemCapabilityType.DISPLAYS, newCaps); + + OnSystemCapabilityUpdated onSystemCapabilityUpdated = new OnSystemCapabilityUpdated(); + onSystemCapabilityUpdated.setSystemCapability(systemCapability); + + scmRpcListener.onReceived(onSystemCapabilityUpdated); + List<DisplayCapability> appliedCaps = (List<DisplayCapability>)systemCapabilityManager.getCapability(SystemCapabilityType.DISPLAYS); + assertNotNull(appliedCaps); + assertTrue(Validator.validateDisplayCapabilityList(newCaps, appliedCaps)); + + DisplayCapabilities appliedConvertedCaps = (DisplayCapabilities)systemCapabilityManager.getCapability(SystemCapabilityType.DISPLAY); + assertNotNull(appliedConvertedCaps); + DisplayCapabilities testConvertedCaps = createDisplayCapabilities(newCaps.get(0).getDisplayName(), newCaps.get(0).getWindowCapabilities().get(0)); + assertTrue(Validator.validateDisplayCapabilities(appliedConvertedCaps, testConvertedCaps)); } public void testOnSystemCapabilityUpdated(){ @@ -329,6 +418,46 @@ public class SystemCapabilityManagerTests extends AndroidTestCase2 { assertEquals(phoneCapability, phoneCapabilityUpdated); } + public void testOnSetDisplayLayout() { + InternalSDLInterface iSDL = new InternalSDLInterface(); + SystemCapabilityManager systemCapabilityManager = createSampleManager(iSDL); + OnRPCListener dlRpcListener = iSDL.rpcListeners.get(FunctionID.SET_DISPLAY_LAYOUT.getId()).get(0); + assertNotNull(dlRpcListener); + + SetDisplayLayoutResponse newLayout = new SetDisplayLayoutResponse(); + newLayout.setDisplayCapabilities(Test.GENERAL_DISPLAYCAPABILITIES); + newLayout.setButtonCapabilities(Test.GENERAL_BUTTONCAPABILITIES_LIST); + newLayout.setSoftButtonCapabilities(Test.GENERAL_SOFTBUTTONCAPABILITIES_LIST); + newLayout.setPresetBankCapabilities(Test.GENERAL_PRESETBANKCAPABILITIES); + newLayout.setSuccess(true); + newLayout.setResultCode(Result.SUCCESS); + + dlRpcListener.onReceived(newLayout); + + + DisplayCapabilities appliedCaps = (DisplayCapabilities)systemCapabilityManager.getCapability(SystemCapabilityType.DISPLAY); + assertNotNull(appliedCaps); + assertTrue(Validator.validateDisplayCapabilities(newLayout.getDisplayCapabilities(), appliedCaps)); + + List<DisplayCapability> convertedCaps = (List<DisplayCapability>)systemCapabilityManager.getCapability(SystemCapabilityType.DISPLAYS); + assertNotNull(convertedCaps); + List<DisplayCapability> testCaps = createDisplayCapabilityList(newLayout.getDisplayCapabilities(), newLayout.getButtonCapabilities(), newLayout.getSoftButtonCapabilities()); + assertTrue(Validator.validateDisplayCapabilityList(convertedCaps, testCaps)); + + WindowCapability matchWindowCapability = testCaps.get(0).getWindowCapabilities().get(0); + WindowCapability testWindowCapability = systemCapabilityManager.getDefaultMainWindowCapability(); + assertTrue(Validator.validateWindowCapability(matchWindowCapability, testWindowCapability)); + assertNull(systemCapabilityManager.getWindowCapability(42)); + } + + public void testManagerBeforeDisplayUpdate() { + InternalSDLInterface iSDL = new InternalSDLInterface(); + SystemCapabilityManager systemCapabilityManager = new SystemCapabilityManager(iSDL); + assertNull(systemCapabilityManager.getDefaultMainWindowCapability()); + assertNull(systemCapabilityManager.getWindowCapability(PredefinedWindows.DEFAULT_WINDOW.getValue())); + assertNull(systemCapabilityManager.getWindowCapability(PredefinedWindows.PRIMARY_WIDGET.getValue())); + } + private class InternalSDLInterface implements ISdl{ private final Object RPC_LISTENER_LOCK = new Object(); SparseArray<CopyOnWriteArrayList<OnRPCListener>> rpcListeners = new SparseArray<>(); @@ -465,6 +594,8 @@ public class SystemCapabilityManagerTests extends AndroidTestCase2 { @Override public void startAudioService(boolean encrypted){} + @Override + public void startRPCEncryption() {} } diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/DisplayCapabilitiesTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/DisplayCapabilitiesTests.java index 28d7e1460..4f0256f79 100644 --- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/DisplayCapabilitiesTests.java +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/DisplayCapabilitiesTests.java @@ -7,7 +7,6 @@ import com.smartdevicelink.proxy.rpc.ScreenParams; import com.smartdevicelink.proxy.rpc.TextField; import com.smartdevicelink.proxy.rpc.enums.DisplayType; import com.smartdevicelink.proxy.rpc.enums.MediaClockFormat; -import com.smartdevicelink.proxy.rpc.enums.MenuLayout; import com.smartdevicelink.test.JsonUtils; import com.smartdevicelink.test.Test; import com.smartdevicelink.test.Validator; diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/PermissionItemTest.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/PermissionItemTest.java index 5fc144fea..491803317 100644 --- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/PermissionItemTest.java +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/PermissionItemTest.java @@ -29,6 +29,7 @@ public class PermissionItemTest extends TestCase { msg.setRpcName(Test.GENERAL_STRING); msg.setHMIPermissions(Test.GENERAL_HMIPERMISSIONS); msg.setParameterPermissions(Test.GENERAL_PARAMETERPERMISSIONS); + msg.setRequireEncryption(Test.GENERAL_BOOLEAN); } /** @@ -39,11 +40,13 @@ public class PermissionItemTest extends TestCase { String rpcName = msg.getRpcName(); HMIPermissions hmiPermissions = msg.getHMIPermissions(); ParameterPermissions parameterPermissions = msg.getParameterPermissions(); + boolean isEncryptionRequired = msg.getRequireEncryption(); // Valid Tests assertEquals(Test.MATCH, Test.GENERAL_STRING, rpcName); assertTrue(Test.TRUE, Validator.validateHmiPermissions(Test.GENERAL_HMIPERMISSIONS, hmiPermissions)); assertTrue(Test.TRUE, Validator.validateParameterPermissions(Test.GENERAL_PARAMETERPERMISSIONS, parameterPermissions)); + assertEquals(Test.MATCH, Test.GENERAL_BOOLEAN, isEncryptionRequired); // Invalid/Null Tests PermissionItem msg = new PermissionItem(); @@ -52,6 +55,7 @@ public class PermissionItemTest extends TestCase { assertNull(Test.NULL, msg.getRpcName()); assertNull(Test.NULL, msg.getHMIPermissions()); assertNull(Test.NULL, msg.getParameterPermissions()); + assertNull(Test.NULL, msg.getRequireEncryption()); } public void testJson() { @@ -61,6 +65,7 @@ public class PermissionItemTest extends TestCase { reference.put(PermissionItem.KEY_RPC_NAME, Test.GENERAL_STRING); reference.put(PermissionItem.KEY_HMI_PERMISSIONS, Test.JSON_HMIPERMISSIONS); reference.put(PermissionItem.KEY_PARAMETER_PERMISSIONS, Test.JSON_PARAMETERPERMISSIONS); + reference.put(PermissionItem.KEY_REQUIRE_ENCRYPTION, Test.GENERAL_BOOLEAN); JSONObject underTest = msg.serializeJSON(); assertEquals(Test.MATCH, reference.length(), underTest.length()); @@ -73,6 +78,8 @@ public class PermissionItemTest extends TestCase { assertTrue(Test.TRUE, Validator.validateStringList(JsonUtils.readStringListFromJsonObject(reference, key), JsonUtils.readStringListFromJsonObject(underTest, key))); } else if (key.equals(PermissionItem.KEY_PARAMETER_PERMISSIONS)) { assertTrue(Test.TRUE, Validator.validateStringList(JsonUtils.readStringListFromJsonObject(reference, key), JsonUtils.readStringListFromJsonObject(underTest, key))); + } else if (key.equals(PermissionItem.KEY_REQUIRE_ENCRYPTION)) { + assertEquals(Test.MATCH, JsonUtils.readBooleanFromJsonObject(reference, key), JsonUtils.readBooleanFromJsonObject(underTest, key)); } else { assertEquals(Test.MATCH, JsonUtils.readObjectFromJsonObject(reference, key), JsonUtils.readObjectFromJsonObject(underTest, key)); } diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/SystemCapabilityTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/SystemCapabilityTests.java index c6a3cfa0e..203f72060 100644 --- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/SystemCapabilityTests.java +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/SystemCapabilityTests.java @@ -13,10 +13,13 @@ 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.JSONArray; import org.json.JSONException; import org.json.JSONObject; + import java.util.Hashtable; import java.util.Iterator; import java.util.List; diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/TemplateConfigurationTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/TemplateConfigurationTests.java index fe505218c..4fc3744be 100644 --- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/TemplateConfigurationTests.java +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/TemplateConfigurationTests.java @@ -6,9 +6,12 @@ import com.smartdevicelink.proxy.rpc.TemplateConfiguration; 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; diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/WindowCapabilityTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/WindowCapabilityTests.java index 973c6e0b8..550231452 100644 --- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/WindowCapabilityTests.java +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/WindowCapabilityTests.java @@ -11,7 +11,9 @@ import com.smartdevicelink.proxy.rpc.enums.MenuLayout; 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; diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/WindowTypeCapabilitiesTest.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/WindowTypeCapabilitiesTest.java index 4b9c767e3..539737554 100644 --- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/WindowTypeCapabilitiesTest.java +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/WindowTypeCapabilitiesTest.java @@ -4,9 +4,12 @@ import com.smartdevicelink.proxy.rpc.WindowTypeCapabilities; import com.smartdevicelink.proxy.rpc.enums.WindowType; 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; public class WindowTypeCapabilitiesTest extends TestCase { diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/PredefinedWindowsTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/PredefinedWindowsTests.java index 3b37070b7..eae294933 100644 --- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/PredefinedWindowsTests.java +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/PredefinedWindowsTests.java @@ -1,7 +1,9 @@ package com.smartdevicelink.test.rpc.enums; import com.smartdevicelink.proxy.rpc.enums.PredefinedWindows; + import junit.framework.TestCase; + import java.util.ArrayList; import java.util.Arrays; import java.util.List; diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/ResultTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/ResultTests.java index 992f4e54e..f3b374b4c 100644 --- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/ResultTests.java +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/ResultTests.java @@ -88,6 +88,8 @@ public class ResultTests extends TestCase { Result enumReadOnly = Result.valueForString(example); example = "CORRUPTED_DATA"; Result enumCorruptData = Result.valueForString(example); + example = "ENCRYPTION_NEEDED"; + Result enumEncryptionRequired = Result.valueForString(example); assertNotNull("SUCCESS returned null", enumSuccess); assertNotNull("INVALID_DATA returned null", enumInvalidData); @@ -124,6 +126,7 @@ public class ResultTests extends TestCase { assertNotNull("DATA_NOT_AVAILABLE returned null", enumDataNotAvailable); assertNotNull("READ_ONLY returned null", enumReadOnly); assertNotNull("CORRUPTED_DATA", enumCorruptData); + assertNotNull("ENCRYPTION_NEEDED", enumEncryptionRequired); } /** @@ -196,6 +199,7 @@ public class ResultTests extends TestCase { enumTestList.add(Result.DATA_NOT_AVAILABLE); enumTestList.add(Result.READ_ONLY); enumTestList.add(Result.CORRUPTED_DATA); + enumTestList.add(Result.ENCRYPTION_NEEDED); assertTrue("Enum value list does not match enum class list", enumValueList.containsAll(enumTestList) && enumTestList.containsAll(enumValueList)); diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/WindowTypeTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/WindowTypeTests.java index b6e26f9df..c3c78c870 100644 --- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/WindowTypeTests.java +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/WindowTypeTests.java @@ -1,7 +1,9 @@ package com.smartdevicelink.test.rpc.enums; import com.smartdevicelink.proxy.rpc.enums.WindowType; + import junit.framework.TestCase; + import java.util.ArrayList; import java.util.Arrays; import java.util.List; diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/notifications/OnPermissionsChangeTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/notifications/OnPermissionsChangeTests.java index e390fc599..5064753c6 100644 --- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/notifications/OnPermissionsChangeTests.java +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/notifications/OnPermissionsChangeTests.java @@ -24,6 +24,7 @@ public class OnPermissionsChangeTests extends BaseRpcTests{ OnPermissionsChange msg = new OnPermissionsChange(); msg.setPermissionItem(Test.GENERAL_PERMISSIONITEM_LIST); + msg.setRequireEncryption(Test.GENERAL_BOOLEAN); return msg; } @@ -44,6 +45,7 @@ public class OnPermissionsChangeTests extends BaseRpcTests{ try{ result.put(OnPermissionsChange.KEY_PERMISSION_ITEM, Test.JSON_PERMISSIONITEMS); + result.put(OnPermissionsChange.KEY_REQUIRE_ENCRYPTION, Test.GENERAL_BOOLEAN); }catch(JSONException e){ fail(Test.JSON_FAIL); } @@ -57,17 +59,19 @@ public class OnPermissionsChangeTests extends BaseRpcTests{ public void testRpcValues () { // Test Values List<PermissionItem> data = ( (OnPermissionsChange) msg ).getPermissionItem(); - + boolean isRequired = ((OnPermissionsChange)msg).getRequireEncryption(); // Valid Tests assertEquals(Test.MATCH, Test.GENERAL_PERMISSIONITEM_LIST.size(), data.size()); for(int i=0; i<data.size(); i++){ assertTrue(Test.TRUE, Validator.validatePermissionItem(Test.GENERAL_PERMISSIONITEM_LIST.get(i), data.get(i))); } + assertEquals(Test.MATCH, Test.GENERAL_BOOLEAN, isRequired); // Invalid/Null Tests OnPermissionsChange msg = new OnPermissionsChange(); assertNotNull(Test.NOT_NULL, msg); testNullBase(msg); + assertNull(Test.NULL, msg.getRequireEncryption()); assertNull(Test.NULL, msg.getPermissionItem()); } diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/requests/CreateWindowTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/requests/CreateWindowTests.java index dd8264caf..267be01f1 100644 --- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/requests/CreateWindowTests.java +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/requests/CreateWindowTests.java @@ -9,8 +9,10 @@ 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; /** diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/requests/DeleteWindowTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/requests/DeleteWindowTests.java index 3602d2d62..48080615f 100644 --- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/requests/DeleteWindowTests.java +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/requests/DeleteWindowTests.java @@ -8,8 +8,10 @@ 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; /** diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/requests/GetInteriorVehicleDataConsentTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/requests/GetInteriorVehicleDataConsentTests.java index d736e5176..15a902a84 100644 --- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/requests/GetInteriorVehicleDataConsentTests.java +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/requests/GetInteriorVehicleDataConsentTests.java @@ -10,7 +10,6 @@ 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; diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/responses/CloseApplicationResponseTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/responses/CloseApplicationResponseTests.java index dac0190c7..eb56a5293 100644 --- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/responses/CloseApplicationResponseTests.java +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/responses/CloseApplicationResponseTests.java @@ -38,7 +38,6 @@ import com.smartdevicelink.marshal.JsonRPCMarshaller; import com.smartdevicelink.protocol.enums.FunctionID; import com.smartdevicelink.proxy.RPCMessage; import com.smartdevicelink.proxy.rpc.CloseApplicationResponse; -import com.smartdevicelink.proxy.rpc.UnregisterAppInterfaceResponse; import com.smartdevicelink.test.BaseRpcTests; import com.smartdevicelink.test.JsonUtils; import com.smartdevicelink.test.Test; diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/responses/CreateWindowResponseTest.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/responses/CreateWindowResponseTest.java index 6bbdb1e6b..8099a9ce7 100644 --- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/responses/CreateWindowResponseTest.java +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/responses/CreateWindowResponseTest.java @@ -8,8 +8,10 @@ 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; /** diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/responses/DeleteWindowResponseTest.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/responses/DeleteWindowResponseTest.java index 145f432f3..01bcd1491 100644 --- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/responses/DeleteWindowResponseTest.java +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/responses/DeleteWindowResponseTest.java @@ -8,8 +8,10 @@ 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; /** diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/SdlConnection/SdlSession.java b/android/sdl_android/src/main/java/com/smartdevicelink/SdlConnection/SdlSession.java index 58fa8d576..33f9d885e 100644 --- a/android/sdl_android/src/main/java/com/smartdevicelink/SdlConnection/SdlSession.java +++ b/android/sdl_android/src/main/java/com/smartdevicelink/SdlConnection/SdlSession.java @@ -107,6 +107,7 @@ public class SdlSession implements ISdlConnectionListener, IHeartbeatMonitorList StreamPacketizer mAudioPacketizer = null;
SdlEncoder mSdlEncoder = null;
VirtualDisplayEncoder virtualDisplayEncoder = null;
+ boolean sdlSecurityInitializing = false;
public static SdlSession createSession(byte wiproVersion, ISdlConnectionListener listener, BaseTransportConfig btConfig) {
@@ -450,9 +451,12 @@ public class SdlSession implements ISdlConnectionListener, IHeartbeatMonitorList if (!serviceList.contains(serviceType))
serviceList.add(serviceType);
- sdlSecurity.initialize();
+ if (!sdlSecurityInitializing) {
+ sdlSecurityInitializing = true;
+ sdlSecurity.initialize();
+ return;
+ }
}
- return;
}
_sdlConnection.startService(serviceType, sessionID, isEncrypted);
}
diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/SdlConnection/SdlSession2.java b/android/sdl_android/src/main/java/com/smartdevicelink/SdlConnection/SdlSession2.java index b9b9a5e40..14258cbfe 100644 --- a/android/sdl_android/src/main/java/com/smartdevicelink/SdlConnection/SdlSession2.java +++ b/android/sdl_android/src/main/java/com/smartdevicelink/SdlConnection/SdlSession2.java @@ -154,9 +154,12 @@ public class SdlSession2 extends SdlSession implements ISdlProtocol{ if (!serviceList.contains(serviceType)) serviceList.add(serviceType); - sdlSecurity.initialize(); + if (!sdlSecurityInitializing) { + sdlSecurityInitializing = true; + sdlSecurity.initialize(); + return; + } } - return; } sdlProtocol.startService(serviceType, sessionID, isEncrypted); } diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/managers/SdlManager.java b/android/sdl_android/src/main/java/com/smartdevicelink/managers/SdlManager.java index a12b5d154..d36106c13 100644 --- a/android/sdl_android/src/main/java/com/smartdevicelink/managers/SdlManager.java +++ b/android/sdl_android/src/main/java/com/smartdevicelink/managers/SdlManager.java @@ -120,6 +120,7 @@ public class SdlManager extends BaseSdlManager{ private SdlManagerListener managerListener; private List<Class<? extends SdlSecurityBase>> sdlSecList; private LockScreenConfig lockScreenConfig; + private ServiceEncryptionListener serviceEncryptionListener; // Managers private PermissionManager permissionManager; @@ -131,7 +132,7 @@ public class SdlManager extends BaseSdlManager{ // Initialize proxyBridge with anonymous lifecycleListener - private final ProxyBridge proxyBridge= new ProxyBridge(new ProxyBridge.LifecycleListener() { + private final ProxyBridge proxyBridge = new ProxyBridge(new ProxyBridge.LifecycleListener() { @Override public void onProxyConnected() { DebugTool.logInfo("Proxy is connected. Now initializing."); @@ -680,7 +681,7 @@ public class SdlManager extends BaseSdlManager{ proxy.setMinimumProtocolVersion(minimumProtocolVersion); proxy.setMinimumRPCVersion(minimumRPCVersion); if (sdlSecList != null && !sdlSecList.isEmpty()) { - proxy.setSdlSecurityClassList(sdlSecList); + proxy.setSdlSecurity(sdlSecList, serviceEncryptionListener); } //Setup the notification queue initNotificationQueue(); @@ -900,6 +901,13 @@ public class SdlManager extends BaseSdlManager{ } } + @Override + public void startRPCEncryption() { + if (proxy != null) { + proxy.startProtectedRPCService(); + } + } + }; @@ -1097,12 +1105,24 @@ public class SdlManager extends BaseSdlManager{ * Sets the Security library * @param secList The list of security class(es) */ + @Deprecated public Builder setSdlSecurity(List<Class<? extends SdlSecurityBase>> secList) { sdlManager.sdlSecList = secList; return this; } /** + * Sets the security libraries and a callback to notify caller when there is update to encryption service + * @param secList The list of security class(es) + * @param listener The callback object + */ + public Builder setSdlSecurity(@NonNull List<Class<? extends SdlSecurityBase>> secList, ServiceEncryptionListener listener) { + sdlManager.sdlSecList = secList; + sdlManager.serviceEncryptionListener = listener; + return this; + } + + /** * Set the SdlManager Listener * @param listener the listener */ @@ -1173,4 +1193,13 @@ public class SdlManager extends BaseSdlManager{ return sdlManager; } } + + /** + * Start a secured RPC service + */ + public void startRPCEncryption() { + if (proxy != null) { + proxy.startProtectedRPCService(); + } + } } diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/proxy/SdlProxyBase.java b/android/sdl_android/src/main/java/com/smartdevicelink/proxy/SdlProxyBase.java index ec6c751b8..30ebb6cb5 100644 --- a/android/sdl_android/src/main/java/com/smartdevicelink/proxy/SdlProxyBase.java +++ b/android/sdl_android/src/main/java/com/smartdevicelink/proxy/SdlProxyBase.java @@ -61,6 +61,7 @@ import com.smartdevicelink.encoder.VirtualDisplayEncoder; import com.smartdevicelink.exception.SdlException;
import com.smartdevicelink.exception.SdlExceptionCause;
import com.smartdevicelink.haptic.HapticInterfaceManager;
+import com.smartdevicelink.managers.ServiceEncryptionListener;
import com.smartdevicelink.managers.lifecycle.RpcConverter;
import com.smartdevicelink.marshal.JsonRPCMarshaller;
import com.smartdevicelink.protocol.ProtocolMessage;
@@ -149,8 +150,10 @@ import java.net.ProtocolException; import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
+import java.util.Set;
import java.util.Vector;
import java.util.concurrent.Callable;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -307,6 +310,9 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> private Version minimumProtocolVersion;
private Version minimumRPCVersion;
+ private Set<String> encryptionRequiredRPCs = new HashSet<>();
+ private boolean rpcSecuredServiceStarted;
+ private ServiceEncryptionListener serviceEncryptionListener;
// Interface broker
private SdlInterfaceBroker _interfaceBroker = null;
@@ -504,6 +510,11 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> AudioStreamingParams params) {
return SdlProxyBase.this.startAudioStream(isEncrypted, codec, params);
}
+
+ @Override
+ public void startRPCEncryption() {
+ SdlProxyBase.this.startProtectedRPCService();
+ }
};
private void notifyPutFileStreamError(Exception e, String info)
@@ -1022,8 +1033,14 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _outgoingProxyMessageDispatcher = null;
}
throw e;
- }
-
+ }
+
+ addOnRPCNotificationListener(FunctionID.ON_PERMISSIONS_CHANGE, onPermissionsChangeListener);
+ this._internalInterface.addServiceListener(SessionType.RPC, securedServiceListener);
+ this._internalInterface.addServiceListener(SessionType.NAV, securedServiceListener);
+ this._internalInterface.addServiceListener(SessionType.PCM, securedServiceListener);
+
+
// Trace that ctor has fired
SdlTrace.logProxyEvent("SdlProxy Created, instanceID=" + this.toString(), SDL_LIB_TRACE_KEY);
}
@@ -1791,6 +1808,9 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> }
_proxyDisposed = true;
+ rpcSecuredServiceStarted = false;
+ encryptionRequiredRPCs.clear();
+ serviceEncryptionListener = null;
SdlTrace.logProxyEvent("Application called dispose() method.", SDL_LIB_TRACE_KEY);
@@ -2105,7 +2125,89 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> _proxyListener.onError("Proxy callback dispatcher is down. Proxy instance is invalid.", e);
}
/************* END Functions used by the Message Dispatching Queues ****************/
-
+
+
+ private OnRPCNotificationListener onPermissionsChangeListener = new OnRPCNotificationListener() {
+ @Override
+ public void onNotified(RPCNotification notification) {
+ List<PermissionItem> permissionItems = ((OnPermissionsChange) notification).getPermissionItem();
+ Boolean requireEncryptionAppLevel = ((OnPermissionsChange) notification).getRequireEncryption();
+ encryptionRequiredRPCs.clear();
+ if (requireEncryptionAppLevel == null || requireEncryptionAppLevel) {
+ if (permissionItems != null && !permissionItems.isEmpty()) {
+ for (PermissionItem permissionItem : permissionItems) {
+ if (permissionItem != null && Boolean.TRUE.equals(permissionItem.getRequireEncryption())) {
+ String rpcName = permissionItem.getRpcName();
+ if (rpcName != null) {
+ encryptionRequiredRPCs.add(rpcName);
+ }
+ }
+ }
+ }
+ checkStatusAndInitSecuredService();
+ }
+ }
+ };
+
+ private ISdlServiceListener securedServiceListener = new ISdlServiceListener() {
+ @Override
+ public void onServiceStarted(SdlSession session, SessionType type, boolean isEncrypted) {
+ if(SessionType.RPC.equals(type)){
+ rpcSecuredServiceStarted = isEncrypted;
+ }
+ if (serviceEncryptionListener != null) {
+ serviceEncryptionListener.onEncryptionServiceUpdated(type, isEncrypted, null);
+ }
+ DebugTool.logInfo("onServiceStarted, session Type: " + type.getName() + ", isEncrypted: " + isEncrypted);
+ }
+
+ @Override
+ public void onServiceEnded(SdlSession session, SessionType type) {
+ if (SessionType.RPC.equals(type)) {
+ rpcSecuredServiceStarted = false;
+ }
+ if (serviceEncryptionListener != null) {
+ serviceEncryptionListener.onEncryptionServiceUpdated(type, false, null);
+ }
+ DebugTool.logInfo("onServiceEnded, session Type: " + type.getName());
+ }
+
+ @Override
+ public void onServiceError(SdlSession session, SessionType type, String reason) {
+ if (SessionType.RPC.equals(type)) {
+ rpcSecuredServiceStarted = false;
+ }
+ if (serviceEncryptionListener != null) {
+ serviceEncryptionListener.onEncryptionServiceUpdated(type, false, "onServiceError: " + reason);
+ }
+ DebugTool.logError("onServiceError, session Type: " + type.getName() + ", reason: " + reason);
+ }
+ };
+
+ /**
+ * Checks if an RPC requires encryption
+ *
+ * @param rpcName the rpc name (FunctionID) to check
+ * @return true if the given RPC requires encryption; false, otherwise
+ */
+ public boolean getRPCRequiresEncryption(@NonNull FunctionID rpcName) {
+ return encryptionRequiredRPCs.contains(rpcName.toString());
+ }
+
+ /**
+ * Gets the encryption requirement
+ * @return true if encryption is required; false otherwise
+ */
+ public boolean getRequiresEncryption() {
+ return !encryptionRequiredRPCs.isEmpty();
+ }
+
+ private void checkStatusAndInitSecuredService() {
+ if ((_hmiLevel != null && _hmiLevel != HMILevel.HMI_NONE) && getRequiresEncryption() && !rpcSecuredServiceStarted) {
+ startProtectedRPCService();
+ }
+ }
+
// Private sendRPCMessagePrivate method. All RPCMessages are funneled through this method after error checking.
protected void sendRPCMessagePrivate(RPCMessage message) throws SdlException {
try {
@@ -2149,8 +2251,24 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> pm.setMessageType(MessageType.RPC);
pm.setSessionType(SessionType.RPC);
pm.setFunctionID(FunctionID.getFunctionId(message.getFunctionName()));
- pm.setPayloadProtected(message.isPayloadProtected());
-
+ if (rpcSecuredServiceStarted && getRPCRequiresEncryption(message.getFunctionID())) {
+ pm.setPayloadProtected(true);
+ } else {
+ pm.setPayloadProtected(message.isPayloadProtected());
+ }
+ if (pm.getPayloadProtected() && (!rpcSecuredServiceStarted || !rpcProtectedStartResponse)){
+ String errorInfo = "Trying to send an encrypted message and there is no secured service";
+ if (message.getMessageType().equals((RPCMessage.KEY_REQUEST))) {
+ RPCRequest request = (RPCRequest) message;
+ OnRPCResponseListener listener = ((RPCRequest) message).getOnRPCResponseListener();
+ if (listener != null) {
+ listener.onError(request.getCorrelationID(), Result.ABORTED, errorInfo);
+ }
+ }
+ DebugTool.logWarning(errorInfo);
+ return;
+ }
+
if (sdlSession != null) {
pm.setSessionID(sdlSession.getSessionId());
}
@@ -3856,6 +3974,9 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> if (msg.getHmiLevel() == HMILevel.HMI_FULL) firstTimeFull = false;
_hmiLevel = msg.getHmiLevel();
+ if (_hmiLevel != HMILevel.HMI_NONE) {
+ checkStatusAndInitSecuredService();
+ }
_audioStreamingState = msg.getAudioStreamingState();
msg.format(rpcSpecVersion, true);
@@ -7949,11 +8070,22 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> return sdlSession.getCurrentTransportType();
}
-
+
+ @Deprecated
public void setSdlSecurityClassList(List<Class<? extends SdlSecurityBase>> list) {
_secList = list;
- }
-
+ }
+
+ /**
+ * Sets the security libraries and a callback to notify caller when there is update to encryption service
+ * @param secList The list of security class(es)
+ * @param listener The callback object
+ */
+ public void setSdlSecurity(@NonNull List<Class<? extends SdlSecurityBase>> secList, ServiceEncryptionListener listener) {
+ _secList = secList;
+ serviceEncryptionListener = listener;
+ }
+
private void setSdlSecurity(SdlSecurityBase sec) {
if (sdlSession != null)
{
diff --git a/android/sdl_android/src/test/java/com/smartdevicelink/streaming/video/VideoStreamingParametersTest.java b/android/sdl_android/src/test/java/com/smartdevicelink/streaming/video/VideoStreamingParametersTest.java index 9088e716d..f08bada0f 100644 --- a/android/sdl_android/src/test/java/com/smartdevicelink/streaming/video/VideoStreamingParametersTest.java +++ b/android/sdl_android/src/test/java/com/smartdevicelink/streaming/video/VideoStreamingParametersTest.java @@ -37,7 +37,7 @@ import com.smartdevicelink.proxy.rpc.VideoStreamingCapability; import org.junit.Before; import org.junit.Test; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; public class VideoStreamingParametersTest { private VideoStreamingParameters params; diff --git a/base/src/main/java/com/smartdevicelink/managers/ServiceEncryptionListener.java b/base/src/main/java/com/smartdevicelink/managers/ServiceEncryptionListener.java new file mode 100644 index 000000000..fedefdec2 --- /dev/null +++ b/base/src/main/java/com/smartdevicelink/managers/ServiceEncryptionListener.java @@ -0,0 +1,10 @@ +package com.smartdevicelink.managers; + +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +import com.smartdevicelink.protocol.enums.SessionType; + +public interface ServiceEncryptionListener { + void onEncryptionServiceUpdated(@NonNull SessionType serviceType, boolean isServiceEncrypted, @Nullable String error); +}
\ No newline at end of file diff --git a/base/src/main/java/com/smartdevicelink/managers/lifecycle/BaseEncryptionLifecycleManager.java b/base/src/main/java/com/smartdevicelink/managers/lifecycle/BaseEncryptionLifecycleManager.java new file mode 100644 index 000000000..808f4b0cd --- /dev/null +++ b/base/src/main/java/com/smartdevicelink/managers/lifecycle/BaseEncryptionLifecycleManager.java @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2019 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. + */ + +package com.smartdevicelink.managers.lifecycle; + +import android.support.annotation.NonNull; +import com.smartdevicelink.SdlConnection.SdlSession; +import com.smartdevicelink.managers.ServiceEncryptionListener; +import com.smartdevicelink.protocol.enums.FunctionID; +import com.smartdevicelink.protocol.enums.SessionType; +import com.smartdevicelink.proxy.RPCNotification; +import com.smartdevicelink.proxy.interfaces.ISdl; +import com.smartdevicelink.proxy.interfaces.ISdlServiceListener; +import com.smartdevicelink.proxy.rpc.OnHMIStatus; +import com.smartdevicelink.proxy.rpc.OnPermissionsChange; +import com.smartdevicelink.proxy.rpc.PermissionItem; +import com.smartdevicelink.proxy.rpc.enums.HMILevel; +import com.smartdevicelink.proxy.rpc.listeners.OnRPCNotificationListener; +import com.smartdevicelink.util.DebugTool; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +abstract class BaseEncryptionLifecycleManager { + private ISdl internalInterface; + private ServiceEncryptionListener serviceEncryptionListener; + private HMILevel currentHMILevel; + private Set<String> encryptionRequiredRPCs = new HashSet<>(); + private boolean rpcSecuredServiceStarted; + + BaseEncryptionLifecycleManager(@NonNull ISdl isdl, ServiceEncryptionListener listener) { + internalInterface = isdl; + serviceEncryptionListener = listener; + rpcSecuredServiceStarted = false; + + OnRPCNotificationListener onHMIStatusListener = new OnRPCNotificationListener() { + @Override + public void onNotified(RPCNotification notification) { + OnHMIStatus onHMIStatus = (OnHMIStatus) notification; + currentHMILevel = onHMIStatus.getHmiLevel(); + checkStatusAndInitSecuredService(); + } + }; + + OnRPCNotificationListener onPermissionsChangeListener = new OnRPCNotificationListener() { + @Override + public void onNotified(RPCNotification notification) { + List<PermissionItem> permissionItems = ((OnPermissionsChange) notification).getPermissionItem(); + Boolean requireEncryptionAppLevel = ((OnPermissionsChange) notification).getRequireEncryption(); + encryptionRequiredRPCs.clear(); + if (requireEncryptionAppLevel == null || requireEncryptionAppLevel) { + if (permissionItems != null && !permissionItems.isEmpty()) { + for (PermissionItem permissionItem : permissionItems) { + if (permissionItem != null && Boolean.TRUE.equals(permissionItem.getRequireEncryption())) { + String rpcName = permissionItem.getRpcName(); + if (rpcName != null) { + encryptionRequiredRPCs.add(rpcName); + } + } + } + } + checkStatusAndInitSecuredService(); + } + } + }; + + ISdlServiceListener securedServiceListener = new ISdlServiceListener() { + @Override + public void onServiceStarted(SdlSession session, SessionType type, boolean isEncrypted) { + if(SessionType.RPC.equals(type)){ + rpcSecuredServiceStarted = isEncrypted; + } + if (serviceEncryptionListener != null) { + serviceEncryptionListener.onEncryptionServiceUpdated(type, isEncrypted, null); + } + DebugTool.logInfo("onServiceStarted, session Type: " + type.getName() + ", isEncrypted: " + isEncrypted); + } + + @Override + public void onServiceEnded(SdlSession session, SessionType type) { + if (SessionType.RPC.equals(type)) { + rpcSecuredServiceStarted = false; + } + if (serviceEncryptionListener != null) { + serviceEncryptionListener.onEncryptionServiceUpdated(type, false, null); + } + DebugTool.logInfo("onServiceEnded, session Type: " + type.getName()); + } + + @Override + public void onServiceError(SdlSession session, SessionType type, String reason) { + if (SessionType.RPC.equals(type)) { + rpcSecuredServiceStarted = false; + } + if (serviceEncryptionListener != null) { + serviceEncryptionListener.onEncryptionServiceUpdated(type, false, "onServiceError: " + reason); + } + DebugTool.logError("onServiceError, session Type: " + type.getName() + ", reason: " + reason); + } + }; + + internalInterface.addOnRPCNotificationListener(FunctionID.ON_HMI_STATUS, onHMIStatusListener); + internalInterface.addOnRPCNotificationListener(FunctionID.ON_PERMISSIONS_CHANGE, onPermissionsChangeListener); + internalInterface.addServiceListener(SessionType.RPC, securedServiceListener); + } + + /** + * Gets the app level encryption requirement + * + * @return true if encryption is required for app level; false otherwise + */ + private boolean getRequiresEncryption() { + return !encryptionRequiredRPCs.isEmpty(); + } + + /** + * Checks if an RPC requires encryption + * + * @param rpcName the rpc name to check + * @return true if the given RPC requires encryption; false, otherwise + */ + boolean getRPCRequiresEncryption(@NonNull FunctionID rpcName) { + return encryptionRequiredRPCs.contains(rpcName.toString()); + } + + /** + * Checks the current state and make the call back to initiate secured service flow + */ + private void checkStatusAndInitSecuredService() { + if ((currentHMILevel != null && currentHMILevel != HMILevel.HMI_NONE) && getRequiresEncryption() && !isEncryptionReady() ) { + internalInterface.startRPCEncryption(); + } + } + + /** + * Check to see if a secured service is ready to use + * + * @return true if there is a secured service; false otherwise + */ + boolean isEncryptionReady() { + return rpcSecuredServiceStarted; + } + + /** + * Clean up everything after the manager is no longer needed + */ + void dispose() { + rpcSecuredServiceStarted = false; + encryptionRequiredRPCs.clear(); + serviceEncryptionListener = null; + } +} diff --git a/base/src/main/java/com/smartdevicelink/managers/permission/BasePermissionManager.java b/base/src/main/java/com/smartdevicelink/managers/permission/BasePermissionManager.java index 23b0ab8f7..5e242e21e 100644 --- a/base/src/main/java/com/smartdevicelink/managers/permission/BasePermissionManager.java +++ b/base/src/main/java/com/smartdevicelink/managers/permission/BasePermissionManager.java @@ -50,8 +50,10 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.UUID; /** @@ -67,6 +69,7 @@ abstract class BasePermissionManager extends BaseSubManager{ private Map<FunctionID, PermissionItem> currentPermissionItems; private OnRPCNotificationListener onHMIStatusListener, onPermissionsChangeListener; private List<PermissionFilter> filters; + private Set<String> encryptionRequiredRPCs = new HashSet<>(); // Permission groups status constants @IntDef({PERMISSION_GROUP_STATUS_ALLOWED, PERMISSION_GROUP_STATUS_DISALLOWED, @@ -116,6 +119,8 @@ abstract class BasePermissionManager extends BaseSubManager{ public void onNotified(RPCNotification notification) { List<PermissionItem> permissionItems = ((OnPermissionsChange)notification).getPermissionItem(); Map<FunctionID, PermissionItem> previousPermissionItems = currentPermissionItems; + Boolean requireEncryptionAppLevel = ((OnPermissionsChange) notification).getRequireEncryption(); + encryptionRequiredRPCs.clear(); currentPermissionItems = new HashMap<>(); if (permissionItems != null && !permissionItems.isEmpty()) { for (PermissionItem permissionItem : permissionItems) { @@ -123,6 +128,14 @@ abstract class BasePermissionManager extends BaseSubManager{ if (functionID != null) { currentPermissionItems.put(functionID, permissionItem); } + if (Boolean.TRUE.equals(permissionItem.getRequireEncryption())) { + if (requireEncryptionAppLevel == null || requireEncryptionAppLevel) { + String rpcName = permissionItem.getRpcName(); + if (rpcName != null) { + encryptionRequiredRPCs.add(rpcName); + } + } + } } } notifyListeners(previousPermissionItems, currentHMILevel, currentPermissionItems, currentHMILevel); @@ -138,6 +151,24 @@ abstract class BasePermissionManager extends BaseSubManager{ super.start(listener); } + /** + * Checks if an RPC requires encryption + * + * @param rpcName the rpc name (FunctionID) to check + * @return true if the given RPC requires encryption; false, otherwise + */ + public boolean getRPCRequiresEncryption(@NonNull FunctionID rpcName) { + return encryptionRequiredRPCs.contains(rpcName.toString()); + } + + /** + * Gets the encryption requirement + * @return true if encryption is required; false otherwise + */ + public boolean getRequiresEncryption() { + return !encryptionRequiredRPCs.isEmpty(); + } + private synchronized void checkState(){ if(this.getState() == SETTING_UP && currentHMILevel != null){ transitionToState(READY); diff --git a/base/src/main/java/com/smartdevicelink/managers/screen/BaseSoftButtonManager.java b/base/src/main/java/com/smartdevicelink/managers/screen/BaseSoftButtonManager.java index 54a851684..dd20f342a 100644 --- a/base/src/main/java/com/smartdevicelink/managers/screen/BaseSoftButtonManager.java +++ b/base/src/main/java/com/smartdevicelink/managers/screen/BaseSoftButtonManager.java @@ -42,15 +42,16 @@ import com.smartdevicelink.managers.file.filetypes.SdlArtwork; import com.smartdevicelink.protocol.enums.FunctionID; import com.smartdevicelink.proxy.RPCNotification; import com.smartdevicelink.proxy.RPCResponse; +import com.smartdevicelink.proxy.SystemCapabilityManager; import com.smartdevicelink.proxy.interfaces.ISdl; import com.smartdevicelink.proxy.interfaces.OnSystemCapabilityListener; -import com.smartdevicelink.proxy.rpc.DisplayCapabilities; +import com.smartdevicelink.proxy.rpc.DisplayCapability; import com.smartdevicelink.proxy.rpc.OnButtonEvent; import com.smartdevicelink.proxy.rpc.OnButtonPress; import com.smartdevicelink.proxy.rpc.OnHMIStatus; import com.smartdevicelink.proxy.rpc.Show; import com.smartdevicelink.proxy.rpc.SoftButton; -import com.smartdevicelink.proxy.rpc.SoftButtonCapabilities; +import com.smartdevicelink.proxy.rpc.WindowCapability; import com.smartdevicelink.proxy.rpc.enums.ButtonName; import com.smartdevicelink.proxy.rpc.enums.HMILevel; import com.smartdevicelink.proxy.rpc.enums.PredefinedWindows; @@ -77,14 +78,13 @@ abstract class BaseSoftButtonManager extends BaseSubManager { private static final String TAG = "SoftButtonManager"; private WeakReference<FileManager> fileManager; - private DisplayCapabilities displayCapabilities; - private SoftButtonCapabilities softButtonCapabilities; + WindowCapability defaultMainWindowCapability; private CopyOnWriteArrayList<SoftButtonObject> softButtonObjects; private HMILevel currentHMILevel; private Show inProgressShowRPC; private CompletionListener inProgressListener, queuedUpdateListener, cachedListener; private boolean hasQueuedUpdate, batchUpdates, waitingOnHMILevelUpdateToSetButtons; - private final OnSystemCapabilityListener onSoftButtonCapabilitiesListener, onDisplayCapabilitiesListener; + private final OnSystemCapabilityListener onDisplayCapabilityListener; private final OnRPCNotificationListener onHMIStatusListener, onButtonPressListener, onButtonEventListener; private final SoftButtonObject.UpdateListener updateListener; @@ -99,7 +99,7 @@ abstract class BaseSoftButtonManager extends BaseSubManager { * @param internalInterface an instance of the ISdl interface that can be used for common SDL operations (sendRpc, addRpcListener, etc) * @param fileManager an instance of the FileManager so that button graphics can be sent */ - BaseSoftButtonManager(@NonNull ISdl internalInterface, @NonNull FileManager fileManager) { + BaseSoftButtonManager(@NonNull final ISdl internalInterface, @NonNull FileManager fileManager) { super(internalInterface); this.fileManager = new WeakReference<>(fileManager); this.softButtonObjects = new CopyOnWriteArrayList<>(); @@ -114,41 +114,31 @@ abstract class BaseSoftButtonManager extends BaseSubManager { // Add OnSoftButtonCapabilitiesListener to keep softButtonCapabilities updated - onSoftButtonCapabilitiesListener = new OnSystemCapabilityListener() { + onDisplayCapabilityListener = new OnSystemCapabilityListener() { @Override public void onCapabilityRetrieved(Object capability) { - List<SoftButtonCapabilities> softButtonCapabilitiesList = (List<SoftButtonCapabilities>) capability; - if (softButtonCapabilitiesList != null && !softButtonCapabilitiesList.isEmpty()) { - softButtonCapabilities = softButtonCapabilitiesList.get(0); - } else { - softButtonCapabilities = null; + // instead of using the parameter it's more safe to use the convenience method + List<DisplayCapability> capabilities = SystemCapabilityManager.convertToList(capability, DisplayCapability.class); + if (capabilities == null || capabilities.size() == 0) { + DebugTool.logError("SoftButton Manager - Capabilities sent here are null or empty"); + }else { + DisplayCapability display = capabilities.get(0); + for (WindowCapability windowCapability : display.getWindowCapabilities()) { + int currentWindowID = windowCapability.getWindowID() != null ? windowCapability.getWindowID() : PredefinedWindows.DEFAULT_WINDOW.getValue(); + if (currentWindowID == PredefinedWindows.DEFAULT_WINDOW.getValue()) { + defaultMainWindowCapability = windowCapability; + } + } } } @Override public void onError(String info) { - Log.w(TAG, "SoftButton Capability cannot be retrieved:"); - softButtonCapabilities = null; + DebugTool.logError("Display Capability cannot be retrieved"); + defaultMainWindowCapability = null; } }; - this.internalInterface.addOnSystemCapabilityListener(SystemCapabilityType.SOFTBUTTON, onSoftButtonCapabilitiesListener); - - - // Add OnDisplayCapabilitiesListener to keep displayCapabilities updated - onDisplayCapabilitiesListener = new OnSystemCapabilityListener() { - @Override - public void onCapabilityRetrieved(Object capability) { - displayCapabilities = (DisplayCapabilities) capability; - } - - @Override - public void onError(String info) { - Log.w(TAG, "Display Capability cannot be retrieved:"); - displayCapabilities = null; - } - }; - this.internalInterface.addOnSystemCapabilityListener(SystemCapabilityType.DISPLAY, onDisplayCapabilitiesListener); - + this.internalInterface.addOnSystemCapabilityListener(SystemCapabilityType.DISPLAYS, onDisplayCapabilityListener); // Add OnHMIStatusListener to keep currentHMILevel updated this.onHMIStatusListener = new OnRPCNotificationListener() { @@ -528,8 +518,10 @@ abstract class BaseSoftButtonManager extends BaseSubManager { internalInterface.sendRPC(inProgressShowRPC); } - private boolean softButtonImagesSupported(){ - return (displayCapabilities == null || displayCapabilities.getGraphicSupported()) && (softButtonCapabilities == null || softButtonCapabilities.getImageSupported()); + private boolean softButtonImagesSupported() { + return defaultMainWindowCapability == null + || defaultMainWindowCapability.getSoftButtonCapabilities() == null + || (!defaultMainWindowCapability.getSoftButtonCapabilities().isEmpty() && defaultMainWindowCapability.getSoftButtonCapabilities().get(0).getImageSupported()); } /** @@ -588,8 +580,7 @@ abstract class BaseSoftButtonManager extends BaseSubManager { internalInterface.removeOnRPCNotificationListener(FunctionID.ON_HMI_STATUS, onHMIStatusListener); internalInterface.removeOnRPCNotificationListener(FunctionID.ON_BUTTON_PRESS, onButtonPressListener); internalInterface.removeOnRPCNotificationListener(FunctionID.ON_BUTTON_EVENT, onButtonEventListener); - internalInterface.removeOnSystemCapabilityListener(SystemCapabilityType.SOFTBUTTON, onSoftButtonCapabilitiesListener); - internalInterface.removeOnSystemCapabilityListener(SystemCapabilityType.DISPLAY, onDisplayCapabilitiesListener); + internalInterface.removeOnSystemCapabilityListener(SystemCapabilityType.DISPLAYS, onDisplayCapabilityListener); } /** diff --git a/base/src/main/java/com/smartdevicelink/managers/screen/BaseTextAndGraphicManager.java b/base/src/main/java/com/smartdevicelink/managers/screen/BaseTextAndGraphicManager.java index e6a936957..83190d078 100644 --- a/base/src/main/java/com/smartdevicelink/managers/screen/BaseTextAndGraphicManager.java +++ b/base/src/main/java/com/smartdevicelink/managers/screen/BaseTextAndGraphicManager.java @@ -42,13 +42,15 @@ import com.smartdevicelink.managers.file.filetypes.SdlArtwork; import com.smartdevicelink.protocol.enums.FunctionID; import com.smartdevicelink.proxy.RPCNotification; import com.smartdevicelink.proxy.RPCResponse; +import com.smartdevicelink.proxy.SystemCapabilityManager; import com.smartdevicelink.proxy.interfaces.ISdl; import com.smartdevicelink.proxy.interfaces.OnSystemCapabilityListener; -import com.smartdevicelink.proxy.rpc.DisplayCapabilities; +import com.smartdevicelink.proxy.rpc.DisplayCapability; import com.smartdevicelink.proxy.rpc.MetadataTags; import com.smartdevicelink.proxy.rpc.OnHMIStatus; import com.smartdevicelink.proxy.rpc.Show; import com.smartdevicelink.proxy.rpc.TextField; +import com.smartdevicelink.proxy.rpc.WindowCapability; import com.smartdevicelink.proxy.rpc.enums.HMILevel; import com.smartdevicelink.proxy.rpc.enums.MetadataType; import com.smartdevicelink.proxy.rpc.enums.PredefinedWindows; @@ -82,14 +84,14 @@ abstract class BaseTextAndGraphicManager extends BaseSubManager { volatile Show inProgressUpdate; Show currentScreenData, queuedImageUpdate; HMILevel currentHMILevel; - protected DisplayCapabilities displayCapabilities; + WindowCapability defaultMainWindowCapability; private boolean pendingHMIFull, batchingUpdates; private final WeakReference<FileManager> fileManager; private final WeakReference<SoftButtonManager> softButtonManager; private CompletionListener queuedUpdateListener, inProgressListener, pendingHMIListener; SdlArtwork blankArtwork; private OnRPCNotificationListener hmiListener; - private OnSystemCapabilityListener onDisplayCapabilitiesListener; + private OnSystemCapabilityListener onDisplaysCapabilityListener; private SdlArtwork primaryGraphic, secondaryGraphic; private TextAlignment textAlignment; private String textField1, textField2, textField3, textField4, mediaTrackTextField, title; @@ -135,7 +137,7 @@ abstract class BaseTextAndGraphicManager extends BaseSubManager { primaryGraphic = null; secondaryGraphic = null; blankArtwork = null; - displayCapabilities = null; + defaultMainWindowCapability = null; inProgressUpdate = null; queuedImageUpdate = null; currentScreenData = null; @@ -148,7 +150,7 @@ abstract class BaseTextAndGraphicManager extends BaseSubManager { // remove listeners internalInterface.removeOnRPCNotificationListener(FunctionID.ON_HMI_STATUS, hmiListener); - internalInterface.removeOnSystemCapabilityListener(SystemCapabilityType.DISPLAY, onDisplayCapabilitiesListener); + internalInterface.removeOnSystemCapabilityListener(SystemCapabilityType.DISPLAYS, onDisplaysCapabilityListener); super.dispose(); } @@ -175,20 +177,32 @@ abstract class BaseTextAndGraphicManager extends BaseSubManager { }; internalInterface.addOnRPCNotificationListener(FunctionID.ON_HMI_STATUS, hmiListener); - // Add OnDisplayCapabilitiesListener to keep displayCapabilities updated - onDisplayCapabilitiesListener = new OnSystemCapabilityListener() { + + onDisplaysCapabilityListener = new OnSystemCapabilityListener() { @Override public void onCapabilityRetrieved(Object capability) { - displayCapabilities = (DisplayCapabilities)capability; + // instead of using the parameter it's more safe to use the convenience method + List<DisplayCapability> capabilities = SystemCapabilityManager.convertToList(capability, DisplayCapability.class); + if (capabilities == null || capabilities.size() == 0) { + DebugTool.logError("TextAndGraphic Manager - Capabilities sent here are null or empty"); + }else { + DisplayCapability display = capabilities.get(0); + for (WindowCapability windowCapability : display.getWindowCapabilities()) { + int currentWindowID = windowCapability.getWindowID() != null ? windowCapability.getWindowID() : PredefinedWindows.DEFAULT_WINDOW.getValue(); + if (currentWindowID == PredefinedWindows.DEFAULT_WINDOW.getValue()) { + defaultMainWindowCapability = windowCapability; + } + } + } } @Override public void onError(String info) { - Log.e(TAG, "DISPLAY Capability cannot be retrieved:"); - displayCapabilities = null; + DebugTool.logError("Display Capability cannot be retrieved"); + defaultMainWindowCapability = null; } }; - this.internalInterface.addOnSystemCapabilityListener(SystemCapabilityType.DISPLAY, onDisplayCapabilitiesListener); + this.internalInterface.addOnSystemCapabilityListener(SystemCapabilityType.DISPLAYS, onDisplaysCapabilityListener); } // Upload / Send @@ -323,7 +337,7 @@ abstract class BaseTextAndGraphicManager extends BaseSubManager { if (this.softButtonManager.get() != null) { this.softButtonManager.get().setCurrentMainField1(inProgressUpdate.getMainField1()); } - internalInterface.sendRPCRequest(inProgressUpdate); + internalInterface.sendRPC(inProgressUpdate); } // Images @@ -719,6 +733,7 @@ abstract class BaseTextAndGraphicManager extends BaseSubManager { abstract SdlArtwork getBlankArtwork(); + @SuppressWarnings("BooleanMethodIsAlwaysInverted") private boolean sdlArtworkNeedsUpload(SdlArtwork artwork){ if (fileManager.get() != null) { return artwork != null && !fileManager.get().hasUploadedFile(artwork) && !artwork.isStaticIcon(); @@ -727,7 +742,7 @@ abstract class BaseTextAndGraphicManager extends BaseSubManager { } private boolean shouldUpdatePrimaryImage() { - if (displayCapabilities == null || displayCapabilities.getGraphicSupported()) { + if (defaultMainWindowCapability == null || defaultMainWindowCapability.getImageTypeSupported() == null || defaultMainWindowCapability.getImageTypeSupported().size() > 0) { if (currentScreenData.getGraphic() == null && primaryGraphic != null) { return true; } else if (currentScreenData.getGraphic() == null && primaryGraphic == null) { @@ -741,7 +756,7 @@ abstract class BaseTextAndGraphicManager extends BaseSubManager { private boolean shouldUpdateSecondaryImage() { // Cannot detect if there is a secondary image, so we'll just try to detect if there's a primary image and allow it if there is. - if (displayCapabilities == null || displayCapabilities.getGraphicSupported()) { + if (defaultMainWindowCapability == null || defaultMainWindowCapability.getImageTypeSupported() == null || defaultMainWindowCapability.getImageTypeSupported().size() > 0) { if (currentScreenData.getGraphic() == null && secondaryGraphic != null) { return true; } else if (currentScreenData.getGraphic() == null && secondaryGraphic == null) { @@ -755,13 +770,13 @@ abstract class BaseTextAndGraphicManager extends BaseSubManager { int getNumberOfLines() { - if (displayCapabilities == null){ + if (defaultMainWindowCapability == null){ return 4; } int linesFound = 0; - List<TextField> textFields = displayCapabilities.getTextFields(); + List<TextField> textFields = defaultMainWindowCapability.getTextFields(); TextFieldName name; for (TextField field : textFields) { if (field.getName() != null) { diff --git a/base/src/main/java/com/smartdevicelink/managers/screen/SoftButtonState.java b/base/src/main/java/com/smartdevicelink/managers/screen/SoftButtonState.java index 9e48b2f7d..97842a8eb 100644 --- a/base/src/main/java/com/smartdevicelink/managers/screen/SoftButtonState.java +++ b/base/src/main/java/com/smartdevicelink/managers/screen/SoftButtonState.java @@ -39,8 +39,6 @@ import com.smartdevicelink.proxy.rpc.SoftButton; import com.smartdevicelink.proxy.rpc.enums.SoftButtonType; import com.smartdevicelink.proxy.rpc.enums.SystemAction; -import java.util.List; - /** * <strong>SoftButtonState</strong> <br> * Defines an individual state for SoftButtonObject.<br> diff --git a/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/BaseChoiceSetManager.java b/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/BaseChoiceSetManager.java index e343cd131..591f50a84 100644 --- a/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/BaseChoiceSetManager.java +++ b/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/BaseChoiceSetManager.java @@ -42,11 +42,13 @@ import com.smartdevicelink.managers.CompletionListener; import com.smartdevicelink.managers.file.FileManager; import com.smartdevicelink.protocol.enums.FunctionID; import com.smartdevicelink.proxy.RPCNotification; +import com.smartdevicelink.proxy.SystemCapabilityManager; import com.smartdevicelink.proxy.interfaces.ISdl; import com.smartdevicelink.proxy.interfaces.OnSystemCapabilityListener; -import com.smartdevicelink.proxy.rpc.DisplayCapabilities; +import com.smartdevicelink.proxy.rpc.DisplayCapability; import com.smartdevicelink.proxy.rpc.KeyboardProperties; import com.smartdevicelink.proxy.rpc.OnHMIStatus; +import com.smartdevicelink.proxy.rpc.WindowCapability; import com.smartdevicelink.proxy.rpc.enums.HMILevel; import com.smartdevicelink.proxy.rpc.enums.InteractionMode; import com.smartdevicelink.proxy.rpc.enums.KeyboardLayout; @@ -60,7 +62,6 @@ import com.smartdevicelink.proxy.rpc.listeners.OnRPCNotificationListener; import com.smartdevicelink.util.DebugTool; import java.lang.ref.WeakReference; -import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.concurrent.Future; @@ -80,9 +81,9 @@ abstract class BaseChoiceSetManager extends BaseSubManager { final WeakReference<FileManager> fileManager; OnRPCNotificationListener hmiListener; - OnSystemCapabilityListener displayListener; + OnSystemCapabilityListener onDisplayCapabilityListener; HMILevel currentHMILevel; - DisplayCapabilities displayCapabilities; + WindowCapability defaultMainWindowCapability; SystemContext currentSystemContext; HashSet<ChoiceCell> preloadedChoices, pendingPreloadChoices; ChoiceSet pendingPresentationSet; @@ -139,7 +140,7 @@ abstract class BaseChoiceSetManager extends BaseSubManager { currentHMILevel = null; currentSystemContext = null; - displayCapabilities = null; + defaultMainWindowCapability = null; pendingPresentationSet = null; pendingPresentOperation = null; @@ -149,7 +150,7 @@ abstract class BaseChoiceSetManager extends BaseSubManager { // remove listeners internalInterface.removeOnRPCNotificationListener(FunctionID.ON_HMI_STATUS, hmiListener); - internalInterface.removeOnSystemCapabilityListener(SystemCapabilityType.DISPLAY, displayListener); + internalInterface.removeOnSystemCapabilityListener(SystemCapabilityType.DISPLAYS, onDisplayCapabilityListener); super.dispose(); } @@ -207,7 +208,7 @@ abstract class BaseChoiceSetManager extends BaseSubManager { pendingPreloadChoices.addAll(choicesToUpload); if (fileManager.get() != null) { - PreloadChoicesOperation preloadChoicesOperation = new PreloadChoicesOperation(internalInterface, fileManager.get(), displayCapabilities, isVROptional, choicesToUpload, new CompletionListener() { + PreloadChoicesOperation preloadChoicesOperation = new PreloadChoicesOperation(internalInterface, fileManager.get(), defaultMainWindowCapability, isVROptional, choicesToUpload, new CompletionListener() { @Override public void onComplete(boolean success) { if (success){ @@ -509,19 +510,32 @@ abstract class BaseChoiceSetManager extends BaseSubManager { // LISTENERS private void addListeners(){ - // DISPLAY CAPABILITIES - via SCM - displayListener = new OnSystemCapabilityListener() { + // DISPLAY/WINDOW CAPABILITIES - via SCM + onDisplayCapabilityListener = new OnSystemCapabilityListener() { @Override public void onCapabilityRetrieved(Object capability) { - displayCapabilities = (DisplayCapabilities) capability; + // instead of using the parameter it's more safe to use the convenience method + List<DisplayCapability> capabilities = SystemCapabilityManager.convertToList(capability, DisplayCapability.class); + if (capabilities == null || capabilities.size() == 0) { + DebugTool.logError("SoftButton Manager - Capabilities sent here are null or empty"); + }else { + DisplayCapability display = capabilities.get(0); + for (WindowCapability windowCapability : display.getWindowCapabilities()) { + int currentWindowID = windowCapability.getWindowID() != null ? windowCapability.getWindowID() : PredefinedWindows.DEFAULT_WINDOW.getValue(); + if (currentWindowID == PredefinedWindows.DEFAULT_WINDOW.getValue()) { + defaultMainWindowCapability = windowCapability; + } + } + } } @Override public void onError(String info) { DebugTool.logError("Unable to retrieve display capabilities. Many things will probably break. Info: "+ info); + defaultMainWindowCapability = null; } }; - internalInterface.getCapability(SystemCapabilityType.DISPLAY, displayListener); + this.internalInterface.addOnSystemCapabilityListener(SystemCapabilityType.DISPLAYS, onDisplayCapabilityListener); // HMI UPDATES hmiListener = new OnRPCNotificationListener() { diff --git a/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/ChoiceSet.java b/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/ChoiceSet.java index b846760c7..34bdbd6a4 100644 --- a/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/ChoiceSet.java +++ b/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/ChoiceSet.java @@ -34,6 +34,7 @@ package com.smartdevicelink.managers.screen.choiceset; import android.support.annotation.NonNull; import android.support.annotation.Nullable; + import com.smartdevicelink.proxy.TTSChunkFactory; import com.smartdevicelink.proxy.rpc.KeyboardProperties; import com.smartdevicelink.proxy.rpc.TTSChunk; diff --git a/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/KeyboardAutocompleteCompletionListener.java b/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/KeyboardAutocompleteCompletionListener.java index 992509019..13b19238d 100644 --- a/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/KeyboardAutocompleteCompletionListener.java +++ b/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/KeyboardAutocompleteCompletionListener.java @@ -32,9 +32,6 @@ package com.smartdevicelink.managers.screen.choiceset; -import com.smartdevicelink.proxy.SystemCapabilityManager; -import com.smartdevicelink.proxy.rpc.enums.SystemCapabilityType; - import java.util.List; public interface KeyboardAutocompleteCompletionListener { diff --git a/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/PreloadChoicesOperation.java b/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/PreloadChoicesOperation.java index 99cd91a96..6492d2c09 100644 --- a/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/PreloadChoicesOperation.java +++ b/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/PreloadChoicesOperation.java @@ -49,6 +49,7 @@ import com.smartdevicelink.proxy.rpc.DisplayCapabilities; import com.smartdevicelink.proxy.rpc.Image; import com.smartdevicelink.proxy.rpc.ImageField; import com.smartdevicelink.proxy.rpc.TextField; +import com.smartdevicelink.proxy.rpc.WindowCapability; import com.smartdevicelink.proxy.rpc.enums.ImageFieldName; import com.smartdevicelink.proxy.rpc.enums.Result; import com.smartdevicelink.proxy.rpc.enums.TextFieldName; @@ -66,18 +67,18 @@ class PreloadChoicesOperation extends AsynchronousOperation { private WeakReference<ISdl> internalInterface; private WeakReference<FileManager> fileManager; - private DisplayCapabilities displayCapabilities; + private WindowCapability defaultMainWindowCapability; private HashSet<ChoiceCell> cellsToUpload; private CompletionListener completionListener; private boolean isRunning; private boolean isVROptional; - PreloadChoicesOperation(ISdl internalInterface, FileManager fileManager, DisplayCapabilities displayCapabilities, + PreloadChoicesOperation(ISdl internalInterface, FileManager fileManager, WindowCapability defaultMainWindowCapability, Boolean isVROptional, HashSet<ChoiceCell> cellsToPreload, CompletionListener listener){ super(); this.internalInterface = new WeakReference<>(internalInterface); this.fileManager = new WeakReference<>(fileManager); - this.displayCapabilities = displayCapabilities; + this.defaultMainWindowCapability = defaultMainWindowCapability; this.isVROptional = isVROptional; this.cellsToUpload = cellsToPreload; this.completionListener = listener; @@ -249,10 +250,10 @@ class PreloadChoicesOperation extends AsynchronousOperation { } boolean hasImageFieldOfName(ImageFieldName name){ - if (displayCapabilities == null ){ return false; } - if (displayCapabilities.getGraphicSupported() == null || !displayCapabilities.getGraphicSupported()) { return false; } - if (displayCapabilities.getImageFields() != null){ - for (ImageField field : displayCapabilities.getImageFields()){ + if (defaultMainWindowCapability == null ){ return false; } + if (defaultMainWindowCapability.getImageTypeSupported() == null || defaultMainWindowCapability.getImageTypeSupported().isEmpty()) { return false; } + if (defaultMainWindowCapability.getImageFields() != null){ + for (ImageField field : defaultMainWindowCapability.getImageFields()){ if (field.getName().equals(name)){ return true; } @@ -262,9 +263,9 @@ class PreloadChoicesOperation extends AsynchronousOperation { } boolean hasTextFieldOfName(TextFieldName name){ - if (displayCapabilities == null ){ return false; } - if (displayCapabilities.getTextFields() != null){ - for (TextField field : displayCapabilities.getTextFields()){ + if (defaultMainWindowCapability == null ){ return false; } + if (defaultMainWindowCapability.getTextFields() != null){ + for (TextField field : defaultMainWindowCapability.getTextFields()){ if (field.getName().equals(name)){ return true; } @@ -272,5 +273,4 @@ class PreloadChoicesOperation extends AsynchronousOperation { } return false; } - }
\ No newline at end of file diff --git a/base/src/main/java/com/smartdevicelink/managers/screen/menu/BaseMenuManager.java b/base/src/main/java/com/smartdevicelink/managers/screen/menu/BaseMenuManager.java index f53331157..21a4eec06 100644 --- a/base/src/main/java/com/smartdevicelink/managers/screen/menu/BaseMenuManager.java +++ b/base/src/main/java/com/smartdevicelink/managers/screen/menu/BaseMenuManager.java @@ -43,13 +43,14 @@ import com.smartdevicelink.protocol.enums.FunctionID; import com.smartdevicelink.proxy.RPCNotification; import com.smartdevicelink.proxy.RPCRequest; import com.smartdevicelink.proxy.RPCResponse; +import com.smartdevicelink.proxy.SystemCapabilityManager; import com.smartdevicelink.proxy.interfaces.ISdl; import com.smartdevicelink.proxy.interfaces.OnSystemCapabilityListener; import com.smartdevicelink.proxy.rpc.AddCommand; import com.smartdevicelink.proxy.rpc.AddSubMenu; import com.smartdevicelink.proxy.rpc.DeleteCommand; import com.smartdevicelink.proxy.rpc.DeleteSubMenu; -import com.smartdevicelink.proxy.rpc.DisplayCapabilities; +import com.smartdevicelink.proxy.rpc.DisplayCapability; import com.smartdevicelink.proxy.rpc.ImageField; import com.smartdevicelink.proxy.rpc.MenuParams; import com.smartdevicelink.proxy.rpc.OnCommand; @@ -57,10 +58,10 @@ import com.smartdevicelink.proxy.rpc.OnHMIStatus; import com.smartdevicelink.proxy.rpc.SdlMsgVersion; import com.smartdevicelink.proxy.rpc.ShowAppMenu; import com.smartdevicelink.proxy.rpc.SetGlobalProperties; +import com.smartdevicelink.proxy.rpc.WindowCapability; import com.smartdevicelink.proxy.rpc.enums.DisplayType; import com.smartdevicelink.proxy.rpc.enums.HMILevel; import com.smartdevicelink.proxy.rpc.enums.ImageFieldName; -import com.smartdevicelink.proxy.rpc.enums.MenuLayout; import com.smartdevicelink.proxy.rpc.enums.PredefinedWindows; import com.smartdevicelink.proxy.rpc.enums.Result; import com.smartdevicelink.proxy.rpc.enums.SystemCapabilityType; @@ -91,15 +92,15 @@ abstract class BaseMenuManager extends BaseSubManager { DynamicMenuUpdatesMode dynamicMenuUpdatesMode; MenuConfiguration menuConfiguration; SdlMsgVersion sdlMsgVersion; - private DisplayType displayType; + private String displayType; boolean waitingOnHMIUpdate; private boolean hasQueuedUpdate; HMILevel currentHMILevel; OnRPCNotificationListener hmiListener, commandListener; - OnSystemCapabilityListener displayListener; - DisplayCapabilities displayCapabilities; + OnSystemCapabilityListener onDisplaysCapabilityListener; + WindowCapability defaultMainWindowCapability; private static final int MAX_ID = 2000000000; private static final int parentIdNotFound = MAX_ID; @@ -138,7 +139,7 @@ abstract class BaseMenuManager extends BaseSubManager { currentHMILevel = null; currentSystemContext = SystemContext.SYSCTXT_MAIN; dynamicMenuUpdatesMode = DynamicMenuUpdatesMode.ON_WITH_COMPAT_MODE; - displayCapabilities = null; + defaultMainWindowCapability = null; inProgressUpdate = null; hasQueuedUpdate = false; waitingOnHMIUpdate = false; @@ -151,7 +152,7 @@ abstract class BaseMenuManager extends BaseSubManager { // remove listeners internalInterface.removeOnRPCNotificationListener(FunctionID.ON_HMI_STATUS, hmiListener); internalInterface.removeOnRPCNotificationListener(FunctionID.ON_COMMAND, commandListener); - internalInterface.removeOnSystemCapabilityListener(SystemCapabilityType.DISPLAY, displayListener); + internalInterface.removeOnSystemCapabilityListener(SystemCapabilityType.DISPLAYS, onDisplaysCapabilityListener); super.dispose(); } @@ -450,13 +451,13 @@ abstract class BaseMenuManager extends BaseSubManager { } } - private boolean checkUpdateMode(DynamicMenuUpdatesMode updateMode, DisplayType displayType){ + private boolean checkUpdateMode(DynamicMenuUpdatesMode updateMode, String displayType){ if (updateMode.equals(DynamicMenuUpdatesMode.ON_WITH_COMPAT_MODE)){ if (displayType == null){ return true; } - return (!displayType.equals(DisplayType.GEN3_8_INCH)); + return (!displayType.equals(DisplayType.GEN3_8_INCH.toString())); } else if (updateMode.equals(DynamicMenuUpdatesMode.FORCE_OFF)){ return false; @@ -773,8 +774,8 @@ abstract class BaseMenuManager extends BaseSubManager { @SuppressWarnings("BooleanMethodIsAlwaysInverted") private boolean supportsImages(){ - if (displayCapabilities != null && displayCapabilities.getImageFields() != null) { - List<ImageField> imageFields = displayCapabilities.getImageFields(); + if (defaultMainWindowCapability != null && defaultMainWindowCapability.getImageFields() != null) { + List<ImageField> imageFields = defaultMainWindowCapability.getImageFields(); for (ImageField field : imageFields) { if (field.getName().equals(ImageFieldName.cmdIcon)) { return true; @@ -1004,25 +1005,34 @@ abstract class BaseMenuManager extends BaseSubManager { // LISTENERS - @SuppressWarnings("deprecation") private void addListeners(){ - // DISPLAY CAPABILITIES - via SCM - displayListener = new OnSystemCapabilityListener() { + onDisplaysCapabilityListener = new OnSystemCapabilityListener() { @Override public void onCapabilityRetrieved(Object capability) { - displayCapabilities = (DisplayCapabilities) capability; - if (displayCapabilities != null) { - displayType = displayCapabilities.getDisplayType(); + // instead of using the parameter it's more safe to use the convenience method + List<DisplayCapability> capabilities = SystemCapabilityManager.convertToList(capability, DisplayCapability.class); + if (capabilities == null || capabilities.size() == 0) { + DebugTool.logError("SoftButton Manager - Capabilities sent here are null or empty"); + }else { + DisplayCapability display = capabilities.get(0); + displayType = display.getDisplayName(); + for (WindowCapability windowCapability : display.getWindowCapabilities()) { + int currentWindowID = windowCapability.getWindowID() != null ? windowCapability.getWindowID() : PredefinedWindows.DEFAULT_WINDOW.getValue(); + if (currentWindowID == PredefinedWindows.DEFAULT_WINDOW.getValue()) { + defaultMainWindowCapability = windowCapability; + } + } } } @Override public void onError(String info) { - DebugTool.logError("Unable to retrieve display capabilities: "+ info); + DebugTool.logError("Display Capability cannot be retrieved"); + defaultMainWindowCapability = null; } }; - internalInterface.getCapability(SystemCapabilityType.DISPLAY, displayListener); + this.internalInterface.addOnSystemCapabilityListener(SystemCapabilityType.DISPLAYS, onDisplaysCapabilityListener); // HMI UPDATES hmiListener = new OnRPCNotificationListener() { diff --git a/base/src/main/java/com/smartdevicelink/proxy/SystemCapabilityManager.java b/base/src/main/java/com/smartdevicelink/proxy/SystemCapabilityManager.java index 2e01ce026..febeb24ca 100644 --- a/base/src/main/java/com/smartdevicelink/proxy/SystemCapabilityManager.java +++ b/base/src/main/java/com/smartdevicelink/proxy/SystemCapabilityManager.java @@ -36,7 +36,9 @@ import com.smartdevicelink.proxy.interfaces.ISdl; import com.smartdevicelink.proxy.interfaces.OnSystemCapabilityListener; import com.smartdevicelink.proxy.rpc.AppServiceCapability; import com.smartdevicelink.proxy.rpc.AppServicesCapabilities; +import com.smartdevicelink.proxy.rpc.ButtonCapabilities; import com.smartdevicelink.proxy.rpc.DisplayCapabilities; +import com.smartdevicelink.proxy.rpc.DisplayCapability; import com.smartdevicelink.proxy.rpc.GetSystemCapability; import com.smartdevicelink.proxy.rpc.GetSystemCapabilityResponse; import com.smartdevicelink.proxy.rpc.HMICapabilities; @@ -44,9 +46,17 @@ import com.smartdevicelink.proxy.rpc.OnSystemCapabilityUpdated; import com.smartdevicelink.proxy.rpc.RegisterAppInterfaceResponse; import com.smartdevicelink.proxy.rpc.SdlMsgVersion; import com.smartdevicelink.proxy.rpc.SetDisplayLayoutResponse; +import com.smartdevicelink.proxy.rpc.SoftButtonCapabilities; import com.smartdevicelink.proxy.rpc.SystemCapability; +import com.smartdevicelink.proxy.rpc.WindowCapability; +import com.smartdevicelink.proxy.rpc.WindowTypeCapabilities; +import com.smartdevicelink.proxy.rpc.enums.DisplayType; +import com.smartdevicelink.proxy.rpc.enums.ImageType; +import com.smartdevicelink.proxy.rpc.enums.MediaClockFormat; +import com.smartdevicelink.proxy.rpc.enums.PredefinedWindows; import com.smartdevicelink.proxy.rpc.enums.Result; import com.smartdevicelink.proxy.rpc.enums.SystemCapabilityType; +import com.smartdevicelink.proxy.rpc.enums.WindowType; import com.smartdevicelink.proxy.rpc.listeners.OnRPCListener; import com.smartdevicelink.proxy.rpc.listeners.OnRPCResponseListener; import com.smartdevicelink.util.CorrelationIdGenerator; @@ -54,8 +64,10 @@ import com.smartdevicelink.util.DebugTool; import com.smartdevicelink.util.Version; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; +import java.util.ListIterator; import java.util.concurrent.CopyOnWriteArrayList; public class SystemCapabilityManager { @@ -64,18 +76,161 @@ public class SystemCapabilityManager { private final Object LISTENER_LOCK; private final ISdl callback; private OnRPCListener rpcListener; + private boolean shouldConvertDeprecatedDisplayCapabilities; public SystemCapabilityManager(ISdl callback){ this.callback = callback; this.LISTENER_LOCK = new Object(); this.onSystemCapabilityListeners = new HashMap<>(); this.cachedSystemCapabilities = new HashMap<>(); + this.shouldConvertDeprecatedDisplayCapabilities = true; setupRpcListeners(); } + private List<DisplayCapability> createDisplayCapabilityList(RegisterAppInterfaceResponse rpc) { + return createDisplayCapabilityList(rpc.getDisplayCapabilities(), rpc.getButtonCapabilities(), rpc.getSoftButtonCapabilities()); + } + + private List<DisplayCapability> createDisplayCapabilityList(SetDisplayLayoutResponse rpc) { + return createDisplayCapabilityList(rpc.getDisplayCapabilities(), rpc.getButtonCapabilities(), rpc.getSoftButtonCapabilities()); + } + + private List<DisplayCapability> createDisplayCapabilityList(DisplayCapabilities display, List<ButtonCapabilities> button, List<SoftButtonCapabilities> softButton) { + // Based on deprecated Display capabilities we don't know if widgets are supported, + // The Default MAIN window is the only window we know is supported + WindowTypeCapabilities windowTypeCapabilities = new WindowTypeCapabilities(WindowType.MAIN, 1); + + DisplayCapability displayCapability = new DisplayCapability(); + displayCapability.setDisplayName(display != null ? display.getDisplayName() : display.getDisplayType().toString()); + displayCapability.setWindowTypeSupported(Collections.singletonList(windowTypeCapabilities)); + + // Create a window capability object for the default MAIN window + WindowCapability defaultWindowCapability = new WindowCapability(); + defaultWindowCapability.setWindowID(PredefinedWindows.DEFAULT_WINDOW.getValue()); + defaultWindowCapability.setButtonCapabilities(button); + defaultWindowCapability.setSoftButtonCapabilities(softButton); + + // return if display capabilities don't exist. + if (display == null) { + displayCapability.setWindowCapabilities(Collections.singletonList(defaultWindowCapability)); + return Collections.singletonList(displayCapability); + } + + // copy all available display capabilities + defaultWindowCapability.setTemplatesAvailable(display.getTemplatesAvailable()); + defaultWindowCapability.setNumCustomPresetsAvailable(display.getNumCustomPresetsAvailable()); + defaultWindowCapability.setTextFields(display.getTextFields()); + defaultWindowCapability.setImageFields(display.getImageFields()); + ArrayList<ImageType> imageTypeSupported = new ArrayList<>(); + imageTypeSupported.add(ImageType.STATIC); // static images expected to always work on any head unit + if (display.getGraphicSupported()) { + imageTypeSupported.add(ImageType.DYNAMIC); + } + defaultWindowCapability.setImageTypeSupported(imageTypeSupported); + + displayCapability.setWindowCapabilities(Collections.singletonList(defaultWindowCapability)); + return Collections.singletonList(displayCapability); + } + + private DisplayCapabilities createDeprecatedDisplayCapabilities(String displayName, WindowCapability defaultMainWindow) { + DisplayCapabilities convertedCapabilities = new DisplayCapabilities(); + convertedCapabilities.setDisplayType(DisplayType.SDL_GENERIC); //deprecated but it is mandatory... + convertedCapabilities.setDisplayName(displayName); + convertedCapabilities.setTextFields(defaultMainWindow.getTextFields()); + convertedCapabilities.setImageFields(defaultMainWindow.getImageFields()); + convertedCapabilities.setTemplatesAvailable(defaultMainWindow.getTemplatesAvailable()); + convertedCapabilities.setNumCustomPresetsAvailable(defaultMainWindow.getNumCustomPresetsAvailable()); + convertedCapabilities.setMediaClockFormats(new ArrayList<MediaClockFormat>()); // mandatory field but allows empty array + // if there are imageTypes in the response, we must assume graphics are supported + convertedCapabilities.setGraphicSupported(defaultMainWindow.getImageTypeSupported() != null && defaultMainWindow.getImageTypeSupported().size() > 0); + + return convertedCapabilities; + } + + private void updateDeprecatedDisplayCapabilities() { + WindowCapability defaultMainWindowCapabilities = getDefaultMainWindowCapability(); + List<DisplayCapability> displayCapabilityList = convertToList(getCapability(SystemCapabilityType.DISPLAYS), DisplayCapability.class); + + if (defaultMainWindowCapabilities == null || displayCapabilityList == null || displayCapabilityList.size() == 0) { + return; + } + + // cover the deprecated capabilities for backward compatibility + setCapability(SystemCapabilityType.DISPLAY, createDeprecatedDisplayCapabilities(displayCapabilityList.get(0).getDisplayName(), defaultMainWindowCapabilities)); + setCapability(SystemCapabilityType.BUTTON, defaultMainWindowCapabilities.getButtonCapabilities()); + setCapability(SystemCapabilityType.SOFTBUTTON, defaultMainWindowCapabilities.getSoftButtonCapabilities()); + } + + private void updateCachedDisplayCapabilityList(List<DisplayCapability> newCapabilities) { + if (newCapabilities == null || newCapabilities.size() == 0) { + DebugTool.logWarning("Received invalid display capability list"); + return; + } + + List<DisplayCapability> oldCapabilities = convertToList(getCapability(SystemCapabilityType.DISPLAYS), DisplayCapability.class); + + if (oldCapabilities == null || oldCapabilities.size() == 0) { + setCapability(SystemCapabilityType.DISPLAYS, newCapabilities); + updateDeprecatedDisplayCapabilities(); + return; + } + + DisplayCapability oldDefaultDisplayCapabilities = oldCapabilities.get(0); + ArrayList<WindowCapability> copyWindowCapabilities = new ArrayList<>(oldDefaultDisplayCapabilities.getWindowCapabilities()); + + DisplayCapability newDefaultDisplayCapabilities = newCapabilities.get(0); + List<WindowCapability> newWindowCapabilities = newDefaultDisplayCapabilities.getWindowCapabilities(); + + for (WindowCapability newWindow : newWindowCapabilities) { + ListIterator<WindowCapability> iterator = copyWindowCapabilities.listIterator(); + boolean oldFound = false; + while (iterator.hasNext()) { + WindowCapability oldWindow = iterator.next(); + int newWindowID = newWindow.getWindowID() != null ? newWindow.getWindowID() : PredefinedWindows.DEFAULT_WINDOW.getValue(); + int oldWindowID = oldWindow.getWindowID() != null ? oldWindow.getWindowID() : PredefinedWindows.DEFAULT_WINDOW.getValue(); + if (newWindowID == oldWindowID) { + iterator.set(newWindow); // replace the old window caps with new ones + oldFound = true; + break; + } + } + + if (!oldFound) { + copyWindowCapabilities.add(newWindow); // this is a new unknown window + } + } + + // replace the window capabilities array with the merged one. + newDefaultDisplayCapabilities.setWindowCapabilities(copyWindowCapabilities); + setCapability(SystemCapabilityType.DISPLAYS, Collections.singletonList(newDefaultDisplayCapabilities)); + updateDeprecatedDisplayCapabilities(); + } + + + public WindowCapability getWindowCapability(int windowID) { + List<DisplayCapability> capabilities = convertToList(getCapability(SystemCapabilityType.DISPLAYS), DisplayCapability.class); + if (capabilities == null || capabilities.size() == 0) { + return null; + } + DisplayCapability display = capabilities.get(0); + for (WindowCapability windowCapability : display.getWindowCapabilities()) { + int currentWindowID = windowCapability.getWindowID() != null ? windowCapability.getWindowID() : PredefinedWindows.DEFAULT_WINDOW.getValue(); + if (currentWindowID == windowID) { + return windowCapability; + } + } + return null; + } + + public WindowCapability getDefaultMainWindowCapability() { + return getWindowCapability(PredefinedWindows.DEFAULT_WINDOW.getValue()); + } + public void parseRAIResponse(RegisterAppInterfaceResponse response){ if(response!=null && response.getSuccess()) { + this.shouldConvertDeprecatedDisplayCapabilities = true; // reset the flag + setCapability(SystemCapabilityType.DISPLAYS, createDisplayCapabilityList(response)); setCapability(SystemCapabilityType.HMI, response.getHmiCapabilities()); setCapability(SystemCapabilityType.DISPLAY, response.getDisplayCapabilities()); setCapability(SystemCapabilityType.AUDIO_PASSTHROUGH, response.getAudioPassThruCapabilities()); @@ -90,7 +245,7 @@ public class SystemCapabilityManager { } } - private void setupRpcListeners(){ + private void setupRpcListeners() { rpcListener = new OnRPCListener() { @Override public void onReceived(RPCMessage message) { @@ -103,36 +258,53 @@ public class SystemCapabilityManager { setCapability(SystemCapabilityType.BUTTON, response.getButtonCapabilities()); setCapability(SystemCapabilityType.PRESET_BANK, response.getPresetBankCapabilities()); setCapability(SystemCapabilityType.SOFTBUTTON, response.getSoftButtonCapabilities()); + if (shouldConvertDeprecatedDisplayCapabilities) { + setCapability(SystemCapabilityType.DISPLAYS, createDisplayCapabilityList(response)); + } + break; + case GET_SYSTEM_CAPABILITY: + GetSystemCapabilityResponse systemCapabilityResponse = (GetSystemCapabilityResponse) message; + SystemCapability systemCapability = systemCapabilityResponse.getSystemCapability(); + if (systemCapabilityResponse.getSuccess() && SystemCapabilityType.DISPLAYS.equals(systemCapability.getSystemCapabilityType())) { + shouldConvertDeprecatedDisplayCapabilities = false; // Successfully got DISPLAYS data. No conversion needed anymore + List<DisplayCapability> newCapabilities = (List<DisplayCapability>) systemCapability.getCapabilityForType(SystemCapabilityType.DISPLAYS); + updateCachedDisplayCapabilityList(newCapabilities); + } break; } - } else if (RPCMessage.KEY_NOTIFICATION.equals(message.getMessageType())){ + } else if (RPCMessage.KEY_NOTIFICATION.equals(message.getMessageType())) { switch (message.getFunctionID()) { case ON_SYSTEM_CAPABILITY_UPDATED: - OnSystemCapabilityUpdated onSystemCapabilityUpdated =(OnSystemCapabilityUpdated)message; - if(onSystemCapabilityUpdated.getSystemCapability() != null){ + OnSystemCapabilityUpdated onSystemCapabilityUpdated = (OnSystemCapabilityUpdated) message; + if (onSystemCapabilityUpdated.getSystemCapability() != null) { SystemCapability systemCapability = onSystemCapabilityUpdated.getSystemCapability(); SystemCapabilityType systemCapabilityType = systemCapability.getSystemCapabilityType(); Object capability = systemCapability.getCapabilityForType(systemCapabilityType); - if(cachedSystemCapabilities.containsKey(systemCapabilityType)) { //The capability already exists + if (cachedSystemCapabilities.containsKey(systemCapabilityType)) { //The capability already exists switch (systemCapabilityType) { case APP_SERVICES: // App services only updates what was changed so we need // to update the capability rather than override it AppServicesCapabilities appServicesCapabilities = (AppServicesCapabilities) capability; - if(capability != null) { - List<AppServiceCapability> appServicesCapabilitiesList = appServicesCapabilities.getAppServices(); - AppServicesCapabilities cachedAppServicesCapabilities = (AppServicesCapabilities) cachedSystemCapabilities.get(systemCapabilityType); - //Update the cached app services - cachedAppServicesCapabilities.updateAppServices(appServicesCapabilitiesList); - //Set the new capability object to the updated cached capabilities - capability = cachedAppServicesCapabilities; + if (capability != null) { + List<AppServiceCapability> appServicesCapabilitiesList = appServicesCapabilities.getAppServices(); + AppServicesCapabilities cachedAppServicesCapabilities = (AppServicesCapabilities) cachedSystemCapabilities.get(systemCapabilityType); + //Update the cached app services + cachedAppServicesCapabilities.updateAppServices(appServicesCapabilitiesList); + //Set the new capability object to the updated cached capabilities + capability = cachedAppServicesCapabilities; } break; + case DISPLAYS: + shouldConvertDeprecatedDisplayCapabilities = false; // Successfully got DISPLAYS data. No conversion needed anymore + // this notification can return only affected windows (hence not all windows) + List<DisplayCapability> newCapabilities = (List<DisplayCapability>) capability; + updateCachedDisplayCapabilityList(newCapabilities); } } - if(capability != null){ - setCapability(systemCapabilityType, capability); - } + if (capability != null) { + setCapability(systemCapabilityType, capability); + } } } } @@ -140,7 +312,8 @@ public class SystemCapabilityManager { } }; - if(callback != null){ + if (callback != null) { + callback.addOnRPCListener(FunctionID.GET_SYSTEM_CAPABILITY, rpcListener); callback.addOnRPCListener(FunctionID.SET_DISPLAY_LAYOUT, rpcListener); callback.addOnRPCListener(FunctionID.ON_SYSTEM_CAPABILITY_UPDATED, rpcListener); } diff --git a/base/src/main/java/com/smartdevicelink/proxy/interfaces/ISdl.java b/base/src/main/java/com/smartdevicelink/proxy/interfaces/ISdl.java index 8eaa74429..244c34395 100644 --- a/base/src/main/java/com/smartdevicelink/proxy/interfaces/ISdl.java +++ b/base/src/main/java/com/smartdevicelink/proxy/interfaces/ISdl.java @@ -263,4 +263,8 @@ public interface ISdl { */ @NonNull Version getProtocolVersion(); + /** + * Start encrypted RPC service + */ + void startRPCEncryption(); } diff --git a/base/src/main/java/com/smartdevicelink/proxy/rpc/CreateWindow.java b/base/src/main/java/com/smartdevicelink/proxy/rpc/CreateWindow.java index c2066f1c4..d0ac5807c 100644 --- a/base/src/main/java/com/smartdevicelink/proxy/rpc/CreateWindow.java +++ b/base/src/main/java/com/smartdevicelink/proxy/rpc/CreateWindow.java @@ -1,9 +1,11 @@ package com.smartdevicelink.proxy.rpc;
import android.support.annotation.NonNull;
+
import com.smartdevicelink.protocol.enums.FunctionID;
import com.smartdevicelink.proxy.RPCRequest;
import com.smartdevicelink.proxy.rpc.enums.WindowType;
+
import java.util.Hashtable;
/**
diff --git a/base/src/main/java/com/smartdevicelink/proxy/rpc/CreateWindowResponse.java b/base/src/main/java/com/smartdevicelink/proxy/rpc/CreateWindowResponse.java index 86dac3602..733283462 100644 --- a/base/src/main/java/com/smartdevicelink/proxy/rpc/CreateWindowResponse.java +++ b/base/src/main/java/com/smartdevicelink/proxy/rpc/CreateWindowResponse.java @@ -1,9 +1,11 @@ package com.smartdevicelink.proxy.rpc;
import android.support.annotation.NonNull;
+
import com.smartdevicelink.protocol.enums.FunctionID;
import com.smartdevicelink.proxy.RPCResponse;
import com.smartdevicelink.proxy.rpc.enums.Result;
+
import java.util.Hashtable;
/**
diff --git a/base/src/main/java/com/smartdevicelink/proxy/rpc/DeleteWindow.java b/base/src/main/java/com/smartdevicelink/proxy/rpc/DeleteWindow.java index 52cca2a04..3c766deeb 100644 --- a/base/src/main/java/com/smartdevicelink/proxy/rpc/DeleteWindow.java +++ b/base/src/main/java/com/smartdevicelink/proxy/rpc/DeleteWindow.java @@ -1,8 +1,10 @@ package com.smartdevicelink.proxy.rpc;
import android.support.annotation.NonNull;
+
import com.smartdevicelink.protocol.enums.FunctionID;
import com.smartdevicelink.proxy.RPCRequest;
+
import java.util.Hashtable;
/**
diff --git a/base/src/main/java/com/smartdevicelink/proxy/rpc/DeleteWindowResponse.java b/base/src/main/java/com/smartdevicelink/proxy/rpc/DeleteWindowResponse.java index d519e11d9..d943e860b 100644 --- a/base/src/main/java/com/smartdevicelink/proxy/rpc/DeleteWindowResponse.java +++ b/base/src/main/java/com/smartdevicelink/proxy/rpc/DeleteWindowResponse.java @@ -1,9 +1,11 @@ package com.smartdevicelink.proxy.rpc;
import android.support.annotation.NonNull;
+
import com.smartdevicelink.protocol.enums.FunctionID;
import com.smartdevicelink.proxy.RPCResponse;
import com.smartdevicelink.proxy.rpc.enums.Result;
+
import java.util.Hashtable;
/**
diff --git a/base/src/main/java/com/smartdevicelink/proxy/rpc/DisplayCapability.java b/base/src/main/java/com/smartdevicelink/proxy/rpc/DisplayCapability.java index 3d8862d1b..992083689 100644 --- a/base/src/main/java/com/smartdevicelink/proxy/rpc/DisplayCapability.java +++ b/base/src/main/java/com/smartdevicelink/proxy/rpc/DisplayCapability.java @@ -1,6 +1,7 @@ package com.smartdevicelink.proxy.rpc; import com.smartdevicelink.proxy.RPCStruct; + import java.util.Hashtable; import java.util.List; diff --git a/base/src/main/java/com/smartdevicelink/proxy/rpc/OnPermissionsChange.java b/base/src/main/java/com/smartdevicelink/proxy/rpc/OnPermissionsChange.java index 4f5845e4a..7a9532e36 100644 --- a/base/src/main/java/com/smartdevicelink/proxy/rpc/OnPermissionsChange.java +++ b/base/src/main/java/com/smartdevicelink/proxy/rpc/OnPermissionsChange.java @@ -1,34 +1,34 @@ -/* - * Copyright (c) 2017 - 2019, SmartDeviceLink Consortium, 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 SmartDeviceLink Consortium, 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. - */ +/*
+ * Copyright (c) 2017 - 2019, SmartDeviceLink Consortium, 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 SmartDeviceLink Consortium, 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.
+ */
package com.smartdevicelink.proxy.rpc;
import android.support.annotation.NonNull;
@@ -82,6 +82,7 @@ import java.util.List; */
public class OnPermissionsChange extends RPCNotification {
public static final String KEY_PERMISSION_ITEM = "permissionItem";
+ public static final String KEY_REQUIRE_ENCRYPTION = "requireEncryption";
/**
*Constructs a newly allocated OnCommand object
*/
@@ -118,4 +119,20 @@ public class OnPermissionsChange extends RPCNotification { public void setPermissionItem(@NonNull List<PermissionItem> permissionItem) {
setParameters(KEY_PERMISSION_ITEM, permissionItem);
}
+
+ /**
+ * Returns the encryption requirement for this permission change
+ * @return true if encryption is required, false otherwise
+ */
+ public Boolean getRequireEncryption() {
+ return getBoolean(KEY_REQUIRE_ENCRYPTION);
+ }
+
+ /**
+ * Sets the encryption requirement for this permission change
+ * @param isRequired the boolean requirement to be set
+ */
+ public void setRequireEncryption(Boolean isRequired) {
+ setParameters(KEY_REQUIRE_ENCRYPTION, isRequired);
+ }
}
diff --git a/base/src/main/java/com/smartdevicelink/proxy/rpc/PermissionItem.java b/base/src/main/java/com/smartdevicelink/proxy/rpc/PermissionItem.java index 7b5801b96..63d9624f7 100644 --- a/base/src/main/java/com/smartdevicelink/proxy/rpc/PermissionItem.java +++ b/base/src/main/java/com/smartdevicelink/proxy/rpc/PermissionItem.java @@ -1,34 +1,34 @@ -/* - * Copyright (c) 2017 - 2019, SmartDeviceLink Consortium, 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 SmartDeviceLink Consortium, 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. - */ +/*
+ * Copyright (c) 2017 - 2019, SmartDeviceLink Consortium, 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 SmartDeviceLink Consortium, 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.
+ */
package com.smartdevicelink.proxy.rpc;
@@ -83,6 +83,7 @@ public class PermissionItem extends RPCStruct { public static final String KEY_RPC_NAME = "rpcName";
public static final String KEY_HMI_PERMISSIONS = "hmiPermissions";
public static final String KEY_PARAMETER_PERMISSIONS = "parameterPermissions";
+ public static final String KEY_REQUIRE_ENCRYPTION = "requireEncryption";
/**
* Constructs a new PermissionItem object
*/
@@ -125,4 +126,20 @@ public class PermissionItem extends RPCStruct { public void setParameterPermissions(@NonNull ParameterPermissions parameterPermissions) {
setValue(KEY_PARAMETER_PERMISSIONS, parameterPermissions);
}
+
+ /**
+ * Gets the encryption requirement for this item
+ * @return true is encryption is required, false otherwise
+ */
+ public Boolean getRequireEncryption() {
+ return (Boolean) getValue(KEY_REQUIRE_ENCRYPTION);
+ }
+
+ /**
+ * Sets the encryption requirement for this item
+ * @param isRequired the boolean requirement to be set
+ */
+ public void setRequireEncryption(Boolean isRequired) {
+ setValue(KEY_REQUIRE_ENCRYPTION, isRequired);
+ }
}
diff --git a/base/src/main/java/com/smartdevicelink/proxy/rpc/SystemCapability.java b/base/src/main/java/com/smartdevicelink/proxy/rpc/SystemCapability.java index 2ea186742..73634c17b 100644 --- a/base/src/main/java/com/smartdevicelink/proxy/rpc/SystemCapability.java +++ b/base/src/main/java/com/smartdevicelink/proxy/rpc/SystemCapability.java @@ -37,7 +37,6 @@ import com.smartdevicelink.proxy.RPCStruct; import com.smartdevicelink.proxy.rpc.enums.SystemCapabilityType; import java.util.Hashtable; -import java.util.List; /** * Struct that indicates the a SystemCapabilityType and houses different structs to describe particular capabilities @@ -83,46 +82,46 @@ public class SystemCapability extends RPCStruct { } public Object getCapabilityForType(SystemCapabilityType type) { - if(type == null) { + if (type == null) { return null; - }else if (type.equals(SystemCapabilityType.NAVIGATION)) { + } else if (type.equals(SystemCapabilityType.NAVIGATION)) { return getObject(NavigationCapability.class, KEY_NAVIGATION_CAPABILITY); } else if (type.equals(SystemCapabilityType.PHONE_CALL)) { return getObject(PhoneCapability.class, KEY_PHONE_CAPABILITY); - } else if (type.equals(SystemCapabilityType.VIDEO_STREAMING)){ + } else if (type.equals(SystemCapabilityType.VIDEO_STREAMING)) { return getObject(VideoStreamingCapability.class, KEY_VIDEO_STREAMING_CAPABILITY); - }else if(type.equals(SystemCapabilityType.REMOTE_CONTROL)){ + } else if (type.equals(SystemCapabilityType.REMOTE_CONTROL)) { return getObject(RemoteControlCapabilities.class, KEY_REMOTE_CONTROL_CAPABILITY); - }else if(type.equals(SystemCapabilityType.APP_SERVICES)){ - return (RPCStruct) getObject(AppServicesCapabilities.class, KEY_APP_SERVICES_CAPABILITIES); - }else if(type.equals(SystemCapabilityType.SEAT_LOCATION)){ - return (RPCStruct) getObject(SeatLocationCapability.class, KEY_SEAT_LOCATION_CAPABILITY); - }else if(type.equals(SystemCapabilityType.DISPLAYS)){ + } else if (type.equals(SystemCapabilityType.APP_SERVICES)) { + return getObject(AppServicesCapabilities.class, KEY_APP_SERVICES_CAPABILITIES); + } else if (type.equals(SystemCapabilityType.SEAT_LOCATION)) { + return getObject(SeatLocationCapability.class, KEY_SEAT_LOCATION_CAPABILITY); + } else if (type.equals(SystemCapabilityType.DISPLAYS)) { return getObject(DisplayCapability.class, KEY_DISPLAY_CAPABILITIES); - }else{ + } else { return null; } } - public void setCapabilityForType(SystemCapabilityType type, Object capability){ - if(type == null) { + public void setCapabilityForType(SystemCapabilityType type, Object capability) { + if (type == null) { return; - }else if(type.equals(SystemCapabilityType.NAVIGATION)){ + } else if (type.equals(SystemCapabilityType.NAVIGATION)) { setValue(KEY_NAVIGATION_CAPABILITY, capability); - }else if(type.equals(SystemCapabilityType.PHONE_CALL)){ + } else if (type.equals(SystemCapabilityType.PHONE_CALL)) { setValue(KEY_PHONE_CAPABILITY, capability); - }else if(type.equals(SystemCapabilityType.VIDEO_STREAMING)){ + } else if (type.equals(SystemCapabilityType.VIDEO_STREAMING)) { setValue(KEY_VIDEO_STREAMING_CAPABILITY, capability); - }else if(type.equals(SystemCapabilityType.REMOTE_CONTROL)){ + } else if (type.equals(SystemCapabilityType.REMOTE_CONTROL)) { setValue(KEY_REMOTE_CONTROL_CAPABILITY, capability); - }else if(type.equals(SystemCapabilityType.APP_SERVICES)){ - setValue(KEY_APP_SERVICES_CAPABILITIES, capability); - }else if(type.equals(SystemCapabilityType.SEAT_LOCATION)){ + } else if (type.equals(SystemCapabilityType.APP_SERVICES)) { + setValue(KEY_APP_SERVICES_CAPABILITIES, capability); + } else if (type.equals(SystemCapabilityType.SEAT_LOCATION)) { setValue(KEY_SEAT_LOCATION_CAPABILITY, capability); - }else if(type.equals(SystemCapabilityType.DISPLAYS)) { + } else if (type.equals(SystemCapabilityType.DISPLAYS)) { setValue(KEY_DISPLAY_CAPABILITIES, capability); - }else{ - return; + } else { + return; } } diff --git a/base/src/main/java/com/smartdevicelink/proxy/rpc/TemplateConfiguration.java b/base/src/main/java/com/smartdevicelink/proxy/rpc/TemplateConfiguration.java index ed9c4c3d3..a92e8e28a 100644 --- a/base/src/main/java/com/smartdevicelink/proxy/rpc/TemplateConfiguration.java +++ b/base/src/main/java/com/smartdevicelink/proxy/rpc/TemplateConfiguration.java @@ -1,7 +1,9 @@ package com.smartdevicelink.proxy.rpc;
import android.support.annotation.NonNull;
+
import com.smartdevicelink.proxy.RPCStruct;
+
import java.util.Hashtable;
/**
diff --git a/base/src/main/java/com/smartdevicelink/proxy/rpc/WindowTypeCapabilities.java b/base/src/main/java/com/smartdevicelink/proxy/rpc/WindowTypeCapabilities.java index c4071e93c..f57d9a415 100644 --- a/base/src/main/java/com/smartdevicelink/proxy/rpc/WindowTypeCapabilities.java +++ b/base/src/main/java/com/smartdevicelink/proxy/rpc/WindowTypeCapabilities.java @@ -1,8 +1,10 @@ package com.smartdevicelink.proxy.rpc;
import android.support.annotation.NonNull;
+
import com.smartdevicelink.proxy.RPCStruct;
import com.smartdevicelink.proxy.rpc.enums.WindowType;
+
import java.util.Hashtable;
/**
diff --git a/base/src/main/java/com/smartdevicelink/proxy/rpc/enums/Result.java b/base/src/main/java/com/smartdevicelink/proxy/rpc/enums/Result.java index 1df3bcba5..7bc9454aa 100644 --- a/base/src/main/java/com/smartdevicelink/proxy/rpc/enums/Result.java +++ b/base/src/main/java/com/smartdevicelink/proxy/rpc/enums/Result.java @@ -1,34 +1,34 @@ -/* - * Copyright (c) 2017 - 2019, SmartDeviceLink Consortium, 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 SmartDeviceLink Consortium, 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. - */ +/*
+ * Copyright (c) 2017 - 2019, SmartDeviceLink Consortium, 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 SmartDeviceLink Consortium, 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.
+ */
package com.smartdevicelink.proxy.rpc.enums;
/**
@@ -212,6 +212,10 @@ public enum Result { * The data sent failed to pass CRC check in receiver end
*/
CORRUPTED_DATA,
+ /**
+ * The data sent needs to be encrypted
+ */
+ ENCRYPTION_NEEDED,
;
/**
diff --git a/base/src/main/java/com/smartdevicelink/proxy/rpc/enums/SystemCapabilityType.java b/base/src/main/java/com/smartdevicelink/proxy/rpc/enums/SystemCapabilityType.java index cdd8b01a5..758a33905 100644 --- a/base/src/main/java/com/smartdevicelink/proxy/rpc/enums/SystemCapabilityType.java +++ b/base/src/main/java/com/smartdevicelink/proxy/rpc/enums/SystemCapabilityType.java @@ -288,6 +288,7 @@ public enum SystemCapabilityType { * </tr> * </table> */ + @Deprecated DISPLAY (false), @@ -399,6 +400,7 @@ public enum SystemCapabilityType { * </tr> * </table> */ + @Deprecated BUTTON (false), /** @@ -441,6 +443,7 @@ public enum SystemCapabilityType { * </tr> * </table> */ + @Deprecated PRESET_BANK (false), /** @@ -464,6 +467,7 @@ public enum SystemCapabilityType { * </tr> * </table> */ + @Deprecated SOFTBUTTON (false), /** diff --git a/baseAndroid/src/main/java/com/smartdevicelink/managers/ServiceEncryptionListener.java b/baseAndroid/src/main/java/com/smartdevicelink/managers/ServiceEncryptionListener.java new file mode 120000 index 000000000..f35552f46 --- /dev/null +++ b/baseAndroid/src/main/java/com/smartdevicelink/managers/ServiceEncryptionListener.java @@ -0,0 +1 @@ +../../../../../../../base/src/main/java/com/smartdevicelink/managers/ServiceEncryptionListener.java
\ No newline at end of file diff --git a/javaSE/src/main/java/com/smartdevicelink/managers/SdlManager.java b/javaSE/src/main/java/com/smartdevicelink/managers/SdlManager.java index 99e29a109..29278b51e 100644 --- a/javaSE/src/main/java/com/smartdevicelink/managers/SdlManager.java +++ b/javaSE/src/main/java/com/smartdevicelink/managers/SdlManager.java @@ -34,6 +34,7 @@ package com.smartdevicelink.managers; import android.support.annotation.NonNull; import android.util.Log; + import com.smartdevicelink.managers.file.FileManager; import com.smartdevicelink.managers.file.filetypes.SdlArtwork; import com.smartdevicelink.managers.lifecycle.LifecycleConfigurationUpdate; @@ -47,7 +48,12 @@ import com.smartdevicelink.proxy.RPCRequest; import com.smartdevicelink.proxy.RPCResponse; import com.smartdevicelink.proxy.SystemCapabilityManager; import com.smartdevicelink.proxy.interfaces.ISdl; -import com.smartdevicelink.proxy.rpc.*; +import com.smartdevicelink.proxy.rpc.ChangeRegistration; +import com.smartdevicelink.proxy.rpc.OnHMIStatus; +import com.smartdevicelink.proxy.rpc.RegisterAppInterfaceResponse; +import com.smartdevicelink.proxy.rpc.SetAppIcon; +import com.smartdevicelink.proxy.rpc.TTSChunk; +import com.smartdevicelink.proxy.rpc.TemplateColorScheme; import com.smartdevicelink.proxy.rpc.enums.AppHMIType; import com.smartdevicelink.proxy.rpc.enums.Language; import com.smartdevicelink.proxy.rpc.enums.Result; @@ -61,9 +67,13 @@ import com.smartdevicelink.transport.BaseTransportConfig; import com.smartdevicelink.transport.enums.TransportType; import com.smartdevicelink.util.DebugTool; import com.smartdevicelink.util.Version; + import org.json.JSONException; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Vector; /** @@ -85,6 +95,7 @@ public class SdlManager extends BaseSdlManager{ private SdlArtwork appIcon; private SdlManagerListener managerListener; private List<Class<? extends SdlSecurityBase>> sdlSecList; + private ServiceEncryptionListener serviceEncryptionListener; // Managers @@ -191,7 +202,7 @@ public class SdlManager extends BaseSdlManager{ private void notifyDevListener(String info) { if (managerListener != null) { if (getState() == BaseSubManager.ERROR){ - managerListener.onError(this,info, null); + managerListener.onError(this, info, null); } else { managerListener.onStart(this); } @@ -313,7 +324,6 @@ public class SdlManager extends BaseSdlManager{ // MANAGER GETTERS - /** * Gets the PermissionManager. <br> * <strong>Note: PermissionManager should be used only after SdlManager.start() CompletionListener callback is completed successfully.</strong> @@ -536,7 +546,7 @@ public class SdlManager extends BaseSdlManager{ _internalInterface = lifecycleManager.getInternalInterface(SdlManager.this); if (sdlSecList != null && !sdlSecList.isEmpty()) { - lifecycleManager.setSdlSecurityClassList(sdlSecList); + lifecycleManager.setSdlSecurity(sdlSecList, serviceEncryptionListener); } //Setup the notification queue @@ -708,12 +718,24 @@ public class SdlManager extends BaseSdlManager{ * Sets the Security libraries * @param secList The list of security class(es) */ + @Deprecated public Builder setSdlSecurity(List<Class<? extends SdlSecurityBase>> secList) { sdlManager.sdlSecList = secList; return this; } /** + * Sets the security libraries and a callback to notify caller when there is update to encryption service + * @param secList The list of security class(es) + * @param listener The callback object + */ + public Builder setSdlSecurity(@NonNull List<Class<? extends SdlSecurityBase>> secList, ServiceEncryptionListener listener) { + sdlManager.sdlSecList = secList; + sdlManager.serviceEncryptionListener = listener; + return this; + } + + /** * Set the SdlManager Listener * @param listener the listener */ @@ -771,4 +793,12 @@ public class SdlManager extends BaseSdlManager{ } } + /** + * Start a secured RPC service + */ + public void startRPCEncryption() { + if (lifecycleManager != null) { + lifecycleManager.startRPCEncryption(); + } + } } diff --git a/javaSE/src/main/java/com/smartdevicelink/managers/lifecycle/EncryptionLifecycleManager.java b/javaSE/src/main/java/com/smartdevicelink/managers/lifecycle/EncryptionLifecycleManager.java new file mode 100644 index 000000000..1d5915bf4 --- /dev/null +++ b/javaSE/src/main/java/com/smartdevicelink/managers/lifecycle/EncryptionLifecycleManager.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2019 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. + */ + +package com.smartdevicelink.managers.lifecycle; + +import android.support.annotation.NonNull; + +import com.smartdevicelink.managers.ServiceEncryptionListener; +import com.smartdevicelink.proxy.interfaces.ISdl; + +class EncryptionLifecycleManager extends BaseEncryptionLifecycleManager { + + EncryptionLifecycleManager(@NonNull ISdl internalInterface, ServiceEncryptionListener listener) { + super(internalInterface, listener); + } +} diff --git a/javaSE/src/main/java/com/smartdevicelink/managers/lifecycle/LifecycleManager.java b/javaSE/src/main/java/com/smartdevicelink/managers/lifecycle/LifecycleManager.java index 9e3314672..7b2d3ec32 100644 --- a/javaSE/src/main/java/com/smartdevicelink/managers/lifecycle/LifecycleManager.java +++ b/javaSE/src/main/java/com/smartdevicelink/managers/lifecycle/LifecycleManager.java @@ -32,22 +32,60 @@ package com.smartdevicelink.managers.lifecycle; +import android.support.annotation.NonNull; import android.support.annotation.RestrictTo; import android.util.Log; + import com.smartdevicelink.SdlConnection.ISdlConnectionListener; import com.smartdevicelink.SdlConnection.SdlSession; import com.smartdevicelink.exception.SdlException; import com.smartdevicelink.managers.SdlManager; +import com.smartdevicelink.managers.ServiceEncryptionListener; import com.smartdevicelink.marshal.JsonRPCMarshaller; import com.smartdevicelink.protocol.ProtocolMessage; import com.smartdevicelink.protocol.enums.FunctionID; import com.smartdevicelink.protocol.enums.MessageType; import com.smartdevicelink.protocol.enums.SessionType; -import com.smartdevicelink.proxy.*; -import com.smartdevicelink.proxy.interfaces.*; -import com.smartdevicelink.proxy.rpc.*; -import com.smartdevicelink.proxy.rpc.enums.*; -import com.smartdevicelink.proxy.rpc.listeners.*; +import com.smartdevicelink.proxy.RPCMessage; +import com.smartdevicelink.proxy.RPCNotification; +import com.smartdevicelink.proxy.RPCRequest; +import com.smartdevicelink.proxy.RPCResponse; +import com.smartdevicelink.proxy.SystemCapabilityManager; +import com.smartdevicelink.proxy.interfaces.IAudioStreamListener; +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.OnAppInterfaceUnregistered; +import com.smartdevicelink.proxy.rpc.OnButtonEvent; +import com.smartdevicelink.proxy.rpc.OnButtonPress; +import com.smartdevicelink.proxy.rpc.OnHMIStatus; +import com.smartdevicelink.proxy.rpc.OnSystemRequest; +import com.smartdevicelink.proxy.rpc.RegisterAppInterface; +import com.smartdevicelink.proxy.rpc.RegisterAppInterfaceResponse; +import com.smartdevicelink.proxy.rpc.SdlMsgVersion; +import com.smartdevicelink.proxy.rpc.SubscribeButton; +import com.smartdevicelink.proxy.rpc.SystemRequest; +import com.smartdevicelink.proxy.rpc.TTSChunk; +import com.smartdevicelink.proxy.rpc.TemplateColorScheme; +import com.smartdevicelink.proxy.rpc.UnregisterAppInterface; +import com.smartdevicelink.proxy.rpc.VehicleType; +import com.smartdevicelink.proxy.rpc.enums.AppHMIType; +import com.smartdevicelink.proxy.rpc.enums.AppInterfaceUnregisteredReason; +import com.smartdevicelink.proxy.rpc.enums.ButtonName; +import com.smartdevicelink.proxy.rpc.enums.FileType; +import com.smartdevicelink.proxy.rpc.enums.HMILevel; +import com.smartdevicelink.proxy.rpc.enums.Language; +import com.smartdevicelink.proxy.rpc.enums.RequestType; +import com.smartdevicelink.proxy.rpc.enums.Result; +import com.smartdevicelink.proxy.rpc.enums.SdlDisconnectedReason; +import com.smartdevicelink.proxy.rpc.enums.SystemCapabilityType; +import com.smartdevicelink.proxy.rpc.listeners.OnMultipleRequestListener; +import com.smartdevicelink.proxy.rpc.listeners.OnPutFileUpdateListener; +import com.smartdevicelink.proxy.rpc.listeners.OnRPCListener; +import com.smartdevicelink.proxy.rpc.listeners.OnRPCNotificationListener; +import com.smartdevicelink.proxy.rpc.listeners.OnRPCRequestListener; +import com.smartdevicelink.proxy.rpc.listeners.OnRPCResponseListener; import com.smartdevicelink.security.SdlSecurityBase; import com.smartdevicelink.streaming.audio.AudioStreamingCodec; import com.smartdevicelink.streaming.audio.AudioStreamingParams; @@ -64,7 +102,7 @@ import java.util.Vector; import java.util.concurrent.CopyOnWriteArrayList; /** - * The lifecycle manager creates a centeral point for all SDL session logic to converge. It should only be used by + * The lifecycle manager creates a central point for all SDL session logic to converge. It should only be used by * the library itself. Usage outside the library is not permitted and will not be protected for in the future. */ @RestrictTo(RestrictTo.Scope.LIBRARY) @@ -100,6 +138,7 @@ public class LifecycleManager extends BaseLifecycleManager { private final HashMap<Integer, CopyOnWriteArrayList<OnRPCRequestListener>> rpcRequestListeners; protected final SystemCapabilityManager systemCapabilityManager; + private EncryptionLifecycleManager encryptionLifecycleManager; protected RegisterAppInterfaceResponse raiResponse = null; @@ -128,7 +167,6 @@ public class LifecycleManager extends BaseLifecycleManager { this.session = new SdlSession(sdlConnectionListener, config); this.systemCapabilityManager = new SystemCapabilityManager(internalInterface); - } public void start(){ @@ -141,6 +179,15 @@ public class LifecycleManager extends BaseLifecycleManager { } + /** + * Start a secured RPC service + */ + public void startRPCEncryption() { + if (session != null) { + session.startService(SessionType.RPC, session.getSessionId(), true); + } + } + public void stop(){ session.close(); } @@ -735,7 +782,7 @@ public class LifecycleManager extends BaseLifecycleManager { message.format(rpcSpecVersion,true); byte[] msgBytes = JsonRPCMarshaller.marshall(message, (byte)getProtocolVersion().getMajor()); - ProtocolMessage pm = new ProtocolMessage(); + final ProtocolMessage pm = new ProtocolMessage(); pm.setData(msgBytes); if (session != null){ pm.setSessionID(session.getSessionId()); @@ -744,7 +791,24 @@ public class LifecycleManager extends BaseLifecycleManager { pm.setMessageType(MessageType.RPC); pm.setSessionType(SessionType.RPC); pm.setFunctionID(FunctionID.getFunctionId(message.getFunctionName())); - pm.setPayloadProtected(message.isPayloadProtected()); + + if (encryptionLifecycleManager != null && encryptionLifecycleManager.isEncryptionReady() && encryptionLifecycleManager.getRPCRequiresEncryption(message.getFunctionID())) { + pm.setPayloadProtected(true); + } else { + pm.setPayloadProtected(message.isPayloadProtected()); + } + if (pm.getPayloadProtected() && (encryptionLifecycleManager == null || !encryptionLifecycleManager.isEncryptionReady())){ + String errorInfo = "Trying to send an encrypted message and there is no secured service"; + if (message.getMessageType().equals((RPCMessage.KEY_REQUEST))) { + RPCRequest request = (RPCRequest) message; + OnRPCResponseListener listener = ((RPCRequest) message).getOnRPCResponseListener(); + if (listener != null) { + listener.onError(request.getCorrelationID(), Result.ABORTED, errorInfo); + } + } + DebugTool.logWarning(errorInfo); + return; + } if(RPCMessage.KEY_REQUEST.equals(message.getMessageType())){ // Request Specifics pm.setRPCType((byte)0x00); @@ -1113,6 +1177,11 @@ public class LifecycleManager extends BaseLifecycleManager { public Version getProtocolVersion() { return LifecycleManager.this.getProtocolVersion(); } + + @Override + public void startRPCEncryption() { + LifecycleManager.this.startRPCEncryption(); + } }; /* ******************************************************************************************************* @@ -1344,12 +1413,26 @@ public class LifecycleManager extends BaseLifecycleManager { if (session != null && session.getIsConnected()) { session.close(); } + if (encryptionLifecycleManager != null){ + encryptionLifecycleManager.dispose(); + } } + @Deprecated public void setSdlSecurityClassList(List<Class<? extends SdlSecurityBase>> list) { _secList = list; } + /** + * Sets the security libraries and a callback to notify caller when there is update to encryption service + * @param secList The list of security class(es) + * @param listener The callback object + */ + public void setSdlSecurity(@NonNull List<Class<? extends SdlSecurityBase>> secList, ServiceEncryptionListener listener) { + this._secList = secList; + this.encryptionLifecycleManager = new EncryptionLifecycleManager(internalInterface, listener); + } + private void processRaiResponse(RegisterAppInterfaceResponse rai) { if (rai == null) return; diff --git a/javaSE/src/main/java/com/smartdevicelink/managers/screen/choiceset/ChoiceSetManager.java b/javaSE/src/main/java/com/smartdevicelink/managers/screen/choiceset/ChoiceSetManager.java index f470b8a68..df14bfa6f 100644 --- a/javaSE/src/main/java/com/smartdevicelink/managers/screen/choiceset/ChoiceSetManager.java +++ b/javaSE/src/main/java/com/smartdevicelink/managers/screen/choiceset/ChoiceSetManager.java @@ -33,7 +33,6 @@ package com.smartdevicelink.managers.screen.choiceset; import android.support.annotation.NonNull; - import com.smartdevicelink.managers.file.FileManager; import com.smartdevicelink.proxy.interfaces.ISdl; |