summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicoleYarroch <nicole@livio.io>2019-08-13 16:40:26 -0400
committerNicoleYarroch <nicole@livio.io>2019-08-13 16:40:26 -0400
commit30514fbc3b0671c84387a815907f1159a7529f47 (patch)
treecb8dff67e46a6cdacd926c046b672a610f9ed5d4
parentbe6d813dc2626bbc6b6729aeb44aa7f7dd0078c2 (diff)
downloadsdl_android-30514fbc3b0671c84387a815907f1159a7529f47.tar.gz
Keyboard now cancels with `cancelID`
Test cases fixed
-rw-r--r--android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/ChoiceSetManagerTests.java60
-rw-r--r--android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/PresentKeyboardOperationTests.java3
-rw-r--r--base/src/main/java/com/smartdevicelink/managers/screen/BaseScreenManager.java22
-rw-r--r--base/src/main/java/com/smartdevicelink/managers/screen/choiceset/BaseChoiceSetManager.java50
-rw-r--r--base/src/main/java/com/smartdevicelink/managers/screen/choiceset/PresentChoiceSetOperation.java14
-rw-r--r--base/src/main/java/com/smartdevicelink/managers/screen/choiceset/PresentKeyboardOperation.java80
6 files changed, 160 insertions, 69 deletions
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 9cdb1b67c..4d47ba89c 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
@@ -48,11 +48,14 @@ import com.smartdevicelink.proxy.rpc.enums.Language;
import com.smartdevicelink.proxy.rpc.enums.SystemContext;
import com.smartdevicelink.proxy.rpc.enums.TriggerSource;
+import org.junit.Test;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
+import java.util.concurrent.LinkedBlockingQueue;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
@@ -72,7 +75,6 @@ public class ChoiceSetManagerTests extends AndroidTestCase2 {
ISdl internalInterface = mock(ISdl.class);
FileManager fileManager = mock(FileManager.class);
csm = new ChoiceSetManager(internalInterface, fileManager);
- csm.sdlMsgVersion = new SdlMsgVersion(6, 0);
assertEquals(csm.getState(), BaseSubManager.SETTING_UP);
assertEquals(csm.currentSystemContext, SystemContext.SYSCTXT_MAIN);
@@ -241,28 +243,48 @@ public class ChoiceSetManagerTests extends AndroidTestCase2 {
}
}
+ public void testPresentingKeyboard() {}
+
+ public void testPresentingKeyboardWithDeprecatedMethod() {}
+
+ public void testPresentingKeyboardWhenKeyboardCannotBeSentToCore() {}
+
public void testDismissKeyboardThatIsExecuting(){
- PresentKeyboardOperation testOp = mock(PresentKeyboardOperation.class);
- doReturn(true).when(testOp).isExecuting();
- csm.currentlyPresentedKeyboardOperation = testOp;
- csm.dismissKeyboard();
- verify(testOp, times(1)).dismissKeyboard();
+ Integer testCancelID = 42;
+ PresentKeyboardOperation testKeyboardOp = mock(PresentKeyboardOperation.class);
+ doReturn(testCancelID).when(testKeyboardOp).getCancelID();
+ doReturn(true).when(testKeyboardOp).isExecuting();
+ csm.currentlyPresentedKeyboardOperation = testKeyboardOp;
+ csm.dismissKeyboard(testCancelID);
+ verify(testKeyboardOp, times(1)).dismissKeyboard();
}
public void testDismissKeyboardThatIsNotExecuting(){
- PresentKeyboardOperation testOp = mock(PresentKeyboardOperation.class);
- doReturn(false).when(testOp).isExecuting();
- csm.currentlyPresentedKeyboardOperation = testOp;
- csm.dismissKeyboard();
- verify(testOp, times(0)).dismissKeyboard();
+ Integer testCancelID = 42;
+ PresentKeyboardOperation testKeyboardOp = mock(PresentKeyboardOperation.class);
+ doReturn(false).when(testKeyboardOp).isExecuting();
+ doReturn(testCancelID).when(testKeyboardOp).getCancelID();
+ csm.currentlyPresentedKeyboardOperation = testKeyboardOp;
+ csm.dismissKeyboard(testCancelID);
+ verify(testKeyboardOp, times(1)).dismissKeyboard();
}
-
- public void testDismissKeyboardIfHeadUnitDoesNotSupportFeature(){
- csm.sdlMsgVersion = new SdlMsgVersion(5, 3);
- PresentKeyboardOperation testOp = mock(PresentKeyboardOperation.class);
- doReturn(true).when(testOp).isExecuting();
- csm.currentlyPresentedKeyboardOperation = testOp;
- csm.dismissKeyboard();
- verify(testOp, times(0)).dismissKeyboard();
+
+ public void testDismissingMultipleKeyboards(){
+ Integer testCancelID = 42;
+ PresentKeyboardOperation testKeyboardOp = mock(PresentKeyboardOperation.class);
+ doReturn(true).when(testKeyboardOp).isExecuting();
+ doReturn(96).when(testKeyboardOp).getCancelID();
+ csm.currentlyPresentedKeyboardOperation = testKeyboardOp;
+
+ PresentKeyboardOperation testKeyboardOp2 = mock(PresentKeyboardOperation.class);
+ doReturn(true).when(testKeyboardOp2).isExecuting();
+ doReturn(testCancelID).when(testKeyboardOp2).getCancelID();
+ LinkedBlockingQueue<Runnable> testOperationQueue = new LinkedBlockingQueue<>();
+ testOperationQueue.add(testKeyboardOp2);
+ csm.operationQueue = testOperationQueue;
+
+ csm.dismissKeyboard(testCancelID);
+ verify(testKeyboardOp, times(0)).dismissKeyboard();
+ verify(testKeyboardOp2, times(1)).dismissKeyboard();
}
}
diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/PresentKeyboardOperationTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/PresentKeyboardOperationTests.java
index 7e096c13a..39cd71b5a 100644
--- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/PresentKeyboardOperationTests.java
+++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/PresentKeyboardOperationTests.java
@@ -42,6 +42,7 @@ import com.smartdevicelink.proxy.interfaces.ISdl;
import com.smartdevicelink.proxy.rpc.CancelInteraction;
import com.smartdevicelink.proxy.rpc.KeyboardProperties;
import com.smartdevicelink.proxy.rpc.PerformInteraction;
+import com.smartdevicelink.proxy.rpc.SdlMsgVersion;
import com.smartdevicelink.proxy.rpc.SetGlobalProperties;
import com.smartdevicelink.proxy.rpc.enums.KeyboardLayout;
import com.smartdevicelink.proxy.rpc.enums.KeypressMode;
@@ -86,6 +87,8 @@ public class PresentKeyboardOperationTests extends AndroidTestCase2 {
}
};
doAnswer(setGlobalPropertiesAnswer).when(internalInterface).sendRPC(any(SetGlobalProperties.class));
+
+ presentKeyboardOperation.sdlMsgVersion = new SdlMsgVersion(6,0);
}
@Override
diff --git a/base/src/main/java/com/smartdevicelink/managers/screen/BaseScreenManager.java b/base/src/main/java/com/smartdevicelink/managers/screen/BaseScreenManager.java
index f9c8876c4..4884b0b7d 100644
--- a/base/src/main/java/com/smartdevicelink/managers/screen/BaseScreenManager.java
+++ b/base/src/main/java/com/smartdevicelink/managers/screen/BaseScreenManager.java
@@ -523,8 +523,20 @@ abstract class BaseScreenManager extends BaseSubManager {
* @param customKeyboardProperties - the custom keyboard configuration to be used when the keyboard is displayed
* @param keyboardListener - A keyboard listener to capture user input
*/
+ @Deprecated
public void presentKeyboard(@NonNull String initialText, @Nullable KeyboardProperties customKeyboardProperties, @NonNull KeyboardListener keyboardListener){
- this.choiceSetManager.presentKeyboard(initialText, customKeyboardProperties, keyboardListener);
+ presentKeyboard(initialText, keyboardListener, customKeyboardProperties);
+ }
+
+ /**
+ * Presents a keyboard on the Head unit to capture user input
+ * @param initialText - The initial text that is used as a placeholder text. It might not work on some head units.
+ * @param keyboardListener - A keyboard listener to capture user input
+ * @param customKeyboardProperties - the custom keyboard configuration to be used when the keyboard is displayed
+ * @return A unique cancelID that can be used to cancel this keyboard. If `null`, no keyboard was created.
+ */
+ public Integer presentKeyboard(@NonNull String initialText, @NonNull KeyboardListener keyboardListener, @Nullable KeyboardProperties customKeyboardProperties){
+ return this.choiceSetManager.presentKeyboard(initialText, keyboardListener, customKeyboardProperties);
}
/**
@@ -543,10 +555,11 @@ abstract class BaseScreenManager extends BaseSubManager {
}
/**
- * Cancels the keyboard-only interface if it is currently showing.
+ * Dismisses a currently presented keyboard with the associated ID. Canceling a keyboard only works when connected to SDL Core v.6.0+. When connected to older versions of SDL Core the keyboard will not be dismissed.
+ * @param cancelID The unique ID assigned to the keyboard
*/
- public void dismissKeyboard() {
- this.choiceSetManager.dismissKeyboard();
+ public void dismissKeyboard(Integer cancelID) {
+ this.choiceSetManager.dismissKeyboard(cancelID);
}
// END CHOICE SETS
@@ -588,5 +601,4 @@ abstract class BaseScreenManager extends BaseSubManager {
}
});
}
-
}
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 6d7ee5fa4..a3db8f38a 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
@@ -78,7 +78,6 @@ abstract class BaseChoiceSetManager extends BaseSubManager {
private static final int CHECKING_VOICE = 0xA0;
private KeyboardProperties keyboardConfiguration;
final WeakReference<FileManager> fileManager;
- SdlMsgVersion sdlMsgVersion;
OnRPCNotificationListener hmiListener;
OnSystemCapabilityListener displayListener;
@@ -124,7 +123,6 @@ abstract class BaseChoiceSetManager extends BaseSubManager {
executor.pause(); // pause until HMI ready
currentlyPresentedKeyboardOperation = null;
- this.sdlMsgVersion = internalInterface.getSdlMsgVersion();
}
@Override
@@ -375,14 +373,25 @@ abstract class BaseChoiceSetManager extends BaseSubManager {
* @param customKeyboardConfig - the custom keyboard configuration to be used when the keyboard is displayed
* @param listener - A keyboard listener to capture user input
*/
+ @Deprecated
public void presentKeyboard(@NonNull String initialText, @Nullable KeyboardProperties customKeyboardConfig, @NonNull KeyboardListener listener){
+ presentKeyboard(initialText, listener, customKeyboardConfig);
+ }
+ /**
+ * Presents a keyboard on the Head unit to capture user input
+ * @param initialText - The initial text that is used as a placeholder text. It might not work on some head units.
+ * @param customKeyboardConfig - the custom keyboard configuration to be used when the keyboard is displayed
+ * @param listener - A keyboard listener to capture user input
+ * @return - A unique id that can be used to cancel this keyboard. If `null`, no keyboard was created.
+ */
+ public Integer presentKeyboard(@NonNull String initialText, @NonNull KeyboardListener listener, @Nullable KeyboardProperties customKeyboardConfig){
if (initialText == null || initialText.length() == 0){
DebugTool.logError("initialText cannot be an empty string.");
- return;
+ return null;
}
- if (!isReady()){ return; }
+ if (!isReady()){ return null; }
if (pendingPresentationSet != null && pendingPresentOperation != null){
pendingPresentOperation.cancel(true);
@@ -400,22 +409,37 @@ abstract class BaseChoiceSetManager extends BaseSubManager {
// Present a keyboard with the choice set that we used to test VR's optional state
DebugTool.logInfo("Presenting Keyboard - Choice Set Manager");
- PresentKeyboardOperation keyboardOp = new PresentKeyboardOperation(internalInterface, keyboardConfiguration, initialText, customKeyboardConfig, listener, nextCancelId++);
+ Integer keyboardCancelID = nextCancelId++;
+ PresentKeyboardOperation keyboardOp = new PresentKeyboardOperation(internalInterface, keyboardConfiguration, initialText, customKeyboardConfig, listener, keyboardCancelID);
currentlyPresentedKeyboardOperation = keyboardOp;
pendingPresentOperation = executor.submit(keyboardOp);
+ return keyboardCancelID;
}
- /*
- * Cancels the keyboard-only interface if it is currently showing
- */
- public void dismissKeyboard() {
- if (sdlMsgVersion.getMajorVersion() < 6){
- DebugTool.logWarning("Canceling a presented keyboard is not supported on this head unit");
+ /**
+ * Cancels the keyboard-only interface if it is currently showing. If the keyboard has not yet been sent to Core, it will not be sent.
+ *
+ * This will only dismiss an already presented keyboard if connected to head units running SDL 6.0+.
+ *
+ * @param cancelID - The unique ID assigned to the keyboard, passed as the return value from `presentKeyboardWithInitialText:keyboardDelegate:`
+ */
+ public void dismissKeyboard(Integer cancelID) {
+ // First, attempt to cancel the currently executing keyboard operation (Once an operation has started it is removed from the operationQueue)
+ if (currentlyPresentedKeyboardOperation != null && currentlyPresentedKeyboardOperation.getCancelID() == cancelID) {
+ currentlyPresentedKeyboardOperation.dismissKeyboard();
return;
}
- if (currentlyPresentedKeyboardOperation == null || !currentlyPresentedKeyboardOperation.isExecuting()) { return; }
- currentlyPresentedKeyboardOperation.dismissKeyboard();
+ // Next, attempt to cancel keyboard operations that have not yet started
+ for (Runnable operation : operationQueue){
+ if (!(operation instanceof PresentKeyboardOperation)){ continue; }
+
+ PresentKeyboardOperation pendingOp = (PresentKeyboardOperation) operation;
+ if (!(pendingOp.getCancelID() == cancelID)) { continue; }
+
+ pendingOp.dismissKeyboard();
+ break;
+ }
}
/**
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 864c1afc9..d177e4f8b 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
@@ -229,18 +229,18 @@ class PresentChoiceSetOperation extends AsynchronousOperation {
* Cancels the choice set. If the choice set has not yet been sent to Core, it will not be sent. If the choice set is already presented on Core, the choice set will be dismissed using the `CancelInteraction` RPC.
*/
private void cancelInteraction() {
- if (sdlMsgVersion.getMajorVersion() < 6){
- DebugTool.logWarning("Canceling a presented choice set is not supported on this head unit");
- return;
- }
-
if (isFinished()) {
- // This operation has already finished so it can not be canceled.
+ DebugTool.logInfo("This operation has already finished so it can not be canceled.");
return;
} else if (Thread.currentThread().isInterrupted()) {
- // This operation has been canceled. It will be finished at some point during the operation.
+ DebugTool.logInfo("This operation has already been canceled. It will be finished at some point during the operation.");
return;
} else if (isExecuting()) {
+ if (sdlMsgVersion.getMajorVersion() < 6){
+ DebugTool.logWarning("Canceling a presented choice set is not supported on this head unit");
+ return;
+ }
+
DebugTool.logInfo("Canceling the presented choice set interaction.");
CancelInteraction cancelInteraction = new CancelInteraction(FunctionID.PERFORM_INTERACTION.getId(), cancelID);
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 30d2b75e6..9346725fb 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
@@ -44,6 +44,7 @@ import com.smartdevicelink.proxy.rpc.CancelInteraction;
import com.smartdevicelink.proxy.rpc.KeyboardProperties;
import com.smartdevicelink.proxy.rpc.OnKeyboardInput;
import com.smartdevicelink.proxy.rpc.PerformInteraction;
+import com.smartdevicelink.proxy.rpc.SdlMsgVersion;
import com.smartdevicelink.proxy.rpc.SetGlobalProperties;
import com.smartdevicelink.proxy.rpc.enums.InteractionMode;
import com.smartdevicelink.proxy.rpc.enums.KeyboardEvent;
@@ -67,6 +68,7 @@ class PresentKeyboardOperation extends AsynchronousOperation {
private String initialText;
private OnRPCNotificationListener keyboardRPCListener;
private Integer cancelID;
+ SdlMsgVersion sdlMsgVersion;
PresentKeyboardOperation(ISdl internalInterface, KeyboardProperties originalKeyboardProperties, String initialText, KeyboardProperties customConfig, KeyboardListener keyboardListener, Integer cancelID){
this.internalInterface = new WeakReference<>(internalInterface);
@@ -76,6 +78,7 @@ class PresentKeyboardOperation extends AsynchronousOperation {
this.customConfig = customConfig;
this.initialText = initialText;
this.cancelID = cancelID;
+ this.sdlMsgVersion = internalInterface.getSdlMsgVersion();
}
@Override
@@ -88,6 +91,12 @@ class PresentKeyboardOperation extends AsynchronousOperation {
private void start(){
DebugTool.logInfo("Choice Operation: Executing present keyboard operation");
+
+ if (Thread.currentThread().isInterrupted()) {
+ finishOperation();
+ return;
+ }
+
if (keyboardListener != null){
keyboardProperties = customConfig;
updatedKeyboardProperties = true;
@@ -96,6 +105,11 @@ class PresentKeyboardOperation extends AsynchronousOperation {
updateKeyboardProperties(new CompletionListener() {
@Override
public void onComplete(boolean success) {
+ if (Thread.currentThread().isInterrupted()) {
+ finishOperation();
+ return;
+ }
+
presentKeyboard();
}
});
@@ -124,40 +138,48 @@ class PresentKeyboardOperation extends AsynchronousOperation {
}else{
DebugTool.logError("Internal Interface null in present keyboard operation - choice");
}
-
}
- /*
- * Cancels a currently presented keyboard
- */
+ /**
+ * Cancels the keyboard-only interface if it is currently showing. If the keyboard has not yet been sent to Core, it will not be sent.
+ *
+ * This will only dismiss an already presented keyboard if connected to head units running SDL 6.0+.
+ */
void dismissKeyboard() {
- if (Thread.currentThread().isInterrupted()) {
- // This operation has been canceled. It will be finished at some point during the operation.
+ if (isFinished()) {
+ DebugTool.logInfo("This operation has already finished so it can not be canceled.");
return;
- }
-
- if (!isExecuting()) {
- DebugTool.logInfo("Keyboard is not being presented so it can not be canceled.");
+ } else if (Thread.currentThread().isInterrupted()) {
+ DebugTool.logInfo("This operation has already been canceled. It will be finished at some point during the operation.");
return;
- }
-
- DebugTool.logInfo("Canceling the presented keyboard.");
- CancelInteraction cancelInteraction = new CancelInteraction(FunctionID.PERFORM_INTERACTION.getId(), cancelID);
- cancelInteraction.setOnRPCResponseListener(new OnRPCResponseListener() {
- @Override
- public void onResponse(int correlationId, RPCResponse response) {
- DebugTool.logInfo("Canceled the presented keyboard " + ((response.getResultCode() == Result.SUCCESS) ? "successfully" : "unsuccessfully"));
+ } else if (isExecuting()) {
+ if (sdlMsgVersion.getMajorVersion() < 6){
+ DebugTool.logWarning("Canceling a keyboard is not supported on this head unit");
+ return;
}
- @Override
- public void onError(int correlationId, Result resultCode, String info){
- DebugTool.logError("Error canceling the presented keyboard " + resultCode + " " + info);
+ DebugTool.logInfo("Canceling the presented keyboard.");
+
+ CancelInteraction cancelInteraction = new CancelInteraction(FunctionID.PERFORM_INTERACTION.getId(), cancelID);
+ cancelInteraction.setOnRPCResponseListener(new OnRPCResponseListener() {
+ @Override
+ public void onResponse(int correlationId, RPCResponse response) {
+ DebugTool.logInfo("Canceled the presented keyboard " + ((response.getResultCode() == Result.SUCCESS) ? "successfully" : "unsuccessfully"));
+ }
+
+ @Override
+ public void onError(int correlationId, Result resultCode, String info){
+ DebugTool.logError("Error canceling the presented keyboard " + resultCode + " " + info);
+ }
+ });
+ if (internalInterface.get() != null){
+ internalInterface.get().sendRPC(cancelInteraction);
+ } else {
+ DebugTool.logError("Internal interface null - could not send cancel interaction for keyboard.");
}
- });
- if (internalInterface.get() != null){
- internalInterface.get().sendRPC(cancelInteraction);
} else {
- DebugTool.logError("Internal interface null - could not send cancel interaction for keyboard");
+ DebugTool.logInfo("Canceling a keyboard that has not yet been sent to Core.");
+ Thread.currentThread().interrupt();
}
}
@@ -242,6 +264,10 @@ class PresentKeyboardOperation extends AsynchronousOperation {
return pi;
}
+ public Integer getCancelID() {
+ return cancelID;
+ }
+
// LISTENERS
private void addListeners(){
@@ -249,6 +275,10 @@ class PresentKeyboardOperation extends AsynchronousOperation {
keyboardRPCListener = new OnRPCNotificationListener() {
@Override
public void onNotified(RPCNotification notification) {
+ if (Thread.currentThread().isInterrupted()) {
+ finishOperation();
+ return;
+ }
if (keyboardListener == null){
DebugTool.logError("Received Keyboard Input But Listener is null");