diff options
author | Bretty <brettywhite@users.noreply.github.com> | 2018-03-09 11:02:06 -0500 |
---|---|---|
committer | Joey Grover <joeygrover@gmail.com> | 2018-03-09 11:02:06 -0500 |
commit | 115942eb69d8d1490f7106bbe0f715e9bb3bc6c4 (patch) | |
tree | e2b6787a5b2b20d915125220f83c081997c36bf9 | |
parent | f1d8dbac21709f2b9332eefa1cc0f0bbab35cbf4 (diff) | |
download | sdl_android-115942eb69d8d1490f7106bbe0f715e9bb3bc6c4.tar.gz |
Feature/issue 606 send multiple RPCS (#685)
* initial commit multple RPC work
* added javadocs
* working sending async
* removed uneccessary call
* send multiple async
* updated method name for clarity
* remove code per bilal’s review
* new javadoc for method
* start of tests
* adding some tests
* adding one more assert / fix comments
* remove duplicate method / fixes
* addressed final issues
* fixed error override in tests
* removed unused lock object
* add onError callback
4 files changed, 289 insertions, 3 deletions
diff --git a/sdl_android/src/androidTest/java/com/smartdevicelink/test/proxy/SdlProxyBaseTests.java b/sdl_android/src/androidTest/java/com/smartdevicelink/test/proxy/SdlProxyBaseTests.java index fdc52f9b7..b50f6f48d 100644 --- a/sdl_android/src/androidTest/java/com/smartdevicelink/test/proxy/SdlProxyBaseTests.java +++ b/sdl_android/src/androidTest/java/com/smartdevicelink/test/proxy/SdlProxyBaseTests.java @@ -8,7 +8,10 @@ import android.util.Log; import com.smartdevicelink.exception.SdlException; import com.smartdevicelink.exception.SdlExceptionCause; +import com.smartdevicelink.proxy.RPCRequest; +import com.smartdevicelink.proxy.RPCResponse; import com.smartdevicelink.proxy.SdlProxyALM; +import com.smartdevicelink.proxy.SdlProxyBase; import com.smartdevicelink.proxy.SdlProxyBuilder; import com.smartdevicelink.proxy.SdlProxyConfigurationResources; import com.smartdevicelink.proxy.callbacks.OnServiceEnded; @@ -66,6 +69,7 @@ import com.smartdevicelink.proxy.rpc.SetDisplayLayoutResponse; import com.smartdevicelink.proxy.rpc.SetGlobalPropertiesResponse; import com.smartdevicelink.proxy.rpc.SetInteriorVehicleDataResponse; import com.smartdevicelink.proxy.rpc.SetMediaClockTimerResponse; +import com.smartdevicelink.proxy.rpc.Show; import com.smartdevicelink.proxy.rpc.ShowConstantTbtResponse; import com.smartdevicelink.proxy.rpc.ShowResponse; import com.smartdevicelink.proxy.rpc.SliderResponse; @@ -79,7 +83,9 @@ import com.smartdevicelink.proxy.rpc.UnsubscribeButtonResponse; import com.smartdevicelink.proxy.rpc.UnsubscribeVehicleDataResponse; import com.smartdevicelink.proxy.rpc.UnsubscribeWayPointsResponse; import com.smartdevicelink.proxy.rpc.UpdateTurnListResponse; +import com.smartdevicelink.proxy.rpc.enums.Result; import com.smartdevicelink.proxy.rpc.enums.SdlDisconnectedReason; +import com.smartdevicelink.proxy.rpc.listeners.OnMultipleRequestListener; import com.smartdevicelink.streaming.video.SdlRemoteDisplay; import com.smartdevicelink.streaming.video.VideoStreamingParameters; import com.smartdevicelink.test.streaming.video.SdlRemoteDisplayTest; @@ -87,6 +93,8 @@ import com.smartdevicelink.test.streaming.video.SdlRemoteDisplayTest; import junit.framework.Assert; import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; public class SdlProxyBaseTests extends AndroidTestCase{ @@ -162,6 +170,114 @@ public class SdlProxyBaseTests extends AndroidTestCase{ } } + public void testMultipleRPCSendSynchronous() { + + List<RPCRequest> rpcs = new ArrayList<>(); + + // rpc 1 + Show show = new Show(); + show.setMainField1("hey y'all"); + show.setMainField2(""); + show.setMainField3(""); + show.setMainField4(""); + rpcs.add(show); + + // rpc 2 + Show show2 = new Show(); + show2.setMainField1(""); + show2.setMainField2("It is Wednesday My Dudes"); + show2.setMainField3(""); + show2.setMainField4(""); + rpcs.add(show2); + + OnMultipleRequestListener mrl = new OnMultipleRequestListener() { + @Override + public void onUpdate(int remainingRequests) { + + } + + @Override + public void onFinished() { + + } + + @Override + public void onError(int correlationId, Result resultCode, String info) { + assert false; + } + + @Override + public void onResponse(int correlationId, RPCResponse response) { + + } + }; + try{ + // public void sendRequests(List<RPCRequest> rpcs, final OnMultipleRequestListener listener) throws SdlException { + Method m = SdlProxyBase.class.getDeclaredMethod("sendRequests", SdlProxyBase.class); + assertNotNull(m); + m.setAccessible(true); + m.invoke(rpcs,mrl); + assert true; + + }catch (Exception e){ + assert false; + } + } + + public void testMultipleRPCSendAsynchronous() { + + List<RPCRequest> rpcs = new ArrayList<>(); + + // rpc 1 + Show show = new Show(); + show.setMainField1("hey y'all"); + show.setMainField2(""); + show.setMainField3(""); + show.setMainField4(""); + rpcs.add(show); + + // rpc 2 + Show show2 = new Show(); + show2.setMainField1(""); + show2.setMainField2("It is Wednesday My Dudes"); + show2.setMainField3(""); + show2.setMainField4(""); + rpcs.add(show2); + + OnMultipleRequestListener mrl = new OnMultipleRequestListener() { + @Override + public void onUpdate(int remainingRequests) { + + } + + @Override + public void onFinished() { + + } + + @Override + public void onError(int correlationId, Result resultCode, String info) { + assert false; + } + + @Override + public void onResponse(int correlationId, RPCResponse response) { + + } + }; + try{ + // public void sendSequentialRequests(List<RPCRequest> rpcs, final OnMultipleRequestListener listener) throws SdlException { + Method m = SdlProxyBase.class.getDeclaredMethod("sendSequentialRequests", SdlProxyBase.class); + assertNotNull(m); + m.setAccessible(true); + m.invoke(rpcs,mrl); + assert true; + + }catch (Exception e){ + assert false; + } + } + public class ProxyListenerTest implements IProxyListenerALM { @Override diff --git a/sdl_android/src/main/java/com/smartdevicelink/proxy/SdlProxyBase.java b/sdl_android/src/main/java/com/smartdevicelink/proxy/SdlProxyBase.java index 67b3d15da..fffeb4525 100644 --- a/sdl_android/src/main/java/com/smartdevicelink/proxy/SdlProxyBase.java +++ b/sdl_android/src/main/java/com/smartdevicelink/proxy/SdlProxyBase.java @@ -93,6 +93,7 @@ import com.smartdevicelink.proxy.rpc.enums.SystemCapabilityType; import com.smartdevicelink.proxy.rpc.enums.TextAlignment;
import com.smartdevicelink.proxy.rpc.enums.TouchType;
import com.smartdevicelink.proxy.rpc.enums.UpdateMode;
+import com.smartdevicelink.proxy.rpc.listeners.OnMultipleRequestListener;
import com.smartdevicelink.proxy.rpc.listeners.OnPutFileUpdateListener;
import com.smartdevicelink.proxy.rpc.listeners.OnRPCNotificationListener;
import com.smartdevicelink.proxy.rpc.listeners.OnRPCResponseListener;
@@ -108,6 +109,7 @@ import com.smartdevicelink.trace.enums.InterfaceActivityDirection; import com.smartdevicelink.transport.BaseTransportConfig;
import com.smartdevicelink.transport.SiphonServer;
import com.smartdevicelink.transport.enums.TransportType;
+import com.smartdevicelink.util.CorrelationIdGenerator;
import com.smartdevicelink.util.DebugTool;
@@ -130,7 +132,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> UNREGISTER_APP_INTERFACE_CORRELATION_ID = 65530,
POLICIES_CORRELATION_ID = 65535;
- // Sdlhronization Objects
+ // Sdl Synchronization Objects
private static final Object CONNECTION_REFERENCE_LOCK = new Object(),
INCOMING_MESSAGE_QUEUE_THREAD_LOCK = new Object(),
OUTGOING_MESSAGE_QUEUE_THREAD_LOCK = new Object(),
@@ -3425,12 +3427,124 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> SdlTrace.logProxyEvent("Proxy received RPC Message: " + functionName, SDL_LIB_TRACE_KEY);
}
+
+ /**
+ * Takes a list of RPCRequests and sends it to SDL in a synchronous fashion. Responses are captured through callback on OnMultipleRequestListener.
+ * For sending requests asynchronously, use sendRequests <br>
+ *
+ * <strong>NOTE: This will override any listeners on individual RPCs</strong>
+ *
+ * @param rpcs is the list of RPCRequests being sent
+ * @param listener listener for updates and completions
+ * @throws SdlException if an unrecoverable error is encountered
+ */
+ @SuppressWarnings("unused")
+ public void sendSequentialRequests(final List<RPCRequest> rpcs, final OnMultipleRequestListener listener) throws SdlException {
+ if (_proxyDisposed) {
+ throw new SdlException("This object has been disposed, it is no long capable of executing methods.", SdlExceptionCause.SDL_PROXY_DISPOSED);
+ }
+
+ SdlTrace.logProxyEvent("Application called sendSequentialRequests", SDL_LIB_TRACE_KEY);
+
+ synchronized(CONNECTION_REFERENCE_LOCK) {
+ if (!getIsConnected()) {
+ SdlTrace.logProxyEvent("Application attempted to call sendSequentialRequests without a connected transport.", SDL_LIB_TRACE_KEY);
+ throw new SdlException("There is no valid connection to SDL. sendSequentialRequests cannot be called until SDL has been connected.", SdlExceptionCause.SDL_UNAVAILABLE);
+ }
+ }
+
+ if (rpcs == null){
+ //Log error here
+ throw new SdlException("You must send some RPCs", SdlExceptionCause.INVALID_ARGUMENT);
+ }
+
+ int requestCount = rpcs.size();
+
+ // Break out of recursion, we have finished the requests
+ if (requestCount == 0) {
+ listener.onFinished();
+ return;
+ }
+
+ RPCRequest rpc = rpcs.remove(0);
+ rpc.setCorrelationID(CorrelationIdGenerator.generateId());
+
+ rpc.setOnRPCResponseListener(new OnRPCResponseListener() {
+ @Override
+ public void onResponse(int correlationId, RPCResponse response) {
+ if (response.getSuccess()) {
+ // success
+ listener.onUpdate(rpcs.size());
+ try {
+ // recurse after successful response of RPC
+ sendSequentialRequests(rpcs, listener);
+ } catch (SdlException e) {
+ e.printStackTrace();
+ listener.onError(correlationId, Result.GENERIC_ERROR, e.toString());
+ }
+ }
+ }
+
+ @Override
+ public void onError(int correlationId, Result resultCode, String info){
+ listener.onError(correlationId, resultCode, info);
+ }
+ });
+
+ sendRPCRequestPrivate(rpc);
+ }
+
+ /**
+ * Takes a list of RPCRequests and sends it to SDL. Responses are captured through callback on OnMultipleRequestListener.
+ * For sending requests synchronously, use sendSequentialRequests <br>
+ *
+ * <strong>NOTE: This will override any listeners on individual RPCs</strong>
+ *
+ * @param rpcs is the list of RPCRequests being sent
+ * @param listener listener for updates and completions
+ * @throws SdlException if an unrecoverable error is encountered
+ */
+ @SuppressWarnings("unused")
+ public void sendRequests(List<RPCRequest> rpcs, final OnMultipleRequestListener listener) throws SdlException {
+
+ if (_proxyDisposed) {
+ throw new SdlException("This object has been disposed, it is no long capable of executing methods.", SdlExceptionCause.SDL_PROXY_DISPOSED);
+ }
+
+ SdlTrace.logProxyEvent("Application called sendRequests", SDL_LIB_TRACE_KEY);
+
+ synchronized(CONNECTION_REFERENCE_LOCK) {
+ if (!getIsConnected()) {
+ SdlTrace.logProxyEvent("Application attempted to call sendRequests without a connected transport.", SDL_LIB_TRACE_KEY);
+ throw new SdlException("There is no valid connection to SDL. sendRequests cannot be called until SDL has been connected.", SdlExceptionCause.SDL_UNAVAILABLE);
+ }
+ }
+
+ if (rpcs == null){
+ //Log error here
+ throw new SdlException("You must send some RPCs, the array is null", SdlExceptionCause.INVALID_ARGUMENT);
+ }
+
+ int arraySize = rpcs.size();
+
+ if (arraySize == 0) {
+ throw new SdlException("You must send some RPCs, the array is empty", SdlExceptionCause.INVALID_ARGUMENT);
+ }
+
+ for (int i = 0; i < arraySize; i++) {
+ RPCRequest rpc = rpcs.get(i);
+ rpc.setCorrelationID(CorrelationIdGenerator.generateId());
+ listener.addCorrelationId(rpc.getCorrelationID());
+ rpc.setOnRPCResponseListener(listener.getSingleRpcResponseListener());
+ sendRPCRequestPrivate(rpc);
+ }
+ }
/**
* Takes an RPCRequest and sends it to SDL. Responses are captured through callback on IProxyListener.
*
* @param request is the RPCRequest being sent
- * @throws SdlException if an unrecoverable error is encountered if an unrecoverable error is encountered
+ * @throws SdlException if an unrecoverable error is encountered
*/
public void sendRPCRequest(RPCRequest request) throws SdlException {
if (_proxyDisposed) {
@@ -3474,7 +3588,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> SdlTrace.logProxyEvent("Application attempted to send a RegisterAppInterface or UnregisterAppInterface while using ALM.", SDL_LIB_TRACE_KEY);
throw new SdlException("The RPCRequest, " + request.getFunctionName() +
- ", is unallowed using the Advanced Lifecycle Management Model.", SdlExceptionCause.INCORRECT_LIFECYCLE_MODEL);
+ ", is un-allowed using the Advanced Lifecycle Management Model.", SdlExceptionCause.INCORRECT_LIFECYCLE_MODEL);
}
}
diff --git a/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/listeners/OnMultipleRequestListener.java b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/listeners/OnMultipleRequestListener.java new file mode 100644 index 000000000..107de1bf9 --- /dev/null +++ b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/listeners/OnMultipleRequestListener.java @@ -0,0 +1,52 @@ +package com.smartdevicelink.proxy.rpc.listeners; + +import android.util.Log; + +import com.smartdevicelink.proxy.RPCResponse; +import com.smartdevicelink.proxy.rpc.enums.Result; + +import org.json.JSONException; + +import java.util.Vector; + +/** + * This is the listener for sending Multiple RPCs. + */ +public abstract class OnMultipleRequestListener extends OnRPCResponseListener { + + final Vector<Integer> correlationIds; + OnRPCResponseListener rpcResponseListener; + private static String TAG = "OnMultipleRequestListener"; + + public OnMultipleRequestListener(){ + setListenerType(UPDATE_LISTENER_TYPE_MULTIPLE_REQUESTS); + correlationIds = new Vector<>(); + + rpcResponseListener = new OnRPCResponseListener() { + @Override + public void onResponse(int correlationId, RPCResponse response) { + correlationIds.remove(Integer.valueOf(correlationId)); + if(correlationIds.size()>0){ + onUpdate(correlationIds.size()); + }else{ + onFinished(); + } + } + }; + } + + public void addCorrelationId(int correlationid){ + correlationIds.add(correlationid); + } + /** + * onUpdate is called during multiple stream request + * @param remainingRequests of the original request + */ + public abstract void onUpdate(int remainingRequests); + public abstract void onFinished(); + public abstract void onError(int correlationId, Result resultCode, String info); + + public OnRPCResponseListener getSingleRpcResponseListener(){ + return rpcResponseListener; + } +}
\ No newline at end of file diff --git a/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/listeners/OnRPCResponseListener.java b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/listeners/OnRPCResponseListener.java index 4bc5ccd79..c21244926 100644 --- a/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/listeners/OnRPCResponseListener.java +++ b/sdl_android/src/main/java/com/smartdevicelink/proxy/rpc/listeners/OnRPCResponseListener.java @@ -12,6 +12,10 @@ public abstract class OnRPCResponseListener { * Listener type specific to putfile */ public final static int UPDATE_LISTENER_TYPE_PUT_FILE = 1; + /** + * Listener type specific to sendRequests and sendSequentialRequests + */ + public final static int UPDATE_LISTENER_TYPE_MULTIPLE_REQUESTS = 2; /** * Stores what type of listener this instance is. This prevents of from having to use reflection |