diff options
author | Joey Grover <joeygrover@gmail.com> | 2016-09-27 14:26:08 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-09-27 14:26:08 -0400 |
commit | 503249159fae9bb9e31b4a4d1ee2fc6a82c567cf (patch) | |
tree | 38083e31eb8bbff21006a21174af64891062c288 | |
parent | a5139a51cbc708d8ff4d1c64c3114f0d59f362e6 (diff) | |
parent | 3688c6c1e3d60df91e0a795f3820a2699930a32a (diff) | |
download | sdl_android-503249159fae9bb9e31b4a4d1ee2fc6a82c567cf.tar.gz |
Merge pull request #330 from smartdevicelink/feature/multiplexing_cleanup
Multiplexing cleanup
11 files changed, 350 insertions, 190 deletions
diff --git a/sdl_android_lib/src/com/smartdevicelink/SdlConnection/SdlConnection.java b/sdl_android_lib/src/com/smartdevicelink/SdlConnection/SdlConnection.java index e6472f279..c9a5c13f2 100644 --- a/sdl_android_lib/src/com/smartdevicelink/SdlConnection/SdlConnection.java +++ b/sdl_android_lib/src/com/smartdevicelink/SdlConnection/SdlConnection.java @@ -102,7 +102,6 @@ public class SdlConnection implements IProtocolListener, ITransportListener { cachedMultiConfig.setService(null);
}
enableLegacyMode(true,TransportType.BLUETOOTH); //We will use legacy bluetooth connection for this attempt
- Log.d(TAG, "Legacy transport : " + legacyTransportRequest);
}
}
@@ -110,7 +109,6 @@ public class SdlConnection implements IProtocolListener, ITransportListener { (transportConfig.getTransportType() == TransportType.MULTIPLEX)){
_transport = new MultiplexTransport((MultiplexTransportConfig)transportConfig,this);
}else if(isLegacyModeEnabled() && legacyTransportRequest == TransportType.BLUETOOTH){
- Log.d(TAG, "Creating legacy bluetooth connection");
_transport = new BTTransport(this, true);
}else if(transportConfig.getTransportType() == TransportType.BLUETOOTH){
_transport = new BTTransport(this,((BTTransportConfig)transportConfig).getKeepSocketActive());
@@ -529,22 +527,20 @@ public class SdlConnection implements IProtocolListener, ITransportListener { MultiplexTransport multi = ((MultiplexTransport)_transport);
MultiplexTransportConfig config = multi.getConfig();
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
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);
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
Log.w(TAG, "Conflicting services. Disconnecting from current and connecting to new");
- Log.w(TAG, "Old service " + config.getService().toShortString());
- Log.w(TAG, "New Serivce " + tempCompName.toString());
+ //Log.w(TAG, "Old service " + config.getService().toShortString());
+ //Log.w(TAG, "New Serivce " + tempCompName.toString());
multi.disconnect();
config.setService(tempCompName);
_transport = new MultiplexTransport(config,this);
diff --git a/sdl_android_lib/src/com/smartdevicelink/transport/MultiplexBluetoothTransport.java b/sdl_android_lib/src/com/smartdevicelink/transport/MultiplexBluetoothTransport.java index 08fe98586..95746b05a 100644 --- a/sdl_android_lib/src/com/smartdevicelink/transport/MultiplexBluetoothTransport.java +++ b/sdl_android_lib/src/com/smartdevicelink/transport/MultiplexBluetoothTransport.java @@ -49,7 +49,7 @@ public class MultiplexBluetoothTransport { private static final String TAG = "Bluetooth Transport"; private static final UUID SERVER_UUID= new UUID(0x936DA01F9ABD4D9DL, 0x80C702AF85C822A8L); // Name for the SDP record when creating server socket - private static final String NAME_SECURE =" SdlProxy";// = "LIVIO_CONNECT"; + private static final String NAME_SECURE =" SdlRouterService"; protected static final String SHARED_PREFS = "sdl.bluetoothprefs"; @@ -696,7 +696,7 @@ public class MultiplexBluetoothTransport { //Log.d(TAG, "Creating a Connected - Write Thread"); mmSocket = socket; OutputStream tmpOut = null; - setName(" Livio Bluetooth Write Thread"); + setName("SDL Router BT Write Thread"); // Get the BluetoothSocket input and output streams try { tmpOut = socket.getOutputStream(); @@ -731,7 +731,6 @@ public class MultiplexBluetoothTransport { public synchronized void cancel() { try { - Log.d(TAG, "Calling Cancel in the write thread"); if(mmOutStream!=null){ mmOutStream.flush(); mmOutStream.close(); @@ -756,7 +755,7 @@ public class MultiplexBluetoothTransport { //Log.d(TAG, "Creating a Connected - Read Thread"); mmSocket = socket; InputStream tmpIn = null; - setName(" Livio Bluetooth Read Thread"); + setName("SDL Router BT Read Thread"); // Get the BluetoothSocket input and output streams try { tmpIn = socket.getInputStream(); diff --git a/sdl_android_lib/src/com/smartdevicelink/transport/MultiplexTransport.java b/sdl_android_lib/src/com/smartdevicelink/transport/MultiplexTransport.java index e82bcd209..39c401e1f 100644 --- a/sdl_android_lib/src/com/smartdevicelink/transport/MultiplexTransport.java +++ b/sdl_android_lib/src/com/smartdevicelink/transport/MultiplexTransport.java @@ -15,7 +15,7 @@ import com.smartdevicelink.transport.enums.TransportType; public class MultiplexTransport extends SdlTransport{ private final static String TAG = "Multiplex Transport"; - private String sComment = "I'm_a_little_teapot"; + private String sComment = "Multiplexing"; TransportBrokerThread brokerThread; protected boolean isDisconnecting = false; @@ -213,7 +213,7 @@ public class MultiplexTransport extends SdlTransport{ public void run() { Looper.prepare(); - if(broker==null){Log.d("JOEY", "Starting broker"); + if(broker==null){ synchronized(this){ initTransportBroker(); if(queueStart){ @@ -228,7 +228,6 @@ public class MultiplexTransport extends SdlTransport{ } threadLooper = Looper.myLooper(); Looper.loop(); - Log.i(TAG, "Looper has finished. Thread should be sutting down"); } @@ -242,9 +241,8 @@ public class MultiplexTransport extends SdlTransport{ Log.d(TAG, "On transport connected..."); if(!connected){ connected = true; - Log.d(TAG, "Handling transport connected"); handleTransportConnected(); - }else{Log.d(TAG, "Already connected");} + }//else{Log.d(TAG, "Already connected");} return true; }else{ try{ diff --git a/sdl_android_lib/src/com/smartdevicelink/transport/RouterServiceValidator.java b/sdl_android_lib/src/com/smartdevicelink/transport/RouterServiceValidator.java index 5809a19aa..3c5b71c5e 100644 --- a/sdl_android_lib/src/com/smartdevicelink/transport/RouterServiceValidator.java +++ b/sdl_android_lib/src/com/smartdevicelink/transport/RouterServiceValidator.java @@ -35,7 +35,7 @@ import com.smartdevicelink.util.HttpRequestTask.HttpRequestTaskCallback; * */ public class RouterServiceValidator { - private static final String TAG = "PackageCheckUtl"; + private static final String TAG = "RSVP"; public static final String ROUTER_SERVICE_PACKAGE = "com.sdl.router"; private static final String REQUEST_PREFIX = "https://woprjr.smartdevicelink.com/api/1/applications/queryTrustedRouters"; @@ -116,7 +116,7 @@ public class RouterServiceValidator { } } - Log.d(TAG, "Checking app package: " + service.getClassName()); + //Log.d(TAG, "Checking app package: " + service.getClassName()); packageName = this.appPackageForComponentName(service, pm); @@ -328,10 +328,9 @@ public class RouterServiceValidator { intent.setAction("sdl.router.startservice"); List<ResolveInfo> infoList = packageManager.queryBroadcastReceivers(intent, 0); if(infoList!=null){ - Log.i(TAG, "Number of SDL apps: " + infoList.size()); String packageName; for(ResolveInfo info : infoList){ - Log.i(TAG, "SDL apps: " + info.activityInfo.packageName); + //Log.i(TAG, "SDL apps: " + info.activityInfo.packageName); packageName = info.activityInfo.packageName; try { apps.add(new SdlApp(packageName,packageManager.getPackageInfo(packageName,0).versionCode)); @@ -362,7 +361,6 @@ public class RouterServiceValidator { } 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; return false; @@ -393,15 +391,13 @@ public class RouterServiceValidator { try {object.put(JSON_PUT_ARRAY_TAG, array);} catch (JSONException e) {e.printStackTrace();} - Log.d(TAG, "Request of apps: " + object.toString()); - if (cb == null) { cb = new HttpRequestTaskCallback() { @Override public void httpCallComplete(String response) { // Might want to check if this list is ok - Log.d(TAG, "APPS! " + response); + //Log.d(TAG, "APPS! " + response); setTrustedList(context, response); pendingListRefresh = false; } diff --git a/sdl_android_lib/src/com/smartdevicelink/transport/SdlBroadcastReceiver.java b/sdl_android_lib/src/com/smartdevicelink/transport/SdlBroadcastReceiver.java index 1686285c9..ae07046c5 100644 --- a/sdl_android_lib/src/com/smartdevicelink/transport/SdlBroadcastReceiver.java +++ b/sdl_android_lib/src/com/smartdevicelink/transport/SdlBroadcastReceiver.java @@ -1,6 +1,8 @@ package com.smartdevicelink.transport; import java.util.Locale; +import java.util.Vector; +import java.util.concurrent.ConcurrentLinkedQueue; import android.app.ActivityManager; import android.app.ActivityManager.RunningServiceInfo; @@ -9,8 +11,6 @@ import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; -import android.content.SharedPreferences; -import android.content.pm.PackageManager.NameNotFoundException; import android.util.Log; public abstract class SdlBroadcastReceiver extends BroadcastReceiver{ @@ -29,7 +29,7 @@ public abstract class SdlBroadcastReceiver extends BroadcastReceiver{ public static final String TRANSPORT_GLOBAL_PREFS = "SdlTransportPrefs"; public static final String IS_TRANSPORT_CONNECTED = "isTransportConnected"; - public static ComponentName runningBluetoothServicePackage = null; + public static Vector<ComponentName> runningBluetoothServicePackage = null; @SuppressWarnings("rawtypes") private static Class localRouterClass; @@ -72,15 +72,15 @@ public abstract class SdlBroadcastReceiver extends BroadcastReceiver{ String packageName = intent.getStringExtra(TransportConstants.START_ROUTER_SERVICE_SDL_ENABLED_APP_PACKAGE); ComponentName componentName = intent.getParcelableExtra(TransportConstants.START_ROUTER_SERVICE_SDL_ENABLED_CMP_NAME); if(componentName!=null){ - Log.v(TAG, "SDL enabled by router service from " + packageName + " compnent package " + componentName.getPackageName() + " - " + componentName.getClassName()); + //Log.v(TAG, "SDL enabled by router service from " + packageName + " compnent package " + componentName.getPackageName() + " - " + componentName.getClassName()); RouterServiceValidator vlad = new RouterServiceValidator(context,componentName); if(vlad.validate()){ - Log.d(TAG, "Router service trusted!"); + //Log.d(TAG, "Router service trusted!"); queuedService = componentName; 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()); + Log.w(TAG, "RouterService was not trusted. Ignoring intent from : "+ componentName.getClassName()); } } @@ -93,7 +93,6 @@ public abstract class SdlBroadcastReceiver extends BroadcastReceiver{ return; }else if(intent.getBooleanExtra(TransportConstants.PING_ROUTER_SERVICE_EXTRA, false)){ //We were told to wake up our router services - Log.d(TAG, "Starting router service off ping"); boolean altServiceWake = intent.getBooleanExtra(TransportConstants.BIND_REQUEST_TYPE_ALT_TRANSPORT, false); didStart = wakeUpRouterService(context, false,altServiceWake ); @@ -113,7 +112,6 @@ public abstract class SdlBroadcastReceiver extends BroadcastReceiver{ return; }else if(state == BluetoothAdapter.STATE_TURNING_ON){ //We started bluetooth, we should check for a new valid router list - Log.d(TAG, "Attempting to get list of approved router services"); RouterServiceValidator.createTrustedListRequest(context,true); } } @@ -121,7 +119,6 @@ public abstract class SdlBroadcastReceiver extends BroadcastReceiver{ if(localRouterClass!=null){ //If there is a supplied router service lets run some logic regarding starting one if(!didStart){ - Log.d(TAG, "Waking up router service"); didStart = wakeUpRouterService(context, true,false); } @@ -138,10 +135,8 @@ public abstract class SdlBroadcastReceiver extends BroadcastReceiver{ } private boolean wakeUpRouterService(Context context, boolean ping, boolean altTransportWake){ - Log.d(TAG, "Waking up router service"); if(!isRouterServiceRunning(context, ping)){ //If there isn't a service running we should try to start one - Log.i(TAG, "Attempting to start an instance of the Router Service"); //The under class should have implemented this.... //So let's start up our service since no copy is running @@ -152,18 +147,21 @@ public abstract class SdlBroadcastReceiver extends BroadcastReceiver{ context.startService(serviceIntent); return true; }else{ - Log.i(TAG, "An instance of the Router Service is already running"); - if(altTransportWake){ + if(altTransportWake && runningBluetoothServicePackage!=null && runningBluetoothServicePackage.size()>0){ Intent serviceIntent = new Intent(); - serviceIntent.setComponent(runningBluetoothServicePackage); serviceIntent.setAction(TransportConstants.BIND_REQUEST_TYPE_ALT_TRANSPORT); - context.startService(serviceIntent); + //context.startService(serviceIntent); + for(ComponentName compName: runningBluetoothServicePackage){ + serviceIntent.setComponent(compName); + context.startService(serviceIntent); + + } return true; } return false; } } - + /** * Determines if an instance of the Router Service is currently running on the device. * @param context A context to access Android system services through. @@ -175,13 +173,18 @@ public abstract class SdlBroadcastReceiver extends BroadcastReceiver{ Log.e(TAG, "Can't look for router service, context supplied was null"); return false; } - Log.d(TAG, "Looking for Service: "+ SDL_ROUTER_SERVICE_CLASS_NAME); ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); + if(runningBluetoothServicePackage==null){ + runningBluetoothServicePackage = new Vector<ComponentName>(); + }else{ + runningBluetoothServicePackage.clear(); + } 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(Locale.US).contains(SDL_ROUTER_SERVICE_CLASS_NAME)) { - runningBluetoothServicePackage = service.service; //Store which instance is running + + runningBluetoothServicePackage.add(service.service); //Store which instance is running if(pingService){ Intent intent = new Intent(); intent.setClassName(service.service.getPackageName(), service.service.getClassName()); @@ -197,20 +200,63 @@ public abstract class SdlBroadcastReceiver extends BroadcastReceiver{ } /** + * This call will reach out to all SDL related router services to check if they're connected. If a the router service is connected, it will react by pinging all clients. This receiver will then + * receive that ping and if the router service is trusted, the onSdlEnabled method will be called. + * @param context + */ + public static void queryForConnectedService(Context context){ + //Leverage existing call. Include ping bit + requestTransportStatus(context,null,true); + } + /** * 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 * @param callback Use this callback to find out if the router service is connected or not. */ - public static void requestTransportStatus(Context context, SdlRouterStatusProvider.ConnectedStatusCallback callback){ - Log.d(TAG, "Checking to see if router service is transport connected"); + public static void requestTransportStatus(Context context, final SdlRouterStatusProvider.ConnectedStatusCallback callback){ + requestTransportStatus(context,callback,false); + } + + private static void requestTransportStatus(Context context, final SdlRouterStatusProvider.ConnectedStatusCallback callback, final boolean triggerRouterServicePing){ if(context == null){ if(callback!=null){ - callback.onConnectionStatusUpdate(false, context); + callback.onConnectionStatusUpdate(false, null,context); } + return; } - if(isRouterServiceRunning(context,false)){ //So there is a service up, let's see if it's connected - SdlRouterStatusProvider provider = new SdlRouterStatusProvider(context,runningBluetoothServicePackage,callback); - provider.checkIsConnected(); + if(isRouterServiceRunning(context,false) && !runningBluetoothServicePackage.isEmpty()){ //So there is a service up, let's see if it's connected + final ConcurrentLinkedQueue<ComponentName> list = new ConcurrentLinkedQueue<ComponentName>(runningBluetoothServicePackage); + if(runningBluetoothServicePackage.size()>0){ //TODO for testing do this for all cases + final SdlRouterStatusProvider.ConnectedStatusCallback sdlBrCallback = new SdlRouterStatusProvider.ConnectedStatusCallback() { + + @Override + public void onConnectionStatusUpdate(boolean connected, ComponentName service,Context context) { + if(!connected && !list.isEmpty()){ + SdlRouterStatusProvider provider = new SdlRouterStatusProvider(context,list.poll(), this); + if(triggerRouterServicePing){provider.setFlags(TransportConstants.ROUTER_STATUS_FLAG_TRIGGER_PING); } + provider.checkIsConnected(); + }else{ + Log.d(TAG, service.getPackageName() + " is connected = " + connected); + if(callback!=null){ + callback.onConnectionStatusUpdate(connected, service,context); + } + list.clear(); + } + + } + }; + SdlRouterStatusProvider provider = new SdlRouterStatusProvider(context,list.poll(),sdlBrCallback); + if(triggerRouterServicePing){ + provider.setFlags(TransportConstants.ROUTER_STATUS_FLAG_TRIGGER_PING); + } + provider.checkIsConnected(); + }else{ //If only one service is running, just check that + SdlRouterStatusProvider provider = new SdlRouterStatusProvider(context,runningBluetoothServicePackage.get(0),callback); + if(triggerRouterServicePing){ + provider.setFlags(TransportConstants.ROUTER_STATUS_FLAG_TRIGGER_PING); + } + provider.checkIsConnected(); + } }else{ Log.w(TAG, "Router service isn't running, returning false."); if(BluetoothAdapter.getDefaultAdapter()!=null && BluetoothAdapter.getDefaultAdapter().isEnabled()){ @@ -220,10 +266,11 @@ public abstract class SdlBroadcastReceiver extends BroadcastReceiver{ context.sendBroadcast(serviceIntent); } if(callback!=null){ - callback.onConnectionStatusUpdate(false, context); + callback.onConnectionStatusUpdate(false, null,context); } } } + public static ComponentName consumeQueuedRouterService(){ diff --git a/sdl_android_lib/src/com/smartdevicelink/transport/SdlPsm.java b/sdl_android_lib/src/com/smartdevicelink/transport/SdlPsm.java index b04b4453b..d6a9840ae 100644 --- a/sdl_android_lib/src/com/smartdevicelink/transport/SdlPsm.java +++ b/sdl_android_lib/src/com/smartdevicelink/transport/SdlPsm.java @@ -195,14 +195,17 @@ public class SdlPsm{ if(dataLength==0){ return FINISHED_STATE; //We are done if we don't have any payload } - payload = new byte[dataLength]; + try{ + payload = new byte[dataLength]; + }catch(OutOfMemoryError oom){ + return ERROR_STATE; + } dumpSize = dataLength; return DATA_PUMP_STATE; case DATA_PUMP_STATE: payload[dataLength-dumpSize] = rawByte; dumpSize--; - //Log.trace(TAG,rawByte + " read. Data Length remaining: " + dumpSize); //Do we have any more bytes to read in? if(dumpSize>0){ return DATA_PUMP_STATE; diff --git a/sdl_android_lib/src/com/smartdevicelink/transport/SdlRouterService.java b/sdl_android_lib/src/com/smartdevicelink/transport/SdlRouterService.java index 7519dce0e..c6c511dc4 100644 --- a/sdl_android_lib/src/com/smartdevicelink/transport/SdlRouterService.java +++ b/sdl_android_lib/src/com/smartdevicelink/transport/SdlRouterService.java @@ -5,6 +5,7 @@ import static com.smartdevicelink.transport.TransportConstants.FORMED_PACKET_EXT import static com.smartdevicelink.transport.TransportConstants.HARDWARE_DISCONNECTED; import static com.smartdevicelink.transport.TransportConstants.SEND_PACKET_TO_APP_LOCATION_EXTRA_NAME; +import java.lang.ref.WeakReference; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; @@ -293,16 +294,23 @@ public class SdlRouterService extends Service{ /** * Target we publish for clients to send messages to RouterHandler. */ - final Messenger routerMessenger = new Messenger(new RouterHandler()); + final Messenger routerMessenger = new Messenger(new RouterHandler(this)); /** * Handler of incoming messages from clients. */ - class RouterHandler extends Handler { + static class RouterHandler extends Handler { + WeakReference<SdlRouterService> provider; + + public RouterHandler(SdlRouterService provider){ + this.provider = new WeakReference<SdlRouterService>(provider); + } + @Override public void handleMessage(Message msg) { final Bundle receivedBundle = msg.getData(); Bundle returnBundle; + final SdlRouterService service = this.provider.get(); switch (msg.what) { case TransportConstants.ROUTER_REQUEST_BT_CLIENT_CONNECT: @@ -311,14 +319,14 @@ public class SdlRouterService extends Service{ //Log.d(TAG,"Attempting to connect as bt client"); BluetoothDevice device = receivedBundle.getParcelable(BluetoothDevice.EXTRA_DEVICE); connectAsClient = true; - if(device==null || !bluetoothConnect(device)){ + if(device==null || !service.bluetoothConnect(device)){ Log.e(TAG, "Unable to connect to bluetooth device"); connectAsClient = false; } } //**************** We don't break here so we can let the app register as well case TransportConstants.ROUTER_REGISTER_CLIENT: //msg.arg1 is appId - pingClients(); + //pingClients(); Message message = Message.obtain(); message.what = TransportConstants.ROUTER_REGISTER_CLIENT_RESPONSE; message.arg1 = TransportConstants.REGISTRATION_RESPONSE_SUCESS; @@ -335,7 +343,7 @@ public class SdlRouterService extends Service{ } break; } - if(SdlRouterService.this.legacyModeEnabled){ + if(service.legacyModeEnabled){ Log.w(TAG, "Unable to register app as legacy mode is enabled"); if(msg.replyTo!=null){ message.arg1 = TransportConstants.REGISTRATION_RESPONSE_DENIED_LEGACY_MODE_ENABLED; @@ -348,21 +356,21 @@ public class SdlRouterService extends Service{ break; } - RegisteredApp app = new RegisteredApp(appId,msg.replyTo); - synchronized(REGISTERED_APPS_LOCK){ + RegisteredApp app = service.new RegisteredApp(appId,msg.replyTo); + synchronized(service.REGISTERED_APPS_LOCK){ RegisteredApp old = registeredApps.put(app.getAppId(), app); if(old!=null){ Log.w(TAG, "Replacing already existing app with this app id"); - removeAllSessionsForApp(old, true); + service.removeAllSessionsForApp(old, true); old.close(); } } - onAppRegistered(app); + service.onAppRegistered(app); returnBundle = new Bundle(); //Add params if connected - if(SdlRouterService.this.isTransportConnected){ - returnBundle.putString(TransportConstants.HARDWARE_CONNECTED, SdlRouterService.this.connectedTransportType.name()); + if(service.isTransportConnected){ + returnBundle.putString(TransportConstants.HARDWARE_CONNECTED, service.connectedTransportType.name()); if(MultiplexBluetoothTransport.currentlyConnectedDevice!=null){ returnBundle.putString(CONNECTED_DEVICE_STRING_EXTRA_NAME, MultiplexBluetoothTransport.currentlyConnectedDevice); } @@ -374,7 +382,7 @@ public class SdlRouterService extends Service{ int result = app.sendMessage(message); if(result == RegisteredApp.SEND_MESSAGE_ERROR_MESSENGER_DEAD_OBJECT){ - synchronized(REGISTERED_APPS_LOCK){ + synchronized(service.REGISTERED_APPS_LOCK){ registeredApps.remove(appId); } } @@ -383,17 +391,17 @@ public class SdlRouterService extends Service{ long appIdToUnregister = receivedBundle.getLong(TransportConstants.APP_ID_EXTRA, -1); Log.i(TAG, "Unregistering client: " + appIdToUnregister); RegisteredApp unregisteredApp = null; - synchronized(REGISTERED_APPS_LOCK){ + synchronized(service.REGISTERED_APPS_LOCK){ unregisteredApp = registeredApps.remove(appIdToUnregister); } Message response = Message.obtain(); response.what = TransportConstants.ROUTER_UNREGISTER_CLIENT_RESPONSE; if(unregisteredApp == null){ response.arg1 = TransportConstants.UNREGISTRATION_RESPONSE_FAILED_APP_ID_NOT_FOUND; - removeAllSessionsWithAppId(appIdToUnregister); + service.removeAllSessionsWithAppId(appIdToUnregister); }else{ response.arg1 = TransportConstants.UNREGISTRATION_RESPONSE_SUCESS; - removeAllSessionsForApp(unregisteredApp,false); + service.removeAllSessionsForApp(unregisteredApp,false); } Log.i(TAG, "Unregistering client response: " + response.arg1 ); try { @@ -417,7 +425,7 @@ public class SdlRouterService extends Service{ Long buffAppId = receivedBundle.getLong(TransportConstants.APP_ID_EXTRA); RegisteredApp buffApp = null; if(buffAppId!=null){ - synchronized(REGISTERED_APPS_LOCK){ + synchronized(service.REGISTERED_APPS_LOCK){ buffApp = registeredApps.get(buffAppId); } } @@ -425,13 +433,13 @@ public class SdlRouterService extends Service{ if(buffApp !=null){ buffApp.handleIncommingClientMessage(receivedBundle); }else{ - writeBytesToTransport(receivedBundle); + service.writeBytesToTransport(receivedBundle); } } } }; - if(packetExecuter!=null){ - packetExecuter.execute(packetRun); + if(service.packetExecuter!=null){ + service.packetExecuter.execute(packetRun); } } break; @@ -440,7 +448,7 @@ public class SdlRouterService extends Service{ Message extraSessionResponse = Message.obtain(); extraSessionResponse.what = TransportConstants.ROUTER_REQUEST_NEW_SESSION_RESPONSE; if(appIdRequesting>0){ - synchronized(REGISTERED_APPS_LOCK){ + synchronized(service.REGISTERED_APPS_LOCK){ if(registeredApps!=null){ RegisteredApp appRequesting = registeredApps.get(appIdRequesting); if(appRequesting!=null){ @@ -465,12 +473,12 @@ public class SdlRouterService extends Service{ case TransportConstants.ROUTER_REMOVE_SESSION: long appIdWithSession = receivedBundle.getLong(TransportConstants.APP_ID_EXTRA, -1); long sessionId = receivedBundle.getLong(TransportConstants.SESSION_ID_EXTRA, -1); - removeSessionFromMap((int)sessionId); + service.removeSessionFromMap((int)sessionId); Message removeSessionResponse = Message.obtain(); removeSessionResponse.what = TransportConstants.ROUTER_REMOVE_SESSION_RESPONSE; if(appIdWithSession>0){ if(sessionId>=0){ - synchronized(REGISTERED_APPS_LOCK){ + synchronized(service.REGISTERED_APPS_LOCK){ if(registeredApps!=null){ RegisteredApp appRequesting = registeredApps.get(appIdWithSession); if(appRequesting!=null){ @@ -508,15 +516,23 @@ public class SdlRouterService extends Service{ /** * Target we publish for alternative transport (USB) clients to send messages to RouterHandler. */ - final Messenger altTransportMessenger = new Messenger(new AltTransportHandler()); + final Messenger altTransportMessenger = new Messenger(new AltTransportHandler(this)); /** * Handler of incoming messages from an alternative transport (USB). */ - class AltTransportHandler extends Handler { - ClassLoader loader = getClass().getClassLoader(); + static class AltTransportHandler extends Handler { + ClassLoader loader; + WeakReference<SdlRouterService> provider; + + public AltTransportHandler(SdlRouterService provider){ + this.provider = new WeakReference<SdlRouterService>(provider); + loader = getClass().getClassLoader(); + } + @Override public void handleMessage(Message msg) { + SdlRouterService service = this.provider.get(); Bundle receivedBundle = msg.getData(); switch(msg.what){ case TransportConstants.HARDWARE_CONNECTION_EVENT: @@ -526,8 +542,8 @@ 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; - onTransportDisconnected(TransportType.valueOf(receivedBundle.getString(TransportConstants.HARDWARE_DISCONNECTED))); - shouldServiceRemainOpen(null); //this will close the service if bluetooth is not available + service.onTransportDisconnected(TransportType.valueOf(receivedBundle.getString(TransportConstants.HARDWARE_DISCONNECTED))); + service.shouldServiceRemainOpen(null); //this will close the service if bluetooth is not available } }else if(receivedBundle.containsKey(TransportConstants.HARDWARE_CONNECTED)){ Message retMsg = Message.obtain(); @@ -539,15 +555,15 @@ public class SdlRouterService extends Service{ } altTransportService = msg.replyTo; //Clear out the timer to make sure the service knows we're good to go - if(altTransportTimerHandler!=null && altTransportTimerRunnable!=null){ - altTransportTimerHandler.removeCallbacks(altTransportTimerRunnable); + if(service.altTransportTimerHandler!=null && service.altTransportTimerRunnable!=null){ + service.altTransportTimerHandler.removeCallbacks(service.altTransportTimerRunnable); } - altTransportTimerHandler = null; - altTransportTimerRunnable = null; + service.altTransportTimerHandler = null; + service.altTransportTimerRunnable = null; //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))); + service.onTransportConnected(TransportType.valueOf(receivedBundle.getString(TransportConstants.HARDWARE_CONNECTED))); }else{ //There seems to be some other transport connected //Error retMsg.arg1 = TransportConstants.ROUTER_REGISTER_ALT_TRANSPORT_ALREADY_CONNECTED; @@ -566,7 +582,7 @@ public class SdlRouterService extends Service{ if(receivedBundle.containsKey(TransportConstants.FORMED_PACKET_EXTRA_NAME)){ SdlPacket packet = receivedBundle.getParcelable(TransportConstants.FORMED_PACKET_EXTRA_NAME); if(packet!=null){ - onPacketRead(packet); + service.onPacketRead(packet); }else{ Log.w(TAG, "Received null packet from alt transport service"); } @@ -584,28 +600,40 @@ 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()); + final Messenger routerStatusMessenger = new Messenger(new RouterStatusHandler(this)); /** * Handler of incoming messages from an alternative transport (USB). */ - class RouterStatusHandler extends Handler { - ClassLoader loader = getClass().getClassLoader(); + static class RouterStatusHandler extends Handler { + WeakReference<SdlRouterService> provider; + + public RouterStatusHandler(SdlRouterService provider){ + this.provider = new WeakReference<SdlRouterService>(provider); + } + @Override public void handleMessage(Message msg) { + SdlRouterService service = this.provider.get(); switch(msg.what){ case TransportConstants.ROUTER_STATUS_CONNECTED_STATE_REQUEST: - if(msg.replyTo==null){ - break; + int flags = msg.arg1; + if(msg.replyTo!=null){ + Message message = Message.obtain(); + message.what = TransportConstants.ROUTER_STATUS_CONNECTED_STATE_RESPONSE; + message.arg1 = (service.isTransportConnected == true) ? 1 : 0; + try { + msg.replyTo.send(message); + } catch (RemoteException e) { + e.printStackTrace(); + } + } + if(service.isTransportConnected && ((TransportConstants.ROUTER_STATUS_FLAG_TRIGGER_PING & flags) == TransportConstants.ROUTER_STATUS_FLAG_TRIGGER_PING)){ + if(service.pingIntent == null){ + service.initPingIntent(); + } + service.getBaseContext().sendBroadcast(service.pingIntent); } - 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); @@ -628,7 +656,9 @@ public class SdlRouterService extends Service{ } String requestType = intent.getAction();//intent.getIntExtra(TransportConstants.ROUTER_BIND_REQUEST_TYPE_EXTRA, TransportConstants.BIND_REQUEST_TYPE_CLIENT); if(TransportConstants.BIND_REQUEST_TYPE_ALT_TRANSPORT.equals(requestType)){ - return this.altTransportMessenger.getBinder(); + if(0 != (getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE)){ //Only allow alt transport in debug mode + 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)){ @@ -748,14 +778,11 @@ public class SdlRouterService extends Service{ } public void startUpSequence(){ - IntentFilter stateChangeFilter = new IntentFilter("android.bluetooth.adapter.action.STATE_CHANGED"); - stateChangeFilter.addAction("android.bluetooth.device.action.CLASS_CHANGED"); - IntentFilter disconnectFilter1 = new IntentFilter("android.bluetooth.device.action.ACL_DISCONNECTED"); - IntentFilter disconnectFilter2 = new IntentFilter("android.bluetooth.device.action.ACL_DISCONNECT_REQUESTED"); - - registerReceiver(mListenForDisconnect,stateChangeFilter ); - registerReceiver(mListenForDisconnect,disconnectFilter1 ); - registerReceiver(mListenForDisconnect,disconnectFilter2 ); + IntentFilter disconnectFilter = new IntentFilter("android.bluetooth.adapter.action.STATE_CHANGED"); + disconnectFilter.addAction("android.bluetooth.device.action.CLASS_CHANGED"); + disconnectFilter.addAction("android.bluetooth.device.action.ACL_DISCONNECTED"); + disconnectFilter.addAction("android.bluetooth.device.action.ACL_DISCONNECT_REQUESTED"); + registerReceiver(mListenForDisconnect,disconnectFilter ); IntentFilter filter = new IntentFilter(); filter.addAction(REGISTER_WITH_ROUTER_ACTION); @@ -996,13 +1023,11 @@ public class SdlRouterService extends Service{ Log.d(TAG, "Not starting own bluetooth during legacy mode"); return; } - Log.i(TAG, "Iniitializing Bluetooth Serial Class"); + Log.i(TAG, "Iniitializing bluetooth transport"); //init serial service if(mSerialService ==null){ - Log.d(TAG, "Local copy of BT Server is null"); mSerialService = MultiplexBluetoothTransport.getBluetoothSerialServerInstance(); if(mSerialService==null){ - Log.d(TAG, "Local copy of BT Server is still null and so is global"); mSerialService = MultiplexBluetoothTransport.getBluetoothSerialServerInstance(mHandlerBT); } } @@ -1073,7 +1098,6 @@ public class SdlRouterService extends Service{ cachedModuleVersion = -1; //Reset our cached version if(registeredApps== null || registeredApps.isEmpty()){ - Log.w(TAG, "No clients to notify. Sending global notification."); Intent unregisterIntent = new Intent(); unregisterIntent.putExtra(HARDWARE_DISCONNECTED, type.name()); unregisterIntent.putExtra(TransportConstants.ENABLE_LEGACY_MODE_EXTRA, legacyModeEnabled); @@ -1175,7 +1199,7 @@ public class SdlRouterService extends Service{ int offset = bundle.getInt(TransportConstants.BYTES_TO_SEND_EXTRA_OFFSET, 0); //If nothing, start at the begining of the array int count = bundle.getInt(TransportConstants.BYTES_TO_SEND_EXTRA_COUNT, packet.length); //In case there isn't anything just send the whole packet. if(packet!=null){ - mSerialService.write(packet,offset,count); Log.i(TAG, "Wrote out bytes"); + mSerialService.write(packet,offset,count); return true; } return false; @@ -1191,7 +1215,7 @@ public class SdlRouterService extends Service{ private boolean manuallyWriteBytes(byte[] bytes, int offset, int count){ if(mSerialService !=null && mSerialService.getState()==MultiplexBluetoothTransport.STATE_CONNECTED){ if(bytes!=null){ - mSerialService.write(bytes,offset,count);Log.i(TAG, "Wrote out bytes manually"); + mSerialService.write(bytes,offset,count); return true; } return false; @@ -1211,7 +1235,6 @@ public class SdlRouterService extends Service{ */ private boolean sendThroughAltTransport(Bundle bundle){ if(altTransportService!=null){ - Log.d(TAG, "Sending packet through alt transport"); Message msg = Message.obtain(); msg.what = TransportConstants.ROUTER_SEND_PACKET; msg.setData(bundle); @@ -1235,7 +1258,6 @@ public class SdlRouterService extends Service{ */ private boolean sendThroughAltTransport(byte[] bytes, int offset, int count){ if(altTransportService!=null){ - Log.d(TAG, "Sending packet through alt transport"); Message msg = Message.obtain(); msg.what = TransportConstants.ROUTER_SEND_PACKET; Bundle bundle = new Bundle(); @@ -1321,7 +1343,7 @@ public class SdlRouterService extends Service{ bundle.putParcelable(FORMED_PACKET_EXTRA_NAME, copyPacket); bundle.putInt(TransportConstants.BYTES_TO_SEND_FLAGS, TransportConstants.BYTES_TO_SEND_FLAG_SDL_PACKET_INCLUDED); message.setData(bundle); - Log.d(TAG, "First packet before sending: " + message.getData().toString()); + //Log.d(TAG, "First packet before sending: " + message.getData().toString()); if(!sendPacketMessageToClient(app, message, version)){ Log.w(TAG, "Error sending first message of split packet to client " + app.appId); return false; @@ -1335,7 +1357,7 @@ public class SdlRouterService extends Service{ return false; } } - Log.i(TAG, "Large packet finished being sent"); + //Log.i(TAG, "Large packet finished being sent"); } }else{ //If we can't find a session for this packet we just drop the packet @@ -1550,8 +1572,8 @@ public class SdlRouterService extends Service{ LocalRouterService newestServiceReceived = getLocalBluetoothServiceComapre(); LocalRouterService self = getLocalRouterService(); //We can send in null here, because it should have already been created - Log.v(TAG, "Self service info " + self); - Log.v(TAG, "Newest compare to service info " + newestServiceReceived); + //Log.v(TAG, "Self service info " + self); + //Log.v(TAG, "Newest compare to service info " + newestServiceReceived); if(newestServiceReceived!=null && self.isNewer(newestServiceReceived)){ Log.d(TAG, "There is a newer version of the Router Service, starting it up"); closing = true; @@ -1624,8 +1646,8 @@ public class SdlRouterService extends Service{ SparseArray<Long> iter = sessionMap.clone(); int size = iter.size(); for(int i = 0; i<size; i++){ - Log.d(TAG, "Investigating session " +iter.keyAt(i)); - Log.d(TAG, "App id is: " + iter.valueAt(i)); + //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){ sessionHashIdMap.remove(iter.keyAt(i)); sessionMap.removeAt(i); @@ -1644,8 +1666,8 @@ public class SdlRouterService extends Service{ Vector<Long> sessions = app.getSessionIds(); int size = sessions.size(), sessionId; for(int i=0; i<size;i++){ - Log.d(TAG, "Investigating session " +sessions.get(i).intValue()); - Log.d(TAG, "App id is: " + sessionMap.get(sessions.get(i).intValue())); + //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); if(cleanModule){ @@ -1687,7 +1709,7 @@ public class SdlRouterService extends Service{ } } } - Log.d(TAG, sessionId + " session returning App Id: " + appId); + //Log.d(TAG, sessionId + " session returning App Id: " + appId); return appId; } } @@ -1796,7 +1818,7 @@ public class SdlRouterService extends Service{ peekTask = app.peekNextTask(); if(peekTask!=null){ peekWeight = peekTask.getWeight(currentTime); - Log.v(TAG, "App " + app.appId +" has a task with weight "+ peekWeight); + //Log.v(TAG, "App " + app.appId +" has a task with weight "+ peekWeight); if(peekWeight>currentPriority){ if(app.queuePaused){ app.notIt();//Reset the timer @@ -1817,6 +1839,15 @@ public class SdlRouterService extends Service{ return null; } + private void initPingIntent(){ + 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); + } + private void startClientPings(){ synchronized(this){ if(!isTransportConnected){ //If we aren't connected, bail @@ -1846,12 +1877,7 @@ public class SdlRouterService extends Service{ 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); + initPingIntent(); } getBaseContext().sendBroadcast(pingIntent); synchronized(PING_COUNT_LOCK){ @@ -2086,7 +2112,7 @@ public class SdlRouterService extends Service{ public boolean handleIncommingClientMessage(final Bundle receivedBundle){ int flags = receivedBundle.getInt(TransportConstants.BYTES_TO_SEND_FLAGS, TransportConstants.BYTES_TO_SEND_FLAG_NONE); - Log.d(TAG, "Flags received: " + flags); + //Log.d(TAG, "Flags received: " + flags); if(flags!=TransportConstants.BYTES_TO_SEND_FLAG_NONE){ byte[] packet = receivedBundle.getByteArray(TransportConstants.BYTES_TO_SEND_EXTRA_NAME); if(flags == TransportConstants.BYTES_TO_SEND_FLAG_LARGE_PACKET_START){ @@ -2203,12 +2229,18 @@ public class SdlRouterService extends Service{ if(messenger!=null){ if(deathNote == null){ deathNote = new DeathRecipient(){ + final Object deathLock = new Object(); @Override public void binderDied() { - Log.w(TAG, "Binder died"); - removeAllSessionsForApp(RegisteredApp.this,true); - removeAppFromMap(RegisteredApp.this); - startClientPings(); + synchronized(deathLock){ + Log.w(TAG, "Binder died for app " + RegisteredApp.this.appId); + if(messenger!=null && messenger.getBinder()!=null){ + messenger.getBinder().unlinkToDeath(this, 0); + } + removeAllSessionsForApp(RegisteredApp.this,true); + removeAppFromMap(RegisteredApp.this); + startClientPings(); + } } }; } diff --git a/sdl_android_lib/src/com/smartdevicelink/transport/SdlRouterStatusProvider.java b/sdl_android_lib/src/com/smartdevicelink/transport/SdlRouterStatusProvider.java index f36dcb2c0..7daad4760 100644 --- a/sdl_android_lib/src/com/smartdevicelink/transport/SdlRouterStatusProvider.java +++ b/sdl_android_lib/src/com/smartdevicelink/transport/SdlRouterStatusProvider.java @@ -23,6 +23,7 @@ public class SdlRouterStatusProvider { ConnectedStatusCallback cb = null; Messenger routerServiceMessenger = null; private ComponentName routerService = null; + private int flags = 0; final Messenger clientMessenger; @@ -36,13 +37,14 @@ public class SdlRouterStatusProvider { //Register with router service Message msg = Message.obtain(); msg.what = TransportConstants.ROUTER_STATUS_CONNECTED_STATE_REQUEST; + msg.arg1 = flags; msg.replyTo = clientMessenger; try { routerServiceMessenger.send(msg); } catch (RemoteException e) { e.printStackTrace(); if(cb!=null){ - cb.onConnectionStatusUpdate(false, context); + cb.onConnectionStatusUpdate(false, routerService, context); } } } @@ -64,11 +66,14 @@ public class SdlRouterStatusProvider { this.clientMessenger = new Messenger(new ClientHandler(this)); } - + public void setFlags(int flags){ + this.flags = flags; + } public void checkIsConnected(){ if(!bindToService()){ //We are unable to bind to service - cb.onConnectionStatusUpdate(false, context); + cb.onConnectionStatusUpdate(false, routerService, context); + unBindFromService(); } } @@ -77,7 +82,7 @@ public class SdlRouterStatusProvider { unBindFromService(); } } - + private boolean bindToService(){ if(isBound){ return true; @@ -105,7 +110,7 @@ public class SdlRouterStatusProvider { private void handleRouterStatusConnectedResponse(int connectedStatus){ if(cb!=null){ - cb.onConnectionStatusUpdate(connectedStatus == 1, context); + cb.onConnectionStatusUpdate(connectedStatus == 1, routerService,context); } unBindFromService(); routerServiceMessenger =null; @@ -131,7 +136,7 @@ public class SdlRouterStatusProvider { }; public interface ConnectedStatusCallback{ - public void onConnectionStatusUpdate(boolean connected, Context context); + public void onConnectionStatusUpdate(boolean connected, ComponentName service, 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 493612ea3..aa5f35c3f 100644 --- a/sdl_android_lib/src/com/smartdevicelink/transport/TransportBroker.java +++ b/sdl_android_lib/src/com/smartdevicelink/transport/TransportBroker.java @@ -1,5 +1,6 @@ package com.smartdevicelink.transport; +import java.lang.ref.WeakReference; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; @@ -40,7 +41,7 @@ public class TransportBroker { private TransportType queuedOnTransportConnect = null; Messenger routerServiceMessenger = null; - final Messenger clientMessenger = new Messenger(new ClientHandler()); + final Messenger clientMessenger; boolean isBound = false, registeredWithRouterService = false; private String routerPackage = null, routerClassName = null; @@ -65,7 +66,7 @@ public class TransportBroker { } public void onServiceDisconnected(ComponentName className) { - Log.d(TAG, "UN-Bound from service " + className.getClassName()); + Log.d(TAG, "Unbound from service " + className.getClassName()); routerServiceMessenger = null; registeredWithRouterService = false; isBound = false; @@ -125,12 +126,20 @@ public class TransportBroker { /** * Handler of incoming messages from service. */ - @SuppressLint("HandlerLeak") - class ClientHandler extends Handler { - ClassLoader loader = getClass().getClassLoader(); + static class ClientHandler extends Handler { + ClassLoader loader; + WeakReference<TransportBroker> provider; + + public ClientHandler(TransportBroker provider){ + this.provider = new WeakReference<TransportBroker>(provider); + loader = getClass().getClassLoader(); + } @Override public void handleMessage(Message msg) { - + TransportBroker broker = provider.get(); + if(broker == null){ + Log.e(TAG, "Broker object null, unable to process message"); + } Bundle bundle = msg.getData(); if(bundle!=null){ @@ -143,8 +152,7 @@ public class TransportBroker { if(bundle !=null && bundle.containsKey(TransportConstants.ENABLE_LEGACY_MODE_EXTRA)){ boolean enableLegacy = bundle.getBoolean(TransportConstants.ENABLE_LEGACY_MODE_EXTRA, false); - Log.d(TAG, "Setting legacy mode: " +enableLegacy ); - enableLegacyMode(enableLegacy); + broker.enableLegacyMode(enableLegacy); } //Find out what message we have and what to do with it @@ -153,13 +161,13 @@ public class TransportBroker { switch(msg.arg1){ case TransportConstants.REGISTRATION_RESPONSE_SUCESS: // yay! we have been registered. Now what? - registeredWithRouterService = true; + broker.registeredWithRouterService = true; if(bundle !=null){ if(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))); + broker.onHardwareConnected(TransportType.valueOf(bundle.getString(TransportConstants.HARDWARE_CONNECTED))); } /*if(bundle.containsKey(TransportConstants.ROUTER_SERVICE_VERSION)){ //Keep track if we actually get this @@ -168,14 +176,14 @@ public class TransportBroker { break; case TransportConstants.REGISTRATION_RESPONSE_DENIED_LEGACY_MODE_ENABLED: Log.d(TAG, "Denied registration because router is in legacy mode" ); - registeredWithRouterService = false; - enableLegacyMode(true); + broker.registeredWithRouterService = false; + broker.enableLegacyMode(true); //We call this so we can start the process of legacy connection //onHardwareDisconnected(TransportType.BLUETOOTH); - onLegacyModeEnabled(); + broker.onLegacyModeEnabled(); break; default: - registeredWithRouterService = false; + broker.registeredWithRouterService = false; Log.w(TAG, "Registration denied from router service. Reason - " + msg.arg1); break; }; @@ -201,38 +209,36 @@ public class TransportBroker { Parcelable packet = bundle.getParcelable(TransportConstants.FORMED_PACKET_EXTRA_NAME); if(flags == TransportConstants.BYTES_TO_SEND_FLAG_NONE){ - if(packet!=null){ Log.i(TAG, "received packet to process "+ packet.toString()); - onPacketReceived(packet); + if(packet!=null){ //Log.i(TAG, "received packet to process "+ packet.toString()); + broker.onPacketReceived(packet); }else{ Log.w(TAG, "Received null packet from router service, not passing along"); } }else if(flags == TransportConstants.BYTES_TO_SEND_FLAG_SDL_PACKET_INCLUDED){ - Log.i(TAG, "Starting a buffered split packet"); - bufferedPacket = (SdlPacket) packet; - if(bufferedPayloadAssembler !=null){ - bufferedPayloadAssembler.close(); - bufferedPayloadAssembler = null; + broker.bufferedPacket = (SdlPacket) packet; + if(broker.bufferedPayloadAssembler !=null){ + broker.bufferedPayloadAssembler.close(); + broker.bufferedPayloadAssembler = null; } - bufferedPayloadAssembler = new ByteAraryMessageAssembler(); - bufferedPayloadAssembler.init(); + broker.bufferedPayloadAssembler = new ByteAraryMessageAssembler(); + broker.bufferedPayloadAssembler.init(); } }else if(bundle.containsKey(TransportConstants.BYTES_TO_SEND_EXTRA_NAME)){ //This should contain the payload - if(bufferedPayloadAssembler!=null){ + if(broker.bufferedPayloadAssembler!=null){ byte[] chunk = bundle.getByteArray(TransportConstants.BYTES_TO_SEND_EXTRA_NAME); - if(!bufferedPayloadAssembler.handleMessage(flags, chunk)){ + if(!broker.bufferedPayloadAssembler.handleMessage(flags, chunk)){ //If there was a problem Log.e(TAG, "Error handling bytes for split packet"); } - if(bufferedPayloadAssembler.isFinished()){ - bufferedPacket.setPayload(bufferedPayloadAssembler.getBytes()); + if(broker.bufferedPayloadAssembler.isFinished()){ + broker.bufferedPacket.setPayload(broker.bufferedPayloadAssembler.getBytes()); - bufferedPayloadAssembler.close(); - bufferedPayloadAssembler = null; - Log.i(TAG, "Split packet finished from router service = " + bufferedPacket.toString()); - onPacketReceived(bufferedPacket); - bufferedPacket = null; + broker.bufferedPayloadAssembler.close(); + broker.bufferedPayloadAssembler = null; + broker.onPacketReceived(broker.bufferedPacket); + broker.bufferedPacket = null; } } //} @@ -246,9 +252,9 @@ public class TransportBroker { //We should shut down, so call Log.d(TAG, "Hardware disconnected"); if(isLegacyModeEnabled()){ - onLegacyModeEnabled(); + broker.onLegacyModeEnabled(); }else{ - onHardwareDisconnected(TransportType.valueOf(bundle.getString(TransportConstants.HARDWARE_DISCONNECTED))); + broker.onHardwareDisconnected(TransportType.valueOf(bundle.getString(TransportConstants.HARDWARE_DISCONNECTED))); } break; } @@ -257,7 +263,7 @@ public class TransportBroker { 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))); + broker.onHardwareConnected(TransportType.valueOf(bundle.getString(TransportConstants.HARDWARE_CONNECTED))); break; } break; @@ -278,6 +284,7 @@ public class TransportBroker { @SuppressLint("SimpleDateFormat") public TransportBroker(Context context, String appId, ComponentName service){ synchronized(INIT_LOCK){ + clientMessenger = new Messenger(new ClientHandler(this)); initRouterConnection(); //So the user should have set the AppId, lets define where the intents need to be sent SimpleDateFormat s = new SimpleDateFormat("hhmmssss"); //So we have a time stamp of the event @@ -301,7 +308,7 @@ public class TransportBroker { * This beings the initial connection with the router service. */ public boolean start(){ - Log.d(TAG, "Starting up transport broker for " + whereToReply); + //Log.d(TAG, "Starting up transport broker for " + whereToReply); synchronized(INIT_LOCK){ if(currentContext==null){ throw new IllegalStateException("This instance can't be started since it's local reference of context is null. Ensure when suppling a context to the TransportBroker that it is valid"); @@ -319,7 +326,6 @@ public class TransportBroker { } public void resetSession(){ - Log.d(TAG, "RESETING transport broker for " + whereToReply); synchronized(INIT_LOCK){ unregisterWithRouterService(); routerServiceMessenger = null; @@ -331,7 +337,7 @@ public class TransportBroker { * This method will end our communication with the router service. */ public void stop(){ - Log.d(TAG, "STOPPING transport broker for " + whereToReply); + //Log.d(TAG, "STOPPING transport broker for " + whereToReply); synchronized(INIT_LOCK){ unregisterWithRouterService(); unBindFromRouterService(); @@ -364,7 +370,7 @@ public class TransportBroker { } public void onHardwareDisconnected(TransportType type){ - synchronized(INIT_LOCK){Log.d(TAG, "onHardwareDisconnect"); + synchronized(INIT_LOCK){ unBindFromRouterService(); routerServiceMessenger = null; routerConnection = null; @@ -397,7 +403,6 @@ public class TransportBroker { * @return */ private boolean isRouterServiceRunning(Context context){ - Log.d(TAG,whereToReply + " checking if a bluetooth service is running"); if(context==null){ return false; @@ -445,7 +450,7 @@ public class TransportBroker { sendMessageToRouterService(message); return true; }else{ //Message is too big for IPC transaction - Log.w(TAG, "Message too big for single IPC transaction. Breaking apart. Size - " + bytes.length); + //Log.w(TAG, "Message too big for single IPC transaction. Breaking apart. Size - " + bytes.length); ByteArrayMessageSpliter splitter = new ByteArrayMessageSpliter(appId,TransportConstants.ROUTER_SEND_PACKET,bytes,packet.getPrioirtyCoefficient() ); while(splitter.isActive()){ sendMessageToRouterService(splitter.nextMessage()); diff --git a/sdl_android_lib/src/com/smartdevicelink/transport/TransportConstants.java b/sdl_android_lib/src/com/smartdevicelink/transport/TransportConstants.java index ac9b9b6c6..612b5775a 100644 --- a/sdl_android_lib/src/com/smartdevicelink/transport/TransportConstants.java +++ b/sdl_android_lib/src/com/smartdevicelink/transport/TransportConstants.java @@ -11,10 +11,6 @@ package com.smartdevicelink.transport; public class TransportConstants { public static final String START_ROUTER_SERVICE_ACTION ="sdl.router.startservice"; - public static final String UNREGISTER_WITH_ROUTER_ACTION = "com.sdl.android.unregister"; - public static final String SEND_PACKET_ACTION = "com.sdl.android.sendpacket"; - public static final String SEND__GLOBAL_PACKET_ACTION = "com.sdl.android.sendglobalpacket"; - public static final String BIND_LOCATION_PACKAGE_NAME_EXTRA = "BIND_LOCATION_PACKAGE_NAME_EXTRA"; public static final String BIND_LOCATION_CLASS_NAME_EXTRA = "BIND_LOCATION_CLASS_NAME_EXTRA"; @@ -38,10 +34,6 @@ public class TransportConstants { public static final String APP_ID_EXTRA = "app.id"; public static final String SESSION_ID_EXTRA = "session.id"; - public static final String LOG_BASIC_DEBUG_BOOLEAN_EXTRA = "basicDebugBool"; - public static final String LOG_TRACE_BT_DEBUG_BOOLEAN_EXTRA = "btTraceBool"; - - public static final String ENABLE_LEGACY_MODE_EXTRA = "ENABLE_LEGACY_MODE_EXTRA"; public static final String HARDWARE_DISCONNECTED = "hardware.disconect"; @@ -198,6 +190,11 @@ public class TransportConstants { public static final int ROUTER_STATUS_CONNECTED_STATE_REQUEST = 0x01; public static final int ROUTER_STATUS_CONNECTED_STATE_RESPONSE = 0x02; + /** + * This flag when used to check router status will trigger the router service in sending out a ping that if it is connected to a device + */ + public static final int ROUTER_STATUS_FLAG_TRIGGER_PING = 0x02; + diff --git a/sdl_android_lib/src/com/smartdevicelink/util/DebugTool.java b/sdl_android_lib/src/com/smartdevicelink/util/DebugTool.java index 3b73b007c..716d96c59 100644 --- a/sdl_android_lib/src/com/smartdevicelink/util/DebugTool.java +++ b/sdl_android_lib/src/com/smartdevicelink/util/DebugTool.java @@ -1,10 +1,20 @@ package com.smartdevicelink.util;
+import java.util.Hashtable;
import java.util.Vector;
import android.util.Log;
import com.smartdevicelink.exception.SdlException;
+import com.smartdevicelink.marshal.JsonRPCMarshaller;
+import com.smartdevicelink.protocol.BinaryFrameHeader;
+import com.smartdevicelink.protocol.ProtocolMessage;
+import com.smartdevicelink.protocol.SdlPacket;
+import com.smartdevicelink.protocol.enums.FunctionID;
+import com.smartdevicelink.protocol.enums.MessageType;
+import com.smartdevicelink.protocol.enums.SessionType;
+import com.smartdevicelink.proxy.RPCMessage;
+import com.smartdevicelink.proxy.RPCStruct;
import com.smartdevicelink.proxy.Version;
import com.smartdevicelink.transport.SiphonServer;
@@ -267,4 +277,76 @@ public class DebugTool { } // end-catch
}
}
+
+ /**
+ * Debug method to try to extract the RPC hash from the packet payload. Should only be used while debugging, not in production.
+ * Currently it will only handle single frame RPCs
+ * @param packet to inspect
+ * @return The Hashtable to be used to construct an RPC
+ */
+ public static Hashtable<String, Object> getRPCHash(SdlPacket packet){
+ if(packet == null ||
+ packet.getFrameType().getValue() != SdlPacket.FRAME_TYPE_SINGLE ||
+ packet.getServiceType()!=SdlPacket.SERVICE_TYPE_RPC){
+ Log.w("Debug", "Unable to get hash");
+ return null;
+ }
+ int version = packet.getVersion();
+
+ ProtocolMessage message = new ProtocolMessage();
+ SessionType serviceType = SessionType.valueOf((byte)packet.getServiceType());
+ if (serviceType == SessionType.RPC) {
+ message.setMessageType(MessageType.RPC);
+ } else if (serviceType == SessionType.BULK_DATA) {
+ message.setMessageType(MessageType.BULK);
+ } // end-if
+ message.setSessionType(serviceType);
+ message.setSessionID((byte)packet.getSessionId());
+ //If it is WiPro 2.0 it must have binary header
+ if (version > 1) {
+ BinaryFrameHeader binFrameHeader = BinaryFrameHeader.
+ parseBinaryHeader(packet.getPayload());
+ message.setVersion((byte) version);
+ message.setRPCType(binFrameHeader.getRPCType());
+ message.setFunctionID(binFrameHeader.getFunctionID());
+ message.setCorrID(binFrameHeader.getCorrID());
+ if (binFrameHeader.getJsonSize() > 0){
+ message.setData(binFrameHeader.getJsonData());
+ }
+ if (binFrameHeader.getBulkData() != null){
+ message.setBulkData(binFrameHeader.getBulkData());
+ }
+ } else {
+ message.setData(packet.getPayload());
+ }
+ Hashtable<String, Object> hash = new Hashtable<String, Object>();
+ if (packet.getVersion() > 1) {
+ Hashtable<String, Object> hashTemp = new Hashtable<String, Object>();
+
+ hashTemp.put(RPCMessage.KEY_CORRELATION_ID, message.getCorrID());
+ if (message.getJsonSize() > 0) {
+ final Hashtable<String, Object> mhash = JsonRPCMarshaller.unmarshall(message.getData());
+ hashTemp.put(RPCMessage.KEY_PARAMETERS, mhash);
+ }
+
+ String functionName = FunctionID.getFunctionName(message.getFunctionID());
+ if (functionName != null) {
+ hashTemp.put(RPCMessage.KEY_FUNCTION_NAME, functionName);
+ } else {
+ return null;
+ }
+ if (message.getRPCType() == 0x00) {
+ hash.put(RPCMessage.KEY_REQUEST, hashTemp);
+ } else if (message.getRPCType() == 0x01) {
+ hash.put(RPCMessage.KEY_RESPONSE, hashTemp);
+ } else if (message.getRPCType() == 0x02) {
+ hash.put(RPCMessage.KEY_NOTIFICATION, hashTemp);
+ }
+ if (message.getBulkData() != null) hash.put(RPCStruct.KEY_BULK_DATA, message.getBulkData());
+ } else {
+ final Hashtable<String, Object> mhash = JsonRPCMarshaller.unmarshall(message.getData());
+ hash = mhash;
+ }
+ return hash;
+ }
}
|