summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoey Grover <joeygrover@gmail.com>2018-10-02 13:40:37 -0400
committerGitHub <noreply@github.com>2018-10-02 13:40:37 -0400
commitc267dd1b7ab6ebed479f772d802372a08ca1e66e (patch)
tree04414c3dd89f3624a97e2bf8d995edb6cb9f8dc3
parent8aa8bb330e6d3cdc158d0a1f10c19955e87b5528 (diff)
parent5246850830a17e5b15b5bddef6f53229d75ab0bd (diff)
downloadsdl_android-feature/issue_782_Android_Managers.tar.gz
Merge pull request #879 from smartdevicelink/feature/sim_transport_integration_with_managersfeature/issue_782_Android_Managers
Improve manager states
-rw-r--r--sdl_android/src/androidTest/java/com/smartdevicelink/managers/SdlManagerTests.java129
-rw-r--r--sdl_android/src/androidTest/java/com/smartdevicelink/managers/video/VideoStreamingManagerTests.java2
-rw-r--r--sdl_android/src/androidTest/java/com/smartdevicelink/test/proxy/SystemCapabilityManagerTests.java5
-rw-r--r--sdl_android/src/main/java/com/smartdevicelink/managers/BaseSubManager.java32
-rw-r--r--sdl_android/src/main/java/com/smartdevicelink/managers/SdlManager.java268
-rw-r--r--sdl_android/src/main/java/com/smartdevicelink/managers/audio/AudioStreamManager.java90
-rw-r--r--sdl_android/src/main/java/com/smartdevicelink/managers/lockscreen/LockScreenManager.java4
-rw-r--r--sdl_android/src/main/java/com/smartdevicelink/managers/permission/PermissionManager.java14
-rw-r--r--sdl_android/src/main/java/com/smartdevicelink/managers/screen/ScreenManager.java25
-rw-r--r--sdl_android/src/main/java/com/smartdevicelink/managers/screen/SoftButtonManager.java3
-rw-r--r--sdl_android/src/main/java/com/smartdevicelink/managers/video/VideoStreamingManager.java75
-rw-r--r--sdl_android/src/main/java/com/smartdevicelink/proxy/SdlProxyBase.java6
-rw-r--r--sdl_android/src/main/java/com/smartdevicelink/proxy/interfaces/ISdl.java12
13 files changed, 533 insertions, 132 deletions
diff --git a/sdl_android/src/androidTest/java/com/smartdevicelink/managers/SdlManagerTests.java b/sdl_android/src/androidTest/java/com/smartdevicelink/managers/SdlManagerTests.java
index b1957cd7f..ff8ab3c1d 100644
--- a/sdl_android/src/androidTest/java/com/smartdevicelink/managers/SdlManagerTests.java
+++ b/sdl_android/src/androidTest/java/com/smartdevicelink/managers/SdlManagerTests.java
@@ -4,6 +4,7 @@ import android.content.Context;
import android.test.AndroidTestCase;
import com.smartdevicelink.exception.SdlException;
+import com.smartdevicelink.managers.lockscreen.LockScreenConfig;
import com.smartdevicelink.protocol.enums.FunctionID;
import com.smartdevicelink.proxy.RPCRequest;
import com.smartdevicelink.proxy.RPCResponse;
@@ -68,7 +69,7 @@ public class SdlManagerTests extends AndroidTestCase {
templateColorScheme.setPrimaryColor(Test.GENERAL_RGBCOLOR);
templateColorScheme.setSecondaryColor(Test.GENERAL_RGBCOLOR);
- sdlManager = createSampleManager("heyApp", "123456");
+ sdlManager = createSampleManager("heyApp", "123456", Test.GENERAL_LOCKSCREENCONFIG);
}
@Override
@@ -82,7 +83,7 @@ public class SdlManagerTests extends AndroidTestCase {
return mTestContext;
}
- private SdlManager createSampleManager(String appName, String appId){
+ private SdlManager createSampleManager(String appName, String appId, LockScreenConfig lockScreenConfig){
SdlManager manager;
SdlManagerListener listener = new SdlManagerListener() {
@@ -112,7 +113,7 @@ public class SdlManagerTests extends AndroidTestCase {
builder.setNightColorScheme(templateColorScheme);
builder.setVrSynonyms(Test.GENERAL_VECTOR_STRING);
builder.setTtsName(Test.GENERAL_VECTOR_TTS_CHUNKS);
- builder.setLockScreenConfig(Test.GENERAL_LOCKSCREENCONFIG);
+ builder.setLockScreenConfig(lockScreenConfig);
manager = builder.build();
// mock SdlProxyBase and set it manually
@@ -125,12 +126,12 @@ public class SdlManagerTests extends AndroidTestCase {
// TESTS
public void testNotNull(){
- assertNotNull(createSampleManager("app","123456"));
+ assertNotNull(createSampleManager("app","123456", Test.GENERAL_LOCKSCREENCONFIG));
}
public void testMissingAppName() {
try {
- createSampleManager(null,"123456");
+ createSampleManager(null,"123456", Test.GENERAL_LOCKSCREENCONFIG);
} catch (IllegalArgumentException ex) {
assertSame(ex.getMessage(), "You must specify an app name by calling setAppName");
}
@@ -138,7 +139,7 @@ public class SdlManagerTests extends AndroidTestCase {
public void testMissingAppId() {
try {
- createSampleManager("app",null);
+ createSampleManager("app",null, Test.GENERAL_LOCKSCREENCONFIG);
} catch (IllegalArgumentException ex) {
assertSame(ex.getMessage(), "You must specify an app ID by calling setAppId");
}
@@ -164,20 +165,124 @@ public class SdlManagerTests extends AndroidTestCase {
sdlManager.start();
// Create and force all sub managers to be ready manually. Because SdlManager will not start until all sub managers are ready.
- // Note : SdlManager.initialize() will not be called automatically by proxy as in real life because we have mock proxy not a real one
+ // Note: SdlManager.initialize() will not be called automatically by proxy as in real life because we have mock proxy not a real one
sdlManager.initialize();
- sdlManager.setState(BaseSubManager.READY);
- sdlManager.getAudioStreamManager().transitionToState(BaseSubManager.READY);
- // manager.getVideoStreamingManager().transitionToState(BaseSubManager.READY);
- // manager.getLockScreenManager().transitionToState(BaseSubManager.READY);
- sdlManager.getScreenManager().transitionToState(BaseSubManager.READY);
+
+ // Set all sub managers' states to ready
sdlManager.getPermissionManager().transitionToState(BaseSubManager.READY);
sdlManager.getFileManager().transitionToState(BaseSubManager.READY);
+ sdlManager.getScreenManager().transitionToState(BaseSubManager.READY);
+ sdlManager.getLockScreenManager().transitionToState(BaseSubManager.READY);
// Make sure the listener is called exactly once
assertEquals("Listener was not called or called more/less frequently than expected", listenerCalledCounter, 1);
}
+ public void testManagerStates() {
+ SdlManager sdlManager = createSampleManager("test", "00000", new LockScreenConfig());
+ sdlManager.initialize();
+
+
+ // Case 1-A:
+ sdlManager.getPermissionManager().transitionToState(BaseSubManager.READY);
+ sdlManager.getFileManager().transitionToState(BaseSubManager.READY);
+ sdlManager.getScreenManager().transitionToState(BaseSubManager.READY);
+ sdlManager.getLockScreenConfig().setEnabled(true);
+ sdlManager.getLockScreenManager().transitionToState(BaseSubManager.READY);
+ sdlManager.checkState();
+ assertEquals(BaseSubManager.READY, sdlManager.getState());
+
+
+ // Case 1-B:
+ sdlManager.getPermissionManager().transitionToState(BaseSubManager.READY);
+ sdlManager.getFileManager().transitionToState(BaseSubManager.READY);
+ sdlManager.getScreenManager().transitionToState(BaseSubManager.READY);
+ sdlManager.getLockScreenConfig().setEnabled(false);
+ sdlManager.getLockScreenManager().transitionToState(BaseSubManager.SETTING_UP);
+ sdlManager.checkState();
+ assertEquals(BaseSubManager.READY, sdlManager.getState());
+
+
+ // Case 2-A:
+ sdlManager.getPermissionManager().transitionToState(BaseSubManager.ERROR);
+ sdlManager.getFileManager().transitionToState(BaseSubManager.ERROR);
+ sdlManager.getScreenManager().transitionToState(BaseSubManager.ERROR);
+ sdlManager.getLockScreenConfig().setEnabled(true);
+ sdlManager.getLockScreenManager().transitionToState(BaseSubManager.ERROR);
+ sdlManager.checkState();
+ assertEquals(BaseSubManager.ERROR, sdlManager.getState());
+
+
+ // Case 1-B:
+ sdlManager.getPermissionManager().transitionToState(BaseSubManager.ERROR);
+ sdlManager.getFileManager().transitionToState(BaseSubManager.ERROR);
+ sdlManager.getScreenManager().transitionToState(BaseSubManager.ERROR);
+ sdlManager.getLockScreenConfig().setEnabled(false);
+ sdlManager.getLockScreenManager().transitionToState(BaseSubManager.SETTING_UP);
+ sdlManager.checkState();
+ assertEquals(BaseSubManager.ERROR, sdlManager.getState());
+
+
+ // Case 3-A:
+ sdlManager.getPermissionManager().transitionToState(BaseSubManager.ERROR);
+ sdlManager.getFileManager().transitionToState(BaseSubManager.READY);
+ sdlManager.getScreenManager().transitionToState(BaseSubManager.SETTING_UP);
+ sdlManager.getLockScreenConfig().setEnabled(true);
+ sdlManager.getLockScreenManager().transitionToState(BaseSubManager.LIMITED);
+ sdlManager.checkState();
+ assertEquals(BaseSubManager.SETTING_UP, sdlManager.getState());
+
+
+ // Case 3-B:
+ sdlManager.getPermissionManager().transitionToState(BaseSubManager.ERROR);
+ sdlManager.getFileManager().transitionToState(BaseSubManager.READY);
+ sdlManager.getScreenManager().transitionToState(BaseSubManager.SETTING_UP);
+ sdlManager.getLockScreenConfig().setEnabled(false);
+ sdlManager.getLockScreenManager().transitionToState(BaseSubManager.SETTING_UP);
+ sdlManager.checkState();
+ assertEquals(BaseSubManager.SETTING_UP, sdlManager.getState());
+
+
+ // Case 4-A:
+ sdlManager.getPermissionManager().transitionToState(BaseSubManager.READY);
+ sdlManager.getFileManager().transitionToState(BaseSubManager.ERROR);
+ sdlManager.getScreenManager().transitionToState(BaseSubManager.READY);
+ sdlManager.getLockScreenConfig().setEnabled(true);
+ sdlManager.getLockScreenManager().transitionToState(BaseSubManager.READY);
+ sdlManager.checkState();
+ assertEquals(BaseSubManager.LIMITED, sdlManager.getState());
+
+
+ // Case 4-B:
+ sdlManager.getPermissionManager().transitionToState(BaseSubManager.READY);
+ sdlManager.getFileManager().transitionToState(BaseSubManager.ERROR);
+ sdlManager.getScreenManager().transitionToState(BaseSubManager.READY);
+ sdlManager.getLockScreenConfig().setEnabled(false);
+ sdlManager.getLockScreenManager().transitionToState(BaseSubManager.SETTING_UP);
+ sdlManager.checkState();
+ assertEquals(BaseSubManager.LIMITED, sdlManager.getState());
+
+
+ // Case 5-A:
+ sdlManager.getPermissionManager().transitionToState(BaseSubManager.READY);
+ sdlManager.getFileManager().transitionToState(BaseSubManager.LIMITED);
+ sdlManager.getScreenManager().transitionToState(BaseSubManager.ERROR);
+ sdlManager.getLockScreenConfig().setEnabled(true);
+ sdlManager.getLockScreenManager().transitionToState(BaseSubManager.READY);
+ sdlManager.checkState();
+ assertEquals(BaseSubManager.LIMITED, sdlManager.getState());
+
+
+ // Case 5-B:
+ sdlManager.getPermissionManager().transitionToState(BaseSubManager.READY);
+ sdlManager.getFileManager().transitionToState(BaseSubManager.LIMITED);
+ sdlManager.getScreenManager().transitionToState(BaseSubManager.ERROR);
+ sdlManager.getLockScreenConfig().setEnabled(false);
+ sdlManager.getLockScreenManager().transitionToState(BaseSubManager.SETTING_UP);
+ sdlManager.checkState();
+ assertEquals(BaseSubManager.LIMITED, sdlManager.getState());
+ }
+
public void testSendRPC(){
listenerCalledCounter = 0;
diff --git a/sdl_android/src/androidTest/java/com/smartdevicelink/managers/video/VideoStreamingManagerTests.java b/sdl_android/src/androidTest/java/com/smartdevicelink/managers/video/VideoStreamingManagerTests.java
index baddc8182..1099a1623 100644
--- a/sdl_android/src/androidTest/java/com/smartdevicelink/managers/video/VideoStreamingManagerTests.java
+++ b/sdl_android/src/androidTest/java/com/smartdevicelink/managers/video/VideoStreamingManagerTests.java
@@ -90,6 +90,7 @@ public class VideoStreamingManagerTests extends AndroidTestCase {
public void testInitialization(){
ISdl internalInterface = mock(ISdl.class);
+ when(internalInterface.getProtocolVersion()).thenReturn(new Version(5,1,0));
Answer<Void> onAddServiceListener = new Answer<Void>() {
@Override
@@ -242,6 +243,7 @@ public class VideoStreamingManagerTests extends AndroidTestCase {
public void testConvertTouchEvent(){
ISdl internalInterface = mock(ISdl.class);
+ when(internalInterface.getProtocolVersion()).thenReturn(new Version(5,1,0));
final VideoStreamingManager videoStreamingManager = new VideoStreamingManager(internalInterface);
videoStreamingManager.start(new CompletionListener() {
diff --git a/sdl_android/src/androidTest/java/com/smartdevicelink/test/proxy/SystemCapabilityManagerTests.java b/sdl_android/src/androidTest/java/com/smartdevicelink/test/proxy/SystemCapabilityManagerTests.java
index 8916fe054..45c0f691a 100644
--- a/sdl_android/src/androidTest/java/com/smartdevicelink/test/proxy/SystemCapabilityManagerTests.java
+++ b/sdl_android/src/androidTest/java/com/smartdevicelink/test/proxy/SystemCapabilityManagerTests.java
@@ -219,6 +219,11 @@ public class SystemCapabilityManagerTests extends AndroidTestCase {
public boolean removeOnSystemCapabilityListener(SystemCapabilityType systemCapabilityType, OnSystemCapabilityListener listener) { return false; }
@Override
+ public boolean isTransportForServiceAvailable(SessionType serviceType) {
+ return false;
+ }
+
+ @Override
public void startAudioService(boolean isEncrypted, AudioStreamingCodec codec,
AudioStreamingParams params) {}
diff --git a/sdl_android/src/main/java/com/smartdevicelink/managers/BaseSubManager.java b/sdl_android/src/main/java/com/smartdevicelink/managers/BaseSubManager.java
index edd9ff640..6475b481e 100644
--- a/sdl_android/src/main/java/com/smartdevicelink/managers/BaseSubManager.java
+++ b/sdl_android/src/main/java/com/smartdevicelink/managers/BaseSubManager.java
@@ -3,6 +3,9 @@ package com.smartdevicelink.managers;
import android.support.annotation.NonNull;
import com.smartdevicelink.proxy.interfaces.ISdl;
+import com.smartdevicelink.transport.utl.TransportRecord;
+
+import java.util.List;
/**
* <strong>BaseSubManager</strong> <br>
@@ -29,12 +32,13 @@ public abstract class BaseSubManager {
/**
* Starts up a BaseSubManager, and calls provided callback once BaseSubManager is done setting up or failed setup.
- * @param listener CompletionListener that is called once the BaseSubManager's state is READY or ERROR
+ * @param listener CompletionListener that is called once the BaseSubManager's state is READY, LIMITED, or ERROR
*/
public void start(CompletionListener listener){
this.completionListener = listener;
- if((state == READY || state == ERROR) && completionListener != null){
- completionListener.onComplete(state == READY);
+ int state = getState();
+ if((state == READY || state == LIMITED || state == ERROR) && completionListener != null){
+ completionListener.onComplete(state == READY || state == LIMITED);
completionListener = null;
}
}
@@ -50,11 +54,8 @@ public abstract class BaseSubManager {
synchronized (STATE_LOCK) {
this.state = state;
}
- if(state == READY && completionListener != null){
- completionListener.onComplete(true);
- completionListener = null;
- }else if(state == ERROR && completionListener != null){
- completionListener.onComplete(false);
+ if((state == READY || state == LIMITED || state == ERROR) && completionListener != null ){
+ completionListener.onComplete(state == READY || state == LIMITED);
completionListener = null;
}
}
@@ -64,4 +65,19 @@ public abstract class BaseSubManager {
return state;
}
}
+
+ //This allows the method to not be exposed to developers
+ protected void handleTransportUpdated(List<TransportRecord> connectedTransports, boolean audioStreamTransportAvail, boolean videoStreamTransportAvail){
+ this.onTransportUpdate(connectedTransports,audioStreamTransportAvail,videoStreamTransportAvail);
+ }
+
+ /**
+ * Transport status has been updated
+ * @param connectedTransports currently connected transports
+ * @param audioStreamTransportAvail if there is a transport that could be used to carry the
+ * audio service
+ * @param videoStreamTransportAvail if there is a transport that could be used to carry the
+ * video service
+ */
+ protected void onTransportUpdate(List<TransportRecord> connectedTransports, boolean audioStreamTransportAvail, boolean videoStreamTransportAvail){}
}
diff --git a/sdl_android/src/main/java/com/smartdevicelink/managers/SdlManager.java b/sdl_android/src/main/java/com/smartdevicelink/managers/SdlManager.java
index 1c478b8c4..2f4de7f97 100644
--- a/sdl_android/src/main/java/com/smartdevicelink/managers/SdlManager.java
+++ b/sdl_android/src/main/java/com/smartdevicelink/managers/SdlManager.java
@@ -1,19 +1,20 @@
package com.smartdevicelink.managers;
+import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
-import com.smartdevicelink.managers.file.FileManager;
-import com.smartdevicelink.managers.permission.PermissionManager;
+import com.smartdevicelink.exception.SdlException;
import com.smartdevicelink.managers.audio.AudioStreamManager;
+import com.smartdevicelink.managers.file.FileManager;
import com.smartdevicelink.managers.file.filetypes.SdlArtwork;
import com.smartdevicelink.managers.lockscreen.LockScreenConfig;
import com.smartdevicelink.managers.lockscreen.LockScreenManager;
+import com.smartdevicelink.managers.permission.PermissionManager;
import com.smartdevicelink.managers.screen.ScreenManager;
-import com.smartdevicelink.exception.SdlException;
import com.smartdevicelink.managers.video.VideoStreamingManager;
import com.smartdevicelink.protocol.enums.FunctionID;
import com.smartdevicelink.protocol.enums.SessionType;
@@ -44,6 +45,11 @@ import com.smartdevicelink.streaming.audio.AudioStreamingCodec;
import com.smartdevicelink.streaming.audio.AudioStreamingParams;
import com.smartdevicelink.streaming.video.VideoStreamingParameters;
import com.smartdevicelink.transport.BaseTransportConfig;
+import com.smartdevicelink.transport.MultiplexTransportConfig;
+import com.smartdevicelink.transport.enums.TransportType;
+import com.smartdevicelink.transport.utl.TransportRecord;
+import com.smartdevicelink.util.DebugTool;
+import com.smartdevicelink.util.Version;
import java.util.ArrayList;
import java.util.List;
@@ -62,8 +68,7 @@ import java.util.Vector;
* 4. Helper methods
*/
public class SdlManager{
-
- private static String TAG = "Sdl Manager";
+ private static final String TAG = "SdlManager";
private SdlProxyBase proxy;
private String appId, appName, shortAppName;
private boolean isMediaApp;
@@ -78,11 +83,11 @@ public class SdlManager{
private SdlManagerListener managerListener;
private int state = -1;
private List<Class<? extends SdlSecurityBase>> sdlSecList;
- public LockScreenConfig lockScreenConfig;
+ private LockScreenConfig lockScreenConfig;
+ private final Object STATE_LOCK = new Object();
// Managers
-
private PermissionManager permissionManager;
private FileManager fileManager;
private LockScreenManager lockScreenManager;
@@ -95,7 +100,7 @@ public class SdlManager{
private final ProxyBridge proxyBridge= new ProxyBridge(new ProxyBridge.LifecycleListener() {
@Override
public void onProxyConnected() {
- Log.d(TAG, "Proxy is connected. Now initializing.");
+ DebugTool.logInfo("Proxy is connected. Now initializing.");
initialize();
}
@@ -125,95 +130,144 @@ public class SdlManager{
@Override
public synchronized void onComplete(boolean success) {
if(!success){
- Log.d(TAG, "Sub manager failed to initialize");
+ Log.e(TAG, "Sub manager failed to initialize");
}
- if(
- permissionManager != null && permissionManager.getState() != BaseSubManager.SETTING_UP &&
- fileManager != null && fileManager.getState() != BaseSubManager.SETTING_UP &&
- audioStreamManager != null && audioStreamManager.getState() != BaseSubManager.SETTING_UP &&
- (videoStreamingManager == null || (videoStreamingManager != null && videoStreamingManager.getState() != BaseSubManager.SETTING_UP)) &&
- lockScreenManager != null && lockScreenManager.getState() != BaseSubManager.SETTING_UP &&
- screenManager != null && screenManager.getState() != BaseSubManager.SETTING_UP
-
- ){
- state = BaseSubManager.READY;
- if(managerListener != null){
- managerListener.onStart();
- }
+ checkState();
+ }
+ };
- // Set the app icon
- if (SdlManager.this.appIcon != null && SdlManager.this.appIcon.getName() != null) {
- if (!fileManager.hasUploadedFile(SdlManager.this.appIcon)) {
- fileManager.uploadArtwork(SdlManager.this.appIcon, new CompletionListener() {
- @Override
- public void onComplete(boolean success) {
- if (success) {
- SetAppIcon msg = new SetAppIcon(SdlManager.this.appIcon.getName());
- _internalInterface.sendRPCRequest(msg);
- }
- }
- });
- } else {
- SetAppIcon msg = new SetAppIcon(SdlManager.this.appIcon.getName());
- _internalInterface.sendRPCRequest(msg);
+ void checkState() {
+ if (permissionManager != null && fileManager != null && screenManager != null && (!lockScreenConfig.isEnabled() || lockScreenManager != null)) {
+ if (permissionManager.getState() == BaseSubManager.READY && fileManager.getState() == BaseSubManager.READY && screenManager.getState() == BaseSubManager.READY && (!lockScreenConfig.isEnabled() || lockScreenManager.getState() == BaseSubManager.READY)) {
+ DebugTool.logInfo("Starting sdl manager, all sub managers are in ready state");
+ transitionToState(BaseSubManager.READY);
+ notifyDevListener(null);
+ onReady();
+ } else if (permissionManager.getState() == BaseSubManager.ERROR && fileManager.getState() == BaseSubManager.ERROR && screenManager.getState() == BaseSubManager.ERROR && (!lockScreenConfig.isEnabled() || lockScreenManager.getState() == BaseSubManager.ERROR)) {
+ String info = "ERROR starting sdl manager, all sub managers are in error state";
+ Log.e(TAG, info);
+ transitionToState(BaseSubManager.ERROR);
+ notifyDevListener(info);
+ } else if (permissionManager.getState() == BaseSubManager.SETTING_UP || fileManager.getState() == BaseSubManager.SETTING_UP || screenManager.getState() == BaseSubManager.SETTING_UP || (lockScreenConfig.isEnabled() && lockScreenManager != null && lockScreenManager.getState() == BaseSubManager.SETTING_UP)) {
+ DebugTool.logInfo("SETTING UP sdl manager, some sub managers are still setting up");
+ transitionToState(BaseSubManager.SETTING_UP);
+ // No need to notify developer here!
+ } else {
+ Log.w(TAG, "LIMITED starting sdl manager, some sub managers are in error or limited state and the others finished setting up");
+ transitionToState(BaseSubManager.LIMITED);
+ notifyDevListener(null);
+ onReady();
+ }
+ } else {
+ // We should never be here, but somehow one of the sub-sub managers is null
+ String info = "ERROR one of the sdl sub managers is null";
+ Log.e(TAG, info);
+ transitionToState(BaseSubManager.ERROR);
+ notifyDevListener(info);
+ }
+ }
+
+ private void notifyDevListener(String info) {
+ if (managerListener != null) {
+ if (getState() == BaseSubManager.ERROR){
+ managerListener.onError(info, null);
+ } else {
+ managerListener.onStart();
+ }
+ }
+ }
+
+ private void onReady(){
+ // Set the app icon
+ if (SdlManager.this.appIcon != null && SdlManager.this.appIcon.getName() != null) {
+ if (fileManager != null && fileManager.getState() == BaseSubManager.READY && !fileManager.hasUploadedFile(SdlManager.this.appIcon)) {
+ fileManager.uploadArtwork(SdlManager.this.appIcon, new CompletionListener() {
+ @Override
+ public void onComplete(boolean success) {
+ if (success) {
+ SetAppIcon msg = new SetAppIcon(SdlManager.this.appIcon.getName());
+ _internalInterface.sendRPCRequest(msg);
+ }
}
- }
+ });
+ } else {
+ SetAppIcon msg = new SetAppIcon(SdlManager.this.appIcon.getName());
+ _internalInterface.sendRPCRequest(msg);
}
}
- };
+ }
protected void initialize(){
- // instantiate managers
-
+ // Instantiate sub managers
this.permissionManager = new PermissionManager(_internalInterface);
- this.permissionManager.start(subManagerListener);
-
this.fileManager = new FileManager(_internalInterface, context);
- this.fileManager.start(subManagerListener);
-
if (lockScreenConfig.isEnabled()) {
this.lockScreenManager = new LockScreenManager(lockScreenConfig, context, _internalInterface);
- this.lockScreenManager.start(subManagerListener);
}
-
this.screenManager = new ScreenManager(_internalInterface, this.fileManager);
- this.screenManager.start(subManagerListener);
-
-
if(getAppTypes().contains(AppHMIType.NAVIGATION) || getAppTypes().contains(AppHMIType.PROJECTION)){
this.videoStreamingManager = new VideoStreamingManager(_internalInterface);
- this.videoStreamingManager.start(subManagerListener);
+ } else {
+ this.videoStreamingManager = null;
}
-
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN
+ && (getAppTypes().contains(AppHMIType.NAVIGATION) || getAppTypes().contains(AppHMIType.PROJECTION)) ) {
this.audioStreamManager = new AudioStreamManager(_internalInterface, context);
- this.audioStreamManager.start(subManagerListener);
} else {
this.audioStreamManager = null;
}
+ // Start sub managers
+ this.permissionManager.start(subManagerListener);
+ this.fileManager.start(subManagerListener);
+ if (lockScreenConfig.isEnabled()){
+ this.lockScreenManager.start(subManagerListener);
+ }
+ this.screenManager.start(subManagerListener);
+ }
+
+ /**
+ * Get the current state for the SdlManager
+ * @return int value that represents the current state
+ * @see BaseSubManager
+ */
+ public int getState() {
+ synchronized (STATE_LOCK) {
+ return state;
+ }
+ }
+
+ protected void transitionToState(int state) {
+ synchronized (STATE_LOCK) {
+ this.state = state;
+ }
}
+ @SuppressLint("NewApi")
public void dispose() {
- this.permissionManager.dispose();
+ if (this.permissionManager != null) {
+ this.permissionManager.dispose();
+ }
- this.fileManager.dispose();
+ if (this.fileManager != null) {
+ this.fileManager.dispose();
+ }
if (this.lockScreenManager != null) {
this.lockScreenManager.dispose();
}
- this.screenManager.dispose();
+ if (this.screenManager != null) {
+ this.screenManager.dispose();
+ }
if(this.videoStreamingManager != null) {
this.videoStreamingManager.dispose();
}
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
- if (this.audioStreamManager != null) {
- this.audioStreamManager.dispose();
- }
+ // SuppressLint("NewApi") is used because audioStreamManager is only available on android >= jelly bean
+ if (this.audioStreamManager != null) {
+ this.audioStreamManager.dispose();
}
if(managerListener != null){
@@ -222,16 +276,7 @@ public class SdlManager{
}
}
- /**
- * Sets the state of SdlManager to one of those defined in BaseSubManager
- * @param state int representing desired state of SdlManager
- */
- protected void setState(int state){
- this.state = state;
- }
-
// BUILDER
-
public static class Builder {
SdlManager sdlManager;
@@ -424,15 +469,15 @@ public class SdlManager{
sdlManager.hmiLanguage = Language.EN_US;
}
- sdlManager.state = BaseSubManager.SETTING_UP;
+ sdlManager.transitionToState(BaseSubManager.SETTING_UP);
return sdlManager;
}
}
private void checkSdlManagerState(){
- if (state != BaseSubManager.READY){
- throw new IllegalStateException("SdlManager is not ready for use, be sure to initialize with start() method, implement callback, and use SubManagers in the SdlManager's callback");
+ if (getState() != BaseSubManager.READY && getState() != BaseSubManager.LIMITED){
+ Log.e(TAG, "SdlManager is not ready for use, be sure to initialize with start() method, implement callback, and use SubManagers in the SdlManager's callback");
}
}
@@ -444,6 +489,9 @@ public class SdlManager{
* @return a PermissionManager object
*/
public PermissionManager getPermissionManager() {
+ if (permissionManager.getState() != BaseSubManager.READY && permissionManager.getState() != BaseSubManager.LIMITED){
+ Log.e(TAG,"PermissionManager should not be accessed because it is not in READY/LIMITED state");
+ }
checkSdlManagerState();
return permissionManager;
}
@@ -454,26 +502,33 @@ public class SdlManager{
* @return a FileManager object
*/
public FileManager getFileManager() {
+ if (fileManager.getState() != BaseSubManager.READY && fileManager.getState() != BaseSubManager.LIMITED){
+ Log.e(TAG, "FileManager should not be accessed because it is not in READY/LIMITED state");
+ }
checkSdlManagerState();
return fileManager;
}
-
/**
* Gets the VideoStreamingManager. <br>
- * <strong>Note: VideoStreamingManager should be used only after SdlManager.start() CompletionListener callback is completed successfully.</strong>
- * @return a VideoStreamingManager object
+ * The VideoStreamingManager returned will only be not null if the registered app type is
+ * either NAVIGATION or PROJECTION. Once the VideoStreamingManager is retrieved, its start()
+ * method will need to be called before use.
+ * <br><br><strong>Note: VideoStreamingManager should be used only after SdlManager.start() CompletionListener callback is completed successfully.</strong>
+ * @return a VideoStreamingManager object attached to shit SdlManager instance
*/
- public VideoStreamingManager getVideoStreamingManager() {
+ public @Nullable VideoStreamingManager getVideoStreamingManager() {
checkSdlManagerState();
return videoStreamingManager;
}
-
/**
* Gets the AudioStreamManager. <br>
- * <strong>Note: AudioStreamManager should be used only after SdlManager.start() CompletionListener callback is completed successfully.</strong>
+ * The AudioStreamManager returned will only be not null if the registered app type is
+ * either NAVIGATION or PROJECTION. Once the AudioStreamManager is retrieved, its start()
+ * method will need to be called before use.
+ * <br><strong>Note: AudioStreamManager should be used only after SdlManager.start() CompletionListener callback is completed successfully.</strong>
* @return a AudioStreamManager object
*/
public @Nullable AudioStreamManager getAudioStreamManager() {
@@ -487,6 +542,9 @@ public class SdlManager{
* @return a ScreenManager object
*/
public ScreenManager getScreenManager() {
+ if (screenManager.getState() != BaseSubManager.READY && screenManager.getState() != BaseSubManager.LIMITED){
+ Log.e(TAG, "ScreenManager should not be accessed because it is not in READY/LIMITED state");
+ }
checkSdlManagerState();
return screenManager;
}
@@ -497,11 +555,13 @@ public class SdlManager{
* @return a LockScreenManager object
*/
public LockScreenManager getLockScreenManager() {
+ if (lockScreenManager.getState() != BaseSubManager.READY && lockScreenManager.getState() != BaseSubManager.LIMITED){
+ Log.e(TAG, "LockScreenManager should not be accessed because it is not in READY/LIMITED state");
+ }
checkSdlManagerState();
return lockScreenManager;
}
-
/**
* Gets the SystemCapabilityManager. <br>
* <strong>Note: SystemCapabilityManager should be used only after SdlManager.start() CompletionListener callback is completed successfully.</strong>
@@ -511,9 +571,7 @@ public class SdlManager{
return proxy.getSystemCapabilityManager();
}
-
// PROTECTED GETTERS
-
protected String getAppName() { return appName; }
protected String getAppId() { return appId; }
@@ -630,6 +688,30 @@ public class SdlManager{
public void start(){
if (proxy == null) {
try {
+ if(transport!= null && transport.getTransportType() == TransportType.MULTIPLEX){
+ //Do the thing
+ MultiplexTransportConfig multiplexTransportConfig = (MultiplexTransportConfig)(transport);
+ final MultiplexTransportConfig.TransportListener devListener = multiplexTransportConfig.getTransportListener();
+ multiplexTransportConfig.setTransportListener(new MultiplexTransportConfig.TransportListener() {
+ @Override
+ public void onTransportEvent(List<TransportRecord> connectedTransports, boolean audioStreamTransportAvail, boolean videoStreamTransportAvail) {
+
+ //Pass to submanagers that need it
+ if(videoStreamingManager != null){
+ videoStreamingManager.handleTransportUpdated(connectedTransports, audioStreamTransportAvail, videoStreamTransportAvail);
+ }
+
+ if(audioStreamManager != null){
+ audioStreamManager.handleTransportUpdated(connectedTransports, audioStreamTransportAvail, videoStreamTransportAvail);
+ }
+ //If the developer supplied a listener to start, it is time to call that
+ if(devListener != null){
+ devListener.onTransportEvent(connectedTransports,audioStreamTransportAvail,videoStreamTransportAvail);
+ }
+ }
+ });
+ }
+
proxy = new SdlProxyBase(proxyBridge, context, appName, shortAppName, isMediaApp, hmiLanguage,
hmiLanguage, hmiTypes, appId, transport, vrSynonyms, ttsChunks, dayColorScheme,
nightColorScheme) {};
@@ -649,7 +731,6 @@ public class SdlManager{
}
// INTERNAL INTERFACE
-
private ISdl _internalInterface = new ISdl() {
@Override
public void start() {
@@ -795,6 +876,16 @@ public class SdlManager{
}
@Override
+ public boolean isTransportForServiceAvailable(SessionType serviceType) {
+ if(SessionType.NAV.equals(serviceType)){
+ return proxy.isVideoStreamTransportAvailable();
+ }else if(SessionType.PCM.equals(serviceType)){
+ return proxy.isAudioStreamTransportAvailable();
+ }
+ return false;
+ }
+
+ @Override
public SdlMsgVersion getSdlMsgVersion(){
try {
return proxy.getSdlMsgVersion();
@@ -805,10 +896,13 @@ public class SdlManager{
}
@Override
- public com.smartdevicelink.util.Version getProtocolVersion() {
- return proxy.getProtocolVersion();
+ public @NonNull Version getProtocolVersion() {
+ if(proxy.getProtocolVersion() != null){
+ return proxy.getProtocolVersion();
+ }else{
+ return new Version(1,0,0);
+ }
}
};
-
}
diff --git a/sdl_android/src/main/java/com/smartdevicelink/managers/audio/AudioStreamManager.java b/sdl_android/src/main/java/com/smartdevicelink/managers/audio/AudioStreamManager.java
index a959ee93c..da58692af 100644
--- a/sdl_android/src/main/java/com/smartdevicelink/managers/audio/AudioStreamManager.java
+++ b/sdl_android/src/main/java/com/smartdevicelink/managers/audio/AudioStreamManager.java
@@ -16,17 +16,26 @@ import com.smartdevicelink.SdlConnection.SdlSession;
import com.smartdevicelink.managers.BaseSubManager;
import com.smartdevicelink.managers.CompletionListener;
import com.smartdevicelink.managers.StreamingStateMachine;
+import com.smartdevicelink.protocol.enums.FunctionID;
import com.smartdevicelink.protocol.enums.SessionType;
+import com.smartdevicelink.proxy.RPCNotification;
import com.smartdevicelink.proxy.interfaces.IAudioStreamListener;
import com.smartdevicelink.proxy.interfaces.ISdl;
import com.smartdevicelink.proxy.interfaces.ISdlServiceListener;
+import com.smartdevicelink.proxy.interfaces.OnSystemCapabilityListener;
import com.smartdevicelink.proxy.rpc.AudioPassThruCapabilities;
+import com.smartdevicelink.proxy.rpc.OnHMIStatus;
+import com.smartdevicelink.proxy.rpc.enums.HMILevel;
import com.smartdevicelink.proxy.rpc.enums.SystemCapabilityType;
+import com.smartdevicelink.proxy.rpc.listeners.OnRPCNotificationListener;
+import com.smartdevicelink.transport.utl.TransportRecord;
+import com.smartdevicelink.util.Version;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
import java.util.LinkedList;
+import java.util.List;
import java.util.Queue;
/**
@@ -45,7 +54,9 @@ public class AudioStreamManager extends BaseSubManager {
private final Queue<BaseAudioDecoder> queue;
private final WeakReference<Context> context;
private final StreamingStateMachine streamingStateMachine;
-
+ private AudioPassThruCapabilities audioStreamingCapabilities;
+ private HMILevel hmiLevel;
+ private boolean isTransportAvailable = false;
// This completion listener is used as a callback to the app developer when starting/stopping audio service
private CompletionListener serviceCompletionListener;
// As the internal interface does not provide timeout we need to use a future task
@@ -114,27 +125,81 @@ public class AudioStreamManager extends BaseSubManager {
}
};
+ private final OnRPCNotificationListener hmiListener = new OnRPCNotificationListener() {
+ @Override
+ public void onNotified(RPCNotification notification) {
+ if(notification != null){
+ hmiLevel = ((OnHMIStatus)notification).getHmiLevel();
+ if(hmiLevel.equals(HMILevel.HMI_FULL) || hmiLevel.equals(HMILevel.HMI_LIMITED)){
+ checkState();
+ }
+ }
+ }
+ };
+
/**
* Creates a new object of AudioStreamManager
* @param internalInterface The internal interface to the connected device.
*/
public AudioStreamManager(@NonNull ISdl internalInterface, @NonNull Context context) {
super(internalInterface);
+ if(Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN){
+ this.queue = null;
+ this.context = null;
+ this.serviceCompletionHandler = null;
+ this.streamingStateMachine = null;
+ transitionToState(ERROR);
+ return;
+ }
this.queue = new LinkedList<>();
this.context = new WeakReference<>(context);
this.serviceCompletionHandler = new Handler(Looper.getMainLooper());
internalInterface.addServiceListener(SessionType.PCM, serviceListener);
+ // Listen for HMILevel changes
+ internalInterface.addOnRPCNotificationListener(FunctionID.ON_HMI_STATUS, hmiListener);
+
streamingStateMachine = new StreamingStateMachine();
+
}
@Override
public void start(CompletionListener listener) {
- transitionToState(READY);
+ isTransportAvailable = internalInterface.isTransportForServiceAvailable(SessionType.PCM);
+ getAudioStreamingCapabilities();
+ checkState();
super.start(listener);
}
+ private void checkState(){
+ if(audioStreamingCapabilities != null
+ && isTransportAvailable
+ && hmiLevel != null
+ && (hmiLevel.equals(HMILevel.HMI_LIMITED) || hmiLevel.equals(HMILevel.HMI_FULL))){
+ transitionToState(READY);
+ }
+ }
+
+ private void getAudioStreamingCapabilities(){
+ internalInterface.getCapability(SystemCapabilityType.PCM_STREAMING, new OnSystemCapabilityListener() {
+ @Override
+ public void onCapabilityRetrieved(Object capability) {
+ if(capability != null && capability instanceof AudioPassThruCapabilities){
+ audioStreamingCapabilities = (AudioPassThruCapabilities) capability;
+ checkState();
+ }
+ }
+
+ @Override
+ public void onError(String info) {
+ Log.e(TAG, "Error retrieving audio streaming capability: " + info);
+ streamingStateMachine.transitionToState(StreamingStateMachine.ERROR);
+ transitionToState(ERROR);
+ }
+ });
+ }
+
@Override
public void dispose() {
stopAudioStream(new CompletionListener() {
@@ -331,6 +396,27 @@ public class AudioStreamManager extends BaseSubManager {
}
}
+
+ @Override
+ protected void onTransportUpdate(List<TransportRecord> connectedTransports, boolean audioStreamTransportAvail, boolean videoStreamTransportAvail){
+
+ isTransportAvailable = audioStreamTransportAvail;
+
+ if(internalInterface.getProtocolVersion().isNewerThan(new Version(5,1,0)) >= 0){
+ if(audioStreamTransportAvail){
+ checkState();
+ }
+ }else{
+ //The protocol version doesn't support simultaneous transports.
+ if(!audioStreamTransportAvail){
+ //If video streaming isn't available on primary transport then it is not possible to
+ //use the video streaming manager until a complete register on a transport that
+ //supports video
+ transitionToState(ERROR);
+ }
+ }
+ }
+
@IntDef({SampleType.UNSIGNED_8_BIT, SampleType.SIGNED_16_BIT, SampleType.FLOAT})
@Retention(RetentionPolicy.SOURCE)
public @interface SampleType {
diff --git a/sdl_android/src/main/java/com/smartdevicelink/managers/lockscreen/LockScreenManager.java b/sdl_android/src/main/java/com/smartdevicelink/managers/lockscreen/LockScreenManager.java
index b40c39fde..7419e9e17 100644
--- a/sdl_android/src/main/java/com/smartdevicelink/managers/lockscreen/LockScreenManager.java
+++ b/sdl_android/src/main/java/com/smartdevicelink/managers/lockscreen/LockScreenManager.java
@@ -84,9 +84,7 @@ public class LockScreenManager extends BaseSubManager {
}
deviceLogo = null;
deviceIconUrl = null;
-
- // transition state
- transitionToState(SHUTDOWN);
+ super.dispose();
}
////
diff --git a/sdl_android/src/main/java/com/smartdevicelink/managers/permission/PermissionManager.java b/sdl_android/src/main/java/com/smartdevicelink/managers/permission/PermissionManager.java
index f71b95203..0c0ea2b6e 100644
--- a/sdl_android/src/main/java/com/smartdevicelink/managers/permission/PermissionManager.java
+++ b/sdl_android/src/main/java/com/smartdevicelink/managers/permission/PermissionManager.java
@@ -59,7 +59,6 @@ import java.util.UUID;
*/
public PermissionManager(@NonNull ISdl internalInterface){
super(internalInterface);
- transitionToState(SETTING_UP);
this.currentPermissionItems = new HashMap<>();
this.filters = new ArrayList<>();
@@ -67,11 +66,9 @@ import java.util.UUID;
onHMIStatusListener = new OnRPCNotificationListener() {
@Override
public void onNotified(RPCNotification notification) {
- if (currentHMILevel == null && getState() == SETTING_UP){
- transitionToState(READY);
- }
HMILevel previousHMILevel = currentHMILevel;
currentHMILevel = ((OnHMIStatus)notification).getHmiLevel();
+ checkState();
notifyListeners(currentPermissionItems, previousHMILevel, currentPermissionItems, currentHMILevel);
}
};
@@ -96,9 +93,16 @@ import java.util.UUID;
@Override
public void start(CompletionListener listener) {
+ checkState();
super.start(listener);
}
+ private synchronized void checkState(){
+ if(this.getState() == SETTING_UP && currentHMILevel != null){
+ transitionToState(READY);
+ }
+ }
+
/**
* Go over all developer's listeners and call them if needed because of HMI level change or permission items change
* @param previousPermissionItems
@@ -226,8 +230,6 @@ import java.util.UUID;
// Remove developer's listeners
filters.clear();
-
- transitionToState(SHUTDOWN);
}
/**
diff --git a/sdl_android/src/main/java/com/smartdevicelink/managers/screen/ScreenManager.java b/sdl_android/src/main/java/com/smartdevicelink/managers/screen/ScreenManager.java
index 2b68fbd64..4351ddc91 100644
--- a/sdl_android/src/main/java/com/smartdevicelink/managers/screen/ScreenManager.java
+++ b/sdl_android/src/main/java/com/smartdevicelink/managers/screen/ScreenManager.java
@@ -34,21 +34,21 @@ public class ScreenManager extends BaseSubManager {
public synchronized void onComplete(boolean success) {
if (softButtonManager != null && textAndGraphicManager != null) {
if (softButtonManager.getState() == BaseSubManager.READY && textAndGraphicManager.getState() == BaseSubManager.READY) {
+ Log.i(TAG, "Starting screen manager, all sub managers are in ready state");
transitionToState(READY);
- }else if (softButtonManager.getState() == BaseSubManager.ERROR && textAndGraphicManager.getState() == BaseSubManager.ERROR){
+ } else if (softButtonManager.getState() == BaseSubManager.ERROR && textAndGraphicManager.getState() == BaseSubManager.ERROR) {
Log.e(TAG, "ERROR starting screen manager, both sub managers in error state");
transitionToState(ERROR);
- } else if (softButtonManager.getState() == BaseSubManager.ERROR || textAndGraphicManager.getState() == BaseSubManager.ERROR) {
- Log.e(TAG, "ERROR starting screen manager, one sub manager in error state");
+ } else if (textAndGraphicManager.getState() == BaseSubManager.SETTING_UP || softButtonManager.getState() == BaseSubManager.SETTING_UP) {
+ Log.i(TAG, "SETTING UP screen manager, one sub manager is still setting up");
+ transitionToState(SETTING_UP);
+ } else {
+ Log.w(TAG, "LIMITED starting screen manager, one sub manager in error state and the other is ready");
transitionToState(LIMITED);
}
- } else if (softButtonManager == null || textAndGraphicManager == null) {
+ } else {
// We should never be here, but somehow one of the sub-sub managers is null
Log.e(TAG, "ERROR one of the screen sub managers is null");
- transitionToState(LIMITED);
- } else {
- Log.e(TAG, "ERROR both of the screen sub managers are null");
- // We should never be here, but somehow both of the sub-sub managers is null
transitionToState(ERROR);
}
}
@@ -56,11 +56,15 @@ public class ScreenManager extends BaseSubManager {
public ScreenManager(@NonNull ISdl internalInterface, @NonNull FileManager fileManager) {
super(internalInterface);
- transitionToState(SETTING_UP);
this.fileManager = new WeakReference<>(fileManager);
initialize();
}
+ @Override
+ public void start(CompletionListener listener) {
+ super.start(listener);
+ }
+
private void initialize(){
if (fileManager.get() != null) {
this.softButtonManager = new SoftButtonManager(internalInterface, fileManager.get());
@@ -73,7 +77,8 @@ public class ScreenManager extends BaseSubManager {
/**
* <p>Called when manager is being torn down</p>
*/
- public void dispose(){
+ @Override
+ public void dispose() {
softButtonManager.dispose();
textAndGraphicManager.dispose();
super.dispose();
diff --git a/sdl_android/src/main/java/com/smartdevicelink/managers/screen/SoftButtonManager.java b/sdl_android/src/main/java/com/smartdevicelink/managers/screen/SoftButtonManager.java
index 537e327d5..0f7e22dea 100644
--- a/sdl_android/src/main/java/com/smartdevicelink/managers/screen/SoftButtonManager.java
+++ b/sdl_android/src/main/java/com/smartdevicelink/managers/screen/SoftButtonManager.java
@@ -67,7 +67,6 @@ class SoftButtonManager extends BaseSubManager {
*/
SoftButtonManager(@NonNull ISdl internalInterface, @NonNull FileManager fileManager) {
super(internalInterface);
- transitionToState(BaseSubManager.SETTING_UP);
this.fileManager = new WeakReference<>(fileManager);
this.softButtonObjects = new CopyOnWriteArrayList<>();
this.currentHMILevel = HMILevel.HMI_NONE; // Assume NONE until we get something else
@@ -498,8 +497,6 @@ class SoftButtonManager extends BaseSubManager {
public void dispose() {
super.dispose();
- transitionToState(SHUTDOWN);
-
// Remove listeners
internalInterface.removeOnRPCNotificationListener(FunctionID.ON_HMI_STATUS, onHMIStatusListener);
internalInterface.removeOnRPCNotificationListener(FunctionID.ON_BUTTON_PRESS, onButtonPressListener);
diff --git a/sdl_android/src/main/java/com/smartdevicelink/managers/video/VideoStreamingManager.java b/sdl_android/src/main/java/com/smartdevicelink/managers/video/VideoStreamingManager.java
index 3ececf0b0..b390fdf81 100644
--- a/sdl_android/src/main/java/com/smartdevicelink/managers/video/VideoStreamingManager.java
+++ b/sdl_android/src/main/java/com/smartdevicelink/managers/video/VideoStreamingManager.java
@@ -36,6 +36,8 @@ import com.smartdevicelink.proxy.rpc.enums.TouchType;
import com.smartdevicelink.proxy.rpc.listeners.OnRPCNotificationListener;
import com.smartdevicelink.streaming.video.SdlRemoteDisplay;
import com.smartdevicelink.streaming.video.VideoStreamingParameters;
+import com.smartdevicelink.transport.utl.TransportRecord;
+import com.smartdevicelink.util.Version;
import java.lang.ref.WeakReference;
import java.util.List;
@@ -56,6 +58,7 @@ public class VideoStreamingManager extends BaseSubManager {
private StreamingStateMachine stateMachine;
private VideoStreamingParameters parameters;
private IVideoStreamListener streamListener;
+ private boolean isTransportAvailable = false;
// INTERNAL INTERFACES
@@ -89,6 +92,9 @@ public class VideoStreamingManager extends BaseSubManager {
public void onNotified(RPCNotification notification) {
if(notification != null){
hmiLevel = ((OnHMIStatus)notification).getHmiLevel();
+ if(hmiLevel.equals(HMILevel.HMI_FULL)){
+ checkState();
+ }
}
}
};
@@ -125,10 +131,55 @@ public class VideoStreamingManager extends BaseSubManager {
@Override
public void start(CompletionListener listener) {
- transitionToState(READY);
+ isTransportAvailable = internalInterface.isTransportForServiceAvailable(SessionType.NAV);
+ getVideoStreamingParams();
+ checkState();
super.start(listener);
}
+ private synchronized void checkState(){
+ if(this.getState() == SETTING_UP
+ && isTransportAvailable
+ && hmiLevel != null
+ && hmiLevel.equals(HMILevel.HMI_FULL)
+ && parameters != null){
+ transitionToState(READY);
+ }
+ }
+
+ private void getVideoStreamingParams(){
+ if(internalInterface.getProtocolVersion().getMajor() >= 5) {
+ internalInterface.getCapability(SystemCapabilityType.VIDEO_STREAMING, new OnSystemCapabilityListener() {
+ @Override
+ public void onCapabilityRetrieved(Object capability) {
+ VideoStreamingParameters params = new VideoStreamingParameters();
+ params.update((VideoStreamingCapability)capability); //Streaming parameters are ready time to stream
+ VideoStreamingManager.this.parameters = params;
+
+ checkState();
+
+ }
+
+ @Override
+ public void onError(String info) {
+ Log.e(TAG, "Error retrieving video streaming capability: " + info);
+ stateMachine.transitionToState(StreamingStateMachine.ERROR);
+ transitionToState(ERROR);
+ }
+ });
+ }else{
+ //We just use default video streaming params
+ VideoStreamingParameters params = new VideoStreamingParameters();
+ DisplayCapabilities dispCap = (DisplayCapabilities)internalInterface.getCapability(SystemCapabilityType.DISPLAY);
+ if(dispCap !=null){
+ params.setResolution(dispCap.getScreenParams().getImageResolution());
+ }
+
+ this.parameters = params;
+ checkState();
+ }
+ }
+
/**
* 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
* @param context a context that can be used to create the remote display
@@ -272,6 +323,7 @@ public class VideoStreamingManager extends BaseSubManager {
/**
* Stops streaming, ends video streaming service and removes service listeners.
*/
+ @Override
public void dispose(){
stopStreaming();
@@ -289,6 +341,7 @@ public class VideoStreamingManager extends BaseSubManager {
internalInterface.removeOnRPCNotificationListener(FunctionID.ON_HMI_STATUS, hmiListener);
stateMachine.transitionToState(StreamingStateMachine.NONE);
+ super.dispose();
}
// PUBLIC METHODS FOR CHECKING STATE
@@ -540,4 +593,24 @@ public class VideoStreamingManager extends BaseSubManager {
}
}
+ @Override
+ protected void onTransportUpdate(List<TransportRecord> connectedTransports, boolean audioStreamTransportAvail, boolean videoStreamTransportAvail){
+
+ isTransportAvailable = videoStreamTransportAvail;
+
+ if(internalInterface.getProtocolVersion().isNewerThan(new Version(5,1,0)) >= 0){
+ if(videoStreamTransportAvail){
+ checkState();
+ }
+ }else{
+ //The protocol version doesn't support simultaneous transports.
+ if(!videoStreamTransportAvail){
+ //If video streaming isn't available on primary transport then it is not possible to
+ //use the video streaming manager until a complete register on a transport that
+ //supports video
+ transitionToState(ERROR);
+ }
+ }
+ }
+
} \ No newline at end of file
diff --git a/sdl_android/src/main/java/com/smartdevicelink/proxy/SdlProxyBase.java b/sdl_android/src/main/java/com/smartdevicelink/proxy/SdlProxyBase.java
index 6b2be9725..b376d7276 100644
--- a/sdl_android/src/main/java/com/smartdevicelink/proxy/SdlProxyBase.java
+++ b/sdl_android/src/main/java/com/smartdevicelink/proxy/SdlProxyBase.java
@@ -392,6 +392,12 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase>
}
@Override
+ public boolean isTransportForServiceAvailable(SessionType serviceType) {
+ return SdlProxyBase.this.sdlSession != null
+ && SdlProxyBase.this.sdlSession.isTransportForServiceAvailable(serviceType);
+ }
+
+ @Override
public void startAudioService(boolean isEncrypted, AudioStreamingCodec codec,
AudioStreamingParams params) {
if(getIsConnected()){
diff --git a/sdl_android/src/main/java/com/smartdevicelink/proxy/interfaces/ISdl.java b/sdl_android/src/main/java/com/smartdevicelink/proxy/interfaces/ISdl.java
index 29d3b9073..5eb8ff36a 100644
--- a/sdl_android/src/main/java/com/smartdevicelink/proxy/interfaces/ISdl.java
+++ b/sdl_android/src/main/java/com/smartdevicelink/proxy/interfaces/ISdl.java
@@ -203,6 +203,18 @@ public interface ISdl {
boolean removeOnSystemCapabilityListener(SystemCapabilityType systemCapabilityType, OnSystemCapabilityListener listener);
/**
+ * Check to see if a transport is available to start/use the supplied service.
+ * @param serviceType the session that should be checked for transport availability
+ * @return true if there is either a supported
+ * transport currently connected or a transport is
+ * available to connect with for the supplied service type.
+ * <br>false if there is no
+ * transport connected to support the service type in question and
+ * no possibility in the foreseeable future.
+ */
+ boolean isTransportForServiceAvailable(SessionType serviceType);
+
+ /**
* Get the RPC specification version currently being used for the SDL messages
* @return SdlMsgVersion the current RPC specification version
*/