summaryrefslogtreecommitdiff
path: root/android/sdl_android/src/main/java/com/smartdevicelink/transport/SdlBroadcastReceiver.java
diff options
context:
space:
mode:
Diffstat (limited to 'android/sdl_android/src/main/java/com/smartdevicelink/transport/SdlBroadcastReceiver.java')
-rw-r--r--android/sdl_android/src/main/java/com/smartdevicelink/transport/SdlBroadcastReceiver.java74
1 files changed, 64 insertions, 10 deletions
diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/transport/SdlBroadcastReceiver.java b/android/sdl_android/src/main/java/com/smartdevicelink/transport/SdlBroadcastReceiver.java
index 93f6cc850..7bed1b482 100644
--- a/android/sdl_android/src/main/java/com/smartdevicelink/transport/SdlBroadcastReceiver.java
+++ b/android/sdl_android/src/main/java/com/smartdevicelink/transport/SdlBroadcastReceiver.java
@@ -66,6 +66,7 @@ import java.util.Locale;
import java.util.Vector;
import java.util.concurrent.ConcurrentLinkedQueue;
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
import static com.smartdevicelink.transport.TransportConstants.FOREGROUND_EXTRA;
public abstract class SdlBroadcastReceiver extends BroadcastReceiver {
@@ -73,6 +74,7 @@ public abstract class SdlBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = "Sdl Broadcast Receiver";
protected static final String SDL_ROUTER_SERVICE_CLASS_NAME = "sdlrouterservice";
+ protected static final int ANDROID_12_ROUTER_SERVICE_VERSION = 16;
public static final String LOCAL_ROUTER_SERVICE_EXTRA = "router_service";
public static final String LOCAL_ROUTER_SERVICE_DID_START_OWN = "did_start";
@@ -90,6 +92,7 @@ public abstract class SdlBroadcastReceiver extends BroadcastReceiver {
private static Thread.UncaughtExceptionHandler foregroundExceptionHandler = null;
private static final Object DEVICE_LISTENER_LOCK = new Object();
private static SdlDeviceListener sdlDeviceListener;
+ private static String serviceName = null;
public int getRouterServiceVersion() {
return SdlRouterService.ROUTER_SERVICE_VERSION_NUMBER;
@@ -98,6 +101,7 @@ public abstract class SdlBroadcastReceiver extends BroadcastReceiver {
@Override
@CallSuper
public void onReceive(Context context, Intent intent) {
+
//Log.i(TAG, "Sdl Receiver Activated");
final String action = intent.getAction();
if (action == null) {
@@ -132,6 +136,10 @@ public abstract class SdlBroadcastReceiver extends BroadcastReceiver {
device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
}
+ if (serviceName == null) {
+ serviceName = getSdlServiceName();
+ }
+
boolean didStart = false;
if (localRouterClass == null) {
localRouterClass = defineLocalSdlRouterClass();
@@ -296,6 +304,18 @@ public abstract class SdlBroadcastReceiver extends BroadcastReceiver {
String routerServicePackage = null;
if (sdlAppInfoList != null && !sdlAppInfoList.isEmpty() && sdlAppInfoList.get(0).getRouterServiceComponentName() != null) {
routerServicePackage = sdlAppInfoList.get(0).getRouterServiceComponentName().getPackageName();
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ // If all apps have a RS newer than the Android 12 update, chosen app does not have BT Connect permissions, and more than 1 sdl app is installed
+ if (!isPreAndroid12RSOnDevice(sdlAppInfoList) && !AndroidTools.isPermissionGranted(BLUETOOTH_CONNECT, context, routerServicePackage) && sdlAppInfoList.size() > 1) {
+ for (SdlAppInfo appInfo : sdlAppInfoList) {
+ if (AndroidTools.isPermissionGranted(BLUETOOTH_CONNECT, context, appInfo.getRouterServiceComponentName().getPackageName())) {
+ //If this app in the list has BT Connect permissions, we want to use that apps RS
+ routerServicePackage = appInfo.getRouterServiceComponentName().getPackageName();
+ break;
+ }
+ }
+ }
+ }
}
DebugTool.logInfo(TAG, ": This app's package: " + myPackage);
DebugTool.logInfo(TAG, ": Router service app's package: " + routerServicePackage);
@@ -362,13 +382,16 @@ public abstract class SdlBroadcastReceiver extends BroadcastReceiver {
}
/**
- * This method will set a new UncaughtExceptionHandler for the current thread. The only
- * purpose of the custom UncaughtExceptionHandler is to catch the rare occurrence that the
- * SdlRouterService can't be started fast enough by the system after calling
- * startForegroundService so the onCreate method doesn't get called before the foreground promise
- * timer expires. The new UncaughtExceptionHandler will catch that specific exception and tell the
- * main looper to continue forward. This still leaves the SdlRouterService killed, but prevents
- * an ANR to the app that makes the startForegroundService call.
+ * This method will set a new UncaughtExceptionHandler for the current thread.
+ * There are two exceptions we want to catch here. The first exception is the rare
+ * occurrence that the SdlRouterService can't be started fast enough by the system after calling
+ * startForegroundService so the onCreate method doesn't get called before the foreground
+ * promise timer expires. The second is for the instance where the developers "SdlService" class
+ * can't be started fast enough by the system after calling startForegroundService OR the app
+ * is unable to start the "SdlService" class because the developer did not export the service
+ * in the manifest. The new UncaughtExceptionHandler will catch these specific exception and
+ * tell the main looper to continue forward. This still leaves the respective Service killed,
+ * but prevents an ANR to the app that makes the startForegroundService call.
*/
static protected void setForegroundExceptionHandler() {
final Thread.UncaughtExceptionHandler defaultUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
@@ -378,10 +401,9 @@ public abstract class SdlBroadcastReceiver extends BroadcastReceiver {
public void uncaughtException(Thread t, Throwable e) {
if (e != null
&& e instanceof AndroidRuntimeException
- && "android.app.RemoteServiceException".equals(e.getClass().getName()) //android.app.RemoteServiceException is a private class
+ && ("android.app.RemoteServiceException".equals(e.getClass().getName()) || "android.app.ForegroundServiceDidNotStartInTimeException".equals(e.getClass().getName())) //android.app.RemoteServiceException is a private class
&& e.getMessage() != null
- && e.getMessage().contains("SdlRouterService")) {
-
+ && (e.getMessage().contains("SdlRouterService")) || e.getMessage().contains(serviceName)) {
DebugTool.logInfo(TAG, "Handling failed startForegroundService call");
Looper.loop();
} else if (defaultUncaughtExceptionHandler != null) { //No other exception should be handled
@@ -598,6 +620,18 @@ public abstract class SdlBroadcastReceiver extends BroadcastReceiver {
final List<SdlAppInfo> sdlAppInfoList = AndroidTools.querySdlAppInfo(context, new SdlAppInfo.BestRouterComparator(), vehicleType);
if (sdlAppInfoList != null && !sdlAppInfoList.isEmpty()) {
ComponentName routerService = sdlAppInfoList.get(0).getRouterServiceComponentName();
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ // If all apps have a RS newer than the Android 12 update, chosen app does not have BT Connect permissions, and more than 1 sdl app is installed
+ if (!isPreAndroid12RSOnDevice(sdlAppInfoList) && !AndroidTools.isPermissionGranted(BLUETOOTH_CONNECT, context, routerService.getPackageName()) && sdlAppInfoList.size() > 1) {
+ for (SdlAppInfo appInfo : sdlAppInfoList) {
+ if (AndroidTools.isPermissionGranted(BLUETOOTH_CONNECT, context, appInfo.getRouterServiceComponentName().getPackageName())) {
+ routerService = appInfo.getRouterServiceComponentName();
+ //If this app in the list has BT Connect permissions, we want to use that apps RS
+ break;
+ }
+ }
+ }
+ }
startRouterService(context, routerService, false, bluetoothDevice, true, vehicleType);
}
}
@@ -634,6 +668,16 @@ public abstract class SdlBroadcastReceiver extends BroadcastReceiver {
}
}
+ private static boolean isPreAndroid12RSOnDevice(List<SdlAppInfo> sdlAppInfoList) {
+ for (SdlAppInfo appInfo : sdlAppInfoList) {
+ //If an installed app RS version is older than Android 12 update version (16)
+ if (appInfo.getRouterServiceVersion() < ANDROID_12_ROUTER_SERVICE_VERSION) {
+ return true;
+ }
+ }
+ return false;
+ }
+
/**
* We need to define this for local copy of the Sdl Router Service class.
* It will be the main point of connection for Sdl enabled apps
@@ -656,6 +700,16 @@ public abstract class SdlBroadcastReceiver extends BroadcastReceiver {
*/
public abstract void onSdlEnabled(Context context, Intent intent);
+
+ /**
+ * The developer can override this method to return the name of the class that manages their
+ * SdlService. This method is used to ensure the SdlBroadcastReceivers exception catcher catches
+ * the correct exception that may be thrown by the app trying to start their SdlService. If this
+ * exception is not caught the user may experience an ANR for that app.
+ */
+ public String getSdlServiceName() {
+ return "SdlService";
+ }
//public abstract void onSdlDisabled(Context context); //Removing for now until we're able to abstract from developer