diff options
7 files changed, 239 insertions, 76 deletions
diff --git a/sdl_android_lib/src/com/smartdevicelink/SdlConnection/SdlConnection.java b/sdl_android_lib/src/com/smartdevicelink/SdlConnection/SdlConnection.java index 60d6e5362..3a4e74c3a 100644 --- a/sdl_android_lib/src/com/smartdevicelink/SdlConnection/SdlConnection.java +++ b/sdl_android_lib/src/com/smartdevicelink/SdlConnection/SdlConnection.java @@ -556,7 +556,6 @@ public class SdlConnection implements IProtocolListener, ITransportListener, ISt } catch (SdlException e) {
e.printStackTrace();
}
- ((MultiplexTransport)_transport).forceHardwareConnectEvent(TransportType.BLUETOOTH);
}
}else{ //The service must be null or already consumed. Let's see if we can find the connection that consumed it
for (SdlSession session : listenerList) {
@@ -734,12 +733,14 @@ public class SdlConnection implements IProtocolListener, ITransportListener, ISt ComponentName tempCompName = SdlBroadcastReceiver.consumeQueuedRouterService();
//Log.d(TAG, "Consumed component name: " +tempCompName );
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);
-
- if(!forced && multi.isDisconnecting() ){ //If we aren't able to force a connection it means the
+ if(!multi.getIsConnected() && multi.isDisconnecting() ){ //If we aren't able to force a connection it means the
//Log.d(TAG, "Recreating our multiplexing transport");
_transport = new MultiplexTransport(config,this);
- ((MultiplexTransport)_transport).forceHardwareConnectEvent(TransportType.BLUETOOTH);
+ try {
+ startTransport();
+ } catch (SdlException e) {
+ e.printStackTrace();
+ }
}//else{Log.w(TAG, "Guess we're just calling it a day");}
}else if(tempCompName!=null){
//We have a conflicting service request
@@ -754,7 +755,6 @@ public class SdlConnection implements IProtocolListener, ITransportListener, ISt } catch (SdlException e) {
e.printStackTrace();
}
- ((MultiplexTransport)_transport).forceHardwareConnectEvent(TransportType.BLUETOOTH);
}
}else if(_transport.getTransportType()==TransportType.BLUETOOTH
diff --git a/sdl_android_lib/src/com/smartdevicelink/transport/MultiplexTransport.java b/sdl_android_lib/src/com/smartdevicelink/transport/MultiplexTransport.java index 5556d9af1..e82bcd209 100644 --- a/sdl_android_lib/src/com/smartdevicelink/transport/MultiplexTransport.java +++ b/sdl_android_lib/src/com/smartdevicelink/transport/MultiplexTransport.java @@ -33,16 +33,6 @@ public class MultiplexTransport extends SdlTransport{ //brokerThread.start(); } - - public boolean forceHardwareConnectEvent(TransportType type){ - if(brokerThread!=null){ - brokerThread.onHardwareConnected(type); - return true; - } - Log.w(TAG, "Transport broker thread was null, nothing to force connect. Are we disconnecting? " + isDisconnecting); - return false; - - } public boolean isDisconnecting(){ return this.isDisconnecting; diff --git a/sdl_android_lib/src/com/smartdevicelink/transport/SdlBroadcastReceiver.java b/sdl_android_lib/src/com/smartdevicelink/transport/SdlBroadcastReceiver.java index 2d268edf0..1686285c9 100644 --- a/sdl_android_lib/src/com/smartdevicelink/transport/SdlBroadcastReceiver.java +++ b/sdl_android_lib/src/com/smartdevicelink/transport/SdlBroadcastReceiver.java @@ -199,31 +199,18 @@ public abstract class SdlBroadcastReceiver extends BroadcastReceiver{ /** * If a Router Service is running, this method determines if that service is connected to a device over some form of transport. * @param context A context to access Android system services through. If null is passed, this will always return false - * @return True if a transport connection is established, false otherwise. + * @param callback Use this callback to find out if the router service is connected or not. */ - public static boolean isTransportConnected(Context context){ + public static void requestTransportStatus(Context context, SdlRouterStatusProvider.ConnectedStatusCallback callback){ Log.d(TAG, "Checking to see if router service is transport connected"); if(context == null){ - return false; + if(callback!=null){ + callback.onConnectionStatusUpdate(false, context); + } } if(isRouterServiceRunning(context,false)){ //So there is a service up, let's see if it's connected - Context con; - try { - con = context.createPackageContext(runningBluetoothServicePackage.getPackageName(), 0); - if(con==null ){ - Log.w(TAG, "Unable to check for service connection. Returning false. "+runningBluetoothServicePackage); - return false; // =( well that sucks. - } - SharedPreferences pref = con.getSharedPreferences( - con.getPackageName()+TRANSPORT_GLOBAL_PREFS , 4); - boolean connected = pref.getBoolean(IS_TRANSPORT_CONNECTED, false); - // Log.w(TAG, "Is Connected? Returning " + connected); - return connected; - } catch (NameNotFoundException e) { - e.printStackTrace(); - return false; - } - + SdlRouterStatusProvider provider = new SdlRouterStatusProvider(context,runningBluetoothServicePackage,callback); + provider.checkIsConnected(); }else{ Log.w(TAG, "Router service isn't running, returning false."); if(BluetoothAdapter.getDefaultAdapter()!=null && BluetoothAdapter.getDefaultAdapter().isEnabled()){ @@ -232,9 +219,10 @@ public abstract class SdlBroadcastReceiver extends BroadcastReceiver{ serviceIntent.putExtra(TransportConstants.PING_ROUTER_SERVICE_EXTRA, true); context.sendBroadcast(serviceIntent); } + if(callback!=null){ + callback.onConnectionStatusUpdate(false, context); + } } - - return false; } diff --git a/sdl_android_lib/src/com/smartdevicelink/transport/SdlRouterService.java b/sdl_android_lib/src/com/smartdevicelink/transport/SdlRouterService.java index f48238c7f..9cfa8b7c7 100644 --- a/sdl_android_lib/src/com/smartdevicelink/transport/SdlRouterService.java +++ b/sdl_android_lib/src/com/smartdevicelink/transport/SdlRouterService.java @@ -102,7 +102,8 @@ public class SdlRouterService extends Service{ private static boolean connectAsClient = false; private static boolean closing = false; - private boolean isTarnsportConnected = false; + private boolean isTransportConnected = false; + private TransportType connectedTransportType = null; private static Context currentContext = null; private Handler versionCheckTimeOutHandler, altTransportTimerHandler; @@ -318,9 +319,10 @@ public class SdlRouterService extends Service{ pingClients(); Message message = Message.obtain(); message.what = TransportConstants.ROUTER_REGISTER_CLIENT_RESPONSE; + message.arg1 = TransportConstants.REGISTRATION_RESPONSE_SUCESS; long appId = receivedBundle.getLong(TransportConstants.APP_ID_EXTRA, -1); if(appId<0 || msg.replyTo == null){ - Log.w(TAG, "Unable to requster app as no id or messenger was included"); + Log.w(TAG, "Unable to register app as no id or messenger was included"); if(msg.replyTo!=null){ message.arg1 = TransportConstants.REGISTRATION_RESPONSE_DENIED_APP_ID_NOT_INCLUDED; try { @@ -354,11 +356,14 @@ public class SdlRouterService extends Service{ } } onAppRegistered(app); - + returnBundle = new Bundle(); - - if(MultiplexBluetoothTransport.currentlyConnectedDevice!=null){ - returnBundle.putString(CONNECTED_DEVICE_STRING_EXTRA_NAME, MultiplexBluetoothTransport.currentlyConnectedDevice); + //Add params if connected + if(SdlRouterService.this.isTransportConnected){ + returnBundle.putString(TransportConstants.HARDWARE_CONNECTED, SdlRouterService.this.connectedTransportType.name()); + if(MultiplexBluetoothTransport.currentlyConnectedDevice!=null){ + returnBundle.putString(CONNECTED_DEVICE_STRING_EXTRA_NAME, MultiplexBluetoothTransport.currentlyConnectedDevice); + } } if(!returnBundle.isEmpty()){ message.setData(returnBundle); @@ -369,7 +374,6 @@ public class SdlRouterService extends Service{ registeredApps.remove(appId); } } - break; case TransportConstants.ROUTER_UNREGISTER_CLIENT: long appIdToUnregister = receivedBundle.getLong(TransportConstants.APP_ID_EXTRA, -1); @@ -518,7 +522,6 @@ public class SdlRouterService extends Service{ && altTransportService.equals(msg.replyTo)){ //The same transport that was connected to the router service is now telling us it's disconnected. Let's inform clients and clear our saved messenger altTransportService = null; - storeConnectedStatus(false); onTransportDisconnected(TransportType.valueOf(receivedBundle.getString(TransportConstants.HARDWARE_DISCONNECTED))); shouldServiceRemainOpen(null); //this will close the service if bluetooth is not available } @@ -538,7 +541,6 @@ public class SdlRouterService extends Service{ altTransportTimerHandler = null; altTransportTimerRunnable = null; - storeConnectedStatus(true); //Let the alt transport know they are good to go retMsg.arg1 = TransportConstants.ROUTER_REGISTER_ALT_TRANSPORT_RESPONSE_SUCESS; onTransportConnected(TransportType.valueOf(receivedBundle.getString(TransportConstants.HARDWARE_CONNECTED))); @@ -574,6 +576,39 @@ public class SdlRouterService extends Service{ } }; + + /** + * Target we publish for alternative transport (USB) clients to send messages to RouterHandler. + */ + final Messenger routerStatusMessenger = new Messenger(new RouterStatusHandler()); + + /** + * Handler of incoming messages from an alternative transport (USB). + */ + class RouterStatusHandler extends Handler { + ClassLoader loader = getClass().getClassLoader(); + @Override + public void handleMessage(Message msg) { + switch(msg.what){ + case TransportConstants.ROUTER_STATUS_CONNECTED_STATE_REQUEST: + if(msg.replyTo==null){ + break; + } + Message message = Message.obtain(); + message.what = TransportConstants.ROUTER_STATUS_CONNECTED_STATE_RESPONSE; + message.arg1 = (isTransportConnected == true) ? 1 : 0; + try { + msg.replyTo.send(message); + } catch (RemoteException e) { + e.printStackTrace(); + } + break; + default: + Log.w(TAG, "Unsopported request: " + msg.what); + break; + } + } + }; /* ************************************************************************************************************************************** *********************************************** Life Cycle ************************************************************** @@ -592,6 +627,8 @@ public class SdlRouterService extends Service{ return this.altTransportMessenger.getBinder(); }else if(TransportConstants.BIND_REQUEST_TYPE_CLIENT.equals(requestType)){ return this.routerMessenger.getBinder(); + }else if(TransportConstants.BIND_REQUEST_TYPE_STATUS.equals(requestType)){ + return this.routerStatusMessenger.getBinder(); }else{ Log.w(TAG, "Uknown bind request type"); } @@ -689,7 +726,6 @@ public class SdlRouterService extends Service{ } closing = false; currentContext = getBaseContext(); - storeConnectedStatus(false); startVersionCheck(); Log.i(TAG, "SDL Router Service has been created"); @@ -945,7 +981,6 @@ public class SdlRouterService extends Service{ */ public void closeSelf(){ closing = true; - storeConnectedStatus(false); if(getBaseContext()!=null){ stopSelf(); }else{ @@ -978,7 +1013,7 @@ public class SdlRouterService extends Service{ } public void onTransportConnected(final TransportType type){ - isTarnsportConnected = true; + isTransportConnected = true; enterForeground(); if(packetWriteTaskMaster!=null){ packetWriteTaskMaster.close(); @@ -987,6 +1022,8 @@ public class SdlRouterService extends Service{ packetWriteTaskMaster = new PacketWriteTaskMaster(); packetWriteTaskMaster.start(); + connectedTransportType = type; + Intent startService = new Intent(); startService.setAction(START_SERVICE_ACTION); startService.putExtra(TransportConstants.START_ROUTER_SERVICE_SDL_ENABLED_EXTRA, true); @@ -995,6 +1032,23 @@ public class SdlRouterService extends Service{ startService.putExtra(TransportConstants.START_ROUTER_SERVICE_SDL_ENABLED_CMP_NAME, new ComponentName(this, this.getClass())); sendBroadcast(startService); //HARDWARE_CONNECTED + if(!(registeredApps== null || registeredApps.isEmpty())){ + //If we have clients + notifyClients(createHardwareConnectedMessage(type)); + } + } + + private Message createHardwareConnectedMessage(final TransportType type){ + Message message = Message.obtain(); + message.what = TransportConstants.HARDWARE_CONNECTION_EVENT; + Bundle bundle = new Bundle(); + bundle.putString(TransportConstants.HARDWARE_CONNECTED, type.name()); + if(MultiplexBluetoothTransport.currentlyConnectedDevice!=null){ + bundle.putString(CONNECTED_DEVICE_STRING_EXTRA_NAME, MultiplexBluetoothTransport.currentlyConnectedDevice); + } + message.setData(bundle); + return message; + } public void onTransportDisconnected(TransportType type){ @@ -1002,8 +1056,8 @@ public class SdlRouterService extends Service{ return; } Log.e(TAG, "Notifying client service of hardware disconnect."); - - isTarnsportConnected = false; + connectedTransportType = null; + isTransportConnected = false; stopClientPings(); exitForeground();//Leave our foreground state as we don't have a connection anymore @@ -1074,18 +1128,15 @@ public class SdlRouterService extends Service{ case MESSAGE_STATE_CHANGE: switch (msg.arg1) { case MultiplexBluetoothTransport.STATE_CONNECTED: - storeConnectedStatus(true); onTransportConnected(TransportType.BLUETOOTH); break; case MultiplexBluetoothTransport.STATE_CONNECTING: // Currently attempting to connect - update UI? break; case MultiplexBluetoothTransport.STATE_LISTEN: - storeConnectedStatus(false); break; case MultiplexBluetoothTransport.STATE_NONE: // We've just lost the connection - storeConnectedStatus(false); if(!connectAsClient ){ if(!legacyModeEnabled && !closing){ initBluetoothSerialService(); @@ -1423,17 +1474,6 @@ 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); - SharedPreferences.Editor editor = prefs.edit(); - editor.putBoolean(SdlBroadcastReceiver.IS_TRANSPORT_CONNECTED, isConnected); - editor.commit(); - } - /** * This method will set the last known bluetooth connection method that worked with this phone. * This helps speed up the process of connecting @@ -1774,7 +1814,7 @@ public class SdlRouterService extends Service{ private void startClientPings(){ synchronized(this){ - if(!isTarnsportConnected){ //If we aren't connected, bail + if(!isTransportConnected){ //If we aren't connected, bail return; } if(isPingingClients){ diff --git a/sdl_android_lib/src/com/smartdevicelink/transport/SdlRouterStatusProvider.java b/sdl_android_lib/src/com/smartdevicelink/transport/SdlRouterStatusProvider.java new file mode 100644 index 000000000..f36dcb2c0 --- /dev/null +++ b/sdl_android_lib/src/com/smartdevicelink/transport/SdlRouterStatusProvider.java @@ -0,0 +1,137 @@ +package com.smartdevicelink.transport; + +import java.lang.ref.WeakReference; + +import android.annotation.SuppressLint; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.Handler; +import android.os.IBinder; +import android.os.Message; +import android.os.Messenger; +import android.os.RemoteException; +import android.util.Log; + +public class SdlRouterStatusProvider { + + private static final String TAG = "SdlRouterStateProvider"; + + private Context context = null; + private boolean isBound = false; + ConnectedStatusCallback cb = null; + Messenger routerServiceMessenger = null; + private ComponentName routerService = null; + + final Messenger clientMessenger; + + private ServiceConnection routerConnection= new ServiceConnection() { + + public void onServiceConnected(ComponentName className, IBinder service) { + Log.d(TAG, "Bound to service " + className.toString()); + routerServiceMessenger = new Messenger(service); + isBound = true; + //So we just established our connection + //Register with router service + Message msg = Message.obtain(); + msg.what = TransportConstants.ROUTER_STATUS_CONNECTED_STATE_REQUEST; + msg.replyTo = clientMessenger; + try { + routerServiceMessenger.send(msg); + } catch (RemoteException e) { + e.printStackTrace(); + if(cb!=null){ + cb.onConnectionStatusUpdate(false, context); + } + } + } + + public void onServiceDisconnected(ComponentName className) { + Log.d(TAG, "UN-Bound from service " + className.getClassName()); + routerServiceMessenger = null; + isBound = false; + } + }; + + public SdlRouterStatusProvider(Context context, ComponentName service, ConnectedStatusCallback callback){ + if(context == null || service == null || callback == null){ + throw new IllegalStateException("Supplied params are not correct. Context == null? "+ (context==null) + " ComponentName == null? " + (service == null) + " ConnectedStatusListener == null? " + callback); + } + this.context = context; + this.routerService = service; + this.cb = callback; + this.clientMessenger = new Messenger(new ClientHandler(this)); + + } + + public void checkIsConnected(){ + if(!bindToService()){ + //We are unable to bind to service + cb.onConnectionStatusUpdate(false, context); + } + } + + public void cancel(){ + if(isBound){ + unBindFromService(); + } + } + + private boolean bindToService(){ + if(isBound){ + return true; + } + Intent bindingIntent = new Intent(); + bindingIntent.setClassName(this.routerService.getPackageName(), this.routerService.getClassName());//This sets an explicit intent + //Quickly make sure it's just up and running + context.startService(bindingIntent); + bindingIntent.setAction( TransportConstants.BIND_REQUEST_TYPE_STATUS); + return context.bindService(bindingIntent, routerConnection, Context.BIND_AUTO_CREATE); + } + + private void unBindFromService(){ + try{ + if(context!=null && routerConnection!=null){ + context.unbindService(routerConnection); + }else{ + Log.w(TAG, "Unable to unbind from router service, context was null"); + } + + }catch(IllegalArgumentException e){ + //This is ok + } + } + + private void handleRouterStatusConnectedResponse(int connectedStatus){ + if(cb!=null){ + cb.onConnectionStatusUpdate(connectedStatus == 1, context); + } + unBindFromService(); + routerServiceMessenger =null; + } + + static class ClientHandler extends Handler { + WeakReference<SdlRouterStatusProvider> provider; + + public ClientHandler(SdlRouterStatusProvider provider){ + this.provider = new WeakReference<SdlRouterStatusProvider>(provider); + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case TransportConstants.ROUTER_STATUS_CONNECTED_STATE_RESPONSE: + provider.get().handleRouterStatusConnectedResponse(msg.arg1); + break; + default: + break; + } + } + }; + + public interface ConnectedStatusCallback{ + public void onConnectionStatusUpdate(boolean connected, Context context); + } + +} diff --git a/sdl_android_lib/src/com/smartdevicelink/transport/TransportBroker.java b/sdl_android_lib/src/com/smartdevicelink/transport/TransportBroker.java index 90e066baf..c941c6d78 100644 --- a/sdl_android_lib/src/com/smartdevicelink/transport/TransportBroker.java +++ b/sdl_android_lib/src/com/smartdevicelink/transport/TransportBroker.java @@ -154,15 +154,12 @@ public class TransportBroker { case TransportConstants.REGISTRATION_RESPONSE_SUCESS: // yay! we have been registered. Now what? registeredWithRouterService = true; - if(bundle!=null && bundle.containsKey(TransportConstants.CONNECTED_DEVICE_STRING_EXTRA_NAME)){ - //Keep track if we actually get this - } - if(queuedOnTransportConnect!=null){ - onHardwareConnected(queuedOnTransportConnect); - queuedOnTransportConnect = null; - }else if(SdlBroadcastReceiver.isTransportConnected(getContext())){ - onHardwareConnected(null); //FIXME to include type - } + if(bundle !=null && bundle.containsKey(TransportConstants.HARDWARE_CONNECTED)){ + if(bundle.containsKey(TransportConstants.CONNECTED_DEVICE_STRING_EXTRA_NAME)){ + //Keep track if we actually get this + } + onHardwareConnected(TransportType.valueOf(bundle.getString(TransportConstants.HARDWARE_CONNECTED))); + } break; case TransportConstants.REGISTRATION_RESPONSE_DENIED_LEGACY_MODE_ENABLED: Log.d(TAG, "Denied registration because router is in legacy mode" ); @@ -252,6 +249,9 @@ public class TransportBroker { } if(bundle.containsKey(TransportConstants.HARDWARE_CONNECTED)){ + if(bundle!=null && bundle.containsKey(TransportConstants.CONNECTED_DEVICE_STRING_EXTRA_NAME)){ + //Keep track if we actually get this + } onHardwareConnected(TransportType.valueOf(bundle.getString(TransportConstants.HARDWARE_CONNECTED))); break; } diff --git a/sdl_android_lib/src/com/smartdevicelink/transport/TransportConstants.java b/sdl_android_lib/src/com/smartdevicelink/transport/TransportConstants.java index 00b7e54b0..5850c0144 100644 --- a/sdl_android_lib/src/com/smartdevicelink/transport/TransportConstants.java +++ b/sdl_android_lib/src/com/smartdevicelink/transport/TransportConstants.java @@ -53,6 +53,7 @@ public class TransportConstants { public static final String BIND_REQUEST_TYPE_CLIENT = "BIND_REQUEST_TYPE_CLIENT"; public static final String BIND_REQUEST_TYPE_ALT_TRANSPORT = "BIND_REQUEST_TYPE_ALT_TRANSPORT"; + public static final String BIND_REQUEST_TYPE_STATUS = "BIND_REQUEST_TYPE_STATUS"; public static final String PING_ROUTER_SERVICE_EXTRA = "ping.router.service"; @@ -190,6 +191,13 @@ public class TransportConstants { public static final int PACKET_SENDING_ERROR_UKNOWN = 0xFF; + /** + * Status binder + */ + + public static final int ROUTER_STATUS_CONNECTED_STATE_REQUEST = 0x01; + public static final int ROUTER_STATUS_CONNECTED_STATE_RESPONSE = 0x02; + |