Skip to content

Commit c36bafe

Browse files
committed
Merge branch 'develop' into bugfix/issue_1377_logging
2 parents 59f11f6 + b85d06a commit c36bafe

7 files changed

Lines changed: 442 additions & 54 deletions

File tree

android/sdl_android/src/main/java/com/smartdevicelink/transport/MultiplexBluetoothTransport.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -815,8 +815,10 @@ public void run() {
815815
}
816816
} catch (IOException|NullPointerException e) { // NPE is ONLY to catch error on mmInStream
817817
DebugTool.logError(TAG, "Lost connection in the Connected Thread");
818-
e.printStackTrace();
819-
connectionLost();
818+
if(DebugTool.isDebugEnabled()){
819+
e.printStackTrace();
820+
}
821+
connectionLost();
820822
break;
821823
}
822824
}

android/sdl_android/src/main/java/com/smartdevicelink/transport/SdlBroadcastReceiver.java

Lines changed: 140 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
import com.smartdevicelink.R;
5353
import com.smartdevicelink.transport.RouterServiceValidator.TrustedListCallback;
5454
import com.smartdevicelink.transport.enums.TransportType;
55+
import com.smartdevicelink.transport.utl.SdlDeviceListener;
5556
import com.smartdevicelink.util.AndroidTools;
5657
import com.smartdevicelink.util.DebugTool;
5758
import com.smartdevicelink.util.SdlAppInfo;
@@ -84,6 +85,8 @@ public abstract class SdlBroadcastReceiver extends BroadcastReceiver{
8485
private static final Object QUEUED_SERVICE_LOCK = new Object();
8586
private static ComponentName queuedService = null;
8687
private static Thread.UncaughtExceptionHandler foregroundExceptionHandler = null;
88+
private static final Object DEVICE_LISTENER_LOCK = new Object();
89+
private static SdlDeviceListener sdlDeviceListener;
8790

8891
public int getRouterServiceVersion(){
8992
return SdlRouterService.ROUTER_SERVICE_VERSION_NUMBER;
@@ -188,10 +191,7 @@ public void onListObtained(boolean successful) {
188191

189192
});
190193
}
191-
192-
}else{
193-
//This was previously not hooked up, so let's leave it commented out
194-
//onSdlDisabled(context);
194+
195195
}
196196
return;
197197
}else if(intent.getBooleanExtra(TransportConstants.PING_ROUTER_SERVICE_EXTRA, false)){
@@ -222,52 +222,101 @@ public void onListObtained(boolean successful) {
222222
}
223223
}
224224

225+
/**
226+
* This method will attempt to start the router service.
227+
* @param context to be used to start the service and send broadcasts
228+
* @param componentName the router service that should be started
229+
* @param altTransportWake if the alt transport flag should be set. Only used in debug
230+
* @param device the connected bluetooth device
231+
*/
232+
private static void startRouterService(Context context, ComponentName componentName, boolean altTransportWake, BluetoothDevice device, boolean confirmedDevice) {
233+
if (componentName == null) {
234+
return;
235+
}
236+
237+
Intent serviceIntent = new Intent();
238+
serviceIntent.setComponent(componentName);
239+
240+
if (altTransportWake) {
241+
serviceIntent.setAction(TransportConstants.BIND_REQUEST_TYPE_ALT_TRANSPORT);
242+
}
243+
244+
if (device != null) {
245+
serviceIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
246+
}
247+
248+
if (confirmedDevice) {
249+
serviceIntent.putExtra(TransportConstants.CONFIRMED_SDL_DEVICE, confirmedDevice);
250+
}
251+
252+
try {
253+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
254+
context.startService(serviceIntent);
255+
} else {
256+
serviceIntent.putExtra(FOREGROUND_EXTRA, true);
257+
DebugTool.logInfo("Attempting to startForegroundService - " + System.currentTimeMillis());
258+
setForegroundExceptionHandler(); //Prevent ANR in case the OS takes too long to start the service
259+
context.startForegroundService(serviceIntent);
260+
261+
}
262+
//Make sure to send this out for old apps to close down
263+
SdlRouterService.LocalRouterService self = SdlRouterService.getLocalRouterService(serviceIntent, serviceIntent.getComponent());
264+
Intent restart = new Intent(SdlRouterService.REGISTER_NEWER_SERVER_INSTANCE_ACTION);
265+
restart.putExtra(LOCAL_ROUTER_SERVICE_EXTRA, self);
266+
restart.putExtra(LOCAL_ROUTER_SERVICE_DID_START_OWN, true);
267+
context.sendBroadcast(restart);
268+
269+
} catch (SecurityException e) {
270+
DebugTool.logError(TAG, "Security exception, process is bad");
271+
}
272+
}
273+
225274
private boolean wakeUpRouterService(final Context context, final boolean ping, final boolean altTransportWake, final BluetoothDevice device){
226-
new ServiceFinder(context, context.getPackageName(), new ServiceFinder.ServiceFinderCallback() {
275+
new ServiceFinder(context, context.getPackageName(), new ServiceFinder.ServiceFinderCallback() {
227276
@Override
228277
public void onComplete(Vector<ComponentName> routerServices) {
229278
runningBluetoothServicePackage = new Vector<ComponentName>();
230279
runningBluetoothServicePackage.addAll(routerServices);
231280
if (runningBluetoothServicePackage.isEmpty()) {
232281
//If there isn't a service running we should try to start one
233282
//We will try to sort the SDL enabled apps and find the one that's been installed the longest
234-
Intent serviceIntent;
235-
List<SdlAppInfo> sdlAppInfoList = AndroidTools.querySdlAppInfo(context, new SdlAppInfo.BestRouterComparator());
283+
final List<SdlAppInfo> sdlAppInfoList = AndroidTools.querySdlAppInfo(context, new SdlAppInfo.BestRouterComparator());
284+
synchronized (DEVICE_LISTENER_LOCK) {
285+
final boolean sdlDeviceListenerEnabled = SdlDeviceListener.isFeatureSupported(sdlAppInfoList);
286+
if (sdlDeviceListenerEnabled) {
287+
String myPackage = context.getPackageName();
288+
String routerServicePackage = null;
289+
if (sdlAppInfoList != null && !sdlAppInfoList.isEmpty() && sdlAppInfoList.get(0).getRouterServiceComponentName() != null) {
290+
routerServicePackage = sdlAppInfoList.get(0).getRouterServiceComponentName().getPackageName();
291+
}
292+
DebugTool.logInfo(TAG + ": This app's package: " + myPackage);
293+
DebugTool.logInfo(TAG + ": Router service app's package: " + routerServicePackage);
294+
if (myPackage != null && myPackage.equalsIgnoreCase(routerServicePackage)) {
295+
SdlDeviceListener sdlDeviceListener = getSdlDeviceListener(context, device);
296+
if (!sdlDeviceListener.isRunning()) {
297+
sdlDeviceListener.start();
298+
}
299+
} else {
300+
DebugTool.logInfo(TAG + ": Not the app to start the router service nor device listener");
301+
}
302+
return;
303+
}
304+
}
305+
236306
if (sdlAppInfoList != null && !sdlAppInfoList.isEmpty()) {
237-
serviceIntent = new Intent();
238-
serviceIntent.setComponent(sdlAppInfoList.get(0).getRouterServiceComponentName());
307+
startRouterService(context, sdlAppInfoList.get(0).getRouterServiceComponentName(), altTransportWake, device, false);
239308
} else{
240-
DebugTool.logInfo(TAG, "No SDL Router Services found");
241-
DebugTool.logInfo(TAG, "WARNING: This application has not specified its SdlRouterService correctly in the manifest. THIS WILL THROW AN EXCEPTION IN FUTURE RELEASES!!");
309+
DebugTool.logInfo(TAG, "No SDL Router Services found");
310+
DebugTool.logInfo(TAG, "WARNING: This application has not specified its SdlRouterService correctly in the manifest. THIS WILL THROW AN EXCEPTION IN FUTURE RELEASES!!");
242311
return;
243312
}
244-
if (altTransportWake) {
245-
serviceIntent.setAction(TransportConstants.BIND_REQUEST_TYPE_ALT_TRANSPORT);
246-
}
247-
if(device != null){
248-
serviceIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
249-
}
250-
try {
251-
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
252-
context.startService(serviceIntent);
253-
}else {
254-
serviceIntent.putExtra(FOREGROUND_EXTRA, true);
255-
DebugTool.logInfo(TAG,"Attempting to startForegroundService - " + System.currentTimeMillis());
256-
setForegroundExceptionHandler(); //Prevent ANR in case the OS takes too long to start the service
257-
context.startForegroundService(serviceIntent);
258313

314+
} else { //There are currently running services
315+
if(DebugTool.isDebugEnabled()){
316+
for(ComponentName service : runningBluetoothServicePackage){
317+
DebugTool.logInfo("Currently running router service: " + service.getPackageName());
259318
}
260-
//Make sure to send this out for old apps to close down
261-
SdlRouterService.LocalRouterService self = SdlRouterService.getLocalRouterService(serviceIntent, serviceIntent.getComponent());
262-
Intent restart = new Intent(SdlRouterService.REGISTER_NEWER_SERVER_INSTANCE_ACTION);
263-
restart.putExtra(LOCAL_ROUTER_SERVICE_EXTRA, self);
264-
restart.putExtra(LOCAL_ROUTER_SERVICE_DID_START_OWN, true);
265-
context.sendBroadcast(restart);
266-
267-
} catch (SecurityException e) {
268-
DebugTool.logError(TAG, "Security exception, process is bad");
269319
}
270-
} else {
271320
if (altTransportWake) {
272321
wakeRouterServiceAltTransport(context);
273322
return;
@@ -280,15 +329,19 @@ public void onComplete(Vector<ComponentName> routerServices) {
280329
}
281330
}
282331
});
283-
return true;
332+
return true;
284333
}
285334

286335
private void wakeRouterServiceAltTransport(Context context){
287336
Intent serviceIntent = new Intent();
288337
serviceIntent.setAction(TransportConstants.BIND_REQUEST_TYPE_ALT_TRANSPORT);
289338
for (ComponentName compName : runningBluetoothServicePackage) {
290339
serviceIntent.setComponent(compName);
291-
context.startService(serviceIntent);
340+
try{
341+
context.startService(serviceIntent);
342+
} catch (Exception e){
343+
DebugTool.logError(TAG, "Can't start router service for alt transport");
344+
}
292345

293346
}
294347
}
@@ -328,10 +381,9 @@ public void uncaughtException(Thread t, Throwable e) {
328381
* Determines if an instance of the Router Service is currently running on the device.<p>
329382
* <b>Note:</b> This method no longer works on Android Oreo or newer
330383
* @param context A context to access Android system services through.
331-
* @param pingService Set this to true if you want to make sure the service is up and listening to bluetooth
332384
* @return True if a SDL Router Service is currently running, false otherwise.
333385
*/
334-
private static boolean isRouterServiceRunning(Context context, boolean pingService){
386+
private static boolean isRouterServiceRunning(Context context){
335387
if(context == null){
336388
DebugTool.logError(TAG, "Can't look for router service, context supplied was null");
337389
return false;
@@ -355,17 +407,15 @@ private static boolean isRouterServiceRunning(Context context, boolean pingServi
355407
//Log.d(TAG, "Found Service: "+ service.service.getClassName());
356408
if ((service.service.getClassName()).toLowerCase(Locale.US).contains(SDL_ROUTER_SERVICE_CLASS_NAME) && AndroidTools.isServiceExported(context, service.service)) {
357409
runningBluetoothServicePackage.add(service.service); //Store which instance is running
358-
if (pingService) {
359-
pingRouterService(context, service.service.getPackageName(), service.service.getClassName());
360-
}
361410
}
362411
}
363412
return runningBluetoothServicePackage.size() > 0;
364413

365414
}
366415

367416
/**
368-
* Attempts to ping a running router service
417+
* Attempts to ping a running router service. It does call startForegroundService so it is
418+
* important to only call this as a ping if the service is already started.
369419
* @param context A context to access Android system services through.
370420
* @param packageName Package name for service to ping
371421
* @param className Class name for service to ping
@@ -430,7 +480,7 @@ private static void requestTransportStatus(Context context, final SdlRouterStatu
430480
}
431481
return;
432482
}
433-
if((!lookForServices || isRouterServiceRunning(context,false)) && !runningBluetoothServicePackage.isEmpty()){ //So there is a service up, let's see if it's connected
483+
if((!lookForServices || isRouterServiceRunning(context)) && !runningBluetoothServicePackage.isEmpty()){ //So there is a service up, let's see if it's connected
434484
final ConcurrentLinkedQueue<ComponentName> list = new ConcurrentLinkedQueue<ComponentName>(runningBluetoothServicePackage);
435485
final SdlRouterStatusProvider.ConnectedStatusCallback sdlBrCallback = new SdlRouterStatusProvider.ConnectedStatusCallback() {
436486

@@ -470,12 +520,13 @@ public void onListObtained(boolean successful) {
470520
}else{
471521
DebugTool.logWarning(TAG, "Router service isn't running, returning false.");
472522
if(isBluetoothConnected()){
473-
DebugTool.logInfo(TAG, "Bluetooth is connected. Attempting to start Router Service");
523+
DebugTool.logInfo(TAG, "Bluetooth is connected. Attempting to ping Router Service");
474524
Intent serviceIntent = new Intent();
475525
serviceIntent.setAction(TransportConstants.START_ROUTER_SERVICE_ACTION);
476526
serviceIntent.putExtra(TransportConstants.PING_ROUTER_SERVICE_EXTRA, true);
477-
AndroidTools.sendExplicitBroadcast(context,serviceIntent,null);
527+
AndroidTools.sendExplicitBroadcast(context, serviceIntent,null);
478528
}
529+
479530
if(callback!=null){
480531
callback.onConnectionStatusUpdate(false, null,context);
481532
}
@@ -499,6 +550,49 @@ private static boolean isBluetoothConnected() {
499550
return false;
500551
}
501552

553+
554+
private static SdlDeviceListener getSdlDeviceListener(Context context, BluetoothDevice bluetoothDevice){
555+
556+
synchronized (DEVICE_LISTENER_LOCK){
557+
if (sdlDeviceListener == null){
558+
sdlDeviceListener = new SdlDeviceListener(context, bluetoothDevice, new SdlDeviceListener.Callback() {
559+
@Override
560+
public boolean onTransportConnected(Context context, BluetoothDevice bluetoothDevice) {
561+
562+
synchronized (DEVICE_LISTENER_LOCK){
563+
sdlDeviceListener = null;
564+
if(context != null) {
565+
final List<SdlAppInfo> sdlAppInfoList = AndroidTools.querySdlAppInfo(context, new SdlAppInfo.BestRouterComparator());
566+
if(sdlAppInfoList != null && !sdlAppInfoList.isEmpty()) {
567+
ComponentName routerService = sdlAppInfoList.get(0).getRouterServiceComponentName();
568+
startRouterService(context, routerService, false, bluetoothDevice, true);
569+
}
570+
}
571+
}
572+
573+
return false;
574+
}
575+
576+
@Override
577+
public void onTransportDisconnected(BluetoothDevice bluetoothDevice) {
578+
synchronized (DEVICE_LISTENER_LOCK){
579+
sdlDeviceListener = null;
580+
}
581+
}
582+
583+
@Override
584+
public void onTransportError(BluetoothDevice bluetoothDevice) {
585+
synchronized (DEVICE_LISTENER_LOCK){
586+
sdlDeviceListener = null;
587+
}
588+
}
589+
});
590+
}
591+
}
592+
593+
return sdlDeviceListener;
594+
}
595+
502596
public static ComponentName consumeQueuedRouterService(){
503597
synchronized(QUEUED_SERVICE_LOCK){
504598
ComponentName retVal = queuedService;

android/sdl_android/src/main/java/com/smartdevicelink/transport/SdlRouterService.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ public class SdlRouterService extends Service{
139139
/**
140140
* <b> NOTE: DO NOT MODIFY THIS UNLESS YOU KNOW WHAT YOU'RE DOING.</b>
141141
*/
142-
protected static final int ROUTER_SERVICE_VERSION_NUMBER = 12;
142+
protected static final int ROUTER_SERVICE_VERSION_NUMBER = 13;
143143

144144
private static final String ROUTER_SERVICE_PROCESS = "com.smartdevicelink.router";
145145

@@ -1258,7 +1258,9 @@ public int onStartCommand(Intent intent, int flags, int startId) {
12581258
address = device.getAddress();
12591259
}
12601260
}
1261-
int timeout = getNotificationTimeout(address);
1261+
boolean confirmedDevice = intent.getBooleanExtra(TransportConstants.CONFIRMED_SDL_DEVICE, false);
1262+
int timeout = getNotificationTimeout(address, confirmedDevice);
1263+
12621264
enterForeground("Waiting for connection...", timeout, false);
12631265
resetForegroundTimeOut(timeout);
12641266
} else {
@@ -1382,9 +1384,9 @@ private void notifyAltTransportOfClose(int reason){
13821384
* @return the amount of time for a timeout handler to remove the notification.
13831385
*/
13841386
@SuppressLint("MissingPermission")
1385-
private int getNotificationTimeout(String address){
1387+
private int getNotificationTimeout(String address, boolean confirmedDevice){
13861388
if(address != null){
1387-
if(hasSDLConnected(address)){
1389+
if(confirmedDevice || hasSDLConnected(address)){
13881390
return FOREGROUND_TIMEOUT * 2;
13891391
}else if(this.isFirstStatusCheck(address)) {
13901392
// If this is the first time the service has ever connected to this device we want

android/sdl_android/src/main/java/com/smartdevicelink/transport/TransportManager.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
import com.smartdevicelink.protocol.SdlPacket;
4949
import com.smartdevicelink.protocol.enums.ControlFrameTags;
5050
import com.smartdevicelink.transport.enums.TransportType;
51+
import com.smartdevicelink.transport.utl.SdlDeviceListener;
5152
import com.smartdevicelink.transport.utl.TransportRecord;
5253
import com.smartdevicelink.util.DebugTool;
5354

@@ -99,7 +100,7 @@ public void onFinishedValidation(boolean valid, ComponentName name) {
99100
if (valid) {
100101
mConfig.service = name;
101102
transport = new TransportBrokerImpl(contextWeakReference.get(), mConfig.appId, mConfig.service);
102-
DebugTool.logInfo(TAG, "TransportManager start got called; transport=" + transport);
103+
DebugTool.logInfo(TAG, "TransportManager start was called; transport=" + transport);
103104
if(transport != null){
104105
transport.start();
105106
}
@@ -301,6 +302,16 @@ public synchronized boolean onHardwareConnected(List<TransportRecord> transports
301302
transportStatus.clear();
302303
transportStatus.addAll(transports);
303304
}
305+
//If a bluetooth device has connected, make sure to save the mac address in the case
306+
//this app is asked to host the router service, the app knows to do so immediately on connection.
307+
if(transports != null && transports.size() > 0) {
308+
for (TransportRecord record : transports) {
309+
if(record != null && TransportType.BLUETOOTH.equals(record.getType())) {
310+
SdlDeviceListener.setSDLConnectedStatus(contextWeakReference.get(), record.getAddress(),true);
311+
}
312+
}
313+
}
314+
304315
transportListener.onTransportConnected(transports);
305316
return true;
306317
}

0 commit comments

Comments
 (0)