diff options
author | Joey Grover <joeygrover@gmail.com> | 2018-10-02 13:40:37 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-10-02 13:40:37 -0400 |
commit | c267dd1b7ab6ebed479f772d802372a08ca1e66e (patch) | |
tree | 04414c3dd89f3624a97e2bf8d995edb6cb9f8dc3 | |
parent | 8aa8bb330e6d3cdc158d0a1f10c19955e87b5528 (diff) | |
parent | 5246850830a17e5b15b5bddef6f53229d75ab0bd (diff) | |
download | sdl_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
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 */ |