summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/ChoiceCellTests.java123
-rw-r--r--android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/ChoiceSetLayoutTests.java92
-rw-r--r--android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/ChoiceSetTests.java101
-rw-r--r--android/sdl_android/src/main/java/com/smartdevicelink/managers/screen/choiceset/ChoiceSetManager.java55
-rw-r--r--base/src/main/java/com/smartdevicelink/managers/screen/choiceset/BaseChoiceSetManager.java387
-rw-r--r--base/src/main/java/com/smartdevicelink/managers/screen/choiceset/ChoiceCell.java261
-rw-r--r--base/src/main/java/com/smartdevicelink/managers/screen/choiceset/ChoiceSet.java360
-rw-r--r--base/src/main/java/com/smartdevicelink/managers/screen/choiceset/ChoiceSetLayout.java46
-rw-r--r--base/src/main/java/com/smartdevicelink/managers/screen/choiceset/ChoiceSetSelectionListener.java40
-rw-r--r--base/src/main/java/com/smartdevicelink/managers/screen/choiceset/KeyboardAutocompleteCompletionListener.java42
-rw-r--r--base/src/main/java/com/smartdevicelink/managers/screen/choiceset/KeyboardCharacterSetCompletionListener.java12
-rw-r--r--base/src/main/java/com/smartdevicelink/managers/screen/choiceset/KeyboardListener.java87
-rw-r--r--javaSE/src/main/java/com/smartdevicelink/managers/screen/choiceset/ChoiceSetManager.java55
13 files changed, 1661 insertions, 0 deletions
diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/ChoiceCellTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/ChoiceCellTests.java
new file mode 100644
index 000000000..7d1108aff
--- /dev/null
+++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/ChoiceCellTests.java
@@ -0,0 +1,123 @@
+/*
+ * 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.screen.choiceset;
+
+import com.smartdevicelink.AndroidTestCase2;
+import com.smartdevicelink.managers.file.filetypes.SdlArtwork;
+import com.smartdevicelink.proxy.rpc.enums.FileType;
+import com.smartdevicelink.test.Test;
+
+public class ChoiceCellTests extends AndroidTestCase2 {
+
+ private static final int MAX_ID = 2000000000;
+ private SdlArtwork artwork = new SdlArtwork("image", FileType.GRAPHIC_PNG, 1, true);
+
+ @Override
+ public void setUp() throws Exception{
+ super.setUp();
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testSettersAndGetters(){
+
+ // set everything
+ ChoiceCell choiceCell = new ChoiceCell(Test.GENERAL_STRING);
+ choiceCell.setSecondaryText(Test.GENERAL_STRING);
+ choiceCell.setTertiaryText(Test.GENERAL_STRING);
+ choiceCell.setVoiceCommands(Test.GENERAL_STRING_LIST);
+ choiceCell.setArtwork(artwork);
+ choiceCell.setSecondaryArtwork(artwork);
+
+
+ // use getters and assert equality
+ assertEquals(choiceCell.getText(), Test.GENERAL_STRING);
+ assertEquals(choiceCell.getSecondaryText(), Test.GENERAL_STRING);
+ assertEquals(choiceCell.getTertiaryText(), Test.GENERAL_STRING);
+ assertEquals(choiceCell.getVoiceCommands(), Test.GENERAL_STRING_LIST);
+ assertEquals(choiceCell.getArtwork(), artwork);
+ assertEquals(choiceCell.getSecondaryArtwork(), artwork);
+ assertEquals(choiceCell.getChoiceId(), MAX_ID);
+ }
+
+ public void testConstructors() {
+ // first constructor was tested in previous method, use the rest here
+
+ ChoiceCell choiceCell = new ChoiceCell(Test.GENERAL_STRING, Test.GENERAL_STRING_LIST, artwork);
+ choiceCell.setSecondaryText(Test.GENERAL_STRING);
+ choiceCell.setTertiaryText(Test.GENERAL_STRING);
+ choiceCell.setSecondaryArtwork(artwork);
+ assertEquals(choiceCell.getText(), Test.GENERAL_STRING);
+ assertEquals(choiceCell.getSecondaryText(), Test.GENERAL_STRING);
+ assertEquals(choiceCell.getTertiaryText(), Test.GENERAL_STRING);
+ assertEquals(choiceCell.getVoiceCommands(), Test.GENERAL_STRING_LIST);
+ assertEquals(choiceCell.getArtwork(), artwork);
+ assertEquals(choiceCell.getSecondaryArtwork(), artwork);
+ assertEquals(choiceCell.getChoiceId(), MAX_ID);
+
+
+ choiceCell = new ChoiceCell(Test.GENERAL_STRING, Test.GENERAL_STRING, Test.GENERAL_STRING, Test.GENERAL_STRING_LIST, artwork, artwork);
+ assertEquals(choiceCell.getText(), Test.GENERAL_STRING);
+ assertEquals(choiceCell.getSecondaryText(), Test.GENERAL_STRING);
+ assertEquals(choiceCell.getTertiaryText(), Test.GENERAL_STRING);
+ assertEquals(choiceCell.getVoiceCommands(), Test.GENERAL_STRING_LIST);
+ assertEquals(choiceCell.getArtwork(), artwork);
+ assertEquals(choiceCell.getSecondaryArtwork(), artwork);
+ assertEquals(choiceCell.getChoiceId(), MAX_ID);
+ }
+
+ public void testCellEquality(){
+
+ ChoiceCell choiceCell = new ChoiceCell(Test.GENERAL_STRING, Test.GENERAL_STRING_LIST, artwork);
+ choiceCell.setSecondaryText(Test.GENERAL_STRING);
+ choiceCell.setTertiaryText(Test.GENERAL_STRING);
+ choiceCell.setSecondaryArtwork(artwork);
+
+ ChoiceCell choiceCell2 = new ChoiceCell(Test.GENERAL_STRING, Test.GENERAL_STRING_LIST, artwork);
+ choiceCell2.setSecondaryText(Test.GENERAL_STRING);
+ choiceCell2.setTertiaryText(Test.GENERAL_STRING);
+ choiceCell2.setSecondaryArtwork(artwork);
+
+ ChoiceCell choiceCell3 = new ChoiceCell(Test.GENERAL_STRING, Test.GENERAL_STRING_LIST, artwork);
+ choiceCell3.setSecondaryText(Test.GENERAL_STRING);
+ choiceCell3.setTertiaryText(Test.GENERAL_STRING);
+
+ // Make sure our overridden method works, even though these are different objects in memory
+ assertTrue(choiceCell.equals(choiceCell2));
+ assertFalse(choiceCell.equals(choiceCell3));
+
+ }
+}
diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/ChoiceSetLayoutTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/ChoiceSetLayoutTests.java
new file mode 100644
index 000000000..3f147f128
--- /dev/null
+++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/ChoiceSetLayoutTests.java
@@ -0,0 +1,92 @@
+/*
+ * 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.screen.choiceset;
+
+import com.smartdevicelink.AndroidTestCase2;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class ChoiceSetLayoutTests extends AndroidTestCase2 {
+ /**
+ * Verifies that the enum values are not null upon valid assignment.
+ */
+ public void testValidEnums() {
+ ChoiceSetLayout choiceSetLayoutList = ChoiceSetLayout.valueForString("CHOICE_SET_LAYOUT_LIST");
+ ChoiceSetLayout choiceSetLayoutTiles = ChoiceSetLayout.valueForString("CHOICE_SET_LAYOUT_TILES");
+ assertNotNull("CHOICE_SET_LAYOUT_LIST returned null", choiceSetLayoutList);
+ assertNotNull("choiceSetLayoutTiles returned null", choiceSetLayoutTiles);
+ }
+
+ /**
+ * Verifies that an invalid assignment is null.
+ */
+ public void testInvalidEnum() {
+ String example = "deFaUlt";
+ try {
+ ChoiceSetLayout temp = ChoiceSetLayout.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 {
+ ChoiceSetLayout temp = ChoiceSetLayout.valueForString(example);
+ assertNull("Result of valueForString should be null.", temp);
+ } catch (NullPointerException exception) {
+ fail("Null string throws NullPointerException.");
+ }
+ }
+
+ /**
+ * Verifies the possible enum values of DynamicMenuUpdatesMode.
+ */
+ public void testListEnum() {
+ List<ChoiceSetLayout> enumValueList = Arrays.asList(ChoiceSetLayout.values());
+
+ List<ChoiceSetLayout> enumTestList = new ArrayList<>();
+ enumTestList.add(ChoiceSetLayout.CHOICE_SET_LAYOUT_LIST);
+ enumTestList.add(ChoiceSetLayout.CHOICE_SET_LAYOUT_TILES);
+
+
+ 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/managers/screen/choiceset/ChoiceSetTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/ChoiceSetTests.java
new file mode 100644
index 000000000..78b68f2a2
--- /dev/null
+++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/ChoiceSetTests.java
@@ -0,0 +1,101 @@
+/*
+ * 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.screen.choiceset;
+
+import com.smartdevicelink.AndroidTestCase2;
+import com.smartdevicelink.test.Test;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static org.mockito.Mockito.mock;
+
+public class ChoiceSetTests extends AndroidTestCase2 {
+
+ private ChoiceSetSelectionListener listener;
+ private ChoiceSetLayout layout;
+ private List<ChoiceCell> choices;
+ private Integer defaultTimeout;
+
+ @Override
+ public void setUp() throws Exception{
+ super.setUp();
+
+ listener = mock(ChoiceSetSelectionListener.class);
+ layout = ChoiceSetLayout.CHOICE_SET_LAYOUT_LIST;
+ defaultTimeout = 10;
+ choices = Arrays.asList(new ChoiceCell(Test.GENERAL_STRING), new ChoiceCell(Test.GENERAL_STRING));
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testSettersAndGetters(){
+
+ // test small constructor
+ ChoiceSet choiceSet = new ChoiceSet(Test.GENERAL_STRING, listener, choices);
+
+ // use getters and assert equality
+ assertEquals(choiceSet.getTitle(), Test.GENERAL_STRING);
+ assertEquals(choiceSet.getLayout(), layout);
+ assertEquals(choiceSet.getTimeout(), defaultTimeout);
+ assertEquals(choiceSet.getChoices(), choices);
+ assertEquals(choiceSet.getChoiceSetSelectionListener(), listener);
+ }
+
+ public void testConstructors() {
+
+ // first constructor was tested in previous method, use the rest here
+ ChoiceSet choiceSet = new ChoiceSet(Test.GENERAL_STRING, listener, layout, Test.GENERAL_INTEGER, Test.GENERAL_STRING, Test.GENERAL_STRING, Test.GENERAL_STRING, Test.GENERAL_VRHELPITEM_LIST, choices);
+ assertEquals(choiceSet.getTitle(), Test.GENERAL_STRING);
+ assertEquals(choiceSet.getInitialPrompt().get(0).getText(),Test.GENERAL_STRING);
+ assertEquals(choiceSet.getHelpPrompt().get(0).getText(), Test.GENERAL_STRING);
+ assertEquals(choiceSet.getTimeoutPrompt().get(0).getText(), Test.GENERAL_STRING);
+ assertEquals(choiceSet.getLayout(), layout);
+ assertEquals(choiceSet.getTimeout(), Test.GENERAL_INTEGER);
+ assertEquals(choiceSet.getChoices(), choices);
+ assertEquals(choiceSet.getChoiceSetSelectionListener(), listener);
+
+ ChoiceSet choiceSet2 = new ChoiceSet(Test.GENERAL_STRING, listener, layout, Test.GENERAL_INTEGER, Test.GENERAL_TTSCHUNK_LIST, Test.GENERAL_TTSCHUNK_LIST, Test.GENERAL_TTSCHUNK_LIST, Test.GENERAL_VRHELPITEM_LIST, choices);
+ assertEquals(choiceSet2.getTitle(), Test.GENERAL_STRING);
+ assertEquals(choiceSet2.getInitialPrompt(),Test.GENERAL_TTSCHUNK_LIST);
+ assertEquals(choiceSet2.getHelpPrompt(), Test.GENERAL_TTSCHUNK_LIST);
+ assertEquals(choiceSet2.getTimeoutPrompt(), Test.GENERAL_TTSCHUNK_LIST);
+ assertEquals(choiceSet2.getLayout(), layout);
+ assertEquals(choiceSet2.getTimeout(), Test.GENERAL_INTEGER);
+ assertEquals(choiceSet2.getChoices(), choices);
+ assertEquals(choiceSet2.getChoiceSetSelectionListener(), listener);
+ }
+}
diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/managers/screen/choiceset/ChoiceSetManager.java b/android/sdl_android/src/main/java/com/smartdevicelink/managers/screen/choiceset/ChoiceSetManager.java
new file mode 100644
index 000000000..2cb3ad2f3
--- /dev/null
+++ b/android/sdl_android/src/main/java/com/smartdevicelink/managers/screen/choiceset/ChoiceSetManager.java
@@ -0,0 +1,55 @@
+/*
+ * 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.screen.choiceset;
+
+import android.support.annotation.NonNull;
+
+import com.smartdevicelink.managers.file.FileManager;
+import com.smartdevicelink.proxy.interfaces.ISdl;
+
+/**
+ * <strong>ChoiceSetManager</strong> <br>
+ * ChoiceSetManager gives the developer the ability to control how soft choice sets are displayed on the head unit.<br>
+ * Note: This class must be accessed through the SdlManager->ScreenManager. Do not instantiate it by itself.<br>
+ */
+class ChoiceSetManager extends BaseChoiceSetManager {
+
+ /**
+ * Creates a new instance of the ChoiceSetManager
+ *
+ * @param internalInterface
+ */
+ ChoiceSetManager(@NonNull ISdl internalInterface, @NonNull FileManager fileManager) {
+ super(internalInterface, fileManager);
+ }
+}
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
new file mode 100644
index 000000000..1010eefc4
--- /dev/null
+++ b/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/BaseChoiceSetManager.java
@@ -0,0 +1,387 @@
+/*
+ * 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.screen.choiceset;
+
+import android.support.annotation.NonNull;
+
+import com.smartdevicelink.managers.BaseSubManager;
+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.interfaces.ISdl;
+import com.smartdevicelink.proxy.interfaces.OnSystemCapabilityListener;
+import com.smartdevicelink.proxy.rpc.DisplayCapabilities;
+import com.smartdevicelink.proxy.rpc.KeyboardProperties;
+import com.smartdevicelink.proxy.rpc.OnHMIStatus;
+import com.smartdevicelink.proxy.rpc.enums.HMILevel;
+import com.smartdevicelink.proxy.rpc.enums.InteractionMode;
+import com.smartdevicelink.proxy.rpc.enums.KeyboardLayout;
+import com.smartdevicelink.proxy.rpc.enums.KeypressMode;
+import com.smartdevicelink.proxy.rpc.enums.Language;
+import com.smartdevicelink.proxy.rpc.enums.SystemCapabilityType;
+import com.smartdevicelink.proxy.rpc.enums.SystemContext;
+import com.smartdevicelink.proxy.rpc.listeners.OnRPCNotificationListener;
+import com.smartdevicelink.util.DebugTool;
+
+import java.lang.ref.WeakReference;
+import java.util.HashSet;
+import java.util.List;
+
+/**
+ * <strong>ChoiceSetManager</strong> <br>
+ * <p>
+ * Note: This class must be accessed through the SdlManager. Do not instantiate it by itself. <br>
+ */
+public abstract class BaseChoiceSetManager extends BaseSubManager {
+
+ // additional state
+ private static final int CHECKING_VOICE = 0xA0;
+
+ OnRPCNotificationListener hmiListener;
+ OnSystemCapabilityListener displayListener;
+
+ private final WeakReference<FileManager> fileManager;
+ private KeyboardProperties keyboardConfiguration;
+ private HMILevel currentHMILevel;
+ private SystemContext currentSystemContext;
+ private DisplayCapabilities displayCapabilities;
+
+ private HashSet<ChoiceCell> preloadedChoices;
+ private HashSet<ChoiceCell> pendingPreloadChoices;
+ private HashSet<ChoiceCell> preloadedMutableChoices;
+ private HashSet<ChoiceCell> pendingMutablePreloadChoices;
+ private ChoiceSet pendingPresentationSet;
+ private Boolean isVROptional;
+
+ private int nextChoiceId;
+ private int choiceCellIdMin = 1;
+
+ public BaseChoiceSetManager(@NonNull ISdl internalInterface, @NonNull FileManager fileManager) {
+ super(internalInterface);
+
+ transitionToState(SHUTDOWN); // We need to do some stuff first. keep in shutdown state
+ this.fileManager = new WeakReference<>(fileManager);
+ preloadedMutableChoices = new HashSet<>();
+ pendingMutablePreloadChoices = new HashSet<>();
+ nextChoiceId = choiceCellIdMin;
+ isVROptional = true;
+ keyboardConfiguration = defaultKeyboardConfiguration();
+ addListeners();
+ }
+
+ @Override
+ public void start(CompletionListener listener){
+ if (getState() == SHUTDOWN) {
+ transitionToState(SETTING_UP);
+ checkVoiceOptional();
+ super.start(listener);
+ } // Else we are already started
+ }
+
+ @Override
+ public void dispose(){
+
+ currentHMILevel = null;
+ currentSystemContext = null;
+ displayCapabilities = null;
+
+ // TODO: cancel all queued operations, if any exist
+
+ pendingPresentationSet = null;
+ isVROptional = true;
+ nextChoiceId = choiceCellIdMin;
+
+ super.dispose();
+ }
+
+ public void preloadChoices(List<ChoiceCell> choices, CompletionListener listener){
+ if (getState() != READY){ return; }
+
+ HashSet<ChoiceCell> choicesToUpload = choicesToBeUploadedWithArray(choices);
+ choicesToUpload.removeAll(preloadedMutableChoices);
+ choicesToUpload.removeAll(pendingMutablePreloadChoices);
+
+ if (choicesToUpload.size() == 0){
+ if (listener != null){
+ listener.onComplete(true);
+ }
+ return;
+ }
+
+ updateIdsOnChoices(choicesToUpload);
+
+ // Add the preload cells to the pending preload choices
+ pendingMutablePreloadChoices.addAll(choicesToUpload);
+
+ // Upload pending preloads
+
+ //TODO: PreloadChoicesOperation
+
+ }
+
+ public void deleteChoices(List<ChoiceCell> choices){
+ if (getState() != READY){ return; }
+
+ // Find cells to be deleted that are already uploaded or are pending upload
+ HashSet<ChoiceCell> cellsToDelete = choicesToBeDeletedWithArray(choices);
+ HashSet<ChoiceCell> cellsToBeRemovedFromPending = choicesToBeRemovedFromPendingWithArray(choices);
+
+ // If choices are deleted that are already uploaded or pending and are used by a pending presentation, cancel it and send an error
+ if (pendingPresentationSet != null && pendingPresentationSet.getChoices() != null) {
+ HashSet<ChoiceCell> pendingPresentationChoices = new HashSet<>(pendingPresentationSet.getChoices());
+
+ }
+
+ }
+
+ public void presentChoiceSet(final ChoiceSet choiceSet, InteractionMode mode, KeyboardListener listener){
+ if (getState() != READY){ return; }
+ if (choiceSet == null) {
+ DebugTool.logWarning("Attempted to present a null choice set. Ignoring request");
+ return;
+ }
+ // Perform additional checks against the ChoiceSet
+ if (!setUpChoiceSet(choiceSet)){ return; }
+
+ if (this.pendingPresentationSet != null){
+ // cancel pendingPresentationOperation
+ }
+
+ this.pendingPresentationSet = choiceSet;
+ preloadChoices(this.pendingPresentationSet.getChoices(), new CompletionListener() {
+ @Override
+ public void onComplete(boolean success) {
+ if (!success){
+ choiceSet.getChoiceSetSelectionListener().onError("There was an error pre-loading choice set choices");
+ return;
+ }
+ }
+ });
+
+ findIdsOnChoiceSet(this.pendingPresentationSet);
+
+ // create presentationChoiceSetOperation
+ // add the operation to the queue
+
+ }
+
+ public void presentKeyboardWithInitialText(String initialText, KeyboardListener listener){
+ if (getState() != READY){ return; }
+
+ if (pendingPresentationSet != null){
+ //[self.pendingPresentOperation cancel];
+ pendingPresentationSet = null;
+ }
+
+ // create PresentKeyboardOperation
+ // add operation to the transaction queue
+ }
+
+ // SETTERS
+
+ public void setKeyboardConfiguration(KeyboardProperties keyboardConfiguration){
+
+ if (keyboardConfiguration == 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(KeypressMode.RESEND_CURRENT_ENTRY);
+ properties.setLimitedCharacterList(keyboardConfiguration.getLimitedCharacterList());
+ properties.setAutoCompleteText(keyboardConfiguration.getAutoCompleteText());
+ this.keyboardConfiguration = properties;
+ }
+ }
+
+ // GETTERS
+
+ public HashSet<ChoiceCell> getPreloadedChoices(){
+ return this.preloadedChoices;
+ }
+
+ public HashSet<ChoiceCell> getPendingPreloadChoices(){
+ return this.pendingPreloadChoices;
+ }
+
+ // CHOICE SET MANAGEMENT HELPERS
+
+ private HashSet<ChoiceCell> choicesToBeUploadedWithArray(List<ChoiceCell> choices){
+ HashSet<ChoiceCell> choicesSet = new HashSet<>(choices);
+ choicesSet.removeAll(this.preloadedChoices);
+ return choicesSet;
+ }
+
+ private HashSet<ChoiceCell> choicesToBeDeletedWithArray(List<ChoiceCell> choices){
+ HashSet<ChoiceCell> choicesSet = new HashSet<>(choices);
+ choicesSet.retainAll(this.preloadedChoices);
+ return choicesSet;
+ }
+
+ private HashSet<ChoiceCell> choicesToBeRemovedFromPendingWithArray(List<ChoiceCell> choices){
+ HashSet<ChoiceCell> choicesSet = new HashSet<>(choices);
+ choicesSet.retainAll(this.pendingPreloadChoices);
+ return choicesSet;
+ }
+
+ private void updateIdsOnChoices(HashSet<ChoiceCell> choices){
+ for (ChoiceCell cell : choices){
+ cell.setChoiceId(this.nextChoiceId);
+ this.nextChoiceId++;
+ }
+ }
+
+ private void findIdsOnChoiceSet(ChoiceSet choiceSet){
+ findIdsOnChoices(new HashSet<>(choiceSet.getChoices()));
+ }
+
+ private void findIdsOnChoices(HashSet<ChoiceCell> choices){
+ for (ChoiceCell cell : choices){
+ ChoiceCell uploadCell = null;
+ if (pendingPreloadChoices.contains(cell)){
+ uploadCell = findIfPresent(cell, pendingPreloadChoices);
+ }else if (preloadedChoices.contains(cell)){
+ uploadCell = findIfPresent(cell, preloadedChoices);
+ }
+ if (uploadCell != null ){
+ cell.setChoiceId(uploadCell.getChoiceId());
+ }
+ }
+ }
+
+ private ChoiceCell findIfPresent(ChoiceCell cell, HashSet<ChoiceCell> set){
+ if (set.contains(cell)) {
+ for (ChoiceCell setCell : set) {
+ if (setCell.equals(cell))
+ return setCell;
+ }
+ }
+ return null;
+ }
+
+ // LISTENERS
+
+ private void addListeners(){
+
+ // DISPLAY CAPABILITIES - via SCM
+ displayListener = new OnSystemCapabilityListener() {
+ @Override
+ public void onCapabilityRetrieved(Object capability) {
+ displayCapabilities = (DisplayCapabilities) capability;
+ }
+
+ @Override
+ public void onError(String info) {
+ DebugTool.logError("Unable to retrieve display capabilities. Many things will probably break. Info: "+ info);
+ }
+ };
+ internalInterface.getCapability(SystemCapabilityType.DISPLAY, displayListener);
+
+ // HMI UPDATES
+ hmiListener = new OnRPCNotificationListener() {
+ @Override
+ public void onNotified(RPCNotification notification) {
+ OnHMIStatus hmiStatus = (OnHMIStatus) notification;
+ HMILevel oldHMILevel = currentHMILevel;
+ currentHMILevel = hmiStatus.getHmiLevel();
+ }
+ };
+ internalInterface.addOnRPCNotificationListener(FunctionID.ON_HMI_STATUS, hmiListener);
+
+ }
+
+ // ADDITIONAL HELPERS
+
+ private void checkVoiceOptional(){
+ transitionToState(CHECKING_VOICE);
+
+ // TODO: CheckChoiceVROptionalOperation
+ }
+
+ private boolean setUpChoiceSet(ChoiceSet choiceSet) {
+
+ List<ChoiceCell> choices = choiceSet.getChoices();
+
+ // Choices are not optional here
+ if (choices == null) {
+ DebugTool.logError("Cannot initiate a choice set with no choices");
+ return false;
+ }
+
+ HashSet<String> choiceTextSet = new HashSet<>();
+ HashSet<String> uniqueVoiceCommands = new HashSet<>();
+ int allVoiceCommandsCount = 0;
+ int choiceCellWithVoiceCommandCount = 0;
+
+ for (ChoiceCell cell : choices) {
+
+ choiceTextSet.add(cell.getText());
+
+ if (cell.getVoiceCommands() != null) {
+ uniqueVoiceCommands.addAll(cell.getVoiceCommands());
+ choiceCellWithVoiceCommandCount += 1;
+ allVoiceCommandsCount += cell.getVoiceCommands().size();
+ }
+ }
+
+ // Cell text MUST be unique
+ if (choiceTextSet.size() < choices.size()) {
+ DebugTool.logError("Attempted to create a choice set with duplicate cell text. Cell text must be unique. The choice set will not be set.");
+ return false;
+ }
+
+ // All or none of the choices MUST have VR Commands
+ if (choiceCellWithVoiceCommandCount > 0 && choiceCellWithVoiceCommandCount < choices.size()) {
+ DebugTool.logError("If using voice recognition commands, all of the choice set cells must have unique VR commands. There are " + uniqueVoiceCommands.size() + " cells with unique voice commands and " + allVoiceCommandsCount + " total cells. The choice set will not be set.");
+ return false;
+ }
+
+ // All VR Commands MUST be unique
+ if (uniqueVoiceCommands.size() < allVoiceCommandsCount) {
+ DebugTool.logError("If using voice recognition commands, all VR commands must be unique. There are " + uniqueVoiceCommands.size() + " unique VR commands and " + allVoiceCommandsCount + " VR commands. The choice set will not be set.");
+ return false;
+ }
+
+ return true;
+ }
+
+
+ private KeyboardProperties defaultKeyboardConfiguration(){
+ KeyboardProperties defaultProperties = new KeyboardProperties();
+ defaultProperties.setLanguage(Language.EN_US);
+ defaultProperties.setKeyboardLayout(KeyboardLayout.QWERTY);
+ defaultProperties.setKeypressMode(KeypressMode.RESEND_CURRENT_ENTRY);
+ return defaultProperties;
+ }
+}
diff --git a/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/ChoiceCell.java b/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/ChoiceCell.java
new file mode 100644
index 000000000..136ee0741
--- /dev/null
+++ b/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/ChoiceCell.java
@@ -0,0 +1,261 @@
+/*
+ * 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.screen.choiceset;
+
+import android.support.annotation.NonNull;
+
+import com.smartdevicelink.managers.file.filetypes.SdlArtwork;
+
+import java.util.List;
+
+public class ChoiceCell {
+ private String text, secondaryText, tertiaryText;
+ private List<String> voiceCommands;
+ private SdlArtwork artwork, secondaryArtwork;
+ private Integer choiceId;
+
+ /**
+ * MAX ID for cells - Cannot use Integer.MAX_INT as the value is too high.
+ */
+ private static final int MAX_ID = 2000000000;
+
+ /**
+ * Initialize the cell with text and nothing else.
+ *
+ * @param text - The primary text of the cell.
+ */
+ public ChoiceCell(@NonNull String text) {
+ setText(text);
+ setChoiceId(MAX_ID);
+ }
+
+ /**
+ * Initialize the cell with text, optional artwork, and optional voice commands
+ *
+ * @param text - The primary text of the cell
+ * @param voiceCommands - Strings that can be spoken by the user to activate this cell in a voice or both interaction mode
+ * @param artwork - The primary artwork of the cell
+ */
+ public ChoiceCell(@NonNull String text, List<String> voiceCommands, SdlArtwork artwork) {
+ setText(text);
+ setVoiceCommands(voiceCommands);
+ setArtwork(artwork);
+ setChoiceId(MAX_ID);
+ }
+
+ /**
+ * Initialize the cell with all optional items
+ *
+ * @param text - The primary text
+ * @param secondaryText - The secondary text
+ * @param tertiaryText - The tertiary text
+ * @param voiceCommands - Strings that can be spoken by the user to activate this cell in a voice or both interaction mode
+ * @param artwork - The primary artwork of the cell
+ * @param secondaryArtwork - The secondary artwork of the cell
+ */
+ public ChoiceCell(@NonNull String text, String secondaryText, String tertiaryText, List<String> voiceCommands, SdlArtwork artwork, SdlArtwork secondaryArtwork) {
+ setText(text);
+ setSecondaryText(secondaryText);
+ setTertiaryText(tertiaryText);
+ setVoiceCommands(voiceCommands);
+ setArtwork(artwork);
+ setSecondaryArtwork(secondaryArtwork);
+ setChoiceId(MAX_ID);
+ }
+
+ /**
+ * Maps to Choice.menuName. The primary text of the cell. Duplicates within an `ChoiceSet`
+ * are not permitted and will result in the `ChoiceSet` failing to initialize.
+ * @return The primary text of the cell
+ */
+ public String getText() {
+ return text;
+ }
+
+ /**
+ * @param text - Maps to Choice.menuName. The primary text of the cell. Duplicates within an `ChoiceSet`
+ * are not permitted and will result in the `ChoiceSet` failing to initialize.
+ */
+ public void setText(@NonNull String text) {
+ this.text = text;
+ }
+
+ /**
+ * Maps to Choice.secondaryText. Optional secondary text of the cell, if available. Duplicates
+ * within an `ChoiceSet` are permitted.
+ * @return Optional secondary text of the cell
+ */
+ public String getSecondaryText() {
+ return secondaryText;
+ }
+
+ /**
+ * @param secondaryText - Maps to Choice.secondaryText. Optional secondary text of the cell, if
+ * available. Duplicates within an `ChoiceSet` are permitted.
+ */
+ public void setSecondaryText(String secondaryText) {
+ this.secondaryText = secondaryText;
+ }
+
+ /**
+ * Maps to Choice.tertiaryText. Optional tertiary text of the cell, if available. Duplicates within an `ChoiceSet` are permitted.
+ * @return Optional tertiary text of the cell
+ */
+ public String getTertiaryText() {
+ return tertiaryText;
+ }
+
+ /**
+ * @param tertiaryText - Maps to Choice.tertiaryText. Optional tertiary text of the cell, if
+ * available. Duplicates within an `ChoiceSet` are permitted.
+ */
+ public void setTertiaryText(String tertiaryText) {
+ this.tertiaryText = tertiaryText;
+ }
+
+ /**
+ * Maps to Choice.vrCommands. Optional voice commands the user can speak to activate the cell.
+ * If not set and the head unit requires it, this will be set to the number in the list that this
+ * item appears. However, this would be a very poor experience for a user if the choice set is
+ * presented as a voice only interaction or both interaction mode. Therefore, consider not setting
+ * this only when you know the choice set will be presented as a touch only interaction.
+ * @return The list of voice command strings
+ */
+ public List<String> getVoiceCommands() {
+ return voiceCommands;
+ }
+
+ /**
+ * @param voiceCommands - Maps to Choice.vrCommands. Optional voice commands the user can speak to activate the cell.
+ * If not set and the head unit requires it, this will be set to the number in the list that this
+ * item appears. However, this would be a very poor experience for a user if the choice set is
+ * presented as a voice only interaction or both interaction mode. Therefore, consider not setting
+ * this only when you know the choice set will be presented as a touch only interaction.
+ */
+ public void setVoiceCommands(List<String> voiceCommands) {
+ this.voiceCommands = voiceCommands;
+ }
+
+ /**
+ * Maps to Choice.image. Optional image for the cell. This will be uploaded before the cell is
+ * used when the cell is preloaded or presented for the first time.
+ * @return The SdlArtwork
+ */
+ public SdlArtwork getArtwork() {
+ return artwork;
+ }
+
+ /**
+ * @param artwork - Maps to Choice.image. Optional image for the cell. This will be uploaded
+ * before the cell is used when the cell is preloaded or presented for the first time.
+ */
+ public void setArtwork(SdlArtwork artwork) {
+ this.artwork = artwork;
+ }
+
+ /**
+ * Maps to Choice.secondaryImage. Optional secondary image for the cell. This will be uploaded
+ * before the cell is used when the cell is preloaded or presented for the first time.
+ * @return The SdlArtwork
+ */
+ public SdlArtwork getSecondaryArtwork() {
+ return secondaryArtwork;
+ }
+
+ /**
+ * @param secondaryArtwork - Maps to Choice.secondaryImage. Optional secondary image for the cell.
+ * This will be uploaded before the cell is used when the cell is preloaded or presented for the first time.
+ */
+ public void setSecondaryArtwork(SdlArtwork secondaryArtwork) {
+ this.secondaryArtwork = secondaryArtwork;
+ }
+
+ /**
+ * NOTE: USED INTERNALLY
+ * Set the choice Id.
+ * @param choiceId - the choice Id
+ */
+ void setChoiceId(int choiceId) {
+ this.choiceId = choiceId;
+ }
+
+ /**
+ * NOTE: USED INTERNALLY
+ * Get the choiceId
+ * @return the choiceId for this Choice Cell
+ */
+ int getChoiceId() {
+ return choiceId;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+ result += ((getText() == null) ? 0 : Integer.rotateLeft(getText().hashCode(), 1));
+ result += ((getSecondaryText() == null) ? 0 : Integer.rotateLeft(getSecondaryText().hashCode(), 2));
+ result += ((getTertiaryText() == null) ? 0 : Integer.rotateLeft(getTertiaryText().hashCode(), 3));
+ result += ((getArtwork() == null || getArtwork().getName() == null) ? 0 : Integer.rotateLeft(getArtwork().getName().hashCode(), 4));
+ result += ((getSecondaryArtwork() == null || getSecondaryArtwork().getName() == null) ? 0 : Integer.rotateLeft(getSecondaryArtwork().getName().hashCode(), 5));
+ result += ((getVoiceCommands() == null) ? 0 : Integer.rotateLeft(getVoiceCommands().hashCode(), 6));
+ return result;
+ }
+
+ /**
+ * Uses our custom hashCode for ChoiceCell objects
+ * @param o - The object to compare
+ * @return boolean of whether the objects are the same or not
+ */
+ @Override
+ public boolean equals(Object o) {
+ // if this is the same memory address, its the same
+ if (this == o) return true;
+ // if this is not an instance of this class, not the same
+ if (!(o instanceof ChoiceCell)) return false;
+
+ ChoiceCell choiceCell = (ChoiceCell) o;
+ // if we get to this point, create the hashes and compare them
+ return hashCode() == choiceCell.hashCode();
+ }
+
+ /**
+ * Overriding toString was throwing a warning in AS, so I changed the name for now
+ * @return A string description of the cell, useful for debugging.
+ */
+ public String getDescription() {
+ return "ChoiceCell: ID: " + this.choiceId + " Text: " + text+ " - "+ secondaryText+" - "+ " - "+ tertiaryText+ " " +
+ "| Artwork Names: "+ ((getArtwork() == null || getArtwork().getName() == null) ? "Primary Art null" : getArtwork().getName())
+ + " - "+((getSecondaryArtwork() == null || getSecondaryArtwork().getName() == null) ? "Secondary Art null" : getSecondaryArtwork().getName()) +
+ " Voice Commands Size: "+ ((getVoiceCommands() == null) ? 0 : getVoiceCommands().size());
+ }
+
+}
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
new file mode 100644
index 000000000..335fddf9f
--- /dev/null
+++ b/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/ChoiceSet.java
@@ -0,0 +1,360 @@
+/*
+ * 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.screen.choiceset;
+
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.util.Log;
+
+import com.smartdevicelink.exception.SdlException;
+import com.smartdevicelink.exception.SdlExceptionCause;
+import com.smartdevicelink.proxy.TTSChunkFactory;
+import com.smartdevicelink.proxy.rpc.TTSChunk;
+import com.smartdevicelink.proxy.rpc.VrHelpItem;
+import com.smartdevicelink.util.DebugTool;
+
+import java.util.HashSet;
+import java.util.List;
+
+public class ChoiceSet {
+ private String title;
+ private List<TTSChunk> initialPrompt, timeoutPrompt, helpPrompt;
+ private ChoiceSetLayout layout;
+ private Integer timeout;
+ private List<ChoiceCell> choices;
+ private List<VrHelpItem> vrHelpList;
+ private ChoiceSetSelectionListener choiceSetSelectionListener;
+
+ // defaults
+ private Integer defaultTimeout = 10;
+ private ChoiceSetLayout defaultLayout = ChoiceSetLayout.CHOICE_SET_LAYOUT_LIST;
+
+ /**
+ * Initialize with a title, listener, and choices. It will use the default timeout and layout,
+ * all other properties (such as prompts) will be `null`.
+ *
+ * @param title - The choice set's title
+ * @param listener - The choice set listener called after the user has interacted with your choice set
+ * @param choices - The choices to be displayed to the user for interaction
+ */
+ public ChoiceSet(@NonNull String title, @NonNull ChoiceSetSelectionListener listener, @NonNull List<ChoiceCell> choices) {
+
+ setTitle(title);
+ setChoiceSetSelectionListener(listener);
+ setChoices(choices);
+
+ // defaults
+ setLayout(defaultLayout);
+ setTimeout(defaultTimeout);
+
+ // things to do
+ checkChoiceSetParameters();
+ }
+
+ /**
+ * Constructor with all possible properties.
+ *
+ * @param title - The choice set's title
+ * @param listener - The choice set listener called after the user has interacted with your choice set
+ * @param layout - The layout of choice options (Manual/touch only)
+ * @param timeout - The timeout of a touch interaction (Manual/touch only)
+ * @param initialPrompt - A voice prompt spoken to the user when this set is displayed
+ * @param timeoutPrompt - A voice prompt spoken to the user when the set times out (Voice only)
+ * @param helpPrompt - A voice prompt spoken to the user when the user asks for "help"
+ * @param helpList - A table list of text and images shown to the user during a voice recognition session for this choice set (Voice only)
+ * @param choices - The list of choices presented to the user either as a manual/touch interaction or via the user's voice
+ */
+ public ChoiceSet(@NonNull String title, @NonNull ChoiceSetSelectionListener listener, @Nullable ChoiceSetLayout layout, @Nullable Integer timeout, @Nullable String initialPrompt, @Nullable String timeoutPrompt, @Nullable String helpPrompt, @Nullable List<VrHelpItem> helpList, @NonNull List<ChoiceCell> choices) {
+
+ setTitle(title);
+ setChoiceSetSelectionListener(listener);
+ setLayout(layout);
+ setTimeout(timeout);
+ setChoices(choices);
+
+ // Help the dev by creating TTS chunks for them
+ if (initialPrompt != null){
+ setInitialPrompt(TTSChunkFactory.createSimpleTTSChunks(initialPrompt));
+ }
+
+ if (timeoutPrompt != null){
+ setTimeoutPrompt(TTSChunkFactory.createSimpleTTSChunks(timeoutPrompt));
+ }
+
+ if (helpPrompt != null){
+ setHelpPrompt(TTSChunkFactory.createSimpleTTSChunks(helpPrompt));
+ }
+
+ // things to do
+ checkChoiceSetParameters();
+ setUpHelpItems(helpList);
+ }
+
+ /**
+ * Constructor with all possible properties.
+ *
+ * @param title - The choice set's title
+ * @param listener - The choice set listener called after the user has interacted with your choice set
+ * @param layout - The layout of choice options (Manual/touch only)
+ * @param timeout - The timeout of a touch interaction (Manual/touch only)
+ * @param initialPrompt - A voice prompt spoken to the user when this set is displayed
+ * @param timeoutPrompt - A voice prompt spoken to the user when the set times out (Voice only)
+ * @param helpPrompt - A voice prompt spoken to the user when the user asks for "help"
+ * @param helpList - A table list of text and images shown to the user during a voice recognition session for this choice set (Voice only)
+ * @param choices - The list of choices presented to the user either as a manual/touch interaction or via the user's voice
+ */
+ public ChoiceSet(@NonNull String title, @NonNull ChoiceSetSelectionListener listener, @Nullable ChoiceSetLayout layout, @Nullable Integer timeout, @Nullable List<TTSChunk> initialPrompt, @Nullable List<TTSChunk> timeoutPrompt, @Nullable List<TTSChunk> helpPrompt, @Nullable List<VrHelpItem> helpList, @NonNull List<ChoiceCell> choices) {
+
+ setTitle(title);
+ setChoiceSetSelectionListener(listener);
+ setInitialPrompt(initialPrompt);
+ setTimeoutPrompt(timeoutPrompt);
+ setHelpPrompt(helpPrompt);
+ setChoices(choices);
+ setTimeout(timeout);
+ setLayout(layout);
+
+ // things to do
+ checkChoiceSetParameters();
+ setUpHelpItems(helpList);
+ }
+
+ /**
+ * Maps to PerformInteraction.initialText. The title of the choice set, and/or the initial text on a keyboard prompt.
+ * @return the title
+ */
+ public String getTitle() {
+ return title;
+ }
+
+ /**
+ * @param title - Maps to PerformInteraction.initialText. The title of the choice set, and/or the initial text on a keyboard prompt.
+ */
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ /**
+ * Maps to PerformInteraction.initialPrompt. The initial prompt spoken to the user at the start of an interaction.
+ * @return The list of TTSChunks
+ */
+ public List<TTSChunk> getInitialPrompt() {
+ return initialPrompt;
+ }
+
+ /**
+ * @param initialPrompt - Maps to PerformInteraction.initialPrompt. The initial prompt spoken to the user at the start of an interaction.
+ */
+ public void setInitialPrompt(List<TTSChunk> initialPrompt) {
+ this.initialPrompt = initialPrompt;
+ }
+
+ /**
+ * Maps to PerformInteraction.timeoutPrompt. This text is spoken when a VR interaction times out.
+ * If this set is presented in a manual (non-voice) only interaction, this will be ignored.
+ * @return - The list of TTS Chunks
+ */
+ public List<TTSChunk> getTimeoutPrompt() {
+ return timeoutPrompt;
+ }
+
+ /**
+ * @param timeoutPrompt - Maps to PerformInteraction.timeoutPrompt. This text is spoken when a
+ * VR interaction times out. If this set is presented in a manual (non-voice) only interaction, this will be ignored.
+ */
+ public void setTimeoutPrompt(List<TTSChunk> timeoutPrompt) {
+ this.timeoutPrompt = timeoutPrompt;
+ }
+
+ /**
+ * Maps to PerformInteraction.helpPrompt. This is the spoken string when a user speaks "help" when the interaction is occurring.
+ * @return The List of TTS Chunks
+ */
+ public List<TTSChunk> getHelpPrompt() {
+ return helpPrompt;
+ }
+
+ /**
+ * @param helpPrompt - Maps to PerformInteraction.helpPrompt. This is the spoken string when a user
+ * speaks "help" when the interaction is occurring.
+ */
+ public void setHelpPrompt(List<TTSChunk> helpPrompt) {
+ this.helpPrompt = helpPrompt;
+ }
+
+ /**
+ * Maps to PerformInteraction.vrHelp. This is a list of help text presented to the user when
+ * they are in a voice recognition interaction from your choice set of options. If this set is
+ * presented in a touch only interaction, this will be ignored.
+ *
+ * Note: That while VRHelpItem's position will be automatically set based on position in the
+ * array, the image will need to uploaded by you before use using the FileManager.
+ *
+ * @return The List of VR Help Items
+ */
+ public List<VrHelpItem> getVrHelpList() {
+ return vrHelpList;
+ }
+
+ /**
+ * @param vrHelpList - Maps to PerformInteraction.vrHelp. This is a list of help text presented to the user when
+ * they are in a voice recognition interaction from your choice set of options. If this set is
+ * presented in a touch only interaction, this will be ignored.
+ *
+ * Note: That while SDLVRHelpItem's position will be automatically set based on position in the
+ * array, the image will need to uploaded by you before use using the FileManager.
+ */
+ public void setVrHelpList(List<VrHelpItem> vrHelpList) {
+
+ if (vrHelpList != null) {
+ for (int i = 0; i < vrHelpList.size(); i++) {
+ vrHelpList.get(i).setPosition(i+1);
+ }
+ }
+
+ this.vrHelpList = vrHelpList;
+ }
+
+ /**
+ * Maps to PerformInteraction.interactionLayout. Whether the presented choices are arranged as
+ * a set of tiles or a list.
+ * @return The ChoiceSetLayout
+ */
+ public ChoiceSetLayout getLayout() {
+ return layout;
+ }
+
+ /**
+ * @param layout - Maps to PerformInteraction.interactionLayout. Whether the presented choices
+ * are arranged as a set of tiles or a list.
+ */
+ public void setLayout(ChoiceSetLayout layout) {
+ if (layout == null){
+ this.layout = defaultLayout;
+ } else {
+ this.layout = layout;
+ }
+ }
+
+ /**
+ * Maps to PerformInteraction.timeout. This applies only to a manual selection (not a voice
+ * selection, which has its timeout handled by the system). Defaults to `defaultTimeout`.
+ * @return The Timeout
+ */
+ public Integer getTimeout() {
+ return timeout;
+ }
+
+ /**
+ * @param timeout - Maps to PerformInteraction.timeout. This applies only to a manual selection
+ * (not a voice selection, which has its timeout handled by the system). Defaults to `defaultTimeout`.
+ */
+ public void setTimeout(Integer timeout) {
+ if (timeout == null) {
+ this.timeout = defaultTimeout;
+ } else {
+ this.timeout = timeout;
+ }
+ }
+
+ /**
+ * The choices to be displayed to the user within this choice set. These choices could match
+ * those already preloaded
+ *
+ * This is limited to 100 items. If you attempt to set more than 100 items, the set will not
+ * have any items (this array will be empty).
+ * @return The List of ChoiceCells
+ */
+ public List<ChoiceCell> getChoices() {
+ return choices;
+ }
+
+ /**
+ * @param choices - The choices to be displayed to the user within this choice set. These choices could match
+ * those already preloaded
+ *
+ * This is limited to 100 items. If you attempt to set more than 100 items, the set will not
+ * have any items (this array will be empty).
+ */
+ public void setChoices(List<ChoiceCell> choices) {
+ this.choices = choices;
+ }
+
+ /**
+ * The listener of this choice set, called when the user interacts with it.
+ * @return The listener
+ */
+ public ChoiceSetSelectionListener getChoiceSetSelectionListener() {
+ return choiceSetSelectionListener;
+ }
+
+ /**
+ * @param choiceSetSelectionListener The listener of this choice set, called when the user interacts with it.
+ */
+ public void setChoiceSetSelectionListener(ChoiceSetSelectionListener choiceSetSelectionListener) {
+ this.choiceSetSelectionListener = choiceSetSelectionListener;
+ }
+
+ // HELPERS
+
+ private void checkChoiceSetParameters(){
+ if (DebugTool.isDebugEnabled()) {
+ if (getTitle() != null) {
+ if (getTitle().length() == 0 || getTitle().length() > 500) {
+ DebugTool.logWarning("Attempted to create a choice set with a title of " + getTitle().length() + " length. Only 500 characters are supported.");
+ }
+ }
+ if (getTimeout() != null) {
+ if (getTimeout() < 5 || getTimeout() > 100) {
+ DebugTool.logWarning("Attempted to create a choice set with a " + getTimeout() + " second timeout; Only 5 - 100 seconds is valid");
+ }
+ }
+ if (getChoices() != null) {
+ if (getChoices().size() == 0 || getChoices().size() > 100) {
+ DebugTool.logWarning("Attempted to create a choice set with "+getChoices().size()+" choices; Only 1 - 100 choices are valid");
+ }
+ }
+ }
+ }
+
+ private void setUpHelpItems(List<VrHelpItem> helpItems){
+ // set help item positioning
+ if (helpItems != null) {
+ for (int i = 0; i < helpItems.size(); i++) {
+ helpItems.get(i).setPosition(i+1);
+ }
+ setVrHelpList(helpItems);
+ }
+ }
+
+}
diff --git a/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/ChoiceSetLayout.java b/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/ChoiceSetLayout.java
new file mode 100644
index 000000000..312accd75
--- /dev/null
+++ b/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/ChoiceSetLayout.java
@@ -0,0 +1,46 @@
+/*
+ * 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.screen.choiceset;
+
+public enum ChoiceSetLayout {
+ CHOICE_SET_LAYOUT_LIST,
+ CHOICE_SET_LAYOUT_TILES;
+
+ public static ChoiceSetLayout valueForString(String value) {
+ try {
+ return valueOf(value);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+}
diff --git a/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/ChoiceSetSelectionListener.java b/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/ChoiceSetSelectionListener.java
new file mode 100644
index 000000000..5f477b58a
--- /dev/null
+++ b/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/ChoiceSetSelectionListener.java
@@ -0,0 +1,40 @@
+/*
+ * 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.screen.choiceset;
+
+import com.smartdevicelink.proxy.rpc.enums.TriggerSource;
+
+public interface ChoiceSetSelectionListener {
+ void onChoiceSelected(ChoiceCell choiceCell, TriggerSource triggerSource, int rowIndex);
+ void onError(String error);
+}
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
new file mode 100644
index 000000000..a921766db
--- /dev/null
+++ b/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/KeyboardAutocompleteCompletionListener.java
@@ -0,0 +1,42 @@
+/*
+ * 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.screen.choiceset;
+
+public interface KeyboardAutocompleteCompletionListener {
+
+ /**
+ * This listener is called when you wish to update your autocomplete text in response to the user's input
+ * @param updatedAutoCompleteText - The new autocomplete text to use
+ */
+ void onUpdatedAutoCompleteText(String updatedAutoCompleteText);
+}
diff --git a/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/KeyboardCharacterSetCompletionListener.java b/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/KeyboardCharacterSetCompletionListener.java
new file mode 100644
index 000000000..7221bf7d1
--- /dev/null
+++ b/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/KeyboardCharacterSetCompletionListener.java
@@ -0,0 +1,12 @@
+package com.smartdevicelink.managers.screen.choiceset;
+
+import java.util.List;
+
+public interface KeyboardCharacterSetCompletionListener {
+
+ /**
+ * This listener is called when you wish to update your keyboard's limitedCharacterSet in response to the user's input
+ * @param updatedCharacterSet - The new set of characters to use
+ */
+ void onUpdatedCharacterSet(List<String> updatedCharacterSet);
+}
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
new file mode 100644
index 000000000..a92fafa75
--- /dev/null
+++ b/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/KeyboardListener.java
@@ -0,0 +1,87 @@
+/*
+ * 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.screen.choiceset;
+
+import com.smartdevicelink.proxy.rpc.enums.KeyboardEvent;
+
+public interface KeyboardListener {
+
+ /**
+ * The keyboard session completed with some input.
+ *
+ * This will be sent upon ENTRY_SUBMITTED or ENTRY_VOICE. If the event is ENTRY_VOICE, the user
+ * requested to start a voice session in order to submit input to this keyboard. This MUST be
+ * handled by you. Start an Audio Pass Thru session if supported.
+ *
+ * @param inputText - The submitted input text on the keyboard
+ * @param event - ENTRY_SUBMITTED if the user pressed the submit button on the keyboard, ENTRY_VOICE
+ * if the user requested that a voice session begin
+ */
+ void onUserDidSubmitInput(String inputText, KeyboardEvent event);
+
+ /**
+ * The keyboard session aborted.
+ *
+ * This will be sent if the keyboard event ENTRY_CANCELLED or ENTRY_ABORTED is sent
+ *
+ * @param event - ENTRY_CANCELLED if the user cancelled the keyboard input, or ENTRY_ABORTED if
+ * the system aborted the input due to a higher priority event
+ */
+ void onKeyboardDidAbortWithReason(KeyboardEvent event);
+
+ /**
+ * Implement this in order to provide a custom keyboard configuration to just this keyboard. To
+ * apply default settings to all keyboards, see SDLScreenManager.keyboardConfiguration
+ *
+ * @param currentInputText - The user's full current input text
+ * @param keyboardAutocompleteCompletionListener - A listener to update the autoCompleteText
+ */
+ void updateAutocompleteWithInput(String currentInputText, KeyboardAutocompleteCompletionListener keyboardAutocompleteCompletionListener);
+
+ /**
+ * Implement this if you wish to update the limitedCharacterSet as the user updates their input.
+ * This is called upon a KEYPRESS event.
+ *
+ * @param currentInputText - The user's full current input text
+ * @param keyboardCharacterSetCompletionListener - A listener to update the limitedCharacterSet
+ */
+ void updateCharacterSetWithInput(String currentInputText, KeyboardCharacterSetCompletionListener keyboardCharacterSetCompletionListener);
+
+ /**
+ * Implement this to be notified of all events occurring on the keyboard
+ *
+ * @param event - The event that occurred
+ * @param currentInputText - The user's full current input text
+ */
+ void onKeyboardDidSendEvent(KeyboardEvent event, String currentInputText);
+} \ No newline at end of file
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
new file mode 100644
index 000000000..2cb3ad2f3
--- /dev/null
+++ b/javaSE/src/main/java/com/smartdevicelink/managers/screen/choiceset/ChoiceSetManager.java
@@ -0,0 +1,55 @@
+/*
+ * 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.screen.choiceset;
+
+import android.support.annotation.NonNull;
+
+import com.smartdevicelink.managers.file.FileManager;
+import com.smartdevicelink.proxy.interfaces.ISdl;
+
+/**
+ * <strong>ChoiceSetManager</strong> <br>
+ * ChoiceSetManager gives the developer the ability to control how soft choice sets are displayed on the head unit.<br>
+ * Note: This class must be accessed through the SdlManager->ScreenManager. Do not instantiate it by itself.<br>
+ */
+class ChoiceSetManager extends BaseChoiceSetManager {
+
+ /**
+ * Creates a new instance of the ChoiceSetManager
+ *
+ * @param internalInterface
+ */
+ ChoiceSetManager(@NonNull ISdl internalInterface, @NonNull FileManager fileManager) {
+ super(internalInterface, fileManager);
+ }
+}