diff options
author | Bilal Alsharifi <599206+bilal-alsharifi@users.noreply.github.com> | 2019-02-27 11:00:03 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-02-27 11:00:03 -0500 |
commit | 3a8dc4545c2a186fd80804097049e0c2284faac8 (patch) | |
tree | 223959216ce1a051848e3fe51d3724d585388677 | |
parent | 52b185e609b382b34917932f8b3ac9616a8d206f (diff) | |
parent | f2647ec517fcaa33eb3e12757fd310d7315309ce (diff) | |
download | sdl_android-3a8dc4545c2a186fd80804097049e0c2284faac8.tar.gz |
Merge pull request #933 from smartdevicelink/bugfix/usb_enhacements
usb enhacements
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> |