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 c7c0df7e4a..59afe220b7 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 @@ -34,15 +34,18 @@ */ package com.smartdevicelink.managers.screen.choiceset; - import androidx.test.ext.junit.runners.AndroidJUnit4; import com.livio.taskmaster.Taskmaster; import com.smartdevicelink.managers.BaseSubManager; import com.smartdevicelink.managers.ISdl; import com.smartdevicelink.managers.file.FileManager; +import com.smartdevicelink.proxy.rpc.KeyboardCapabilities; +import com.smartdevicelink.proxy.rpc.KeyboardLayoutCapability; import com.smartdevicelink.proxy.rpc.KeyboardProperties; +import com.smartdevicelink.proxy.rpc.WindowCapability; import com.smartdevicelink.proxy.rpc.enums.HMILevel; +import com.smartdevicelink.proxy.rpc.enums.KeyboardInputMask; import com.smartdevicelink.proxy.rpc.enums.KeyboardLayout; import com.smartdevicelink.proxy.rpc.enums.KeypressMode; import com.smartdevicelink.proxy.rpc.enums.Language; @@ -54,6 +57,7 @@ import org.junit.Test; import org.junit.runner.RunWith; +import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -288,6 +292,116 @@ public void testPresentingKeyboardShouldNotReturnCancelIDIfKeyboardCannotBeSent( assertNull(cancelId); } + @Test + public void testDefaultWindowCapabilityNotSet() throws NoSuchFieldException, IllegalAccessException { + ISdl internalInterface = mock(ISdl.class); + when(internalInterface.getTaskmaster()).thenReturn(taskmaster); + FileManager fileManager = mock(FileManager.class); + + // Test direct set + ChoiceSetManager newCSM = new ChoiceSetManager(internalInterface, fileManager); + newCSM.setKeyboardConfiguration(newCSM.defaultKeyboardConfiguration()); + Field field = BaseChoiceSetManager.class.getDeclaredField("keyboardConfiguration"); + field.setAccessible(true); + KeyboardProperties properties = (KeyboardProperties)field.get(newCSM); + assertEquals(properties, csm.defaultKeyboardConfiguration()); + + // Test presentKeyboard + newCSM = new ChoiceSetManager(internalInterface, fileManager); + newCSM.presentKeyboard("qwerty", newCSM.defaultKeyboardConfiguration(), null); + field = BaseChoiceSetManager.class.getDeclaredField("keyboardConfiguration"); + field.setAccessible(true); + properties = (KeyboardProperties)field.get(newCSM); + assertEquals(properties, csm.defaultKeyboardConfiguration()); + } + + @Test + public void testDefaultWindowCapabilityTooManyKeys() throws NoSuchFieldException, IllegalAccessException { + ISdl internalInterface = mock(ISdl.class); + when(internalInterface.getTaskmaster()).thenReturn(taskmaster); + FileManager fileManager = mock(FileManager.class); + + ChoiceSetManager newCSM = new ChoiceSetManager(internalInterface, fileManager); + WindowCapability smallKeysAmountCapability = new WindowCapability(); + KeyboardCapabilities capabilities = new KeyboardCapabilities(); + capabilities.setMaskInputCharactersSupported(true); + KeyboardLayout layout = KeyboardLayout.QWERTY; + capabilities.setSupportedKeyboards(Collections.singletonList(new KeyboardLayoutCapability(layout, 1))); + smallKeysAmountCapability.setKeyboardCapabilities(capabilities); + newCSM.defaultMainWindowCapability = smallKeysAmountCapability; + + KeyboardProperties setProperties = new KeyboardProperties(); + setProperties.setKeyboardLayout(layout); + setProperties.setCustomKeys(Arrays.asList("1", "2")); + + newCSM.setKeyboardConfiguration(setProperties); + Field field = BaseChoiceSetManager.class.getDeclaredField("keyboardConfiguration"); + field.setAccessible(true); + + KeyboardProperties getProperties = (KeyboardProperties)field.get(newCSM); + + assertEquals(getProperties.getCustomKeys().size(), 1); + } + + @Test + public void testCustomKeysNull() throws NoSuchFieldException, IllegalAccessException { + ISdl internalInterface = mock(ISdl.class); + when(internalInterface.getTaskmaster()).thenReturn(taskmaster); + FileManager fileManager = mock(FileManager.class); + + ChoiceSetManager newCSM = new ChoiceSetManager(internalInterface, fileManager); + WindowCapability smallKeysAmountCapability = new WindowCapability(); + KeyboardCapabilities capabilities = new KeyboardCapabilities(); + capabilities.setMaskInputCharactersSupported(true); + KeyboardLayout layout = KeyboardLayout.QWERTY; + capabilities.setSupportedKeyboards(Collections.singletonList(new KeyboardLayoutCapability(layout, 0))); + smallKeysAmountCapability.setKeyboardCapabilities(capabilities); + newCSM.defaultMainWindowCapability = smallKeysAmountCapability; + + KeyboardProperties setProperties = new KeyboardProperties(); + setProperties.setKeyboardLayout(layout); + setProperties.setCustomKeys(new ArrayList()); + + newCSM.setKeyboardConfiguration(setProperties); + Field field = BaseChoiceSetManager.class.getDeclaredField("keyboardConfiguration"); + field.setAccessible(true); + + KeyboardProperties getProperties = (KeyboardProperties)field.get(newCSM); + + assertNull(getProperties.getCustomKeys()); + } + + @Test + public void testMaskInputCharactersNotSupported() throws NoSuchFieldException, IllegalAccessException { + ISdl internalInterface = mock(ISdl.class); + when(internalInterface.getTaskmaster()).thenReturn(taskmaster); + FileManager fileManager = mock(FileManager.class); + + ChoiceSetManager newCSM = new ChoiceSetManager(internalInterface, fileManager); + WindowCapability maskInputNotSupportedCapability = new WindowCapability(); + KeyboardCapabilities capabilities = new KeyboardCapabilities(); + + capabilities.setMaskInputCharactersSupported(false); + KeyboardLayout layout = KeyboardLayout.QWERTY; + capabilities.setSupportedKeyboards(Collections.singletonList(new KeyboardLayoutCapability(layout, 0))); + + maskInputNotSupportedCapability.setKeyboardCapabilities(capabilities); + + newCSM.defaultMainWindowCapability = maskInputNotSupportedCapability; + + KeyboardProperties setProperties = new KeyboardProperties(); + setProperties.setKeyboardLayout(layout); + setProperties.setMaskInputCharacters(KeyboardInputMask.DISABLE_INPUT_KEY_MASK); + + newCSM.setKeyboardConfiguration(setProperties); + Field field = BaseChoiceSetManager.class.getDeclaredField("keyboardConfiguration"); + field.setAccessible(true); + + KeyboardProperties getProperties = (KeyboardProperties)field.get(newCSM); + + assertNull(getProperties.getMaskInputCharacters()); + } + @Test public void testDismissingExecutingKeyboard() { Integer testCancelID = 42; diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/TestValues.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/TestValues.java index eeafa2edb3..c82a200ade 100644 --- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/TestValues.java +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/TestValues.java @@ -57,6 +57,7 @@ import com.smartdevicelink.proxy.rpc.enums.ImageType; import com.smartdevicelink.proxy.rpc.enums.InteractionMode; import com.smartdevicelink.proxy.rpc.enums.KeyboardEvent; +import com.smartdevicelink.proxy.rpc.enums.KeyboardInputMask; import com.smartdevicelink.proxy.rpc.enums.KeyboardLayout; import com.smartdevicelink.proxy.rpc.enums.KeypressMode; import com.smartdevicelink.proxy.rpc.enums.Language; @@ -332,6 +333,7 @@ public class TestValues { public static final LightControlData GENERAL_LIGHTCONTROLDATA = new LightControlData(); public static final HMISettingsControlData GENERAL_HMISETTINGSCONTROLDATA = new HMISettingsControlData(); public static final DynamicUpdateCapabilities GENERAL_DYNAMICUPDATECAPABILITIES = new DynamicUpdateCapabilities(); + public static final KeyboardCapabilities GENERAL_KEYBOARD_CAPABILITIES = new KeyboardCapabilities(); public static final WindowState GENERAL_WINDOWSTATE = new WindowState(); public static final SeatOccupancy GENERAL_SEAT_OCCUPANCY = new SeatOccupancy(); @@ -384,6 +386,9 @@ public class TestValues { public static final List GENERAL_TURN_LIST = new ArrayList(); public static final List GENERAL_CHOICE_LIST = new ArrayList(); public static final List GENERAL_STRING_LIST = Arrays.asList(new String[]{"a", "b"}); + public static final KeyboardInputMask GENERAL_KEYBOARD_INPUT_MASK = KeyboardInputMask.ENABLE_INPUT_KEY_MASK; + public static final KeyboardLayoutCapability GENERAL_KEYBOARD_LAYOUT_CAPABILITY = new KeyboardLayoutCapability(GENERAL_KEYBOARDLAYOUT, 1); + public static final List GENERAL_SUPPORTED_KEYBOARDS_LIST = new ArrayList(); public static final List GENERAL_INTEGER_LIST = Arrays.asList(new Integer[]{-1, -2}); public static final List GENERAL_TTSCHUNK_LIST = new ArrayList(2); public static final List GENERAL_HMILEVEL_LIST = Arrays.asList(new HMILevel[]{HMILevel.HMI_FULL, HMILevel.HMI_BACKGROUND}); @@ -510,7 +515,9 @@ public void onVoiceCommandSelected() { public static final JSONArray JSON_IMAGE_TYPES = new JSONArray(); public static final JSONObject JSON_DISPLAYCAPABILITY = new JSONObject(); public static final JSONArray JSON_DISPLAYCAPABILITY_LIST = new JSONArray(); + public static final JSONArray JSON_SUPPORTED_KEYBOARDS_LIST = new JSONArray(); public static final JSONObject JSON_DYNAMICUPDATECAPABILITIES = new JSONObject(); + public static final JSONObject JSON_KEYBOARD_CAPABILITY = new JSONObject(); public static final JSONArray JSON_ROOF_STATUSES = new JSONArray(); public static final JSONArray JSON_DOOR_STATUSES = new JSONArray(); public static final JSONArray JSON_GATE_STATUSES = new JSONArray(); @@ -1085,6 +1092,10 @@ public void onVoiceCommandSelected() { GENERAL_STABILITY_CONTROL_STATUS.setEscSystem(GENERAL_ESC_SYSTEM); GENERAL_STABILITY_CONTROL_STATUS.setTrailerSwayControl(GENERAL_S_WAY_CONTROL); + GENERAL_SUPPORTED_KEYBOARDS_LIST.add(GENERAL_KEYBOARD_LAYOUT_CAPABILITY); + + GENERAL_KEYBOARD_CAPABILITIES.setMaskInputCharactersSupported(TestValues.GENERAL_BOOLEAN); + GENERAL_KEYBOARD_CAPABILITIES.setSupportedKeyboards(GENERAL_SUPPORTED_KEYBOARDS_LIST); // SEAT_OCCUPANCY GENERAL_SEAT_LOCATION.setGrid(GENERAL_LOCATION_GRID); @@ -1117,6 +1128,14 @@ public void onVoiceCommandSelected() { try { + for (KeyboardLayoutCapability keyboard : GENERAL_SUPPORTED_KEYBOARDS_LIST) { + JSON_SUPPORTED_KEYBOARDS_LIST.put(keyboard.serializeJSON()); + } + + JSON_KEYBOARD_CAPABILITY.put(KeyboardCapabilities.KEY_MASK_INPUT_CHARACTERS_SUPPORTED, GENERAL_BOOLEAN); + JSON_KEYBOARD_CAPABILITY.put(KeyboardCapabilities.KEY_SUPPORTED_KEYBOARDS, JSON_SUPPORTED_KEYBOARDS_LIST); + + JSON_OBJECT_GENERAL_SEATS_OCCUPIED.put(SeatStatus.KEY_SEAT_LOCATION, GENERAL_SEAT_LOCATION.serializeJSON()); JSON_OBJECT_GENERAL_SEATS_OCCUPIED.put(SeatStatus.KEY_CONDITION_ACTIVE, GENERAL_BOOLEAN); JSON_GENERAL_SEATS_OCCUPIED.put(JSON_OBJECT_GENERAL_SEATS_OCCUPIED); 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 6db76934fb..e8d89c818d 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 @@ -10,6 +10,7 @@ import com.smartdevicelink.proxy.rpc.enums.FileType; import com.smartdevicelink.proxy.rpc.enums.HMILevel; import com.smartdevicelink.proxy.rpc.enums.HmiZoneCapabilities; +import com.smartdevicelink.proxy.rpc.enums.KeyboardLayout; import com.smartdevicelink.proxy.rpc.enums.PRNDL; import com.smartdevicelink.proxy.rpc.enums.PrerecordedSpeech; import com.smartdevicelink.proxy.rpc.enums.SpeechCapabilities; @@ -3947,6 +3948,43 @@ public static boolean validateStabilityControlStatus(VehicleDataResult status1, return status1.getDataType().equals(status2.getDataType()) && status1.getResultCode().equals(status2.getResultCode()); } + public static boolean validateKeyboardLayoutCapability(KeyboardLayoutCapability keyboard1, KeyboardLayoutCapability keyboard2) { + if (keyboard1 == null) { + return (keyboard2 == null); + } + if (keyboard2 == null) { + return (keyboard1 == null); + } + return keyboard1.getKeyboardLayout().equals(keyboard2.getKeyboardLayout()) && keyboard1.getNumConfigurableKeys().equals(keyboard2.getNumConfigurableKeys()); + } + + public static boolean validateKeyboardCapabilities(KeyboardCapabilities keyboardCapabilities1, KeyboardCapabilities keyboardCapabilities2) { + if (keyboardCapabilities1 == null) { + return (keyboardCapabilities2 == null); + } + if (keyboardCapabilities2 == null) { + return (keyboardCapabilities1 == null); + } + + boolean keyboardsEqual = true; + if (keyboardCapabilities1.getSupportedKeyboards() != null && keyboardCapabilities2.getSupportedKeyboards() != null) { + + for (KeyboardLayoutCapability keyboardLayoutCapability1 : keyboardCapabilities1.getSupportedKeyboards()) { + for (KeyboardLayoutCapability keyboardLayoutCapability2 : keyboardCapabilities2.getSupportedKeyboards()) { + if (!validateKeyboardLayoutCapability(keyboardLayoutCapability1, keyboardLayoutCapability2)) { + keyboardsEqual = false; + break; + } + } + if (!keyboardsEqual) { + break; + } + } + } + + return keyboardsEqual && keyboardCapabilities1.getMaskInputCharactersSupported().equals(keyboardCapabilities2.getMaskInputCharactersSupported()); + } + public static boolean validateSeatStatuses(List seatStatusesItem1, List seatStatusesItem2) { if (seatStatusesItem1 == null) { return (seatStatusesItem2 == null); diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/KeyboardCapabilitiesTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/KeyboardCapabilitiesTests.java new file mode 100644 index 0000000000..13d8970d64 --- /dev/null +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/KeyboardCapabilitiesTests.java @@ -0,0 +1,82 @@ +package com.smartdevicelink.test.rpc.datatypes; + +import com.smartdevicelink.marshal.JsonRPCMarshaller; +import com.smartdevicelink.proxy.rpc.KeyboardCapabilities; +import com.smartdevicelink.proxy.rpc.KeyboardLayoutCapability; +import com.smartdevicelink.test.JsonUtils; +import com.smartdevicelink.test.TestValues; +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; + +public class KeyboardCapabilitiesTests extends TestCase { + private KeyboardCapabilities msg; + + @Override + public void setUp() { + msg = new KeyboardCapabilities(); + + msg.setMaskInputCharactersSupported(TestValues.GENERAL_BOOLEAN); + msg.setSupportedKeyboards(TestValues.GENERAL_SUPPORTED_KEYBOARDS_LIST); + } + + /** + * Tests the expected values of the RPC message. + */ + public void testRpcValues() { + // Test Values + Boolean maskInputCharactersSupported = msg.getMaskInputCharactersSupported(); + List supportedKeyboards = msg.getSupportedKeyboards(); + + // Valid Tests + assertEquals(TestValues.MATCH, TestValues.GENERAL_BOOLEAN, (boolean) maskInputCharactersSupported); + assertEquals(TestValues.MATCH, TestValues.GENERAL_SUPPORTED_KEYBOARDS_LIST, supportedKeyboards); + + // Invalid/Null Tests + KeyboardCapabilities msg = new KeyboardCapabilities(); + assertNotNull(TestValues.NOT_NULL, msg); + + assertNull(TestValues.NULL, msg.getMaskInputCharactersSupported()); + assertNull(TestValues.NULL, msg.getSupportedKeyboards()); + } + + public void testJson() { + JSONObject reference = new JSONObject(); + + try { + reference.put(KeyboardCapabilities.KEY_MASK_INPUT_CHARACTERS_SUPPORTED, TestValues.GENERAL_BOOLEAN); + reference.put(KeyboardCapabilities.KEY_SUPPORTED_KEYBOARDS, TestValues.JSON_SUPPORTED_KEYBOARDS_LIST); + + JSONObject underTest = msg.serializeJSON(); + assertEquals(TestValues.MATCH, reference.length(), underTest.length()); + + Iterator iterator = reference.keys(); + while (iterator.hasNext()) { + String key = (String) iterator.next(); + if (key.equals(KeyboardCapabilities.KEY_SUPPORTED_KEYBOARDS)) { + JSONArray referenceArray = JsonUtils.readJsonArrayFromJsonObject(reference, key); + JSONArray underTestArray = JsonUtils.readJsonArrayFromJsonObject(underTest, key); + assertEquals(TestValues.MATCH, referenceArray.length(), underTestArray.length()); + + for (int i = 0; i < referenceArray.length(); i++) { + Hashtable hashReference = JsonRPCMarshaller.deserializeJSONObject(referenceArray.getJSONObject(i)); + Hashtable hashTest = JsonRPCMarshaller.deserializeJSONObject(underTestArray.getJSONObject(i)); + assertTrue(TestValues.TRUE, Validator.validateKeyboardLayoutCapability(new KeyboardLayoutCapability(hashReference), new KeyboardLayoutCapability(hashTest))); + } + } else { + assertEquals(TestValues.MATCH, JsonUtils.readObjectFromJsonObject(reference, key), JsonUtils.readObjectFromJsonObject(underTest, key)); + } + } + } catch (JSONException e) { + fail(TestValues.JSON_FAIL); + } + } +} diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/KeyboardPropertiesTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/KeyboardPropertiesTests.java index e06bd5e0b0..2d02f10f7c 100644 --- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/KeyboardPropertiesTests.java +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/KeyboardPropertiesTests.java @@ -1,6 +1,7 @@ package com.smartdevicelink.test.rpc.datatypes; import com.smartdevicelink.proxy.rpc.KeyboardProperties; +import com.smartdevicelink.proxy.rpc.enums.KeyboardInputMask; import com.smartdevicelink.proxy.rpc.enums.KeyboardLayout; import com.smartdevicelink.proxy.rpc.enums.KeypressMode; import com.smartdevicelink.proxy.rpc.enums.Language; @@ -34,8 +35,11 @@ public void setUp() { msg.setKeypressMode(TestValues.GENERAL_KEYPRESSMODE); msg.setLanguage(TestValues.GENERAL_LANGUAGE); msg.setLimitedCharacterList(TestValues.GENERAL_STRING_LIST); + msg.setCustomKeys(TestValues.GENERAL_STRING_LIST); + msg.setMaskInputCharacters(TestValues.GENERAL_KEYBOARD_INPUT_MASK); } + /** * Tests the expected values of the RPC message. */ @@ -47,6 +51,8 @@ public void testRpcValues() { KeypressMode keypressMode = msg.getKeypressMode(); Language language = msg.getLanguage(); List limitedChars = msg.getLimitedCharacterList(); + KeyboardInputMask keyInputMask = msg.getMaskInputCharacters(); + List customKeys = msg.getCustomKeys(); // Valid Tests assertEquals(TestValues.MATCH, TestValues.GENERAL_STRING, autoCompleteText); @@ -57,6 +63,8 @@ public void testRpcValues() { assertEquals(TestValues.MATCH, TestValues.GENERAL_LANGUAGE, language); assertEquals(TestValues.MATCH, TestValues.GENERAL_STRING_LIST.size(), limitedChars.size()); assertTrue(TestValues.TRUE, Validator.validateStringList(TestValues.GENERAL_STRING_LIST, limitedChars)); + assertEquals(TestValues.MATCH, TestValues.GENERAL_KEYBOARD_INPUT_MASK, keyInputMask); + assertEquals(TestValues.MATCH, TestValues.GENERAL_STRING_LIST, customKeys); // Invalid/Null Tests KeyboardProperties msg = new KeyboardProperties(); @@ -69,6 +77,8 @@ public void testRpcValues() { assertNull(TestValues.NULL, msg.getLanguage()); assertNull(TestValues.NULL, msg.getKeyboardLayout()); assertNull(TestValues.NULL, msg.getLimitedCharacterList()); + assertNull(TestValues.NULL, msg.getMaskInputCharacters()); + assertNull(TestValues.NULL, msg.getCustomKeys()); } public void testJson() { @@ -81,6 +91,8 @@ public void testJson() { reference.put(KeyboardProperties.KEY_KEYPRESS_MODE, TestValues.GENERAL_KEYPRESSMODE); reference.put(KeyboardProperties.KEY_LANGUAGE, TestValues.GENERAL_LANGUAGE); reference.put(KeyboardProperties.KEY_LIMITED_CHARACTER_LIST, JsonUtils.createJsonArray(TestValues.GENERAL_STRING_LIST)); + reference.put(KeyboardProperties.KEY_CUSTOM_KEYS, JsonUtils.createJsonArray(TestValues.GENERAL_STRING_LIST)); + reference.put(KeyboardProperties.KEY_MASK_INPUT_CHARACTERS, TestValues.GENERAL_KEYBOARD_INPUT_MASK); JSONObject underTest = msg.serializeJSON(); assertEquals(TestValues.MATCH, reference.length(), underTest.length()); @@ -88,7 +100,7 @@ public void testJson() { Iterator iterator = reference.keys(); while (iterator.hasNext()) { String key = (String) iterator.next(); - if (key.equals(KeyboardProperties.KEY_LIMITED_CHARACTER_LIST) || key.equals(KeyboardProperties.KEY_AUTO_COMPLETE_LIST)) { + if (key.equals(KeyboardProperties.KEY_LIMITED_CHARACTER_LIST) || key.equals(KeyboardProperties.KEY_AUTO_COMPLETE_LIST) || key.equals(KeyboardProperties.KEY_CUSTOM_KEYS)) { assertTrue(TestValues.TRUE, Validator.validateStringList(JsonUtils.readStringListFromJsonObject(reference, key), JsonUtils.readStringListFromJsonObject(underTest, key))); } else { assertEquals(TestValues.MATCH, JsonUtils.readObjectFromJsonObject(reference, key), JsonUtils.readObjectFromJsonObject(underTest, key)); 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 cee5b5f84c..0ad5e466dc 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 @@ -4,6 +4,7 @@ import com.smartdevicelink.proxy.rpc.ButtonCapabilities; import com.smartdevicelink.proxy.rpc.DynamicUpdateCapabilities; import com.smartdevicelink.proxy.rpc.ImageField; +import com.smartdevicelink.proxy.rpc.KeyboardCapabilities; import com.smartdevicelink.proxy.rpc.SoftButtonCapabilities; import com.smartdevicelink.proxy.rpc.TextField; import com.smartdevicelink.proxy.rpc.WindowCapability; @@ -46,6 +47,7 @@ public void setUp() { msg.setSoftButtonCapabilities(TestValues.GENERAL_SOFTBUTTONCAPABILITIES_LIST); msg.setMenuLayoutsAvailable(TestValues.GENERAL_MENU_LAYOUT_LIST); msg.setDynamicUpdateCapabilities(TestValues.GENERAL_DYNAMICUPDATECAPABILITIES); + msg.setKeyboardCapabilities(TestValues.GENERAL_KEYBOARD_CAPABILITIES); } /** @@ -63,6 +65,7 @@ public void testRpcValues() { List softButtonCapabilities = msg.getSoftButtonCapabilities(); List menuLayouts = msg.getMenuLayoutsAvailable(); DynamicUpdateCapabilities dynamicUpdateCapabilities = msg.getDynamicUpdateCapabilities(); + KeyboardCapabilities keyboardCapabilities = msg.getKeyboardCapabilities(); // Valid Tests assertEquals(TestValues.MATCH, TestValues.GENERAL_INT, windowID); @@ -75,6 +78,7 @@ public void testRpcValues() { assertEquals(TestValues.MATCH, TestValues.GENERAL_SOFTBUTTONCAPABILITIES_LIST.size(), softButtonCapabilities.size()); assertEquals(TestValues.MATCH, TestValues.GENERAL_MENU_LAYOUT_LIST.size(), menuLayouts.size()); assertEquals(TestValues.MATCH, TestValues.GENERAL_DYNAMICUPDATECAPABILITIES, dynamicUpdateCapabilities); + assertEquals(TestValues.MATCH, TestValues.GENERAL_KEYBOARD_CAPABILITIES, keyboardCapabilities); for (int i = 0; i < TestValues.GENERAL_TEXTFIELD_LIST.size(); i++) { assertTrue(TestValues.TRUE, Validator.validateTextFields(TestValues.GENERAL_TEXTFIELD_LIST.get(i), textFields.get(i))); @@ -113,6 +117,7 @@ public void testRpcValues() { assertNull(TestValues.NULL, msg.getSoftButtonCapabilities()); assertNull(TestValues.NULL, msg.getMenuLayoutsAvailable()); assertNull(TestValues.NULL, msg.getDynamicUpdateCapabilities()); + assertNull(TestValues.NULL, msg.getKeyboardCapabilities()); } public void testJson() { @@ -129,6 +134,7 @@ public void testJson() { reference.put(WindowCapability.KEY_SOFT_BUTTON_CAPABILITIES, TestValues.JSON_SOFTBUTTONCAPABILITIES); reference.put(WindowCapability.KEY_MENU_LAYOUTS_AVAILABLE, JsonUtils.createJsonArray(TestValues.GENERAL_MENU_LAYOUT_LIST)); reference.put(WindowCapability.KEY_DYNAMIC_UPDATE_CAPABILITIES, TestValues.JSON_DYNAMICUPDATECAPABILITIES); + reference.put(WindowCapability.KEY_KEYBOARD_CAPABILITIES, TestValues.JSON_KEYBOARD_CAPABILITY); JSONObject underTest = msg.serializeJSON(); assertEquals(TestValues.MATCH, reference.length(), underTest.length()); @@ -214,6 +220,13 @@ public void testJson() { imageFieldNameListTest.add((ImageFieldName) underTestArray.get(i)); } assertTrue(TestValues.TRUE, imageFieldNameListReference.containsAll(imageFieldNameListTest) && imageFieldNameListTest.containsAll(imageFieldNameListReference)); + } else if (key.equals(WindowCapability.KEY_KEYBOARD_CAPABILITIES)){ + JSONObject jsonReference = JsonUtils.readJsonObjectFromJsonObject(reference, key); + JSONObject jsonUnderTest = JsonUtils.readJsonObjectFromJsonObject(underTest, key); + + Hashtable hashReference = JsonRPCMarshaller.deserializeJSONObject(jsonReference); + Hashtable hashTest = JsonRPCMarshaller.deserializeJSONObject(jsonUnderTest); + assertTrue(TestValues.TRUE, Validator.validateKeyboardCapabilities(new KeyboardCapabilities(hashReference), new KeyboardCapabilities(hashTest))); } else { assertEquals(TestValues.MATCH, JsonUtils.readObjectFromJsonObject(reference, key), JsonUtils.readObjectFromJsonObject(underTest, key)); } diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/KeyboardEventTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/KeyboardEventTests.java index 13a28cfda6..740603fe4f 100644 --- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/KeyboardEventTests.java +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/KeyboardEventTests.java @@ -28,12 +28,18 @@ public void testValidEnums() { KeyboardEvent enumEntryAborted = KeyboardEvent.valueForString(example); example = "ENTRY_VOICE"; KeyboardEvent enumEntryVoice = KeyboardEvent.valueForString(example); + example = "INPUT_KEY_MASK_ENABLED"; + KeyboardEvent enumInputMaskEnabled = KeyboardEvent.valueForString(example); + example = "INPUT_KEY_MASK_DISABLED"; + KeyboardEvent enumInputMaskDisabled = KeyboardEvent.valueForString(example); assertNotNull("KEYPRESS returned null", enumKeypress); assertNotNull("ENTRY_SUBMITTED returned null", enumEntrySubmitted); assertNotNull("ENTRY_CANCELLED returned null", enumEntryCancelled); assertNotNull("ENTRY_ABORTED returned null", enumEntryAborted); assertNotNull("ENTRY_VOICE returned null", enumEntryVoice); + assertNotNull("INPUT_KEY_MASK_ENABLED returned null", enumInputMaskEnabled); + assertNotNull("INPUT_KEY_MASK_DISABLED returned null", enumInputMaskDisabled); } /** @@ -74,6 +80,8 @@ public void testListEnum() { enumTestList.add(KeyboardEvent.ENTRY_CANCELLED); enumTestList.add(KeyboardEvent.ENTRY_ABORTED); enumTestList.add(KeyboardEvent.ENTRY_VOICE); + enumTestList.add(KeyboardEvent.INPUT_KEY_MASK_ENABLED); + enumTestList.add(KeyboardEvent.INPUT_KEY_MASK_DISABLED); 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/KeyboardInputMaskTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/KeyboardInputMaskTests.java new file mode 100644 index 0000000000..66cee940c5 --- /dev/null +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/KeyboardInputMaskTests.java @@ -0,0 +1,69 @@ +package com.smartdevicelink.test.rpc.enums; + +import com.smartdevicelink.proxy.rpc.enums.KeyboardInputMask; + +import junit.framework.TestCase; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class KeyboardInputMaskTests extends TestCase { + + /** + * Verifies that the enum values are not null upon valid assignment. + */ + public void testValidEnums() { + String example = "ENABLE_INPUT_KEY_MASK"; + KeyboardInputMask enumEnableInputKeyMask = KeyboardInputMask.valueForString(example); + example = "DISABLE_INPUT_KEY_MASK"; + KeyboardInputMask enumDisableInputKeyMask = KeyboardInputMask.valueForString(example); + example = "USER_CHOICE_INPUT_KEY_MASK"; + KeyboardInputMask enumUserChoiceInputKeyMask = KeyboardInputMask.valueForString(example); + + assertNotNull("ENABLE_INPUT_KEY_MASK returned null", enumEnableInputKeyMask); + assertNotNull("DISABLE_INPUT_KEY_MASK returned null", enumDisableInputKeyMask); + assertNotNull("USER_CHOICE_INPUT_KEY_MASK returned null", enumUserChoiceInputKeyMask); + } + + /** + * Verifies that an invalid assignment is null. + */ + public void testInvalidEnum() { + String example = "ENAablE_INPUT_KEY_MASK"; + try { + KeyboardInputMask temp = KeyboardInputMask.valueForString(example); + assertNull("Result of valueForString should be null.", temp); + } catch (IllegalArgumentException exception) { + fail("Invalid enum throws IllegalArgumentException."); + } + } + + /** + * Verifies that a null assignment is invalid. + */ + public void testNullEnum() { + String example = null; + try { + KeyboardInputMask temp = KeyboardInputMask.valueForString(example); + assertNull("Result of valueForString should be null.", temp); + } catch (NullPointerException exception) { + fail("Null string throws NullPointerException."); + } + } + + /** + * Verifies the possible enum values of MassageCushion. + */ + public void testListEnum() { + List enumValueList = Arrays.asList(KeyboardInputMask.values()); + + List enumTestList = new ArrayList(); + enumTestList.add(KeyboardInputMask.ENABLE_INPUT_KEY_MASK); + enumTestList.add(KeyboardInputMask.DISABLE_INPUT_KEY_MASK); + enumTestList.add(KeyboardInputMask.USER_CHOICE_INPUT_KEY_MASK); + + 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/KeyboardLayoutTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/KeyboardLayoutTests.java index c75b9d7e9d..52a7236e75 100644 --- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/KeyboardLayoutTests.java +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/KeyboardLayoutTests.java @@ -24,10 +24,13 @@ public void testValidEnums() { KeyboardLayout enumQwertz = KeyboardLayout.valueForString(example); example = "AZERTY"; KeyboardLayout enumAzerty = KeyboardLayout.valueForString(example); + example = "NUMERIC"; + KeyboardLayout enumNumeric = KeyboardLayout.valueForString(example); assertNotNull("QWERTY returned null", enumQwerty); assertNotNull("QWERTZ returned null", enumQwertz); assertNotNull("AZERTY returned null", enumAzerty); + assertNotNull("NUMERIC returned null", enumNumeric); } /** @@ -66,6 +69,7 @@ public void testListEnum() { enumTestList.add(KeyboardLayout.QWERTY); enumTestList.add(KeyboardLayout.QWERTZ); enumTestList.add(KeyboardLayout.AZERTY); + enumTestList.add(KeyboardLayout.NUMERIC); assertTrue("Enum value list does not match enum class list", enumValueList.containsAll(enumTestList) && enumTestList.containsAll(enumValueList)); 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 70c9f2546d..06b08c09c7 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 @@ -48,6 +48,8 @@ import com.smartdevicelink.protocol.enums.FunctionID; import com.smartdevicelink.proxy.RPCNotification; import com.smartdevicelink.proxy.rpc.DisplayCapability; +import com.smartdevicelink.proxy.rpc.KeyboardCapabilities; +import com.smartdevicelink.proxy.rpc.KeyboardLayoutCapability; import com.smartdevicelink.proxy.rpc.KeyboardProperties; import com.smartdevicelink.proxy.rpc.OnHMIStatus; import com.smartdevicelink.proxy.rpc.WindowCapability; @@ -66,6 +68,7 @@ import java.lang.ref.WeakReference; import java.util.HashSet; import java.util.List; +import java.util.Locale; /** * ChoiceSetManager
@@ -110,6 +113,7 @@ abstract class BaseChoiceSetManager extends BaseSubManager { // capabilities currentSystemContext = SystemContext.SYSCTXT_MAIN; currentHMILevel = HMILevel.HMI_NONE; + keyboardConfiguration = defaultKeyboardConfiguration(); addListeners(); // setting/instantiating class vars @@ -119,7 +123,6 @@ abstract class BaseChoiceSetManager extends BaseSubManager { nextChoiceId = choiceCellIdMin; nextCancelId = choiceCellCancelIdMin; isVROptional = false; - keyboardConfiguration = defaultKeyboardConfiguration(); currentlyPresentedKeyboardOperation = null; } @@ -393,6 +396,7 @@ public Integer presentKeyboard(@NonNull String initialText, @Nullable KeyboardPr DebugTool.logWarning(TAG, "There is a current or pending choice set, cancelling and continuing."); } + customKeyboardConfig = createValidKeyboardConfigurationBasedOnKeyboardCapabilitiesFromConfiguration(customKeyboardConfig); if (customKeyboardConfig == null) { if (this.keyboardConfiguration != null) { customKeyboardConfig = this.keyboardConfiguration; @@ -452,19 +456,56 @@ public void dismissKeyboard(@NonNull Integer cancelID) { * @param keyboardConfiguration - the custom keyboard configuration to be used when the keyboard is displayed */ public void setKeyboardConfiguration(@Nullable KeyboardProperties keyboardConfiguration) { - if (keyboardConfiguration == null) { + KeyboardProperties properties = createValidKeyboardConfigurationBasedOnKeyboardCapabilitiesFromConfiguration(keyboardConfiguration); + if (properties == null) { this.keyboardConfiguration = defaultKeyboardConfiguration(); } else { - KeyboardProperties properties = new KeyboardProperties(); - properties.setLanguage((keyboardConfiguration.getLanguage() == null ? Language.EN_US : keyboardConfiguration.getLanguage())); - properties.setKeyboardLayout((keyboardConfiguration.getKeyboardLayout() == null ? KeyboardLayout.QWERTZ : keyboardConfiguration.getKeyboardLayout())); - properties.setKeypressMode((keyboardConfiguration.getKeypressMode() == null ? KeypressMode.RESEND_CURRENT_ENTRY : keyboardConfiguration.getKeypressMode())); - properties.setLimitedCharacterList(keyboardConfiguration.getLimitedCharacterList()); - properties.setAutoCompleteText(keyboardConfiguration.getAutoCompleteText()); this.keyboardConfiguration = properties; } } + // Takes a keyboard configuration (SDLKeyboardProperties) and creates a valid version of it, if possible, based on this object's internal keyboardCapabilities + private KeyboardProperties createValidKeyboardConfigurationBasedOnKeyboardCapabilitiesFromConfiguration(@Nullable KeyboardProperties keyboardConfiguration) { + KeyboardCapabilities keyboardCapabilities = defaultMainWindowCapability != null ? defaultMainWindowCapability.getKeyboardCapabilities() : null; + + // If there are no keyboard capabilities, if there is no passed keyboard configuration, or if there is no layout to the passed keyboard configuration, just pass back the passed in configuration + if (keyboardCapabilities == null || keyboardConfiguration == null || keyboardConfiguration.getKeyboardLayout() == null) { + return keyboardConfiguration; + } + + KeyboardLayoutCapability selectedLayoutCapability = null; + for (KeyboardLayoutCapability layoutCapability : keyboardCapabilities.getSupportedKeyboards()) { + if (layoutCapability.getKeyboardLayout().equals(keyboardConfiguration.getKeyboardLayout())) { + selectedLayoutCapability = layoutCapability; + break; + } + } + + if (selectedLayoutCapability == null) { + DebugTool.logError(TAG, String.format("Configured keyboard layout is not supported: %s", keyboardConfiguration.getKeyboardLayout())); + return null; + } + + KeyboardProperties modifiedKeyboardConfiguration = (KeyboardProperties) keyboardConfiguration.clone(); + + if (keyboardConfiguration.getCustomKeys() == null || keyboardConfiguration.getCustomKeys().isEmpty()) { + modifiedKeyboardConfiguration.setCustomKeys(null); + } else { + // If there are more custom keys than are allowed for the selected keyboard layout, we need to trim the number of keys to only use the first n number of custom keys, where n is the number of allowed custom keys for that layout. + int numConfigurableKeys = selectedLayoutCapability.getNumConfigurableKeys(); + if (keyboardConfiguration.getCustomKeys().size() > numConfigurableKeys) { + modifiedKeyboardConfiguration.setCustomKeys(keyboardConfiguration.getCustomKeys().subList(0, numConfigurableKeys)); + DebugTool.logWarning(TAG, String.format(Locale.US, "%d custom keys set, but the selected layout: %s only supports %d. Dropping the rest.", keyboardConfiguration.getCustomKeys().size(), keyboardConfiguration.getKeyboardLayout(), numConfigurableKeys)); + } + } + + // If the keyboard does not support masking input characters, we will remove it from the keyboard configuration + if (!keyboardCapabilities.getMaskInputCharactersSupported()) { + modifiedKeyboardConfiguration.setMaskInputCharacters(null); + } + + return modifiedKeyboardConfiguration; + } // GETTERS /** diff --git a/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/KeyboardListener.java b/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/KeyboardListener.java index 175f39324b..619f2c2f2b 100644 --- a/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/KeyboardListener.java +++ b/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/KeyboardListener.java @@ -84,4 +84,6 @@ public interface KeyboardListener { * @param currentInputText - The user's full current input text */ void onKeyboardDidSendEvent(KeyboardEvent event, String currentInputText); + + void onKeyboardDidUpdateInputMask(KeyboardEvent event); } \ No newline at end of file diff --git a/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/PresentChoiceSetOperation.java b/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/PresentChoiceSetOperation.java index d0fb36bd1f..b5d3945d1c 100644 --- a/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/PresentChoiceSetOperation.java +++ b/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/PresentChoiceSetOperation.java @@ -359,6 +359,8 @@ public void onUpdatedCharacterSet(List updatedCharacterSet) { } else if (onKeyboard.getEvent().equals(KeyboardEvent.ENTRY_ABORTED) || onKeyboard.getEvent().equals(KeyboardEvent.ENTRY_CANCELLED)) { // Notify of abort / Cancellation keyboardListener.onKeyboardDidAbortWithReason(onKeyboard.getEvent()); + } else if (onKeyboard.getEvent().equals(KeyboardEvent.INPUT_KEY_MASK_ENABLED) || onKeyboard.getEvent().equals(KeyboardEvent.INPUT_KEY_MASK_DISABLED)) { + keyboardListener.onKeyboardDidUpdateInputMask(onKeyboard.getEvent()); } } }; diff --git a/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/PresentKeyboardOperation.java b/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/PresentKeyboardOperation.java index 54c26aaa66..2b13cf8ac2 100644 --- a/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/PresentKeyboardOperation.java +++ b/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/PresentKeyboardOperation.java @@ -305,6 +305,8 @@ public void onUpdatedCharacterSet(List updatedCharacterSet) { } else if (onKeyboard.getEvent().equals(KeyboardEvent.ENTRY_ABORTED) || onKeyboard.getEvent().equals(KeyboardEvent.ENTRY_CANCELLED)) { // Notify of abort / Cancellation keyboardListener.onKeyboardDidAbortWithReason(onKeyboard.getEvent()); + } else if (onKeyboard.getEvent().equals(KeyboardEvent.INPUT_KEY_MASK_ENABLED) || onKeyboard.getEvent().equals(KeyboardEvent.INPUT_KEY_MASK_DISABLED)) { + keyboardListener.onKeyboardDidUpdateInputMask(onKeyboard.getEvent()); } } diff --git a/base/src/main/java/com/smartdevicelink/proxy/rpc/KeyboardCapabilities.java b/base/src/main/java/com/smartdevicelink/proxy/rpc/KeyboardCapabilities.java new file mode 100644 index 0000000000..bc2fb43017 --- /dev/null +++ b/base/src/main/java/com/smartdevicelink/proxy/rpc/KeyboardCapabilities.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2017 - 2021, 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 com.smartdevicelink.proxy.RPCStruct; + +import java.util.Hashtable; +import java.util.List; + +/** + * + *

Parameter List

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Param NameTypeDescriptionRequiredNotesVersion Available
maskInputCharactersSupportedBooleanAvailability of capability to mask input characters using keyboard. True: Available,False: Not AvailableN
supportedKeyboardsListCapabilities of supported keyboard layouts by HMI.N{"array_max_size": 1000, "array_min_size": 1}
+ * @since SmartDeviceLink 7.1.0 + */ +public class KeyboardCapabilities extends RPCStruct { + + public static final String KEY_MASK_INPUT_CHARACTERS_SUPPORTED = "maskInputCharactersSupported"; + public static final String KEY_SUPPORTED_KEYBOARDS = "supportedKeyboards"; + + /** + * Constructs a new KeyboardCapabilities object + */ + public KeyboardCapabilities() { } + + /** + * Constructs a new KeyboardCapabilities object indicated by the Hashtable parameter + * + * @param hash The Hashtable to use + */ + public KeyboardCapabilities(Hashtable hash) { + super(hash); + } + + /** + * Sets the maskInputCharactersSupported. + * + * @param maskInputCharactersSupported Availability of capability to mask input characters using keyboard. True: Available, + * False: Not Available + */ + public KeyboardCapabilities setMaskInputCharactersSupported(Boolean maskInputCharactersSupported) { + setValue(KEY_MASK_INPUT_CHARACTERS_SUPPORTED, maskInputCharactersSupported); + return this; + } + + /** + * Gets the maskInputCharactersSupported. + * + * @return Boolean Availability of capability to mask input characters using keyboard. True: Available, + * False: Not Available + */ + public Boolean getMaskInputCharactersSupported() { + return getBoolean(KEY_MASK_INPUT_CHARACTERS_SUPPORTED); + } + + /** + * Sets the supportedKeyboards. + * + * @param supportedKeyboards Capabilities of supported keyboard layouts by HMI. + * {"array_max_size": 1000, "array_min_size": 1} + */ + public KeyboardCapabilities setSupportedKeyboards(List supportedKeyboards) { + setValue(KEY_SUPPORTED_KEYBOARDS, supportedKeyboards); + return this; + } + + /** + * Gets the supportedKeyboards. + * + * @return List Capabilities of supported keyboard layouts by HMI. + * {"array_max_size": 1000, "array_min_size": 1} + */ + @SuppressWarnings("unchecked") + public List getSupportedKeyboards() { + return (List) getObject(KeyboardLayoutCapability.class, KEY_SUPPORTED_KEYBOARDS); + } +} diff --git a/base/src/main/java/com/smartdevicelink/proxy/rpc/KeyboardLayoutCapability.java b/base/src/main/java/com/smartdevicelink/proxy/rpc/KeyboardLayoutCapability.java new file mode 100644 index 0000000000..cf3f13b9c9 --- /dev/null +++ b/base/src/main/java/com/smartdevicelink/proxy/rpc/KeyboardLayoutCapability.java @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2017 - 2021, 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 androidx.annotation.NonNull; + +import com.smartdevicelink.proxy.RPCStruct; +import com.smartdevicelink.proxy.rpc.enums.KeyboardLayout; + +import java.util.Hashtable; + +/** + * Describes the capabilities of a single keyboard layout. + * + *

Parameter List

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Param NameTypeDescriptionRequiredNotesVersion Available
keyboardLayoutKeyboardLayoutY
numConfigurableKeysIntegerNumber of keys available for special characters, App can customize as per their needs.Y{"num_max_value": 10, "num_min_value": 0}
+ * + * @since SmartDeviceLink 7.1.0 + */ +public class KeyboardLayoutCapability extends RPCStruct { + public static final String KEY_KEYBOARD_LAYOUT = "keyboardLayout"; + public static final String KEY_NUM_CONFIGURABLE_KEYS = "numConfigurableKeys"; + + /** + * Constructs a new KeyboardLayoutCapability object + */ + public KeyboardLayoutCapability() { } + + /** + * Constructs a new KeyboardLayoutCapability object indicated by the Hashtable parameter + * + * @param hash The Hashtable to use + */ + public KeyboardLayoutCapability(Hashtable hash) { + super(hash); + } + + /** + * Constructs a new KeyboardLayoutCapability object + * + * @param keyboardLayout + * @param numConfigurableKeys Number of keys available for special characters, App can customize as per their needs. + * {"num_max_value": 10, "num_min_value": 0} + */ + public KeyboardLayoutCapability(@NonNull KeyboardLayout keyboardLayout, @NonNull Integer numConfigurableKeys) { + this(); + setKeyboardLayout(keyboardLayout); + setNumConfigurableKeys(numConfigurableKeys); + } + + /** + * Sets the keyboardLayout. + * + * @param keyboardLayout + */ + public KeyboardLayoutCapability setKeyboardLayout(@NonNull KeyboardLayout keyboardLayout) { + setValue(KEY_KEYBOARD_LAYOUT, keyboardLayout); + return this; + } + + /** + * Gets the keyboardLayout. + * + * @return KeyboardLayout + */ + public KeyboardLayout getKeyboardLayout() { + return (KeyboardLayout) getObject(KeyboardLayout.class, KEY_KEYBOARD_LAYOUT); + } + + /** + * Sets the numConfigurableKeys. + * + * @param numConfigurableKeys Number of keys available for special characters, App can customize as per their needs. + * {"num_max_value": 10, "num_min_value": 0} + */ + public KeyboardLayoutCapability setNumConfigurableKeys(@NonNull Integer numConfigurableKeys) { + setValue(KEY_NUM_CONFIGURABLE_KEYS, numConfigurableKeys); + return this; + } + + /** + * Gets the numConfigurableKeys. + * + * @return Integer Number of keys available for special characters, App can customize as per their needs. + * {"num_max_value": 10, "num_min_value": 0} + */ + public Integer getNumConfigurableKeys() { + return getInteger(KEY_NUM_CONFIGURABLE_KEYS); + } +} diff --git a/base/src/main/java/com/smartdevicelink/proxy/rpc/KeyboardProperties.java b/base/src/main/java/com/smartdevicelink/proxy/rpc/KeyboardProperties.java index cfd9b0dae2..a596237209 100644 --- a/base/src/main/java/com/smartdevicelink/proxy/rpc/KeyboardProperties.java +++ b/base/src/main/java/com/smartdevicelink/proxy/rpc/KeyboardProperties.java @@ -32,6 +32,7 @@ package com.smartdevicelink.proxy.rpc; import com.smartdevicelink.proxy.RPCStruct; +import com.smartdevicelink.proxy.rpc.enums.KeyboardInputMask; import com.smartdevicelink.proxy.rpc.enums.KeyboardLayout; import com.smartdevicelink.proxy.rpc.enums.KeypressMode; import com.smartdevicelink.proxy.rpc.enums.Language; @@ -101,6 +102,27 @@ * Array = true maxlength = 1000 minsize = 0 maxsize = 100 * Allows an app to prepopulate the text field with a list of suggested or completed entry as the user types. Set to an empty array to remove the auto-complete list from the screen * + * + * maskInputCharacters + * KeyboardInputMask + * false + * + * @since SmartDeviceLink 7.1.0 + * + * Allows an app to mask entered characters on HMI + * + * + * customKeys + * List + * false + * + * @since SmartDeviceLink 7.1.0 + * + * + * Array of special characters to show in customizable keys. If omitted, keyboard will show default special characters + * {"string_max_length": 1, "string_min_length": 1, "array_max_size": 10, "array_min_size": 1} + * + * * * * @since SmartDeviceLink 3.0 @@ -113,6 +135,8 @@ public class KeyboardProperties extends RPCStruct { @Deprecated public static final String KEY_AUTO_COMPLETE_TEXT = "autoCompleteText"; public static final String KEY_AUTO_COMPLETE_LIST = "autoCompleteList"; + public static final String KEY_MASK_INPUT_CHARACTERS = "maskInputCharacters"; + public static final String KEY_CUSTOM_KEYS = "customKeys"; public static final String KEY_LANGUAGE = "language"; private static final KeypressMode KEYPRESS_MODE_DEFAULT = KeypressMode.RESEND_CURRENT_ENTRY; @@ -201,6 +225,7 @@ public KeyboardProperties setAutoCompleteText(String autoCompleteText) { * * @return List representing the suggestions list */ + @SuppressWarnings("unchecked") public List getAutoCompleteList() { return (List) getObject(String.class, KEY_AUTO_COMPLETE_LIST); } @@ -215,4 +240,51 @@ public KeyboardProperties setAutoCompleteList(List autoCompleteList) { setValue(KEY_AUTO_COMPLETE_LIST, autoCompleteList); return this; } + + /** + * Sets the maskInputCharacters. + * + * @param maskInputCharacters Allows an app to mask entered characters on HMI + * @since SmartDeviceLink 7.1.0 + */ + public KeyboardProperties setMaskInputCharacters(KeyboardInputMask maskInputCharacters) { + setValue(KEY_MASK_INPUT_CHARACTERS, maskInputCharacters); + return this; + } + + /** + * Gets the maskInputCharacters. + * + * @return KeyboardInputMask Allows an app to mask entered characters on HMI + * @since SmartDeviceLink 7.1.0 + */ + public KeyboardInputMask getMaskInputCharacters() { + return (KeyboardInputMask) getObject(KeyboardInputMask.class, KEY_MASK_INPUT_CHARACTERS); + } + + /** + * Sets the customKeys. + * + * @param customKeys Array of special characters to show in customizable keys. If omitted, keyboard will show + * default special characters + * {"string_max_length": 1, "string_min_length": 1, "array_max_size": 10, "array_min_size": 1} + * @since SmartDeviceLink 7.1.0 + */ + public KeyboardProperties setCustomKeys(List customKeys) { + setValue(KEY_CUSTOM_KEYS, customKeys); + return this; + } + + /** + * Gets the customKeys. + * + * @return List Array of special characters to show in customizable keys. If omitted, keyboard will show + * default special characters + * {"string_max_length": 1, "string_min_length": 1, "array_max_size": 10, "array_min_size": 1} + * @since SmartDeviceLink 7.1.0 + */ + @SuppressWarnings("unchecked") + public List getCustomKeys() { + return (List) getObject(String.class, KEY_CUSTOM_KEYS); + } } diff --git a/base/src/main/java/com/smartdevicelink/proxy/rpc/WindowCapability.java b/base/src/main/java/com/smartdevicelink/proxy/rpc/WindowCapability.java index 28a5b0ccb3..4de9d153cb 100644 --- a/base/src/main/java/com/smartdevicelink/proxy/rpc/WindowCapability.java +++ b/base/src/main/java/com/smartdevicelink/proxy/rpc/WindowCapability.java @@ -21,6 +21,10 @@ public class WindowCapability extends RPCStruct { public static final String KEY_SOFT_BUTTON_CAPABILITIES = "softButtonCapabilities"; public static final String KEY_MENU_LAYOUTS_AVAILABLE = "menuLayoutsAvailable"; public static final String KEY_DYNAMIC_UPDATE_CAPABILITIES = "dynamicUpdateCapabilities"; + /** + * @since SmartDeviceLink 7.1.0 + */ + public static final String KEY_KEYBOARD_CAPABILITIES = "keyboardCapabilities"; public WindowCapability() { } @@ -240,4 +244,25 @@ public WindowCapability setDynamicUpdateCapabilities(DynamicUpdateCapabilities d public DynamicUpdateCapabilities getDynamicUpdateCapabilities() { return (DynamicUpdateCapabilities) getObject(DynamicUpdateCapabilities.class, KEY_DYNAMIC_UPDATE_CAPABILITIES); } + + /** + * Sets the keyboardCapabilities. + * + * @param keyboardCapabilities See KeyboardCapabilities + * @since SmartDeviceLink 7.1.0 + */ + public WindowCapability setKeyboardCapabilities(KeyboardCapabilities keyboardCapabilities) { + setValue(KEY_KEYBOARD_CAPABILITIES, keyboardCapabilities); + return this; + } + + /** + * Gets the keyboardCapabilities. + * + * @return KeyboardCapabilities See KeyboardCapabilities + * @since SmartDeviceLink 7.1.0 + */ + public KeyboardCapabilities getKeyboardCapabilities() { + return (KeyboardCapabilities) getObject(KeyboardCapabilities.class, KEY_KEYBOARD_CAPABILITIES); + } } diff --git a/base/src/main/java/com/smartdevicelink/proxy/rpc/enums/KeyboardEvent.java b/base/src/main/java/com/smartdevicelink/proxy/rpc/enums/KeyboardEvent.java index 2e3b45c1b2..a54d247a6b 100644 --- a/base/src/main/java/com/smartdevicelink/proxy/rpc/enums/KeyboardEvent.java +++ b/base/src/main/java/com/smartdevicelink/proxy/rpc/enums/KeyboardEvent.java @@ -58,7 +58,14 @@ public enum KeyboardEvent { * @since SmartDeviceLink 4.0 */ ENTRY_VOICE, - ; + /** + * @since SmartDeviceLink 7.1.0 + */ + INPUT_KEY_MASK_ENABLED, + /** + * @since SmartDeviceLink 7.1.0 + */ + INPUT_KEY_MASK_DISABLED; /** * Convert String to KeyboardEvent diff --git a/base/src/main/java/com/smartdevicelink/proxy/rpc/enums/KeyboardInputMask.java b/base/src/main/java/com/smartdevicelink/proxy/rpc/enums/KeyboardInputMask.java new file mode 100644 index 0000000000..391947a879 --- /dev/null +++ b/base/src/main/java/com/smartdevicelink/proxy/rpc/enums/KeyboardInputMask.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2017 - 2020, 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; + +/** + * Enumeration listing possible input character masking. + * + * @since SmartDeviceLink 7.1.0 + */ +public enum KeyboardInputMask { + ENABLE_INPUT_KEY_MASK, + DISABLE_INPUT_KEY_MASK, + USER_CHOICE_INPUT_KEY_MASK; + + /** + * Convert String to KeyboardInputMask + * + * @param value String + * @return KeyboardInputMask + */ + public static KeyboardInputMask valueForString(String value) { + try { + return valueOf(value); + } catch (Exception e) { + return null; + } + } +} diff --git a/base/src/main/java/com/smartdevicelink/proxy/rpc/enums/KeyboardLayout.java b/base/src/main/java/com/smartdevicelink/proxy/rpc/enums/KeyboardLayout.java index fac69ac4d0..0e263c4138 100644 --- a/base/src/main/java/com/smartdevicelink/proxy/rpc/enums/KeyboardLayout.java +++ b/base/src/main/java/com/smartdevicelink/proxy/rpc/enums/KeyboardLayout.java @@ -39,7 +39,11 @@ public enum KeyboardLayout { QWERTY, QWERTZ, - AZERTY; + AZERTY, + /** + * @since SmartDeviceLink 7.1.0 + */ + NUMERIC; public static KeyboardLayout valueForString(String value) { try {