summaryrefslogtreecommitdiff
path: root/android
diff options
context:
space:
mode:
authorBilal Alsharifi <bilal.alsharifi@gmail.com>2020-06-03 13:32:26 -0400
committerBilal Alsharifi <bilal.alsharifi@gmail.com>2020-06-03 13:32:26 -0400
commitafb592c0804c55be7a5ba395f181dc4d50d745f5 (patch)
tree79c9eba3ac7ec2132963f7a6b308b0ff9fedf1c4 /android
parentf2ee959c1d252d7ecc8537fcb108e8c57f162a8e (diff)
downloadsdl_android-afb592c0804c55be7a5ba395f181dc4d50d745f5.tar.gz
Move NAV & PCM code to Android LifecycleManager
Diffstat (limited to 'android')
-rw-r--r--android/sdl_android/src/main/java/com/smartdevicelink/managers/lifecycle/LifecycleManager.java265
1 files changed, 265 insertions, 0 deletions
diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/managers/lifecycle/LifecycleManager.java b/android/sdl_android/src/main/java/com/smartdevicelink/managers/lifecycle/LifecycleManager.java
index 66fc880f4..d4eeff1df 100644
--- a/android/sdl_android/src/main/java/com/smartdevicelink/managers/lifecycle/LifecycleManager.java
+++ b/android/sdl_android/src/main/java/com/smartdevicelink/managers/lifecycle/LifecycleManager.java
@@ -36,18 +36,40 @@ import android.support.annotation.RestrictTo;
import com.smartdevicelink.SdlConnection.SdlSession;
import com.smartdevicelink.SdlConnection.SdlSession2;
+import com.smartdevicelink.protocol.enums.SessionType;
+import com.smartdevicelink.proxy.interfaces.ISdlServiceListener;
+import com.smartdevicelink.proxy.rpc.enums.SystemCapabilityType;
+import com.smartdevicelink.streaming.video.VideoStreamingParameters;
import com.smartdevicelink.transport.BaseTransportConfig;
import com.smartdevicelink.transport.MultiplexTransportConfig;
import com.smartdevicelink.transport.TCPTransportConfig;
import com.smartdevicelink.transport.enums.TransportType;
+import com.smartdevicelink.util.DebugTool;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.Executors;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.ScheduledExecutorService;
/**
* The lifecycle manager creates a central point for all SDL session logic to converge. It should only be used by
* the library itself. Usage outside the library is not permitted and will not be protected for in the future.
+ *
* @author Bilal Alsharifi.
*/
@RestrictTo(RestrictTo.Scope.LIBRARY)
public class LifecycleManager extends BaseLifecycleManager {
+ private static final int RESPONSE_WAIT_TIME = 2000;
+ private ISdlServiceListener navServiceListener;
+ private boolean navServiceStartResponseReceived = false;
+ private boolean navServiceStartResponse = false;
+ private boolean navServiceEndResponseReceived = false;
+ private boolean navServiceEndResponse = false;
+ private boolean pcmServiceStartResponseReceived = false;
+ private boolean pcmServiceStartResponse = false;
+ private boolean pcmServiceEndResponseReceived = false;
+ private boolean pcmServiceEndResponse = false;
+
public LifecycleManager(AppConfig appConfig, BaseTransportConfig config, LifecycleListener listener) {
super(appConfig, listener);
@@ -59,4 +81,247 @@ public class LifecycleManager extends BaseLifecycleManager {
this.session = SdlSession.createSession((byte) getProtocolVersion().getMajor(), sdlConnectionListener, config);
}
}
+
+ @Override
+ void onProtocolSessionStarted(SessionType sessionType) {
+ super.onProtocolSessionStarted(sessionType);
+ if (sessionType.eq(SessionType.NAV)) {
+ navServiceStartResponseReceived = true;
+ navServiceStartResponse = true;
+ } else if (sessionType.eq(SessionType.PCM)) {
+ pcmServiceStartResponseReceived = true;
+ pcmServiceStartResponse = true;
+ }
+ }
+
+ @Override
+ void onProtocolSessionStartedNACKed(SessionType sessionType) {
+ super.onProtocolSessionStartedNACKed(sessionType);
+ if (sessionType.eq(SessionType.NAV)) {
+ navServiceStartResponseReceived = true;
+ navServiceStartResponse = false;
+ } else if (sessionType.eq(SessionType.PCM)) {
+ pcmServiceStartResponseReceived = true;
+ pcmServiceStartResponse = false;
+ }
+ }
+
+ @Override
+ void onProtocolSessionEnded(SessionType sessionType) {
+ super.onProtocolSessionEnded(sessionType);
+ if (sessionType.eq(SessionType.NAV)) {
+ navServiceEndResponseReceived = true;
+ navServiceEndResponse = true;
+ } else if (sessionType.eq(SessionType.PCM)) {
+ pcmServiceEndResponseReceived = true;
+ pcmServiceEndResponse = true;
+ }
+ }
+
+ @Override
+ void onProtocolSessionEndedNACKed(SessionType sessionType) {
+ super.onProtocolSessionEndedNACKed(sessionType);
+ if (sessionType.eq(SessionType.NAV)) {
+ navServiceEndResponseReceived = true;
+ navServiceEndResponse = false;
+ } else if (sessionType.eq(SessionType.PCM)) {
+ pcmServiceEndResponseReceived = true;
+ pcmServiceEndResponse = false;
+ }
+ }
+
+ /**
+ * This method will try to start the video service with the requested parameters.
+ * When it returns it will attempt to store the accepted parameters if available.
+ *
+ * @param isEncrypted if the service should be encrypted
+ * @param parameters the desired video streaming parameters
+ */
+ @Override
+ void startVideoService(boolean isEncrypted, VideoStreamingParameters parameters) {
+ if (session == null) {
+ DebugTool.logWarning("SdlSession is not created yet.");
+ return;
+ }
+ if (!session.getIsConnected()) {
+ DebugTool.logWarning("Connection is not available.");
+ return;
+ }
+
+ session.setDesiredVideoParams(parameters);
+ tryStartVideoStream(isEncrypted, parameters);
+ }
+
+ /**
+ * Try to open a video service by using the video streaming parameters supplied.
+ * Only information from codecs, width and height are used during video format negotiation.
+ *
+ * @param isEncrypted Specify true if packets on this service have to be encrypted
+ * @param parameters VideoStreamingParameters that are desired. Does not guarantee this is what will be accepted.
+ * @return If the service is opened successfully, an instance of VideoStreamingParams is
+ * returned which contains accepted video format. If the service is opened with legacy
+ * mode (i.e. without any negotiation) then an instance of VideoStreamingParams is
+ * returned. If the service was not opened then null is returned.
+ */
+ private VideoStreamingParameters tryStartVideoStream(boolean isEncrypted, VideoStreamingParameters parameters) {
+ if (session == null) {
+ DebugTool.logWarning("SdlSession is not created yet.");
+ return null;
+ }
+ if (getProtocolVersion() != null && getProtocolVersion().getMajor() >= 5 && !systemCapabilityManager.isCapabilitySupported(SystemCapabilityType.VIDEO_STREAMING)) {
+ DebugTool.logWarning("Module doesn't support video streaming.");
+ return null;
+ }
+ if (parameters == null) {
+ DebugTool.logWarning("Video parameters were not supplied.");
+ return null;
+ }
+
+ if (!navServiceStartResponseReceived || !navServiceStartResponse //If we haven't started the service before
+ || (navServiceStartResponse && isEncrypted && !session.isServiceProtected(SessionType.NAV))) { //Or the service has been started but we'd like to start an encrypted one
+ session.setDesiredVideoParams(parameters);
+
+ navServiceStartResponseReceived = false;
+ navServiceStartResponse = false;
+
+ session.startService(SessionType.NAV, session.getSessionId(), isEncrypted);
+ addNavListener();
+ FutureTask<Void> fTask = new FutureTask<>(new CallableMethod(RESPONSE_WAIT_TIME));
+ ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
+ scheduler.execute(fTask);
+
+ //noinspection StatementWithEmptyBody
+ while (!navServiceStartResponseReceived && !fTask.isDone()) ;
+ scheduler.shutdown();
+ }
+
+ if (navServiceStartResponse) {
+ if (getProtocolVersion() != null && getProtocolVersion().getMajor() < 5) { //Versions 1-4 do not support streaming parameter negotiations
+ session.setAcceptedVideoParams(parameters);
+ }
+ return session.getAcceptedVideoParams();
+ }
+
+ return null;
+ }
+
+ private void addNavListener() {
+ // videos may be started and stopped. Only add this once
+ if (navServiceListener == null) {
+
+ navServiceListener = new ISdlServiceListener() {
+ @Override
+ public void onServiceStarted(SdlSession session, SessionType type, boolean isEncrypted) {
+ }
+
+ @Override
+ public void onServiceEnded(SdlSession session, SessionType type) {
+ // reset nav flags so nav can start upon the next transport connection
+ navServiceStartResponseReceived = false;
+ navServiceStartResponse = false;
+ }
+
+ @Override
+ public void onServiceError(SdlSession session, SessionType type, String reason) {
+ // if there is an error reset the flags so that there is a chance to restart streaming
+ navServiceStartResponseReceived = false;
+ navServiceStartResponse = false;
+ }
+ };
+ session.addServiceListener(SessionType.NAV, navServiceListener);
+ }
+ }
+
+ /**
+ * Closes the opened video service (serviceType 11)
+ *
+ * @return true if the video service is closed successfully, return false otherwise
+ */
+ @Override
+ boolean endVideoStream() {
+ if (session == null) {
+ DebugTool.logWarning("SdlSession is not created yet.");
+ return false;
+ }
+ if (!session.getIsConnected()) {
+ DebugTool.logWarning("Connection is not available.");
+ return false;
+ }
+
+ navServiceEndResponseReceived = false;
+ navServiceEndResponse = false;
+ session.stopVideoStream();
+
+ FutureTask<Void> fTask = new FutureTask<>(new CallableMethod(RESPONSE_WAIT_TIME));
+ ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
+ scheduler.execute(fTask);
+
+ //noinspection StatementWithEmptyBody
+ while (!navServiceEndResponseReceived && !fTask.isDone()) ;
+ scheduler.shutdown();
+
+ return navServiceEndResponse;
+ }
+
+ @Override
+ void startAudioService(boolean isEncrypted) {
+ if (session == null) {
+ DebugTool.logWarning("SdlSession is not created yet.");
+ return;
+ }
+ if (!session.getIsConnected()) {
+ DebugTool.logWarning("Connection is not available.");
+ return;
+ }
+ session.startService(SessionType.PCM, session.getSessionId(), isEncrypted);
+ }
+
+ /**
+ * Closes the opened audio service (serviceType 10)
+ *
+ * @return true if the audio service is closed successfully, return false otherwise
+ */
+ @Override
+ boolean endAudioStream() {
+ if (session == null) {
+ DebugTool.logWarning("SdlSession is not created yet.");
+ return false;
+ }
+ if (!session.getIsConnected()) {
+ DebugTool.logWarning("Connection is not available.");
+ return false;
+ }
+
+ pcmServiceEndResponseReceived = false;
+ pcmServiceEndResponse = false;
+ session.stopAudioStream();
+
+ FutureTask<Void> fTask = new FutureTask<>(new CallableMethod(RESPONSE_WAIT_TIME));
+ ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
+ scheduler.execute(fTask);
+
+ //noinspection StatementWithEmptyBody
+ while (!pcmServiceEndResponseReceived && !fTask.isDone()) ;
+ scheduler.shutdown();
+
+ return pcmServiceEndResponse;
+ }
+
+ private class CallableMethod implements Callable<Void> {
+ private final long waitTime;
+
+ public CallableMethod(int timeInMillis) {
+ this.waitTime = timeInMillis;
+ }
+
+ @Override
+ public Void call() {
+ try {
+ Thread.sleep(waitTime);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+ }
}