11package  com .smartdevicelink .transport ;
22
33import  java .util .Locale ;
4+ import  java .util .Vector ;
5+ import  java .util .concurrent .ConcurrentLinkedQueue ;
46
57import  android .app .ActivityManager ;
68import  android .app .ActivityManager .RunningServiceInfo ;
911import  android .content .ComponentName ;
1012import  android .content .Context ;
1113import  android .content .Intent ;
12- import  android .content .SharedPreferences ;
13- import  android .content .pm .PackageManager .NameNotFoundException ;
1414import  android .util .Log ;
1515
1616public  abstract  class  SdlBroadcastReceiver  extends  BroadcastReceiver {
@@ -29,7 +29,7 @@ public abstract class SdlBroadcastReceiver extends BroadcastReceiver{
2929	public  static  final  String  TRANSPORT_GLOBAL_PREFS  						= "SdlTransportPrefs" ; 
3030	public  static  final  String  IS_TRANSPORT_CONNECTED 						= "isTransportConnected" ; 
3131
32- 	public  static  ComponentName  runningBluetoothServicePackage  = null ;
32+ 	public  static  Vector < ComponentName >  runningBluetoothServicePackage  = null ;
3333
3434    @ SuppressWarnings ("rawtypes" )
3535	private  static  Class  localRouterClass ;
@@ -72,15 +72,15 @@ public void onReceive(Context context, Intent intent) {
7272					String  packageName  = intent .getStringExtra (TransportConstants .START_ROUTER_SERVICE_SDL_ENABLED_APP_PACKAGE );
7373					ComponentName  componentName  = intent .getParcelableExtra (TransportConstants .START_ROUTER_SERVICE_SDL_ENABLED_CMP_NAME );
7474					if (componentName !=null ){
75- 						Log .v (TAG , "SDL enabled by router service from "  + packageName  + " compnent package "  + componentName .getPackageName ()  + " - "  + componentName .getClassName ());
75+ 						// Log.v(TAG, "SDL enabled by router service from " + packageName + " compnent package " + componentName.getPackageName()  + " - " + componentName.getClassName());
7676						RouterServiceValidator  vlad  = new  RouterServiceValidator (context ,componentName );
7777						if (vlad .validate ()){
78- 							Log .d (TAG , "Router service trusted!" );
78+ 							// Log.d(TAG, "Router service trusted!");
7979							queuedService  = componentName ;
8080							intent .setAction ("com.sdl.noaction" ); //Replace what's there so we do go into some unintended loop 
8181							onSdlEnabled (context , intent );
8282						}else {
83- 							Log .e (TAG , "RouterService was not trusted. Ignoring intent from : " + componentName .getClassName ());
83+ 							Log .w (TAG , "RouterService was not trusted. Ignoring intent from : " + componentName .getClassName ());
8484						}
8585
8686					}
@@ -93,7 +93,6 @@ public void onReceive(Context context, Intent intent) {
9393				return ;
9494			}else  if (intent .getBooleanExtra (TransportConstants .PING_ROUTER_SERVICE_EXTRA , false )){
9595				//We were told to wake up our router services 
96- 				Log .d (TAG , "Starting router service off ping" );
9796				boolean  altServiceWake  = intent .getBooleanExtra (TransportConstants .BIND_REQUEST_TYPE_ALT_TRANSPORT , false );
9897				didStart  = wakeUpRouterService (context , false ,altServiceWake  );
9998
@@ -113,15 +112,13 @@ public void onReceive(Context context, Intent intent) {
113112	    			return ;
114113	    		}else  if (state  == BluetoothAdapter .STATE_TURNING_ON ){
115114	    			//We started bluetooth, we should check for a new valid router list 
116- 	    			Log .d (TAG , "Attempting to get list of approved router services" );
117115	    			RouterServiceValidator .createTrustedListRequest (context ,true );
118116	    		}
119117	    }
120118
121119	    if (localRouterClass !=null ){ //If there is a supplied router service lets run some logic regarding starting one 
122120
123121	    	if (!didStart ){
124- 	    		Log .d (TAG , "Waking up router service" );
125122	    		didStart  = wakeUpRouterService (context , true ,false );
126123	    	}
127124
@@ -138,10 +135,8 @@ public void onReceive(Context context, Intent intent) {
138135	}
139136
140137	private  boolean  wakeUpRouterService (Context  context , boolean  ping , boolean  altTransportWake ){
141- 		Log .d (TAG , "Waking up router service" );
142138    	if (!isRouterServiceRunning (context , ping )){  
143139    		//If there isn't a service running we should try to start one 
144-     		Log .i (TAG , "Attempting to start an instance of the Router Service" );
145140    		//The under class should have implemented this.... 
146141
147142    		//So let's start up our service since no copy is running 
@@ -152,18 +147,21 @@ private boolean wakeUpRouterService(Context context, boolean ping, boolean altTr
152147    		context .startService (serviceIntent );
153148    		return  true ;
154149    	}else {
155-     		Log .i (TAG , "An instance of the Router Service is already running" );	
156-     		if (altTransportWake ){
150+     		if (altTransportWake  &&  runningBluetoothServicePackage !=null  && runningBluetoothServicePackage .size ()>0 ){
157151    			Intent  serviceIntent  = new  Intent ();
158-     			serviceIntent .setComponent (runningBluetoothServicePackage );
159152        		serviceIntent .setAction (TransportConstants .BIND_REQUEST_TYPE_ALT_TRANSPORT );
160-         		context .startService (serviceIntent );
153+         		//context.startService(serviceIntent); 
154+         		for (ComponentName  compName : runningBluetoothServicePackage ){
155+         			serviceIntent .setComponent (compName );
156+         			context .startService (serviceIntent );
157+ 
158+         		}
161159        		return  true ;
162160    		}
163161    		return  false ;
164162    	}
165163	}
166- 	 
164+ 
167165	/** 
168166	 * Determines if an instance of the Router Service is currently running on the device.  
169167	 * @param context A context to access Android system services through. 
@@ -175,13 +173,18 @@ private static boolean isRouterServiceRunning(Context context, boolean pingServi
175173			Log .e (TAG , "Can't look for router service, context supplied was null" );
176174			return  false ;
177175		}
178- 		Log .d (TAG , "Looking for Service: " + SDL_ROUTER_SERVICE_CLASS_NAME );
179176		ActivityManager  manager  = (ActivityManager ) context .getSystemService (Context .ACTIVITY_SERVICE );
177+ 		if (runningBluetoothServicePackage ==null ){
178+ 			runningBluetoothServicePackage  = new  Vector <ComponentName >();
179+ 		}else {
180+ 			runningBluetoothServicePackage .clear ();
181+ 		}
180182	    for  (RunningServiceInfo  service  : manager .getRunningServices (Integer .MAX_VALUE )) {
181183	    	//We will check to see if it contains this name, should be pretty specific 
182184	    	//Log.d(TAG, "Found Service: "+ service.service.getClassName()); 
183185	    	if  ((service .service .getClassName ()).toLowerCase (Locale .US ).contains (SDL_ROUTER_SERVICE_CLASS_NAME )) {
184- 	    		runningBluetoothServicePackage  = service .service ;	//Store which instance is running 
186+ 	    		
187+ 	    		runningBluetoothServicePackage .add (service .service );	//Store which instance is running 
185188	            if (pingService ){
186189	            	Intent  intent  = new  Intent ();
187190	            	intent .setClassName (service .service .getPackageName (), service .service .getClassName ());
@@ -196,21 +199,64 @@ private static boolean isRouterServiceRunning(Context context, boolean pingServi
196199
197200	}
198201
202+ 	/** 
203+ 	 * 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 
204+ 	 * receive that ping and if the router service is trusted, the onSdlEnabled method will be called.  
205+ 	 * @param context 
206+ 	 */ 
207+ 	public  static  void  queryForConnectedService (Context  context ){
208+ 		//Leverage existing call. Include ping bit 
209+ 		requestTransportStatus (context ,null ,true );
210+ 	}
199211	/** 
200212	 * If a Router Service is running, this method determines if that service is connected to a device over some form of transport. 
201213	 * @param context A context to access Android system services through. If null is passed, this will always return false 
202214	 * @param callback Use this callback to find out if the router service is connected or not.  
203215	 */ 
204- 	public  static  void  requestTransportStatus (Context  context , SdlRouterStatusProvider .ConnectedStatusCallback  callback ){
205- 		Log .d (TAG , "Checking to see if router service is transport connected" );
216+ 	public  static  void  requestTransportStatus (Context  context , final  SdlRouterStatusProvider .ConnectedStatusCallback  callback ){
217+ 		requestTransportStatus (context ,callback ,false );
218+ 	}
219+ 
220+ 	private  static  void  requestTransportStatus (Context  context , final  SdlRouterStatusProvider .ConnectedStatusCallback  callback , final  boolean  triggerRouterServicePing ){
206221		if (context  == null ){
207222			if (callback !=null ){
208- 				callback .onConnectionStatusUpdate (false , context );
223+ 				callback .onConnectionStatusUpdate (false , null , context );
209224			}
225+ 			return ;
210226		}
211- 		if (isRouterServiceRunning (context ,false )){	//So there is a service up, let's see if it's connected 
212- 			SdlRouterStatusProvider  provider  = new  SdlRouterStatusProvider (context ,runningBluetoothServicePackage ,callback );
213- 			provider .checkIsConnected ();
227+ 		if (isRouterServiceRunning (context ,false ) && !runningBluetoothServicePackage .isEmpty ()){	//So there is a service up, let's see if it's connected 
228+ 			final  ConcurrentLinkedQueue <ComponentName > list  = new  ConcurrentLinkedQueue <ComponentName >(runningBluetoothServicePackage );
229+ 			if (runningBluetoothServicePackage .size ()>0 ){ //TODO for testing do this for all cases 
230+ 				final  SdlRouterStatusProvider .ConnectedStatusCallback  sdlBrCallback  = new  SdlRouterStatusProvider .ConnectedStatusCallback () {	
231+ 					
232+ 					@ Override 
233+ 					public  void  onConnectionStatusUpdate (boolean  connected , ComponentName  service ,Context  context ) {
234+ 						if (!connected  && !list .isEmpty ()){
235+ 							SdlRouterStatusProvider  provider  = new  SdlRouterStatusProvider (context ,list .poll (), this );
236+ 							if (triggerRouterServicePing ){provider .setFlags (TransportConstants .ROUTER_STATUS_FLAG_TRIGGER_PING );	}
237+ 							provider .checkIsConnected ();
238+ 						}else {
239+ 							Log .d (TAG , service .getPackageName () + " is connected = "  + connected );
240+ 							if (callback !=null ){
241+ 								callback .onConnectionStatusUpdate (connected , service ,context );
242+ 							}
243+ 							list .clear ();
244+ 						}
245+ 
246+ 					}
247+ 				};
248+ 				SdlRouterStatusProvider  provider  = new  SdlRouterStatusProvider (context ,list .poll (),sdlBrCallback );
249+ 				if (triggerRouterServicePing ){
250+ 					provider .setFlags (TransportConstants .ROUTER_STATUS_FLAG_TRIGGER_PING );
251+ 				}
252+ 				provider .checkIsConnected ();
253+ 			}else { //If only one service is running, just check that 
254+ 				SdlRouterStatusProvider  provider  = new  SdlRouterStatusProvider (context ,runningBluetoothServicePackage .get (0 ),callback );
255+ 				if (triggerRouterServicePing ){
256+ 					provider .setFlags (TransportConstants .ROUTER_STATUS_FLAG_TRIGGER_PING );
257+ 				}
258+ 				provider .checkIsConnected ();
259+ 			}
214260		}else {
215261			Log .w (TAG , "Router service isn't running, returning false." );
216262			if (BluetoothAdapter .getDefaultAdapter ()!=null  && BluetoothAdapter .getDefaultAdapter ().isEnabled ()){
@@ -220,10 +266,11 @@ public static void requestTransportStatus(Context context, SdlRouterStatusProvid
220266	    		context .sendBroadcast (serviceIntent );
221267			}
222268			if (callback !=null ){
223- 				callback .onConnectionStatusUpdate (false , context );
269+ 				callback .onConnectionStatusUpdate (false , null , context );
224270			}
225271		}
226272	}
273+ 	
227274
228275
229276	public  static  ComponentName  consumeQueuedRouterService (){
0 commit comments