summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBilal Alsharifi <599206+bilal-alsharifi@users.noreply.github.com>2019-02-27 11:00:03 -0500
committerGitHub <noreply@github.com>2019-02-27 11:00:03 -0500
commit3a8dc4545c2a186fd80804097049e0c2284faac8 (patch)
tree223959216ce1a051848e3fe51d3724d585388677
parent52b185e609b382b34917932f8b3ac9616a8d206f (diff)
parentf2647ec517fcaa33eb3e12757fd310d7315309ce (diff)
downloadsdl_android-3a8dc4545c2a186fd80804097049e0c2284faac8.tar.gz
Merge pull request #933 from smartdevicelink/bugfix/usb_enhacements
usb enhacements
-rw-r--r--sdl_android/src/main/java/com/smartdevicelink/protocol/SdlProtocol.java3
-rw-r--r--sdl_android/src/main/java/com/smartdevicelink/transport/MultiplexUsbTransport.java43
-rw-r--r--sdl_android/src/main/java/com/smartdevicelink/transport/SdlRouterService.java183
-rw-r--r--sdl_android/src/main/java/com/smartdevicelink/transport/TransportBroker.java13
-rw-r--r--sdl_android/src/main/java/com/smartdevicelink/transport/USBAccessoryAttachmentActivity.java20
-rw-r--r--sdl_android/src/main/java/com/smartdevicelink/transport/UsbTransferProvider.java50
-rw-r--r--sdl_android/src/main/java/com/smartdevicelink/util/AndroidTools.java13
-rw-r--r--sdl_android/src/main/res/values/sdl.xml2
8 files changed, 251 insertions, 76 deletions
diff --git a/sdl_android/src/main/java/com/smartdevicelink/protocol/SdlProtocol.java b/sdl_android/src/main/java/com/smartdevicelink/protocol/SdlProtocol.java
index f97e8403c..7f223d1ce 100644
--- a/sdl_android/src/main/java/com/smartdevicelink/protocol/SdlProtocol.java
+++ b/sdl_android/src/main/java/com/smartdevicelink/protocol/SdlProtocol.java
@@ -1147,7 +1147,7 @@ public class SdlProtocol {
activeTransports.remove(SessionType.PCM);
}
- if(disconnectedTransport.equals(getTransportForSession(SessionType.RPC))){
+ if(disconnectedTransport.equals(getTransportForSession(SessionType.RPC)) || disconnectedTransport.equals(connectedPrimaryTransport)){
//transportTypes.remove(type);
boolean primaryTransportAvailable = false;
if(requestedPrimaryTransports != null && requestedPrimaryTransports.size() > 1){
@@ -1161,6 +1161,7 @@ public class SdlProtocol {
}
}
}
+ connectedPrimaryTransport = null;
transportManager.close(iSdlProtocol.getSessionId());
transportManager = null;
requestedSession = false;
diff --git a/sdl_android/src/main/java/com/smartdevicelink/transport/MultiplexUsbTransport.java b/sdl_android/src/main/java/com/smartdevicelink/transport/MultiplexUsbTransport.java
index e807f7ac7..7ebcec1c2 100644
--- a/sdl_android/src/main/java/com/smartdevicelink/transport/MultiplexUsbTransport.java
+++ b/sdl_android/src/main/java/com/smartdevicelink/transport/MultiplexUsbTransport.java
@@ -62,7 +62,8 @@ public class MultiplexUsbTransport extends MultiplexBaseTransport{
private final Bundle deviceInfo;
private ReaderThread readerThread;
private WriterThread writerThread;
- private final ParcelFileDescriptor parcelFileDescriptor;
+ private ParcelFileDescriptor parcelFileDescriptor;
+ private Boolean connectionSuccessful = null;
MultiplexUsbTransport(ParcelFileDescriptor parcelFileDescriptor, Handler handler, Bundle bundle){
super(handler, TransportType.USB);
@@ -99,9 +100,18 @@ public class MultiplexUsbTransport extends MultiplexBaseTransport{
public synchronized void start(){
setState(STATE_CONNECTING);
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
+ if(fileDescriptor == null || !fileDescriptor.valid()){
+ Log.e(TAG, "USB FD was null or not valid,");
+ setState(STATE_NONE);
+ return;
+ }
readerThread = new ReaderThread(fileDescriptor);
+ readerThread.setDaemon(true);
writerThread = new WriterThread(fileDescriptor);
+ writerThread.setDaemon(true);
+ readerThread.start();
+ writerThread.start();
// Send the name of the connected device back to the UI Activity
Message msg = handler.obtainMessage(SdlRouterService.MESSAGE_DEVICE_NAME);
@@ -112,29 +122,33 @@ public class MultiplexUsbTransport extends MultiplexBaseTransport{
handler.sendMessage(msg);
setState(STATE_CONNECTED);
- readerThread.start();
- writerThread.start();
}
protected synchronized void stop(int stateToTransitionTo) {
//Log.d(TAG, "Attempting to close the Usb transports");
if (writerThread != null) {
writerThread.cancel();
+ writerThread.interrupt();
writerThread = null;
}
if (readerThread != null) {
readerThread.cancel();
+ readerThread.interrupt();
readerThread = null;
}
- if(parcelFileDescriptor != null){
+ if( (connectionSuccessful== null || connectionSuccessful == true ) //else, the connection was bad. Not closing the PFD helps recover
+ && parcelFileDescriptor != null){
try {
parcelFileDescriptor.close();
} catch (IOException e) {
e.printStackTrace();
}
}
+ parcelFileDescriptor = null;
+
+ System.gc();
setState(stateToTransitionTo);
}
@@ -182,8 +196,12 @@ public class MultiplexUsbTransport extends MultiplexBaseTransport{
bundle.putString(LOG, "Device connection was lost");
msg.setData(bundle);
handler.sendMessage(msg);
- stop();
-
+ handler.postDelayed(new Runnable() { //sends this stop back to the main thread to exit the reader thread
+ @Override
+ public void run() {
+ stop();
+ }
+ }, 250);
}
private class ReaderThread extends Thread{
@@ -199,7 +217,7 @@ public class MultiplexUsbTransport extends MultiplexBaseTransport{
@Override
public void run() { //FIXME probably check to see what the BT does
super.run();
- final int READ_BUFFER_SIZE = 4096;
+ final int READ_BUFFER_SIZE = 16384;
byte[] buffer = new byte[READ_BUFFER_SIZE];
int bytesRead;
boolean stateProgress;
@@ -221,6 +239,9 @@ public class MultiplexUsbTransport extends MultiplexBaseTransport{
Log.w(TAG,"Read some data, but thread is interrupted");
return;
}
+ if(connectionSuccessful != null && connectionSuccessful == false){
+ connectionSuccessful = true;
+ }
byte input;
for(int i=0;i<bytesRead; i++){
input=buffer[i];
@@ -284,12 +305,11 @@ public class MultiplexUsbTransport extends MultiplexBaseTransport{
public WriterThread(FileDescriptor fileDescriptor) {
//Log.d(TAG, "Creating a Connected - Write Thread");
OutputStream tmpOut = null;
- setName("SDL Router BT Write Thread");
+ setName("SDL USB Write Thread");
// Get the Usb output streams
mmOutStream = new FileOutputStream(fileDescriptor);
-
-
}
+
/**
* Write to the connected OutStream.
* @param buffer The bytes to write
@@ -302,6 +322,9 @@ public class MultiplexUsbTransport extends MultiplexBaseTransport{
}
//This would be a good spot to log out all bytes received
mmOutStream.write(buffer, offset, count);
+ if(connectionSuccessful == null){
+ connectionSuccessful = false;
+ }
//Log.w(TAG, "Wrote out to device: bytes = "+ count);
} catch (IOException|NullPointerException e) { // STRICTLY to catch mmOutStream NPE
// Exception during write
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 f6a6a8736..e0f71a121 100644
--- a/sdl_android/src/main/java/com/smartdevicelink/transport/SdlRouterService.java
+++ b/sdl_android/src/main/java/com/smartdevicelink/transport/SdlRouterService.java
@@ -47,6 +47,7 @@ import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.Vector;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
@@ -80,6 +81,7 @@ import android.content.pm.ResolveInfo;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
+import android.os.BatteryManager;
import android.os.Build;
import android.os.Bundle;
import android.os.DeadObjectException;
@@ -92,6 +94,7 @@ import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.Parcelable;
import android.os.RemoteException;
+import android.support.annotation.NonNull;
import android.util.Log;
import android.util.SparseArray;
import android.util.SparseIntArray;
@@ -136,7 +139,7 @@ public class SdlRouterService extends Service{
/**
* <b> NOTE: DO NOT MODIFY THIS UNLESS YOU KNOW WHAT YOU'RE DOING.</b>
*/
- protected static final int ROUTER_SERVICE_VERSION_NUMBER = 8;
+ protected static final int ROUTER_SERVICE_VERSION_NUMBER = 9;
private static final String ROUTER_SERVICE_PROCESS = "com.smartdevicelink.router";
@@ -207,7 +210,7 @@ public class SdlRouterService extends Service{
private boolean startSequenceComplete = false;
private ExecutorService packetExecutor = null;
- HashMap<TransportType, PacketWriteTaskMaster> packetWriteTaskMasterMap = null;
+ ConcurrentHashMap<TransportType, PacketWriteTaskMaster> packetWriteTaskMasterMap = null;
/**
@@ -819,12 +822,14 @@ public class SdlRouterService extends Service{
@SuppressWarnings("Convert2Diamond")
static class UsbTransferHandler extends Handler {
final WeakReference<SdlRouterService> provider;
+ Runnable usbCableDisconnectRunnable;
+ BroadcastReceiver usbCableDisconnectBroadcastReceiver;
public UsbTransferHandler(SdlRouterService provider){
this.provider = new WeakReference<SdlRouterService>(provider);
}
- @Override
+ @Override
public void handleMessage(Message msg) {
if(this.provider.get() == null){
return;
@@ -832,14 +837,51 @@ public class SdlRouterService extends Service{
SdlRouterService service = this.provider.get();
switch(msg.what){
case TransportConstants.USB_CONNECTED_WITH_DEVICE:
+ service.enterForeground("Opening USB connection",FOREGROUND_TIMEOUT,false);
+ service.resetForegroundTimeOut(FOREGROUND_TIMEOUT);
int flags = msg.arg1;
- ParcelFileDescriptor parcelFileDescriptor = (ParcelFileDescriptor)msg.obj;
- if(parcelFileDescriptor != null){
- //New USB constructor with PFD
- service.usbTransport = new MultiplexUsbTransport(parcelFileDescriptor,service.usbHandler,msg.getData());
- service.usbTransport.start();
+ ParcelFileDescriptor parcelFileDescriptor = (ParcelFileDescriptor)msg.obj;
+
+ if(parcelFileDescriptor != null) {
+ //New USB constructor with PFD
+ service.usbTransport = new MultiplexUsbTransport(parcelFileDescriptor, service.usbHandler, msg.getData());
+
+
+ usbCableDisconnectRunnable = new Runnable() {
+ @Override
+ public void run() {
+ if(provider.get() != null && AndroidTools.isUSBCableConnected(provider.get().getApplicationContext())) {
+ provider.get().usbTransport.start();
+ }
+ }
+ };
+ postDelayed(usbCableDisconnectRunnable, 4000);
+
+
+ // Register a BroadcastReceiver to stop USB transport if USB cable got disconnected
+ if (provider.get() != null) {
+ usbCableDisconnectBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ int plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
+ if (provider.get()!= null && plugged != BatteryManager.BATTERY_PLUGGED_AC && plugged != BatteryManager.BATTERY_PLUGGED_USB) {
+ try {
+ provider.get().getApplicationContext().unregisterReceiver(usbCableDisconnectBroadcastReceiver);
+ } catch (Exception e){ }
+ removeCallbacks(usbCableDisconnectRunnable);
+ if (provider.get().usbTransport != null) {
+ provider.get().usbTransport.stop();
+ }
+ }
+ }
+ };
+ provider.get().getApplicationContext().registerReceiver(usbCableDisconnectBroadcastReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
}
+
+
+ }
+
if(msg.replyTo!=null){
Message message = Message.obtain();
message.what = TransportConstants.ROUTER_USB_ACC_RECEIVED;
@@ -849,12 +891,7 @@ public class SdlRouterService extends Service{
e.printStackTrace();
}
}
- if(service.isPrimaryTransportConnected() && ((TransportConstants.ROUTER_STATUS_FLAG_TRIGGER_PING & flags) == TransportConstants.ROUTER_STATUS_FLAG_TRIGGER_PING)){
- if(service.pingIntent == null){
- service.initPingIntent();
- }
- AndroidTools.sendExplicitBroadcast(service.getApplicationContext(),service.pingIntent, null);
- }
+
break;
case TransportConstants.ALT_TRANSPORT_CONNECTED:
break;
@@ -1319,7 +1356,14 @@ public class SdlRouterService extends Service{
foregroundTimeoutRunnable = new Runnable() {
@Override
public void run() {
- exitForeground();
+ if(!getConnectedTransports().isEmpty()){
+ // Updates notification to one of still connected transport
+ enterForeground(createConnectedNotificationText(),0,true);
+ return;
+ }else{
+ exitForeground();//Leave our foreground state as we don't have a connection
+
+ }
}
};
} else {
@@ -1392,7 +1436,8 @@ public class SdlRouterService extends Service{
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
builder.setContentIntent(pendingIntent);
- if(chronometerLength > 0) {
+ if(chronometerLength > 0 && android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ //The countdown method is only available in SDKs >= 24
builder.setWhen(chronometerLength + System.currentTimeMillis());
builder.setUsesChronometer(true);
builder.setChronometerCountDown(true);
@@ -1607,7 +1652,7 @@ public class SdlRouterService extends Service{
enterForeground(createConnectedNotificationText(),0,true);
if(packetWriteTaskMasterMap == null){
- packetWriteTaskMasterMap = new HashMap<>();
+ packetWriteTaskMasterMap = new ConcurrentHashMap<>();
}
TransportType type = record.getType();
@@ -1615,6 +1660,7 @@ public class SdlRouterService extends Service{
if(packetWriteTaskMaster!=null){
packetWriteTaskMaster.close();
+ packetWriteTaskMaster.alert();
}
packetWriteTaskMaster = new PacketWriteTaskMaster();
packetWriteTaskMaster.setTransportType(type);
@@ -1670,6 +1716,9 @@ public class SdlRouterService extends Service{
public void onTransportDisconnected(TransportRecord record){
cachedModuleVersion = -1; //Reset our cached version
+ //Stop any current pings being sent before the proper state can be determined.
+ stopClientPings();
+
if(registeredApps != null && !registeredApps.isEmpty()){
Message message = Message.obtain();
message.what = TransportConstants.HARDWARE_CONNECTION_EVENT;
@@ -1686,7 +1735,61 @@ public class SdlRouterService extends Service{
message.setData(bundle);
notifyClients(message);
+
+ synchronized (REGISTERED_APPS_LOCK) {
+ Collection<RegisteredApp> apps = registeredApps.values();
+ for (RegisteredApp app : apps) {
+ app.unregisterTransport(-1,record.getType());
+
+ }
+ }
}
+ //Remove and close the packet task master assigned to this transport
+ if(packetWriteTaskMasterMap != null
+ && record != null
+ && packetWriteTaskMasterMap.containsKey(record.getType())){
+ PacketWriteTaskMaster master = packetWriteTaskMasterMap.remove(record.getType());
+ if(master != null){
+ master.close();
+ master.alert();
+ }
+ }
+ //Ensure the associated transport is dealt with
+ switch (record.getType()){
+ case BLUETOOTH:
+ synchronized(SESSION_LOCK){
+ if(bluetoothSessionMap!= null){
+ bluetoothSessionMap.clear();
+ }
+ }
+ if(!connectAsClient ){
+ if(!legacyModeEnabled && !closing){
+ initBluetoothSerialService();
+ }
+ }
+ break;
+ case USB:
+ if(usbTransport != null){
+ usbTransport = null;
+ }
+ synchronized(SESSION_LOCK){
+ if(usbSessionMap!= null){
+ usbSessionMap.clear();
+ }
+ }
+ break;
+ case TCP:
+ if(tcpTransport != null){
+ tcpTransport = null;
+ }
+ synchronized(SESSION_LOCK){
+ if(tcpSessionMap!=null){
+ tcpSessionMap.clear();
+ }
+ }
+ break;
+ }
+
if(!getConnectedTransports().isEmpty()){
// Updates notification to one of still connected transport
enterForeground(createConnectedNotificationText(),0,true);
@@ -1701,32 +1804,12 @@ public class SdlRouterService extends Service{
if(altTransportService!=null){ //If we still have an alt transport open, then we don't need to tell the clients to close
return;
}
- switch (record.getType()){
- case BLUETOOTH:
- if(!connectAsClient ){
- if(!legacyModeEnabled && !closing){
- initBluetoothSerialService();
- }
- }
- break;
- case USB:
- break;
- case TCP:
- break;
- }
- Log.e(TAG, "Notifying client service of hardware disconnect.");
- stopClientPings();
+ Log.e(TAG, "Notifying client service of hardware disconnect.");
- PacketWriteTaskMaster packetWriteTaskMaster = packetWriteTaskMasterMap.remove(record.getType());
- if(packetWriteTaskMaster!=null){
- packetWriteTaskMaster.close();
- }
-
//We've notified our clients, less clean up the mess now.
synchronized(SESSION_LOCK){
- this.bluetoothSessionMap.clear();
this.sessionHashIdMap.clear();
}
synchronized(REGISTERED_APPS_LOCK){
@@ -2855,7 +2938,7 @@ public class SdlRouterService extends Service{
int priorityForBuffingMessage;
DeathRecipient deathNote = null;
//Packet queue vars
- final HashMap<TransportType, PacketWriteTaskBlockingQueue> queues;
+ final ConcurrentHashMap<TransportType, PacketWriteTaskBlockingQueue> queues;
Handler queueWaitHandler;
Runnable queueWaitRunnable = null;
boolean queuePaused = false;
@@ -2873,7 +2956,7 @@ public class SdlRouterService extends Service{
this.appId = appId;
this.messenger = messenger;
this.sessionIds = new Vector<Long>();
- this.queues = new HashMap<>();
+ this.queues = new ConcurrentHashMap<>();
queueWaitHandler = new Handler();
registeredTransports = new SparseArray<ArrayList<TransportType>>();
awaitingSession = new Vector<>();
@@ -2891,7 +2974,7 @@ public class SdlRouterService extends Service{
this.appId = appId;
this.messenger = messenger;
this.sessionIds = new Vector<Long>();
- this.queues = new HashMap<>();
+ this.queues = new ConcurrentHashMap<>();
queueWaitHandler = new Handler();
registeredTransports = new SparseArray<ArrayList<TransportType>>();
awaitingSession = new Vector<>();
@@ -3049,14 +3132,25 @@ public class SdlRouterService extends Service{
}
}
- protected boolean unregisterTransport(int sessionId, TransportType transportType){
+ protected boolean unregisterTransport(int sessionId, @NonNull TransportType transportType){
+ if(queues != null && queues.containsValue(transportType)){
+ PacketWriteTaskBlockingQueue queue = queues.remove(transportType);
+ queue.clear();
+ }
synchronized (TRANSPORT_LOCK){
- if(this.registeredTransports.indexOfKey(sessionId) >= 0){
+ if(sessionId == -1){
+ int size = this.registeredTransports.size();
+ for(int i = 0; i <size; i++){
+ this.registeredTransports.valueAt(i).remove(transportType);
+ }
+ return true;
+ }else if(this.registeredTransports.indexOfKey(sessionId) >= 0){
return this.registeredTransports.get(sessionId).remove(transportType);
}else{
return false;
}
}
+
}
protected void unregisterAllTransports(int sessionId){
@@ -3066,7 +3160,7 @@ public class SdlRouterService extends Service{
}else if(sessionId == -1){
int size = this.registeredTransports.size();
for(int i = 0; i <size; i++){
- this.registeredTransports.get(i).clear();
+ this.registeredTransports.valueAt(i).clear();
}
}
}
@@ -3347,6 +3441,7 @@ public class SdlRouterService extends Service{
public PacketWriteTaskMaster(){
this.setName("PacketWriteTaskMaster");
+ this.setDaemon(true);
}
protected void setTransportType(TransportType transportType){
this.transportType = transportType;
diff --git a/sdl_android/src/main/java/com/smartdevicelink/transport/TransportBroker.java b/sdl_android/src/main/java/com/smartdevicelink/transport/TransportBroker.java
index 21e9fedef..7bdd10857 100644
--- a/sdl_android/src/main/java/com/smartdevicelink/transport/TransportBroker.java
+++ b/sdl_android/src/main/java/com/smartdevicelink/transport/TransportBroker.java
@@ -118,6 +118,7 @@ public class TransportBroker {
Log.d(TAG, "Unbound from service " + className.getClassName());
routerServiceMessenger = null;
registeredWithRouterService = false;
+ unBindFromRouterService();
isBound = false;
onHardwareDisconnected(null, null);
}
@@ -446,6 +447,7 @@ public class TransportBroker {
routerServiceMessenger = null;
queuedOnTransportConnect = null;
unBindFromRouterService();
+ isBound = false;
}
}
@@ -464,12 +466,13 @@ public class TransportBroker {
}
}
- private void unBindFromRouterService() {
+ private synchronized void unBindFromRouterService() {
try {
- if (getContext() != null && routerConnection != null) {
+ if (isBound && getContext() != null && routerConnection != null) {
getContext().unbindService(routerConnection);
+ isBound = false;
} else {
- Log.w(TAG, "Unable to unbind from router service, context was null");
+ Log.w(TAG, "Unable to unbind from router service. bound? " + isBound + " context? " + (getContext()!=null) + " router connection?" + (routerConnection != null));
}
} catch (IllegalArgumentException e) {
@@ -652,6 +655,10 @@ public class TransportBroker {
@SuppressLint("InlinedApi")
private boolean sendBindingIntent() {
+ if(this.isBound){
+ Log.e(TAG, "Already bound");
+ return false;
+ }
if (this.routerPackage != null && this.routerClassName != null) {
Log.d(TAG, "Sending bind request to " + this.routerPackage + " - " + this.routerClassName);
Intent bindingIntent = new Intent();
diff --git a/sdl_android/src/main/java/com/smartdevicelink/transport/USBAccessoryAttachmentActivity.java b/sdl_android/src/main/java/com/smartdevicelink/transport/USBAccessoryAttachmentActivity.java
index 4b878c2aa..878715147 100644
--- a/sdl_android/src/main/java/com/smartdevicelink/transport/USBAccessoryAttachmentActivity.java
+++ b/sdl_android/src/main/java/com/smartdevicelink/transport/USBAccessoryAttachmentActivity.java
@@ -98,7 +98,6 @@ public class USBAccessoryAttachmentActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- checkUsbAccessoryIntent("Create");
}
@Override
@@ -107,7 +106,16 @@ public class USBAccessoryAttachmentActivity extends Activity {
checkUsbAccessoryIntent("Resume");
}
- private void checkUsbAccessoryIntent(String sourceAction) {
+ @Override
+ protected void onNewIntent(Intent intent) {
+ super.onNewIntent(intent);
+ this.setIntent(intent);
+ }
+
+ private synchronized void checkUsbAccessoryIntent(String sourceAction) {
+ if(usbAccessory != null){
+ return;
+ }
final Intent intent = getIntent();
String action = intent.getAction();
Log.d(TAG, sourceAction + " with action: " + action);
@@ -118,8 +126,16 @@ public class USBAccessoryAttachmentActivity extends Activity {
wakeUpRouterService(getApplicationContext());
+ }else{
+ finish();
}
+ }
+ @Override
+ protected void onDestroy() {
+ usbAccessory = null;
+ permissionGranted = null;
+ super.onDestroy();
}
@SuppressWarnings("deprecation")
diff --git a/sdl_android/src/main/java/com/smartdevicelink/transport/UsbTransferProvider.java b/sdl_android/src/main/java/com/smartdevicelink/transport/UsbTransferProvider.java
index 9657a2c27..1479fa9e1 100644
--- a/sdl_android/src/main/java/com/smartdevicelink/transport/UsbTransferProvider.java
+++ b/sdl_android/src/main/java/com/smartdevicelink/transport/UsbTransferProvider.java
@@ -40,6 +40,7 @@ import android.content.Intent;
import android.content.ServiceConnection;
import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbManager;
+import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
@@ -51,6 +52,8 @@ import android.os.RemoteException;
import android.util.Log;
import com.smartdevicelink.util.AndroidTools;
+
+import java.io.IOException;
import java.lang.ref.WeakReference;
@TargetApi(12)
@@ -103,12 +106,13 @@ public class UsbTransferProvider {
if(context == null || service == null || usbAccessory == null){
throw new IllegalStateException("Supplied params are not correct. Context == null? "+ (context==null) + " ComponentName == null? " + (service == null) + " Usb Accessory == null? " + usbAccessory);
}
- this.context = context;
- this.routerService = service;
- this.callback = callback;
- this.clientMessenger = new Messenger(new ClientHandler(this));
- usbPfd = getFileDescriptor(usbAccessory);
- if(usbPfd != null){
+ usbPfd = getFileDescriptor(usbAccessory, context);
+ if(usbPfd != null && usbPfd.getFileDescriptor() != null && usbPfd.getFileDescriptor().valid()){
+ this.context = context;
+ this.routerService = service;
+ this.callback = callback;
+ this.clientMessenger = new Messenger(new ClientHandler(this));
+
usbInfoBundle = new Bundle();
usbInfoBundle.putString(MultiplexUsbTransport.MANUFACTURER, usbAccessory.getManufacturer());
usbInfoBundle.putString(MultiplexUsbTransport.MODEL, usbAccessory.getModel());
@@ -117,20 +121,28 @@ public class UsbTransferProvider {
usbInfoBundle.putString(MultiplexUsbTransport.SERIAL, usbAccessory.getSerial());
usbInfoBundle.putString(MultiplexUsbTransport.DESCRIPTION, usbAccessory.getDescription());
checkIsConnected();
+ }else{
+ Log.e(TAG, "Unable to open accessory");
+ clientMessenger = null;
+ if(callback != null){
+ callback.onUsbTransferUpdate(false);
+ }
}
}
@SuppressLint("NewApi")
- private ParcelFileDescriptor getFileDescriptor(UsbAccessory accessory) {
- try {
- UsbManager manager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
+ private ParcelFileDescriptor getFileDescriptor(UsbAccessory accessory, Context context) {
+ if (AndroidTools.isUSBCableConnected(context)) {
+ try {
+ UsbManager manager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
- if (manager != null) {
- return manager.openAccessory(accessory);
+ if (manager != null) {
+ return manager.openAccessory(accessory);
+ }
+ } catch (Exception e) {
}
- }catch (Exception e){}
-
+ }
return null;
}
@@ -181,11 +193,19 @@ public class UsbTransferProvider {
}
private void finish(){
- if(callback != null){
- callback.onUsbTransferUpdate(true);
+ try {
+ usbPfd.close();
+ } catch (IOException e) {
+ e.printStackTrace();
}
+ usbPfd = null;
unBindFromService();
routerServiceMessenger =null;
+ context = null;
+ System.gc();
+ if(callback != null){
+ callback.onUsbTransferUpdate(true);
+ }
}
static class ClientHandler extends Handler {
diff --git a/sdl_android/src/main/java/com/smartdevicelink/util/AndroidTools.java b/sdl_android/src/main/java/com/smartdevicelink/util/AndroidTools.java
index 62f379031..4237845b7 100644
--- a/sdl_android/src/main/java/com/smartdevicelink/util/AndroidTools.java
+++ b/sdl_android/src/main/java/com/smartdevicelink/util/AndroidTools.java
@@ -35,11 +35,13 @@ package com.smartdevicelink.util;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
+import android.os.BatteryManager;
import com.smartdevicelink.transport.TransportConstants;
@@ -160,4 +162,15 @@ public class AndroidTools {
}
}
+ /**
+ * Checks if the usb cable is physically connected or not
+ * Note: the intent here is a sticky intent so registerReceiver is actually a synchronous call and doesn't register a receiver on each call
+ * @param context a context instance
+ * @return boolean value that represents whether the usb cable is physically connected or not
+ */
+ public static boolean isUSBCableConnected(Context context) {
+ Intent intent = context.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
+ int plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
+ return plugged == BatteryManager.BATTERY_PLUGGED_AC || plugged == BatteryManager.BATTERY_PLUGGED_USB;
+ }
}
diff --git a/sdl_android/src/main/res/values/sdl.xml b/sdl_android/src/main/res/values/sdl.xml
index ca8b15851..8ee8f70cb 100644
--- a/sdl_android/src/main/res/values/sdl.xml
+++ b/sdl_android/src/main/res/values/sdl.xml
@@ -2,7 +2,7 @@
<resources>
<string name="sdl_router_service_version_name" translatable="false">sdl_router_version</string>
- <integer name="sdl_router_service_version_value">8</integer>
+ <integer name="sdl_router_service_version_value">9</integer>
<string name="sdl_router_service_is_custom_name" translatable="false">sdl_custom_router</string>
</resources>