summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoey Grover <joeygrover@gmail.com>2022-04-13 11:03:25 -0400
committerGitHub <noreply@github.com>2022-04-13 11:03:25 -0400
commit16b2ab698a70294c0e060dd88883936a6288b6b8 (patch)
treeb3b1fed7243708b656290d8496453cb01bb1b911
parentdb5c9438505c4a3a64d2e6a16b36b3a61358a3e9 (diff)
parenta174b5d63917985c428af4524ee167fcda6d4207 (diff)
downloadsdl_android-16b2ab698a70294c0e060dd88883936a6288b6b8.tar.gz
Merge pull request #1795 from smartdevicelink/5.4.0_RC5.4.0
Release 5.4.0
-rw-r--r--CHANGELOG.md51
-rw-r--r--VERSION2
-rwxr-xr-xandroid/hello_sdl_android/build.gradle4
-rwxr-xr-xandroid/hello_sdl_android/src/main/AndroidManifest.xml5
-rwxr-xr-xandroid/hello_sdl_android/src/main/java/com/sdl/hellosdlandroid/MainActivity.java43
-rwxr-xr-xandroid/hello_sdl_android/src/main/java/com/sdl/hellosdlandroid/SdlReceiver.java33
-rwxr-xr-xandroid/hello_sdl_android/src/main/java/com/sdl/hellosdlandroid/SdlService.java9
-rw-r--r--android/sdl_android/build.gradle8
-rw-r--r--android/sdl_android/gradle.properties1
-rw-r--r--android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/AlertManagerTest.java4
-rw-r--r--android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/PresentAlertOperationTest.java4
-rw-r--r--android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/ScreenManagerTests.java37
-rw-r--r--android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/SoftButtonManagerTests.java122
-rw-r--r--android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/ChoiceSetManagerTests.java10
-rw-r--r--android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/PreloadPresentChoicesOperationTests.java4
-rw-r--r--android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuConfigurationUpdateOperationTests.java4
-rw-r--r--android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuManagerTests.java9
-rw-r--r--android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuReplaceUtilitiesTests.java102
-rw-r--r--android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuShowOperationTests.java4
-rw-r--r--android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/VoiceCommandUpdateOperationTests.java45
-rw-r--r--android/sdl_android/src/androidTest/java/com/smartdevicelink/test/TestValues.java2
-rw-r--r--android/sdl_android/src/androidTest/java/com/smartdevicelink/test/Validator.java4
-rw-r--r--android/sdl_android/src/androidTest/java/com/smartdevicelink/test/protocol/SecurityQueryPayloadTests.java31
-rw-r--r--android/sdl_android/src/androidTest/java/com/smartdevicelink/test/protocol/enums/SecurityQueryIDTests.java4
-rw-r--r--android/sdl_android/src/androidTest/java/com/smartdevicelink/test/protocol/enums/SecurityQueryTypeTests.java2
-rw-r--r--android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/RPCGenericTests.java6
-rw-r--r--android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/AppCapabilityTests.java10
-rw-r--r--android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/RoofStatusTests.java8
-rw-r--r--android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/VideoStreamingCapabilityTests.java12
-rw-r--r--android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/WindowCapabilityTests.java2
-rw-r--r--android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/AppCapabilityTypeTests.java6
-rw-r--r--android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/notifications/OnAppCapabilityUpdatedTests.java16
-rw-r--r--android/sdl_android/src/main/java/com/smartdevicelink/encoder/VirtualDisplayEncoder.java34
-rw-r--r--android/sdl_android/src/main/java/com/smartdevicelink/managers/SdlManager.java58
-rw-r--r--android/sdl_android/src/main/java/com/smartdevicelink/managers/file/filetypes/SdlFile.java4
-rw-r--r--android/sdl_android/src/main/java/com/smartdevicelink/managers/lifecycle/LifecycleManager.java111
-rw-r--r--android/sdl_android/src/main/java/com/smartdevicelink/managers/lockscreen/LockScreenManager.java2
-rw-r--r--android/sdl_android/src/main/java/com/smartdevicelink/managers/video/VideoStreamManager.java73
-rw-r--r--android/sdl_android/src/main/java/com/smartdevicelink/managers/video/resolution/VideoStreamingRange.java2
-rw-r--r--android/sdl_android/src/main/java/com/smartdevicelink/transport/MultiplexBluetoothTransport.java2
-rw-r--r--android/sdl_android/src/main/java/com/smartdevicelink/transport/SdlBroadcastReceiver.java76
-rw-r--r--android/sdl_android/src/main/java/com/smartdevicelink/transport/SdlRouterService.java215
-rw-r--r--android/sdl_android/src/main/java/com/smartdevicelink/transport/USBAccessoryAttachmentActivity.java1
-rw-r--r--android/sdl_android/src/main/java/com/smartdevicelink/transport/utl/SdlDeviceListener.java15
-rw-r--r--android/sdl_android/src/main/java/com/smartdevicelink/util/AndroidTools.java29
-rw-r--r--android/sdl_android/src/main/java/com/smartdevicelink/util/SdlAppInfo.java8
-rw-r--r--android/sdl_android/src/main/res/values/sdl.xml2
-rw-r--r--android/sdl_android/src/main/res/values/strings.xml1
-rw-r--r--base/src/main/java/com/smartdevicelink/managers/BaseSdlManager.java93
-rw-r--r--base/src/main/java/com/smartdevicelink/managers/file/UploadFileOperation.java6
-rw-r--r--base/src/main/java/com/smartdevicelink/managers/lifecycle/BaseLifecycleManager.java188
-rw-r--r--base/src/main/java/com/smartdevicelink/managers/lifecycle/BaseSystemCapabilityManager.java12
-rw-r--r--base/src/main/java/com/smartdevicelink/managers/screen/DispatchGroup.java5
-rw-r--r--base/src/main/java/com/smartdevicelink/managers/screen/PresentAlertOperation.java24
-rw-r--r--base/src/main/java/com/smartdevicelink/managers/screen/SoftButtonObject.java49
-rw-r--r--base/src/main/java/com/smartdevicelink/managers/screen/SoftButtonReplaceOperation.java2
-rw-r--r--base/src/main/java/com/smartdevicelink/managers/screen/choiceset/ChoiceCell.java2
-rw-r--r--base/src/main/java/com/smartdevicelink/managers/screen/choiceset/PreloadPresentChoicesOperation.java20
-rw-r--r--base/src/main/java/com/smartdevicelink/managers/screen/menu/BaseVoiceCommandManager.java8
-rw-r--r--base/src/main/java/com/smartdevicelink/managers/screen/menu/DynamicMenuUpdateAlgorithm.java4
-rw-r--r--base/src/main/java/com/smartdevicelink/managers/screen/menu/MenuCell.java4
-rw-r--r--base/src/main/java/com/smartdevicelink/managers/screen/menu/MenuReplaceOperation.java22
-rw-r--r--base/src/main/java/com/smartdevicelink/managers/screen/menu/MenuReplaceUtilities.java74
-rw-r--r--base/src/main/java/com/smartdevicelink/managers/screen/menu/VoiceCommandUpdateOperation.java2
-rw-r--r--base/src/main/java/com/smartdevicelink/protocol/SdlProtocolBase.java5
-rw-r--r--base/src/main/java/com/smartdevicelink/protocol/SecurityQueryPayload.java63
-rw-r--r--base/src/main/java/com/smartdevicelink/proxy/RPCStruct.java12
-rw-r--r--base/src/main/java/com/smartdevicelink/proxy/rpc/AddCommand.java2
-rw-r--r--base/src/main/java/com/smartdevicelink/proxy/rpc/GetVehicleDataResponse.java2
-rw-r--r--base/src/main/java/com/smartdevicelink/proxy/rpc/ScrollableMessage.java10
-rw-r--r--base/src/main/java/com/smartdevicelink/proxy/rpc/Slider.java10
-rw-r--r--base/src/main/java/com/smartdevicelink/proxy/rpc/SubscribeVehicleDataResponse.java1
-rw-r--r--base/src/main/java/com/smartdevicelink/proxy/rpc/TireStatus.java1
-rw-r--r--base/src/main/java/com/smartdevicelink/proxy/rpc/UnsubscribeVehicleDataResponse.java1
-rw-r--r--base/src/main/java/com/smartdevicelink/proxy/rpc/VideoStreamingCapability.java2
-rw-r--r--base/src/main/java/com/smartdevicelink/proxy/rpc/enums/AppCapabilityType.java4
-rw-r--r--base/src/main/java/com/smartdevicelink/session/BaseSdlSession.java77
-rw-r--r--base/src/main/java/com/smartdevicelink/streaming/video/VideoStreamingParameters.java36
-rw-r--r--base/src/main/java/com/smartdevicelink/transport/SdlPsm.java10
-rw-r--r--base/src/main/java/com/smartdevicelink/transport/SiphonServer.java4
-rw-r--r--base/src/main/java/com/smartdevicelink/transport/TransportConstants.java2
-rw-r--r--base/src/main/java/com/smartdevicelink/util/FileUtls.java2
-rw-r--r--javaEE/hello_sdl_java_ee/src/main/java/com/smartdevicelink/SdlService.java4
-rw-r--r--javaEE/javaEE/build.gradle1
-rw-r--r--javaEE/javaEE/gradle.properties1
-rw-r--r--javaEE/javaEE/src/test/java/com/smartdevicelink/test/TestValues.java10
-rw-r--r--javaSE/javaSE/build.gradle3
-rw-r--r--javaSE/javaSE/gradle.properties1
-rw-r--r--javaSE/javaSE/src/main/java/com/smartdevicelink/BuildConfig.java2
-rw-r--r--javaSE/javaSE/src/main/java/com/smartdevicelink/managers/SdlManager.java27
-rw-r--r--javaSE/javaSE/src/main/java/com/smartdevicelink/managers/lifecycle/LifecycleManager.java6
-rw-r--r--javaSE/javaSE/src/main/java/com/smartdevicelink/managers/screen/AlertManager.java1
92 files changed, 1464 insertions, 588 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c5a689a7b..f7f1182d5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,14 +1,57 @@
-# 5.3.1 Release Notes
+# 5.4.0 Release Notes
## Summary:
||Version|
|--|--|
| **Protocol** | 5.4.1
| **RPC** | 8.0.0
-| **Tested Targeting** | Android 30
+| **Tested Targeting** | Android 31
## Bug Fixes / Enhancements:
-- [userDidSubmitInput getting called multiple times after a search request is submitted](https://github.com/smartdevicelink/sdl_java_suite/issues/1768)
+- [Video auto restarts streaming regardless if HMI level is streamable ](https://github.com/smartdevicelink/sdl_java_suite/issues/1807)
+
+- [Video Streaming Fails on Android 12 at Low Resolutions](https://github.com/smartdevicelink/sdl_java_suite/issues/1803)
+
+- [sdl_java_se uses deprecated testCompile in build.gradle](https://github.com/smartdevicelink/sdl_java_suite/issues/1805)
+
+- [Incorrect behavior and potential crashes in PresentAlertOperation.supportsSoftButtonImages()](https://github.com/smartdevicelink/sdl_java_suite/issues/1800)
+
+- [Bugfix/rs notification issue usb](https://github.com/smartdevicelink/sdl_java_suite/pull/1797)
+
+- [Attempting to Send Voice Command with No Strings Fails to Log Error](https://github.com/smartdevicelink/sdl_java_suite/issues/1798)
+
+- [Fix LCM to close down properly](https://github.com/smartdevicelink/sdl_java_suite/pull/1796)
+
+- [Cleanup/proposal sdl 0286 spacing](https://github.com/smartdevicelink/sdl_java_suite/pull/1782)
+
+- [API Reference Docs Typos](https://github.com/smartdevicelink/sdl_java_suite/issues/1792)
+
+- [Foreground Service Notifications can be delayed by 10 seconds](https://github.com/smartdevicelink/sdl_java_suite/issues/1733)
+
+- [Bluetooth Permission Requirements will change in Android 12](https://github.com/smartdevicelink/sdl_java_suite/issues/1732)
+
+- [[SDL 0345] Android 12 Issues](https://github.com/smartdevicelink/sdl_java_suite/issues/1794)
+
+- [SdlRouterService crashes if SDL app sets targetSdkVersion to 31, and running on Android 12](https://github.com/smartdevicelink/sdl_java_suite/issues/1751)
+
+- [Error Code is cut off from bulk data when reading a SEND_INTERNAL_ERROR query](https://github.com/smartdevicelink/sdl_java_suite/issues/1790)
+
+- [NPE crash in BaseLifecycleManager on checkLifecycleConfiguration](https://github.com/smartdevicelink/sdl_java_suite/issues/1783)
+
+- [NPE crash in SdlDeviceListener](https://github.com/smartdevicelink/sdl_java_suite/issues/1780)
+
+- [NPE crash in BaseLifecycleManager](https://github.com/smartdevicelink/sdl_java_suite/issues/1781)
+
+- [SoftButtonObject doesn't handle error states correctly](https://github.com/smartdevicelink/sdl_java_suite/issues/1774)
+
+- [ScrollableMessage.timeout units should be specified in documentation](https://github.com/smartdevicelink/sdl_java_suite/issues/1775)
+
+- [Incorrect SPP error notification presented to user](https://github.com/smartdevicelink/sdl_java_suite/issues/1661)
+
+- [SecurityQuery error notification payload not set](https://github.com/smartdevicelink/sdl_java_suite/issues/1753)
+
+- [Menu Manager won't send submenu cell images on RPC versions >= 5.0 && < 7.0 #2047](https://github.com/smartdevicelink/sdl_java_suite/issues/1756)
+
+- [GenerateSources gradle task in javaSE incorrectly reads the version from gradle.properties instead of VERSION file](https://github.com/smartdevicelink/sdl_java_suite/issues/1763)
-- [NPE in SoftButtonReplaceOperation](https://github.com/smartdevicelink/sdl_java_suite/issues/1767)
diff --git a/VERSION b/VERSION
index c7cb1311a..8a30e8f94 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-5.3.1
+5.4.0
diff --git a/android/hello_sdl_android/build.gradle b/android/hello_sdl_android/build.gradle
index 7640e89c5..5feeba93f 100755
--- a/android/hello_sdl_android/build.gradle
+++ b/android/hello_sdl_android/build.gradle
@@ -1,11 +1,11 @@
apply plugin: 'com.android.application'
android {
- compileSdkVersion 30
+ compileSdkVersion 31
defaultConfig {
applicationId "com.sdl.hellosdlandroid"
minSdkVersion 16
- targetSdkVersion 30
+ targetSdkVersion 31
versionCode 1
versionName "1.0"
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
diff --git a/android/hello_sdl_android/src/main/AndroidManifest.xml b/android/hello_sdl_android/src/main/AndroidManifest.xml
index 1183e7b2c..415aa66c2 100755
--- a/android/hello_sdl_android/src/main/AndroidManifest.xml
+++ b/android/hello_sdl_android/src/main/AndroidManifest.xml
@@ -4,6 +4,8 @@
package="com.sdl.hellosdlandroid">
<uses-permission android:name="android.permission.BLUETOOTH" />
+ <uses-permission android:name="android.permission.BLUETOOTH_CONNECT"
+ tools:targetApi="31"/>
<uses-permission android:name="android.permission.INTERNET" />
<!-- Required to check if WiFi is enabled -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
@@ -30,6 +32,7 @@
tools:ignore="DeepLinks">
<activity
android:name=".MainActivity"
+ android:exported="true"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -40,6 +43,7 @@
<activity
android:name="com.smartdevicelink.transport.USBAccessoryAttachmentActivity"
+ android:exported="true"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
@@ -52,6 +56,7 @@
<service
android:name="com.sdl.hellosdlandroid.SdlService"
+ android:exported="true"
android:foregroundServiceType="connectedDevice">
</service>
<service
diff --git a/android/hello_sdl_android/src/main/java/com/sdl/hellosdlandroid/MainActivity.java b/android/hello_sdl_android/src/main/java/com/sdl/hellosdlandroid/MainActivity.java
index 43ad79ac7..8497e3b73 100755
--- a/android/hello_sdl_android/src/main/java/com/sdl/hellosdlandroid/MainActivity.java
+++ b/android/hello_sdl_android/src/main/java/com/sdl/hellosdlandroid/MainActivity.java
@@ -1,27 +1,66 @@
package com.sdl.hellosdlandroid;
import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.Build;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
+import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.ContextCompat;
+
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
public class MainActivity extends AppCompatActivity {
+ private static final int REQUEST_CODE = 200;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
- //If we are connected to a module we want to start our SdlService
+
+
if (BuildConfig.TRANSPORT.equals("MULTI") || BuildConfig.TRANSPORT.equals("MULTI_HB")) {
+ if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && !checkPermission()) {
+ requestPermission();
+ return;
+ }
+ //If we are connected to a module we want to start our SdlService
SdlReceiver.queryForConnectedService(this);
- } else if (BuildConfig.TRANSPORT.equals("TCP")) {
+ } else if (BuildConfig.TRANSPORT.equals("TCP")){
Intent proxyIntent = new Intent(this, SdlService.class);
startService(proxyIntent);
}
}
+ private boolean checkPermission() {
+ return PackageManager.PERMISSION_GRANTED == ContextCompat.checkSelfPermission(getApplicationContext(), BLUETOOTH_CONNECT);
+ }
+
+ private void requestPermission() {
+ ActivityCompat.requestPermissions(this, new String[]{BLUETOOTH_CONNECT}, REQUEST_CODE);
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ switch (requestCode) {
+ case REQUEST_CODE:
+ if (grantResults.length > 0) {
+
+ boolean btConnectGranted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
+
+ if (btConnectGranted) {
+ SdlReceiver.queryForConnectedService(this);
+ }
+ }
+ break;
+ }
+ }
+
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
diff --git a/android/hello_sdl_android/src/main/java/com/sdl/hellosdlandroid/SdlReceiver.java b/android/hello_sdl_android/src/main/java/com/sdl/hellosdlandroid/SdlReceiver.java
index 32c0ab1d5..e130d3d78 100755
--- a/android/hello_sdl_android/src/main/java/com/sdl/hellosdlandroid/SdlReceiver.java
+++ b/android/hello_sdl_android/src/main/java/com/sdl/hellosdlandroid/SdlReceiver.java
@@ -1,11 +1,13 @@
package com.sdl.hellosdlandroid;
+import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import com.smartdevicelink.transport.SdlBroadcastReceiver;
import com.smartdevicelink.transport.SdlRouterService;
+import com.smartdevicelink.transport.TransportConstants;
import com.smartdevicelink.util.DebugTool;
public class SdlReceiver extends SdlBroadcastReceiver {
@@ -16,13 +18,27 @@ public class SdlReceiver extends SdlBroadcastReceiver {
DebugTool.logInfo(TAG, "SDL Enabled");
intent.setClass(context, SdlService.class);
- // SdlService needs to be foregrounded in Android O and above
- // This will prevent apps in the background from crashing when they try to start SdlService
- // Because Android O doesn't allow background apps to start background services
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- context.startForegroundService(intent);
+ // Starting with Android S SdlService needs to be started from a foreground context.
+ // We will check the intent for a pendingIntent parcelable extra
+ // This pendingIntent allows us to start the SdlService from the context of the active router service which is in the foreground
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ PendingIntent pendingIntent = (PendingIntent) intent.getParcelableExtra(TransportConstants.PENDING_INTENT_EXTRA);
+ if (pendingIntent != null) {
+ try {
+ pendingIntent.send(context, 0, intent);
+ } catch (PendingIntent.CanceledException e) {
+ e.printStackTrace();
+ }
+ }
} else {
- context.startService(intent);
+ // SdlService needs to be foregrounded in Android O and above
+ // This will prevent apps in the background from crashing when they try to start SdlService
+ // Because Android O doesn't allow background apps to start background services
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ context.startForegroundService(intent);
+ } else {
+ context.startService(intent);
+ }
}
}
@@ -35,4 +51,9 @@ public class SdlReceiver extends SdlBroadcastReceiver {
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent); // Required if overriding this method
}
+
+ @Override
+ public String getSdlServiceName() {
+ return SdlService.class.getSimpleName();
+ }
} \ No newline at end of file
diff --git a/android/hello_sdl_android/src/main/java/com/sdl/hellosdlandroid/SdlService.java b/android/hello_sdl_android/src/main/java/com/sdl/hellosdlandroid/SdlService.java
index c6e9ce3ef..59daf2050 100755
--- a/android/hello_sdl_android/src/main/java/com/sdl/hellosdlandroid/SdlService.java
+++ b/android/hello_sdl_android/src/main/java/com/sdl/hellosdlandroid/SdlService.java
@@ -108,10 +108,13 @@ public class SdlService extends Service {
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager != null) {
notificationManager.createNotificationChannel(channel);
- Notification serviceNotification = new Notification.Builder(this, channel.getId())
+ Notification.Builder builder = new Notification.Builder(this, channel.getId())
.setContentTitle("Connected through SDL")
- .setSmallIcon(R.drawable.ic_sdl)
- .build();
+ .setSmallIcon(R.drawable.ic_sdl);
+ if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ builder.setForegroundServiceBehavior(Notification.FOREGROUND_SERVICE_IMMEDIATE);
+ }
+ Notification serviceNotification = builder.build();
startForeground(FOREGROUND_SERVICE_ID, serviceNotification);
}
}
diff --git a/android/sdl_android/build.gradle b/android/sdl_android/build.gradle
index 489da844e..4f2548737 100644
--- a/android/sdl_android/build.gradle
+++ b/android/sdl_android/build.gradle
@@ -1,11 +1,11 @@
apply plugin: 'com.android.library'
android {
- compileSdkVersion 30
+ compileSdkVersion 31
defaultConfig {
minSdkVersion 16
- targetSdkVersion 30
- versionCode 21
+ targetSdkVersion 31
+ versionCode 22
versionName new File(projectDir.path, ('/../../VERSION')).text.trim()
buildConfigField "String", "VERSION_NAME", '\"' + versionName + '\"'
resValue "string", "SDL_LIB_VERSION", '\"' + versionName + '\"'
@@ -40,6 +40,8 @@ android {
}
}
+ext { VERSION_NAME = "$project.android.defaultConfig.versionName" }
+
dependencies {
api fileTree(dir: 'libs', include: ['*.jar'])
//api 'com.livio.taskmaster:taskmaster:0.6.0'
diff --git a/android/sdl_android/gradle.properties b/android/sdl_android/gradle.properties
index 3137d38b9..d720ac795 100644
--- a/android/sdl_android/gradle.properties
+++ b/android/sdl_android/gradle.properties
@@ -1,6 +1,5 @@
GROUP=com.smartdevicelink
POM_ARTIFACT_ID=sdl_android
-VERSION_NAME=5.3.1
POM_NAME=sdl_android
POM_PACKAGING=aar
diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/AlertManagerTest.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/AlertManagerTest.java
index 1655b3d08..1ebac1567 100644
--- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/AlertManagerTest.java
+++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/AlertManagerTest.java
@@ -68,9 +68,9 @@ public class AlertManagerTest {
public Void answer(InvocationOnMock invocation) {
Object[] args = invocation.getArguments();
OnPermissionChangeListener onPermissionChangeListener = (OnPermissionChangeListener) args[2];
- Map<FunctionID, PermissionStatus > allowedPermissions = new HashMap<>();
+ Map<FunctionID, PermissionStatus> allowedPermissions = new HashMap<>();
int permissionGroupStatus = PermissionManager.PERMISSION_GROUP_STATUS_DISALLOWED;
- onPermissionChangeListener.onPermissionsChange(allowedPermissions,permissionGroupStatus);
+ onPermissionChangeListener.onPermissionsChange(allowedPermissions, permissionGroupStatus);
return null;
}
};
diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/PresentAlertOperationTest.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/PresentAlertOperationTest.java
index 1283992a2..5f69010f1 100644
--- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/PresentAlertOperationTest.java
+++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/PresentAlertOperationTest.java
@@ -194,10 +194,10 @@ public class PresentAlertOperationTest {
windowCapability = getWindowCapability(2);
- presentAlertOperation = new PresentAlertOperation(internalInterface, alertView, windowCapability, speechCapabilities, fileManager, 1, alertCompletionListener, alertSoftButtonClearListener);
+ presentAlertOperation = new PresentAlertOperation(internalInterface, alertView, windowCapability, speechCapabilities, fileManager, 1, alertCompletionListener, alertSoftButtonClearListener);
alert = presentAlertOperation.alertRpc();
assertEquals(alert.getAlertText1(), alertView.getText());
- assertEquals(alert.getAlertText2(),alertView.getSecondaryText() + " - " + alertView.getTertiaryText());
+ assertEquals(alert.getAlertText2(), alertView.getSecondaryText() + " - " + alertView.getTertiaryText());
}
@Test
diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/ScreenManagerTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/ScreenManagerTests.java
index b5cecf26c..b5c0059c4 100644
--- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/ScreenManagerTests.java
+++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/ScreenManagerTests.java
@@ -209,22 +209,19 @@ public class ScreenManagerTests {
SoftButtonObject softButtonObject3 = new SoftButtonObject("object1", Arrays.asList(softButtonState1, softButtonState2), softButtonState1.getName(), null);
SoftButtonObject softButtonObject4 = new SoftButtonObject("object2", Arrays.asList(softButtonState3, softButtonState4), softButtonState3.getName(), null);
assertTrue(screenManager.checkAndAssignButtonIds(softButtonObjects, BaseScreenManager.ManagerLocation.SOFTBUTTON_MANAGER));
-
-
-
-
-
}
+
@Test
public void testAssigningIdsToSoftButtonObjects() {
+ SoftButtonState defaultState = new SoftButtonState("default", "hi", null);
SoftButtonObject sbo1, sbo2, sbo3, sbo4, sbo5;
// Case 1 - don't set id for any button (Manager should set ids automatically starting from 1 and up)
- sbo1 = new SoftButtonObject(null, Collections.EMPTY_LIST, null, null);
- sbo2 = new SoftButtonObject(null, Collections.EMPTY_LIST, null, null);
- sbo3 = new SoftButtonObject(null, Collections.EMPTY_LIST, null, null);
- sbo4 = new SoftButtonObject(null, Collections.EMPTY_LIST, null, null);
- sbo5 = new SoftButtonObject(null, Collections.EMPTY_LIST, null, null);
+ sbo1 = new SoftButtonObject(null, defaultState, null);
+ sbo2 = new SoftButtonObject(null, defaultState, null);
+ sbo3 = new SoftButtonObject(null, defaultState, null);
+ sbo4 = new SoftButtonObject(null, defaultState, null);
+ sbo5 = new SoftButtonObject(null, defaultState, null);
screenManager.checkAndAssignButtonIds(Arrays.asList(sbo1, sbo2, sbo3, sbo4, sbo5), BaseScreenManager.ManagerLocation.SOFTBUTTON_MANAGER);
assertEquals("SoftButtonObject id doesn't match the expected value", 1, sbo1.getButtonId());
assertEquals("SoftButtonObject id doesn't match the expected value", 2, sbo2.getButtonId());
@@ -234,15 +231,15 @@ public class ScreenManagerTests {
// Case 2 - Set ids for all buttons (Manager shouldn't alter the ids set by developer)
- sbo1 = new SoftButtonObject(null, Collections.EMPTY_LIST, null, null);
+ sbo1 = new SoftButtonObject(null, defaultState, null);
sbo1.setButtonId(100);
- sbo2 = new SoftButtonObject(null, Collections.EMPTY_LIST, null, null);
+ sbo2 = new SoftButtonObject(null, defaultState, null);
sbo2.setButtonId(200);
- sbo3 = new SoftButtonObject(null, Collections.EMPTY_LIST, null, null);
+ sbo3 = new SoftButtonObject(null, defaultState, null);
sbo3.setButtonId(300);
- sbo4 = new SoftButtonObject(null, Collections.EMPTY_LIST, null, null);
+ sbo4 = new SoftButtonObject(null, defaultState, null);
sbo4.setButtonId(400);
- sbo5 = new SoftButtonObject(null, Collections.EMPTY_LIST, null, null);
+ sbo5 = new SoftButtonObject(null, defaultState, null);
sbo5.setButtonId(500);
screenManager.checkAndAssignButtonIds(Arrays.asList(sbo1, sbo2, sbo3, sbo4, sbo5), BaseScreenManager.ManagerLocation.SOFTBUTTON_MANAGER);
assertEquals("SoftButtonObject id doesn't match the expected value", 100, sbo1.getButtonId());
@@ -253,13 +250,13 @@ public class ScreenManagerTests {
// Case 3 - Set ids for some buttons (Manager shouldn't alter the ids set by developer. And it should assign ids for the ones that don't have id)
- sbo1 = new SoftButtonObject(null, Collections.EMPTY_LIST, null, null);
+ sbo1 = new SoftButtonObject(null, defaultState, null);
sbo1.setButtonId(50);
- sbo2 = new SoftButtonObject(null, Collections.EMPTY_LIST, null, null);
- sbo3 = new SoftButtonObject(null, Collections.EMPTY_LIST, null, null);
- sbo4 = new SoftButtonObject(null, Collections.EMPTY_LIST, null, null);
+ sbo2 = new SoftButtonObject(null, defaultState, null);
+ sbo3 = new SoftButtonObject(null, defaultState, null);
+ sbo4 = new SoftButtonObject(null, defaultState, null);
sbo4.setButtonId(100);
- sbo5 = new SoftButtonObject(null, Collections.EMPTY_LIST, null, null);
+ sbo5 = new SoftButtonObject(null, defaultState, null);
screenManager.checkAndAssignButtonIds(Arrays.asList(sbo1, sbo2, sbo3, sbo4, sbo5), BaseScreenManager.ManagerLocation.SOFTBUTTON_MANAGER);
assertEquals("SoftButtonObject id doesn't match the expected value", 50, sbo1.getButtonId());
assertEquals("SoftButtonObject id doesn't match the expected value", 101, sbo2.getButtonId());
diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/SoftButtonManagerTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/SoftButtonManagerTests.java
index becc01a74..67e7384e9 100644
--- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/SoftButtonManagerTests.java
+++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/SoftButtonManagerTests.java
@@ -44,6 +44,7 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+
import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertFalse;
import static junit.framework.TestCase.assertNull;
@@ -350,8 +351,8 @@ public class SoftButtonManagerTests {
softButtonStateList.add(softButtonState1);
softButtonStateList2.add(softButtonState1);
softButtonStateList2.add(softButtonState2);
- softButtonObject1 = new SoftButtonObject("hi", softButtonStateList, "Hi", null);
- softButtonObject2 = new SoftButtonObject("hi", softButtonStateList2, "Hi", null);
+ softButtonObject1 = new SoftButtonObject("hi", softButtonStateList, softButtonStateList.get(0).getName(), null);
+ softButtonObject2 = new SoftButtonObject("hi", softButtonStateList2, softButtonStateList2.get(0).getName(), null);
assertNotEquals(softButtonObject1, softButtonObject2);
// Case 5: SoftButtonStates are not the same, assertFalse
@@ -365,8 +366,8 @@ public class SoftButtonManagerTests {
assertNotEquals(softButtonObject1, softButtonObject2);
// Case 7: SoftButtonObject currentStateName not same, assertFalse
- softButtonObject1 = new SoftButtonObject("hi", softButtonStateList, "Hi", null);
- softButtonObject2 = new SoftButtonObject("hi", softButtonStateList, "Hi2", null);
+ softButtonObject1 = new SoftButtonObject("hi", softButtonStateList2, softButtonStateList2.get(0).getName(), null);
+ softButtonObject2 = new SoftButtonObject("hi", softButtonStateList2, softButtonStateList2.get(1).getName(), null);
assertNotEquals(softButtonObject1, softButtonObject2);
}
@@ -402,4 +403,117 @@ public class SoftButtonManagerTests {
softButtonState2 = new SoftButtonState("object1-state1", "o1s1", artwork1);
assertEquals(softButtonState1, softButtonState2);
}
+
+ /**
+ * Test constructing SoftButtonObject with an empty state list
+ */
+ @Test
+ public void testConstructSoftButtonObjectWithEmptyStateList() {
+ List<SoftButtonState> stateList = new ArrayList<>();
+ SoftButtonObject softButtonObject = new SoftButtonObject("hello_there", stateList, "general_kenobi", null);
+ assertNull(softButtonObject.getStates());
+ }
+
+ /**
+ * Test constructing SoftButtonObject with an nonempty state list
+ */
+ @Test
+ public void testConstructSoftButtonObjectWithNonEmptyStateList() {
+ List<SoftButtonState> stateList = new ArrayList<>();
+ SoftButtonState softButtonState = new SoftButtonState("general_kenobi", "General Kenobi", null);
+ stateList.add(softButtonState);
+ SoftButtonObject softButtonObject = new SoftButtonObject("hello_there", stateList, "general_kenobi", null);
+ assertEquals(stateList, softButtonObject.getStates());
+ }
+
+ /**
+ * Test constructing SoftButtonObject with an invalid initialStateName
+ */
+ @Test
+ public void testConstructSoftButtonObjectWithInvalidInitialStateName() {
+ List<SoftButtonState> stateList = new ArrayList<>();
+ SoftButtonState softButtonState = new SoftButtonState("general_kenobi", "General Kenobi", null);
+ stateList.add(softButtonState);
+ SoftButtonObject softButtonObject = new SoftButtonObject("hello_there", stateList, "hello_there", null);
+ assertNull(softButtonObject.getStates());
+ }
+
+ /**
+ * Test assigning an empty state list to existing SoftButtonObject
+ */
+ @Test
+ public void testAssignEmptyStateListToSoftButtonObject() {
+ List<SoftButtonState> nonEmptyStateList = new ArrayList<>();
+ List<SoftButtonState> emptyStateList = new ArrayList<>();
+ SoftButtonState softButtonState = new SoftButtonState("general_kenobi", "General Kenobi", null);
+ nonEmptyStateList.add(softButtonState);
+
+ SoftButtonObject softButtonObject = new SoftButtonObject("hello_there", nonEmptyStateList, "general_kenobi", null);
+
+ softButtonObject.setStates(emptyStateList);
+ assertEquals(nonEmptyStateList, softButtonObject.getStates());
+ }
+
+ /**
+ * Test assigning a state list with the current state to existing SoftButtonObject
+ */
+ @Test
+ public void testAssignStateListWithCurrentStateToSoftButtonObject() {
+ List<SoftButtonState> stateList1 = new ArrayList<>();
+ SoftButtonState softButtonState1 = new SoftButtonState("hello_there", "Hello there", null);
+ stateList1.add(softButtonState1);
+
+ List<SoftButtonState> stateList2 = new ArrayList<>();
+ SoftButtonState softButtonState2 = new SoftButtonState("general_kenobi", "General Kenobi", null);
+ stateList2.add(softButtonState1);
+ stateList2.add(softButtonState2);
+
+ SoftButtonObject softButtonObject = new SoftButtonObject("general_kenobi", stateList1, "hello_there", null);
+
+ softButtonObject.setStates(stateList2);
+
+ assertEquals(stateList2, softButtonObject.getStates());
+ }
+
+ /**
+ * Test assigning a state list without the current state to existing SoftButtonObject
+ */
+ @Test
+ public void testAssignStateListWithoutCurrentStateToSoftButtonObject() {
+ List<SoftButtonState> stateList1 = new ArrayList<>();
+ SoftButtonState softButtonState1 = new SoftButtonState("hello_there", "Hello there", null);
+ stateList1.add(softButtonState1);
+
+ List<SoftButtonState> stateList2 = new ArrayList<>();
+ SoftButtonState softButtonState2 = new SoftButtonState("general_kenobi", "General Kenobi", null);
+ stateList2.add(softButtonState2);
+
+ SoftButtonObject softButtonObject = new SoftButtonObject("general_kenobi", stateList1, "hello_there", null);
+
+ softButtonObject.setStates(stateList2);
+
+ assertEquals(stateList2, softButtonObject.getStates());
+ }
+
+ /**
+ * Test assigning a state list with states that have the same name to existing SoftButtonObject
+ */
+ @Test
+ public void testAssignSameNameStateListToSoftButtonObject() {
+ List<SoftButtonState> stateListUnique = new ArrayList<>();
+ SoftButtonState softButtonState1 = new SoftButtonState("hello_there", "Hello there", null);
+ stateListUnique.add(softButtonState1);
+
+ List<SoftButtonState> stateListDuplicateNames = new ArrayList<>();
+ SoftButtonState softButtonState2 = new SoftButtonState("general_kenobi", "General Kenobi", null);
+ stateListDuplicateNames.add(softButtonState2);
+ SoftButtonState softButtonState3 = new SoftButtonState("general_kenobi", "General Kenobi Again", null);
+ stateListDuplicateNames.add(softButtonState3);
+
+ SoftButtonObject softButtonObject = new SoftButtonObject("general_kenobi", stateListUnique, "hello_there", null);
+
+ softButtonObject.setStates(stateListDuplicateNames);
+
+ assertEquals(stateListUnique, softButtonObject.getStates());
+ }
}
diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/ChoiceSetManagerTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/ChoiceSetManagerTests.java
index f26a7a5c5..1315d2b66 100644
--- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/ChoiceSetManagerTests.java
+++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/ChoiceSetManagerTests.java
@@ -279,7 +279,7 @@ public class ChoiceSetManagerTests {
newCSM.setKeyboardConfiguration(newCSM.defaultKeyboardConfiguration());
Field field = BaseChoiceSetManager.class.getDeclaredField("keyboardConfiguration");
field.setAccessible(true);
- KeyboardProperties properties = (KeyboardProperties)field.get(newCSM);
+ KeyboardProperties properties = (KeyboardProperties) field.get(newCSM);
assertEquals(properties, csm.defaultKeyboardConfiguration());
// Test presentKeyboard
@@ -287,7 +287,7 @@ public class ChoiceSetManagerTests {
newCSM.presentKeyboard("qwerty", newCSM.defaultKeyboardConfiguration(), null);
field = BaseChoiceSetManager.class.getDeclaredField("keyboardConfiguration");
field.setAccessible(true);
- properties = (KeyboardProperties)field.get(newCSM);
+ properties = (KeyboardProperties) field.get(newCSM);
assertEquals(properties, csm.defaultKeyboardConfiguration());
}
@@ -314,7 +314,7 @@ public class ChoiceSetManagerTests {
Field field = BaseChoiceSetManager.class.getDeclaredField("keyboardConfiguration");
field.setAccessible(true);
- KeyboardProperties getProperties = (KeyboardProperties)field.get(newCSM);
+ KeyboardProperties getProperties = (KeyboardProperties) field.get(newCSM);
assertEquals(getProperties.getCustomKeys().size(), 1);
}
@@ -342,7 +342,7 @@ public class ChoiceSetManagerTests {
Field field = BaseChoiceSetManager.class.getDeclaredField("keyboardConfiguration");
field.setAccessible(true);
- KeyboardProperties getProperties = (KeyboardProperties)field.get(newCSM);
+ KeyboardProperties getProperties = (KeyboardProperties) field.get(newCSM);
assertNull(getProperties.getCustomKeys());
}
@@ -373,7 +373,7 @@ public class ChoiceSetManagerTests {
Field field = BaseChoiceSetManager.class.getDeclaredField("keyboardConfiguration");
field.setAccessible(true);
- KeyboardProperties getProperties = (KeyboardProperties)field.get(newCSM);
+ KeyboardProperties getProperties = (KeyboardProperties) field.get(newCSM);
assertNull(getProperties.getMaskInputCharacters());
}
diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/PreloadPresentChoicesOperationTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/PreloadPresentChoicesOperationTests.java
index 0f3725f53..8a8b8c64e 100644
--- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/PreloadPresentChoicesOperationTests.java
+++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/PreloadPresentChoicesOperationTests.java
@@ -344,7 +344,7 @@ public class PreloadPresentChoicesOperationTests {
when(internalInterface.getSdlMsgVersion()).thenReturn(new SdlMsgVersion(6, 0));
WindowCapability windowCapability = new WindowCapability();
HashSet<ChoiceCell> loadedCells = new HashSet<>();
- presentChoicesOperation = new PreloadPresentChoicesOperation(internalInterface, fileManager, choiceSet, InteractionMode.MANUAL_ONLY, null, null, TestValues.GENERAL_INTEGER,null, windowCapability, true, loadedCells, null, null);
+ presentChoicesOperation = new PreloadPresentChoicesOperation(internalInterface, fileManager, choiceSet, InteractionMode.MANUAL_ONLY, null, null, TestValues.GENERAL_INTEGER, null, windowCapability, true, loadedCells, null, null);
presentChoicesOperation.finishOperation(false);
assertEquals(Task.FINISHED, presentChoicesOperation.getState());
@@ -360,7 +360,7 @@ public class PreloadPresentChoicesOperationTests {
when(internalInterface.getSdlMsgVersion()).thenReturn(new SdlMsgVersion(6, 0));
WindowCapability windowCapability = new WindowCapability();
HashSet<ChoiceCell> loadedCells = new HashSet<>();
- presentChoicesOperation = new PreloadPresentChoicesOperation(internalInterface, fileManager, choiceSet, InteractionMode.MANUAL_ONLY, null, null, TestValues.GENERAL_INTEGER,null, windowCapability, true, loadedCells, null, null);
+ presentChoicesOperation = new PreloadPresentChoicesOperation(internalInterface, fileManager, choiceSet, InteractionMode.MANUAL_ONLY, null, null, TestValues.GENERAL_INTEGER, null, windowCapability, true, loadedCells, null, null);
presentChoicesOperation.cancelTask();
assertEquals(Task.CANCELED, presentChoicesOperation.getState());
diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuConfigurationUpdateOperationTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuConfigurationUpdateOperationTests.java
index c52cf6186..c6281652f 100644
--- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuConfigurationUpdateOperationTests.java
+++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuConfigurationUpdateOperationTests.java
@@ -192,7 +192,7 @@ public class MenuConfigurationUpdateOperationTests {
transactionQueue.add(operation, false);
}
- private Answer<Void> createSetGlobalPropertiesAnswer(final boolean success){
+ private Answer<Void> createSetGlobalPropertiesAnswer(final boolean success) {
return new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) {
@@ -206,7 +206,7 @@ public class MenuConfigurationUpdateOperationTests {
};
}
- private WindowCapability createWindowCapability (boolean supportsList, boolean supportsTile) {
+ private WindowCapability createWindowCapability(boolean supportsList, boolean supportsTile) {
WindowCapability windowCapability = new WindowCapability();
windowCapability.setMenuLayoutsAvailable(new ArrayList<MenuLayout>());
if (supportsList) {
diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuManagerTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuManagerTests.java
index 6f8bff69d..863f0b4d9 100644
--- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuManagerTests.java
+++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuManagerTests.java
@@ -145,7 +145,7 @@ public class MenuManagerTests {
@Override
public Void answer(InvocationOnMock invocation) {
Object[] args = invocation.getArguments();
- List<RPCMessage> rpcs = (List<RPCMessage>) args[0];
+ List<RPCMessage> rpcs = (List<RPCMessage>) args[0];
OnMultipleRequestListener listener = (OnMultipleRequestListener) args[1];
for (RPCMessage rpcMessage : rpcs) {
@@ -261,12 +261,15 @@ public class MenuManagerTests {
@Test
public void testUpdatingOldWay() {
+ ISdl internalInterface = mock(ISdl.class);
+ when(internalInterface.getSdlMsgVersion()).thenReturn(new SdlMsgVersion(new Version(8, 0, 0)));
+
// Force Menu Manager to use the old way of deleting / sending all
menuManager.setDynamicUpdatesMode(DynamicMenuUpdatesMode.FORCE_OFF);
assertEquals(menuManager.dynamicMenuUpdatesMode, DynamicMenuUpdatesMode.FORCE_OFF);
// when we only send one command to update, we should only be returned one add command
List<MenuCell> newArray = Arrays.asList(mainCell1, mainCell4);
- assertEquals(MenuReplaceUtilities.allCommandsForCells(newArray, menuManager.fileManager.get(), menuManager.windowCapability, MenuLayout.LIST).size(), 4); // 1 root cells, 1 sub menu root cell, 2 sub menu cells
+ assertEquals(MenuReplaceUtilities.allCommandsForCells(internalInterface, newArray, menuManager.fileManager.get(), menuManager.windowCapability, MenuLayout.LIST).size(), 4); // 1 root cells, 1 sub menu root cell, 2 sub menu cells
menuManager.currentHMILevel = HMILevel.HMI_FULL;
menuManager.setMenuCells(newArray);
@@ -547,7 +550,7 @@ public class MenuManagerTests {
// Sleep to give time to Taskmaster to run the operations
sleep();
- assertEquals(0 , menuManager.currentMenuCells.size());
+ assertEquals(0, menuManager.currentMenuCells.size());
}
@Test
diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuReplaceUtilitiesTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuReplaceUtilitiesTests.java
index 61587dbdc..0c7285531 100644
--- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuReplaceUtilitiesTests.java
+++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuReplaceUtilitiesTests.java
@@ -34,13 +34,16 @@ package com.smartdevicelink.managers.screen.menu;
import androidx.test.ext.junit.runners.AndroidJUnit4;
+import com.smartdevicelink.managers.ISdl;
import com.smartdevicelink.managers.file.FileManager;
import com.smartdevicelink.managers.file.filetypes.SdlArtwork;
import com.smartdevicelink.proxy.rpc.ImageField;
+import com.smartdevicelink.proxy.rpc.SdlMsgVersion;
import com.smartdevicelink.proxy.rpc.WindowCapability;
import com.smartdevicelink.proxy.rpc.enums.ImageFieldName;
import com.smartdevicelink.proxy.rpc.enums.MenuLayout;
import com.smartdevicelink.test.TestValues;
+import com.smartdevicelink.util.Version;
import org.junit.Before;
import org.junit.Test;
@@ -210,7 +213,88 @@ public class MenuReplaceUtilitiesTests {
}
@Test
+ public void testWindowCapabilitySupportsPrimaryImage() {
+ WindowCapability windowCapability;
+ ISdl internalInterface = mock(ISdl.class);
+ MenuCell menuCell = mock(MenuCell.class);
+
+ // Test case 0
+ windowCapability = createWindowCapability(false, true);
+ when(menuCell.isSubMenuCell()).thenReturn(true);
+ when(internalInterface.getSdlMsgVersion()).thenReturn(new SdlMsgVersion(new Version(4, 9, 0)));
+ assertTrue(MenuReplaceUtilities.windowCapabilitySupportsPrimaryImage(internalInterface, windowCapability, menuCell));
+
+ // Test case 1
+ windowCapability = createWindowCapability(false, false);
+ when(menuCell.isSubMenuCell()).thenReturn(true);
+ when(internalInterface.getSdlMsgVersion()).thenReturn(new SdlMsgVersion(new Version(4, 9, 0)));
+ assertFalse(MenuReplaceUtilities.windowCapabilitySupportsPrimaryImage(internalInterface, windowCapability, menuCell));
+
+ // Test case 2
+ windowCapability = createWindowCapability(false, false);
+ when(menuCell.isSubMenuCell()).thenReturn(true);
+ when(internalInterface.getSdlMsgVersion()).thenReturn(new SdlMsgVersion(new Version(5, 0, 0)));
+ assertFalse(MenuReplaceUtilities.windowCapabilitySupportsPrimaryImage(internalInterface, windowCapability, menuCell));
+
+ // Test case 3
+ windowCapability = createWindowCapability(true, false);
+ when(menuCell.isSubMenuCell()).thenReturn(true);
+ when(internalInterface.getSdlMsgVersion()).thenReturn(new SdlMsgVersion(new Version(5, 0, 0)));
+ assertTrue(MenuReplaceUtilities.windowCapabilitySupportsPrimaryImage(internalInterface, windowCapability, menuCell));
+
+ // Test case 4
+ windowCapability = createWindowCapability(false, false);
+ when(menuCell.isSubMenuCell()).thenReturn(true);
+ when(internalInterface.getSdlMsgVersion()).thenReturn(new SdlMsgVersion(new Version(6, 0, 0)));
+ assertFalse(MenuReplaceUtilities.windowCapabilitySupportsPrimaryImage(internalInterface, windowCapability, menuCell));
+
+ // Test case 5
+ windowCapability = createWindowCapability(true, false);
+ when(menuCell.isSubMenuCell()).thenReturn(true);
+ when(internalInterface.getSdlMsgVersion()).thenReturn(new SdlMsgVersion(new Version(6, 0, 0)));
+ assertTrue(MenuReplaceUtilities.windowCapabilitySupportsPrimaryImage(internalInterface, windowCapability, menuCell));
+
+ // Test case 6
+ windowCapability = createWindowCapability(false, false);
+ when(menuCell.isSubMenuCell()).thenReturn(true);
+ when(internalInterface.getSdlMsgVersion()).thenReturn(new SdlMsgVersion(new Version(7, 0, 0)));
+ assertFalse(MenuReplaceUtilities.windowCapabilitySupportsPrimaryImage(internalInterface, windowCapability, menuCell));
+
+ // Test case 7
+ windowCapability = createWindowCapability(false, false);
+ when(menuCell.isSubMenuCell()).thenReturn(true);
+ when(internalInterface.getSdlMsgVersion()).thenReturn(new SdlMsgVersion(new Version(7, 1, 0)));
+ assertFalse(MenuReplaceUtilities.windowCapabilitySupportsPrimaryImage(internalInterface, windowCapability, menuCell));
+
+ // Test case 8
+ windowCapability = createWindowCapability(false, false);
+ when(menuCell.isSubMenuCell()).thenReturn(true);
+ when(internalInterface.getSdlMsgVersion()).thenReturn(new SdlMsgVersion(new Version(8, 0, 0)));
+ assertFalse(MenuReplaceUtilities.windowCapabilitySupportsPrimaryImage(internalInterface, windowCapability, menuCell));
+
+ // Test case 9
+ windowCapability = createWindowCapability(false, true);
+ when(menuCell.isSubMenuCell()).thenReturn(true);
+ when(internalInterface.getSdlMsgVersion()).thenReturn(new SdlMsgVersion(new Version(8, 0, 0)));
+ assertTrue(MenuReplaceUtilities.windowCapabilitySupportsPrimaryImage(internalInterface, windowCapability, menuCell));
+
+ // Test case 10
+ windowCapability = createWindowCapability(false, false);
+ when(menuCell.isSubMenuCell()).thenReturn(false);
+ when(internalInterface.getSdlMsgVersion()).thenReturn(new SdlMsgVersion(new Version(8, 0, 0)));
+ assertFalse(MenuReplaceUtilities.windowCapabilitySupportsPrimaryImage(internalInterface, windowCapability, menuCell));
+
+ // Test case 11
+ windowCapability = createWindowCapability(true, false);
+ when(menuCell.isSubMenuCell()).thenReturn(false);
+ when(internalInterface.getSdlMsgVersion()).thenReturn(new SdlMsgVersion(new Version(8, 0, 0)));
+ assertTrue(MenuReplaceUtilities.windowCapabilitySupportsPrimaryImage(internalInterface, windowCapability, menuCell));
+ }
+
+ @Test
public void testShouldCellIncludeImage() {
+ ISdl internalInterface = mock(ISdl.class);
+ when(internalInterface.getSdlMsgVersion()).thenReturn(new SdlMsgVersion(new Version(8, 0, 0)));
MenuCell menuCell;
WindowCapability windowCapability;
FileManager fileManager;
@@ -220,34 +304,34 @@ public class MenuReplaceUtilitiesTests {
menuCell = new MenuCell(TestValues.GENERAL_STRING, TestValues.GENERAL_ARTWORK, voiceCommands, null);
windowCapability = createWindowCapability(true, true);
fileManager = createMockFileManager(true);
- assertTrue(MenuReplaceUtilities.shouldCellIncludePrimaryImageFromCell(menuCell, fileManager, windowCapability));
+ assertTrue(MenuReplaceUtilities.shouldCellIncludePrimaryImageFromCell(internalInterface, menuCell, fileManager, windowCapability));
// Case 2 - Image are not supported
menuCell = new MenuCell(TestValues.GENERAL_STRING, TestValues.GENERAL_ARTWORK, voiceCommands, null);
windowCapability = createWindowCapability(false, false);
fileManager = createMockFileManager(true);
- assertFalse(MenuReplaceUtilities.shouldCellIncludePrimaryImageFromCell(menuCell, fileManager, windowCapability));
+ assertFalse(MenuReplaceUtilities.shouldCellIncludePrimaryImageFromCell(internalInterface, menuCell, fileManager, windowCapability));
// Case 3 - Artwork is null
menuCell = new MenuCell(TestValues.GENERAL_STRING, null, voiceCommands, null);
windowCapability = createWindowCapability(true, true);
fileManager = createMockFileManager(true);
- assertFalse(MenuReplaceUtilities.shouldCellIncludePrimaryImageFromCell(menuCell, fileManager, windowCapability));
+ assertFalse(MenuReplaceUtilities.shouldCellIncludePrimaryImageFromCell(internalInterface, menuCell, fileManager, windowCapability));
// Case 4 - Artwork has not been uploaded
menuCell = new MenuCell(TestValues.GENERAL_STRING, TestValues.GENERAL_ARTWORK, voiceCommands, null);
windowCapability = createWindowCapability(true, true);
fileManager = createMockFileManager(false);
- assertFalse(MenuReplaceUtilities.shouldCellIncludePrimaryImageFromCell(menuCell, fileManager, windowCapability));
+ assertFalse(MenuReplaceUtilities.shouldCellIncludePrimaryImageFromCell(internalInterface, menuCell, fileManager, windowCapability));
// Case 5 - Artwork is static icon
menuCell = new MenuCell(TestValues.GENERAL_STRING, TestValues.GENERAL_ARTWORK_STATIC, voiceCommands, null);
windowCapability = createWindowCapability(true, true);
fileManager = createMockFileManager(false);
- assertTrue(MenuReplaceUtilities.shouldCellIncludePrimaryImageFromCell(menuCell, fileManager, windowCapability));
+ assertTrue(MenuReplaceUtilities.shouldCellIncludePrimaryImageFromCell(internalInterface, menuCell, fileManager, windowCapability));
}
- private WindowCapability createWindowCapability (boolean supportsCmdIcon, boolean supportsSubMenuIcon) {
+ private WindowCapability createWindowCapability(boolean supportsCmdIcon, boolean supportsSubMenuIcon) {
WindowCapability windowCapability = new WindowCapability();
windowCapability.setImageFields(new ArrayList<ImageField>());
if (supportsCmdIcon) {
@@ -259,7 +343,7 @@ public class MenuReplaceUtilitiesTests {
return windowCapability;
}
- private FileManager createMockFileManager (boolean hasUploadedFile) {
+ private FileManager createMockFileManager(boolean hasUploadedFile) {
FileManager fileManager = mock(FileManager.class);
when(fileManager.hasUploadedFile(any(SdlArtwork.class))).thenReturn(hasUploadedFile);
return fileManager;
@@ -308,7 +392,7 @@ public class MenuReplaceUtilitiesTests {
List<MenuCell> menuCellList = new ArrayList<>(Arrays.asList(menuCell1, menuCell2, menuCell3, menuCell4));
addIdsToMenuCells(menuCellList, parentIdNotFound);
- return menuCellList ;
+ return menuCellList;
}
private List<MenuCell> createNewMenuList() {
@@ -338,6 +422,6 @@ public class MenuReplaceUtilitiesTests {
List<MenuCell> newMenuList = new ArrayList<>(Arrays.asList(menuCell5));
addIdsToMenuCells(newMenuList, parentIdNotFound);
- return newMenuList ;
+ return newMenuList;
}
}
diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuShowOperationTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuShowOperationTests.java
index ee90cee49..29c9b7ce4 100644
--- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuShowOperationTests.java
+++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/MenuShowOperationTests.java
@@ -108,7 +108,7 @@ public class MenuShowOperationTests {
verify(internalInterface, Mockito.times(1)).sendRPC(any(ShowAppMenu.class));
}
- private Answer<Void> createShowAppMenuAnswer(final boolean success, final Integer menuIdToAssert){
+ private Answer<Void> createShowAppMenuAnswer(final boolean success, final Integer menuIdToAssert) {
return new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) {
@@ -118,7 +118,7 @@ public class MenuShowOperationTests {
@Override
public void run() {
ShowAppMenu showAppMenu = (ShowAppMenu) request;
- assertEquals(showAppMenu.getMenuID(), menuIdToAssert);
+ assertEquals(showAppMenu.getMenuID(), menuIdToAssert);
}
});
RPCResponse response = new RPCResponse(request.getFunctionID().toString());
diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/VoiceCommandUpdateOperationTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/VoiceCommandUpdateOperationTests.java
index 67885a902..475e29983 100644
--- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/VoiceCommandUpdateOperationTests.java
+++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/menu/VoiceCommandUpdateOperationTests.java
@@ -117,13 +117,13 @@ public class VoiceCommandUpdateOperationTests {
AddCommand addCommand = null;
try {
- deleteCommand = (DeleteCommand) ((List<Object>)invocation.getArguments()[0]).get(0);
+ deleteCommand = (DeleteCommand) ((List<Object>) invocation.getArguments()[0]).get(0);
} catch (Exception e) {
DebugTool.logInfo(TAG, "not DeleteCommands: " + e);
}
try {
- addCommand = (AddCommand) ((List<Object>)invocation.getArguments()[0]).get(0);
+ addCommand = (AddCommand) ((List<Object>) invocation.getArguments()[0]).get(0);
} catch (Exception e) {
DebugTool.logInfo(TAG, "not AddCommands: " + e);
}
@@ -131,24 +131,24 @@ public class VoiceCommandUpdateOperationTests {
if (deleteCommand != null) {
DeleteCommandResponse badResponse = new DeleteCommandResponse();
badResponse.setSuccess(false);
- List<DeleteCommand> deleteCommands = ((List<DeleteCommand>)invocation.getArguments()[0]);
+ List<DeleteCommand> deleteCommands = ((List<DeleteCommand>) invocation.getArguments()[0]);
for (DeleteCommand command : deleteCommands) {
badResponse.setCorrelationID(command.getCorrelationID());
- ((OnMultipleRequestListener)invocation.getArguments()[1]).onResponse(command.getCorrelationID(), badResponse);
+ ((OnMultipleRequestListener) invocation.getArguments()[1]).onResponse(command.getCorrelationID(), badResponse);
}
} else if (addCommand != null) {
AddCommandResponse badResponse = new AddCommandResponse();
badResponse.setSuccess(false);
- List<AddCommand> addCommands = ((List<AddCommand>)invocation.getArguments()[0]);
+ List<AddCommand> addCommands = ((List<AddCommand>) invocation.getArguments()[0]);
for (AddCommand command : addCommands) {
badResponse.setCorrelationID(command.getCorrelationID());
- ((OnMultipleRequestListener)invocation.getArguments()[1]).onResponse(command.getCorrelationID(), badResponse);
+ ((OnMultipleRequestListener) invocation.getArguments()[1]).onResponse(command.getCorrelationID(), badResponse);
}
} else {
DebugTool.logInfo(TAG, "CallBacks failed");
return null;
}
- ((OnMultipleRequestListener)invocation.getArguments()[1]).onFinished();
+ ((OnMultipleRequestListener) invocation.getArguments()[1]).onFinished();
return null;
}
}).when(internalInterface).sendRPCs(any(List.class), any(OnMultipleRequestListener.class));
@@ -181,13 +181,13 @@ public class VoiceCommandUpdateOperationTests {
AddCommand addCommand = null;
try {
- deleteCommand = (DeleteCommand) ((List<Object>)invocation.getArguments()[0]).get(0);
+ deleteCommand = (DeleteCommand) ((List<Object>) invocation.getArguments()[0]).get(0);
} catch (Exception e) {
DebugTool.logInfo(TAG, "not DeleteCommands: " + e);
}
try {
- addCommand = (AddCommand) ((List<Object>)invocation.getArguments()[0]).get(0);
+ addCommand = (AddCommand) ((List<Object>) invocation.getArguments()[0]).get(0);
} catch (Exception e) {
DebugTool.logInfo(TAG, "not AddCommands: " + e);
}
@@ -195,24 +195,24 @@ public class VoiceCommandUpdateOperationTests {
if (deleteCommand != null) {
DeleteCommandResponse successResponse = new DeleteCommandResponse();
successResponse.setSuccess(true);
- List<DeleteCommand> deleteCommands = ((List<DeleteCommand>)invocation.getArguments()[0]);
+ List<DeleteCommand> deleteCommands = ((List<DeleteCommand>) invocation.getArguments()[0]);
for (DeleteCommand command : deleteCommands) {
successResponse.setCorrelationID(command.getCorrelationID());
- ((OnMultipleRequestListener)invocation.getArguments()[1]).onResponse(command.getCorrelationID(), successResponse);
+ ((OnMultipleRequestListener) invocation.getArguments()[1]).onResponse(command.getCorrelationID(), successResponse);
}
} else if (addCommand != null) {
AddCommandResponse successResponse = new AddCommandResponse();
successResponse.setSuccess(true);
- List<AddCommand> addCommands = ((List<AddCommand>)invocation.getArguments()[0]);
+ List<AddCommand> addCommands = ((List<AddCommand>) invocation.getArguments()[0]);
for (AddCommand command : addCommands) {
successResponse.setCorrelationID(command.getCorrelationID());
- ((OnMultipleRequestListener)invocation.getArguments()[1]).onResponse(command.getCorrelationID(), successResponse);
+ ((OnMultipleRequestListener) invocation.getArguments()[1]).onResponse(command.getCorrelationID(), successResponse);
}
} else {
DebugTool.logInfo(TAG, "CallBacks failed");
return null;
}
- ((OnMultipleRequestListener)invocation.getArguments()[1]).onFinished();
+ ((OnMultipleRequestListener) invocation.getArguments()[1]).onFinished();
return null;
}
}).when(internalInterface).sendRPCs(any(List.class), any(OnMultipleRequestListener.class));
@@ -245,13 +245,13 @@ public class VoiceCommandUpdateOperationTests {
AddCommand addCommand = null;
try {
- deleteCommand = (DeleteCommand) ((List<Object>)invocation.getArguments()[0]).get(0);
+ deleteCommand = (DeleteCommand) ((List<Object>) invocation.getArguments()[0]).get(0);
} catch (Exception e) {
DebugTool.logInfo(TAG, "not DeleteCommands: " + e);
}
try {
- addCommand = (AddCommand) ((List<Object>)invocation.getArguments()[0]).get(0);
+ addCommand = (AddCommand) ((List<Object>) invocation.getArguments()[0]).get(0);
} catch (Exception e) {
DebugTool.logInfo(TAG, "not AddCommands: " + e);
}
@@ -259,24 +259,24 @@ public class VoiceCommandUpdateOperationTests {
if (deleteCommand != null) {
DeleteCommandResponse successResponse = new DeleteCommandResponse();
successResponse.setSuccess(true);
- List<DeleteCommand> deleteCommands = ((List<DeleteCommand>)invocation.getArguments()[0]);
+ List<DeleteCommand> deleteCommands = ((List<DeleteCommand>) invocation.getArguments()[0]);
for (DeleteCommand command : deleteCommands) {
successResponse.setCorrelationID(command.getCorrelationID());
- ((OnMultipleRequestListener)invocation.getArguments()[1]).onResponse(command.getCorrelationID(), successResponse);
+ ((OnMultipleRequestListener) invocation.getArguments()[1]).onResponse(command.getCorrelationID(), successResponse);
}
} else if (addCommand != null) {
AddCommandResponse successResponse = new AddCommandResponse();
successResponse.setSuccess(true);
- List<AddCommand> addCommands = ((List<AddCommand>)invocation.getArguments()[0]);
+ List<AddCommand> addCommands = ((List<AddCommand>) invocation.getArguments()[0]);
for (AddCommand command : addCommands) {
successResponse.setCorrelationID(command.getCorrelationID());
- ((OnMultipleRequestListener)invocation.getArguments()[1]).onResponse(command.getCorrelationID(), successResponse);
+ ((OnMultipleRequestListener) invocation.getArguments()[1]).onResponse(command.getCorrelationID(), successResponse);
}
} else {
DebugTool.logInfo(TAG, "CallBacks failed");
return null;
}
- ((OnMultipleRequestListener)invocation.getArguments()[1]).onFinished();
+ ((OnMultipleRequestListener) invocation.getArguments()[1]).onFinished();
return null;
}
}).when(internalInterface).sendRPCs(any(List.class), any(OnMultipleRequestListener.class));
@@ -298,7 +298,6 @@ public class VoiceCommandUpdateOperationTests {
}
-
@Test
public void testVoiceCommandsInListNotInSecondList() {
VoiceCommand command1 = new VoiceCommand(Collections.singletonList("Command 1"), null);
@@ -314,7 +313,7 @@ public class VoiceCommandUpdateOperationTests {
List<VoiceCommand> voiceCommandList2 = new ArrayList<>();
voiceCommandList2.add(command1Clone);
voiceCommandList2.add(command3);
- VoiceCommandUpdateOperation voiceCommandUpdateOperation = new VoiceCommandUpdateOperation(internalInterface,null,null,null);
+ VoiceCommandUpdateOperation voiceCommandUpdateOperation = new VoiceCommandUpdateOperation(internalInterface, null, null, null);
List<VoiceCommand> differencesList = voiceCommandUpdateOperation.voiceCommandsInListNotInSecondList(voiceCommandList, voiceCommandList2);
assertEquals(differencesList.size(), 1);
diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/TestValues.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/TestValues.java
index da3bb5846..261d121a4 100644
--- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/TestValues.java
+++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/TestValues.java
@@ -1064,7 +1064,7 @@ public class TestValues {
JSON_GENERAL_SEATS_OCCUPIED.put(JSON_OBJECT_GENERAL_SEATS_OCCUPIED);
JSON_OBJECT_GENERAL_SEATS_BELTED.put(SeatStatus.KEY_SEAT_LOCATION, GENERAL_SEATLOCATION.serializeJSON());
- JSON_OBJECT_GENERAL_SEATS_BELTED.put(SeatStatus.KEY_CONDITION_ACTIVE,GENERAL_BOOLEAN);
+ JSON_OBJECT_GENERAL_SEATS_BELTED.put(SeatStatus.KEY_CONDITION_ACTIVE, GENERAL_BOOLEAN);
JSON_GENERAL_SEATS_BELTED.put(JSON_OBJECT_GENERAL_SEATS_BELTED);
JSON_HMIPERMISSIONS.put(HMIPermissions.KEY_ALLOWED, GENERAL_HMILEVEL_LIST);
diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/Validator.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/Validator.java
index 094b29794..235a9dfff 100644
--- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/Validator.java
+++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/Validator.java
@@ -2431,7 +2431,7 @@ public class Validator {
log("validatePermissionItem", "Items are the same object. No defensive copy took place.");
return false;
}
- */
+ */
if (!item1.getRpcName().equals(item2.getRpcName())) {
return false;
}
@@ -2509,7 +2509,7 @@ public class Validator {
log("validateParameterPermissions", "Items are the same object. No defensive copy took place.");
return false;
}
- */
+ */
if (!validateStringList(item1.getAllowed(), item2.getAllowed())) {
return false;
}
diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/protocol/SecurityQueryPayloadTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/protocol/SecurityQueryPayloadTests.java
index 8c0c36041..c39e9bb42 100644
--- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/protocol/SecurityQueryPayloadTests.java
+++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/protocol/SecurityQueryPayloadTests.java
@@ -25,7 +25,7 @@ public class SecurityQueryPayloadTests {
bqh.setQueryID(SecurityQueryID.SEND_HANDSHAKE_DATA);
bqh.setQueryType(SecurityQueryType.REQUEST);
bqh.setBulkData(null);
- bqh.setJsonSize(0);
+ bqh.setJsonData(null);
return bqh;
}
@@ -66,9 +66,9 @@ public class SecurityQueryPayloadTests {
dummyBqh.setQueryType(SecurityQueryType.REQUEST);
dummyBqh.setQueryID(SecurityQueryID.SEND_HANDSHAKE_DATA);
dummyBqh.setCorrelationID(3);
- dummyBqh.setJsonSize(0);
+ dummyBqh.setJsonData(new byte[0]);
- byte[] assembledHeader = dummyBqh.assembleHeaderBytes();
+ byte[] assembledHeader = dummyBqh.assembleBinaryData();
assertEquals(dummyBqh.getQueryType(), SecurityQueryType.valueOf(assembledHeader[0]));
byte[] queryIDFromHeader = new byte[3];
System.arraycopy(assembledHeader, 1, queryIDFromHeader, 0, 3);
@@ -81,7 +81,7 @@ public class SecurityQueryPayloadTests {
public void testAssemblyAndParse() {
SecurityQueryPayload bqh = createDummyBqh();
- byte[] bqhBytes = bqh.assembleHeaderBytes();
+ byte[] bqhBytes = bqh.assembleBinaryData();
assertNotNull(bqhBytes);
SecurityQueryPayload parsedBqh = SecurityQueryPayload.parseBinaryQueryHeader(bqhBytes);
@@ -99,7 +99,7 @@ public class SecurityQueryPayloadTests {
public void testCorruptHeader() {
SecurityQueryPayload bqh = createDummyBqh();
- byte[] bqhBytes = bqh.assembleHeaderBytes();
+ byte[] bqhBytes = bqh.assembleBinaryData();
assertNotNull(safeParse(bqhBytes));
@@ -114,13 +114,18 @@ public class SecurityQueryPayloadTests {
}
@Test
- public void testJsonSetException() {
- try {
- SecurityQueryPayload bqh = createDummyBqh();
- bqh.setJsonData(null);
- fail("Setting JSON data to null should have thrown an exception");
- } catch (Exception e) {
- //Pass
- }
+ public void testNullJsonData() {
+ SecurityQueryPayload bqh = createDummyBqh();
+ bqh.setJsonData(null);
+ assertEquals(0, bqh.getJsonSize());
+ assertEquals(null, bqh.getJsonData());
+ }
+
+ @Test
+ public void testNullBulkData() {
+ SecurityQueryPayload bqh = createDummyBqh();
+ bqh.setBulkData(null);
+ assertEquals(0, bqh.getBulkDataSize());
+ assertEquals(null, bqh.getBulkData());
}
}
diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/protocol/enums/SecurityQueryIDTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/protocol/enums/SecurityQueryIDTests.java
index 4f73f8139..6e1ecf762 100644
--- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/protocol/enums/SecurityQueryIDTests.java
+++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/protocol/enums/SecurityQueryIDTests.java
@@ -39,7 +39,7 @@ public class SecurityQueryIDTests extends TestCase {
assertNotNull("Send Handshake Data string match returned null", enumHandshakeData);
assertNotNull("Send Internal Error string match returned null", enumInternalError);
assertNotNull("Send Invalid QueryID string match returned null", enumInvalidSecurityQueryId);
- } catch(NullPointerException exception) {
+ } catch (NullPointerException exception) {
fail("Null enum list throws NullPointerException.");
}
}
@@ -67,7 +67,7 @@ public class SecurityQueryIDTests extends TestCase {
enumNull = (SecurityQueryID) SecurityQueryID.get(list, (byte[]) null);
assertNull("Null lookup returns a null byte[] value", enumNull);
- }catch (NullPointerException exception) {
+ } catch (NullPointerException exception) {
fail("Null string throws NullPointerException.");
}
}
diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/protocol/enums/SecurityQueryTypeTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/protocol/enums/SecurityQueryTypeTests.java
index 6835da946..2567bbb18 100644
--- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/protocol/enums/SecurityQueryTypeTests.java
+++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/protocol/enums/SecurityQueryTypeTests.java
@@ -48,7 +48,7 @@ public class SecurityQueryTypeTests extends TestCase {
assertNotNull("Invalid Query string byte match returned null", enumInvalidSecurityQueryType);
- }catch (NullPointerException exception) {
+ } catch (NullPointerException exception) {
fail("Null enum list throws NullPointerException.");
}
}
diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/RPCGenericTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/RPCGenericTests.java
index e4a61b9ed..2fa325419 100644
--- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/RPCGenericTests.java
+++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/RPCGenericTests.java
@@ -523,7 +523,7 @@ public class RPCGenericTests {
assertTrue("The following RPCs don't have a constructor that has all the mandatory params: " + rpcsWithInvalidConstructor, rpcsWithInvalidConstructor.isEmpty());
}
- private boolean annotationExists (AnnotatedElement element, String annotationName) {
+ private boolean annotationExists(AnnotatedElement element, String annotationName) {
for (Annotation annotation : element.getDeclaredAnnotations()) {
if (annotation.annotationType().getSimpleName().equalsIgnoreCase(annotationName)) {
return true;
@@ -532,7 +532,7 @@ public class RPCGenericTests {
return false;
}
- private boolean isDeprecated (AnnotatedElement element) {
+ private boolean isDeprecated(AnnotatedElement element) {
return annotationExists(element, "Deprecated");
}
@@ -541,7 +541,7 @@ public class RPCGenericTests {
for (Object anEnum : EnumSet.allOf(aClass)) {
if (anEnum.toString().equals(elementName)) {
try {
- String value = ((Enum)anEnum).name();
+ String value = ((Enum) anEnum).name();
field = aClass.getField(value);
break;
} catch (NoSuchFieldException e) {
diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/AppCapabilityTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/AppCapabilityTests.java
index 225dc393c..66099312e 100644
--- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/AppCapabilityTests.java
+++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/AppCapabilityTests.java
@@ -33,7 +33,7 @@ public class AppCapabilityTests extends TestCase {
/**
* Tests the expected values of the RPC message.
*/
- public void testRpcValues () {
+ public void testRpcValues() {
// Test Values
VideoStreamingCapability videoStreamingCapability = msg.getVideoStreamingCapability();
AppCapabilityType videoStreamingCapabilityType = msg.getAppCapabilityType();
@@ -50,10 +50,10 @@ public class AppCapabilityTests extends TestCase {
assertNull(TestValues.NULL, msg.getVideoStreamingCapability());
}
- public void testJson(){
+ public void testJson() {
JSONObject reference = new JSONObject();
- try{
+ try {
reference.put(KEY_APP_CAPABILITY_TYPE, TestValues.GENERAL_APPCAPABILITYTYPE);
reference.put(KEY_VIDEO_STREAMING_CAPABILITY, TestValues.GENERAL_VIDEOSTREAMINGCAPABILITY);
@@ -61,7 +61,7 @@ public class AppCapabilityTests extends TestCase {
assertEquals(TestValues.MATCH, reference.length(), underTest.length());
Iterator<?> iterator = reference.keys();
- while(iterator.hasNext()){
+ while (iterator.hasNext()) {
String key = (String) iterator.next();
@@ -83,7 +83,7 @@ public class AppCapabilityTests extends TestCase {
);
}
}
- } catch(JSONException e){
+ } catch (JSONException e) {
fail(TestValues.JSON_FAIL);
}
}
diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/RoofStatusTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/RoofStatusTests.java
index 4afc9d778..4c52ab7df 100644
--- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/RoofStatusTests.java
+++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/RoofStatusTests.java
@@ -54,13 +54,13 @@ public class RoofStatusTests extends TestCase {
while (iterator.hasNext()) {
String key = (String) iterator.next();
if (key.equals(RoofStatus.KEY_STATE)) {
- Hashtable<String, Object> hs1 = JsonRPCMarshaller.deserializeJSONObject((JSONObject) JsonUtils.readObjectFromJsonObject(reference, key));
- Hashtable<String, Object> hs2 = JsonRPCMarshaller.deserializeJSONObject((JSONObject) JsonUtils.readObjectFromJsonObject(underTest, key));
+ Hashtable<String, Object> hs1 = JsonRPCMarshaller.deserializeJSONObject((JSONObject) JsonUtils.readObjectFromJsonObject(reference, key));
+ Hashtable<String, Object> hs2 = JsonRPCMarshaller.deserializeJSONObject((JSONObject) JsonUtils.readObjectFromJsonObject(underTest, key));
assertTrue(Validator.validateWindowStates(new WindowState(hs1), new WindowState(hs2)));
} else if (key.equals(RoofStatus.KEY_LOCATION)) {
- Hashtable<String, Object> hs1 = JsonRPCMarshaller.deserializeJSONObject((JSONObject) JsonUtils.readObjectFromJsonObject(reference, key));
- Hashtable<String, Object> hs2 = JsonRPCMarshaller.deserializeJSONObject((JSONObject) JsonUtils.readObjectFromJsonObject(underTest, key));
+ Hashtable<String, Object> hs1 = JsonRPCMarshaller.deserializeJSONObject((JSONObject) JsonUtils.readObjectFromJsonObject(reference, key));
+ Hashtable<String, Object> hs2 = JsonRPCMarshaller.deserializeJSONObject((JSONObject) JsonUtils.readObjectFromJsonObject(underTest, key));
assertTrue(Validator.validateGrid(new Grid(hs1), new Grid(hs2)));
diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/VideoStreamingCapabilityTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/VideoStreamingCapabilityTests.java
index c13199223..1bcb659a4 100644
--- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/VideoStreamingCapabilityTests.java
+++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/VideoStreamingCapabilityTests.java
@@ -35,7 +35,7 @@ public class VideoStreamingCapabilityTests extends TestCase {
msg.setPixelPerInch(TestValues.GENERAL_DOUBLE);
msg.setScale(TestValues.GENERAL_DOUBLE);
msg.setAdditionalVideoStreamingCapabilities(TestValues.GENERAL_ADDITIONAL_CAPABILITY_LIST);
- msg.setPreferredFPS(TestValues.GENERAL_INTEGER);
+ msg.setPreferredFPS(TestValues.GENERAL_INTEGER);
}
/**
@@ -51,7 +51,7 @@ public class VideoStreamingCapabilityTests extends TestCase {
Double pixelPerInch = msg.getPixelPerInch();
Double scale = msg.getScale();
List<VideoStreamingCapability> additionalVideoStreamingCapabilities = msg.getAdditionalVideoStreamingCapabilities();
- Integer preferredFPS = msg.getPreferredFPS();
+ Integer preferredFPS = msg.getPreferredFPS();
// Valid Tests
assertEquals(TestValues.MATCH, (List<VideoStreamingFormat>) TestValues.GENERAL_VIDEOSTREAMINGFORMAT_LIST, format);
@@ -75,7 +75,7 @@ public class VideoStreamingCapabilityTests extends TestCase {
assertNull(TestValues.NULL, msg.getPixelPerInch());
assertNull(TestValues.NULL, msg.getScale());
assertNull(TestValues.NULL, msg.getAdditionalVideoStreamingCapabilities());
- assertNull(TestValues.NULL, msg.getPreferredFPS());
+ assertNull(TestValues.NULL, msg.getPreferredFPS());
}
public void testJson() {
@@ -90,7 +90,7 @@ public class VideoStreamingCapabilityTests extends TestCase {
reference.put(VideoStreamingCapability.KEY_DIAGONAL_SCREEN_SIZE, TestValues.GENERAL_DOUBLE);
reference.put(VideoStreamingCapability.KEY_PIXEL_PER_INCH, TestValues.GENERAL_DOUBLE);
reference.put(VideoStreamingCapability.KEY_SCALE, TestValues.GENERAL_DOUBLE);
- reference.put(VideoStreamingCapability.KEY_PREFERRED_FPS, TestValues.GENERAL_INTEGER);
+ reference.put(VideoStreamingCapability.KEY_PREFERRED_FPS, TestValues.GENERAL_INTEGER);
JSONObject underTest = msg.serializeJSON();
assertEquals(TestValues.MATCH, reference.length(), underTest.length());
@@ -123,14 +123,14 @@ public class VideoStreamingCapabilityTests extends TestCase {
}
@Test
- public void testFormatMethod(){
+ public void testFormatMethod() {
List<VideoStreamingCapability> additionalCapabilities = msg.getAdditionalVideoStreamingCapabilities();
msg.format(null, false);
assertEquals(additionalCapabilities, msg.getAdditionalVideoStreamingCapabilities());
}
@Test
- public void testFormatWillRemoveSelf(){
+ public void testFormatWillRemoveSelf() {
List<VideoStreamingCapability> additionalCapabilities = msg.getAdditionalVideoStreamingCapabilities();
additionalCapabilities.add(msg);
msg.format(null, false);
diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/WindowCapabilityTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/WindowCapabilityTests.java
index 0ad5e466d..756791a5a 100644
--- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/WindowCapabilityTests.java
+++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/datatypes/WindowCapabilityTests.java
@@ -220,7 +220,7 @@ public class WindowCapabilityTests extends TestCase {
imageFieldNameListTest.add((ImageFieldName) underTestArray.get(i));
}
assertTrue(TestValues.TRUE, imageFieldNameListReference.containsAll(imageFieldNameListTest) && imageFieldNameListTest.containsAll(imageFieldNameListReference));
- } else if (key.equals(WindowCapability.KEY_KEYBOARD_CAPABILITIES)){
+ } else if (key.equals(WindowCapability.KEY_KEYBOARD_CAPABILITIES)) {
JSONObject jsonReference = JsonUtils.readJsonObjectFromJsonObject(reference, key);
JSONObject jsonUnderTest = JsonUtils.readJsonObjectFromJsonObject(underTest, key);
diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/AppCapabilityTypeTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/AppCapabilityTypeTests.java
index dd1f08080..22db62763 100644
--- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/AppCapabilityTypeTests.java
+++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/enums/AppCapabilityTypeTests.java
@@ -13,7 +13,7 @@ public class AppCapabilityTypeTests extends TestCase {
/**
* Verifies that the enum values are not null upon valid assignment.
*/
- public void testValidEnums () {
+ public void testValidEnums() {
String example = "VIDEO_STREAMING";
AppCapabilityType enumVideoStreaming = AppCapabilityType.valueForString(example);
@@ -23,7 +23,7 @@ public class AppCapabilityTypeTests extends TestCase {
/**
* Verifies that an invalid assignment is null.
*/
- public void testInvalidEnum () {
+ public void testInvalidEnum() {
String example = "VidEOs_Treamin";
try {
AppCapabilityType temp = AppCapabilityType.valueForString(example);
@@ -37,7 +37,7 @@ public class AppCapabilityTypeTests extends TestCase {
/**
* Verifies that a null assignment is invalid.
*/
- public void testNullEnum () {
+ public void testNullEnum() {
String example = null;
try {
AppCapabilityType temp = AppCapabilityType.valueForString(example);
diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/notifications/OnAppCapabilityUpdatedTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/notifications/OnAppCapabilityUpdatedTests.java
index eaca5122c..c9717bf97 100644
--- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/notifications/OnAppCapabilityUpdatedTests.java
+++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/rpc/notifications/OnAppCapabilityUpdatedTests.java
@@ -19,7 +19,7 @@ import static junit.framework.TestCase.fail;
public class OnAppCapabilityUpdatedTests extends BaseRpcTests {
@Override
- protected RPCMessage createMessage(){
+ protected RPCMessage createMessage() {
OnAppCapabilityUpdated msg = new OnAppCapabilityUpdated();
msg.setAppCapability(TestValues.GENERAL_APPCAPABILITY);
@@ -27,22 +27,22 @@ public class OnAppCapabilityUpdatedTests extends BaseRpcTests {
}
@Override
- protected String getMessageType(){
+ protected String getMessageType() {
return RPCMessage.KEY_NOTIFICATION;
}
@Override
- protected String getCommandType(){
+ protected String getCommandType() {
return FunctionID.ON_APP_CAPABILITY_UPDATED.toString();
}
@Override
- protected JSONObject getExpectedParameters(int sdlVersion){
+ protected JSONObject getExpectedParameters(int sdlVersion) {
JSONObject result = new JSONObject();
- try{
+ try {
result.put(OnAppCapabilityUpdated.KEY_APP_CAPABILITY, TestValues.GENERAL_APPCAPABILITY.serializeJSON());
- }catch(JSONException e){
+ } catch (JSONException e) {
fail(TestValues.JSON_FAIL);
}
@@ -53,9 +53,9 @@ public class OnAppCapabilityUpdatedTests extends BaseRpcTests {
* Tests the expected values of the RPC message.
*/
@Test
- public void testRpcValues () {
+ public void testRpcValues() {
// Test Values
- AppCapability appCapability = ( (OnAppCapabilityUpdated) msg ).getAppCapability();
+ AppCapability appCapability = ((OnAppCapabilityUpdated) msg).getAppCapability();
// Valid Tests
assertEquals(TestValues.MATCH, TestValues.GENERAL_APPCAPABILITY, appCapability);
diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/encoder/VirtualDisplayEncoder.java b/android/sdl_android/src/main/java/com/smartdevicelink/encoder/VirtualDisplayEncoder.java
index 3eba6af30..35fc87683 100644
--- a/android/sdl_android/src/main/java/com/smartdevicelink/encoder/VirtualDisplayEncoder.java
+++ b/android/sdl_android/src/main/java/com/smartdevicelink/encoder/VirtualDisplayEncoder.java
@@ -228,9 +228,7 @@ public class VirtualDisplayEncoder {
mCaptureThread.stopAsync();
try {
mCaptureThread.join();
- } catch(InterruptedException e) {
-
- }
+ } catch (InterruptedException e) {}
mCaptureThread = null;
}
if (encoderThread != null) {
@@ -253,6 +251,10 @@ public class VirtualDisplayEncoder {
inputSurface.release();
inputSurface = null;
}
+ if (mEglCore != null) {
+ mEglCore.release();
+ mEglCore = null;
+ }
} catch (Exception ex) {
DebugTool.logError(TAG, "shutDown() failed");
}
@@ -264,6 +266,9 @@ public class VirtualDisplayEncoder {
* @param Height
*/
private void setupGLES(int Width, int Height) {
+ if (mEglCore != null) {
+ mEglCore.release();
+ }
mEglCore = new EglCore(null, 0);
// This 1x1 offscreen is created just to get the texture name (mTextureId).
@@ -328,7 +333,7 @@ public class VirtualDisplayEncoder {
mBlit = blit;
mWidth = width;
mHeight = height;
- mFrameIntervalNsec = (long)(1000000000 / fps);
+ mFrameIntervalNsec = (long) (1000000000 / fps);
mStartedCallback = onStarted;
}
@@ -482,6 +487,27 @@ public class VirtualDisplayEncoder {
// Create a MediaCodec encoder and configure it. Get a Surface we can use for recording into.
try {
mVideoEncoder = MediaCodec.createEncoderByType(videoMimeType);
+
+ int width = streamingParams.getResolution().getResolutionWidth();
+ int height = streamingParams.getResolution().getResolutionHeight();
+ int frameRate = streamingParams.getFrameRate();
+
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
+ boolean streamSupported = mVideoEncoder.getCodecInfo()
+ .getCapabilitiesForType(videoMimeType)
+ .getVideoCapabilities()
+ .areSizeAndRateSupported(width, height, frameRate);
+
+ if (!streamSupported) {
+ String errorString = "Video streaming " + width + " by " + height + " at "
+ + frameRate + "fps is unsupported on this device";
+
+ DebugTool.logError(TAG, errorString);
+
+ return null;
+ }
+ }
+
mVideoEncoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
Surface surface = mVideoEncoder.createInputSurface(); //prepared
diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/managers/SdlManager.java b/android/sdl_android/src/main/java/com/smartdevicelink/managers/SdlManager.java
index 866b6e80b..6dc3ce4aa 100644
--- a/android/sdl_android/src/main/java/com/smartdevicelink/managers/SdlManager.java
+++ b/android/sdl_android/src/main/java/com/smartdevicelink/managers/SdlManager.java
@@ -91,6 +91,19 @@ public class SdlManager extends BaseSdlManager {
private VideoStreamManager videoStreamManager;
private AudioStreamManager audioStreamManager;
+ private Handler handler = new Handler(Looper.getMainLooper());
+ private Runnable changeRegistrationRunnable = new Runnable() {
+ @Override
+ public void run() {
+ checkLifecycleConfiguration();
+ DebugTool.logInfo(TAG, "Retry Change Registration Count: " + changeRegistrationRetry);
+ }
+ };
+
+ public SdlManager() {
+ DebugTool.logWarning(TAG, "SdlManager must be created with SdlManager.Builder");
+ }
+
/**
* Starts up a SdlManager, and calls provided callback called once all BaseSubManagers are done setting up
*/
@@ -211,14 +224,9 @@ public class SdlManager extends BaseSdlManager {
void retryChangeRegistration() {
changeRegistrationRetry++;
if (changeRegistrationRetry < MAX_RETRY) {
- final Handler handler = new Handler(Looper.getMainLooper());
- handler.postDelayed(new Runnable() {
- @Override
- public void run() {
- checkLifecycleConfiguration();
- DebugTool.logInfo(TAG, "Retry Change Registration Count: " + changeRegistrationRetry);
- }
- }, 3000);
+ if (handler != null && changeRegistrationRunnable != null) {
+ handler.postDelayed(changeRegistrationRunnable, 3000);
+ }
}
}
@@ -229,6 +237,11 @@ public class SdlManager extends BaseSdlManager {
@SuppressLint("NewApi")
@Override
public synchronized void dispose() {
+ int state = getState();
+ if (state == BaseSubManager.SHUTDOWN || state == BaseSubManager.ERROR) {
+ DebugTool.logInfo(TAG, "SdlManager already disposed");
+ return;
+ }
if (this.permissionManager != null) {
this.permissionManager.dispose();
}
@@ -258,6 +271,15 @@ public class SdlManager extends BaseSdlManager {
this.lifecycleManager.stop();
}
+ if (handler != null) {
+ if (changeRegistrationRunnable != null) {
+ handler.removeCallbacks(changeRegistrationRunnable);
+ changeRegistrationRunnable = null;
+ }
+
+ handler = null;
+ }
+
if (managerListener != null) {
managerListener.onDestroy();
managerListener = null;
@@ -397,7 +419,7 @@ public class SdlManager extends BaseSdlManager {
@Override
public void stop() {
- lifecycleManager.getInternalInterface(SdlManager.this).start();
+ lifecycleManager.getInternalInterface(SdlManager.this).stop();
}
@Override
@@ -447,7 +469,7 @@ public class SdlManager extends BaseSdlManager {
@Override
public boolean removeOnRPCNotificationListener(FunctionID notificationId, OnRPCNotificationListener listener) {
- return lifecycleManager.getInternalInterface(SdlManager.this).removeOnRPCNotificationListener(notificationId, listener);
+ return lifecycleManager.getInternalInterface(SdlManager.this).removeOnRPCNotificationListener(notificationId, listener);
}
@Override
@@ -457,7 +479,7 @@ public class SdlManager extends BaseSdlManager {
@Override
public boolean removeOnRPCRequestListener(FunctionID functionID, OnRPCRequestListener listener) {
- return lifecycleManager.getInternalInterface(SdlManager.this).removeOnRPCRequestListener(functionID, listener);
+ return lifecycleManager.getInternalInterface(SdlManager.this).removeOnRPCRequestListener(functionID, listener);
}
@Override
@@ -467,29 +489,29 @@ public class SdlManager extends BaseSdlManager {
@Override
public boolean removeOnRPCListener(FunctionID responseId, OnRPCListener listener) {
- return lifecycleManager.getInternalInterface(SdlManager.this).removeOnRPCListener(responseId, listener);
+ return lifecycleManager.getInternalInterface(SdlManager.this).removeOnRPCListener(responseId, listener);
}
@Override
public RegisterAppInterfaceResponse getRegisterAppInterfaceResponse() {
- return lifecycleManager.getInternalInterface(SdlManager.this).getRegisterAppInterfaceResponse();
+ return lifecycleManager.getInternalInterface(SdlManager.this).getRegisterAppInterfaceResponse();
}
@Override
public boolean isTransportForServiceAvailable(SessionType serviceType) {
- return lifecycleManager.getInternalInterface(SdlManager.this).isTransportForServiceAvailable(serviceType);
+ return lifecycleManager.getInternalInterface(SdlManager.this).isTransportForServiceAvailable(serviceType);
}
@NonNull
@Override
public SdlMsgVersion getSdlMsgVersion() {
- return lifecycleManager.getInternalInterface(SdlManager.this).getSdlMsgVersion();
+ return lifecycleManager.getInternalInterface(SdlManager.this).getSdlMsgVersion();
}
@NonNull
@Override
public Version getProtocolVersion() {
- return lifecycleManager.getInternalInterface(SdlManager.this).getProtocolVersion();
+ return lifecycleManager.getInternalInterface(SdlManager.this).getProtocolVersion();
}
@Override
@@ -504,12 +526,12 @@ public class SdlManager extends BaseSdlManager {
@Override
public Taskmaster getTaskmaster() {
- return lifecycleManager.getInternalInterface(SdlManager.this).getTaskmaster();
+ return lifecycleManager.getInternalInterface(SdlManager.this).getTaskmaster();
}
@Override
public SystemCapabilityManager getSystemCapabilityManager() {
- return lifecycleManager.getInternalInterface(SdlManager.this).getSystemCapabilityManager();
+ return lifecycleManager.getInternalInterface(SdlManager.this).getSystemCapabilityManager();
}
@Override
diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/managers/file/filetypes/SdlFile.java b/android/sdl_android/src/main/java/com/smartdevicelink/managers/file/filetypes/SdlFile.java
index a0c0d9369..eeb62b158 100644
--- a/android/sdl_android/src/main/java/com/smartdevicelink/managers/file/filetypes/SdlFile.java
+++ b/android/sdl_android/src/main/java/com/smartdevicelink/managers/file/filetypes/SdlFile.java
@@ -252,7 +252,7 @@ public class SdlFile implements Cloneable {
}
/**
- * Sets the the name of the static file. Static files comes pre-shipped with the head unit
+ * Sets the name of the static file. Static files comes pre-shipped with the head unit
*
* @param staticIcon a StaticIconName enum value representing the name of a static file that comes pre-shipped with the head unit
*/
@@ -261,7 +261,7 @@ public class SdlFile implements Cloneable {
}
/**
- * Gets the the name of the static file. Static files comes pre-shipped with the head unit
+ * Gets the name of the static file. Static files comes pre-shipped with the head unit
*
* @return a StaticIconName enum value representing the name of a static file that comes pre-shipped with the head unit
*/
diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/managers/lifecycle/LifecycleManager.java b/android/sdl_android/src/main/java/com/smartdevicelink/managers/lifecycle/LifecycleManager.java
index 6d4fddb3d..bfe73c19f 100644
--- a/android/sdl_android/src/main/java/com/smartdevicelink/managers/lifecycle/LifecycleManager.java
+++ b/android/sdl_android/src/main/java/com/smartdevicelink/managers/lifecycle/LifecycleManager.java
@@ -32,6 +32,8 @@
package com.smartdevicelink.managers.lifecycle;
+import static com.smartdevicelink.managers.BaseSubManager.SETTING_UP;
+
import android.content.Context;
import androidx.annotation.RestrictTo;
@@ -76,28 +78,33 @@ public class LifecycleManager extends BaseLifecycleManager {
void initialize() {
super.initialize();
- if (_transportConfig != null && _transportConfig.getTransportType().equals(TransportType.MULTIPLEX)) {
- this.session = new SdlSession(sdlSessionListener, (MultiplexTransportConfig) _transportConfig);
- } else if (_transportConfig != null && _transportConfig.getTransportType().equals(TransportType.TCP)) {
- this.session = new SdlSession(sdlSessionListener, (TCPTransportConfig) _transportConfig);
- } else {
- DebugTool.logError(TAG, "Unable to create session for transport type");
+ synchronized (SESSION_LOCK) {
+ if (_transportConfig != null && _transportConfig.getTransportType().equals(TransportType.MULTIPLEX)) {
+ this.session = new SdlSession(sdlSessionListener, (MultiplexTransportConfig) _transportConfig);
+ } else if (_transportConfig != null && _transportConfig.getTransportType().equals(TransportType.TCP)) {
+ this.session = new SdlSession(sdlSessionListener, (TCPTransportConfig) _transportConfig);
+ } else {
+ DebugTool.logError(TAG, "Unable to create session for transport type");
+ }
}
}
@Override
void cycle(SdlDisconnectedReason disconnectedReason) {
- clean();
- initialize();
+ clean(true);
if (!SdlDisconnectedReason.LEGACY_BLUETOOTH_MODE_ENABLED.equals(disconnectedReason) && !SdlDisconnectedReason.PRIMARY_TRANSPORT_CYCLE_REQUEST.equals(disconnectedReason)) {
//We don't want to alert higher if we are just cycling for legacy bluetooth
onClose("Sdl Proxy Cycled", new SdlException("Sdl Proxy Cycled", SdlExceptionCause.SDL_PROXY_CYCLED), disconnectedReason);
}
- if (session != null) {
- try {
- session.startSession();
- } catch (SdlException e) {
- e.printStackTrace();
+ transitionToState(SETTING_UP);
+ initialize();
+ synchronized (SESSION_LOCK) {
+ if (session != null) {
+ try {
+ session.startSession();
+ } catch (SdlException e) {
+ e.printStackTrace();
+ }
}
}
}
@@ -114,7 +121,7 @@ public class LifecycleManager extends BaseLifecycleManager {
return;
}
- for (TransportRecord record: activeTransports) {
+ for (TransportRecord record : activeTransports) {
if (record.getType() == TransportType.BLUETOOTH) {
String address = record.getAddress();
if (address != null && !address.isEmpty()) {
@@ -163,16 +170,18 @@ public class LifecycleManager extends BaseLifecycleManager {
*/
@Override
void startVideoService(boolean isEncrypted, VideoStreamingParameters parameters, boolean afterPendingRestart) {
- if (session == null) {
- DebugTool.logWarning(TAG, "SdlSession is not created yet.");
- return;
- }
- if (!session.getIsConnected()) {
- DebugTool.logWarning(TAG, "Connection is not available.");
- return;
- }
+ synchronized (SESSION_LOCK) {
+ if (session == null) {
+ DebugTool.logWarning(TAG, "SdlSession is not created yet.");
+ return;
+ }
+ if (!session.getIsConnected()) {
+ DebugTool.logWarning(TAG, "Connection is not available.");
+ return;
+ }
- session.setDesiredVideoParams(parameters);
+ session.setDesiredVideoParams(parameters);
+ }
tryStartVideoStream(isEncrypted, parameters, afterPendingRestart);
}
@@ -185,9 +194,11 @@ public class LifecycleManager extends BaseLifecycleManager {
* @param parameters VideoStreamingParameters that are desired. Does not guarantee this is what will be accepted.
*/
private void tryStartVideoStream(boolean isEncrypted, VideoStreamingParameters parameters, boolean afterPendingRestart) {
- if (session == null) {
- DebugTool.logWarning(TAG, "SdlSession is not created yet.");
- return;
+ synchronized (SESSION_LOCK) {
+ if (session == null) {
+ DebugTool.logWarning(TAG, "SdlSession is not created yet.");
+ return;
+ }
}
if (getProtocolVersion() != null && getProtocolVersion().getMajor() >= 5 && !systemCapabilityManager.isCapabilitySupported(SystemCapabilityType.VIDEO_STREAMING)) {
DebugTool.logWarning(TAG, "Module doesn't support video streaming.");
@@ -198,17 +209,20 @@ public class LifecycleManager extends BaseLifecycleManager {
return;
}
+ synchronized (SESSION_LOCK) {
+ if (afterPendingRestart || !videoServiceStartResponseReceived || !videoServiceStartResponse //If we haven't started the service before
+ || (videoServiceStartResponse && isEncrypted && !session.isServiceProtected(SessionType.NAV))) { //Or the service has been started but we'd like to start an encrypted one
+ if (session != null) {
+ session.setDesiredVideoParams(parameters);
+ }
+ videoServiceStartResponseReceived = false;
+ videoServiceStartResponse = false;
- if (afterPendingRestart || !videoServiceStartResponseReceived || !videoServiceStartResponse //If we haven't started the service before
- || (videoServiceStartResponse && isEncrypted && !session.isServiceProtected(SessionType.NAV))) { //Or the service has been started but we'd like to start an encrypted one
- session.setDesiredVideoParams(parameters);
-
- videoServiceStartResponseReceived = false;
- videoServiceStartResponse = false;
-
- addVideoServiceListener();
- session.startService(SessionType.NAV, isEncrypted);
-
+ addVideoServiceListener();
+ if (session != null) {
+ session.startService(SessionType.NAV, isEncrypted);
+ }
+ }
}
}
@@ -237,20 +251,27 @@ public class LifecycleManager extends BaseLifecycleManager {
videoServiceStartResponse = false;
}
};
- session.addServiceListener(SessionType.NAV, videoServiceListener);
+
+ synchronized (SESSION_LOCK) {
+ if (session != null) {
+ session.addServiceListener(SessionType.NAV, videoServiceListener);
+ }
+ }
}
}
@Override
void startAudioService(boolean isEncrypted) {
- if (session == null) {
- DebugTool.logWarning(TAG, "SdlSession is not created yet.");
- return;
- }
- if (!session.getIsConnected()) {
- DebugTool.logWarning(TAG, "Connection is not available.");
- return;
+ synchronized (SESSION_LOCK) {
+ if (session == null) {
+ DebugTool.logWarning(TAG, "SdlSession is not created yet.");
+ return;
+ }
+ if (!session.getIsConnected()) {
+ DebugTool.logWarning(TAG, "Connection is not available.");
+ return;
+ }
+ session.startService(SessionType.PCM, isEncrypted);
}
- session.startService(SessionType.PCM, isEncrypted);
}
}
diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/managers/lockscreen/LockScreenManager.java b/android/sdl_android/src/main/java/com/smartdevicelink/managers/lockscreen/LockScreenManager.java
index 97e8c8bca..3f6cfb4f3 100644
--- a/android/sdl_android/src/main/java/com/smartdevicelink/managers/lockscreen/LockScreenManager.java
+++ b/android/sdl_android/src/main/java/com/smartdevicelink/managers/lockscreen/LockScreenManager.java
@@ -205,7 +205,7 @@ public class LockScreenManager extends BaseSubManager {
driverDistStatus = DriverDistractionState.DD_ON.equals(ddState.getState());
mLockscreenWarningMsg = ddState.getLockscreenWarningMessage();
boolean previousDismissibleState = isLockscreenDismissible;
- if(ddState.getLockscreenDismissibility() != null ) {
+ if (ddState.getLockscreenDismissibility() != null) {
isLockscreenDismissible = ddState.getLockscreenDismissibility();
} //If the param is null, we assume it stays as the previous value
diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/managers/video/VideoStreamManager.java b/android/sdl_android/src/main/java/com/smartdevicelink/managers/video/VideoStreamManager.java
index cce131baa..9874c0d7c 100644
--- a/android/sdl_android/src/main/java/com/smartdevicelink/managers/video/VideoStreamManager.java
+++ b/android/sdl_android/src/main/java/com/smartdevicelink/managers/video/VideoStreamManager.java
@@ -144,22 +144,34 @@ public class VideoStreamManager extends BaseVideoStreamManager {
hapticManager = new HapticInterfaceManager(internalInterface);
}
checkState();
- startEncoder();
- stateMachine.transitionToState(StreamingStateMachine.STARTED);
- hasStarted = true;
+ boolean encoderStarted = startEncoder();
+ if (encoderStarted) {
+ stateMachine.transitionToState(StreamingStateMachine.STARTED);
+ hasStarted = true;
+ } else {
+ DebugTool.logError(TAG, "Error starting video encoder");
+ stateMachine.transitionToState(StreamingStateMachine.ERROR);
+ withPendingRestart = false;
+ if (session != null) {
+ session.endService(SessionType.NAV);
+ }
+ }
}
}
@Override
public void onServiceEnded(SdlSession session, SessionType type) {
if (SessionType.NAV.equals(type)) {
- if (remoteDisplay !=null){
- stopStreaming(withPendingRestart);
+ if (remoteDisplay != null) {
+ if (withPendingRestart && isHMIStateVideoStreamCapable(currentOnHMIStatus)) {
+ stopStreaming(withPendingRestart);
+ } else {
+ stopStreaming();
+ }
}
stateMachine.transitionToState(StreamingStateMachine.NONE);
transitionToState(SETTING_UP);
-
- if (withPendingRestart){
+ if (withPendingRestart && isHMIStateVideoStreamCapable(currentOnHMIStatus)) {
VideoStreamManager manager = VideoStreamManager.this;
manager.internalInterface.startVideoService(manager.getLastCachedStreamingParameters(), manager.isEncrypted, withPendingRestart);
}
@@ -198,6 +210,10 @@ public class VideoStreamManager extends BaseVideoStreamManager {
if (hasStarted && (isHMIStateVideoStreamCapable(prevOnHMIStatus)) && (!isHMIStateVideoStreamCapable(currentOnHMIStatus))) {
stopVideoStream();
}
+ if (withPendingRestart && hasStarted && (!isHMIStateVideoStreamCapable(prevOnHMIStatus)) && (isHMIStateVideoStreamCapable(currentOnHMIStatus))) {
+ VideoStreamManager manager = VideoStreamManager.this;
+ manager.internalInterface.startVideoService(manager.getLastCachedStreamingParameters(), manager.isEncrypted, withPendingRestart);
+ }
}
}
};
@@ -221,7 +237,7 @@ public class VideoStreamManager extends BaseVideoStreamManager {
public void onCapabilityRetrieved(Object capability) {
VideoStreamingParameters params = (parameters == null) ? new VideoStreamingParameters() : new VideoStreamingParameters(parameters);
- VideoStreamingCapability castedCapability = ((VideoStreamingCapability)capability);
+ VideoStreamingCapability castedCapability = ((VideoStreamingCapability) capability);
// means only scale received
if (castedCapability.getPreferredResolution() == null &&
@@ -297,12 +313,12 @@ public class VideoStreamManager extends BaseVideoStreamManager {
@Override
public void onCapabilityRetrieved(Object capability) {
VideoStreamingParameters params = new VideoStreamingParameters();
- VideoStreamingCapability castedCapability = ((VideoStreamingCapability)capability);
+ VideoStreamingCapability castedCapability = ((VideoStreamingCapability) capability);
VideoStreamManager.this.originalCapability = castedCapability;
params.update(castedCapability, vehicleMake);//Streaming parameters are ready time to stream
VideoStreamManager.this.parameters = params;
checkState();
- }
+ }
@Override
public void onError(String info) {
@@ -351,12 +367,13 @@ public class VideoStreamManager extends BaseVideoStreamManager {
*/
public void startRemoteDisplayStream(Context context, Class<? extends SdlRemoteDisplay> remoteDisplayClass, VideoStreamingParameters parameters, final boolean encrypted, VideoStreamingRange supportedLandscapeStreamingRange, VideoStreamingRange supportedPortraitStreamingRange) {
configureGlobalParameters(context, remoteDisplayClass, encrypted, supportedPortraitStreamingRange, supportedLandscapeStreamingRange);
- if(majorProtocolVersion >= 5 && !internalInterface.getSystemCapabilityManager().isCapabilitySupported(SystemCapabilityType.VIDEO_STREAMING)){
+ if (majorProtocolVersion >= 5 && !internalInterface.getSystemCapabilityManager().isCapabilitySupported(SystemCapabilityType.VIDEO_STREAMING)) {
stateMachine.transitionToState(StreamingStateMachine.ERROR);
return;
}
processCapabilitiesWithPendingStart(encrypted, parameters);
}
+
/**
* Starts streaming a remote display to the module if there is a connected session. This method of streaming requires the device to be on API level 19 or higher
*
@@ -368,7 +385,7 @@ public class VideoStreamManager extends BaseVideoStreamManager {
* @param encrypted a flag of if the stream should be encrypted. Only set if you have a supplied encryption library that the module can understand.
*/
@Deprecated
- public void startRemoteDisplayStream(Context context, Class<? extends SdlRemoteDisplay> remoteDisplayClass, VideoStreamingParameters parameters, final boolean encrypted){
+ public void startRemoteDisplayStream(Context context, Class<? extends SdlRemoteDisplay> remoteDisplayClass, VideoStreamingParameters parameters, final boolean encrypted) {
configureGlobalParameters(context, remoteDisplayClass, encrypted, null, null);
boolean isCapabilitySupported = internalInterface.getSystemCapabilityManager() != null && internalInterface.getSystemCapabilityManager().isCapabilitySupported(SystemCapabilityType.VIDEO_STREAMING);
if (majorProtocolVersion >= 5 && !isCapabilitySupported) {
@@ -472,7 +489,7 @@ public class VideoStreamManager extends BaseVideoStreamManager {
/**
* Initializes and starts the virtual display encoder and creates the remote display
*/
- private void startEncoder() {
+ private boolean startEncoder() {
try {
if (remoteDisplay != null) {
remoteDisplay.resizeView(parameters.getResolution().getResolutionWidth(), parameters.getResolution().getResolutionHeight());
@@ -489,7 +506,9 @@ public class VideoStreamManager extends BaseVideoStreamManager {
} catch (Exception e) {
stateMachine.transitionToState(StreamingStateMachine.ERROR);
e.printStackTrace();
+ return false;
}
+ return true;
}
/**
@@ -577,7 +596,7 @@ public class VideoStreamManager extends BaseVideoStreamManager {
return (stateMachine.getState() == StreamingStateMachine.READY) ||
(stateMachine.getState() == StreamingStateMachine.STARTED) ||
(stateMachine.getState() == StreamingStateMachine.STOPPED);
- }
+ }
/**
* Check if video is currently streaming and visible
@@ -671,8 +690,8 @@ public class VideoStreamManager extends BaseVideoStreamManager {
//A good time to refresh spatial data
DisplayMetrics displayMetrics = new DisplayMetrics();
VideoStreamManager.this.remoteDisplay.getDisplay().getMetrics(displayMetrics);
- displayMetrics.widthPixels = (int) (parameters.getResolution().getResolutionWidth() * parameters.getScale());
- displayMetrics.heightPixels = (int) (parameters.getResolution().getResolutionHeight() * parameters.getScale());
+ displayMetrics.widthPixels = (int) (parameters.getResolution().getResolutionWidth() * parameters.getScale());
+ displayMetrics.heightPixels = (int) (parameters.getResolution().getResolutionHeight() * parameters.getScale());
createTouchScalar(parameters.getResolution(), displayMetrics);
if (hapticManager != null) {
remoteDisplay.getMainView().post(new Runnable() {
@@ -804,16 +823,16 @@ public class VideoStreamManager extends BaseVideoStreamManager {
return parameters;
}
- private List<VideoStreamingCapability> getSupportedCapabilities(VideoStreamingCapability rootCapability){
+ private List<VideoStreamingCapability> getSupportedCapabilities(VideoStreamingCapability rootCapability) {
List<VideoStreamingCapability> validCapabilities = new ArrayList<>();
- if (rootCapability == null){
+ if (rootCapability == null) {
return null;
}
List<VideoStreamingCapability> allCapabilities = new ArrayList<>();
List<VideoStreamingCapability> additionalCapabilities = rootCapability.getAdditionalVideoStreamingCapabilities();
- if (additionalCapabilities != null){
+ if (additionalCapabilities != null) {
allCapabilities.addAll(additionalCapabilities);
}
rootCapability.setAdditionalVideoStreamingCapabilities(null);
@@ -847,7 +866,7 @@ public class VideoStreamManager extends BaseVideoStreamManager {
return validCapabilities;
}
- private Boolean inRange(VideoStreamingCapability capability, VideoStreamingRange range){
+ private Boolean inRange(VideoStreamingCapability capability, VideoStreamingRange range) {
if (capability == null) {
return false;
}
@@ -855,7 +874,7 @@ public class VideoStreamManager extends BaseVideoStreamManager {
return true;
}
- if (isZeroRange(range)){
+ if (isZeroRange(range)) {
return false;
}
@@ -868,7 +887,7 @@ public class VideoStreamManager extends BaseVideoStreamManager {
ImageResolution resolution = capability.getPreferredResolution();
if (resolution != null) {
Double currentAspectRatio = normalizeAspectRatio(resolution);
- if (!range.isAspectRatioInRange(currentAspectRatio)){
+ if (!range.isAspectRatioInRange(currentAspectRatio)) {
return false;
}
}
@@ -892,9 +911,9 @@ public class VideoStreamManager extends BaseVideoStreamManager {
if (width <= 0.0 || height <= 0.0) {
return 0.0;
} else if (width < height) {
- return height/width;
+ return height / width;
} else if (width > height) {
- return width/height;
+ return width / height;
} else {
return 1.0;
}
@@ -910,14 +929,14 @@ public class VideoStreamManager extends BaseVideoStreamManager {
}
}
- private Boolean isZeroRange(VideoStreamingRange range){
- if (range == null || range.getMaximumResolution() == null || range.getMinimumResolution() == null){
+ private Boolean isZeroRange(VideoStreamingRange range) {
+ if (range == null || range.getMaximumResolution() == null || range.getMinimumResolution() == null) {
return false;
}
return isZeroResolution(range.getMaximumResolution()) && isZeroResolution(range.getMinimumResolution());
}
- private boolean isZeroResolution(Resolution resolution){
+ private boolean isZeroResolution(Resolution resolution) {
if (resolution == null) {
return false;
}
diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/managers/video/resolution/VideoStreamingRange.java b/android/sdl_android/src/main/java/com/smartdevicelink/managers/video/resolution/VideoStreamingRange.java
index f94220eef..cac0d62d9 100644
--- a/android/sdl_android/src/main/java/com/smartdevicelink/managers/video/resolution/VideoStreamingRange.java
+++ b/android/sdl_android/src/main/java/com/smartdevicelink/managers/video/resolution/VideoStreamingRange.java
@@ -108,7 +108,7 @@ public class VideoStreamingRange {
if (maximumAspectRatio == null && minimumAspectRatio == null) {
return true;
}
- if (aspectRatio == null){
+ if (aspectRatio == null) {
return false;
}
diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/transport/MultiplexBluetoothTransport.java b/android/sdl_android/src/main/java/com/smartdevicelink/transport/MultiplexBluetoothTransport.java
index 31cea21c8..2eea57b98 100644
--- a/android/sdl_android/src/main/java/com/smartdevicelink/transport/MultiplexBluetoothTransport.java
+++ b/android/sdl_android/src/main/java/com/smartdevicelink/transport/MultiplexBluetoothTransport.java
@@ -117,7 +117,7 @@ public class MultiplexBluetoothTransport extends MultiplexBaseTransport {
* A method to retrieve the currently connected bluetooth device
* @return the connected bluetooth device if connected, null otherwise.
*/
- public BluetoothDevice getConnectedDevice(){
+ public BluetoothDevice getConnectedDevice() {
return connectedDevice;
}
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 588b905cc..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);
@@ -303,7 +323,7 @@ public abstract class SdlBroadcastReceiver extends BroadcastReceiver {
//If the device is not null the listener should start as well as the
//case where this app was installed after BT connected and is the
//only SDL app installed on the device. (Rare corner case)
- if(device != null || sdlAppInfoList.size() == 1) {
+ if (device != null || sdlAppInfoList.size() == 1) {
SdlDeviceListener sdlDeviceListener = getSdlDeviceListener(context, device);
if (!sdlDeviceListener.isRunning()) {
sdlDeviceListener.start();
@@ -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
diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/transport/SdlRouterService.java b/android/sdl_android/src/main/java/com/smartdevicelink/transport/SdlRouterService.java
index 9d24ddfec..04c9a2b0e 100644
--- a/android/sdl_android/src/main/java/com/smartdevicelink/transport/SdlRouterService.java
+++ b/android/sdl_android/src/main/java/com/smartdevicelink/transport/SdlRouterService.java
@@ -70,6 +70,7 @@ import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.Parcelable;
import android.os.RemoteException;
+import android.provider.Settings;
import android.util.AndroidRuntimeException;
import android.util.SparseArray;
import android.util.SparseIntArray;
@@ -119,6 +120,8 @@ import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.Manifest.permission.BLUETOOTH_SCAN;
import static com.smartdevicelink.transport.TransportConstants.CONNECTED_DEVICE_STRING_EXTRA_NAME;
import static com.smartdevicelink.transport.TransportConstants.FOREGROUND_EXTRA;
import static com.smartdevicelink.transport.TransportConstants.FORMED_PACKET_EXTRA_NAME;
@@ -142,7 +145,7 @@ public class SdlRouterService extends Service {
/**
* <b> NOTE: DO NOT MODIFY THIS UNLESS YOU KNOW WHAT YOU'RE DOING.</b>
*/
- protected static final int ROUTER_SERVICE_VERSION_NUMBER = 15;
+ protected static final int ROUTER_SERVICE_VERSION_NUMBER = 16;
private static final String ROUTER_SERVICE_PROCESS = "com.smartdevicelink.router";
@@ -202,6 +205,7 @@ public class SdlRouterService extends Service {
private boolean wrongProcess = false;
private boolean initPassed = false;
private boolean hasCalledStartForeground = false;
+ private boolean hasConnectedBefore = false;
boolean firstStart = true;
public static HashMap<String, RegisteredApp> registeredApps;
@@ -215,6 +219,10 @@ public class SdlRouterService extends Service {
private boolean startSequenceComplete = false;
private VehicleType receivedVehicleType;
+ private boolean waitingForBTRuntimePermissions = false;
+ private Handler btPermissionsHandler;
+ private Runnable btPermissionsRunnable;
+ private final static int BT_PERMISSIONS_CHECK_FREQUENCY = 1000;
private ExecutorService packetExecutor = null;
ConcurrentHashMap<TransportType, PacketWriteTaskMaster> packetWriteTaskMasterMap = null;
@@ -365,6 +373,11 @@ public class SdlRouterService extends Service {
switch (msg.what) {
case TransportConstants.ROUTER_REQUEST_BT_CLIENT_CONNECT:
+ //Starting with Android 12 this use case will require the BLUETOOTH_SCAN PERMISSION
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && !AndroidTools.isPermissionGranted(BLUETOOTH_SCAN, service.getApplicationContext(), service.getPackageName())) {
+ DebugTool.logError(TAG, "BLUETOOTH_SCAN Permissions not granted for this app");
+ break;
+ }
if (receivedBundle.getBoolean(TransportConstants.CONNECT_AS_CLIENT_BOOLEAN_EXTRA, false)
&& !connectAsClient) { //We check this flag to make sure we don't try to connect over and over again. On D/C we should set to false
//Log.d(TAG,"Attempting to connect as bt client");
@@ -1085,7 +1098,7 @@ public class SdlRouterService extends Service {
*
* @return true if this service is set up correctly
*/
- private boolean initCheck() {
+ private boolean initCheck(boolean isConnectedOverUSB) {
if (!processCheck()) {
DebugTool.logError(TAG, "Not using correct process. Shutting down");
wrongProcess = true;
@@ -1095,6 +1108,14 @@ public class SdlRouterService extends Service {
DebugTool.logError(TAG, "Bluetooth Permission is not granted. Shutting down");
return false;
}
+
+ // If Android 12 or newer make sure we have BLUETOOTH_CONNECT Runtime permission
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && !AndroidTools.isPermissionGranted(BLUETOOTH_CONNECT, this, this.getPackageName())) {
+ if (!isConnectedOverUSB) { //If BLUETOOTH_CONNECT permission is not granted We want to make sure we are connected over USB
+ return false;
+ }
+ }
+
if (!AndroidTools.isServiceExported(this, new ComponentName(this, this.getClass()))) { //We want to check to see if our service is actually exported
DebugTool.logError(TAG, "Service isn't exported. Shutting down");
return false;
@@ -1256,10 +1277,14 @@ public class SdlRouterService extends Service {
(HashMap<String, Object>) intent.getSerializableExtra(TransportConstants.VEHICLE_INFO_EXTRA)
);
}
+ boolean isConnectedOverUSB = false;
+ if (intent != null && intent.hasExtra(TransportConstants.CONNECTION_TYPE_EXTRA)) {
+ isConnectedOverUSB = TransportConstants.AOA_USB.equalsIgnoreCase(intent.getStringExtra(TransportConstants.CONNECTION_TYPE_EXTRA));
+ }
// Only trusting the first intent received to start the RouterService and run initial checks to avoid a case where an app could send incorrect data after the spp connection has started.
if (firstStart) {
firstStart = false;
- if (!initCheck()) { // Run checks on process and permissions
+ if (!initCheck(isConnectedOverUSB)) { // Run checks on process and permissions
deployNextRouterService();
closeSelf();
return START_REDELIVER_INTENT;
@@ -1296,6 +1321,7 @@ public class SdlRouterService extends Service {
}
boolean confirmedDevice = intent.getBooleanExtra(TransportConstants.CONFIRMED_SDL_DEVICE, false);
int timeout = getNotificationTimeout(address, confirmedDevice);
+ hasConnectedBefore = hasSDLConnected(address);
enterForeground("Waiting for connection...", timeout, false);
resetForegroundTimeOut(timeout);
@@ -1337,6 +1363,10 @@ public class SdlRouterService extends Service {
altTransportTimerHandler = null;
}
+ if (btPermissionsHandler != null && btPermissionsRunnable != null) {
+ btPermissionsHandler.removeCallbacks(btPermissionsRunnable);
+ }
+
DebugTool.logWarning(TAG, "Sdl Router Service Destroyed");
closing = true;
//No need for this Broadcast Receiver anymore
@@ -1499,6 +1529,10 @@ public class SdlRouterService extends Service {
builder = new Notification.Builder(this, SDL_NOTIFICATION_CHANNEL_ID);
}
+ if (hasConnectedBefore && android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ builder.setForegroundServiceBehavior(Notification.FOREGROUND_SERVICE_IMMEDIATE);
+ }
+
if (0 != (getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE)) { //If we are in debug mode, include what app has the router service open
ComponentName name = new ComponentName(this, this.getClass());
builder.setContentTitle("SDL: " + name.getPackageName());
@@ -1521,7 +1555,8 @@ public class SdlRouterService extends Service {
// Create an intent that will be fired when the user clicks the notification.
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(SDL_NOTIFICATION_FAQS_PAGE));
- PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
+ int flag = android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.S ? PendingIntent.FLAG_IMMUTABLE : 0;
+ PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, flag);
builder.setContentIntent(pendingIntent);
if (chronometerLength > (FOREGROUND_TIMEOUT / 1000) && android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
@@ -1569,12 +1604,22 @@ public class SdlRouterService extends Service {
private void safeStartForeground(int id, Notification notification) {
try {
if (notification == null) {
- //Try the NotificationCompat this time in case there was a previous error
- NotificationCompat.Builder builder =
- new NotificationCompat.Builder(this, SDL_NOTIFICATION_CHANNEL_ID)
+ if (hasConnectedBefore && android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
+ Notification.Builder builder =
+ new Notification.Builder(this, SDL_NOTIFICATION_CHANNEL_ID)
.setContentTitle("SmartDeviceLink")
- .setContentText("Service Running");
- notification = builder.build();
+ .setContentText("Service Running")
+ .setForegroundServiceBehavior(Notification.FOREGROUND_SERVICE_IMMEDIATE);
+ notification = builder.build();
+ } else {
+ //Try the NotificationCompat this time in case there was a previous error
+ NotificationCompat.Builder builder =
+ new NotificationCompat.Builder(this, SDL_NOTIFICATION_CHANNEL_ID)
+ .setContentTitle("SmartDeviceLink")
+ .setContentText("Service Running");
+
+ notification = builder.build();
+ }
}
startForeground(id, notification);
DebugTool.logInfo(TAG, "Entered the foreground - " + System.currentTimeMillis());
@@ -1588,9 +1633,9 @@ public class SdlRouterService extends Service {
if (isForeground && !isPrimaryTransportConnected()) { //Ensure that the service is in the foreground and no longer connected to a transport
DebugTool.logInfo(TAG, "SdlRouterService to exit foreground");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
- this.stopForeground(Service.STOP_FOREGROUND_DETACH);
+ this.stopForeground(Service.STOP_FOREGROUND_REMOVE);
} else {
- stopForeground(false);
+ stopForeground(true);
}
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager != null) {
@@ -1684,6 +1729,9 @@ public class SdlRouterService extends Service {
*/
@SuppressWarnings("MissingPermission")
private boolean bluetoothAvailable() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && !AndroidTools.isPermissionGranted(BLUETOOTH_CONNECT, SdlRouterService.this, SdlRouterService.this.getPackageName())) {
+ return false;
+ }
try {
return (!(BluetoothAdapter.getDefaultAdapter() == null) && BluetoothAdapter.getDefaultAdapter().isEnabled());
} catch (NullPointerException e) { // only for BluetoothAdapter.getDefaultAdapter().isEnabled() call
@@ -1710,7 +1758,7 @@ public class SdlRouterService extends Service {
} else if (intent != null && TransportConstants.BIND_REQUEST_TYPE_ALT_TRANSPORT.equals(intent.getAction())) {
DebugTool.logInfo(TAG, "Received start intent with alt transport request.");
- startAltTransportTimer();
+ startAltTransportTimer(); //This timer is started to allow the router service to stay open while it waits for the USB transfer to take place
return true;
} else if (!bluetoothAvailable()) {//If bluetooth isn't on...there's nothing to see here
//Bluetooth is off, we should shut down
@@ -1732,8 +1780,8 @@ public class SdlRouterService extends Service {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !hasCalledStartForeground) {
//This must be called before stopping self
safeStartForeground(FOREGROUND_SERVICE_ID, null);
- exitForeground();
}
+ exitForeground();
if (getBaseContext() != null) {
stopSelf();
@@ -1745,6 +1793,11 @@ public class SdlRouterService extends Service {
}
private synchronized void initBluetoothSerialService() {
+ if (waitingForBTRuntimePermissions) {
+ DebugTool.logWarning(TAG, "This app has not been granted the BLUETOOTH_CONNECT runtime permission");
+ return;
+ }
+
if (legacyModeEnabled) {
DebugTool.logInfo(TAG, "Not starting own bluetooth during legacy mode");
return;
@@ -1801,6 +1854,17 @@ public class SdlRouterService extends Service {
startService.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ //Starting in Android 12 we need to start services from a foreground context
+ //To enable developers to be able to start their SdlService from the "background"
+ //we will attach a pendingIntent as an extra to the intent
+ //the developer can use this pendingIntent to start their SdlService from the context of
+ //the active RouterService
+ Intent pending = new Intent();
+ PendingIntent pendingIntent = PendingIntent.getForegroundService(this, (int) System.currentTimeMillis(), pending, PendingIntent.FLAG_MUTABLE | Intent.FILL_IN_COMPONENT);
+ startService.putExtra(TransportConstants.PENDING_INTENT_EXTRA, pendingIntent);
+ }
+
AndroidTools.sendExplicitBroadcast(getApplicationContext(), startService, null);
//HARDWARE_CONNECTED
@@ -1808,6 +1872,31 @@ public class SdlRouterService extends Service {
//If we have clients
notifyClients(createHardwareConnectedMessage(record));
}
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && TransportType.USB.equals(record.getType()) && !AndroidTools.isPermissionGranted(BLUETOOTH_CONNECT, SdlRouterService.this, SdlRouterService.this.getPackageName())) {
+ //Delay starting bluetoothTransport when we are connected over USB and the app does not have the BLUETOOTH_CONNECT permissions
+ waitingForBTRuntimePermissions = true;
+ btPermissionsHandler = new Handler(Looper.myLooper());
+ //Continuously Check for the BLUETOOTH_CONNECT Permission
+ btPermissionsRunnable = new Runnable() {
+ @Override
+ public void run() {
+ if (!AndroidTools.isPermissionGranted(BLUETOOTH_CONNECT, SdlRouterService.this, SdlRouterService.this.getPackageName())) {
+ btPermissionsHandler.postDelayed(btPermissionsRunnable, BT_PERMISSIONS_CHECK_FREQUENCY);
+ } else {
+ waitingForBTRuntimePermissions = false;
+ initBluetoothSerialService();
+ final NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+ if(notificationManager != null) {
+ notificationManager.cancel("SDL", TransportConstants.SDL_ERROR_NOTIFICATION_CHANNEL_ID_INT);
+ }
+ }
+ }
+ };
+ btPermissionsHandler.postDelayed(btPermissionsRunnable, BT_PERMISSIONS_CHECK_FREQUENCY);
+ //Present Notification to take user to permissions page for the app
+ showBTPermissionsNotification();
+ }
}
private Message createHardwareConnectedMessage(final TransportRecord record) {
@@ -1891,6 +1980,12 @@ public class SdlRouterService extends Service {
usbSessionMap.clear();
}
}
+ //In case the USB connection has ended before the timer expired, we should stop it
+ if (altTransportTimerHandler != null && altTransportTimerRunnable != null) {
+ altTransportTimerHandler.removeCallbacks(altTransportTimerRunnable);
+ altTransportTimerHandler = null;
+ altTransportTimerRunnable = null;
+ }
break;
case TCP:
if (tcpTransport != null) {
@@ -1942,7 +2037,7 @@ public class SdlRouterService extends Service {
bluetoothTransport.setStateManually(MultiplexBluetoothTransport.STATE_NONE);
bluetoothTransport = null;
}
- if (errorBundle != null && errorBundle.getByte(MultiplexBaseTransport.ERROR_REASON_KEY) == MultiplexBaseTransport.REASON_SPP_ERROR) {
+ if (errorBundle != null && errorBundle.getByte(MultiplexBaseTransport.ERROR_REASON_KEY) == MultiplexBaseTransport.REASON_SPP_ERROR && bluetoothAvailable()) {
notifySppError();
}
break;
@@ -2467,7 +2562,7 @@ public class SdlRouterService extends Service {
/**
* Checks to see if a device address has connected to SDL before.
*
- * @param address the mac address of the device in quesiton
+ * @param address the mac address of the device in question
* @return if this is the first status check of this device
*/
protected boolean isFirstStatusCheck(String address) {
@@ -2478,7 +2573,7 @@ public class SdlRouterService extends Service {
/**
* Checks to see if a device address has connected to SDL before.
*
- * @param address the mac address of the device in quesiton
+ * @param address the mac address of the device in question
* @return if an SDL connection has ever been established with this device
*/
protected boolean hasSDLConnected(String address) {
@@ -2542,6 +2637,11 @@ public class SdlRouterService extends Service {
if (Looper.myLooper() == null) {
Looper.prepare();
}
+
+ if (altTransportTimerHandler != null && altTransportTimerRunnable != null) {
+ altTransportTimerHandler.removeCallbacks(altTransportTimerRunnable);
+ }
+
altTransportTimerHandler = new Handler(Looper.myLooper());
altTransportTimerRunnable = new Runnable() {
public void run() {
@@ -2743,8 +2843,8 @@ public class SdlRouterService extends Service {
}
/* ****************************************************************************************************************************************
- // *********************************************************** LEGACY ****************************************************************
- //*****************************************************************************************************************************************/
+ // *********************************************************** LEGACY ****************************************************************
+ //*****************************************************************************************************************************************/
private boolean legacyModeEnabled = false;
private void enableLegacyMode(boolean enable) {
@@ -2761,9 +2861,9 @@ public class SdlRouterService extends Service {
}
- /* ****************************************************************************************************************************************
- // *********************************************************** UTILITY ****************************************************************
- //*****************************************************************************************************************************************/
+ /* ****************************************************************************************************************************************
+ // *********************************************************** UTILITY ****************************************************************
+ //*****************************************************************************************************************************************/
private void debugPacket(byte[] bytes) {
//DEBUG
@@ -2942,9 +3042,9 @@ public class SdlRouterService extends Service {
pingIntent = null;
}
- /* ****************************************************************************************************************************************
- // ********************************************************** TINY CLASSES ************************************************************
- //*****************************************************************************************************************************************/
+ /* ****************************************************************************************************************************************
+ // ********************************************************** TINY CLASSES ************************************************************
+ //*****************************************************************************************************************************************/
/**
* This class enables us to compare two router services
@@ -2973,7 +3073,7 @@ public class SdlRouterService extends Service {
/**
* Check if input is newer than this version
*
- * @param service a reference to another possible router service that is in quesiton
+ * @param service a reference to another possible router service that is in question
* @return if the supplied service is newer than this one
*/
public boolean isNewer(@SuppressWarnings("deprecation") LocalRouterService service) {
@@ -3138,9 +3238,9 @@ public class SdlRouterService extends Service {
return appId;
}
- /*public long getAppId() {
- return appId;
- }*/
+ /*public long getAppId() {
+ return appId;
+ }*/
/**
* This is a convenience variable and may not be used or useful in different protocols
@@ -3805,6 +3905,10 @@ public class SdlRouterService extends Service {
} else {
builder = new Notification.Builder(getApplicationContext(), TransportConstants.SDL_ERROR_NOTIFICATION_CHANNEL_ID);
}
+
+ if (hasConnectedBefore && android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ builder.setForegroundServiceBehavior(Notification.FOREGROUND_SERVICE_IMMEDIATE);
+ }
ComponentName name = new ComponentName(this, this.getClass());
if (0 != (getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE)) { //If we are in debug mode, include what app has the router service open
builder.setContentTitle("SDL: " + name.getPackageName());
@@ -3843,4 +3947,59 @@ public class SdlRouterService extends Service {
DebugTool.logError(TAG, "notifySppError: Unable to retrieve notification Manager service");
}
}
+
+ private void showBTPermissionsNotification() {
+ Notification.Builder builder;
+ if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
+ builder = new Notification.Builder(getApplicationContext());
+ } else {
+ builder = new Notification.Builder(getApplicationContext(), TransportConstants.SDL_ERROR_NOTIFICATION_CHANNEL_ID);
+ }
+
+ ComponentName name = new ComponentName(this, this.getClass());
+ if (0 != (getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE)) { //If we are in debug mode, include what app has the router service open
+ builder.setContentTitle("SDL: " + name.getPackageName());
+ } else {
+ builder.setContentTitle(getString(R.string.notification_title));
+ }
+ builder.setTicker(getString(R.string.sdl_error_notification_channel_name));
+ builder.setContentText(getString(R.string.allow_bluetooth_permissions));
+
+ //We should use icon from library resources if available
+ int trayId = getResources().getIdentifier("sdl_tray_icon", "drawable", getPackageName());
+
+ builder.setSmallIcon(trayId);
+ Bitmap icon = BitmapFactory.decodeResource(getResources(), R.drawable.spp_error);
+ builder.setLargeIcon(icon);
+
+ builder.setOngoing(false);
+ builder.setAutoCancel(true);
+
+ // Create an intent that will be fired when the user clicks the notification.
+ Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
+ Uri uri = Uri.fromParts("package", getPackageName(), null);
+ intent.setData(uri);
+ int flag = android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.S ? PendingIntent.FLAG_IMMUTABLE : 0;
+ PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, flag);
+ builder.setContentIntent(pendingIntent);
+
+ final String tag = "SDL";
+ //Now we need to add a notification channel
+ final NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+ if (notificationManager != null) {
+ notificationManager.cancel(tag, TransportConstants.SDL_ERROR_NOTIFICATION_CHANNEL_ID_INT);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ NotificationChannel notificationChannel = new NotificationChannel(TransportConstants.SDL_ERROR_NOTIFICATION_CHANNEL_ID, getString(R.string.sdl_error_notification_channel_name), NotificationManager.IMPORTANCE_HIGH);
+ notificationChannel.enableLights(true);
+ notificationChannel.enableVibration(true);
+ notificationChannel.setShowBadge(false);
+ notificationManager.createNotificationChannel(notificationChannel);
+ builder.setChannelId(notificationChannel.getId());
+ }
+ Notification notification = builder.build();
+ notificationManager.notify(tag, TransportConstants.SDL_ERROR_NOTIFICATION_CHANNEL_ID_INT, notification);
+ } else {
+ DebugTool.logError(TAG, "Unable to retrieve notification Manager service");
+ }
+ }
}
diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/transport/USBAccessoryAttachmentActivity.java b/android/sdl_android/src/main/java/com/smartdevicelink/transport/USBAccessoryAttachmentActivity.java
index 8e54de9a1..22ee5d1db 100644
--- a/android/sdl_android/src/main/java/com/smartdevicelink/transport/USBAccessoryAttachmentActivity.java
+++ b/android/sdl_android/src/main/java/com/smartdevicelink/transport/USBAccessoryAttachmentActivity.java
@@ -167,6 +167,7 @@ public class USBAccessoryAttachmentActivity extends Activity {
return;
}
serviceIntent.setAction(TransportConstants.BIND_REQUEST_TYPE_ALT_TRANSPORT);
+ serviceIntent.putExtra(TransportConstants.CONNECTION_TYPE_EXTRA, TransportConstants.AOA_USB);
ComponentName startedService;
try {
diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/transport/utl/SdlDeviceListener.java b/android/sdl_android/src/main/java/com/smartdevicelink/transport/utl/SdlDeviceListener.java
index 41ada091d..8e3682f50 100644
--- a/android/sdl_android/src/main/java/com/smartdevicelink/transport/utl/SdlDeviceListener.java
+++ b/android/sdl_android/src/main/java/com/smartdevicelink/transport/utl/SdlDeviceListener.java
@@ -111,7 +111,7 @@ public class SdlDeviceListener {
// set timeout = if first time seeing BT device, 30s, if not 15s
int timeout = connectedDevice != null && isFirstStatusCheck(connectedDevice.getAddress()) ? 30000 : 15000;
//Set our preference as false for this device for now
- if(connectedDevice != null) {
+ if (connectedDevice != null) {
setSDLConnectedStatus(contextWeakReference.get(), connectedDevice.getAddress(), false);
}
bluetoothHandler = new TransportHandler(this);
@@ -190,7 +190,7 @@ public class SdlDeviceListener {
*/
public void sendStartService() {
SdlDeviceListener sdlListener = this.provider.get();
- SdlPacket serviceProbe = SdlPacketFactory.createStartSession(SessionType.RPC, 0x00, (byte)0x01, (byte)0x00, false);
+ SdlPacket serviceProbe = SdlPacketFactory.createStartSession(SessionType.RPC, 0x00, (byte) 0x01, (byte) 0x00, false);
serviceProbe.putTag(ControlFrameTags.RPC.StartService.PROTOCOL_VERSION, MAX_PROTOCOL_VERSION.toString());
byte[] constructed = serviceProbe.constructPacket();
if (sdlListener.bluetoothTransport != null && sdlListener.bluetoothTransport.getState() == MultiplexBluetoothTransport.STATE_CONNECTED) {
@@ -216,7 +216,7 @@ public class SdlDeviceListener {
} else {
hashID = BitConverter.intFromByteArray(packet.getPayload(), 0);
}
- byte[] stopService = SdlPacketFactory.createEndSession(SessionType.RPC, (byte)packet.getSessionId(), 0, (byte)packet.getVersion(), hashID).constructPacket();
+ byte[] stopService = SdlPacketFactory.createEndSession(SessionType.RPC, (byte) packet.getSessionId(), 0, (byte) packet.getVersion(), hashID).constructPacket();
if (sdlListener.bluetoothTransport != null && sdlListener.bluetoothTransport.getState() == MultiplexBluetoothTransport.STATE_CONNECTED) {
sdlListener.bluetoothTransport.write(stopService, 0, stopService.length);
}
@@ -259,8 +259,11 @@ public class SdlDeviceListener {
AndroidTools.saveVehicleType(sdlListener.contextWeakReference.get(), vehicleType, sdlListener.connectedDevice.getAddress());
boolean keepConnectionOpen = sdlListener.callback.onTransportConnected(sdlListener.contextWeakReference.get(), sdlListener.connectedDevice);
if (!keepConnectionOpen) {
- sdlListener.bluetoothTransport.stop();
- sdlListener.bluetoothTransport = null;
+ if (sdlListener.bluetoothTransport != null) {
+ sdlListener.bluetoothTransport.stop();
+ sdlListener.bluetoothTransport = null;
+ sdlListener.bluetoothHandler = null;
+ }
sdlListener.timeoutHandler.removeCallbacks(sdlListener.timeoutRunner);
}
}
@@ -349,7 +352,7 @@ public class SdlDeviceListener {
/**
* Callback for the SdlDeviceListener. It will return if the supplied device makes a bluetooth
- * connection on the SDL UUID RFCOMM chanel or not. Most of the time the only callback that
+ * connection on the SDL UUID RFCOMM channel or not. Most of the time the only callback that
* matters will be the onTransportConnected.
*/
public interface Callback {
diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/util/AndroidTools.java b/android/sdl_android/src/main/java/com/smartdevicelink/util/AndroidTools.java
index 1f4ba2de0..2700d35d9 100644
--- a/android/sdl_android/src/main/java/com/smartdevicelink/util/AndroidTools.java
+++ b/android/sdl_android/src/main/java/com/smartdevicelink/util/AndroidTools.java
@@ -48,6 +48,7 @@ import android.content.res.XmlResourceParser;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.BatteryManager;
+import android.os.Build;
import android.os.Bundle;
import androidx.annotation.Nullable;
@@ -69,6 +70,9 @@ import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.Manifest.permission.BLUETOOTH_SCAN;
+
public class AndroidTools {
@@ -199,6 +203,25 @@ public class AndroidTools {
return sdlAppInfoList;
}
+ public static boolean isPermissionGranted(String permissionName, Context context, String servicePackageName) {
+ PackageManager packageManager = context.getPackageManager();
+ if (packageManager == null) {
+ return false;
+ }
+ PackageInfo packageInfo;
+ try {
+ packageInfo = packageManager.getPackageInfo(servicePackageName, PackageManager.GET_PERMISSIONS);
+ if (packageInfo == null) {
+ return false;
+ }
+ int permissionResult = packageManager.checkPermission(permissionName, packageInfo.packageName);
+ return permissionResult == PackageManager.PERMISSION_GRANTED;
+ } catch (NameNotFoundException e) {
+ e.printStackTrace();
+ DebugTool.logError(TAG, "servicePackageName not found while checking " + permissionName + " permission", e);
+ return false;
+ }
+ }
/**
* Sends the provided intent to the specified destinations making it an explicit intent, rather
@@ -331,7 +354,7 @@ public class AndroidTools {
*
* @param context a context to access Android system services through.
* @param component a component name of a LocalRouterService.
- * @param manifestFieldId a string resources id that indicates an unique name for the vehicle data in the manifest.
+ * @param manifestFieldId a string resources id that indicates a unique name for the vehicle data in the manifest.
* @return The list of vehicle types, or null if an error occurred or field was not found.
*/
public static @Nullable List<VehicleType> getVehicleTypesFromManifest(Context context, ComponentName component, int manifestFieldId) {
@@ -362,10 +385,10 @@ public class AndroidTools {
XmlResourceParser parser = resources.getXml(xmlFieldId);
return SdlAppInfo.deserializeSupportedVehicles(parser);
} catch (PackageManager.NameNotFoundException e) {
- DebugTool.logError(TAG, "Failed to get OEM vehicle data filter: " + e.getMessage()+ " - assume vehicle data is supported");
+ DebugTool.logError(TAG, "Failed to get OEM vehicle data filter: " + e.getMessage() + " - assume vehicle data is supported");
return null;
} catch (Resources.NotFoundException ex) {
- DebugTool.logError(TAG, "Failed to find resource: " + ex.getMessage()+ " - assume vehicle data is supported");
+ DebugTool.logError(TAG, "Failed to find resource: " + ex.getMessage() + " - assume vehicle data is supported");
return null;
}
}
diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/util/SdlAppInfo.java b/android/sdl_android/src/main/java/com/smartdevicelink/util/SdlAppInfo.java
index 7d5ade055..bfdec946e 100644
--- a/android/sdl_android/src/main/java/com/smartdevicelink/util/SdlAppInfo.java
+++ b/android/sdl_android/src/main/java/com/smartdevicelink/util/SdlAppInfo.java
@@ -136,7 +136,7 @@ public class SdlAppInfo {
if (!contextPackageName.equals(packageName)) {
try {
Context appContext = context.createPackageContext(packageName, 0);
- if (appContext == null){
+ if (appContext == null) {
DebugTool.logError(TAG, "Failed to create context with the given package name");
return;
}
@@ -240,7 +240,7 @@ public class SdlAppInfo {
if (model == null && modelYear == null && trim == null) {
vehicleMakesList.add(vehicleMake);
- } else if (model != null){
+ } else if (model != null) {
vehicleMake.setModel(model);
if (modelYear != null) {
vehicleMake.setModelYear(modelYear);
@@ -271,13 +271,13 @@ public class SdlAppInfo {
* @return true if vehicle type is supported.
*/
public static boolean checkIfVehicleSupported(List<VehicleType> supportedVehicleList, VehicleType connectedVehicle) {
- if (supportedVehicleList == null || supportedVehicleList.isEmpty() || connectedVehicle == null || connectedVehicle.getStore() == null|| connectedVehicle.getStore().isEmpty()) {
+ if (supportedVehicleList == null || supportedVehicleList.isEmpty() || connectedVehicle == null || connectedVehicle.getStore() == null || connectedVehicle.getStore().isEmpty()) {
return true;
}
if (supportedVehicleList.contains(connectedVehicle)) {
return true;
}
- for (VehicleType supportedVehicle: supportedVehicleList) {
+ for (VehicleType supportedVehicle : supportedVehicleList) {
boolean areVehicleMakesEqual = CompareUtils.areStringsEqual(supportedVehicle.getMake(), connectedVehicle.getMake(), true, false);
if (areVehicleMakesEqual) {
String supportedVehicleModel = supportedVehicle.getModel();
diff --git a/android/sdl_android/src/main/res/values/sdl.xml b/android/sdl_android/src/main/res/values/sdl.xml
index 7bb919f0b..bd96c54ab 100644
--- a/android/sdl_android/src/main/res/values/sdl.xml
+++ b/android/sdl_android/src/main/res/values/sdl.xml
@@ -2,7 +2,7 @@
<resources>
<string name="sdl_router_service_version_name" translatable="false">sdl_router_version</string>
- <integer name="sdl_router_service_version_value">15</integer>
+ <integer name="sdl_router_service_version_value">16</integer>
<string name="sdl_router_service_is_custom_name" translatable="false">sdl_custom_router</string>
<string name="sdl_oem_vehicle_type_filter_name" translatable="false">sdl_oem_vehicle_type</string>
diff --git a/android/sdl_android/src/main/res/values/strings.xml b/android/sdl_android/src/main/res/values/strings.xml
index 89322299f..36a089366 100644
--- a/android/sdl_android/src/main/res/values/strings.xml
+++ b/android/sdl_android/src/main/res/values/strings.xml
@@ -5,6 +5,7 @@
<string name="lockscreen_device_image_description">Device Icon</string>
<string name="default_lockscreen_warning_message">Swipe down to dismiss, acknowledging that you are not the driver.</string>
<string name="spp_out_of_resource">Too many apps are using Bluetooth</string>
+ <string name="allow_bluetooth_permissions">Please grant this app the Nearby Devices Permission to use bluetooth</string>
<string name="notification_title">SmartDeviceLink</string>
<string name="sdl_error_notification_channel_name">SDL Error</string>
</resources> \ No newline at end of file
diff --git a/base/src/main/java/com/smartdevicelink/managers/BaseSdlManager.java b/base/src/main/java/com/smartdevicelink/managers/BaseSdlManager.java
index db775e10e..d71cf35f2 100644
--- a/base/src/main/java/com/smartdevicelink/managers/BaseSdlManager.java
+++ b/base/src/main/java/com/smartdevicelink/managers/BaseSdlManager.java
@@ -188,52 +188,57 @@ abstract class BaseSdlManager {
if ((actualLanguage != null && !actualLanguage.equals(language)) || (actualHMILanguage != null && !actualHMILanguage.equals(hmiLanguage))) {
- final LifecycleConfigurationUpdate lcu = managerListener.managerShouldUpdateLifecycle(actualLanguage, actualHMILanguage);
-
- ChangeRegistration changeRegistration;
- changeRegistration = new ChangeRegistration(actualLanguage, actualHMILanguage);
-
- if (lcu != null) {
- changeRegistration.setAppName(lcu.getAppName());
- changeRegistration.setNgnMediaScreenAppName(lcu.getShortAppName());
- changeRegistration.setTtsName(lcu.getTtsName());
- changeRegistration.setVrSynonyms(lcu.getVoiceRecognitionCommandNames());
- changeRegistration.setOnRPCResponseListener(new OnRPCResponseListener() {
- @Override
- public void onResponse(int correlationId, RPCResponse response) {
- if (response.getSuccess()) {
- try {
- DebugTool.logInfo(TAG, response.serializeJSON().toString());
- } catch (JSONException e) {
- DebugTool.logError(TAG, "Error attempting to serialize ChangeRegistrationResponse", e);
- }
-
- // go through and change sdlManager properties that were changed via the LCU update
- hmiLanguage = actualHMILanguage;
- language = actualLanguage;
-
- if (lcu.getAppName() != null) {
- appName = lcu.getAppName();
- }
-
- if (lcu.getShortAppName() != null) {
- shortAppName = lcu.getShortAppName();
+ if(managerListener != null) {
+ final LifecycleConfigurationUpdate lcu = managerListener.managerShouldUpdateLifecycle(actualLanguage, actualHMILanguage);
+
+ ChangeRegistration changeRegistration;
+ changeRegistration = new ChangeRegistration(actualLanguage, actualHMILanguage);
+
+ if (lcu != null) {
+ changeRegistration.setAppName(lcu.getAppName());
+ changeRegistration.setNgnMediaScreenAppName(lcu.getShortAppName());
+ changeRegistration.setTtsName(lcu.getTtsName());
+ changeRegistration.setVrSynonyms(lcu.getVoiceRecognitionCommandNames());
+ changeRegistration.setOnRPCResponseListener(new OnRPCResponseListener() {
+ @Override
+ public void onResponse(int correlationId, RPCResponse response) {
+ if (response.getSuccess()) {
+ try {
+ DebugTool.logInfo(TAG, response.serializeJSON().toString());
+ } catch (JSONException e) {
+ DebugTool.logError(TAG, "Error attempting to serialize ChangeRegistrationResponse", e);
+ }
+
+ // go through and change sdlManager properties that were changed via the LCU update
+ hmiLanguage = actualHMILanguage;
+ language = actualLanguage;
+
+ if (lcu.getAppName() != null) {
+ appName = lcu.getAppName();
+ }
+
+ if (lcu.getShortAppName() != null) {
+ shortAppName = lcu.getShortAppName();
+ }
+
+ if (lcu.getTtsName() != null) {
+ ttsChunks = lcu.getTtsName();
+ }
+
+ if (lcu.getVoiceRecognitionCommandNames() != null) {
+ vrSynonyms = lcu.getVoiceRecognitionCommandNames();
+ }
+ } else {
+ DebugTool.logError(TAG, "Change Registration onError: " + response.getResultCode() + " | Info: " + response.getInfo());
+ retryChangeRegistration();
}
-
- if (lcu.getTtsName() != null) {
- ttsChunks = lcu.getTtsName();
- }
-
- if (lcu.getVoiceRecognitionCommandNames() != null) {
- vrSynonyms = lcu.getVoiceRecognitionCommandNames();
- }
- } else {
- DebugTool.logError(TAG, "Change Registration onError: " + response.getResultCode() + " | Info: " + response.getInfo());
- retryChangeRegistration();
}
- }
- });
- this.sendRPC(changeRegistration);
+ });
+ this.sendRPC(changeRegistration);
+ }
+ }
+ else {
+ DebugTool.logError(TAG, "SdlManagerListener is null");
}
}
}
diff --git a/base/src/main/java/com/smartdevicelink/managers/file/UploadFileOperation.java b/base/src/main/java/com/smartdevicelink/managers/file/UploadFileOperation.java
index aab50a280..df2a4f3f7 100644
--- a/base/src/main/java/com/smartdevicelink/managers/file/UploadFileOperation.java
+++ b/base/src/main/java/com/smartdevicelink/managers/file/UploadFileOperation.java
@@ -244,7 +244,7 @@ class UploadFileOperation extends Task {
try {
this.inputStream.close();
} catch (IOException e) {
- DebugTool.logError(TAG,"Error attempting to close input stream", e);
+ DebugTool.logError(TAG, "Error attempting to close input stream", e);
}
}
@@ -353,7 +353,7 @@ class UploadFileOperation extends Task {
try {
bytesRead = inputStream.read(buffer, 0, size);
} catch (IOException e) {
- DebugTool.logError(TAG,"Error attempting to read from input stream", e);
+ DebugTool.logError(TAG, "Error attempting to read from input stream", e);
}
if (bytesRead > 0) {
@@ -388,7 +388,7 @@ class UploadFileOperation extends Task {
try {
size = inputStream.available();
} catch (IOException e) {
- DebugTool.logError(TAG,"Error trying to get input stream size", e);
+ DebugTool.logError(TAG, "Error trying to get input stream size", e);
}
}
return size;
diff --git a/base/src/main/java/com/smartdevicelink/managers/lifecycle/BaseLifecycleManager.java b/base/src/main/java/com/smartdevicelink/managers/lifecycle/BaseLifecycleManager.java
index 6602e7085..f1b20237b 100644
--- a/base/src/main/java/com/smartdevicelink/managers/lifecycle/BaseLifecycleManager.java
+++ b/base/src/main/java/com/smartdevicelink/managers/lifecycle/BaseLifecycleManager.java
@@ -32,6 +32,12 @@
package com.smartdevicelink.managers.lifecycle;
+import static com.smartdevicelink.managers.BaseSubManager.SETTING_UP;
+import static com.smartdevicelink.managers.BaseSubManager.READY;
+import static com.smartdevicelink.managers.BaseSubManager.LIMITED;
+import static com.smartdevicelink.managers.BaseSubManager.SHUTDOWN;
+import static com.smartdevicelink.managers.BaseSubManager.ERROR;
+
import androidx.annotation.NonNull;
import androidx.annotation.RestrictTo;
@@ -116,7 +122,10 @@ abstract class BaseLifecycleManager {
ON_UPDATE_LISTENER_LOCK = new Object(),
ON_REQUEST_LISTENER_LOCK = new Object(),
ON_NOTIFICATION_LISTENER_LOCK = new Object();
+ protected static final Object SESSION_LOCK = new Object();
+ private final Object STATE_LOCK = new Object();
+ private int state;
SdlSession session;
final AppConfig appConfig;
Version rpcSpecVersion = MAX_SUPPORTED_RPC_VERSION;
@@ -141,6 +150,7 @@ abstract class BaseLifecycleManager {
DisplayCapabilities initialMediaCapabilities;
BaseLifecycleManager(AppConfig appConfig, BaseTransportConfig config, LifecycleListener listener) {
+ transitionToState(SETTING_UP);
this.appConfig = appConfig;
this._transportConfig = config;
this.lifecycleListener = listener;
@@ -151,9 +161,13 @@ abstract class BaseLifecycleManager {
public void start() {
try {
- session.startSession();
+ synchronized (SESSION_LOCK) {
+ if (session != null) {
+ session.startSession();
+ }
+ }
} catch (SdlException e) {
- DebugTool.logError(TAG,"Error attempting to start session", e);
+ DebugTool.logError(TAG, "Error attempting to start session", e);
}
}
@@ -161,19 +175,28 @@ abstract class BaseLifecycleManager {
* Start a secured RPC service
*/
public void startRPCEncryption() {
- if (session != null) {
- session.startService(SessionType.RPC, true);
+ synchronized (SESSION_LOCK) {
+ if (session != null) {
+ session.startService(SessionType.RPC, true);
+ }
}
}
public synchronized void stop() {
- if (session != null) {
- session.close();
- session = null;
+ DebugTool.logInfo(TAG, "LifecycleManager stop requested");
+ clean(true);
+ transitionToState(SHUTDOWN);
+ }
+
+ protected void transitionToState(int state) {
+ synchronized (STATE_LOCK) {
+ this.state = state;
}
- if (taskmaster != null) {
- taskmaster.shutdown();
- taskmaster = null;
+ }
+
+ public int getState() {
+ synchronized (STATE_LOCK) {
+ return state;
}
}
@@ -194,8 +217,10 @@ abstract class BaseLifecycleManager {
}
Version getProtocolVersion() {
- if (session != null && session.getProtocolVersion() != null) {
- return session.getProtocolVersion();
+ synchronized (SESSION_LOCK) {
+ if (session != null && session.getProtocolVersion() != null) {
+ return session.getProtocolVersion();
+ }
}
return new Version(1, 0, 0);
}
@@ -301,10 +326,12 @@ abstract class BaseLifecycleManager {
}
private boolean isConnected() {
- if (session != null) {
- return session.getIsConnected();
- } else {
- return false;
+ synchronized (SESSION_LOCK) {
+ if (session != null) {
+ return session.getIsConnected();
+ } else {
+ return false;
+ }
}
}
@@ -331,6 +358,7 @@ abstract class BaseLifecycleManager {
void onClose(String info, Exception e, SdlDisconnectedReason reason) {
DebugTool.logInfo(TAG, "onClose");
+ transitionToState(SHUTDOWN);
if (lifecycleListener != null) {
lifecycleListener.onClosed((LifecycleManager) this, info, e, reason);
}
@@ -387,10 +415,7 @@ abstract class BaseLifecycleManager {
}
if (minimumRPCVersion != null && minimumRPCVersion.isNewerThan(rpcSpecVersion) == 1) {
DebugTool.logWarning(TAG, String.format("Disconnecting from head unit, the configured minimum RPC version %s is greater than the supported RPC version %s", minimumRPCVersion, rpcSpecVersion));
- UnregisterAppInterface msg = new UnregisterAppInterface();
- msg.setCorrelationID(UNREGISTER_APP_INTERFACE_CORRELATION_ID);
- sendRPCMessagePrivate(msg, true);
- clean();
+ clean(true);
onClose("RPC spec version not supported: " + rpcSpecVersion.toString(), null, SdlDisconnectedReason.MINIMUM_RPC_VERSION_HIGHER_THAN_SUPPORTED);
return;
}
@@ -399,15 +424,19 @@ abstract class BaseLifecycleManager {
VehicleType vehicleType = raiResponse.getVehicleType();
String systemSoftwareVersion = raiResponse.getSystemSoftwareVersion();
if (vehicleType != null || systemSoftwareVersion != null) {
- saveVehicleType(session.getActiveTransports(), vehicleType);
+
+ List<TransportRecord> activeTransports = null;
+ synchronized (SESSION_LOCK) {
+ if (session != null) {
+ activeTransports = session.getActiveTransports();
+ }
+ }
+ saveVehicleType(activeTransports, vehicleType);
SystemInfo systemInfo = new SystemInfo(vehicleType, systemSoftwareVersion, null);
boolean validSystemInfo = lifecycleListener.onSystemInfoReceived(systemInfo);
if (!validSystemInfo) {
DebugTool.logWarning(TAG, "Disconnecting from head unit, the system info was not accepted.");
- UnregisterAppInterface msg = new UnregisterAppInterface();
- msg.setCorrelationID(UNREGISTER_APP_INTERFACE_CORRELATION_ID);
- sendRPCMessagePrivate(msg, true);
- clean();
+ clean(true);
onClose("System not supported", null, SdlDisconnectedReason.DEFAULT);
return;
}
@@ -425,6 +454,7 @@ abstract class BaseLifecycleManager {
DebugTool.logInfo(TAG, "on hmi status");
boolean shouldInit = currentHMIStatus == null;
currentHMIStatus = (OnHMIStatus) message;
+ transitionToState(READY);
if (lifecycleListener != null && shouldInit) {
lifecycleListener.onConnected((LifecycleManager) BaseLifecycleManager.this);
}
@@ -494,7 +524,7 @@ abstract class BaseLifecycleManager {
if (!onAppInterfaceUnregistered.getReason().equals(AppInterfaceUnregisteredReason.LANGUAGE_CHANGE)) {
DebugTool.logInfo(TAG, "on app interface unregistered");
- clean();
+ clean(false);
onClose("OnAppInterfaceUnregistered received from head unit", null, SdlDisconnectedReason.APP_INTERFACE_UNREG);
} else {
DebugTool.logInfo(TAG, "re-registering for language change");
@@ -502,9 +532,11 @@ abstract class BaseLifecycleManager {
}
break;
case UNREGISTER_APP_INTERFACE:
- DebugTool.logInfo(TAG, "unregister app interface");
- clean();
- onClose("UnregisterAppInterface response received from head unit", null, SdlDisconnectedReason.APP_INTERFACE_UNREG);
+ DebugTool.logInfo(TAG, "Unregister app interface response received");
+ //Since only the library sends the UnregisterAppInterface requests, we know
+ //that the correct logic flows already happen based on where the call to send
+ //the request happens. There is also a SYNC4 bug that holds onto the response
+ //until the app reconnects within the same transport session.
break;
}
}
@@ -799,8 +831,10 @@ abstract class BaseLifecycleManager {
final ProtocolMessage pm = new ProtocolMessage();
pm.setData(msgBytes);
- if (session != null) {
- pm.setSessionID((byte) session.getSessionId());
+ synchronized (SESSION_LOCK) {
+ if (session != null) {
+ pm.setSessionID((byte) session.getSessionId());
+ }
}
pm.setMessageType(MessageType.RPC);
@@ -843,7 +877,7 @@ abstract class BaseLifecycleManager {
}
// HAX: Issue #1690, Ford Sync bug returning incorrect display capabilities (https://github.com/smartdevicelink/sdl_java_suite/issues/1690). Save the next desired layout type to the update capabilities when the SetDisplayLayout response is received
if (FunctionID.SET_DISPLAY_LAYOUT.toString().equals(message.getFunctionName())) {
- lastDisplayLayoutRequestTemplate = ((SetDisplayLayout)message).getDisplayLayout();
+ lastDisplayLayoutRequestTemplate = ((SetDisplayLayout) message).getDisplayLayout();
}
} else if (RPCMessage.KEY_RESPONSE.equals(message.getMessageType())) { // Response Specifics
RPCResponse response = (RPCResponse) message;
@@ -868,10 +902,14 @@ abstract class BaseLifecycleManager {
pm.setPriorityCoefficient(1);
}
- session.sendMessage(pm);
+ synchronized (SESSION_LOCK) {
+ if (session != null) {
+ session.sendMessage(pm);
+ }
+ }
} catch (OutOfMemoryError e) {
- DebugTool.logError(TAG,"Error attempting to send RPC message.", e);
+ DebugTool.logError(TAG, "Error attempting to send RPC message.", e);
}
}
@@ -940,22 +978,27 @@ abstract class BaseLifecycleManager {
DebugTool.logInfo(TAG, "on protocol session started");
if (minimumProtocolVersion != null && minimumProtocolVersion.isNewerThan(version) == 1) {
DebugTool.logWarning(TAG, String.format("Disconnecting from head unit, the configured minimum protocol version %s is greater than the supported protocol version %s", minimumProtocolVersion, getProtocolVersion()));
- session.endService(SessionType.RPC);
- clean();
+ clean(false);
onClose("Protocol version not supported: " + version, null, SdlDisconnectedReason.MINIMUM_PROTOCOL_VERSION_HIGHER_THAN_SUPPORTED);
return;
}
if (systemInfo != null && lifecycleListener != null) {
didCheckSystemInfo = true;
- saveVehicleType(session.getActiveTransports(), systemInfo.getVehicleType());
+ List<TransportRecord> activeTransports = null;
+ synchronized (SESSION_LOCK) {
+ if (session != null) {
+ activeTransports = session.getActiveTransports();
+ }
+ }
+ saveVehicleType(activeTransports, systemInfo.getVehicleType());
boolean validSystemInfo = lifecycleListener.onSystemInfoReceived(systemInfo);
if (!validSystemInfo) {
DebugTool.logWarning(TAG, "Disconnecting from head unit, the system info was not accepted.");
- session.endService(SessionType.RPC);
- clean();
+ clean(false);
onClose("System not supported", null, SdlDisconnectedReason.DEFAULT);
return;
+
}
//If the vehicle is acceptable, init security lib
setSecurityLibraryIfAvailable(systemInfo.getVehicleType());
@@ -1024,8 +1067,10 @@ abstract class BaseLifecycleManager {
@Override
public boolean isConnected() {
synchronized (BaseLifecycleManager.this) {
- if (BaseLifecycleManager.this.session != null) {
- return BaseLifecycleManager.this.session.getIsConnected();
+ synchronized (SESSION_LOCK) {
+ if (BaseLifecycleManager.this.session != null) {
+ return BaseLifecycleManager.this.session.getIsConnected();
+ }
}
}
return false;
@@ -1034,8 +1079,10 @@ abstract class BaseLifecycleManager {
@Override
public void addServiceListener(SessionType serviceType, ISdlServiceListener sdlServiceListener) {
synchronized (BaseLifecycleManager.this) {
- if(BaseLifecycleManager.this.session != null ){
- BaseLifecycleManager.this.session.addServiceListener(serviceType, sdlServiceListener);
+ synchronized (SESSION_LOCK) {
+ if (BaseLifecycleManager.this.session != null) {
+ BaseLifecycleManager.this.session.addServiceListener(serviceType, sdlServiceListener);
+ }
}
}
}
@@ -1043,8 +1090,10 @@ abstract class BaseLifecycleManager {
@Override
public void removeServiceListener(SessionType serviceType, ISdlServiceListener sdlServiceListener) {
synchronized (BaseLifecycleManager.this) {
- if (BaseLifecycleManager.this.session != null) {
- BaseLifecycleManager.this.session.removeServiceListener(serviceType, sdlServiceListener);
+ synchronized (SESSION_LOCK) {
+ if (BaseLifecycleManager.this.session != null) {
+ BaseLifecycleManager.this.session.removeServiceListener(serviceType, sdlServiceListener);
+ }
}
}
}
@@ -1114,8 +1163,10 @@ abstract class BaseLifecycleManager {
@Override
public boolean isTransportForServiceAvailable(SessionType serviceType) {
synchronized (BaseLifecycleManager.this) {
- if (BaseLifecycleManager.this.session != null) {
- return BaseLifecycleManager.this.session.isTransportForServiceAvailable(serviceType);
+ synchronized (SESSION_LOCK) {
+ if (BaseLifecycleManager.this.session != null) {
+ return BaseLifecycleManager.this.session.isTransportForServiceAvailable(serviceType);
+ }
}
}
return false;
@@ -1125,11 +1176,11 @@ abstract class BaseLifecycleManager {
@Override
public SdlMsgVersion getSdlMsgVersion() {
SdlMsgVersion msgVersion;
- if(rpcSpecVersion != null) {
+ if (rpcSpecVersion != null) {
msgVersion = new SdlMsgVersion(rpcSpecVersion.getMajor(), rpcSpecVersion.getMinor());
msgVersion.setPatchVersion(rpcSpecVersion.getPatch());
} else {
- msgVersion = new SdlMsgVersion(1,0);
+ msgVersion = new SdlMsgVersion(1, 0);
}
return msgVersion;
@@ -1144,8 +1195,10 @@ abstract class BaseLifecycleManager {
@Override
public long getMtu(SessionType serviceType) {
synchronized (BaseLifecycleManager.this) {
- if (BaseLifecycleManager.this.session != null) {
- return BaseLifecycleManager.this.session.getMtu(serviceType);
+ synchronized (SESSION_LOCK) {
+ if (BaseLifecycleManager.this.session != null) {
+ return BaseLifecycleManager.this.session.getMtu(serviceType);
+ }
}
}
return SdlProtocolBase.V1_V2_MTU_SIZE;
@@ -1229,7 +1282,20 @@ abstract class BaseLifecycleManager {
return null;
}
- void clean() {
+ void clean(boolean sendUnregisterAppInterface) {
+ int state = getState();
+ if (state == SHUTDOWN || state == ERROR) {
+ DebugTool.logInfo(TAG, "No need to clean, LCM is already cleaned: " + state);
+ return;
+ }
+
+ if (sendUnregisterAppInterface) {
+ DebugTool.logInfo(TAG, "Requesting to unregister from device");
+ UnregisterAppInterface uai = new UnregisterAppInterface();
+ uai.setCorrelationID(UNREGISTER_APP_INTERFACE_CORRELATION_ID);
+ sendRPCMessagePrivate(uai, true);
+ }
+
firstTimeFull = true;
currentHMIStatus = null;
lastDisplayLayoutRequestTemplate = null;
@@ -1246,8 +1312,11 @@ abstract class BaseLifecycleManager {
if (rpcRequestListeners != null) {
rpcRequestListeners.clear();
}
- if (session != null && session.getIsConnected()) {
- session.close();
+ synchronized (SESSION_LOCK) {
+ if (session != null && session.getIsConnected()) {
+ session.close();
+ session = null;
+ }
}
if (encryptionLifecycleManager != null) {
encryptionLifecycleManager.dispose();
@@ -1302,9 +1371,11 @@ abstract class BaseLifecycleManager {
if ((sec != null) && (sec.getMakeList() != null)) {
if (sec.getMakeList().contains(make)) {
sec.setAppId(appConfig.getAppID());
- if (session != null) {
- session.setSdlSecurity(sec);
- sec.handleSdlSession(session);
+ synchronized (SESSION_LOCK) {
+ if (session != null) {
+ session.setSdlSecurity(sec);
+ sec.handleSdlSession(session);
+ }
}
return;
}
@@ -1323,12 +1394,13 @@ abstract class BaseLifecycleManager {
this.rpcRequestListeners = new HashMap<>();
this.systemCapabilityManager = new SystemCapabilityManager(internalInterface);
setupInternalRpcListeners();
+
}
abstract void cycle(SdlDisconnectedReason disconnectedReason);
- void saveVehicleType(String address, VehicleType type){
+ void saveVehicleType(String address, VehicleType type) {
}
void saveVehicleType(List<TransportRecord> activeTransports, VehicleType type) {
diff --git a/base/src/main/java/com/smartdevicelink/managers/lifecycle/BaseSystemCapabilityManager.java b/base/src/main/java/com/smartdevicelink/managers/lifecycle/BaseSystemCapabilityManager.java
index 33a778e58..1f6c663a8 100644
--- a/base/src/main/java/com/smartdevicelink/managers/lifecycle/BaseSystemCapabilityManager.java
+++ b/base/src/main/java/com/smartdevicelink/managers/lifecycle/BaseSystemCapabilityManager.java
@@ -590,12 +590,12 @@ abstract class BaseSystemCapabilityManager {
final GetSystemCapability request = new GetSystemCapability();
request.setSystemCapabilityType(systemCapabilityType);
- /*
- The subscription flag in the request should be set based on multiple variables:
- - if subscribe is null (no change), willSubscribe = current subscription status, or false if the HU does not support subscriptions
- - if subscribe is false, then willSubscribe = false
- - if subscribe is true and the HU supports subscriptions, then willSubscribe = true
- */
+ /*
+ The subscription flag in the request should be set based on multiple variables:
+ - if subscribe is null (no change), willSubscribe = current subscription status, or false if the HU does not support subscriptions
+ - if subscribe is false, then willSubscribe = false
+ - if subscribe is true and the HU supports subscriptions, then willSubscribe = true
+ */
boolean shouldSubscribe = (subscribe != null) ? subscribe : isSubscribedToSystemCapability(systemCapabilityType);
final boolean willSubscribe = shouldSubscribe && supportsSubscriptions();
request.setSubscribe(willSubscribe);
diff --git a/base/src/main/java/com/smartdevicelink/managers/screen/DispatchGroup.java b/base/src/main/java/com/smartdevicelink/managers/screen/DispatchGroup.java
index f6dccb715..352f0bbc4 100644
--- a/base/src/main/java/com/smartdevicelink/managers/screen/DispatchGroup.java
+++ b/base/src/main/java/com/smartdevicelink/managers/screen/DispatchGroup.java
@@ -38,20 +38,25 @@ package com.smartdevicelink.managers.screen;
class DispatchGroup {
private int count;
private Runnable runnable;
+
DispatchGroup() {
count = 0;
}
+
synchronized void enter() {
count++;
}
+
synchronized void leave() {
count--;
run();
}
+
void notify(Runnable runnable) {
this.runnable = runnable;
run();
}
+
private void run() {
if (count <= 0 && runnable != null) {
runnable.run();
diff --git a/base/src/main/java/com/smartdevicelink/managers/screen/PresentAlertOperation.java b/base/src/main/java/com/smartdevicelink/managers/screen/PresentAlertOperation.java
index 9957ad309..a85901d3c 100644
--- a/base/src/main/java/com/smartdevicelink/managers/screen/PresentAlertOperation.java
+++ b/base/src/main/java/com/smartdevicelink/managers/screen/PresentAlertOperation.java
@@ -194,7 +194,7 @@ public class PresentAlertOperation extends Task {
List<SdlFile> filesToBeUploaded = new ArrayList<>();
for (TTSChunk ttsChunk : alertView.getAudio().getAudioData()) {
- if(ttsChunk.getType() != SpeechCapabilities.FILE){
+ if (ttsChunk.getType() != SpeechCapabilities.FILE) {
continue;
}
SdlFile audioFile = alertView.getAudio().getAudioFiles().get(ttsChunk.getText());
@@ -300,7 +300,7 @@ public class PresentAlertOperation extends Task {
public void onResponse(int correlationId, RPCResponse response) {
if (!response.getSuccess()) {
DebugTool.logError(TAG, "There was an error presenting the alert: " + response.getInfo());
- } else {
+ } else {
DebugTool.logInfo(TAG, "Alert finished presenting");
}
finishOperation(response.getSuccess(), ((AlertResponse) response).getTryAgainTime());
@@ -401,12 +401,12 @@ public class PresentAlertOperation extends Task {
private List<TTSChunk> getTTSChunksForAlert(AlertView alertView) {
AlertAudioData alertAudioData = alertView.getAudio();
List<TTSChunk> ttsChunks = new ArrayList<>();
- for (TTSChunk chunk : alertAudioData.getAudioData()) {
- if (chunk.getType() == SpeechCapabilities.FILE && !supportsAlertAudioFile()) {
- continue;
- }
- ttsChunks.add(chunk);
+ for (TTSChunk chunk : alertAudioData.getAudioData()) {
+ if (chunk.getType() == SpeechCapabilities.FILE && !supportsAlertAudioFile()) {
+ continue;
}
+ ttsChunks.add(chunk);
+ }
return ttsChunks.size() > 0 ? ttsChunks : null;
}
@@ -416,6 +416,14 @@ public class PresentAlertOperation extends Task {
* @return True if soft button images are currently supported; false if not.
*/
private boolean supportsSoftButtonImages() {
+ if (currentWindowCapability == null ||
+ currentWindowCapability.getSoftButtonCapabilities() == null ||
+ currentWindowCapability.getSoftButtonCapabilities().size() == 0 ||
+ currentWindowCapability.getSoftButtonCapabilities().get(0) == null
+ ) {
+ return true;
+ }
+
SoftButtonCapabilities softButtonCapabilities = currentWindowCapability.getSoftButtonCapabilities().get(0);
return softButtonCapabilities.getImageSupported().booleanValue();
}
@@ -446,7 +454,7 @@ public class PresentAlertOperation extends Task {
if (nonNullFields.isEmpty()) {
return alert;
}
- int numberOfLines = currentWindowCapability!= null ? ManagerUtility.WindowCapabilityUtility.getMaxNumberOfAlertFieldLines(currentWindowCapability) : 3;
+ int numberOfLines = currentWindowCapability != null ? ManagerUtility.WindowCapabilityUtility.getMaxNumberOfAlertFieldLines(currentWindowCapability) : 3;
switch (numberOfLines) {
case 1:
alert = assembleOneLineAlertText(alert, nonNullFields);
diff --git a/base/src/main/java/com/smartdevicelink/managers/screen/SoftButtonObject.java b/base/src/main/java/com/smartdevicelink/managers/screen/SoftButtonObject.java
index 76301bc07..2a9994ead 100644
--- a/base/src/main/java/com/smartdevicelink/managers/screen/SoftButtonObject.java
+++ b/base/src/main/java/com/smartdevicelink/managers/screen/SoftButtonObject.java
@@ -38,7 +38,6 @@ import com.smartdevicelink.proxy.rpc.OnButtonEvent;
import com.smartdevicelink.proxy.rpc.OnButtonPress;
import com.smartdevicelink.proxy.rpc.SoftButton;
import com.smartdevicelink.util.DebugTool;
-
import java.util.Collections;
import java.util.List;
@@ -50,7 +49,7 @@ import java.util.List;
*
* @see SoftButtonState
*/
-public class SoftButtonObject implements Cloneable{
+public class SoftButtonObject implements Cloneable {
private static final String TAG = "SoftButtonObject";
static final int SOFT_BUTTON_ID_NOT_SET_VALUE = -1;
static final int SOFT_BUTTON_ID_MIN_VALUE = 0;
@@ -73,12 +72,24 @@ public class SoftButtonObject implements Cloneable{
*/
public SoftButtonObject(@NonNull String name, @NonNull List<SoftButtonState> states, @NonNull String initialStateName, OnEventListener onEventListener) {
- // Make sure there aren't two states with the same name
- if (hasTwoStatesOfSameName(states)) {
- DebugTool.logError(TAG, "Two states have the same name in states list for soft button object");
- return;
+ boolean repeatedStateNames = hasTwoStatesOfSameName(states);
+
+ boolean hasStateWithInitialName = false;
+ for (SoftButtonState state : states) {
+ if(state.getName().equals(initialStateName)) {
+ hasStateWithInitialName = true;
+ break;
+ }
}
+ if (repeatedStateNames) {
+ DebugTool.logError(TAG, "A SoftButtonObject must have states with different names.");
+ return;
+ }
+ if (!hasStateWithInitialName) {
+ DebugTool.logError(TAG, "A SoftButtonObject must have a state with initialStateName.");
+ return;
+ }
this.name = name;
this.states = states;
this.currentStateName = initialStateName;
@@ -259,11 +270,35 @@ public class SoftButtonObject implements Cloneable{
}
/**
- * Set the the SoftButtonState list
+ * Set the SoftButtonState list
*
* @param states a list of the object's soft button states. <strong>states should be unique for every SoftButtonObject. A SoftButtonState instance cannot be reused for multiple SoftButtonObjects.</strong>
*/
public void setStates(@NonNull List<SoftButtonState> states) {
+
+ boolean repeatedStateNames = hasTwoStatesOfSameName(states);
+
+ if (repeatedStateNames) {
+ DebugTool.logError(TAG, "A SoftButtonObject must have states with different names.");
+ return;
+ }
+
+ if (states.isEmpty()) {
+ DebugTool.logError(TAG, "A SoftButtonObject must contain at least one state");
+ return;
+ }
+
+ boolean hasStateWithCurrentName = false;
+ for (SoftButtonState state : states) {
+ if(state.getName().equals(currentStateName)) {
+ hasStateWithCurrentName = true;
+ break;
+ }
+ }
+ if (!hasStateWithCurrentName) {
+ DebugTool.logError(TAG, "A SoftButtonObject setting states must contain a state with the name " + currentStateName + ".");
+ }
+
this.states = states;
}
diff --git a/base/src/main/java/com/smartdevicelink/managers/screen/SoftButtonReplaceOperation.java b/base/src/main/java/com/smartdevicelink/managers/screen/SoftButtonReplaceOperation.java
index c6578ff2e..b157c4cb9 100644
--- a/base/src/main/java/com/smartdevicelink/managers/screen/SoftButtonReplaceOperation.java
+++ b/base/src/main/java/com/smartdevicelink/managers/screen/SoftButtonReplaceOperation.java
@@ -116,7 +116,7 @@ class SoftButtonReplaceOperation extends Task {
List<SdlArtwork> initialStatesToBeUploaded = new ArrayList<>();
for (SoftButtonObject softButtonObject : softButtonObjects) {
SoftButtonState softButtonState = softButtonObject.getCurrentState();
- if (softButtonState != null && fileManager.get()!= null && fileManager.get().fileNeedsUpload(softButtonState.getArtwork()) && supportsSoftButtonImages()) {
+ if (softButtonState != null && fileManager.get() != null && fileManager.get().fileNeedsUpload(softButtonState.getArtwork()) && supportsSoftButtonImages()) {
initialStatesToBeUploaded.add(softButtonState.getArtwork());
}
}
diff --git a/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/ChoiceCell.java b/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/ChoiceCell.java
index 46d478000..9a4f1bedb 100644
--- a/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/ChoiceCell.java
+++ b/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/ChoiceCell.java
@@ -40,7 +40,7 @@ import com.smartdevicelink.util.DebugTool;
import java.util.ArrayList;
import java.util.List;
-public class ChoiceCell implements Cloneable{
+public class ChoiceCell implements Cloneable {
private String text, secondaryText, tertiaryText;
private List<String> voiceCommands;
private SdlArtwork artwork, secondaryArtwork;
diff --git a/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/PreloadPresentChoicesOperation.java b/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/PreloadPresentChoicesOperation.java
index 91a32ea0b..2eb04342e 100644
--- a/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/PreloadPresentChoicesOperation.java
+++ b/base/src/main/java/com/smartdevicelink/managers/screen/choiceset/PreloadPresentChoicesOperation.java
@@ -110,6 +110,7 @@ class PreloadPresentChoicesOperation extends Task {
Integer selectedCellRow;
KeyboardListener keyboardListener;
final SdlMsgVersion sdlMsgVersion;
+
private enum SDLPreloadPresentChoicesOperationState {
NOT_STARTED,
UPLOADING_IMAGES,
@@ -120,10 +121,11 @@ class PreloadPresentChoicesOperation extends Task {
RESETTING_KEYBOARD_PROPERTIES,
FINISHING
}
+
private SDLPreloadPresentChoicesOperationState currentState;
PreloadPresentChoicesOperation(ISdl internalInterface, FileManager fileManager, String displayName, WindowCapability defaultWindowCapability,
- Boolean isVROptional, LinkedHashSet<ChoiceCell> cellsToPreload, HashSet<ChoiceCell> loadedCells, BaseChoiceSetManager.ChoicesOperationCompletionListener listener) {
+ Boolean isVROptional, LinkedHashSet<ChoiceCell> cellsToPreload, HashSet<ChoiceCell> loadedCells, BaseChoiceSetManager.ChoicesOperationCompletionListener listener) {
super("PreloadPresentChoiceOperation");
this.internalInterface = new WeakReference<>(internalInterface);
this.fileManager = new WeakReference<>(fileManager);
@@ -207,14 +209,14 @@ class PreloadPresentChoicesOperation extends Task {
@Override
public void onComplete(boolean success) {
// If some artworks failed to upload, we are still going to try to load the cells
- if (getState()==CANCELED || !success) {
+ if (getState() == CANCELED || !success) {
finishOperation(false);
return;
}
preloadCells(new CompletionListener() {
@Override
public void onComplete(boolean success) {
- if (getState()==CANCELED || !success) {
+ if (getState() == CANCELED || !success) {
finishOperation(false);
return;
}
@@ -227,7 +229,7 @@ class PreloadPresentChoicesOperation extends Task {
updateKeyboardProperties(new CompletionListener() {
@Override
public void onComplete(boolean success) {
- if (getState()==CANCELED || !success) {
+ if (getState() == CANCELED || !success) {
finishOperation(false);
return;
}
@@ -383,7 +385,7 @@ class PreloadPresentChoicesOperation extends Task {
void resetKeyboardProperties(final CompletionListener listener) {
this.currentState = SDLPreloadPresentChoicesOperationState.RESETTING_KEYBOARD_PROPERTIES;
if (this.keyboardListener == null || this.originalKeyboardProperties == null) {
- if(listener != null) {
+ if (listener != null) {
listener.onComplete(true);
finishOperation(true);
return;
@@ -482,7 +484,7 @@ class PreloadPresentChoicesOperation extends Task {
DebugTool.logInfo(TAG, "Canceling the operation before a present.");
this.cancelTask();
return;
- }else if (sdlMsgVersion.getMajorVersion() < 6) {
+ } else if (sdlMsgVersion.getMajorVersion() < 6) {
DebugTool.logWarning(TAG, "Canceling a presented choice set is not supported on this head unit");
this.cancelTask();
return;
@@ -591,7 +593,7 @@ class PreloadPresentChoicesOperation extends Task {
int lastUsedId = usedIds.get(usedIds.size() - 1);
if (lastUsedId < MAX_CHOICE_ID) {
choiceId = lastUsedId + 1;
- return choiceId;
+ return choiceId;
}
// All our easy options are gone. Find and grab an empty slot from within the sorted list
@@ -646,7 +648,7 @@ class PreloadPresentChoicesOperation extends Task {
}
private void transferUniqueNamesFromCells(ArrayList<ChoiceCell> fromCells, ArrayList<ChoiceCell> toCells) {
- for (int i = 0; i< fromCells.size(); i++) {
+ for (int i = 0; i < fromCells.size(); i++) {
toCells.get(i).setUniqueTextId(fromCells.get(i).getUniqueTextId());
}
}
@@ -711,7 +713,7 @@ class PreloadPresentChoicesOperation extends Task {
ArrayList<Integer> uniqueIds = dictCounter.get(cellKey);
Integer lowestMissingUniqueId = uniqueIds.get(uniqueIds.size() - 1) + 1;
for (int i = 1; i < dictCounter.get(cellKey).size() + 1; i++) {
- if (i != dictCounter.get(cellKey).get(i -1)) {
+ if (i != dictCounter.get(cellKey).get(i - 1)) {
lowestMissingUniqueId = i;
break;
}
diff --git a/base/src/main/java/com/smartdevicelink/managers/screen/menu/BaseVoiceCommandManager.java b/base/src/main/java/com/smartdevicelink/managers/screen/menu/BaseVoiceCommandManager.java
index 9c5c39c21..ec07e5305 100644
--- a/base/src/main/java/com/smartdevicelink/managers/screen/menu/BaseVoiceCommandManager.java
+++ b/base/src/main/java/com/smartdevicelink/managers/screen/menu/BaseVoiceCommandManager.java
@@ -76,7 +76,7 @@ abstract class BaseVoiceCommandManager extends BaseSubManager {
this.transactionQueue = newTransactionQueue();
- currentHMILevel = null;
+ currentHMILevel = null;
addListeners();
lastVoiceCommandId = voiceCommandIdMin;
}
@@ -217,21 +217,27 @@ abstract class BaseVoiceCommandManager extends BaseSubManager {
List<VoiceCommand> validatedVoiceCommands = new ArrayList<>();
for (VoiceCommand voiceCommand : voiceCommands) {
if (voiceCommand == null) {
+ DebugTool.logWarning(TAG, "Voice command is null, it will not be uploaded");
continue;
}
List<String> voiceCommandStrings = new ArrayList<>();
for (String voiceCommandString : voiceCommand.getVoiceCommands()) {
if (voiceCommandString == null) {
+ DebugTool.logWarning(TAG, "Removing null string from voice command");
continue;
}
String trimmedString = voiceCommandString.trim();
if (trimmedString.length() > 0) {
voiceCommandStrings.add(trimmedString);
+ } else {
+ DebugTool.logWarning(TAG, "Empty string removed from voice command");
}
}
if (voiceCommandStrings.size() > 0) {
voiceCommand.setVoiceCommands(voiceCommandStrings);
validatedVoiceCommands.add(voiceCommand);
+ } else {
+ DebugTool.logWarning(TAG, "Voice command will not be uploaded as it contained no valid strings");
}
}
return validatedVoiceCommands;
diff --git a/base/src/main/java/com/smartdevicelink/managers/screen/menu/DynamicMenuUpdateAlgorithm.java b/base/src/main/java/com/smartdevicelink/managers/screen/menu/DynamicMenuUpdateAlgorithm.java
index b6fa0266c..aea0d10d6 100644
--- a/base/src/main/java/com/smartdevicelink/managers/screen/menu/DynamicMenuUpdateAlgorithm.java
+++ b/base/src/main/java/com/smartdevicelink/managers/screen/menu/DynamicMenuUpdateAlgorithm.java
@@ -112,7 +112,7 @@ class DynamicMenuUpdateAlgorithm {
* Builds a 1-1 list of Deletes for every element in the array
* @param oldMenu The old menu list
*/
- static List<MenuCellState> buildAllDeleteStatusesForMenu (List<MenuCell> oldMenu){
+ static List<MenuCellState> buildAllDeleteStatusesForMenu(List<MenuCell> oldMenu) {
List<MenuCellState> oldMenuStatus = new ArrayList<>(oldMenu.size());
for (int index = 0; index < oldMenu.size(); index++) {
oldMenuStatus.add(MenuCellState.DELETE);
@@ -124,7 +124,7 @@ class DynamicMenuUpdateAlgorithm {
* Builds a 1-1 list of Adds for every element in the list
* @param newMenu The new menu list
*/
- static List<MenuCellState> buildAllAddStatusesForMenu (List<MenuCell> newMenu){
+ static List<MenuCellState> buildAllAddStatusesForMenu(List<MenuCell> newMenu) {
List<MenuCellState> newMenuStatus = new ArrayList<>(newMenu.size());
for (int index = 0; index < newMenu.size(); index++) {
newMenuStatus.add(MenuCellState.ADD);
diff --git a/base/src/main/java/com/smartdevicelink/managers/screen/menu/MenuCell.java b/base/src/main/java/com/smartdevicelink/managers/screen/menu/MenuCell.java
index eaf91ae76..5b8e98ef8 100644
--- a/base/src/main/java/com/smartdevicelink/managers/screen/menu/MenuCell.java
+++ b/base/src/main/java/com/smartdevicelink/managers/screen/menu/MenuCell.java
@@ -388,7 +388,7 @@ public class MenuCell implements Cloneable {
*
* @return the cell's tertiaryText
*/
- public String getTertiaryText(){
+ public String getTertiaryText() {
return tertiaryText;
}
@@ -406,7 +406,7 @@ public class MenuCell implements Cloneable {
*
* @return the cell's secondaryArtwork
*/
- public SdlArtwork getSecondaryArtwork(){
+ public SdlArtwork getSecondaryArtwork() {
return secondaryArtwork;
}
diff --git a/base/src/main/java/com/smartdevicelink/managers/screen/menu/MenuReplaceOperation.java b/base/src/main/java/com/smartdevicelink/managers/screen/menu/MenuReplaceOperation.java
index 7db1a85b9..994c14ad8 100644
--- a/base/src/main/java/com/smartdevicelink/managers/screen/menu/MenuReplaceOperation.java
+++ b/base/src/main/java/com/smartdevicelink/managers/screen/menu/MenuReplaceOperation.java
@@ -48,6 +48,8 @@ import static com.smartdevicelink.managers.screen.menu.MenuReplaceUtilities.send
import static com.smartdevicelink.managers.screen.menu.MenuReplaceUtilities.subMenuCommandsForCells;
import static com.smartdevicelink.managers.screen.menu.MenuReplaceUtilities.transferCellIDsFromCells;
import static com.smartdevicelink.managers.screen.menu.MenuReplaceUtilities.transferCellListenersFromCells;
+import static com.smartdevicelink.managers.screen.menu.MenuReplaceUtilities.windowCapabilitySupportsPrimaryImage;
+import static com.smartdevicelink.managers.screen.menu.MenuReplaceUtilities.windowCapabilitySupportsSecondaryImage;
import com.livio.taskmaster.Task;
import com.smartdevicelink.managers.CompletionListener;
@@ -198,7 +200,7 @@ class MenuReplaceOperation extends Task {
}
private void uploadMenuArtworks(final CompletionListener listener) {
- List<SdlArtwork> artworksToBeUploaded = new ArrayList<>(findAllArtworksToBeUploadedFromCells(updatedMenu, fileManager.get(), windowCapability));
+ List<SdlArtwork> artworksToBeUploaded = new ArrayList<>(findAllArtworksToBeUploadedFromCells(internalInterface.get(), updatedMenu, fileManager.get(), windowCapability));
if (artworksToBeUploaded.isEmpty()) {
listener.onComplete(true);
return;
@@ -373,10 +375,10 @@ class MenuReplaceOperation extends Task {
MenuLayout defaultSubmenuLayout = menuConfiguration != null ? menuConfiguration.getSubMenuLayout() : null;
// RPCs for cells on the main menu level. They could be AddCommands or AddSubMenus depending on whether the cell has child cells or not.
- final List<RPCRequest> mainMenuCommands = mainMenuCommandsForCells(addMenuCells, fileManager.get(), fullMenu, windowCapability, defaultSubmenuLayout);
+ final List<RPCRequest> mainMenuCommands = mainMenuCommandsForCells(internalInterface.get(), addMenuCells, fileManager.get(), fullMenu, windowCapability, defaultSubmenuLayout);
// RPCs for cells on the second menu level (one level deep). They could be AddCommands or AddSubMenus.
- final List<RPCRequest> subMenuCommands = subMenuCommandsForCells(addMenuCells, fileManager.get(), windowCapability, defaultSubmenuLayout);
+ final List<RPCRequest> subMenuCommands = subMenuCommandsForCells(internalInterface.get(), addMenuCells, fileManager.get(), windowCapability, defaultSubmenuLayout);
sendRPCs(mainMenuCommands, internalInterface.get(), new SendingRPCsCompletionListener() {
@Override
@@ -465,12 +467,14 @@ class MenuReplaceOperation extends Task {
// Strip away fields that cannot be used to determine uniqueness visually including fields not supported by the HMI
cell.setVoiceCommands(null);
- // Don't check ImageFieldName.subMenuIcon because it was added in 7.0 when the feature was added in 5.0.
- // Just assume that if cmdIcon is not available, the submenu icon is not either.
- if (!hasImageFieldOfName(windowCapability, ImageFieldName.cmdIcon)) {
+ if (!windowCapabilitySupportsPrimaryImage(internalInterface.get(), windowCapability, cell)) {
cell.setIcon(null);
}
+ if (!windowCapabilitySupportsSecondaryImage(windowCapability, cell)) {
+ cell.setSecondaryArtwork(null);
+ }
+
// Check for subMenu fields supported
if (cell.isSubMenuCell()) {
if (!hasTextFieldOfName(windowCapability, TextFieldName.menuSubMenuSecondaryText)) {
@@ -479,9 +483,6 @@ class MenuReplaceOperation extends Task {
if (!hasTextFieldOfName(windowCapability, TextFieldName.menuSubMenuTertiaryText)) {
cell.setTertiaryText(null);
}
- if (!hasImageFieldOfName(windowCapability, ImageFieldName.menuSubMenuSecondaryImage)) {
- cell.setSecondaryArtwork(null);
- }
cell.setSubCells(cellsWithRemovedPropertiesFromCells(cell.getSubCells(), windowCapability));
} else {
if (!hasTextFieldOfName(windowCapability, TextFieldName.menuCommandSecondaryText)) {
@@ -490,9 +491,6 @@ class MenuReplaceOperation extends Task {
if (!hasTextFieldOfName(windowCapability, TextFieldName.menuCommandTertiaryText)) {
cell.setTertiaryText(null);
}
- if (!hasImageFieldOfName(windowCapability, ImageFieldName.menuCommandSecondaryImage)) {
- cell.setSecondaryArtwork(null);
- }
}
}
return removePropertiesClone;
diff --git a/base/src/main/java/com/smartdevicelink/managers/screen/menu/MenuReplaceUtilities.java b/base/src/main/java/com/smartdevicelink/managers/screen/menu/MenuReplaceUtilities.java
index 210b24ba9..2e9711dda 100644
--- a/base/src/main/java/com/smartdevicelink/managers/screen/menu/MenuReplaceUtilities.java
+++ b/base/src/main/java/com/smartdevicelink/managers/screen/menu/MenuReplaceUtilities.java
@@ -53,6 +53,7 @@ import com.smartdevicelink.proxy.rpc.enums.MenuLayout;
import com.smartdevicelink.proxy.rpc.enums.TextFieldName;
import com.smartdevicelink.proxy.rpc.listeners.OnMultipleRequestListener;
import com.smartdevicelink.util.DebugTool;
+import com.smartdevicelink.util.Version;
import java.util.ArrayList;
import java.util.HashMap;
@@ -119,7 +120,7 @@ class MenuReplaceUtilities {
}
}
- static Set<SdlArtwork> findAllArtworksToBeUploadedFromCells(List<MenuCell> cells, FileManager fileManager, WindowCapability windowCapability) {
+ static Set<SdlArtwork> findAllArtworksToBeUploadedFromCells(ISdl internalInterface, List<MenuCell> cells, FileManager fileManager, WindowCapability windowCapability) {
// Make sure we can use images in the menus
if (!hasImageFieldOfName(windowCapability, ImageFieldName.cmdIcon)) {
return new HashSet<>();
@@ -128,30 +129,59 @@ class MenuReplaceUtilities {
Set<SdlArtwork> artworks = new HashSet<>();
for (MenuCell cell : cells) {
if (fileManager != null) {
- if (fileManager.fileNeedsUpload(cell.getIcon())) {
+ if (windowCapabilitySupportsPrimaryImage(internalInterface, windowCapability, cell) && fileManager.fileNeedsUpload(cell.getIcon())) {
artworks.add(cell.getIcon());
}
- if (hasImageFieldOfName(windowCapability, ImageFieldName.menuCommandSecondaryImage) && fileManager.fileNeedsUpload(cell.getSecondaryArtwork())) {
+ if (windowCapabilitySupportsSecondaryImage(windowCapability, cell) && fileManager.fileNeedsUpload(cell.getSecondaryArtwork())) {
artworks.add(cell.getSecondaryArtwork());
}
}
if (cell.isSubMenuCell() && !cell.getSubCells().isEmpty()) {
- artworks.addAll(findAllArtworksToBeUploadedFromCells(cell.getSubCells(), fileManager, windowCapability));
+ artworks.addAll(findAllArtworksToBeUploadedFromCells(internalInterface, cell.getSubCells(), fileManager, windowCapability));
}
}
return artworks;
}
- // If there is an icon and the icon has been uploaded, or if the icon is a static icon, it should include the image
- static boolean shouldCellIncludePrimaryImageFromCell(MenuCell cell, FileManager fileManager, WindowCapability windowCapability) {
- boolean supportsImage = cell.isSubMenuCell() ? hasImageFieldOfName(windowCapability, ImageFieldName.subMenuIcon) : hasImageFieldOfName(windowCapability, ImageFieldName.cmdIcon);
+ static boolean windowCapabilitySupportsPrimaryImage(ISdl internalInterface, WindowCapability windowCapability, MenuCell cell) {
+ boolean supportsImage;
+ if (cell.isSubMenuCell()) {
+ if (isRPCVersionBetween5And7(internalInterface) && hasImageFieldOfName(windowCapability, ImageFieldName.cmdIcon)) {
+ supportsImage = true;
+ } else {
+ supportsImage = hasImageFieldOfName(windowCapability, ImageFieldName.subMenuIcon);
+ }
+ } else {
+ supportsImage = hasImageFieldOfName(windowCapability, ImageFieldName.cmdIcon);
+ }
+ return supportsImage;
+ }
+
+ static boolean isRPCVersionBetween5And7(ISdl internalInterface) {
+ if (internalInterface != null && internalInterface.getSdlMsgVersion() != null) {
+ Version headUnitRPCVersion = new Version(internalInterface.getSdlMsgVersion());
+ Version minRPCVersion = new Version(5, 0, 0);
+ Version maxRPCVersion = new Version(7, 0, 0);
+ // If RPC version is >= 5.0 && < 7.0
+ return (headUnitRPCVersion.isNewerThan(minRPCVersion) == 0 || headUnitRPCVersion.isBetween(minRPCVersion, maxRPCVersion) == 1);
+ }
+ return false;
+ }
+
+ static boolean windowCapabilitySupportsSecondaryImage(WindowCapability windowCapability, MenuCell cell) {
+ return cell.isSubMenuCell() ? hasImageFieldOfName(windowCapability, ImageFieldName.menuSubMenuSecondaryImage) : hasImageFieldOfName(windowCapability, ImageFieldName.menuCommandSecondaryImage);
+ }
+
+ // If there is an icon and the icon has been uploaded, or if the icon is a static icon, it should include the image
+ static boolean shouldCellIncludePrimaryImageFromCell(ISdl internalInterface, MenuCell cell, FileManager fileManager, WindowCapability windowCapability) {
+ boolean supportsImage = windowCapabilitySupportsPrimaryImage(internalInterface, windowCapability, cell);
return cell.getIcon() != null && supportsImage && (fileManager.hasUploadedFile(cell.getIcon()) || cell.getIcon().isStaticIcon());
}
// If there is an icon and the icon has been uploaded, or if the icon is a static icon, it should include the image
static boolean shouldCellIncludeSecondaryImageFromCell(MenuCell cell, FileManager fileManager, WindowCapability windowCapability) {
- boolean supportsImage = cell.isSubMenuCell() ? hasImageFieldOfName(windowCapability, ImageFieldName.menuSubMenuSecondaryImage) : hasImageFieldOfName(windowCapability, ImageFieldName.menuCommandSecondaryImage);
+ boolean supportsImage = windowCapabilitySupportsSecondaryImage(windowCapability, cell);
return cell.getSecondaryArtwork() != null && supportsImage && (fileManager.hasUploadedFile(cell.getSecondaryArtwork()) || cell.getSecondaryArtwork().isStaticIcon());
}
@@ -193,7 +223,7 @@ class MenuReplaceUtilities {
return deletes;
}
- static List<RPCRequest> mainMenuCommandsForCells(List<MenuCell> cells, FileManager fileManager, List<MenuCell> menu, WindowCapability windowCapability, MenuLayout defaultSubmenuLayout) {
+ static List<RPCRequest> mainMenuCommandsForCells(ISdl internalInterface, List<MenuCell> cells, FileManager fileManager, List<MenuCell> menu, WindowCapability windowCapability, MenuLayout defaultSubmenuLayout) {
List<RPCRequest> commands = new ArrayList<>();
// We need the index to use it as position so we will use this type of loop
@@ -203,9 +233,9 @@ class MenuReplaceUtilities {
MenuCell addCell = cells.get(updateCellsIndex);
if (mainCell.equals(addCell)) {
if (addCell.isSubMenuCell()) {
- commands.add(subMenuCommandForMenuCell(addCell, fileManager, windowCapability, menuInteger, defaultSubmenuLayout));
+ commands.add(subMenuCommandForMenuCell(internalInterface, addCell, fileManager, windowCapability, menuInteger, defaultSubmenuLayout));
} else {
- commands.add(commandForMenuCell(addCell, fileManager, windowCapability, menuInteger));
+ commands.add(commandForMenuCell(internalInterface, addCell, fileManager, windowCapability, menuInteger));
}
break;
}
@@ -214,36 +244,36 @@ class MenuReplaceUtilities {
return commands;
}
- static List<RPCRequest> subMenuCommandsForCells(List<MenuCell> cells, FileManager fileManager, WindowCapability windowCapability, MenuLayout defaultSubmenuLayout) {
+ static List<RPCRequest> subMenuCommandsForCells(ISdl internalInterface, List<MenuCell> cells, FileManager fileManager, WindowCapability windowCapability, MenuLayout defaultSubmenuLayout) {
List<RPCRequest> commands = new ArrayList<>();
for (MenuCell cell : cells) {
if (cell.isSubMenuCell() && !cell.getSubCells().isEmpty()) {
- commands.addAll(allCommandsForCells(cell.getSubCells(), fileManager, windowCapability, defaultSubmenuLayout));
+ commands.addAll(allCommandsForCells(internalInterface, cell.getSubCells(), fileManager, windowCapability, defaultSubmenuLayout));
}
}
return commands;
}
- static List<RPCRequest> allCommandsForCells(List<MenuCell> cells, FileManager fileManager, WindowCapability windowCapability, MenuLayout defaultSubmenuLayout) {
+ static List<RPCRequest> allCommandsForCells(ISdl internalInterface, List<MenuCell> cells, FileManager fileManager, WindowCapability windowCapability, MenuLayout defaultSubmenuLayout) {
List<RPCRequest> commands = new ArrayList<>();
for (int cellIndex = 0; cellIndex < cells.size(); cellIndex++) {
MenuCell cell = cells.get(cellIndex);
if (cell.isSubMenuCell()) {
- commands.add(subMenuCommandForMenuCell(cell, fileManager, windowCapability, cellIndex, defaultSubmenuLayout));
+ commands.add(subMenuCommandForMenuCell(internalInterface, cell, fileManager, windowCapability, cellIndex, defaultSubmenuLayout));
// Recursively grab the commands for all the sub cells
if (!cell.getSubCells().isEmpty()) {
- commands.addAll(allCommandsForCells(cell.getSubCells(), fileManager, windowCapability, defaultSubmenuLayout));
+ commands.addAll(allCommandsForCells(internalInterface, cell.getSubCells(), fileManager, windowCapability, defaultSubmenuLayout));
}
} else {
- commands.add(commandForMenuCell(cell, fileManager, windowCapability, cellIndex));
+ commands.add(commandForMenuCell(internalInterface, cell, fileManager, windowCapability, cellIndex));
}
}
return commands;
}
- static AddCommand commandForMenuCell(MenuCell cell, FileManager fileManager, WindowCapability windowCapability, int position) {
+ static AddCommand commandForMenuCell(ISdl internalInterface, MenuCell cell, FileManager fileManager, WindowCapability windowCapability, int position) {
AddCommand command = new AddCommand(cell.getCellId());
MenuParams params = new MenuParams(cell.getUniqueTitle());
@@ -258,7 +288,7 @@ class MenuReplaceUtilities {
} else {
command.setVrCommands(null);
}
- boolean shouldCellIncludePrimaryImage = cell.getIcon() != null && shouldCellIncludePrimaryImageFromCell(cell, fileManager, windowCapability);
+ boolean shouldCellIncludePrimaryImage = cell.getIcon() != null && shouldCellIncludePrimaryImageFromCell(internalInterface, cell, fileManager, windowCapability);
command.setCmdIcon(shouldCellIncludePrimaryImage ? cell.getIcon().getImageRPC() : null);
boolean shouldCellIncludeSecondaryImage = cell.getSecondaryArtwork() != null && shouldCellIncludeSecondaryImageFromCell(cell, fileManager, windowCapability);
@@ -267,8 +297,8 @@ class MenuReplaceUtilities {
return command;
}
- static AddSubMenu subMenuCommandForMenuCell(MenuCell cell, FileManager fileManager, WindowCapability windowCapability, int position, MenuLayout defaultSubmenuLayout) {
- boolean shouldCellIncludePrimaryImage = cell.getIcon() != null && cell.getIcon().getImageRPC() != null && shouldCellIncludePrimaryImageFromCell(cell, fileManager, windowCapability);
+ static AddSubMenu subMenuCommandForMenuCell(ISdl internalInterface, MenuCell cell, FileManager fileManager, WindowCapability windowCapability, int position, MenuLayout defaultSubmenuLayout) {
+ boolean shouldCellIncludePrimaryImage = cell.getIcon() != null && cell.getIcon().getImageRPC() != null && shouldCellIncludePrimaryImageFromCell(internalInterface, cell, fileManager, windowCapability);
Image icon = (shouldCellIncludePrimaryImage ? cell.getIcon().getImageRPC() : null);
boolean shouldCellIncludeSecondaryImage = cell.getSecondaryArtwork() != null && cell.getSecondaryArtwork().getImageRPC() != null && shouldCellIncludeSecondaryImageFromCell(cell, fileManager, windowCapability);
Image secondaryIcon = (shouldCellIncludeSecondaryImage ? cell.getSecondaryArtwork().getImageRPC() : null);
@@ -421,4 +451,4 @@ class MenuReplaceUtilities {
}
});
}
-} \ No newline at end of file
+}
diff --git a/base/src/main/java/com/smartdevicelink/managers/screen/menu/VoiceCommandUpdateOperation.java b/base/src/main/java/com/smartdevicelink/managers/screen/menu/VoiceCommandUpdateOperation.java
index 0650ab388..1144e1479 100644
--- a/base/src/main/java/com/smartdevicelink/managers/screen/menu/VoiceCommandUpdateOperation.java
+++ b/base/src/main/java/com/smartdevicelink/managers/screen/menu/VoiceCommandUpdateOperation.java
@@ -206,7 +206,7 @@ class VoiceCommandUpdateOperation extends Task {
private void sendCurrentVoiceCommands(final CompletionListener listener) {
- List<VoiceCommand> voiceCommandsToAdd = voiceCommandsInListNotInSecondList(pendingVoiceCommands, oldVoiceCommands);
+ List<VoiceCommand> voiceCommandsToAdd = voiceCommandsInListNotInSecondList(pendingVoiceCommands, oldVoiceCommands);
if (voiceCommandsToAdd.size() == 0) {
if (listener != null) {
diff --git a/base/src/main/java/com/smartdevicelink/protocol/SdlProtocolBase.java b/base/src/main/java/com/smartdevicelink/protocol/SdlProtocolBase.java
index f7dd797d0..a8c739750 100644
--- a/base/src/main/java/com/smartdevicelink/protocol/SdlProtocolBase.java
+++ b/base/src/main/java/com/smartdevicelink/protocol/SdlProtocolBase.java
@@ -1239,7 +1239,10 @@ public class SdlProtocolBase {
}
}
- if ((getTransportForSession(SessionType.RPC) != null && disconnectedTransport.equals(getTransportForSession(SessionType.RPC))) || disconnectedTransport.equals(connectedPrimaryTransport)) {
+ if ((getTransportForSession(SessionType.RPC) != null && disconnectedTransport.equals(getTransportForSession(SessionType.RPC)))
+ || disconnectedTransport.equals(connectedPrimaryTransport)
+ || connectedTransports == null
+ || connectedTransports.isEmpty()) {
//Primary transport has been disconnected. Let's check if we can recover.
//transportTypes.remove(type);
boolean primaryTransportAvailable = false;
diff --git a/base/src/main/java/com/smartdevicelink/protocol/SecurityQueryPayload.java b/base/src/main/java/com/smartdevicelink/protocol/SecurityQueryPayload.java
index c7bc1326d..b38c5304a 100644
--- a/base/src/main/java/com/smartdevicelink/protocol/SecurityQueryPayload.java
+++ b/base/src/main/java/com/smartdevicelink/protocol/SecurityQueryPayload.java
@@ -16,7 +16,7 @@ public class SecurityQueryPayload {
private SecurityQueryID _securityQueryID;
private int _correlationID;
private int _jsonSize;
- private SecurityQueryErrorCode _errorCode;
+ private int _bulkDataSize;
private byte[] _jsonData = null;
private byte[] _bulkData = null;
@@ -51,11 +51,6 @@ public class SecurityQueryPayload {
int _jsonSize = BitConverter.intFromByteArray(binHeader, 8);
msg.setJsonSize(_jsonSize);
- //If we get an error message we want the error code from the last 8 bits
- if (msg.getQueryType() == SecurityQueryType.NOTIFICATION && msg.getQueryID() == SecurityQueryID.SEND_INTERNAL_ERROR) {
- msg.setErrorCode(SecurityQueryErrorCode.valueOf(binHeader[binHeader.length - 1]));
- }
-
try {
//Get the JsonData after the header (after 96 bits) based on the jsonData size
if (_jsonSize > 0 && _jsonSize <= (binHeader.length - SECURITY_QUERY_HEADER_SIZE)) {
@@ -66,12 +61,7 @@ public class SecurityQueryPayload {
//Get the binaryData after the header (after 96 bits) and the jsonData size
if (binHeader.length - _jsonSize - SECURITY_QUERY_HEADER_SIZE > 0) {
- byte[] _bulkData;
- if (msg.getQueryType() == SecurityQueryType.NOTIFICATION && msg.getQueryID() == SecurityQueryID.SEND_INTERNAL_ERROR) {
- _bulkData = new byte[binHeader.length - _jsonSize - SECURITY_QUERY_HEADER_SIZE - 1];
- } else {
- _bulkData = new byte[binHeader.length - _jsonSize - SECURITY_QUERY_HEADER_SIZE];
- }
+ byte[] _bulkData = new byte[binHeader.length - _jsonSize - SECURITY_QUERY_HEADER_SIZE];
System.arraycopy(binHeader, SECURITY_QUERY_HEADER_SIZE + _jsonSize, _bulkData, 0, _bulkData.length);
msg.setBulkData(_bulkData);
}
@@ -84,18 +74,28 @@ public class SecurityQueryPayload {
return msg;
}
- public byte[] assembleHeaderBytes() {
+ public byte[] assembleBinaryData() {
// From the properties, create a data buffer
// Query Type - first 8 bits
// Query ID - next 24 bits
// Sequence Number - next 32 bits
// JSON size - next 32 bits
- byte[] ret = new byte[SECURITY_QUERY_HEADER_SIZE];
- ret[0] = _securityQueryType.getValue();
- System.arraycopy(_securityQueryID.getValue(), 0, ret, 1, 3);
- System.arraycopy(BitConverter.intToByteArray(_correlationID), 0, ret, 4, 4);
- System.arraycopy(BitConverter.intToByteArray(_jsonSize), 0, ret, 8, 4);
- return ret;
+ byte[] header = new byte[SECURITY_QUERY_HEADER_SIZE];
+ header[0] = _securityQueryType.getValue();
+ System.arraycopy(_securityQueryID.getValue(), 0, header, 1, 3);
+ System.arraycopy(BitConverter.intToByteArray(_correlationID), 0, header, 4, 4);
+ System.arraycopy(BitConverter.intToByteArray(_jsonSize), 0, header, 8, 4);
+
+ int size = _jsonSize + _bulkDataSize + SECURITY_QUERY_HEADER_SIZE;
+ byte[] dataOut = new byte[size];
+ System.arraycopy(header, 0, dataOut, 0, SECURITY_QUERY_HEADER_SIZE);
+ if (_jsonData != null) {
+ System.arraycopy(_jsonData, 0, dataOut, SECURITY_QUERY_HEADER_SIZE, _jsonSize);
+ }
+ if (_bulkData != null) {
+ System.arraycopy(_bulkData, 0, dataOut, SECURITY_QUERY_HEADER_SIZE + _jsonSize, _bulkDataSize);
+ }
+ return dataOut;
}
public SecurityQueryType getQueryType() {
@@ -126,16 +126,16 @@ public class SecurityQueryPayload {
return _jsonSize;
}
- public void setJsonSize(int _jsonSize) {
+ private void setJsonSize(int _jsonSize) {
this._jsonSize = _jsonSize;
}
- public SecurityQueryErrorCode getErrorCode() {
- return _errorCode;
+ public int getBulkDataSize() {
+ return _bulkDataSize;
}
- public void setErrorCode(SecurityQueryErrorCode _errorCode) {
- this._errorCode = _errorCode;
+ private void setBulkDataSize(int _bulkDataSize) {
+ this._bulkDataSize = _bulkDataSize;
}
public byte[] getJsonData() {
@@ -143,6 +143,12 @@ public class SecurityQueryPayload {
}
public void setJsonData(byte[] _jsonData) {
+ if (_jsonData == null) {
+ this._jsonSize = 0;
+ this._jsonData = null;
+ return;
+ }
+ this._jsonSize = _jsonData.length;
this._jsonData = new byte[this._jsonSize];
System.arraycopy(_jsonData, 0, this._jsonData, 0, _jsonSize);
}
@@ -152,6 +158,13 @@ public class SecurityQueryPayload {
}
public void setBulkData(byte[] _bulkData) {
- this._bulkData = _bulkData;
+ if (_bulkData == null) {
+ this._bulkDataSize = 0;
+ this._bulkData = null;
+ return;
+ }
+ this._bulkDataSize = _bulkData.length;
+ this._bulkData = new byte[this._bulkDataSize];
+ System.arraycopy(_bulkData, 0, this._bulkData, 0, _bulkDataSize);
}
}
diff --git a/base/src/main/java/com/smartdevicelink/proxy/RPCStruct.java b/base/src/main/java/com/smartdevicelink/proxy/RPCStruct.java
index 1db39f2e9..8072a4b23 100644
--- a/base/src/main/java/com/smartdevicelink/proxy/RPCStruct.java
+++ b/base/src/main/java/com/smartdevicelink/proxy/RPCStruct.java
@@ -117,7 +117,7 @@ public class RPCStruct implements Cloneable {
}
/**
- * This method should clean the the RPC to make sure it is compliant with the spec.
+ * This method should clean the RPC to make sure it is compliant with the spec.
* <br><br><b> NOTE:</b> Super needs to be called at the END of the method
*
* @param rpcVersion the rpc spec version that has been negotiated. If value is null the
@@ -270,7 +270,7 @@ public class RPCStruct implements Cloneable {
return customObject;
} catch (Exception e) {
- DebugTool.logError(TAG,"Error attempting to format an object from a Hashtable", e);
+ DebugTool.logError(TAG, "Error attempting to format an object from a Hashtable", e);
}
} else if (obj instanceof List<?>) {
List<?> list = (List<?>) obj;
@@ -302,7 +302,7 @@ public class RPCStruct implements Cloneable {
}
newList.add(customObject);
} catch (Exception e) {
- DebugTool.logError(TAG,"Error attempting to format object from list of Hashtables", e);
+ DebugTool.logError(TAG, "Error attempting to format object from list of Hashtables", e);
return null;
}
}
@@ -336,15 +336,15 @@ public class RPCStruct implements Cloneable {
try {
valueForString = tClass.getDeclaredMethod("valueForString", String.class);
} catch (NoSuchMethodException e) {
- DebugTool.logError(TAG,"Error attempting to find valueForString method in class", e);
+ DebugTool.logError(TAG, "Error attempting to find valueForString method in class", e);
}
if (valueForString != null) {
try {
return valueForString.invoke(null, (String) s);
} catch (IllegalAccessException e) {
- DebugTool.logError(TAG,"Illegal access while using reflection to get enum from string", e);
+ DebugTool.logError(TAG, "Illegal access while using reflection to get enum from string", e);
} catch (InvocationTargetException e) {
- DebugTool.logError(TAG,"Error attempting to use method from reflection to get enum from string", e);
+ DebugTool.logError(TAG, "Error attempting to use method from reflection to get enum from string", e);
}
}
return null;
diff --git a/base/src/main/java/com/smartdevicelink/proxy/rpc/AddCommand.java b/base/src/main/java/com/smartdevicelink/proxy/rpc/AddCommand.java
index 3458e361a..311279eb8 100644
--- a/base/src/main/java/com/smartdevicelink/proxy/rpc/AddCommand.java
+++ b/base/src/main/java/com/smartdevicelink/proxy/rpc/AddCommand.java
@@ -176,7 +176,7 @@ public class AddCommand extends RPCRequest {
}
/**
- * <p>Sets an Unique Command ID that identifies the command. Is returned in an
+ * <p>Sets a Unique Command ID that identifies the command. Is returned in an
* <i>{@linkplain OnCommand}</i> notification to identify the command
* selected by the user</p>
*
diff --git a/base/src/main/java/com/smartdevicelink/proxy/rpc/GetVehicleDataResponse.java b/base/src/main/java/com/smartdevicelink/proxy/rpc/GetVehicleDataResponse.java
index 33ebf324f..c7b429075 100644
--- a/base/src/main/java/com/smartdevicelink/proxy/rpc/GetVehicleDataResponse.java
+++ b/base/src/main/java/com/smartdevicelink/proxy/rpc/GetVehicleDataResponse.java
@@ -110,6 +110,7 @@ public class GetVehicleDataResponse extends RPCResponse {
* @since SmartDeviceLink 7.1.0
*/
public static final String KEY_SEAT_OCCUPANCY = "seatOccupancy";
+
/**
* Constructs a new GetVehicleDataResponse object
*/
@@ -648,6 +649,7 @@ public class GetVehicleDataResponse extends RPCResponse {
public ClimateData getClimateData() {
return (ClimateData) getObject(ClimateData.class, KEY_CLIMATE_DATA);
}
+
/**
* Sets the seatOccupancy.
*
diff --git a/base/src/main/java/com/smartdevicelink/proxy/rpc/ScrollableMessage.java b/base/src/main/java/com/smartdevicelink/proxy/rpc/ScrollableMessage.java
index 019b3d55f..e5e96d7ef 100644
--- a/base/src/main/java/com/smartdevicelink/proxy/rpc/ScrollableMessage.java
+++ b/base/src/main/java/com/smartdevicelink/proxy/rpc/ScrollableMessage.java
@@ -70,7 +70,7 @@ import java.util.List;
* <tr>
* <td>timeout</td>
* <td>Integer</td>
- * <td>App defined timeout. Indicates how long of a timeout from the last action (i.e. scrolling message resets timeout).</td>
+ * <td>App defined timeout. Indicates how long of a timeout in milliseconds from the last action (i.e. scrolling message resets timeout).</td>
* <td>N</td>
* <td>minValue=1000; maxValue=65535; defValue=30000</td>
* <td>SmartDevice Link 1.0 </td>
@@ -166,10 +166,10 @@ public class ScrollableMessage extends RPCRequest {
}
/**
- * Sets an App defined timeout. Indicates how long of a timeout from the
+ * Sets an App defined timeout. Indicates how long of a timeout in milliseconds from the
* last action
*
- * @param timeout an Integer value representing an App defined timeout
+ * @param timeout an Integer value representing an App defined timeout in milliseconds
* <p></p>
* <b>Notes</b>:Minval=0; Maxval=65535;Default=30000
*/
@@ -179,9 +179,9 @@ public class ScrollableMessage extends RPCRequest {
}
/**
- * Gets an App defined timeout
+ * Gets an App defined timeout in milliseconds
*
- * @return Integer -an Integer value representing an App defined timeout
+ * @return Integer -an Integer value representing an App defined timeout in milliseconds
*/
public Integer getTimeout() {
return getInteger(KEY_TIMEOUT);
diff --git a/base/src/main/java/com/smartdevicelink/proxy/rpc/Slider.java b/base/src/main/java/com/smartdevicelink/proxy/rpc/Slider.java
index fae2a8165..152df6f4d 100644
--- a/base/src/main/java/com/smartdevicelink/proxy/rpc/Slider.java
+++ b/base/src/main/java/com/smartdevicelink/proxy/rpc/Slider.java
@@ -95,7 +95,7 @@ import java.util.List;
* <tr>
* <td>timeout</td>
* <td>String</td>
- * <td>App defined timeout. Indicates how long of a timeout from the last action (i.e. sliding control resets timeout). If omitted, the value is set to 10000.</td>
+ * <td>App defined timeout. Indicates how long of a timeout in milliseconds from the last action (i.e. sliding control resets timeout). If omitted, the value is set to 10000.</td>
* <td>N</td>
* <td>Minvalue=0; Maxvalue=65535; Defvalue= 10000</td>
* <td>SmartDeviceLink 2.0</td>
@@ -255,9 +255,9 @@ public class Slider extends RPCRequest {
}
/**
- * Sets an App defined timeout
+ * Sets an App defined timeout in milliseconds
*
- * @param timeout an Integer value representing an App defined timeout
+ * @param timeout an Integer value representing an App defined timeout in milliseconds
* <p></p>
* <b>Notes: </b>Minvalue=0; Maxvalue=65535; Defvalue=10000
*/
@@ -267,9 +267,9 @@ public class Slider extends RPCRequest {
}
/**
- * Gets an App defined timeout
+ * Gets an App defined timeout in milliseconds
*
- * @return Integer -an Integer value representing an App defined timeout
+ * @return Integer -an Integer value representing an App defined timeout in milliseconds
*/
public Integer getTimeout() {
return getInteger(KEY_TIMEOUT);
diff --git a/base/src/main/java/com/smartdevicelink/proxy/rpc/SubscribeVehicleDataResponse.java b/base/src/main/java/com/smartdevicelink/proxy/rpc/SubscribeVehicleDataResponse.java
index 7a268f0f3..05753b8ab 100644
--- a/base/src/main/java/com/smartdevicelink/proxy/rpc/SubscribeVehicleDataResponse.java
+++ b/base/src/main/java/com/smartdevicelink/proxy/rpc/SubscribeVehicleDataResponse.java
@@ -102,6 +102,7 @@ public class SubscribeVehicleDataResponse extends RPCResponse {
* @since SmartDeviceLink 7.1.0
*/
public static final String KEY_SEAT_OCCUPANCY = "seatOccupancy";
+
/**
* Constructs a new SubscribeVehicleDataResponse object
*/
diff --git a/base/src/main/java/com/smartdevicelink/proxy/rpc/TireStatus.java b/base/src/main/java/com/smartdevicelink/proxy/rpc/TireStatus.java
index 68c47cf50..bd7850480 100644
--- a/base/src/main/java/com/smartdevicelink/proxy/rpc/TireStatus.java
+++ b/base/src/main/java/com/smartdevicelink/proxy/rpc/TireStatus.java
@@ -159,6 +159,7 @@ public class TireStatus extends RPCStruct {
* @since SmartDeviceLink 2.0.0
*/
public static final String KEY_RIGHT_REAR = "rightRear";
+
public TireStatus() {
}
diff --git a/base/src/main/java/com/smartdevicelink/proxy/rpc/UnsubscribeVehicleDataResponse.java b/base/src/main/java/com/smartdevicelink/proxy/rpc/UnsubscribeVehicleDataResponse.java
index 114a1971a..9cb5421a8 100644
--- a/base/src/main/java/com/smartdevicelink/proxy/rpc/UnsubscribeVehicleDataResponse.java
+++ b/base/src/main/java/com/smartdevicelink/proxy/rpc/UnsubscribeVehicleDataResponse.java
@@ -102,6 +102,7 @@ public class UnsubscribeVehicleDataResponse extends RPCResponse {
* @since SmartDeviceLink 7.1.0
*/
public static final String KEY_SEAT_OCCUPANCY = "seatOccupancy";
+
/**
* Constructs a new UnsubscribeVehicleDataResponse object
*/
diff --git a/base/src/main/java/com/smartdevicelink/proxy/rpc/VideoStreamingCapability.java b/base/src/main/java/com/smartdevicelink/proxy/rpc/VideoStreamingCapability.java
index 6e1b6abbf..bc879f89b 100644
--- a/base/src/main/java/com/smartdevicelink/proxy/rpc/VideoStreamingCapability.java
+++ b/base/src/main/java/com/smartdevicelink/proxy/rpc/VideoStreamingCapability.java
@@ -197,7 +197,7 @@ public class VideoStreamingCapability extends RPCStruct {
* @since SmartDeviceLink 7.1.0
*/
@SuppressWarnings("unchecked")
- public List<VideoStreamingCapability> getAdditionalVideoStreamingCapabilities(){
+ public List<VideoStreamingCapability> getAdditionalVideoStreamingCapabilities() {
return (List<VideoStreamingCapability>) getObject(VideoStreamingCapability.class, KEY_ADDITIONAL_VIDEO_STREAMING_CAPABILITIES);
}
diff --git a/base/src/main/java/com/smartdevicelink/proxy/rpc/enums/AppCapabilityType.java b/base/src/main/java/com/smartdevicelink/proxy/rpc/enums/AppCapabilityType.java
index 79969528c..7b76d3e5f 100644
--- a/base/src/main/java/com/smartdevicelink/proxy/rpc/enums/AppCapabilityType.java
+++ b/base/src/main/java/com/smartdevicelink/proxy/rpc/enums/AppCapabilityType.java
@@ -46,9 +46,9 @@ public enum AppCapabilityType {
* @return AppCapabilityType
*/
public static AppCapabilityType valueForString(String value) {
- try{
+ try {
return valueOf(value);
- }catch(Exception e){
+ } catch (Exception e) {
return null;
}
}
diff --git a/base/src/main/java/com/smartdevicelink/session/BaseSdlSession.java b/base/src/main/java/com/smartdevicelink/session/BaseSdlSession.java
index 5fcc8d8ca..a33d3eb04 100644
--- a/base/src/main/java/com/smartdevicelink/session/BaseSdlSession.java
+++ b/base/src/main/java/com/smartdevicelink/session/BaseSdlSession.java
@@ -44,6 +44,7 @@ import com.smartdevicelink.protocol.ProtocolMessage;
import com.smartdevicelink.protocol.SdlPacket;
import com.smartdevicelink.protocol.SdlProtocolBase;
import com.smartdevicelink.protocol.enums.ControlFrameTags;
+import com.smartdevicelink.protocol.enums.SecurityQueryErrorCode;
import com.smartdevicelink.protocol.enums.SecurityQueryID;
import com.smartdevicelink.protocol.enums.SecurityQueryType;
import com.smartdevicelink.protocol.enums.SessionType;
@@ -61,7 +62,9 @@ import com.smartdevicelink.util.DebugTool;
import com.smartdevicelink.util.SystemInfo;
import com.smartdevicelink.util.Version;
-import java.util.ArrayList;
+import org.json.JSONException;
+import org.json.JSONObject;
+
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
@@ -217,8 +220,8 @@ public abstract class BaseSdlSession implements ISdlProtocol, ISecurityInitializ
// If the query is of type `Notification` and the id represents a client internal error, we abort the response message and the encryptionManager will not be in state ready.
if (receivedHeader.getQueryID() == SecurityQueryID.SEND_INTERNAL_ERROR
&& receivedHeader.getQueryType() == SecurityQueryType.NOTIFICATION) {
- if (receivedHeader.getErrorCode() != null) {
- DebugTool.logError(TAG, "Security Query module internal error: " + receivedHeader.getErrorCode().getName());
+ if (receivedHeader.getBulkData() != null && receivedHeader.getBulkDataSize() == 1) {
+ DebugTool.logError(TAG, "Security Query module internal error: " + SecurityQueryErrorCode.valueOf(receivedHeader.getBulkData()[0]).getName());
} else {
DebugTool.logError(TAG, "Security Query module error: No information provided");
}
@@ -237,29 +240,28 @@ public abstract class BaseSdlSession implements ISdlProtocol, ISecurityInitializ
iNumBytes = sdlSecurity.runHandshake(data, dataToRead);
- // Assemble a security query payload header for our response
- SecurityQueryPayload responseHeader = new SecurityQueryPayload();
-
- byte[] returnBytes;
+ ProtocolMessage protocolMessage;
if (iNumBytes == null || iNumBytes <= 0) {
DebugTool.logError(TAG, "Internal Error processing control service");
-
- responseHeader.setQueryID(SecurityQueryID.SEND_INTERNAL_ERROR);
- responseHeader.setQueryType(SecurityQueryType.NOTIFICATION);
- responseHeader.setCorrelationID(msg.getCorrID());
- responseHeader.setJsonSize(0);
- returnBytes = new byte[12];
+ protocolMessage = serverSecurityFailedMessageWithClientMessageHeader(msg.getCorrID());
} else {
- responseHeader.setQueryID(SecurityQueryID.SEND_HANDSHAKE_DATA);
- responseHeader.setQueryType(SecurityQueryType.RESPONSE);
- responseHeader.setCorrelationID(msg.getCorrID());
- responseHeader.setJsonSize(0);
- returnBytes = new byte[iNumBytes + 12];
- System.arraycopy(dataToRead, 0, returnBytes, 12, iNumBytes);
+ protocolMessage = serverSecurityHandshakeMessageWithData(msg.getCorrID(), dataToRead);
}
+ //sdlSecurity.hs();
+
+ sendMessage(protocolMessage);
+ }
+
+ private ProtocolMessage serverSecurityHandshakeMessageWithData(int correlationId, byte[] bulkData) {
+ SecurityQueryPayload responseHeader = new SecurityQueryPayload();
+ responseHeader.setQueryID(SecurityQueryID.SEND_HANDSHAKE_DATA);
+ responseHeader.setQueryType(SecurityQueryType.RESPONSE);
+ responseHeader.setCorrelationID(correlationId);
+ responseHeader.setBulkData(bulkData);
+ responseHeader.setJsonData(null);
- System.arraycopy(responseHeader.assembleHeaderBytes(), 0, returnBytes, 0, 12);
+ byte[] returnBytes = responseHeader.assembleBinaryData();
ProtocolMessage protocolMessage = new ProtocolMessage();
protocolMessage.setSessionType(SessionType.CONTROL);
@@ -268,9 +270,40 @@ public abstract class BaseSdlSession implements ISdlProtocol, ISecurityInitializ
protocolMessage.setVersion((byte) sdlProtocol.getProtocolVersion().getMajor());
protocolMessage.setSessionID((byte) this.sessionId);
- //sdlSecurity.hs();
+ return protocolMessage;
+ }
- sendMessage(protocolMessage);
+ private ProtocolMessage serverSecurityFailedMessageWithClientMessageHeader(int correlationId) {
+ SecurityQueryPayload responseHeader = new SecurityQueryPayload();
+ responseHeader.setQueryID(SecurityQueryID.SEND_INTERNAL_ERROR);
+ responseHeader.setQueryType(SecurityQueryType.NOTIFICATION);
+ responseHeader.setCorrelationID(correlationId);
+ byte[] jsonData;
+ JSONObject jsonObject = new JSONObject();
+ try {
+ jsonObject.put("id", SecurityQueryErrorCode.ERROR_UNKNOWN_INTERNAL_ERROR.getValue());
+ jsonObject.put("text", SecurityQueryErrorCode.ERROR_UNKNOWN_INTERNAL_ERROR.getName());
+ jsonData = jsonObject.toString().getBytes();
+ } catch (JSONException e) {
+ DebugTool.logError(TAG, "JSON exception when constructing handshake error Notification");
+ e.printStackTrace();
+ jsonData = new byte[0];
+ }
+ responseHeader.setJsonData(jsonData);
+ byte[] errorCode = new byte[1];
+ errorCode[0] = SecurityQueryErrorCode.ERROR_UNKNOWN_INTERNAL_ERROR.getValue();
+ responseHeader.setBulkData(errorCode);
+
+ byte[] returnBytes = responseHeader.assembleBinaryData();
+
+ ProtocolMessage protocolMessage = new ProtocolMessage();
+ protocolMessage.setSessionType(SessionType.CONTROL);
+ protocolMessage.setData(returnBytes);
+ protocolMessage.setFunctionID(0x01);
+ protocolMessage.setVersion((byte) sdlProtocol.getProtocolVersion().getMajor());
+ protocolMessage.setSessionID((byte) this.sessionId);
+
+ return protocolMessage;
}
/**
diff --git a/base/src/main/java/com/smartdevicelink/streaming/video/VideoStreamingParameters.java b/base/src/main/java/com/smartdevicelink/streaming/video/VideoStreamingParameters.java
index 7a2fe7b78..77e0ffb0a 100644
--- a/base/src/main/java/com/smartdevicelink/streaming/video/VideoStreamingParameters.java
+++ b/base/src/main/java/com/smartdevicelink/streaming/video/VideoStreamingParameters.java
@@ -98,13 +98,13 @@ public class VideoStreamingParameters {
@Deprecated
public VideoStreamingParameters(int displayDensity, int frameRate, int bitrate, int interval,
ImageResolution resolution, VideoStreamingFormat format) {
- this.displayDensity = displayDensity;
- this.frameRate = frameRate;
- this.bitrate = bitrate;
- this.interval = interval;
- this.resolution = resolution;
- this.format = format;
- this.stableFrameRate = true;
+ this.displayDensity = displayDensity;
+ this.frameRate = frameRate;
+ this.bitrate = bitrate;
+ this.interval = interval;
+ this.resolution = resolution;
+ this.format = format;
+ this.stableFrameRate = true;
}
/**
@@ -178,7 +178,7 @@ public class VideoStreamingParameters {
if (!params.additionalCapabilities.isEmpty()) {
this.additionalCapabilities = params.additionalCapabilities;
}
- this.stableFrameRate = params.stableFrameRate;
+ this.stableFrameRate = params.stableFrameRate;
}
}
@@ -304,17 +304,21 @@ public class VideoStreamingParameters {
return resolution;
}
- public boolean isStableFrameRate() {
- return stableFrameRate;
- }
+ public boolean isStableFrameRate() {
+ return stableFrameRate;
+ }
- public void setStableFrameRate(boolean isStable) {
- stableFrameRate = isStable;
- }
+ public void setStableFrameRate(boolean isStable) {
+ stableFrameRate = isStable;
+ }
- public double getScale() { return scale; }
+ public double getScale() {
+ return scale;
+ }
- public double getPreferredDiagonal() { return preferredDiagonal; }
+ public double getPreferredDiagonal() {
+ return preferredDiagonal;
+ }
@Override
public String toString() {
diff --git a/base/src/main/java/com/smartdevicelink/transport/SdlPsm.java b/base/src/main/java/com/smartdevicelink/transport/SdlPsm.java
index dc8fd3bbc..24593c32d 100644
--- a/base/src/main/java/com/smartdevicelink/transport/SdlPsm.java
+++ b/base/src/main/java/com/smartdevicelink/transport/SdlPsm.java
@@ -133,11 +133,11 @@ public class SdlPsm {
//Log.trace(TAG,"Frame Info: " + controlFrameInfo);
switch (frameType) {
case SdlPacket.FRAME_TYPE_CONTROL:
- /*if(frameInfo<FRAME_INFO_HEART_BEAT
- || (frameInfo>FRAME_INFO_END_SERVICE_ACK
- && (frameInfo!=FRAME_INFO_SERVICE_DATA_ACK || frameInfo!=FRAME_INFO_HEART_BEAT_ACK))){
- return ERROR_STATE;
- }*/ //Although some bits are reserved...whatever
+ /*if(frameInfo<FRAME_INFO_HEART_BEAT
+ || (frameInfo>FRAME_INFO_END_SERVICE_ACK
+ && (frameInfo!=FRAME_INFO_SERVICE_DATA_ACK || frameInfo!=FRAME_INFO_HEART_BEAT_ACK))){
+ return ERROR_STATE;
+ }*/ //Although some bits are reserved...whatever
break;
case SdlPacket.FRAME_TYPE_SINGLE: //Fall through since they are both the same
case SdlPacket.FRAME_TYPE_FIRST:
diff --git a/base/src/main/java/com/smartdevicelink/transport/SiphonServer.java b/base/src/main/java/com/smartdevicelink/transport/SiphonServer.java
index 39871b777..66019908c 100644
--- a/base/src/main/java/com/smartdevicelink/transport/SiphonServer.java
+++ b/base/src/main/java/com/smartdevicelink/transport/SiphonServer.java
@@ -107,7 +107,7 @@ public class SiphonServer {
try {
SiphonServer.closeServer();
} catch (IOException e) {
- DebugTool.logError(TAG,"Error while trying to close siphon server", e);
+ DebugTool.logError(TAG, "Error while trying to close siphon server", e);
}
return m_listenPort;
@@ -292,7 +292,7 @@ public class SiphonServer {
try {
// blobSize = length(of message) + 1(size of direction indicator)
- // + 1 (size of msgVersionNumber) + 4 (size of timeStamp)
+ // + 1 (size of msgVersionNumber) + 4 (size of timeStamp)
int blobSize = length + 1 + 1 + 4;
siphonOutputStream.write(BitConverter.intToByteArray(blobSize));
diff --git a/base/src/main/java/com/smartdevicelink/transport/TransportConstants.java b/base/src/main/java/com/smartdevicelink/transport/TransportConstants.java
index 79a055bc9..e671e2fa3 100644
--- a/base/src/main/java/com/smartdevicelink/transport/TransportConstants.java
+++ b/base/src/main/java/com/smartdevicelink/transport/TransportConstants.java
@@ -45,6 +45,8 @@ public class TransportConstants {
public static final String FOREGROUND_EXTRA = "foreground";
public static final String CONFIRMED_SDL_DEVICE = "confirmed_sdl_device";
public static final String VEHICLE_INFO_EXTRA = "vehicle_info";
+ public static final String CONNECTION_TYPE_EXTRA = "connection_type";
+ public static final String PENDING_INTENT_EXTRA = "pending_intent";
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";
diff --git a/base/src/main/java/com/smartdevicelink/util/FileUtls.java b/base/src/main/java/com/smartdevicelink/util/FileUtls.java
index 747052415..387f06b5b 100644
--- a/base/src/main/java/com/smartdevicelink/util/FileUtls.java
+++ b/base/src/main/java/com/smartdevicelink/util/FileUtls.java
@@ -74,7 +74,7 @@ public class FileUtls {
try {
return Files.readAllBytes(file.toPath());
} catch (IOException e) {
- DebugTool.logError(TAG,"Error trying to get file data", e);
+ DebugTool.logError(TAG, "Error trying to get file data", e);
}
}
}
diff --git a/javaEE/hello_sdl_java_ee/src/main/java/com/smartdevicelink/SdlService.java b/javaEE/hello_sdl_java_ee/src/main/java/com/smartdevicelink/SdlService.java
index c261230a6..d0929219f 100644
--- a/javaEE/hello_sdl_java_ee/src/main/java/com/smartdevicelink/SdlService.java
+++ b/javaEE/hello_sdl_java_ee/src/main/java/com/smartdevicelink/SdlService.java
@@ -290,7 +290,7 @@ public class SdlService {
}
});
- MenuCell mainCell5 = new MenuCell("Clear the menu", null, null, null,null, null, new MenuSelectionListener() {
+ MenuCell mainCell5 = new MenuCell("Clear the menu", null, null, null, null, null, new MenuSelectionListener() {
@Override
public void onTriggered(TriggerSource trigger) {
DebugTool.logInfo(TAG, "Clearing Menu. Source: " + trigger.toString());
@@ -353,7 +353,7 @@ public class SdlService {
sdlManager.getScreenManager().presentAlert(alertView, new AlertCompletionListener() {
@Override
public void onComplete(boolean success, Integer tryAgainTime) {
- DebugTool.logInfo(TAG, "Alert presented: "+ success);
+ DebugTool.logInfo(TAG, "Alert presented: " + success);
}
});
}
diff --git a/javaEE/javaEE/build.gradle b/javaEE/javaEE/build.gradle
index a97824e30..c891409a3 100644
--- a/javaEE/javaEE/build.gradle
+++ b/javaEE/javaEE/build.gradle
@@ -2,6 +2,7 @@ apply plugin: 'java-library'
group 'com.smartdevicelink'
version new File(projectDir.path, ('/../../VERSION')).text.trim()
+ext { VERSION_NAME = "$project.version" }
sourceCompatibility = 1.7
diff --git a/javaEE/javaEE/gradle.properties b/javaEE/javaEE/gradle.properties
index a7af0f36b..4bb0ca403 100644
--- a/javaEE/javaEE/gradle.properties
+++ b/javaEE/javaEE/gradle.properties
@@ -1,6 +1,5 @@
GROUP=com.smartdevicelink
POM_ARTIFACT_ID=sdl_java_ee
-VERSION_NAME=5.3.1
POM_NAME=sdl_java_ee
POM_PACKAGING=jar
diff --git a/javaEE/javaEE/src/test/java/com/smartdevicelink/test/TestValues.java b/javaEE/javaEE/src/test/java/com/smartdevicelink/test/TestValues.java
index d3efa2326..6ff8f26bb 100644
--- a/javaEE/javaEE/src/test/java/com/smartdevicelink/test/TestValues.java
+++ b/javaEE/javaEE/src/test/java/com/smartdevicelink/test/TestValues.java
@@ -5,9 +5,9 @@ import com.smartdevicelink.proxy.rpc.enums.FileType;
import java.net.URI;
public class TestValues {
- public static final boolean GENERAL_BOOLEAN = true;
- public static final byte[] GENERAL_BYTE_ARRAY = new byte[0];
- public static final String GENERAL_STRING = "test";
- public static final FileType GENERAL_FILETYPE = FileType.BINARY;
- public static final URI GENERAL_URI = URI.create("http://www.google.com");
+ public static final boolean GENERAL_BOOLEAN = true;
+ public static final byte[] GENERAL_BYTE_ARRAY = new byte[0];
+ public static final String GENERAL_STRING = "test";
+ public static final FileType GENERAL_FILETYPE = FileType.BINARY;
+ public static final URI GENERAL_URI = URI.create("http://www.google.com");
}
diff --git a/javaSE/javaSE/build.gradle b/javaSE/javaSE/build.gradle
index aa97ea53a..c20713e51 100644
--- a/javaSE/javaSE/build.gradle
+++ b/javaSE/javaSE/build.gradle
@@ -2,6 +2,7 @@ apply plugin: 'java-library'
group 'com.smartdevicelink'
version new File(projectDir.path, ('/../../VERSION')).text.trim()
+ext { VERSION_NAME = "$project.version" }
sourceCompatibility = 1.7
@@ -27,7 +28,7 @@ configurations {
}
dependencies {
- testCompile group: 'junit', name: 'junit', version: '4.12'
+ testImplementation group: 'junit', name: 'junit', version: '4.12'
extraLibs fileTree(dir: 'libs', include: ['*.jar'])
extraLibs 'org.mongodb:bson:4.0.5'
extraLibs 'androidx.annotation:annotation:1.1.0'
diff --git a/javaSE/javaSE/gradle.properties b/javaSE/javaSE/gradle.properties
index f2a4bb0f9..e8c9b58c6 100644
--- a/javaSE/javaSE/gradle.properties
+++ b/javaSE/javaSE/gradle.properties
@@ -1,6 +1,5 @@
GROUP=com.smartdevicelink
POM_ARTIFACT_ID=sdl_java_se
-VERSION_NAME=5.3.1
POM_NAME=sdl_java_se
POM_PACKAGING=jar
diff --git a/javaSE/javaSE/src/main/java/com/smartdevicelink/BuildConfig.java b/javaSE/javaSE/src/main/java/com/smartdevicelink/BuildConfig.java
index 9b4ce8fca..c2ed98ba6 100644
--- a/javaSE/javaSE/src/main/java/com/smartdevicelink/BuildConfig.java
+++ b/javaSE/javaSE/src/main/java/com/smartdevicelink/BuildConfig.java
@@ -32,5 +32,5 @@ package com.smartdevicelink;
// THIS FILE IS AUTO GENERATED, DO NOT MODIFY!!
public final class BuildConfig {
- public static final String VERSION_NAME = "5.3.1";
+ public static final String VERSION_NAME = "5.4.0";
} \ No newline at end of file
diff --git a/javaSE/javaSE/src/main/java/com/smartdevicelink/managers/SdlManager.java b/javaSE/javaSE/src/main/java/com/smartdevicelink/managers/SdlManager.java
index f95639ca6..f08f41f58 100644
--- a/javaSE/javaSE/src/main/java/com/smartdevicelink/managers/SdlManager.java
+++ b/javaSE/javaSE/src/main/java/com/smartdevicelink/managers/SdlManager.java
@@ -157,6 +157,12 @@ public class SdlManager extends BaseSdlManager {
@Override
public void dispose() {
+ int state = getState();
+ if (state == BaseSubManager.SHUTDOWN || state == BaseSubManager.ERROR) {
+ DebugTool.logInfo(TAG, "SdlManager already disposed");
+ return;
+ }
+
if (this.permissionManager != null) {
this.permissionManager.dispose();
}
@@ -194,6 +200,7 @@ public class SdlManager extends BaseSdlManager {
super(appId, appName, listener);
}
}
+
private ISdl _internalInterface = new ISdl() {
@Override
public void start() {
@@ -202,7 +209,7 @@ public class SdlManager extends BaseSdlManager {
@Override
public void stop() {
- lifecycleManager.getInternalInterface(SdlManager.this).start();
+ lifecycleManager.getInternalInterface(SdlManager.this).stop();
}
@Override
@@ -252,7 +259,7 @@ public class SdlManager extends BaseSdlManager {
@Override
public boolean removeOnRPCNotificationListener(FunctionID notificationId, OnRPCNotificationListener listener) {
- return lifecycleManager.getInternalInterface(SdlManager.this).removeOnRPCNotificationListener(notificationId, listener);
+ return lifecycleManager.getInternalInterface(SdlManager.this).removeOnRPCNotificationListener(notificationId, listener);
}
@Override
@@ -262,7 +269,7 @@ public class SdlManager extends BaseSdlManager {
@Override
public boolean removeOnRPCRequestListener(FunctionID functionID, OnRPCRequestListener listener) {
- return lifecycleManager.getInternalInterface(SdlManager.this).removeOnRPCRequestListener(functionID, listener);
+ return lifecycleManager.getInternalInterface(SdlManager.this).removeOnRPCRequestListener(functionID, listener);
}
@Override
@@ -272,29 +279,29 @@ public class SdlManager extends BaseSdlManager {
@Override
public boolean removeOnRPCListener(FunctionID responseId, OnRPCListener listener) {
- return lifecycleManager.getInternalInterface(SdlManager.this).removeOnRPCListener(responseId, listener);
+ return lifecycleManager.getInternalInterface(SdlManager.this).removeOnRPCListener(responseId, listener);
}
@Override
public RegisterAppInterfaceResponse getRegisterAppInterfaceResponse() {
- return lifecycleManager.getInternalInterface(SdlManager.this).getRegisterAppInterfaceResponse();
+ return lifecycleManager.getInternalInterface(SdlManager.this).getRegisterAppInterfaceResponse();
}
@Override
public boolean isTransportForServiceAvailable(SessionType serviceType) {
- return lifecycleManager.getInternalInterface(SdlManager.this).isTransportForServiceAvailable(serviceType);
+ return lifecycleManager.getInternalInterface(SdlManager.this).isTransportForServiceAvailable(serviceType);
}
@NonNull
@Override
public SdlMsgVersion getSdlMsgVersion() {
- return lifecycleManager.getInternalInterface(SdlManager.this).getSdlMsgVersion();
+ return lifecycleManager.getInternalInterface(SdlManager.this).getSdlMsgVersion();
}
@NonNull
@Override
public Version getProtocolVersion() {
- return lifecycleManager.getInternalInterface(SdlManager.this).getProtocolVersion();
+ return lifecycleManager.getInternalInterface(SdlManager.this).getProtocolVersion();
}
@Override
@@ -309,12 +316,12 @@ public class SdlManager extends BaseSdlManager {
@Override
public Taskmaster getTaskmaster() {
- return lifecycleManager.getInternalInterface(SdlManager.this).getTaskmaster();
+ return lifecycleManager.getInternalInterface(SdlManager.this).getTaskmaster();
}
@Override
public SystemCapabilityManager getSystemCapabilityManager() {
- return lifecycleManager.getInternalInterface(SdlManager.this).getSystemCapabilityManager();
+ return lifecycleManager.getInternalInterface(SdlManager.this).getSystemCapabilityManager();
}
@Override
diff --git a/javaSE/javaSE/src/main/java/com/smartdevicelink/managers/lifecycle/LifecycleManager.java b/javaSE/javaSE/src/main/java/com/smartdevicelink/managers/lifecycle/LifecycleManager.java
index e29d34640..a23d1ad51 100644
--- a/javaSE/javaSE/src/main/java/com/smartdevicelink/managers/lifecycle/LifecycleManager.java
+++ b/javaSE/javaSE/src/main/java/com/smartdevicelink/managers/lifecycle/LifecycleManager.java
@@ -39,6 +39,8 @@ import com.smartdevicelink.proxy.rpc.enums.SdlDisconnectedReason;
import com.smartdevicelink.session.SdlSession;
import com.smartdevicelink.transport.BaseTransportConfig;
+import static com.smartdevicelink.managers.BaseSubManager.SETTING_UP;
+
/**
* The lifecycle manager creates a central point for all SDL session logic to converge. It should only be used by
* the library itself. Usage outside the library is not permitted and will not be protected for in the future.
@@ -57,7 +59,9 @@ public class LifecycleManager extends BaseLifecycleManager {
@Override
void cycle(SdlDisconnectedReason disconnectedReason) {
- clean();
+ clean(true);
+ transitionToState(SETTING_UP);
+ initialize();
if (session != null) {
try {
session.startSession();
diff --git a/javaSE/javaSE/src/main/java/com/smartdevicelink/managers/screen/AlertManager.java b/javaSE/javaSE/src/main/java/com/smartdevicelink/managers/screen/AlertManager.java
index addcee13d..15e92eb1a 100644
--- a/javaSE/javaSE/src/main/java/com/smartdevicelink/managers/screen/AlertManager.java
+++ b/javaSE/javaSE/src/main/java/com/smartdevicelink/managers/screen/AlertManager.java
@@ -4,6 +4,7 @@ import androidx.annotation.RestrictTo;
import com.smartdevicelink.managers.ISdl;
import com.smartdevicelink.managers.file.FileManager;
+
/**
* <strong>AlertManager</strong> <br>
* <p>