summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSho Amano <samano@xevo.com>2018-10-02 18:57:42 +0900
committerSho Amano <samano@xevo.com>2018-10-10 14:49:51 +0900
commitf4a8bd5078ce777433ec125bc44e7d9773989ff2 (patch)
treec333b0fb5e7ab4f29103880bf939e99bdcb868a7
parentf099f7c6431dd661bd314396722154c57d1499c0 (diff)
downloadsdl_android-f4a8bd5078ce777433ec125bc44e7d9773989ff2.tar.gz
fix: MultiplexTcpTransport may open socket via mobile network
On Android 5+, a Socket will be bound to mobile network if the phone is connected to a Wi-Fi network with no Internet connectivity. This "feature" prevents us from making a local TCP connection between Core. This fix makes sure that the TCP transport works with head units that provide no Internet connectivity over their Wi-Fi.
-rw-r--r--sdl_android/src/main/java/com/smartdevicelink/transport/MultiplexTcpTransport.java8
-rw-r--r--sdl_android/src/main/java/com/smartdevicelink/transport/SdlRouterService.java2
-rw-r--r--sdl_android/src/main/java/com/smartdevicelink/transport/utl/WiFiSocketFactory.java56
3 files changed, 63 insertions, 3 deletions
diff --git a/sdl_android/src/main/java/com/smartdevicelink/transport/MultiplexTcpTransport.java b/sdl_android/src/main/java/com/smartdevicelink/transport/MultiplexTcpTransport.java
index 71dd8f6ee..d5843f4c2 100644
--- a/sdl_android/src/main/java/com/smartdevicelink/transport/MultiplexTcpTransport.java
+++ b/sdl_android/src/main/java/com/smartdevicelink/transport/MultiplexTcpTransport.java
@@ -32,6 +32,7 @@
package com.smartdevicelink.transport;
+import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@@ -39,6 +40,7 @@ import android.util.Log;
import com.smartdevicelink.protocol.SdlPacket;
import com.smartdevicelink.transport.enums.TransportType;
+import com.smartdevicelink.transport.utl.WiFiSocketFactory;
import java.io.IOException;
import java.io.InputStream;
@@ -65,14 +67,16 @@ public class MultiplexTcpTransport extends MultiplexBaseTransport {
private OutputStream mOutputStream = null;
private MultiplexTcpTransport.TcpTransportThread mThread = null;
private WriterThread writerThread;
+ private Context mContext;
- public MultiplexTcpTransport(int port, String ipAddress, boolean autoReconnect, Handler handler) {
+ public MultiplexTcpTransport(int port, String ipAddress, boolean autoReconnect, Handler handler, Context context) {
super(handler, TransportType.TCP);
this.ipAddress = ipAddress;
this.port = port;
connectedDeviceAddress = ipAddress + ":" + port;
this.autoReconnect = autoReconnect;
+ mContext = context;
setState(STATE_NONE);
}
@@ -214,7 +218,7 @@ public class MultiplexTcpTransport extends MultiplexBaseTransport {
}
logInfo(String.format("TCPTransport.connect: Socket is closed. Trying to connect to %s", getAddress()));
- mSocket = new Socket();
+ mSocket = WiFiSocketFactory.createSocket(mContext);
mSocket.connect(new InetSocketAddress(ipAddress, port));
mOutputStream = mSocket.getOutputStream();
mInputStream = mSocket.getInputStream();
diff --git a/sdl_android/src/main/java/com/smartdevicelink/transport/SdlRouterService.java b/sdl_android/src/main/java/com/smartdevicelink/transport/SdlRouterService.java
index ec61a13e3..50c5b5412 100644
--- a/sdl_android/src/main/java/com/smartdevicelink/transport/SdlRouterService.java
+++ b/sdl_android/src/main/java/com/smartdevicelink/transport/SdlRouterService.java
@@ -650,7 +650,7 @@ public class SdlRouterService extends Service{
}//else { TCP transport does not exists.}
//TCP transport either doesn't exist or is not connected. Start one up.
- service.tcpTransport = new MultiplexTcpTransport(port, ipAddress, true, service.tcpHandler);
+ service.tcpTransport = new MultiplexTcpTransport(port, ipAddress, true, service.tcpHandler, service);
service.tcpTransport.start();
}
diff --git a/sdl_android/src/main/java/com/smartdevicelink/transport/utl/WiFiSocketFactory.java b/sdl_android/src/main/java/com/smartdevicelink/transport/utl/WiFiSocketFactory.java
new file mode 100644
index 000000000..ae17fc5a9
--- /dev/null
+++ b/sdl_android/src/main/java/com/smartdevicelink/transport/utl/WiFiSocketFactory.java
@@ -0,0 +1,56 @@
+package com.smartdevicelink.transport.utl;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.os.Build;
+
+import java.io.IOException;
+import java.net.Socket;
+
+import javax.net.SocketFactory;
+
+import static com.smartdevicelink.util.NativeLogTool.logInfo;
+
+public class WiFiSocketFactory {
+ /**
+ * Creates a TCP socket which is bound to Wi-Fi network (for Android 5+)
+ *
+ * On Android 5 and later, this method returns a Socket which is always bound to a Wi-Fi
+ * network. If the phone is not connected to a Wi-Fi network, this method throws an IOException.
+ * Prior to Android 5, this method simply creates a Socket equivalent to "new Socket();".
+ *
+ * @return a Socket instance bound to Wi-Fi network.
+ */
+ public static Socket createSocket(Context context) throws IOException {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ SocketFactory factory = retrieveSocketFactory(context);
+ if (factory == null) {
+ logInfo("Cannot find Wi-Fi network, aborting socket creation.");
+ throw new IOException("The phone is not connected to Wi-Fi network");
+ }
+ return factory.createSocket();
+ } else {
+ return new Socket();
+ }
+ }
+
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ private static SocketFactory retrieveSocketFactory(Context context) {
+ ConnectivityManager connMan = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ // requires ACCESS_NETWORK_STATE permission
+ Network[] allNetworks = connMan.getAllNetworks();
+
+ for (Network network : allNetworks) {
+ // requires ACCESS_NETWORK_STATE permission
+ NetworkCapabilities capabilities = connMan.getNetworkCapabilities(network);
+ if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
+ return network.getSocketFactory();
+ }
+ }
+
+ return null;
+ }
+}