summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoey Grover <joeygrover@gmail.com>2016-06-14 15:22:10 -0400
committerJoey Grover <joeygrover@gmail.com>2016-06-14 15:22:10 -0400
commit2e04d62daf206096dcedd29e939f6d97af58688c (patch)
tree8fc07a203bd844b52280aae45980c63b78dae818
parent10148bc0796b523120edbc497d5feadf34490cc5 (diff)
parent98ae50dba3d8dd4db923e7dc0d812e9d40b2fc3f (diff)
downloadsdl_android-2e04d62daf206096dcedd29e939f6d97af58688c.tar.gz
Merge branch 'develop' of https://github.com/smartdevicelink/sdl_android into feature/aoa_improvements
# Conflicts: # HelloSdl/src/com/hellosdl/sdl/SdlService.java
-rw-r--r--HelloSdl/src/com/hellosdl/MainActivity.java1
-rw-r--r--HelloSdl/src/com/hellosdl/sdl/SdlReceiver.java3
-rw-r--r--HelloSdl/src/com/hellosdl/sdl/SdlService.java12
-rw-r--r--sdl_android_lib/AndroidManifest.xml2
-rw-r--r--sdl_android_lib/src/com/smartdevicelink/SdlConnection/ISdlConnectionListener.java2
-rw-r--r--sdl_android_lib/src/com/smartdevicelink/SdlConnection/SdlConnection.java25
-rw-r--r--sdl_android_lib/src/com/smartdevicelink/SdlConnection/SdlSession.java15
-rw-r--r--sdl_android_lib/src/com/smartdevicelink/protocol/AbstractProtocol.java8
-rw-r--r--sdl_android_lib/src/com/smartdevicelink/protocol/IProtocolListener.java2
-rw-r--r--sdl_android_lib/src/com/smartdevicelink/protocol/SdlPacketFactory.java10
-rw-r--r--sdl_android_lib/src/com/smartdevicelink/protocol/WiProProtocol.java32
-rw-r--r--sdl_android_lib/src/com/smartdevicelink/proxy/RPCMessage.java2
-rw-r--r--sdl_android_lib/src/com/smartdevicelink/proxy/SdlProxyBase.java12
-rw-r--r--sdl_android_lib/src/com/smartdevicelink/proxy/rpc/enums/SdlDisconnectedReason.java4
-rw-r--r--sdl_android_lib/src/com/smartdevicelink/transport/BTTransport.java1
-rw-r--r--sdl_android_lib/src/com/smartdevicelink/transport/MultiplexBluetoothTransport.java11
-rw-r--r--sdl_android_lib/src/com/smartdevicelink/transport/RouterServiceValidator.java53
-rw-r--r--sdl_android_lib/src/com/smartdevicelink/transport/SdlBroadcastReceiver.java11
-rw-r--r--sdl_android_lib/src/com/smartdevicelink/transport/SdlPsm.java4
-rw-r--r--sdl_android_lib/src/com/smartdevicelink/transport/SdlRouterService.java343
-rw-r--r--sdl_android_lib/src/com/smartdevicelink/transport/TransportBroker.java16
-rw-r--r--sdl_android_lib/src/com/smartdevicelink/transport/TransportConstants.java3
-rw-r--r--sdl_android_lib/src/com/smartdevicelink/util/HttpRequestTask.java6
23 files changed, 450 insertions, 128 deletions
diff --git a/HelloSdl/src/com/hellosdl/MainActivity.java b/HelloSdl/src/com/hellosdl/MainActivity.java
index a12123cc8..da6b8ecaf 100644
--- a/HelloSdl/src/com/hellosdl/MainActivity.java
+++ b/HelloSdl/src/com/hellosdl/MainActivity.java
@@ -17,7 +17,6 @@ public class MainActivity extends Activity {
setContentView(R.layout.activity_main);
if(SdlReceiver.isTransportConnected(getBaseContext())){
Intent startIntent = new Intent(getBaseContext(), SdlService.class);
- startIntent.putExtra(SdlReceiver.FORCE_TRANSPORT_CONNECTED, true);
startService(startIntent);
}
}
diff --git a/HelloSdl/src/com/hellosdl/sdl/SdlReceiver.java b/HelloSdl/src/com/hellosdl/sdl/SdlReceiver.java
index e907c8a94..2162516f5 100644
--- a/HelloSdl/src/com/hellosdl/sdl/SdlReceiver.java
+++ b/HelloSdl/src/com/hellosdl/sdl/SdlReceiver.java
@@ -21,7 +21,4 @@ public class SdlReceiver extends com.smartdevicelink.transport.SdlBroadcastRecei
intent.setClass(context, SdlService.class);
context.startService(intent);
}
-
-
-
}
diff --git a/HelloSdl/src/com/hellosdl/sdl/SdlService.java b/HelloSdl/src/com/hellosdl/sdl/SdlService.java
index 641aded59..7acda932c 100644
--- a/HelloSdl/src/com/hellosdl/sdl/SdlService.java
+++ b/HelloSdl/src/com/hellosdl/sdl/SdlService.java
@@ -81,6 +81,7 @@ import com.smartdevicelink.transport.BaseTransportConfig;
import com.smartdevicelink.transport.MultiplexTransportConfig;
import com.smartdevicelink.transport.SdlBroadcastReceiver;
import com.smartdevicelink.transport.USBTransportConfig;
+import com.smartdevicelink.transport.TransportConstants;
/**
* While this class is just an extension off the base Android Service class, we hope in the future we can offer something
@@ -116,11 +117,20 @@ public class SdlService extends Service implements IProxyListenerALM{
}
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ startProxy(null);
+ }
+
+
+
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(proxy == null){
startProxy(intent);
- }else if (intent != null && intent.hasExtra(SdlBroadcastReceiver.FORCE_TRANSPORT_CONNECTED)){
+ }else if (intent != null && intent.hasExtra(TransportConstants.FORCE_TRANSPORT_CONNECTED)){
proxy.forceOnConnected();
}
return START_STICKY;
diff --git a/sdl_android_lib/AndroidManifest.xml b/sdl_android_lib/AndroidManifest.xml
index 190e6d678..e6c874696 100644
--- a/sdl_android_lib/AndroidManifest.xml
+++ b/sdl_android_lib/AndroidManifest.xml
@@ -1,5 +1,5 @@
<manifest package="com.smartdevicelink" xmlns:android="http://schemas.android.com/apk/res/android">
- <uses-sdk android:minSdkVersion="8"/>
+ <uses-sdk android:minSdkVersion="11"/>
<!-- Required to use the USB Accessory mode -->
<uses-feature android:name="android.hardware.usb.accessory"/>
<application android:debuggable="true"/>
diff --git a/sdl_android_lib/src/com/smartdevicelink/SdlConnection/ISdlConnectionListener.java b/sdl_android_lib/src/com/smartdevicelink/SdlConnection/ISdlConnectionListener.java
index 57fb15e50..2f9eff800 100644
--- a/sdl_android_lib/src/com/smartdevicelink/SdlConnection/ISdlConnectionListener.java
+++ b/sdl_android_lib/src/com/smartdevicelink/SdlConnection/ISdlConnectionListener.java
@@ -15,7 +15,7 @@ public interface ISdlConnectionListener {
byte sessionID, byte version, String correlationID);
public void onProtocolSessionStarted(SessionType sessionType,
- byte sessionID, byte version, String correlationID);
+ byte sessionID, byte version, String correlationID, int hashID);
public void onProtocolSessionEnded(SessionType sessionType,
byte sessionID, String correlationID);
diff --git a/sdl_android_lib/src/com/smartdevicelink/SdlConnection/SdlConnection.java b/sdl_android_lib/src/com/smartdevicelink/SdlConnection/SdlConnection.java
index f99ae19b6..60d6e5362 100644
--- a/sdl_android_lib/src/com/smartdevicelink/SdlConnection/SdlConnection.java
+++ b/sdl_android_lib/src/com/smartdevicelink/SdlConnection/SdlConnection.java
@@ -115,9 +115,9 @@ public class SdlConnection implements IProtocolListener, ITransportListener, ISt
_transport = new MultiplexTransport((MultiplexTransportConfig)transportConfig,this);
}else if(isLegacyModeEnabled() && legacyTransportRequest == TransportType.BLUETOOTH){
Log.d(TAG, "Creating legacy bluetooth connection");
- _transport = new BTTransport(this, true); //TODO make sure blindly sending true is ok
+ _transport = new BTTransport(this, true);
}else if(transportConfig.getTransportType() == TransportType.BLUETOOTH){
- _transport = new BTTransport(this,((BTTransportConfig)transportConfig).getKeepSocketActive()); //FIXME we should chage this over to a special legacy config
+ _transport = new BTTransport(this,((BTTransportConfig)transportConfig).getKeepSocketActive());
}
else if (transportConfig.getTransportType() == TransportType.TCP)
{
@@ -145,13 +145,13 @@ public class SdlConnection implements IProtocolListener, ITransportListener, ISt
- private void closeConnection(boolean willRecycle, byte rpcSessionID) {
+ private void closeConnection(boolean willRecycle, byte rpcSessionID, int sessionHashId) {
synchronized(PROTOCOL_REFERENCE_LOCK) {
if (_protocol != null) {
// If transport is still connected, sent EndProtocolSessionMessage
if (_transport != null && _transport.getIsConnected()) {
- _protocol.EndProtocolSession(SessionType.RPC, rpcSessionID);
+ _protocol.EndProtocolSession(SessionType.RPC, rpcSessionID, sessionHashId);
}
if (willRecycle) {
_protocol = null;
@@ -261,8 +261,8 @@ public class SdlConnection implements IProtocolListener, ITransportListener, ISt
@Override
public void onProtocolSessionStarted(SessionType sessionType,
- byte sessionID, byte version, String correlationID) {
- _connectionListener.onProtocolSessionStarted(sessionType, sessionID, version, correlationID);
+ byte sessionID, byte version, String correlationID, int hashID) {
+ _connectionListener.onProtocolSessionStarted(sessionType, sessionID, version, correlationID, hashID);
}
@Override
@@ -494,7 +494,7 @@ public class SdlConnection implements IProtocolListener, ITransportListener, ISt
public void endService (SessionType sessionType, byte sessionID) {
synchronized(PROTOCOL_REFERENCE_LOCK){
if(_protocol != null){
- _protocol.EndProtocolSession(sessionType, sessionID);
+ _protocol.EndProtocolService(sessionType, sessionID);
}
}
}
@@ -519,8 +519,8 @@ public class SdlConnection implements IProtocolListener, ITransportListener, ISt
boolean didRemove = listenerList.remove(registerListener);
if(didRemove && _transport !=null && _transport.getTransportType()== TransportType.MULTIPLEX){ //If we're connected we can request the extra session now
((MultiplexTransport)_transport).removeSession(registerListener.getSessionId());
- }
- closeConnection(listenerList.size() == 0, registerListener.getSessionId());
+ }
+ closeConnection(listenerList.size() == 0, registerListener.getSessionId(), registerListener.getSessionHashId());
}
@@ -594,17 +594,17 @@ public class SdlConnection implements IProtocolListener, ITransportListener, ISt
@Override
public void onProtocolSessionStarted(SessionType sessionType,
- byte sessionID, byte version, String correlationID) {
+ byte sessionID, byte version, String correlationID, int hashID) {
for (SdlSession session : listenerList) {
if (session.getSessionId() == 0) {
- session.onProtocolSessionStarted(sessionType, sessionID, version, correlationID);
+ session.onProtocolSessionStarted(sessionType, sessionID, version, correlationID, hashID);
break;
}
}
if (sessionType.equals(SessionType.NAV) || sessionType.equals(SessionType.PCM)){
SdlSession session = findSessionById(sessionID);
if (session != null) {
- session.onProtocolSessionStarted(sessionType, sessionID, version, correlationID);
+ session.onProtocolSessionStarted(sessionType, sessionID, version, correlationID, hashID);
}
}
}
@@ -733,7 +733,6 @@ public class SdlConnection implements IProtocolListener, ITransportListener, ISt
MultiplexTransportConfig config = multi.getConfig();
ComponentName tempCompName = SdlBroadcastReceiver.consumeQueuedRouterService();
//Log.d(TAG, "Consumed component name: " +tempCompName );
- //TODO check to see what component name connected and comapre it to what we are connected to
if(config.getService().equals(tempCompName)){ //If this is the same service that just connected that we are already looking at. Attempt to reconnect
boolean forced = multi.forceHardwareConnectEvent(TransportType.BLUETOOTH);
diff --git a/sdl_android_lib/src/com/smartdevicelink/SdlConnection/SdlSession.java b/sdl_android_lib/src/com/smartdevicelink/SdlConnection/SdlSession.java
index d4e9212ba..7f1359963 100644
--- a/sdl_android_lib/src/com/smartdevicelink/SdlConnection/SdlSession.java
+++ b/sdl_android_lib/src/com/smartdevicelink/SdlConnection/SdlSession.java
@@ -27,6 +27,7 @@ public class SdlSession implements ISdlConnectionListener, IHeartbeatMonitorList
IHeartbeatMonitor _incomingHeartbeatMonitor = null;
private static final String TAG = "SdlSession";
private LockScreenManager lockScreenMan = new LockScreenManager();
+ private int sessionHashId = 0;
@@ -70,7 +71,10 @@ public class SdlSession implements ISdlConnectionListener, IHeartbeatMonitorList
_incomingHeartbeatMonitor.setListener(this);
}
-
+ public int getSessionHashId() {
+ return this.sessionHashId;
+ }
+
public byte getSessionId() {
return this.sessionId;
}
@@ -174,12 +178,15 @@ public class SdlSession implements ISdlConnectionListener, IHeartbeatMonitorList
@Override
public void onProtocolSessionStarted(SessionType sessionType,
- byte sessionID, byte version, String correlationID) {
+ byte sessionID, byte version, String correlationID, int hashID) {
this.sessionId = sessionID;
lockScreenMan.setSessionID(sessionID);
- this.sessionListener.onProtocolSessionStarted(sessionType, sessionID, version, correlationID);Log.d(TAG, "session - on pro start");
+ this.sessionListener.onProtocolSessionStarted(sessionType, sessionID, version, correlationID, hashID);
//if (version == 3)
- initialiseSession();Log.d(TAG, "inited");
+ initialiseSession();
+ if (sessionType.eq(SessionType.RPC)){
+ sessionHashId = hashID;
+ }
}
@Override
diff --git a/sdl_android_lib/src/com/smartdevicelink/protocol/AbstractProtocol.java b/sdl_android_lib/src/com/smartdevicelink/protocol/AbstractProtocol.java
index 4db9383f1..bcc2e1df5 100644
--- a/sdl_android_lib/src/com/smartdevicelink/protocol/AbstractProtocol.java
+++ b/sdl_android_lib/src/com/smartdevicelink/protocol/AbstractProtocol.java
@@ -45,7 +45,9 @@ public abstract class AbstractProtocol {
// This method ends a protocol session. A corresponding call to the protocol
// listener onProtocolSessionEnded() method will be made when the protocol
// session has ended.
- public abstract void EndProtocolSession(SessionType sessionType, byte sessionID);
+ public abstract void EndProtocolSession(SessionType sessionType, byte sessionID, int hashID);
+
+ public abstract void EndProtocolService(SessionType serviceType, byte sessionID);
// TODO REMOVE
// This method sets the interval at which heartbeat protocol messages will be
// sent to SDL.
@@ -122,8 +124,8 @@ public abstract class AbstractProtocol {
// This method handles the startup of a protocol session. A callback is sent
// to the protocol listener.
protected void handleProtocolSessionStarted(SessionType sessionType,
- byte sessionID, byte version, String correlationID) {
- _protocolListener.onProtocolSessionStarted(sessionType, sessionID, version, correlationID);
+ byte sessionID, byte version, String correlationID, int hashID) {
+ _protocolListener.onProtocolSessionStarted(sessionType, sessionID, version, correlationID, hashID);
}
protected void handleProtocolSessionNACKed(SessionType sessionType,
diff --git a/sdl_android_lib/src/com/smartdevicelink/protocol/IProtocolListener.java b/sdl_android_lib/src/com/smartdevicelink/protocol/IProtocolListener.java
index 0e3ff6842..47317a086 100644
--- a/sdl_android_lib/src/com/smartdevicelink/protocol/IProtocolListener.java
+++ b/sdl_android_lib/src/com/smartdevicelink/protocol/IProtocolListener.java
@@ -12,7 +12,7 @@ public interface IProtocolListener {
void onProtocolMessageReceived(ProtocolMessage msg);
// Called to indicate that a protocol session has been started (from either side)
- void onProtocolSessionStarted(SessionType sessionType, byte sessionID, byte version, String correlationID);
+ void onProtocolSessionStarted(SessionType sessionType, byte sessionID, byte version, String correlationID, int hashID);
void onProtocolSessionNACKed(SessionType sessionType, byte sessionID, byte version, String correlationID);
diff --git a/sdl_android_lib/src/com/smartdevicelink/protocol/SdlPacketFactory.java b/sdl_android_lib/src/com/smartdevicelink/protocol/SdlPacketFactory.java
index 3d3452715..1fff2b1a2 100644
--- a/sdl_android_lib/src/com/smartdevicelink/protocol/SdlPacketFactory.java
+++ b/sdl_android_lib/src/com/smartdevicelink/protocol/SdlPacketFactory.java
@@ -1,7 +1,5 @@
package com.smartdevicelink.protocol;
-import android.util.Log;
-
import com.smartdevicelink.protocol.enums.FrameDataControlFrameType;
import com.smartdevicelink.protocol.enums.SessionType;
@@ -24,14 +22,14 @@ public class SdlPacketFactory {
return new SdlPacket(version,false,SdlPacket.FRAME_TYPE_CONTROL,
serviceType.getValue(),FrameDataControlFrameType.Heartbeat.value(),sessionID,
- 0,0,null); //TODO check that 0 works for message Id. I can't find where it gets set otherwise
+ 0,0,null);
}
public static SdlPacket createHeartbeatACK(SessionType serviceType, byte sessionID, byte version) {
return new SdlPacket(version,false,SdlPacket.FRAME_TYPE_CONTROL,
serviceType.getValue(),FrameDataControlFrameType.HeartbeatACK.value(),sessionID,
- 0,0,null); //TODO check that 0 works for message Id. I can't find where it gets set otherwise
+ 0,0,null);
}
public static SdlPacket createStartSessionACK(SessionType serviceType, byte sessionID, int messageID, byte version) {
@@ -49,10 +47,10 @@ public class SdlPacketFactory {
0,messageID,null);
}
- public static SdlPacket createEndSession(SessionType serviceType, byte sessionID, int messageID, byte version) {
+ public static SdlPacket createEndSession(SessionType serviceType, byte sessionID, int messageID, byte version, byte[] payload) {
return new SdlPacket(version,false,SdlPacket.FRAME_TYPE_CONTROL,
serviceType.getValue(),SdlPacket.FRAME_INFO_END_SERVICE,sessionID,
- 0,messageID,null);
+ payload.length,messageID,payload);
}
public static SdlPacket createSingleSendData(SessionType serviceType, byte sessionID,
diff --git a/sdl_android_lib/src/com/smartdevicelink/protocol/WiProProtocol.java b/sdl_android_lib/src/com/smartdevicelink/protocol/WiProProtocol.java
index 6913c160b..284f04574 100644
--- a/sdl_android_lib/src/com/smartdevicelink/protocol/WiProProtocol.java
+++ b/sdl_android_lib/src/com/smartdevicelink/protocol/WiProProtocol.java
@@ -3,8 +3,6 @@ package com.smartdevicelink.protocol;
import java.io.ByteArrayOutputStream;
import java.util.Hashtable;
-import android.util.Log;
-
import com.smartdevicelink.exception.*;
import com.smartdevicelink.protocol.enums.*;
import com.smartdevicelink.util.BitConverter;
@@ -78,9 +76,10 @@ public class WiProProtocol extends AbstractProtocol {
handlePacketToSend(header);
} // end-method
- public void EndProtocolSession(SessionType sessionType, byte sessionID) {
- SdlPacket header = SdlPacketFactory.createEndSession(sessionType, sessionID, hashID, _version);
+ public void EndProtocolSession(SessionType sessionType, byte sessionID, int hashId) {
+ SdlPacket header = SdlPacketFactory.createEndSession(sessionType, sessionID, hashID, _version, BitConverter.intToByteArray(hashId));
handlePacketToSend(header);
+
} // end-method
public void SendMessage(ProtocolMessage protocolMsg) {
@@ -303,24 +302,22 @@ public class WiProProtocol extends AbstractProtocol {
messageLock = new Object();
_messageLocks.put((byte)packet.getSessionId(), messageLock);
}
- //hashID = BitConverter.intFromByteArray(data, 0);
+ int hashID = 0;
if (_version > 1){
- hashID = packet.getMessageId();
- }
- handleProtocolSessionStarted(serviceType,(byte) packet.getSessionId(), _version, "");
+ if (packet.payload!= null && packet.dataSize == 4){ //hashid will be 4 bytes in length
+ hashID = BitConverter.intFromByteArray(packet.payload, 0);
+ }
+ }
+ handleProtocolSessionStarted(serviceType,(byte) packet.getSessionId(), _version, "", hashID);
} else if (frameInfo == FrameDataControlFrameType.StartSessionNACK.getValue()) {
if (serviceType.eq(SessionType.NAV) || serviceType.eq(SessionType.PCM)) {
handleProtocolSessionNACKed(serviceType, (byte)packet.getSessionId(), _version, "");
-
} else {
handleProtocolError("Got StartSessionNACK for protocol sessionID=" + packet.getSessionId(), null);
}
} else if (frameInfo == FrameDataControlFrameType.EndSession.getValue()) {
- //if (hashID == BitConverter.intFromByteArray(data, 0))
if (_version > 1) {
- if (hashID == packet.getMessageId()){
- handleProtocolSessionEnded(serviceType, (byte)packet.getSessionId(), "");
- }//else...nothing
+ handleProtocolSessionEnded(serviceType, (byte)packet.getSessionId(), "");
} else {
handleProtocolSessionEnded(serviceType, (byte)packet.getSessionId(), "");
}
@@ -329,7 +326,7 @@ public class WiProProtocol extends AbstractProtocol {
} else if (frameInfo == FrameDataControlFrameType.EndSessionNACK.getValue()) {
handleProtocolSessionEndedNACK(serviceType, (byte)packet.getSessionId(), "");
} else if (frameInfo == FrameDataControlFrameType.ServiceDataACK.getValue()) {
- handleProtocolServiceDataACK(serviceType, (byte)packet.getSessionId ());
+ handleProtocolServiceDataACK(serviceType, (byte)packet.getSessionId ());
}
} // end-method
@@ -403,4 +400,11 @@ public class WiProProtocol extends AbstractProtocol {
final SdlPacket heartbeat = SdlPacketFactory.createHeartbeatACK(SessionType.CONTROL, sessionID, _version);
handlePacketToSend(heartbeat);
}
+
+ @Override
+ public void EndProtocolService(SessionType serviceType, byte sessionID) {
+ SdlPacket header = SdlPacketFactory.createEndSession(serviceType, sessionID, hashID, _version, new byte[4]);
+ handlePacketToSend(header);
+
+ }
} // end-class \ No newline at end of file
diff --git a/sdl_android_lib/src/com/smartdevicelink/proxy/RPCMessage.java b/sdl_android_lib/src/com/smartdevicelink/proxy/RPCMessage.java
index 8d3794075..dc2d44ee1 100644
--- a/sdl_android_lib/src/com/smartdevicelink/proxy/RPCMessage.java
+++ b/sdl_android_lib/src/com/smartdevicelink/proxy/RPCMessage.java
@@ -2,8 +2,6 @@ package com.smartdevicelink.proxy;
import java.util.Hashtable;
-import com.smartdevicelink.proxy.rpc.listeners.OnRPCResponseListener;
-
public class RPCMessage extends RPCStruct {
public static final String KEY_REQUEST = "request";
diff --git a/sdl_android_lib/src/com/smartdevicelink/proxy/SdlProxyBase.java b/sdl_android_lib/src/com/smartdevicelink/proxy/SdlProxyBase.java
index b029e5d6f..470cb6a14 100644
--- a/sdl_android_lib/src/com/smartdevicelink/proxy/SdlProxyBase.java
+++ b/sdl_android_lib/src/com/smartdevicelink/proxy/SdlProxyBase.java
@@ -295,7 +295,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase>
@Override
public void onProtocolSessionStarted(SessionType sessionType,
- byte sessionID, byte version, String correlationID) {
+ byte sessionID, byte version, String correlationID, int hashID) {
Intent sendIntent = createBroadcastIntent();
updateBroadcastIntent(sendIntent, "FUNCTION_NAME", "onProtocolSessionStarted");
@@ -323,7 +323,9 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase>
NavServiceStarted();
} else if (sessionType.eq(SessionType.PCM)) {
AudioServiceStarted();
- }
+ } else if (sessionType.eq(SessionType.RPC)){
+ cycleProxy(SdlDisconnectedReason.RPC_SESSION_ENDED);
+ }
else if (_wiproVersion > 1) {
//If version is 2 or above then don't need to specify a Session Type
startRPCProtocolSession(sessionID, correlationID);
@@ -1613,8 +1615,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase>
throw new SdlException("CorrelationID cannot be null. RPC: " + request.getFunctionName(), SdlExceptionCause.INVALID_ARGUMENT);
}
pm.setCorrID(request.getCorrelationID());
- if (request.getBulkData() != null)
+ if (request.getBulkData() != null){
pm.setBulkData(request.getBulkData());
+ }
+ if(request.getFunctionName().equalsIgnoreCase(FunctionID.PUT_FILE.name())){
+ pm.setPriorityCoefficient(1);
+ }
// Queue this outgoing message
synchronized(OUTGOING_MESSAGE_QUEUE_THREAD_LOCK) {
diff --git a/sdl_android_lib/src/com/smartdevicelink/proxy/rpc/enums/SdlDisconnectedReason.java b/sdl_android_lib/src/com/smartdevicelink/proxy/rpc/enums/SdlDisconnectedReason.java
index d1e69f744..0d1902e3a 100644
--- a/sdl_android_lib/src/com/smartdevicelink/proxy/rpc/enums/SdlDisconnectedReason.java
+++ b/sdl_android_lib/src/com/smartdevicelink/proxy/rpc/enums/SdlDisconnectedReason.java
@@ -24,8 +24,10 @@ public enum SdlDisconnectedReason {
/**
* This only occurs when multiplexing is running and it is found to be on an old gen 1 system.
*/
- LEGACY_BLUETOOTH_MODE_ENABLED
+ LEGACY_BLUETOOTH_MODE_ENABLED,
+ RPC_SESSION_ENDED
;
+
public static SdlDisconnectedReason valueForString(String value) {
try{
diff --git a/sdl_android_lib/src/com/smartdevicelink/transport/BTTransport.java b/sdl_android_lib/src/com/smartdevicelink/transport/BTTransport.java
index 3a1ecdd13..e41c501e5 100644
--- a/sdl_android_lib/src/com/smartdevicelink/transport/BTTransport.java
+++ b/sdl_android_lib/src/com/smartdevicelink/transport/BTTransport.java
@@ -11,7 +11,6 @@ import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.os.Build.VERSION;
-import android.util.Log;
import com.smartdevicelink.SdlConnection.SdlConnection;
import com.smartdevicelink.exception.SdlException;
diff --git a/sdl_android_lib/src/com/smartdevicelink/transport/MultiplexBluetoothTransport.java b/sdl_android_lib/src/com/smartdevicelink/transport/MultiplexBluetoothTransport.java
index dba4bdc1c..08fe98586 100644
--- a/sdl_android_lib/src/com/smartdevicelink/transport/MultiplexBluetoothTransport.java
+++ b/sdl_android_lib/src/com/smartdevicelink/transport/MultiplexBluetoothTransport.java
@@ -519,13 +519,7 @@ public class MultiplexBluetoothTransport {
// This is a blocking call and will only return on a
// successful connection or an exception
mBluetoothLevel = SdlRouterService.getBluetoothPrefs(SHARED_PREFS);
- long waitTime = 0;
- if(mmDevice.getName().toLowerCase().contains("fireplug")){
- waitTime = 500;
- }
- else{
- waitTime = 3000;
- }
+ long waitTime = 3000;
try {
Thread.sleep(waitTime);
} catch (InterruptedException e) {
@@ -841,8 +835,7 @@ public class MultiplexBluetoothTransport {
}
Field[] f = bsSocket.getClass().getDeclaredFields();
- int channel = -1;
-
+ //int channel = -1;
BluetoothSocket mySocket = null;
for (Field field : f) {
if(field.getName().equals("mSocket")){
diff --git a/sdl_android_lib/src/com/smartdevicelink/transport/RouterServiceValidator.java b/sdl_android_lib/src/com/smartdevicelink/transport/RouterServiceValidator.java
index ab60c65fa..5809a19aa 100644
--- a/sdl_android_lib/src/com/smartdevicelink/transport/RouterServiceValidator.java
+++ b/sdl_android_lib/src/com/smartdevicelink/transport/RouterServiceValidator.java
@@ -38,7 +38,7 @@ public class RouterServiceValidator {
private static final String TAG = "PackageCheckUtl";
public static final String ROUTER_SERVICE_PACKAGE = "com.sdl.router";
- private static final String REQUEST_PREFIX = "https://woprjr.smartdevicelink.org/api/1/applications/queryTrustedRouters";
+ private static final String REQUEST_PREFIX = "https://woprjr.smartdevicelink.com/api/1/applications/queryTrustedRouters";
private static final String DEFAULT_APP_LIST = "{\"response\": {\"com.livio.sdl\" : { \"versionBlacklist\":[] }, \"com.lexus.tcapp\" : { \"versionBlacklist\":[] }, \"com.toyota.tcapp\" : { \"versionBlacklist\": [] } , \"com.sdl.router\":{\"versionBlacklist\": [] } }}";
@@ -75,6 +75,7 @@ public class RouterServiceValidator {
private Context context= null;
private boolean inDebugMode = false;
+ @SuppressWarnings("unused")
private static boolean pendingListRefresh = false;
private ComponentName service;//This is how we can save different routers over another in a waterfall method if we choose to.
@@ -132,7 +133,6 @@ public class RouterServiceValidator {
Log.d(TAG, "It's our router service running, so time to shut it down");
Intent intent = new Intent();
intent.setComponent(service);
- //TODO Have to fix logic when router service stops. What is the correcty flow?
try{context.stopService(intent);}catch(Exception e){}
}
wakeUpRouterServices();
@@ -165,6 +165,7 @@ public class RouterServiceValidator {
return (this.inDebugMode && ((this.flags & FLAG_DEBUG_INSTALLED_FROM_CHECK) != FLAG_DEBUG_INSTALLED_FROM_CHECK));
}
+ @SuppressWarnings("unused")
private boolean shouldOverrideTimeCheck(){
return (this.inDebugMode && ((this.flags & FLAG_DEBUG_USE_TIMESTAMP_CHECK) != FLAG_DEBUG_USE_TIMESTAMP_CHECK));
}
@@ -240,14 +241,13 @@ public class RouterServiceValidator {
PackageManager packageManager = context.getPackageManager();
try {
final ApplicationInfo applicationInfo = packageManager.getApplicationInfo(packageName, 0);
- //TODO might want to try to get version with this packageManager.getPackageInfo(packageName, 0).versionCode;
- if ("com.android.vending".equals(packageManager.getInstallerPackageName(applicationInfo.packageName))
- || "com.amazon.venezia".equals(packageManager.getInstallerPackageName(applicationInfo.packageName))) {
- // App was installed by Play Store
+ if(TrustedAppStore.isTrustedStore(packageManager.getInstallerPackageName(applicationInfo.packageName))){
+ // App was installed by trusted app store
return true;
}
} catch (final NameNotFoundException e) {
e.printStackTrace();
+ return false;
}
return false;
}
@@ -325,7 +325,7 @@ public class RouterServiceValidator {
List<SdlApp> apps = new ArrayList<SdlApp>();
PackageManager packageManager = context.getPackageManager();
Intent intent = new Intent();
- intent.setAction("sdl.router.startservice"); //FIXME change this string in both the docs and the code
+ intent.setAction("sdl.router.startservice");
List<ResolveInfo> infoList = packageManager.queryBroadcastReceivers(intent, 0);
if(infoList!=null){
Log.i(TAG, "Number of SDL apps: " + infoList.size());
@@ -361,7 +361,7 @@ public class RouterServiceValidator {
return false;
}
- if(!forceRefresh && (System.currentTimeMillis()-getTrustedAppListTimeStamp(context))<REFRESH_TRUSTED_APP_LIST_TIME){ //FIXME
+ if(!forceRefresh && (System.currentTimeMillis()-getTrustedAppListTimeStamp(context))<REFRESH_TRUSTED_APP_LIST_TIME){
Log.d(TAG, "Don't need to get new list");
//Our list should still be ok for now so we will skip the request
pendingListRefresh = false;
@@ -446,7 +446,7 @@ public class RouterServiceValidator {
if(json==null){
return stringToJson(DEFAULT_APP_LIST);
}
- try {//FIXME this isn't complete. Once SHAID or other service is POC'd we can adjust
+ try {
JSONObject object = new JSONObject(json);
JSONObject trustedApps = object.getJSONObject(JSON_RESPONSE_OBJECT_TAG);
return trustedApps;
@@ -535,6 +535,41 @@ public class RouterServiceValidator {
}
}
+ public static enum TrustedAppStore{
+ PLAY_STORE("com.android.vending"),
+ AMAZON("com.amazon.venezia"),
+ XIAOMI("com.xiaomi.market"),
+ SAMSUNG("com.sec.android.app.samsungapps"),
+ WANDOUJIA("com.wandoujia.phoenix2"),
+ BAIDU_APP_SEARCH("com.baidu.appsearch"),
+ HIAPK("com.hiapk.marketpho"),
+ ;
+
+ String packageString;
+ private TrustedAppStore(String packageString){
+ this.packageString = packageString;
+ }
+
+ /**
+ * Test if the supplied store package is one of the trusted app stores
+ * @param packageString
+ * @return
+ */
+ public static boolean isTrustedStore(String packageString){
+ if(packageString == null){
+ return false;
+ }
+ TrustedAppStore[] stores = TrustedAppStore.values();
+ for(int i =0; i<stores.length; i++){
+ if(packageString.equalsIgnoreCase(stores[i].packageString)){
+ return true;
+ }
+ }
+ return false;
+ }
+
+ }
+
}
diff --git a/sdl_android_lib/src/com/smartdevicelink/transport/SdlBroadcastReceiver.java b/sdl_android_lib/src/com/smartdevicelink/transport/SdlBroadcastReceiver.java
index e57874ee8..b02a25c83 100644
--- a/sdl_android_lib/src/com/smartdevicelink/transport/SdlBroadcastReceiver.java
+++ b/sdl_android_lib/src/com/smartdevicelink/transport/SdlBroadcastReceiver.java
@@ -1,5 +1,7 @@
package com.smartdevicelink.transport;
+import java.util.Locale;
+
import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.bluetooth.BluetoothAdapter;
@@ -7,7 +9,6 @@ import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageManager.NameNotFoundException;
import android.util.Log;
@@ -21,8 +22,6 @@ public abstract class SdlBroadcastReceiver extends BroadcastReceiver{
private static final String STATE_CHANGED = "android.bluetooth.adapter.action.STATE_CHANGED" ;
protected static final String SDL_ROUTER_SERVICE_CLASS_NAME = "sdlrouterservice";
-
- public static final String FORCE_TRANSPORT_CONNECTED = "force_connect"; //This is legacy, do not refactor this.
public static final String LOCAL_ROUTER_SERVICE_EXTRA = "router_service";
public static final String LOCAL_ROUTER_SERVICE_DID_START_OWN = "did_start";
@@ -86,8 +85,7 @@ public abstract class SdlBroadcastReceiver extends BroadcastReceiver{
if(vlad.validate()){
Log.d(TAG, "Router service trusted!");
queuedService = componentName;
- intent.setAction(null);
- intent.putExtra(FORCE_TRANSPORT_CONNECTED, true);
+ intent.setAction("com.sdl.noaction"); //Replace what's there so we do go into some unintended loop
onSdlEnabled(context, intent);
}else{
Log.e(TAG, "RouterService was not trusted. Ignoring intent from : "+ componentName.getClassName());
@@ -190,7 +188,7 @@ public abstract class SdlBroadcastReceiver extends BroadcastReceiver{
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
//We will check to see if it contains this name, should be pretty specific
//Log.d(TAG, "Found Service: "+ service.service.getClassName());
- if ((service.service.getClassName()).toLowerCase().contains(SDL_ROUTER_SERVICE_CLASS_NAME)) {
+ if ((service.service.getClassName()).toLowerCase(Locale.US).contains(SDL_ROUTER_SERVICE_CLASS_NAME)) {
runningBluetoothServicePackage = service.service; //Store which instance is running
if(pingService){
Intent intent = new Intent();
@@ -259,6 +257,7 @@ public abstract class SdlBroadcastReceiver extends BroadcastReceiver{
* @return Return the local copy of SdlRouterService.class
* {@inheritDoc}
*/
+ @SuppressWarnings("rawtypes")
public abstract Class defineLocalSdlRouterClass();
diff --git a/sdl_android_lib/src/com/smartdevicelink/transport/SdlPsm.java b/sdl_android_lib/src/com/smartdevicelink/transport/SdlPsm.java
index 25107b883..b04b4453b 100644
--- a/sdl_android_lib/src/com/smartdevicelink/transport/SdlPsm.java
+++ b/sdl_android_lib/src/com/smartdevicelink/transport/SdlPsm.java
@@ -1,12 +1,10 @@
package com.smartdevicelink.transport;
-import android.util.Log;
-
import com.smartdevicelink.protocol.SdlPacket;
public class SdlPsm{
- private static final String TAG = "Sdl PSM";
+ //private static final String TAG = "Sdl PSM";
//Each state represents the byte that should be incomming
public static final int START_STATE = 0x0;
diff --git a/sdl_android_lib/src/com/smartdevicelink/transport/SdlRouterService.java b/sdl_android_lib/src/com/smartdevicelink/transport/SdlRouterService.java
index 9830777cf..1bb7f3d72 100644
--- a/sdl_android_lib/src/com/smartdevicelink/transport/SdlRouterService.java
+++ b/sdl_android_lib/src/com/smartdevicelink/transport/SdlRouterService.java
@@ -13,7 +13,8 @@ import java.util.Set;
import java.util.Vector;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
-import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
import org.json.JSONException;
import org.json.JSONObject;
@@ -46,7 +47,6 @@ import android.os.Parcelable;
import android.os.RemoteException;
import android.util.Log;
import android.util.SparseArray;
-import android.widget.Toast;
import com.smartdevicelink.R;
import com.smartdevicelink.marshal.JsonRPCMarshaller;
@@ -83,6 +83,8 @@ public class SdlRouterService extends Service{
private static final int FOREGROUND_SERVICE_ID = 849;
+ private static final long CLIENT_PING_DELAY = 1000;
+
public static final String REGISTER_NEWER_SERVER_INSTANCE_ACTION = "com.sdl.android.newservice";
public static final String START_SERVICE_ACTION = "sdl.router.startservice";
public static final String REGISTER_WITH_ROUTER_ACTION = "com.sdl.android.register";
@@ -100,6 +102,7 @@ public class SdlRouterService extends Service{
private static boolean connectAsClient = false;
private static boolean closing = false;
+ private boolean isTarnsportConnected = false;
private static Context currentContext = null;
private Handler versionCheckTimeOutHandler, altTransportTimerHandler;
@@ -113,7 +116,8 @@ public class SdlRouterService extends Service{
private Intent lastReceivedStartIntent = null;
public static HashMap<Long,RegisteredApp> registeredApps;
private SparseArray<Long> sessionMap;
- private final Object SESSION_LOCK = new Object(), REGISTERED_APPS_LOCK = new Object();
+ private SparseArray<Integer> sessionHashIdMap;
+ private final Object SESSION_LOCK = new Object(), REGISTERED_APPS_LOCK = new Object(), PING_COUNT_LOCK = new Object();
private static Messenger altTransportService = null;
@@ -132,6 +136,15 @@ public class SdlRouterService extends Service{
private int cachedModuleVersion = -1;
+ /**
+ * Executor for making sure clients are still running during trying times
+ */
+ private ScheduledExecutorService clientPingExecutor = null;
+ Intent pingIntent = null;
+ private boolean isPingingClients = false;
+ int pingCount = 0;
+
+
/* **************************************************************************************************************************************
****************************************************************************************************************************************
*********************************************** Broadcast Receivers START **************************************************************
@@ -216,6 +229,7 @@ public class SdlRouterService extends Service{
}
}
+ @SuppressWarnings("unused")
private void notifyStartedService(Context context){
Intent restart = new Intent(SdlRouterService.REGISTER_NEWER_SERVER_INSTANCE_ACTION);
restart.putExtra(SdlBroadcastReceiver.LOCAL_ROUTER_SERVICE_EXTRA, getLocalRouterService());
@@ -243,7 +257,6 @@ public class SdlRouterService extends Service{
return;
}
- //TODO make sure it's ok to comment out closeBluetoothSerialServer();
connectAsClient=false;
if(action!=null && intent.getAction().equalsIgnoreCase("android.bluetooth.adapter.action.STATE_CHANGED")
@@ -258,7 +271,7 @@ public class SdlRouterService extends Service{
if(legacyModeEnabled){
Log.d(TAG, "Legacy mode enabled and bluetooth d/c'ed, restarting router service bluetooth.");
enableLegacyMode(false);
- onTransportDisconnected(TransportType.BLUETOOTH); //TODO check that this is ok
+ onTransportDisconnected(TransportType.BLUETOOTH);
initBluetoothSerialService();
}
}
@@ -363,7 +376,7 @@ public class SdlRouterService extends Service{
Log.i(TAG, "Unregistering client: " + appIdToUnregister);
RegisteredApp unregisteredApp = null;
synchronized(REGISTERED_APPS_LOCK){
- unregisteredApp = registeredApps.remove(appIdToUnregister);//TODO check if this works
+ unregisteredApp = registeredApps.remove(appIdToUnregister);
}
Message response = Message.obtain();
response.what = TransportConstants.ROUTER_UNREGISTER_CLIENT_RESPONSE;
@@ -530,7 +543,7 @@ public class SdlRouterService extends Service{
retMsg.arg1 = TransportConstants.ROUTER_REGISTER_ALT_TRANSPORT_RESPONSE_SUCESS;
onTransportConnected(TransportType.valueOf(receivedBundle.getString(TransportConstants.HARDWARE_CONNECTED)));
}else{ //There seems to be some other transport connected
- //TODO error
+ //Error
retMsg.arg1 = TransportConstants.ROUTER_REGISTER_ALT_TRANSPORT_ALREADY_CONNECTED;
}
if(msg.replyTo!=null){
@@ -591,7 +604,6 @@ public class SdlRouterService extends Service{
@Override
public boolean onUnbind(Intent intent) {
- // TODO If we are supposed to be shutting down, we need to try again.
Log.d(TAG, "Unbind being called.");
return super.onUnbind(intent);
}
@@ -685,6 +697,7 @@ public class SdlRouterService extends Service{
synchronized(SESSION_LOCK){
this.sessionMap = new SparseArray<Long>();
+ this.sessionHashIdMap = new SparseArray<Integer>();
}
packetExecuter = Executors.newSingleThreadExecutor();
}
@@ -746,6 +759,7 @@ public class SdlRouterService extends Service{
@Override
public void onDestroy(){
+ stopClientPings();
if(versionCheckTimeOutHandler!=null){versionCheckTimeOutHandler.removeCallbacks(versionCheckRunable);}
if(altTransportTimerHandler!=null){
altTransportTimerHandler.removeCallbacks(versionCheckRunable);
@@ -769,6 +783,10 @@ public class SdlRouterService extends Service{
this.sessionMap.clear();
this.sessionMap = null;
}
+ if(this.sessionHashIdMap!=null){
+ this.sessionHashIdMap.clear();
+ this.sessionHashIdMap = null;
+ }
}
//SESSION_LOCK = null;
@@ -847,7 +865,7 @@ public class SdlRouterService extends Service{
builder.setTicker("SmartDeviceLink Connected");
builder.setContentText("Connected to " + this.getConnectedDeviceName());
- //TODO use icon from library resources if available
+ //We should use icon from library resources if available
builder.setSmallIcon(android.R.drawable.stat_sys_data_bluetooth);
builder.setLargeIcon(icon);
builder.setOngoing(true);
@@ -878,7 +896,7 @@ public class SdlRouterService extends Service{
*********************************************** Helper Methods **************************************************************
****************************************************************************************************************************************/
- public String getConnectedDeviceName(){ //FIXME we need to implement something better than this, but for now it will work....
+ public String getConnectedDeviceName(){
return connectedDeviceName;
}
@@ -960,8 +978,7 @@ public class SdlRouterService extends Service{
}
public void onTransportConnected(final TransportType type){
- //TODO remove
- Toast.makeText(getBaseContext(), "SDL "+ type.name()+ " Transport Connected", Toast.LENGTH_SHORT).show();
+ isTarnsportConnected = true;
enterForeground();
if(packetWriteTaskMaster!=null){
packetWriteTaskMaster.close();
@@ -973,9 +990,10 @@ public class SdlRouterService extends Service{
Intent startService = new Intent();
startService.setAction(START_SERVICE_ACTION);
startService.putExtra(TransportConstants.START_ROUTER_SERVICE_SDL_ENABLED_EXTRA, true);
+ startService.putExtra(TransportConstants.FORCE_TRANSPORT_CONNECTED, true);
startService.putExtra(TransportConstants.START_ROUTER_SERVICE_SDL_ENABLED_APP_PACKAGE, getBaseContext().getPackageName());
startService.putExtra(TransportConstants.START_ROUTER_SERVICE_SDL_ENABLED_CMP_NAME, new ComponentName(this, this.getClass()));
- sendBroadcast(startService);
+ sendBroadcast(startService);
//HARDWARE_CONNECTED
}
@@ -985,6 +1003,9 @@ public class SdlRouterService extends Service{
}
Log.e(TAG, "Notifying client service of hardware disconnect.");
+ isTarnsportConnected = false;
+ stopClientPings();
+
exitForeground();//Leave our foreground state as we don't have a connection anymore
if(packetWriteTaskMaster!=null){
@@ -1007,25 +1028,20 @@ public class SdlRouterService extends Service{
Bundle bundle = new Bundle();
bundle.putString(HARDWARE_DISCONNECTED, type.name());
bundle.putBoolean(TransportConstants.ENABLE_LEGACY_MODE_EXTRA, legacyModeEnabled);
- message.setData(bundle); //TODO should we add a transport event what message type?
+ message.setData(bundle);
notifyClients(message);
}
//We've notified our clients, less clean up the mess now.
synchronized(SESSION_LOCK){
this.sessionMap.clear();
+ this.sessionHashIdMap.clear();
}
synchronized(REGISTERED_APPS_LOCK){
if(registeredApps==null){
return;
}
registeredApps.clear();
- //for (RegisteredApp app : registeredApps.values()) {
- // app.clearSessionIds();
- // app.getSessionIds().add((long)-1); //Since we should be expecting at least one session.
- //}
}
- //TODO remove
- Toast.makeText(getBaseContext(), "SDL "+ type.name()+ " Transport disconnected", Toast.LENGTH_SHORT).show();
}
public void onPacketRead(SdlPacket packet){
@@ -1048,7 +1064,7 @@ public class SdlRouterService extends Service{
}
}
- private final Handler mHandlerBT = new Handler() { //TODO make this generic transport handler
+ private final Handler mHandlerBT = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
@@ -1059,7 +1075,7 @@ public class SdlRouterService extends Service{
switch (msg.arg1) {
case MultiplexBluetoothTransport.STATE_CONNECTED:
storeConnectedStatus(true);
- onTransportConnected(TransportType.BLUETOOTH); //FIXME actually check
+ onTransportConnected(TransportType.BLUETOOTH);
break;
case MultiplexBluetoothTransport.STATE_CONNECTING:
// Currently attempting to connect - update UI?
@@ -1074,7 +1090,7 @@ public class SdlRouterService extends Service{
if(!legacyModeEnabled){
initBluetoothSerialService();
}
- onTransportDisconnected(TransportType.BLUETOOTH); //FIXME actually check
+ onTransportDisconnected(TransportType.BLUETOOTH);
}
break;
case MultiplexBluetoothTransport.STATE_ERROR:
@@ -1083,7 +1099,6 @@ public class SdlRouterService extends Service{
mSerialService.setStateManually(MultiplexBluetoothTransport.STATE_NONE);
mSerialService = null;
}
-
break;
}
break;
@@ -1206,12 +1221,27 @@ public class SdlRouterService extends Service{
removeSessionFromMap(session);
byte[] uai = createForceUnregisterApp((byte)session, (byte)packet.getVersion());
manuallyWriteBytes(uai,0,uai.length);
- byte[] stopService = (SdlPacketFactory.createEndSession(SessionType.RPC, (byte)session, 0, (byte)packet.getVersion())).constructPacket();
+ int hashId = 0;
+ synchronized(this.SESSION_LOCK){
+ if(this.sessionHashIdMap.indexOfKey(session)>=0){
+ hashId = this.sessionHashIdMap.get(session);
+ this.sessionHashIdMap.remove(session);
+ }
+ }
+ byte[] stopService = (SdlPacketFactory.createEndSession(SessionType.RPC, (byte)session, 0, (byte)packet.getVersion(),BitConverter.intToByteArray(hashId))).constructPacket();
manuallyWriteBytes(stopService,0,stopService.length);
return false;
}
-
byte version = (byte)packet.getVersion();
+
+ if(shouldAssertNewSession && version>1 && packet.getFrameInfo() == SdlPacket.FRAME_INFO_START_SERVICE_ACK){ //we know this was a start session response
+ if (packet.getPayload() != null && packet.getDataSize() == 4){ //hashid will be 4 bytes in length
+ synchronized(SESSION_LOCK){
+ this.sessionHashIdMap.put(session, (BitConverter.intFromByteArray(packet.getPayload(), 0)));
+ }
+ }
+ }
+
int packetSize = (int) (packet.getDataSize() + SdlPacket.HEADER_SIZE);
//Log.i(TAG, "Checking packet size: " + packetSize);
Message message = Message.obtain();
@@ -1219,8 +1249,6 @@ public class SdlRouterService extends Service{
if(packetSize < ByteArrayMessageSpliter.MAX_BINDER_SIZE){ //This is a small enough packet just send on through
//Log.w(TAG, " Packet size is just right " + packetSize + " is smaller than " + ByteArrayMessageSpliter.MAX_BINDER_SIZE + " = " + (packetSize<ByteArrayMessageSpliter.MAX_BINDER_SIZE));
-
- //TODO put arg1 and 2
message.what = TransportConstants.ROUTER_RECEIVED_PACKET;
bundle.putParcelable(FORMED_PACKET_EXTRA_NAME, packet);
bundle.putInt(TransportConstants.BYTES_TO_SEND_FLAGS, TransportConstants.BYTES_TO_SEND_FLAG_NONE);
@@ -1292,7 +1320,14 @@ public class SdlRouterService extends Service{
Log.i(TAG, "Attempting to stop session " + session);
byte[] uai = createForceUnregisterApp((byte)session, (byte)version);
manuallyWriteBytes(uai,0,uai.length);
- byte[] stopService = (SdlPacketFactory.createEndSession(SessionType.RPC, (byte)session, 0, (byte)version)).constructPacket();
+ int hashId = 0;
+ synchronized(this.SESSION_LOCK){
+ if(this.sessionHashIdMap.indexOfKey(session)>=0){
+ hashId = this.sessionHashIdMap.get(session);
+ this.sessionHashIdMap.remove(session);
+ }
+ }
+ byte[] stopService = (SdlPacketFactory.createEndSession(SessionType.RPC, (byte)session, 0, (byte)version,BitConverter.intToByteArray(hashId))).constructPacket();
manuallyWriteBytes(stopService,0,stopService.length);
}
@@ -1310,10 +1345,18 @@ public class SdlRouterService extends Service{
sessionId = sessions.get(i).intValue();
unregister = createForceUnregisterApp((byte)sessionId,version);
manuallyWriteBytes(unregister,0,unregister.length);
- stopService = (SdlPacketFactory.createEndSession(SessionType.RPC, (byte)sessionId, 0, version)).constructPacket();
+ int hashId = 0;
+ synchronized(this.SESSION_LOCK){
+ if(this.sessionHashIdMap.indexOfKey(sessionId)>=0){
+ hashId = this.sessionHashIdMap.get(sessionId);
+ }
+ }
+ stopService = (SdlPacketFactory.createEndSession(SessionType.RPC, (byte)sessionId, 0, version,BitConverter.intToByteArray(hashId))).constructPacket();
+
manuallyWriteBytes(stopService,0,stopService.length);
synchronized(SESSION_LOCK){
this.sessionMap.remove(sessionId);
+ this.sessionHashIdMap.remove(sessionId);
}
}
synchronized(REGISTERED_APPS_LOCK){
@@ -1324,7 +1367,7 @@ public class SdlRouterService extends Service{
return true;//We should have sent our packet, so we can return true now
}
- private synchronized void closeBluetoothSerialServer(){ //FIXME change to ITransport
+ private synchronized void closeBluetoothSerialServer(){
if(mSerialService != null){
mSerialService.stop();
mSerialService = null;
@@ -1381,6 +1424,8 @@ public class SdlRouterService extends Service{
//********************************************************* PREFERENCES ****************************************************************
//**************************************************************************************************************************************
+ @SuppressLint("WorldReadableFiles")
+ @SuppressWarnings("deprecation")
private void storeConnectedStatus(boolean isConnected){
SharedPreferences prefs = getApplicationContext().getSharedPreferences(getApplicationContext().getPackageName()+SdlBroadcastReceiver.TRANSPORT_GLOBAL_PREFS,
Context.MODE_WORLD_READABLE);
@@ -1528,7 +1573,6 @@ public class SdlRouterService extends Service{
}
}
- @SuppressLint("NewApi")
private boolean removeAllSessionsWithAppId(long appId){
synchronized(SESSION_LOCK){
if(sessionMap!=null){
@@ -1538,7 +1582,8 @@ public class SdlRouterService extends Service{
Log.d(TAG, "Investigating session " +iter.keyAt(i));
Log.d(TAG, "App id is: " + iter.valueAt(i));
if(((Long)iter.valueAt(i)).compareTo(appId) == 0){
- sessionMap.removeAt(i);
+ sessionHashIdMap.remove(iter.keyAt(i));
+ sessionMap.removeAt(i);
}
}
}
@@ -1557,7 +1602,7 @@ public class SdlRouterService extends Service{
Log.d(TAG, "Investigating session " +sessions.get(i).intValue());
Log.d(TAG, "App id is: " + sessionMap.get(sessions.get(i).intValue()));
sessionId = sessions.get(i).intValue();
- removeSessionFromMap(sessionId); //TODO instead of removing, put a null there
+ removeSessionFromMap(sessionId);
if(cleanModule){
attemptToCleanUpModule(sessionId, cachedModuleVersion);
}
@@ -1727,6 +1772,66 @@ public class SdlRouterService extends Service{
return null;
}
+ private void startClientPings(){
+ synchronized(this){
+ if(!isTarnsportConnected){ //If we aren't connected, bail
+ return;
+ }
+ if(isPingingClients){
+ Log.w(TAG, "Already pinging clients. Resting count");
+ synchronized(PING_COUNT_LOCK){
+ pingCount = 0;
+ }
+ return;
+ }
+ if(clientPingExecutor == null){
+ clientPingExecutor = Executors.newSingleThreadScheduledExecutor();
+ }
+ isPingingClients = true;
+ synchronized(PING_COUNT_LOCK){
+ pingCount = 0;
+ }
+ clientPingExecutor.scheduleAtFixedRate(new Runnable(){
+
+ @Override
+ public void run() {
+ if(getPingCount()>=10){
+ Log.d(TAG, "Hit ping limit");
+ stopClientPings();
+ return;
+ }
+ if(pingIntent == null){
+ pingIntent = new Intent();
+ pingIntent.setAction(START_SERVICE_ACTION);
+ pingIntent.putExtra(TransportConstants.START_ROUTER_SERVICE_SDL_ENABLED_EXTRA, true);
+ pingIntent.putExtra(TransportConstants.START_ROUTER_SERVICE_SDL_ENABLED_APP_PACKAGE, getBaseContext().getPackageName());
+ pingIntent.putExtra(TransportConstants.START_ROUTER_SERVICE_SDL_ENABLED_CMP_NAME, new ComponentName(SdlRouterService.this, SdlRouterService.this.getClass()));
+ pingIntent.putExtra(TransportConstants.START_ROUTER_SERVICE_SDL_ENABLED_PING, true);
+ }
+ getBaseContext().sendBroadcast(pingIntent);
+ synchronized(PING_COUNT_LOCK){
+ pingCount++;
+ }
+
+ }
+ }, CLIENT_PING_DELAY, CLIENT_PING_DELAY, TimeUnit.MILLISECONDS); //Give a little delay for first call
+ }
+ }
+
+ private int getPingCount(){
+ synchronized(PING_COUNT_LOCK){
+ return pingCount;
+ }
+ }
+
+ private void stopClientPings(){
+ if(clientPingExecutor!=null && !clientPingExecutor.isShutdown()){
+ clientPingExecutor.shutdownNow();
+ clientPingExecutor = null;
+ isPingingClients = false;
+ }
+ pingIntent = null;
+ }
/* ****************************************************************************************************************************************
// ********************************************************** TINY CLASSES ************************************************************
@@ -1746,7 +1851,7 @@ public class SdlRouterService extends Service{
ComponentName name;
private LocalRouterService(Intent intent, int version, long timeStamp,ComponentName name ){
- this.launchIntent = intent; //TODO we can create an intent object based on component name instead
+ this.launchIntent = intent;
this.version = version;
this.timestamp = timeStamp;
this.name = name;
@@ -1848,7 +1953,7 @@ public class SdlRouterService extends Service{
int prioirtyForBuffingMessage;
DeathRecipient deathNote = null;
//Packey queue vars
- LinkedBlockingQueue<PacketWriteTask> queue; //FIXME use deque?
+ PacketWriteTaskBlockingQueue queue;
Handler queueWaitHandler= null;
Runnable queueWaitRunnable = null;
boolean queuePaused = false;
@@ -1862,7 +1967,7 @@ public class SdlRouterService extends Service{
this.appId = appId;
this.messenger = messenger;
this.sessionIds = new Vector<Long>();
- this.queue = new LinkedBlockingQueue<PacketWriteTask>();
+ this.queue = new PacketWriteTaskBlockingQueue();
queueWaitHandler = new Handler();
setDeathNote();
}
@@ -2058,6 +2163,7 @@ public class SdlRouterService extends Service{
Log.w(TAG, "Binder died");
removeAllSessionsForApp(RegisteredApp.this,true);
removeAppFromMap(RegisteredApp.this);
+ startClientPings();
}
};
}
@@ -2176,4 +2282,167 @@ public class SdlRouterService extends Service{
this.isHalted = true;
}
}
+
+ /**
+ * Custom queue to prioritize packet write tasks based on their priority coefficient.<br> The queue is a doubly linked list.<br><br>
+ * When a tasks is added to the queue, it will be evaluated using it's priority coefficient. If the coefficient is greater than 0, it will simply
+ * be placed at the end of the queue. If the coefficient is equal to 0, the queue will begin to iterate at the head and work it's way back. Once it is found that the current
+ * tasks has a priority coefficient greater than 0, it will be placed right before that task. The idea is to keep a semi-serial queue but creates a priority that allows urgent
+ * tasks such as UI related to skip near the front. However, it is assumed those tasks of higher priority should also be handled in a serial fashion.
+ *
+ * @author Joey Grover
+ *
+ */
+ private class PacketWriteTaskBlockingQueue{
+ final class Node<E> {
+ E item;
+ Node<E> prev;
+ Node<E> next;
+ Node(E item, Node<E> previous, Node<E> next) {
+ this.item = item;
+ this.prev = previous;
+ this.next = next;
+ }
+ }
+
+ private Node<PacketWriteTask> head;
+ private Node<PacketWriteTask> tail;
+
+ /**
+ * This will take the given task and insert it at the tail of the queue
+ * @param task the task to be inserted at the tail of the queue
+ */
+ private void insertAtTail(PacketWriteTask task){
+ if (task == null){
+ throw new NullPointerException();
+ }
+ Node<PacketWriteTask> oldTail = tail;
+ Node<PacketWriteTask> newTail = new Node<PacketWriteTask>(task, oldTail, null);
+ tail = newTail;
+ if (head == null){
+ head = newTail;
+ }else{
+ oldTail.next = newTail;
+ }
+
+ }
+
+ /**
+ * This will take the given task and insert it at the head of the queue
+ * @param task the task to be inserted at the head of the queue
+ */
+ private void insertAtHead(PacketWriteTask task){
+ if (task == null){
+ throw new NullPointerException();
+ }
+ Node<PacketWriteTask> oldHead = head;
+ Node<PacketWriteTask> newHead = new Node<PacketWriteTask>(task, null, oldHead);
+ head = newHead;
+ if (tail == null){
+ tail = newHead;
+ }else{
+ if(oldHead!=null){
+ oldHead.prev = newHead;
+ }
+ }
+ }
+
+ /**
+ * Insert the task in the queue where it belongs
+ * @param task
+ */
+ public void add(PacketWriteTask task){
+ synchronized(this){
+ if (task == null){
+ throw new NullPointerException();
+ }
+
+ //If we currently don't have anything in our queue
+ if(head == null || tail == null){
+ Node<PacketWriteTask> taskNode = new Node<PacketWriteTask>(task, head, tail);
+ head = taskNode;
+ tail = taskNode;
+ return;
+ }else if(task.priorityCoefficient>0){ //If the task is already a not high priority task, we just need to insert it at the tail
+ insertAtTail(task);
+ return;
+ }else if(head.item.priorityCoefficient>0){ //If the head task is already a not high priority task, we just need to insert at head
+ insertAtHead(task);
+ return;
+ }else{
+ if(tail!=null && tail.item.priorityCoefficient==0){ //Saves us from going through the entire list if all of these tasks are priority coef == 0
+ insertAtTail(task);
+ return;
+ }
+ Node<PacketWriteTask> currentPlace = head;
+ while(true){
+ if(currentPlace.item.priorityCoefficient==0){
+ if(currentPlace.next==null){
+ //We've reached the end of the list
+ insertAtTail(task);
+ return;
+ }else{
+ currentPlace = currentPlace.next;
+ continue;
+ }
+ }else{
+ //We've found where this task should be inserted
+ Node<PacketWriteTask> previous = currentPlace.prev;
+ Node<PacketWriteTask> taskNode = new Node<PacketWriteTask>(task, previous, currentPlace);
+ previous.next = taskNode;
+ currentPlace.prev = taskNode;
+ return;
+
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Peek at the current head of the queue
+ * @return the task at the head of the queue but does not remove it from the queue
+ */
+ public PacketWriteTask peek(){
+ synchronized(this){
+ if(head == null){
+ return null;
+ }else{
+ return head.item;
+ }
+ }
+ }
+
+ /**
+ * Remove the head of the queue
+ * @return the old head of the queue
+ */
+ public PacketWriteTask poll(){
+ synchronized(this){
+ if(head == null){
+ return null;
+ }else{
+ Node<PacketWriteTask> retValNode = head;
+ Node<PacketWriteTask> newHead = head.next;
+ if(newHead == null){
+ tail = null;
+ }
+ head = newHead;
+
+ return retValNode.item;
+ }
+ }
+ }
+
+ /**
+ * Currently only clears the head and the tail of the queue.
+ */
+ public void clear(){
+ //Should probably go through the linked list and clear elements, but gc should clear them out automatically.
+ head = null;
+ tail = null;
+ }
+ }
+
+
}
diff --git a/sdl_android_lib/src/com/smartdevicelink/transport/TransportBroker.java b/sdl_android_lib/src/com/smartdevicelink/transport/TransportBroker.java
index 9203b40cd..613c857d9 100644
--- a/sdl_android_lib/src/com/smartdevicelink/transport/TransportBroker.java
+++ b/sdl_android_lib/src/com/smartdevicelink/transport/TransportBroker.java
@@ -7,11 +7,9 @@ import java.util.Locale;
import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
-import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
@@ -127,7 +125,8 @@ public class TransportBroker {
/**
* Handler of incoming messages from service.
*/
- class ClientHandler extends Handler {
+ @SuppressLint("HandlerLeak")
+ class ClientHandler extends Handler {
ClassLoader loader = getClass().getClassLoader();
@Override
public void handleMessage(Message msg) {
@@ -149,7 +148,7 @@ public class TransportBroker {
}
//Find out what message we have and what to do with it
- switch (msg.what) {//FIXME
+ switch (msg.what) {
case TransportConstants.ROUTER_REGISTER_CLIENT_RESPONSE:
switch(msg.arg1){
case TransportConstants.REGISTRATION_RESPONSE_SUCESS:
@@ -279,8 +278,8 @@ public class TransportBroker {
SimpleDateFormat s = new SimpleDateFormat("hhmmssss"); //So we have a time stamp of the event
String timeStamp = s.format(new Date(System.currentTimeMillis()));
if(whereToReply==null){
- if(appId==null){ //FIXME this should really just throw an error
- whereToReply = WHERE_TO_REPLY_PREFIX + "."+ timeStamp; //TODO get appid
+ if(appId==null){ //This should really just throw an error
+ whereToReply = WHERE_TO_REPLY_PREFIX + "."+ timeStamp;
}else{
whereToReply = WHERE_TO_REPLY_PREFIX + appId +"."+ timeStamp;
}
@@ -318,7 +317,7 @@ public class TransportBroker {
Log.d(TAG, "RESETING transport broker for " + whereToReply);
synchronized(INIT_LOCK){
unregisterWithRouterService();
- routerServiceMessenger = null; //TODO make sure theres nothing else we need
+ routerServiceMessenger = null;
queuedOnTransportConnect = null;
unBindFromRouterService();
}
@@ -484,6 +483,7 @@ public class TransportBroker {
}
+ @SuppressLint("InlinedApi")
private boolean sendBindingIntent(){
if(this.routerPackage !=null && this.routerClassName !=null){
Log.d(TAG, "Sending bind request to " + this.routerPackage + " - " + this.routerClassName);
@@ -492,7 +492,7 @@ public class TransportBroker {
//Quickly make sure it's just up and running
getContext().startService(bindingIntent);
bindingIntent.setAction( TransportConstants.BIND_REQUEST_TYPE_CLIENT);
- return getContext().bindService(bindingIntent, routerConnection, Context.BIND_ABOVE_CLIENT);
+ return getContext().bindService(bindingIntent, routerConnection, Context.BIND_AUTO_CREATE);
}else{
return false;
}
diff --git a/sdl_android_lib/src/com/smartdevicelink/transport/TransportConstants.java b/sdl_android_lib/src/com/smartdevicelink/transport/TransportConstants.java
index 7a989fb47..00b7e54b0 100644
--- a/sdl_android_lib/src/com/smartdevicelink/transport/TransportConstants.java
+++ b/sdl_android_lib/src/com/smartdevicelink/transport/TransportConstants.java
@@ -29,7 +29,8 @@ public class TransportConstants {
public static final String START_ROUTER_SERVICE_SDL_ENABLED_EXTRA = "sdl_enabled";
public static final String START_ROUTER_SERVICE_SDL_ENABLED_APP_PACKAGE = "package_name";
public static final String START_ROUTER_SERVICE_SDL_ENABLED_CMP_NAME = "component_name";
-
+ public static final String START_ROUTER_SERVICE_SDL_ENABLED_PING = "ping";
+ public static final String FORCE_TRANSPORT_CONNECTED = "force_connect"; //This is legacy, do not refactor this.
public static final String REPLY_TO_INTENT_EXTRA = "ReplyAddress";
public static final String CONNECT_AS_CLIENT_BOOLEAN_EXTRA = "connectAsClient";
diff --git a/sdl_android_lib/src/com/smartdevicelink/util/HttpRequestTask.java b/sdl_android_lib/src/com/smartdevicelink/util/HttpRequestTask.java
index 1ee1ecb26..f5f56ece4 100644
--- a/sdl_android_lib/src/com/smartdevicelink/util/HttpRequestTask.java
+++ b/sdl_android_lib/src/com/smartdevicelink/util/HttpRequestTask.java
@@ -67,6 +67,9 @@ public class HttpRequestTask extends AsyncTask<String, String, String> {
if(urlString == null || request_type == null){
Log.e(TAG, "Can't process request, param error");
+ if(cb!=null){
+ cb.httpFailure(-1);
+ }
return "Error";
}
@@ -141,6 +144,9 @@ public class HttpRequestTask extends AsyncTask<String, String, String> {
Log.e(TAG, "Error closing stream", e);
}
}
+ if(cb!=null){
+ cb.httpFailure(-1);
+ }
}
return null;
}