summaryrefslogtreecommitdiff
path: root/android/sdl_android/src/main/java/com
diff options
context:
space:
mode:
Diffstat (limited to 'android/sdl_android/src/main/java/com')
-rw-r--r--android/sdl_android/src/main/java/com/smartdevicelink/SdlConnection/SdlSession2.java19
-rw-r--r--android/sdl_android/src/main/java/com/smartdevicelink/haptic/HapticInterfaceManager.java41
-rw-r--r--android/sdl_android/src/main/java/com/smartdevicelink/managers/ProxyBridge.java39
-rw-r--r--android/sdl_android/src/main/java/com/smartdevicelink/managers/SdlManager.java80
-rw-r--r--android/sdl_android/src/main/java/com/smartdevicelink/managers/SdlManagerListener.java16
-rw-r--r--android/sdl_android/src/main/java/com/smartdevicelink/managers/audio/AudioStreamManager.java7
-rw-r--r--android/sdl_android/src/main/java/com/smartdevicelink/managers/lockscreen/LockScreenConfig.java71
-rw-r--r--android/sdl_android/src/main/java/com/smartdevicelink/managers/lockscreen/LockScreenManager.java98
-rw-r--r--android/sdl_android/src/main/java/com/smartdevicelink/managers/lockscreen/SDLLockScreenActivity.java44
-rw-r--r--android/sdl_android/src/main/java/com/smartdevicelink/managers/video/VideoStreamManager.java31
-rw-r--r--android/sdl_android/src/main/java/com/smartdevicelink/protocol/SdlProtocol.java22
-rw-r--r--android/sdl_android/src/main/java/com/smartdevicelink/proxy/LockScreenManager.java63
-rw-r--r--android/sdl_android/src/main/java/com/smartdevicelink/proxy/SdlProxyALM.java70
-rw-r--r--android/sdl_android/src/main/java/com/smartdevicelink/proxy/SdlProxyBase.java188
-rw-r--r--android/sdl_android/src/main/java/com/smartdevicelink/proxy/SdlProxyBuilder.java1
-rw-r--r--android/sdl_android/src/main/java/com/smartdevicelink/proxy/SdlProxyConfigurationResources.java63
-rw-r--r--android/sdl_android/src/main/java/com/smartdevicelink/streaming/video/SdlRemoteDisplay.java2
-rw-r--r--android/sdl_android/src/main/java/com/smartdevicelink/transport/MultiplexTcpTransport.java80
-rw-r--r--android/sdl_android/src/main/java/com/smartdevicelink/transport/SdlRouterService.java10
-rw-r--r--android/sdl_android/src/main/java/com/smartdevicelink/transport/TCPTransportManager.java135
-rw-r--r--android/sdl_android/src/main/java/com/smartdevicelink/transport/TransportBroker.java18
-rw-r--r--android/sdl_android/src/main/java/com/smartdevicelink/transport/utl/WiFiSocketFactory.java4
22 files changed, 906 insertions, 196 deletions
diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/SdlConnection/SdlSession2.java b/android/sdl_android/src/main/java/com/smartdevicelink/SdlConnection/SdlSession2.java
index 457bd9a46..cbd45c49a 100644
--- a/android/sdl_android/src/main/java/com/smartdevicelink/SdlConnection/SdlSession2.java
+++ b/android/sdl_android/src/main/java/com/smartdevicelink/SdlConnection/SdlSession2.java
@@ -45,6 +45,7 @@ import com.smartdevicelink.protocol.heartbeat.IHeartbeatMonitor;
import com.smartdevicelink.proxy.interfaces.ISdlServiceListener;
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.MediaStreamingStatus;
import com.smartdevicelink.util.Version;
@@ -82,8 +83,14 @@ public class SdlSession2 extends SdlSession implements ISdlProtocol{
}
+ public SdlSession2(ISdlConnectionListener listener, TCPTransportConfig config){ //TODO is it better to have two constructors or make it take BaseTransportConfig?
+ this.transportConfig = config;
+ this.sessionListener = listener;
+ this.sdlProtocol = new SdlProtocol(this,config);
+ }
+
boolean isAudioRequirementMet(){
- if(mediaStreamingStatus == null){
+ if(mediaStreamingStatus == null && contextWeakReference!= null && contextWeakReference.get() != null){
mediaStreamingStatus = new MediaStreamingStatus(contextWeakReference.get(), new MediaStreamingStatus.Callback() {
@Override
public void onAudioNoLongerAvailable() {
@@ -304,7 +311,15 @@ public class SdlSession2 extends SdlSession implements ISdlProtocol{
}else if(SessionType.PCM.equals(serviceType)){
stopAudioStream();
}
-
+ // Notify any listeners of the service being ended
+ if(serviceListeners != null && serviceListeners.containsKey(serviceType)){
+ CopyOnWriteArrayList<ISdlServiceListener> listeners = serviceListeners.get(serviceType);
+ if (listeners != null && listeners.size() > 0) {
+ for (ISdlServiceListener listener : listeners) {
+ listener.onServiceEnded(this, serviceType);
+ }
+ }
+ }
}
@Override
diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/haptic/HapticInterfaceManager.java b/android/sdl_android/src/main/java/com/smartdevicelink/haptic/HapticInterfaceManager.java
index 9a6e44897..716fc16fc 100644
--- a/android/sdl_android/src/main/java/com/smartdevicelink/haptic/HapticInterfaceManager.java
+++ b/android/sdl_android/src/main/java/com/smartdevicelink/haptic/HapticInterfaceManager.java
@@ -28,6 +28,8 @@ import com.smartdevicelink.proxy.interfaces.ISdl;
import com.smartdevicelink.proxy.rpc.HapticRect;
import com.smartdevicelink.proxy.rpc.Rectangle;
import com.smartdevicelink.proxy.rpc.SendHapticData;
+import com.smartdevicelink.proxy.rpc.VideoStreamingCapability;
+import com.smartdevicelink.proxy.rpc.enums.SystemCapabilityType;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
@@ -59,8 +61,8 @@ public class HapticInterfaceManager {
*/
public void setHapticData(List<HapticRect> hapticData) {
userHapticData = hapticData;
- ISdl proxy = proxyHolder.get();
- if (proxy != null) {
+ if(proxyHolder.get() != null) {
+ ISdl proxy = proxyHolder.get();
SendHapticData msg = new SendHapticData();
msg.setHapticRectData(userHapticData);
proxy.sendRPCRequest(msg);
@@ -75,15 +77,17 @@ public class HapticInterfaceManager {
* the root or parent View
*/
public void refreshHapticData(View root) {
- ISdl proxy = proxyHolder.get();
- if ((userHapticData == null) && (proxy != null)) {
- List<HapticRect> hapticRects = new ArrayList<>();
- findHapticRects(root, hapticRects);
+ if(proxyHolder.get() != null) {
+ ISdl proxy = proxyHolder.get();
+ if (userHapticData == null) {
+ List<HapticRect> hapticRects = new ArrayList<>();
+ findHapticRects(root, hapticRects);
- SendHapticData msg = new SendHapticData();
- msg.setHapticRectData(hapticRects);
+ SendHapticData msg = new SendHapticData();
+ msg.setHapticRectData(hapticRects);
- proxy.sendRPCRequest(msg);
+ proxy.sendRPC(msg);
+ }
}
}
@@ -91,6 +95,17 @@ public class HapticInterfaceManager {
List<View> focusables = new ArrayList<>();
getFocusableViews(root, focusables);
+ double scale = 1.0;
+
+ if (proxyHolder.get() != null) {
+ ISdl proxy = proxyHolder.get();
+ VideoStreamingCapability videoStreamingCapability = (VideoStreamingCapability)
+ proxy.getCapability(SystemCapabilityType.VIDEO_STREAMING);
+ if (videoStreamingCapability != null && videoStreamingCapability.getScale() != null) {
+ scale = videoStreamingCapability.getScale();
+ }
+ }
+
int [] loc = new int[2];
int id = 0;
for (View view : focusables) {
@@ -99,10 +114,10 @@ public class HapticInterfaceManager {
view.getLocationOnScreen(loc);
Rectangle rect = new Rectangle();
- rect.setWidth((float) w);
- rect.setHeight((float) h);
- rect.setX((float) loc[0]);
- rect.setY((float) loc[1]);
+ rect.setWidth((float) (w * scale));
+ rect.setHeight((float) (h * scale));
+ rect.setX((float) (loc[0] * scale));
+ rect.setY((float) (loc[1] * scale));
HapticRect hapticRect = new HapticRect();
hapticRect.setId(id++);
diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/managers/ProxyBridge.java b/android/sdl_android/src/main/java/com/smartdevicelink/managers/ProxyBridge.java
index fc204df49..23c37bea5 100644
--- a/android/sdl_android/src/main/java/com/smartdevicelink/managers/ProxyBridge.java
+++ b/android/sdl_android/src/main/java/com/smartdevicelink/managers/ProxyBridge.java
@@ -44,13 +44,16 @@ import com.smartdevicelink.proxy.rpc.AddSubMenuResponse;
import com.smartdevicelink.proxy.rpc.AlertManeuverResponse;
import com.smartdevicelink.proxy.rpc.AlertResponse;
import com.smartdevicelink.proxy.rpc.ButtonPressResponse;
+import com.smartdevicelink.proxy.rpc.CancelInteractionResponse;
import com.smartdevicelink.proxy.rpc.ChangeRegistrationResponse;
import com.smartdevicelink.proxy.rpc.CloseApplicationResponse;
import com.smartdevicelink.proxy.rpc.CreateInteractionChoiceSetResponse;
+import com.smartdevicelink.proxy.rpc.CreateWindowResponse;
import com.smartdevicelink.proxy.rpc.DeleteCommandResponse;
import com.smartdevicelink.proxy.rpc.DeleteFileResponse;
import com.smartdevicelink.proxy.rpc.DeleteInteractionChoiceSetResponse;
import com.smartdevicelink.proxy.rpc.DeleteSubMenuResponse;
+import com.smartdevicelink.proxy.rpc.DeleteWindowResponse;
import com.smartdevicelink.proxy.rpc.DiagnosticMessageResponse;
import com.smartdevicelink.proxy.rpc.DialNumberResponse;
import com.smartdevicelink.proxy.rpc.EndAudioPassThruResponse;
@@ -59,6 +62,7 @@ import com.smartdevicelink.proxy.rpc.GetAppServiceDataResponse;
import com.smartdevicelink.proxy.rpc.GetCloudAppPropertiesResponse;
import com.smartdevicelink.proxy.rpc.GetDTCsResponse;
import com.smartdevicelink.proxy.rpc.GetFileResponse;
+import com.smartdevicelink.proxy.rpc.GetInteriorVehicleDataConsentResponse;
import com.smartdevicelink.proxy.rpc.GetInteriorVehicleDataResponse;
import com.smartdevicelink.proxy.rpc.GetSystemCapabilityResponse;
import com.smartdevicelink.proxy.rpc.GetVehicleDataResponse;
@@ -93,6 +97,7 @@ import com.smartdevicelink.proxy.rpc.PublishAppServiceResponse;
import com.smartdevicelink.proxy.rpc.PutFileResponse;
import com.smartdevicelink.proxy.rpc.ReadDIDResponse;
import com.smartdevicelink.proxy.rpc.RegisterAppInterfaceResponse;
+import com.smartdevicelink.proxy.rpc.ReleaseInteriorVehicleDataModuleResponse;
import com.smartdevicelink.proxy.rpc.ResetGlobalPropertiesResponse;
import com.smartdevicelink.proxy.rpc.ScrollableMessageResponse;
import com.smartdevicelink.proxy.rpc.SendHapticDataResponse;
@@ -103,6 +108,7 @@ import com.smartdevicelink.proxy.rpc.SetDisplayLayoutResponse;
import com.smartdevicelink.proxy.rpc.SetGlobalPropertiesResponse;
import com.smartdevicelink.proxy.rpc.SetInteriorVehicleDataResponse;
import com.smartdevicelink.proxy.rpc.SetMediaClockTimerResponse;
+import com.smartdevicelink.proxy.rpc.ShowAppMenuResponse;
import com.smartdevicelink.proxy.rpc.ShowConstantTbtResponse;
import com.smartdevicelink.proxy.rpc.ShowResponse;
import com.smartdevicelink.proxy.rpc.SliderResponse;
@@ -574,6 +580,16 @@ public class ProxyBridge implements IProxyListener{
}
@Override
+ public void onCreateWindowResponse(CreateWindowResponse response) {
+ onRPCReceived(response);
+ }
+
+ @Override
+ public void onDeleteWindowResponse(DeleteWindowResponse response) {
+ onRPCReceived(response);
+ }
+
+ @Override
public void onButtonPressResponse(ButtonPressResponse response) {
onRPCReceived(response);
@@ -609,7 +625,8 @@ public class ProxyBridge implements IProxyListener{
public void onGetCloudAppProperties(GetCloudAppPropertiesResponse response) {
onRPCReceived(response);
}
-@Override
+
+ @Override
public void onPublishAppServiceResponse(PublishAppServiceResponse response){
onRPCReceived(response);
}
@@ -635,6 +652,16 @@ public class ProxyBridge implements IProxyListener{
}
@Override
+ public void onGetInteriorVehicleDataConsentResponse(GetInteriorVehicleDataConsentResponse response) {
+ onRPCReceived(response);
+ }
+
+ @Override
+ public void onReleaseInteriorVehicleDataModuleResponse(ReleaseInteriorVehicleDataModuleResponse response) {
+ onRPCReceived(response);
+ }
+
+ @Override
public void onOnSystemCapabilityUpdated(OnSystemCapabilityUpdated notification){
onRPCReceived(notification);
}
@@ -645,6 +672,16 @@ public class ProxyBridge implements IProxyListener{
}
@Override
+ public void onCancelInteractionResponse(CancelInteractionResponse response) {
+ onRPCReceived(response);
+ }
+
+ @Override
+ public void onShowAppMenuResponse(ShowAppMenuResponse response) {
+ onRPCReceived(response);
+ }
+
+ @Override
public void onUnpublishAppServiceResponse(UnpublishAppServiceResponse response) {
onRPCReceived(response);
}
diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/managers/SdlManager.java b/android/sdl_android/src/main/java/com/smartdevicelink/managers/SdlManager.java
index d4eda9630..b4b66bfc5 100644
--- a/android/sdl_android/src/main/java/com/smartdevicelink/managers/SdlManager.java
+++ b/android/sdl_android/src/main/java/com/smartdevicelink/managers/SdlManager.java
@@ -35,6 +35,8 @@ package com.smartdevicelink.managers;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Build;
+import android.os.Handler;
+import android.os.Looper;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
@@ -43,6 +45,7 @@ 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.lifecycle.LifecycleConfigurationUpdate;
import com.smartdevicelink.managers.lockscreen.LockScreenConfig;
import com.smartdevicelink.managers.lockscreen.LockScreenManager;
import com.smartdevicelink.managers.permission.PermissionManager;
@@ -52,6 +55,7 @@ import com.smartdevicelink.protocol.enums.FunctionID;
import com.smartdevicelink.protocol.enums.SessionType;
import com.smartdevicelink.proxy.RPCMessage;
import com.smartdevicelink.proxy.RPCRequest;
+import com.smartdevicelink.proxy.RPCResponse;
import com.smartdevicelink.proxy.SdlProxyBase;
import com.smartdevicelink.proxy.SystemCapabilityManager;
import com.smartdevicelink.proxy.callbacks.OnServiceEnded;
@@ -61,6 +65,7 @@ import com.smartdevicelink.proxy.interfaces.ISdl;
import com.smartdevicelink.proxy.interfaces.ISdlServiceListener;
import com.smartdevicelink.proxy.interfaces.IVideoStreamListener;
import com.smartdevicelink.proxy.interfaces.OnSystemCapabilityListener;
+import com.smartdevicelink.proxy.rpc.ChangeRegistration;
import com.smartdevicelink.proxy.rpc.OnHMIStatus;
import com.smartdevicelink.proxy.rpc.RegisterAppInterfaceResponse;
import com.smartdevicelink.proxy.rpc.SdlMsgVersion;
@@ -69,12 +74,14 @@ import com.smartdevicelink.proxy.rpc.TTSChunk;
import com.smartdevicelink.proxy.rpc.TemplateColorScheme;
import com.smartdevicelink.proxy.rpc.enums.AppHMIType;
import com.smartdevicelink.proxy.rpc.enums.Language;
+import com.smartdevicelink.proxy.rpc.enums.Result;
import com.smartdevicelink.proxy.rpc.enums.SdlDisconnectedReason;
import com.smartdevicelink.proxy.rpc.enums.SystemCapabilityType;
import com.smartdevicelink.proxy.rpc.listeners.OnMultipleRequestListener;
import com.smartdevicelink.proxy.rpc.listeners.OnRPCListener;
import com.smartdevicelink.proxy.rpc.listeners.OnRPCNotificationListener;
import com.smartdevicelink.proxy.rpc.listeners.OnRPCRequestListener;
+import com.smartdevicelink.proxy.rpc.listeners.OnRPCResponseListener;
import com.smartdevicelink.security.SdlSecurityBase;
import com.smartdevicelink.streaming.audio.AudioStreamingCodec;
import com.smartdevicelink.streaming.audio.AudioStreamingParams;
@@ -86,6 +93,8 @@ import com.smartdevicelink.transport.utl.TransportRecord;
import com.smartdevicelink.util.DebugTool;
import com.smartdevicelink.util.Version;
+import org.json.JSONException;
+
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -126,12 +135,16 @@ public class SdlManager extends BaseSdlManager{
@Override
public void onProxyConnected() {
DebugTool.logInfo("Proxy is connected. Now initializing.");
+ changeRegistrationRetry = 0;
+ checkLifecycleConfiguration();
initialize();
}
@Override
public void onProxyClosed(String info, Exception e, SdlDisconnectedReason reason){
- dispose();
+ if (!reason.equals(SdlDisconnectedReason.LANGUAGE_CHANGE)){
+ dispose();
+ }
}
@Override
@@ -226,6 +239,71 @@ public class SdlManager extends BaseSdlManager{
}
@Override
+ protected void checkLifecycleConfiguration(){
+ final Language actualLanguage = this.getRegisterAppInterfaceResponse().getLanguage();
+
+ if (!actualLanguage.equals(hmiLanguage)) {
+
+ final LifecycleConfigurationUpdate lcu = managerListener.managerShouldUpdateLifecycle(actualLanguage);
+
+ if (lcu != null) {
+ ChangeRegistration changeRegistration = new ChangeRegistration(actualLanguage, actualLanguage);
+ changeRegistration.setAppName(lcu.getAppName());
+ changeRegistration.setNgnMediaScreenAppName(lcu.getShortAppName());
+ changeRegistration.setTtsName(lcu.getTtsName());
+ changeRegistration.setVrSynonyms(lcu.getVoiceRecognitionCommandNames());
+ changeRegistration.setOnRPCResponseListener(new OnRPCResponseListener() {
+ @Override
+ public void onResponse(int correlationId, RPCResponse response) {
+ if (response.getSuccess()){
+ // go through and change sdlManager properties that were changed via the LCU update
+ hmiLanguage = actualLanguage;
+
+ if (lcu.getAppName() != null) {
+ appName = lcu.getAppName();
+ }
+
+ if (lcu.getShortAppName() != null) {
+ shortAppName = lcu.getShortAppName();
+ }
+
+ if (lcu.getTtsName() != null) {
+ ttsChunks = lcu.getTtsName();
+ }
+
+ if (lcu.getVoiceRecognitionCommandNames() != null) {
+ vrSynonyms = lcu.getVoiceRecognitionCommandNames();
+ }
+ }
+ try {
+ DebugTool.logInfo(response.serializeJSON().toString());
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void onError(int correlationId, Result resultCode, String info) {
+ DebugTool.logError("Change Registration onError: " + resultCode + " | Info: " + info);
+ changeRegistrationRetry++;
+ if (changeRegistrationRetry < MAX_RETRY) {
+ final Handler handler = new Handler(Looper.getMainLooper());
+ handler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ checkLifecycleConfiguration();
+ DebugTool.logInfo("Retry Change Registration Count: " + changeRegistrationRetry);
+ }
+ }, 3000);
+ }
+ }
+ });
+ this.sendRPC(changeRegistration);
+ }
+ }
+ }
+
+ @Override
protected void initialize(){
// Instantiate sub managers
this.permissionManager = new PermissionManager(_internalInterface);
diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/managers/SdlManagerListener.java b/android/sdl_android/src/main/java/com/smartdevicelink/managers/SdlManagerListener.java
index 5a59604cc..d27ac27b5 100644
--- a/android/sdl_android/src/main/java/com/smartdevicelink/managers/SdlManagerListener.java
+++ b/android/sdl_android/src/main/java/com/smartdevicelink/managers/SdlManagerListener.java
@@ -32,6 +32,9 @@
package com.smartdevicelink.managers;
+import com.smartdevicelink.managers.lifecycle.LifecycleConfigurationUpdate;
+import com.smartdevicelink.proxy.rpc.enums.Language;
+
public interface SdlManagerListener extends BaseSdlManagerListener{
/**
@@ -50,4 +53,17 @@ public interface SdlManagerListener extends BaseSdlManagerListener{
* @param e the exception
*/
void onError(String info, Exception e);
+
+ /**
+ * Called when the SDL manager detected a language mismatch. In case of a language mismatch the
+ * manager should change the apps registration by updating the lifecycle configuration to the
+ * specified language. If the app can support the specified language it should return an Object
+ * of LifecycleConfigurationUpdate, otherwise it should return null to indicate that the language
+ * is not supported.
+ *
+ * @param language The language of the connected head unit the manager is trying to update the configuration.
+ * @return An object of LifecycleConfigurationUpdate if the head unit language is supported,
+ * otherwise null to indicate that the language is not supported.
+ */
+ LifecycleConfigurationUpdate managerShouldUpdateLifecycle(Language language);
}
diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/managers/audio/AudioStreamManager.java b/android/sdl_android/src/main/java/com/smartdevicelink/managers/audio/AudioStreamManager.java
index 857b26b92..55bff7bba 100644
--- a/android/sdl_android/src/main/java/com/smartdevicelink/managers/audio/AudioStreamManager.java
+++ b/android/sdl_android/src/main/java/com/smartdevicelink/managers/audio/AudioStreamManager.java
@@ -56,6 +56,7 @@ 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.PredefinedWindows;
import com.smartdevicelink.proxy.rpc.enums.SystemCapabilityType;
import com.smartdevicelink.proxy.rpc.listeners.OnRPCNotificationListener;
import com.smartdevicelink.transport.utl.TransportRecord;
@@ -160,7 +161,11 @@ public class AudioStreamManager extends BaseAudioStreamManager {
@Override
public void onNotified(RPCNotification notification) {
if(notification != null){
- hmiLevel = ((OnHMIStatus)notification).getHmiLevel();
+ OnHMIStatus onHMIStatus = (OnHMIStatus)notification;
+ if (onHMIStatus.getWindowID() != null && onHMIStatus.getWindowID() != PredefinedWindows.DEFAULT_WINDOW.getValue()) {
+ return;
+ }
+ hmiLevel = onHMIStatus.getHmiLevel();
if(hmiLevel.equals(HMILevel.HMI_FULL) || hmiLevel.equals(HMILevel.HMI_LIMITED)){
checkState();
}
diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/managers/lockscreen/LockScreenConfig.java b/android/sdl_android/src/main/java/com/smartdevicelink/managers/lockscreen/LockScreenConfig.java
index c5c0027ad..6769db0fc 100644
--- a/android/sdl_android/src/main/java/com/smartdevicelink/managers/lockscreen/LockScreenConfig.java
+++ b/android/sdl_android/src/main/java/com/smartdevicelink/managers/lockscreen/LockScreenConfig.java
@@ -32,6 +32,11 @@
package com.smartdevicelink.managers.lockscreen;
+import android.support.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* <strong>LockScreenConfig</strong> <br>
*
@@ -47,16 +52,39 @@ package com.smartdevicelink.managers.lockscreen;
* <li> customView - If you would like to provide your own view, you can pass it in here.</li>
*
* <li> deviceLogo - On by default. If available, will show the device or OEMs logo on the lockscreen</li>
+ *
+ * <li> displayMode - Describes when the lock screen will be displayed. Defaults to `DISPLAY_MODE_REQUIRED_ONLY`.</li>
+ *
+ * <li> enableDismissGesture - If true, then the lock screen can be dismissed with a downward swipe on compatible head units.
+ * Requires a connection of SDL 6.0+ and the head unit to enable the feature. Defaults to true.</li>
*/
public class LockScreenConfig {
- private boolean enable, deviceLogo;
+ private boolean enable, deviceLogo, enableDismissGesture;
private int backgroundColor, appIconInt, customViewInt;
+ private @DisplayMode int displayMode;
+
+ /**
+ * DISPLAY_MODE_NEVER - The lock screen should never be shown. This should almost always mean that you will build your own lock screen.
+ * DISPLAY_MODE_REQUIRED_ONLY - The lock screen should only be shown when it is required by the head unit.
+ * DISPLAY_MODE_OPTIONAL_OR_REQUIRED - The lock screen should be shown when required by the head unit or when the head unit says that
+ * its optional, but *not* in other cases, such as before the user has interacted with your app on the head unit.
+ * DISPLAY_MODE_ALWAYS - The lock screen should always be shown after connection.
+ */
+ @IntDef({DISPLAY_MODE_NEVER, DISPLAY_MODE_REQUIRED_ONLY, DISPLAY_MODE_OPTIONAL_OR_REQUIRED, DISPLAY_MODE_ALWAYS})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface DisplayMode {}
+ public static final int DISPLAY_MODE_NEVER = 0;
+ public static final int DISPLAY_MODE_REQUIRED_ONLY = 1;
+ public static final int DISPLAY_MODE_OPTIONAL_OR_REQUIRED = 2;
+ public static final int DISPLAY_MODE_ALWAYS = 3;
public LockScreenConfig(){
// set default values
this.enable = true;
this.deviceLogo = true;
+ this.displayMode = DISPLAY_MODE_REQUIRED_ONLY;
+ this.enableDismissGesture = true;
}
/**
@@ -64,7 +92,10 @@ public class LockScreenConfig {
*
* If false, you must manage the lock screen
* @param enable boolean
+ *
+ * @deprecated to disable the lockscreen, use setDisplayMode with DISPLAY_MODE_NEVER instead
*/
+ @Deprecated
public void setEnabled(boolean enable){
this.enable = enable;
}
@@ -72,7 +103,10 @@ public class LockScreenConfig {
/**
* Gets whether the lock screen is being managed for you
* @return boolean
+ *
+ * @deprecated to disable the lockscreen, use setDisplayMode with DISPLAY_MODE_NEVER instead
*/
+ @Deprecated
public boolean isEnabled() {
return enable;
}
@@ -145,4 +179,39 @@ public class LockScreenConfig {
return deviceLogo;
}
+
+ /**
+ * Set the displayMode to be used
+ * @param displayMode - Describes when the lock screen will be displayed. Defaults to `DISPLAY_MODE_REQUIRED_ONLY`.
+ */
+ public void setDisplayMode(@DisplayMode int displayMode){
+ this.displayMode = displayMode;
+ }
+
+ /**
+ * Get the displayMode to be used
+ * @return displayMode - Describes when the lock screen will be displayed. Defaults to `DISPLAY_MODE_REQUIRED_ONLY`.
+ */
+ public @DisplayMode int getDisplayMode(){
+ return this.displayMode;
+ }
+
+ /**
+ * If true, then the lock screen can be dismissed with a downward swipe on compatible head units.
+ * Requires a connection of SDL 6.0+ and the head unit to enable the feature. Defaults to true.
+ * @param enableDismissGesture - enable or disable this feature
+ */
+ public void enableDismissGesture(boolean enableDismissGesture) {
+ this.enableDismissGesture = enableDismissGesture;
+ }
+
+ /**
+ * If true, then the lock screen can be dismissed with a downward swipe on compatible head units.
+ * Requires a connection of SDL 6.0+ and the head unit to enable the feature. Defaults to true.
+ * @return - whether or not this is enabled or disabled
+ */
+ public boolean enableDismissGesture() {
+ return enableDismissGesture;
+ }
+
}
diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/managers/lockscreen/LockScreenManager.java b/android/sdl_android/src/main/java/com/smartdevicelink/managers/lockscreen/LockScreenManager.java
index 43e40be6c..30ed1b575 100644
--- a/android/sdl_android/src/main/java/com/smartdevicelink/managers/lockscreen/LockScreenManager.java
+++ b/android/sdl_android/src/main/java/com/smartdevicelink/managers/lockscreen/LockScreenManager.java
@@ -32,8 +32,10 @@
package com.smartdevicelink.managers.lockscreen;
+import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.os.Build;
import android.util.Log;
@@ -49,6 +51,7 @@ import com.smartdevicelink.proxy.rpc.OnSystemRequest;
import com.smartdevicelink.proxy.rpc.enums.DriverDistractionState;
import com.smartdevicelink.proxy.rpc.enums.HMILevel;
import com.smartdevicelink.proxy.rpc.enums.LockScreenStatus;
+import com.smartdevicelink.proxy.rpc.enums.PredefinedWindows;
import com.smartdevicelink.proxy.rpc.enums.RequestType;
import com.smartdevicelink.proxy.rpc.listeners.OnRPCNotificationListener;
import com.smartdevicelink.util.AndroidTools;
@@ -68,15 +71,17 @@ public class LockScreenManager extends BaseSubManager {
private static final String TAG = "LockScreenManager";
private WeakReference<Context> context;
- private HMILevel hmiLevel;
+ HMILevel hmiLevel;
private OnRPCNotificationListener systemRequestListener, ddListener, hmiListener;
private String deviceIconUrl;
- private boolean driverDistStatus;
+ boolean driverDistStatus, mIsLockscreenDismissible, enableDismissGesture, lockScreenEnabled, deviceLogoEnabled;
private volatile boolean isApplicationForegrounded;
private android.arch.lifecycle.LifecycleObserver lifecycleObserver;
- protected boolean lockScreenEnabled, deviceLogoEnabled;
- protected int lockScreenIcon, lockScreenColor, customView;
- protected Bitmap deviceLogo;
+ int lockScreenIcon, lockScreenColor, customView, displayMode;
+ Bitmap deviceLogo;
+ private boolean mLockScreenHasBeenDismissed, lockscreenDismissReceiverRegistered, receivedFirstDDNotification;
+ private String mLockscreenWarningMsg;
+ private BroadcastReceiver mLockscreenDismissedReceiver;
public LockScreenManager(LockScreenConfig lockScreenConfig, Context context, ISdl internalInterface){
@@ -93,6 +98,14 @@ public class LockScreenManager extends BaseSubManager {
customView = lockScreenConfig.getCustomView();
lockScreenEnabled = lockScreenConfig.isEnabled();
deviceLogoEnabled = lockScreenConfig.isDeviceLogoEnabled();
+ displayMode = lockScreenConfig.getDisplayMode();
+ enableDismissGesture = lockScreenConfig.enableDismissGesture();
+
+ // for older projects that may not use DisplayMode. This can
+ // be removed in a major release
+ if (!lockScreenEnabled){
+ displayMode = LockScreenConfig.DISPLAY_MODE_NEVER;
+ }
setupListeners();
}
@@ -108,6 +121,12 @@ public class LockScreenManager extends BaseSubManager {
// send broadcast to close lock screen if open
if (context.get() != null) {
context.get().sendBroadcast(new Intent(SDLLockScreenActivity.CLOSE_LOCK_SCREEN_ACTION));
+ try {
+ context.get().unregisterReceiver(mLockscreenDismissedReceiver);
+ lockscreenDismissReceiverRegistered = false;
+ } catch (IllegalArgumentException e) {
+ //do nothing
+ }
}
// remove listeners
internalInterface.removeOnRPCNotificationListener(FunctionID.ON_HMI_STATUS, hmiListener);
@@ -153,7 +172,11 @@ public class LockScreenManager extends BaseSubManager {
hmiListener = new OnRPCNotificationListener() {
@Override
public void onNotified(RPCNotification notification) {
- hmiLevel = ((OnHMIStatus)notification).getHmiLevel();
+ OnHMIStatus onHMIStatus = (OnHMIStatus)notification;
+ if (onHMIStatus.getWindowID() != null && onHMIStatus.getWindowID() != PredefinedWindows.DEFAULT_WINDOW.getValue()) {
+ return;
+ }
+ hmiLevel = onHMIStatus.getHmiLevel();
launchLockScreenActivity();
}
};
@@ -166,6 +189,22 @@ public class LockScreenManager extends BaseSubManager {
// do something with the status
if (notification != null) {
OnDriverDistraction ddState = (OnDriverDistraction) notification;
+ Boolean isDismissible = ddState.getLockscreenDismissibility();
+ Log.i(TAG, "Lock screen dismissible: "+ isDismissible);
+ if (isDismissible != null) {
+ // both of these conditions must be met to be able to dismiss lockscreen
+ if (isDismissible && enableDismissGesture){
+ mIsLockscreenDismissible = true;
+
+ // if DisplayMode is set to ALWAYS, it will be shown before the first DD notification.
+ // If this is our first DD notification and we are in ALWAYS mode, send another intent to
+ // enable the dismissal
+ if (!receivedFirstDDNotification && displayMode == LockScreenConfig.DISPLAY_MODE_ALWAYS ){
+ launchLockScreenActivity();
+ }
+ }
+ }
+ mLockscreenWarningMsg = ddState.getLockscreenWarningMessage();
if (ddState.getState() == DriverDistractionState.DD_ON){
// launch lock screen
@@ -174,10 +213,9 @@ public class LockScreenManager extends BaseSubManager {
}else{
// close lock screen
driverDistStatus = false;
- if (context.get() != null) {
- context.get().sendBroadcast(new Intent(SDLLockScreenActivity.CLOSE_LOCK_SCREEN_ACTION));
- }
+ closeLockScreenActivity();
}
+ receivedFirstDDNotification = true;
}
}
};
@@ -226,6 +264,15 @@ public class LockScreenManager extends BaseSubManager {
} else{
isApplicationForegrounded = true;
}
+
+ mLockscreenDismissedReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (SDLLockScreenActivity.KEY_LOCKSCREEN_DISMISSED.equals(intent.getAction())) {
+ mLockScreenHasBeenDismissed = true;
+ }
+ }
+ };
}
////
@@ -240,11 +287,20 @@ public class LockScreenManager extends BaseSubManager {
* X. If the status is set to OFF, Send broadcast to close lock screen if it is open
*/
private void launchLockScreenActivity(){
+ // If the user has dismissed the lockscreen for this run or has disabled it, do not show it
+ if (mLockScreenHasBeenDismissed || displayMode == LockScreenConfig.DISPLAY_MODE_NEVER) {
+ return;
+ }
// intent to open SDLLockScreenActivity
// pass in icon, background color, and custom view
if (lockScreenEnabled && isApplicationForegrounded && context.get() != null) {
+ if (mIsLockscreenDismissible && !lockscreenDismissReceiverRegistered) {
+ context.get().registerReceiver(mLockscreenDismissedReceiver, new IntentFilter(SDLLockScreenActivity.KEY_LOCKSCREEN_DISMISSED));
+ lockscreenDismissReceiverRegistered = true;
+
+ }
LockScreenStatus status = getLockScreenStatus();
- if (status == LockScreenStatus.REQUIRED) {
+ if (status == LockScreenStatus.REQUIRED || displayMode == LockScreenConfig.DISPLAY_MODE_ALWAYS || (status == LockScreenStatus.OPTIONAL && displayMode == LockScreenConfig.DISPLAY_MODE_OPTIONAL_OR_REQUIRED)) {
Intent showLockScreenIntent = new Intent(context.get(), SDLLockScreenActivity.class);
showLockScreenIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
@@ -254,8 +310,24 @@ public class LockScreenManager extends BaseSubManager {
showLockScreenIntent.putExtra(SDLLockScreenActivity.LOCKSCREEN_CUSTOM_VIEW_EXTRA, customView);
showLockScreenIntent.putExtra(SDLLockScreenActivity.LOCKSCREEN_DEVICE_LOGO_EXTRA, deviceLogoEnabled);
showLockScreenIntent.putExtra(SDLLockScreenActivity.LOCKSCREEN_DEVICE_LOGO_BITMAP, deviceLogo);
+ showLockScreenIntent.putExtra(SDLLockScreenActivity.KEY_LOCKSCREEN_DISMISSIBLE, mIsLockscreenDismissible);
+ showLockScreenIntent.putExtra(SDLLockScreenActivity.KEY_LOCKSCREEN_WARNING_MSG, mLockscreenWarningMsg);
context.get().startActivity(showLockScreenIntent);
} else if (status == LockScreenStatus.OFF) {
+ closeLockScreenActivity();
+ }
+ }
+ }
+
+ private void closeLockScreenActivity(){
+
+ if (displayMode == LockScreenConfig.DISPLAY_MODE_ALWAYS){
+ return;
+ }
+
+ if (context.get() != null) {
+ LockScreenStatus status = getLockScreenStatus();
+ if (status == LockScreenStatus.OFF || (status == LockScreenStatus.OPTIONAL && displayMode != LockScreenConfig.DISPLAY_MODE_OPTIONAL_OR_REQUIRED)) {
context.get().sendBroadcast(new Intent(SDLLockScreenActivity.CLOSE_LOCK_SCREEN_ACTION));
}
}
@@ -271,9 +343,9 @@ public class LockScreenManager extends BaseSubManager {
*
* @return Whether or not the Lock Screen is required
*/
- protected synchronized LockScreenStatus getLockScreenStatus() {
+ synchronized LockScreenStatus getLockScreenStatus() {
- if ( (hmiLevel == null) || (hmiLevel.equals(HMILevel.HMI_NONE))) {
+ if ((hmiLevel == null) || (hmiLevel.equals(HMILevel.HMI_NONE))) {
return LockScreenStatus.OFF;
}
else if ( hmiLevel.equals(HMILevel.HMI_BACKGROUND)) {
@@ -284,7 +356,7 @@ public class LockScreenManager extends BaseSubManager {
return LockScreenStatus.REQUIRED;
}
}
- else if ( (hmiLevel.equals(HMILevel.HMI_FULL)) || (hmiLevel.equals(HMILevel.HMI_LIMITED))) {
+ else if ((hmiLevel.equals(HMILevel.HMI_FULL)) || (hmiLevel.equals(HMILevel.HMI_LIMITED))) {
if (!driverDistStatus) {
return LockScreenStatus.OPTIONAL;
} else {
diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/managers/lockscreen/SDLLockScreenActivity.java b/android/sdl_android/src/main/java/com/smartdevicelink/managers/lockscreen/SDLLockScreenActivity.java
index 6ae10ec73..d87d27ca2 100644
--- a/android/sdl_android/src/main/java/com/smartdevicelink/managers/lockscreen/SDLLockScreenActivity.java
+++ b/android/sdl_android/src/main/java/com/smartdevicelink/managers/lockscreen/SDLLockScreenActivity.java
@@ -39,9 +39,12 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.os.Bundle;
+import android.view.GestureDetector;
+import android.view.MotionEvent;
import android.view.Window;
import android.widget.ImageView;
import android.widget.RelativeLayout;
+import android.widget.TextView;
import com.smartdevicelink.R;
@@ -55,6 +58,12 @@ public class SDLLockScreenActivity extends Activity {
public static final String LOCKSCREEN_CUSTOM_VIEW_EXTRA = "LOCKSCREEN_CUSTOM_VIEW_EXTRA";
public static final String LOCKSCREEN_DEVICE_LOGO_DOWNLOADED = "LOCKSCREEN_DEVICE_LOGO_DOWNLOADED";
public static final String CLOSE_LOCK_SCREEN_ACTION = "CLOSE_LOCK_SCREEN";
+ public static final String KEY_LOCKSCREEN_DISMISSED = "KEY_LOCKSCREEN_DISMISSED";
+ public static final String KEY_LOCKSCREEN_DISMISSIBLE = "KEY_LOCKSCREEN_DISMISSIBLE";
+ public static final String KEY_LOCKSCREEN_WARNING_MSG = "KEY_LOCKSCREEN_WARNING_MSG";
+ private static final int MIN_SWIPE_DISTANCE = 200;
+ private boolean mIsDismissible;
+ private GestureDetector mGestureDetector;
private final BroadcastReceiver lockScreenBroadcastReceiver = new BroadcastReceiver() {
@Override
@@ -81,6 +90,7 @@ public class SDLLockScreenActivity extends Activity {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
+ mGestureDetector = new GestureDetector(this, new SwipeUpGestureListener());
// set any parameters that came from the lock screen manager
initializeActivity(getIntent());
@@ -94,6 +104,14 @@ public class SDLLockScreenActivity extends Activity {
}
@Override
+ public boolean onTouchEvent(MotionEvent event) {
+ if (mIsDismissible) {
+ return mGestureDetector.onTouchEvent(event);
+ }
+ return super.onTouchEvent(event);
+ }
+
+ @Override
protected void onDestroy() {
unregisterReceiver(lockScreenBroadcastReceiver);
super.onDestroy();
@@ -107,6 +125,9 @@ public class SDLLockScreenActivity extends Activity {
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
+ if (intent != null && intent.getBooleanExtra(KEY_LOCKSCREEN_DISMISSIBLE, false)){
+ initializeActivity(intent);
+ }
}
public void initializeActivity(Intent intent){
@@ -133,6 +154,11 @@ public class SDLLockScreenActivity extends Activity {
if (deviceLogoEnabled && deviceIcon != null){
setDeviceLogo(deviceIcon);
}
+ mIsDismissible = intent.getBooleanExtra(KEY_LOCKSCREEN_DISMISSIBLE, false);
+ String warningMsg = intent.getStringExtra(KEY_LOCKSCREEN_WARNING_MSG);
+ if (mIsDismissible) {
+ setLockscreenWarningMessage(warningMsg);
+ }
}
}
}
@@ -154,8 +180,26 @@ public class SDLLockScreenActivity extends Activity {
}
}
+ private void setLockscreenWarningMessage(String msg) {
+ TextView tv = findViewById(R.id.lockscreen_text);
+ if (tv != null) {
+ tv.setText(msg != null ? msg : getString(R.string.default_lockscreen_warning_message));
+ }
+ }
+
private void setCustomView(int customView) {
setContentView(customView);
}
+ private class SwipeUpGestureListener extends GestureDetector.SimpleOnGestureListener {
+ @Override
+ public boolean onFling(MotionEvent event1, MotionEvent event2,
+ float velocityX, float velocityY) {
+ if ((event2.getY() - event1.getY()) > MIN_SWIPE_DISTANCE) {
+ sendBroadcast(new Intent(KEY_LOCKSCREEN_DISMISSED));
+ finish();
+ }
+ return true;
+ }
+ }
}
diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/managers/video/VideoStreamManager.java b/android/sdl_android/src/main/java/com/smartdevicelink/managers/video/VideoStreamManager.java
index 49798078c..73065b865 100644
--- a/android/sdl_android/src/main/java/com/smartdevicelink/managers/video/VideoStreamManager.java
+++ b/android/sdl_android/src/main/java/com/smartdevicelink/managers/video/VideoStreamManager.java
@@ -62,6 +62,7 @@ import com.smartdevicelink.proxy.rpc.TouchCoord;
import com.smartdevicelink.proxy.rpc.TouchEvent;
import com.smartdevicelink.proxy.rpc.VideoStreamingCapability;
import com.smartdevicelink.proxy.rpc.enums.HMILevel;
+import com.smartdevicelink.proxy.rpc.enums.PredefinedWindows;
import com.smartdevicelink.proxy.rpc.enums.SystemCapabilityType;
import com.smartdevicelink.proxy.rpc.enums.TouchType;
import com.smartdevicelink.proxy.rpc.listeners.OnRPCNotificationListener;
@@ -92,6 +93,7 @@ public class VideoStreamManager extends BaseVideoStreamManager {
private VideoStreamingParameters parameters;
private IVideoStreamListener streamListener;
private boolean isTransportAvailable = false;
+ private boolean hasStarted;
// INTERNAL INTERFACES
@@ -114,8 +116,7 @@ public class VideoStreamManager extends BaseVideoStreamManager {
}
startEncoder();
stateMachine.transitionToState(StreamingStateMachine.STARTED);
-
-
+ hasStarted = true;
}
}
@@ -140,7 +141,11 @@ public class VideoStreamManager extends BaseVideoStreamManager {
@Override
public void onNotified(RPCNotification notification) {
if(notification != null){
- hmiLevel = ((OnHMIStatus)notification).getHmiLevel();
+ OnHMIStatus onHMIStatus = (OnHMIStatus)notification;
+ if (onHMIStatus.getWindowID() != null && onHMIStatus.getWindowID() != PredefinedWindows.DEFAULT_WINDOW.getValue()) {
+ return;
+ }
+ hmiLevel = onHMIStatus.getHmiLevel();
if(hmiLevel.equals(HMILevel.HMI_FULL)){
checkState();
}
@@ -194,6 +199,7 @@ public class VideoStreamManager extends BaseVideoStreamManager {
&& hmiLevel != null
&& hmiLevel.equals(HMILevel.HMI_FULL)
&& parameters != null){
+ stateMachine.transitionToState(StreamingStateMachine.READY);
transitionToState(READY);
}
}
@@ -310,6 +316,7 @@ public class VideoStreamManager extends BaseVideoStreamManager {
//Encoder should be up and running
createRemoteDisplay(virtualDisplayEncoder.getVirtualDisplay());
stateMachine.transitionToState(StreamingStateMachine.STARTED);
+ hasStarted = true;
} catch (Exception e) {
stateMachine.transitionToState(StreamingStateMachine.ERROR);
e.printStackTrace();
@@ -384,8 +391,7 @@ public class VideoStreamManager extends BaseVideoStreamManager {
* @return boolean (true = yes, false = no)
*/
public boolean isStreaming(){
- return (stateMachine.getState() == StreamingStateMachine.STARTED) ||
- (hmiLevel == HMILevel.HMI_FULL);
+ return (stateMachine.getState() == StreamingStateMachine.STARTED) && (hmiLevel == HMILevel.HMI_FULL);
}
/**
@@ -393,8 +399,7 @@ public class VideoStreamManager extends BaseVideoStreamManager {
* @return boolean (true = not paused, false = paused)
*/
public boolean isPaused(){
- return (stateMachine.getState() == StreamingStateMachine.STARTED) ||
- (hmiLevel != HMILevel.HMI_FULL);
+ return (hasStarted && stateMachine.getState() == StreamingStateMachine.STOPPED) || (hmiLevel != HMILevel.HMI_FULL);
}
/**
@@ -451,9 +456,8 @@ public class VideoStreamManager extends BaseVideoStreamManager {
if(resolution != null){
DisplayMetrics displayMetrics = new DisplayMetrics();
disp.getMetrics(displayMetrics);
- touchScalar[0] = ((float)displayMetrics.widthPixels) / resolution.getResolutionWidth();
- touchScalar[1] = ((float)displayMetrics.heightPixels) / resolution.getResolutionHeight();
- }
+ createTouchScalar(resolution, displayMetrics);
+ }
}
@@ -499,6 +503,11 @@ public class VideoStreamManager extends BaseVideoStreamManager {
}
}
+ void createTouchScalar(ImageResolution resolution, DisplayMetrics displayMetrics) {
+ touchScalar[0] = ((float)displayMetrics.widthPixels) / resolution.getResolutionWidth();
+ touchScalar[1] = ((float)displayMetrics.heightPixels) / resolution.getResolutionHeight();
+ }
+
List<MotionEvent> convertTouchEvent(OnTouchEvent onTouchEvent){
List<MotionEvent> motionEventList = new ArrayList<MotionEvent>();
@@ -677,4 +686,4 @@ public class VideoStreamManager extends BaseVideoStreamManager {
}
}
-} \ No newline at end of file
+}
diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/protocol/SdlProtocol.java b/android/sdl_android/src/main/java/com/smartdevicelink/protocol/SdlProtocol.java
index c06709b52..c443abfc6 100644
--- a/android/sdl_android/src/main/java/com/smartdevicelink/protocol/SdlProtocol.java
+++ b/android/sdl_android/src/main/java/com/smartdevicelink/protocol/SdlProtocol.java
@@ -36,7 +36,12 @@ import android.support.annotation.NonNull;
import com.smartdevicelink.protocol.enums.SessionType;
import com.smartdevicelink.transport.MultiplexTransportConfig;
+import com.smartdevicelink.transport.TCPTransportConfig;
+import com.smartdevicelink.transport.TCPTransportManager;
import com.smartdevicelink.transport.TransportManager;
+import com.smartdevicelink.transport.enums.TransportType;
+
+import java.util.Collections;
@SuppressWarnings("WeakerAccess")
@@ -54,17 +59,26 @@ public class SdlProtocol extends SdlProtocolBase {
}
+ public SdlProtocol(@NonNull ISdlProtocol iSdlProtocol, @NonNull TCPTransportConfig config) {
+ super(iSdlProtocol,config);
+ this.requestedPrimaryTransports = Collections.singletonList(TransportType.TCP);
+ this.requestedSecondaryTransports = null;
+ this.requiresHighBandwidth =false;
+ this.setTransportManager(new TCPTransportManager(config,transportEventListener));
+ }
+
/**
* If there was a TransportListener attached to the supplied multiplex config, this method will
* call the onTransportEvent method.
*/
@Override
void notifyDevTransportListener (){
- MultiplexTransportConfig transportConfig = (MultiplexTransportConfig)this.transportConfig;
- if(transportConfig.getTransportListener() != null && transportManager != null) {
- transportConfig.getTransportListener().onTransportEvent(transportManager.getConnectedTransports(), isTransportForServiceAvailable(SessionType.PCM),isTransportForServiceAvailable(SessionType.NAV));
+ if(TransportType.MULTIPLEX.equals(transportConfig.getTransportType() )) {
+ MultiplexTransportConfig transportConfig = (MultiplexTransportConfig) this.transportConfig;
+ if (transportConfig.getTransportListener() != null && transportManager != null) {
+ transportConfig.getTransportListener().onTransportEvent(transportManager.getConnectedTransports(), isTransportForServiceAvailable(SessionType.PCM), isTransportForServiceAvailable(SessionType.NAV));
+ }
}
}
-
}
diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/proxy/LockScreenManager.java b/android/sdl_android/src/main/java/com/smartdevicelink/proxy/LockScreenManager.java
index 76f92487f..d94372740 100644
--- a/android/sdl_android/src/main/java/com/smartdevicelink/proxy/LockScreenManager.java
+++ b/android/sdl_android/src/main/java/com/smartdevicelink/proxy/LockScreenManager.java
@@ -1,34 +1,34 @@
-/*
- * Copyright (c) 2017 - 2019, SmartDeviceLink Consortium, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided with the
- * distribution.
- *
- * Neither the name of the SmartDeviceLink Consortium, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
+/*
+ * Copyright (c) 2017 - 2019, SmartDeviceLink Consortium, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of the SmartDeviceLink Consortium, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
package com.smartdevicelink.proxy;
import android.graphics.Bitmap;
@@ -40,6 +40,7 @@ import com.smartdevicelink.util.AndroidTools;
import java.io.IOException;
+@Deprecated
public class LockScreenManager {
public interface OnLockScreenIconDownloadedListener{
diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/proxy/SdlProxyALM.java b/android/sdl_android/src/main/java/com/smartdevicelink/proxy/SdlProxyALM.java
index a48376751..763c139e9 100644
--- a/android/sdl_android/src/main/java/com/smartdevicelink/proxy/SdlProxyALM.java
+++ b/android/sdl_android/src/main/java/com/smartdevicelink/proxy/SdlProxyALM.java
@@ -1,34 +1,34 @@
-/*
- * Copyright (c) 2017 - 2019, SmartDeviceLink Consortium, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided with the
- * distribution.
- *
- * Neither the name of the SmartDeviceLink Consortium, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
+/*
+ * Copyright (c) 2017 - 2019, SmartDeviceLink Consortium, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of the SmartDeviceLink Consortium, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
package com.smartdevicelink.proxy;
import android.app.Service;
@@ -67,7 +67,13 @@ import java.util.Vector;
import static com.smartdevicelink.proxy.SystemCapabilityManager.convertToList;
-
+/**
+ * @deprecated use {@link com.smartdevicelink.managers.SdlManager} instead.
+ *
+ * The guide created for the initial transition of SdlProxyBase/ALM to SdlManager can be found at
+ * <a href="https://smartdevicelink.com/en/guides/android/migrating-to-newer-sdl-versions/updating-to-v47/">Migrating to SDL Manager</a>
+ */
+@Deprecated
public class SdlProxyALM extends SdlProxyBase<IProxyListenerALM> {
private static final String SDL_LIB_TRACE_KEY = "42baba60-eb57-11df-98cf-0800200c9a66";
diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/proxy/SdlProxyBase.java b/android/sdl_android/src/main/java/com/smartdevicelink/proxy/SdlProxyBase.java
index b7d81716b..ec6c751b8 100644
--- a/android/sdl_android/src/main/java/com/smartdevicelink/proxy/SdlProxyBase.java
+++ b/android/sdl_android/src/main/java/com/smartdevicelink/proxy/SdlProxyBase.java
@@ -123,6 +123,7 @@ import com.smartdevicelink.trace.enums.InterfaceActivityDirection;
import com.smartdevicelink.transport.BaseTransportConfig;
import com.smartdevicelink.transport.MultiplexTransportConfig;
import com.smartdevicelink.transport.SiphonServer;
+import com.smartdevicelink.transport.TCPTransportConfig;
import com.smartdevicelink.transport.USBTransportConfig;
import com.smartdevicelink.transport.enums.TransportType;
import com.smartdevicelink.util.CorrelationIdGenerator;
@@ -158,8 +159,14 @@ import java.util.concurrent.FutureTask;
import java.util.concurrent.ScheduledExecutorService;
-
+/**
+ * @deprecated use {@link com.smartdevicelink.managers.SdlManager} instead.
+ *
+ * The guide created for the initial transition of SdlProxyBase to SdlManager can be found at
+ * <a href="https://smartdevicelink.com/en/guides/android/migrating-to-newer-sdl-versions/updating-to-v47/">Migrating to SDL Manager</a>
+ */
@SuppressWarnings({"WeakerAccess", "Convert2Diamond"})
+@Deprecated
public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase> {
// Used for calls to Android Log class.
public static final String TAG = "SdlProxy";
@@ -246,6 +253,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase>
private OnSystemRequest lockScreenIconRequest = null;
private TelephonyManager telephonyManager = null;
private DeviceInfo deviceInfo = null;
+ private ISdlServiceListener navServiceListener;
/**
* Contains current configuration for the transport that was selected during
@@ -342,6 +350,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase>
if(isConnected()){
sdlSession.setDesiredVideoParams(parameters);
sdlSession.startService(SessionType.NAV,sdlSession.getSessionId(),encrypted);
+ addNavListener();
}
}
@@ -540,13 +549,13 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase>
@Override
public void onTransportDisconnected(String info, boolean altTransportAvailable, BaseTransportConfig transportConfig) {
+
notifyPutFileStreamError(null, info);
- if( altTransportAvailable){
+ if (altTransportAvailable){
SdlProxyBase.this._transportConfig = transportConfig;
Log.d(TAG, "notifying RPC session ended, but potential primary transport available");
cycleProxy(SdlDisconnectedReason.PRIMARY_TRANSPORT_CYCLE_REQUEST);
-
}else{
notifyProxyClosed(info, new SdlException("Transport disconnected.", SdlExceptionCause.SDL_UNAVAILABLE), SdlDisconnectedReason.TRANSPORT_DISCONNECT);
}
@@ -1563,14 +1572,14 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase>
synchronized(CONNECTION_REFERENCE_LOCK) {
//Handle legacy USB connections
- if(_transportConfig != null
- && TransportType.USB.equals(_transportConfig.getTransportType())){
+ if (_transportConfig != null
+ && TransportType.USB.equals(_transportConfig.getTransportType())) {
//A USB transport config was provided
- USBTransportConfig usbTransportConfig = (USBTransportConfig)_transportConfig;
- if(usbTransportConfig.getUsbAccessory() == null){
+ USBTransportConfig usbTransportConfig = (USBTransportConfig) _transportConfig;
+ if (usbTransportConfig.getUsbAccessory() == null) {
DebugTool.logInfo("Legacy USB transport config was used, but received null for accessory. Attempting to connect with router service");
//The accessory was null which means it came from a router service
- MultiplexTransportConfig multiplexTransportConfig = new MultiplexTransportConfig(usbTransportConfig.getUSBContext(),_appID);
+ MultiplexTransportConfig multiplexTransportConfig = new MultiplexTransportConfig(usbTransportConfig.getUSBContext(), _appID);
multiplexTransportConfig.setRequiresHighBandwidth(true);
multiplexTransportConfig.setSecurityLevel(MultiplexTransportConfig.FLAG_MULTI_SECURITY_OFF);
multiplexTransportConfig.setPrimaryTransports(Collections.singletonList(TransportType.USB));
@@ -1579,9 +1588,11 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase>
}
}
- if(_transportConfig.getTransportType().equals(TransportType.MULTIPLEX)){
- this.sdlSession = new SdlSession2(_interfaceBroker,(MultiplexTransportConfig)_transportConfig);
- }else{
+ if (_transportConfig != null && _transportConfig.getTransportType().equals(TransportType.MULTIPLEX)) {
+ this.sdlSession = new SdlSession2(_interfaceBroker, (MultiplexTransportConfig) _transportConfig);
+ }else if(_transportConfig != null &&_transportConfig.getTransportType().equals(TransportType.TCP)){
+ this.sdlSession = new SdlSession2(_interfaceBroker, (TCPTransportConfig) _transportConfig);
+ }else {
this.sdlSession = SdlSession.createSession((byte)getProtocolVersion().getMajor(),_interfaceBroker, _transportConfig);
}
}
@@ -1834,6 +1845,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase>
try{
_cycling = true;
cleanProxy(disconnectedReason);
+
initializeProxy();
if(!SdlDisconnectedReason.LEGACY_BLUETOOTH_MODE_ENABLED.equals(disconnectedReason)
&& !SdlDisconnectedReason.PRIMARY_TRANSPORT_CYCLE_REQUEST.equals(disconnectedReason)){//We don't want to alert higher if we are just cycling for legacy bluetooth
@@ -3551,6 +3563,36 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase>
_proxyListener.onGetInteriorVehicleDataResponse(msg);
onRPCResponseReceived(msg);
}
+ } else if (functionName.equals(FunctionID.CREATE_WINDOW.toString())) {
+ final CreateWindowResponse msg = new CreateWindowResponse(hash);
+ msg.format(rpcSpecVersion, true);
+ if (_callbackToUIThread) {
+ _mainUIHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ _proxyListener.onCreateWindowResponse(msg);
+ onRPCResponseReceived(msg);
+ }
+ });
+ } else {
+ _proxyListener.onCreateWindowResponse(msg);
+ onRPCResponseReceived(msg);
+ }
+ } else if (functionName.equals(FunctionID.DELETE_WINDOW.toString())) {
+ final DeleteWindowResponse msg = new DeleteWindowResponse(hash);
+ msg.format(rpcSpecVersion, true);
+ if (_callbackToUIThread) {
+ _mainUIHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ _proxyListener.onDeleteWindowResponse(msg);
+ onRPCResponseReceived(msg);
+ }
+ });
+ } else {
+ _proxyListener.onDeleteWindowResponse(msg);
+ onRPCResponseReceived(msg);
+ }
} else if (functionName.equals(FunctionID.GET_SYSTEM_CAPABILITY.toString())) {
// GetSystemCapabilityResponse
final GetSystemCapabilityResponse msg = new GetSystemCapabilityResponse(hash);
@@ -3702,12 +3744,28 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase>
_mainUIHandler.post(new Runnable() {
@Override
public void run() {
- _proxyListener.onCloseApplicationResponse( msg);
+ _proxyListener.onCloseApplicationResponse(msg);
onRPCResponseReceived(msg);
}
});
} else {
- _proxyListener.onCloseApplicationResponse( msg);
+ _proxyListener.onCloseApplicationResponse(msg);
+ onRPCResponseReceived(msg);
+ }
+ } else if (functionName.equals(FunctionID.CANCEL_INTERACTION.toString())) {
+ final CancelInteractionResponse msg = new CancelInteractionResponse(hash);
+ msg.format(rpcSpecVersion, true);
+ if (_callbackToUIThread) {
+ // Run in UI thread
+ _mainUIHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ _proxyListener.onCancelInteractionResponse(msg);
+ onRPCResponseReceived(msg);
+ }
+ });
+ } else {
+ _proxyListener.onCancelInteractionResponse(msg);
onRPCResponseReceived(msg);
}
} else if (functionName.equals(FunctionID.UNPUBLISH_APP_SERVICE.toString())) {
@@ -3726,6 +3784,52 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase>
_proxyListener.onUnpublishAppServiceResponse( msg);
onRPCResponseReceived(msg);
}
+ } else if (functionName.equals(FunctionID.SHOW_APP_MENU.toString())) {
+ final ShowAppMenuResponse msg = new ShowAppMenuResponse(hash);
+ msg.format(rpcSpecVersion, true);
+ if (_callbackToUIThread) {
+ // Run in UI thread
+ _mainUIHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ _proxyListener.onShowAppMenuResponse( msg);
+ onRPCResponseReceived(msg);
+ }
+ });
+ } else {
+ _proxyListener.onShowAppMenuResponse(msg);
+ onRPCResponseReceived(msg);
+ }
+ } else if (functionName.equals(FunctionID.GET_INTERIOR_VEHICLE_DATA_CONSENT.toString())) {
+ final GetInteriorVehicleDataConsentResponse msg = new GetInteriorVehicleDataConsentResponse(hash);
+ msg.format(rpcSpecVersion, true);
+ if (_callbackToUIThread) {
+ _mainUIHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ _proxyListener.onGetInteriorVehicleDataConsentResponse(msg);
+ onRPCResponseReceived(msg);
+ }
+ });
+ } else {
+ _proxyListener.onGetInteriorVehicleDataConsentResponse(msg);
+ onRPCResponseReceived(msg);
+ }
+ } else if (functionName.equals(FunctionID.RELEASE_INTERIOR_VEHICLE_MODULE.toString())) {
+ final ReleaseInteriorVehicleDataModuleResponse msg = new ReleaseInteriorVehicleDataModuleResponse(hash);
+ msg.format(rpcSpecVersion, true);
+ if (_callbackToUIThread) {
+ _mainUIHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ _proxyListener.onReleaseInteriorVehicleDataModuleResponse(msg);
+ onRPCResponseReceived(msg);
+ }
+ });
+ } else {
+ _proxyListener.onReleaseInteriorVehicleDataModuleResponse(msg);
+ onRPCResponseReceived(msg);
+ }
} else {
if (_sdlMsgVersion != null) {
DebugTool.logError("Unrecognized response Message: " + functionName +
@@ -3735,6 +3839,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase>
}
} // end-if
+
} else if (messageType.equals(RPCMessage.KEY_NOTIFICATION)) {
if (functionName.equals(FunctionID.ON_HMI_STATUS.toString())) {
// OnHMIStatus
@@ -4108,7 +4213,19 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase>
if (_advancedLifecycleManagementEnabled) {
// This requires the proxy to be cycled
- cycleProxy(SdlDisconnectedReason.convertAppInterfaceUnregisteredReason(msg.getReason()));
+
+ if(_mainUIHandler == null){
+ _mainUIHandler = new Handler(Looper.getMainLooper());
+ }
+
+ //This needs to be ran on the main thread
+
+ _mainUIHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ cycleProxy(SdlDisconnectedReason.convertAppInterfaceUnregisteredReason(msg.getReason()));
+ }
+ });
} else {
if (_callbackToUIThread) {
// Run in UI thread
@@ -4813,7 +4930,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase>
sdlSession.setDesiredVideoParams(emptyParam);
sdlSession.startService(SessionType.NAV, sdlSession.getSessionId(), isEncrypted);
-
+ addNavListener();
FutureTask<Void> fTask = createFutureTask(new CallableMethod(RESPONSE_WAIT_TIME));
ScheduledExecutorService scheduler = createScheduler();
scheduler.execute(fTask);
@@ -4861,7 +4978,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase>
sdlSession.setDesiredVideoParams(emptyParam);
sdlSession.startService(SessionType.NAV, sdlSession.getSessionId(), isEncrypted);
-
+ addNavListener();
FutureTask<Void> fTask = createFutureTask(new CallableMethod(RESPONSE_WAIT_TIME));
ScheduledExecutorService scheduler = createScheduler();
scheduler.execute(fTask);
@@ -5235,7 +5352,7 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase>
navServiceStartRejectedParams = null;
sdlSession.startService(SessionType.NAV, sdlSession.getSessionId(), isEncrypted);
-
+ addNavListener();
FutureTask<Void> fTask = createFutureTask(new CallableMethod(RESPONSE_WAIT_TIME));
ScheduledExecutorService scheduler = createScheduler();
scheduler.execute(fTask);
@@ -5300,6 +5417,35 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase>
sdlSession.drainEncoder(endOfStream);
}
+ 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
+ resetNavStartFlags();
+ // propagate notification up to proxy listener so the developer will know that the service is ended
+ if (_proxyListener != null) {
+ _proxyListener.onServiceEnded(new OnServiceEnded(type));
+ }
+ }
+
+ @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
+ resetNavStartFlags();
+ }
+ };
+ this.sdlSession.addServiceListener(SessionType.NAV, navServiceListener);
+ }
+ }
+
/**
* Opens a audio service (service type 10) and subsequently provides an IAudioStreamListener
* to the app to send audio data.
@@ -5452,7 +5598,13 @@ public abstract class SdlProxyBase<proxyListenerType extends IProxyListenerBase>
private void AudioServiceEndedNACK() {
pcmServiceEndResponseReceived = true;
pcmServiceEndResponse = false;
- }
+ }
+
+ private void resetNavStartFlags() {
+ navServiceStartResponseReceived = false;
+ navServiceStartResponse = false;
+ navServiceStartRejectedParams = null;
+ }
public void setAppService(Service mService)
{
diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/proxy/SdlProxyBuilder.java b/android/sdl_android/src/main/java/com/smartdevicelink/proxy/SdlProxyBuilder.java
index 897add3f5..5240c4813 100644
--- a/android/sdl_android/src/main/java/com/smartdevicelink/proxy/SdlProxyBuilder.java
+++ b/android/sdl_android/src/main/java/com/smartdevicelink/proxy/SdlProxyBuilder.java
@@ -49,6 +49,7 @@ import com.smartdevicelink.transport.MultiplexTransportConfig;
import java.util.List;
import java.util.Vector;
+@Deprecated
public class SdlProxyBuilder {
// Required parameters
private IProxyListenerALM listener;
diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/proxy/SdlProxyConfigurationResources.java b/android/sdl_android/src/main/java/com/smartdevicelink/proxy/SdlProxyConfigurationResources.java
index c96df0f78..6e76db82a 100644
--- a/android/sdl_android/src/main/java/com/smartdevicelink/proxy/SdlProxyConfigurationResources.java
+++ b/android/sdl_android/src/main/java/com/smartdevicelink/proxy/SdlProxyConfigurationResources.java
@@ -1,38 +1,39 @@
-/*
- * Copyright (c) 2017 - 2019, SmartDeviceLink Consortium, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided with the
- * distribution.
- *
- * Neither the name of the SmartDeviceLink Consortium, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
+/*
+ * Copyright (c) 2017 - 2019, SmartDeviceLink Consortium, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of the SmartDeviceLink Consortium, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
package com.smartdevicelink.proxy;
import android.telephony.TelephonyManager;
+@Deprecated
public class SdlProxyConfigurationResources {
private String _sdlConfigurationFilePath;
private TelephonyManager _telephonyManager;
diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/streaming/video/SdlRemoteDisplay.java b/android/sdl_android/src/main/java/com/smartdevicelink/streaming/video/SdlRemoteDisplay.java
index 8af6b1c59..a35b4790a 100644
--- a/android/sdl_android/src/main/java/com/smartdevicelink/streaming/video/SdlRemoteDisplay.java
+++ b/android/sdl_android/src/main/java/com/smartdevicelink/streaming/video/SdlRemoteDisplay.java
@@ -173,7 +173,7 @@ public abstract class SdlRemoteDisplay extends Presentation {
public void run() {
// Want to create presentation on UI thread so it finds the right Looper
// when setting up the Dialog.
- if ((remoteDisplay == null) && (mDisplay != null))
+ if((mDisplay!=null) && (remoteDisplay == null || remoteDisplay.getDisplay() != mDisplay))
{
try {
Constructor constructor = remoteDisplayClass.getConstructor(Context.class, Display.class);
diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/transport/MultiplexTcpTransport.java b/android/sdl_android/src/main/java/com/smartdevicelink/transport/MultiplexTcpTransport.java
index d5843f4c2..63766f0b1 100644
--- a/android/sdl_android/src/main/java/com/smartdevicelink/transport/MultiplexTcpTransport.java
+++ b/android/sdl_android/src/main/java/com/smartdevicelink/transport/MultiplexTcpTransport.java
@@ -47,6 +47,8 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
import static com.smartdevicelink.util.DebugTool.logError;
import static com.smartdevicelink.util.NativeLogTool.logInfo;
@@ -354,8 +356,46 @@ public class MultiplexTcpTransport extends MultiplexBaseTransport {
}
private class WriterThread extends Thread {
- private boolean mCancelled = false;
+ private boolean isHalted = false;
private boolean mVerbose = false;
+ final BlockingQueue<OutPacket> packetQueue = new LinkedBlockingQueue<>();
+
+ @Override
+ public void run() {
+ while(!isHalted){
+ try{
+ OutPacket packet = packetQueue.take();
+ if(packet == null){
+ continue;
+ }
+
+ OutputStream out;
+ synchronized (MultiplexTcpTransport.this) {
+ out = mOutputStream;
+ }
+
+ if ((out != null) && (!isHalted)) {
+ try {
+ out.write(packet.bytes, packet.offset, packet.count);
+ if (mVerbose) {
+ logInfo("TCPTransport.sendBytesOverTransport: successfully sent data");
+ }
+ } catch (IOException e) {
+ logError("TCPTransport.sendBytesOverTransport: error during sending data: " + e.getMessage());
+ }
+ } else {
+ if (isHalted) {
+ logError("TCPTransport: sendBytesOverTransport request accepted, thread is cancelled");
+ } else {
+ logError("TCPTransport: sendBytesOverTransport request accepted, but output stream is null");
+ }
+ }
+
+ }catch(InterruptedException e){
+ break;
+ }
+ }
+ }
public void write(byte[] msgBytes, int offset, int count) {
if ((msgBytes == null) || (msgBytes.length == 0)) {
@@ -366,32 +406,12 @@ public class MultiplexTcpTransport extends MultiplexBaseTransport {
if (offset + count > msgBytes.length) {
count = msgBytes.length - offset;
}
+ packetQueue.add(new OutPacket(msgBytes, offset, count));
- OutputStream out;
- synchronized (MultiplexTcpTransport.this) {
- out = mOutputStream;
- }
-
- if ((out != null) && (!mCancelled)) {
- try {
- out.write(msgBytes, offset, count);
- if (mVerbose) {
- logInfo("TCPTransport.sendBytesOverTransport: successfully sent data");
- }
- } catch (IOException e) {
- logError("TCPTransport.sendBytesOverTransport: error during sending data: " + e.getMessage());
- }
- } else {
- if (mCancelled) {
- logError("TCPTransport: sendBytesOverTransport request accepted, thread is cancelled");
- } else {
- logError("TCPTransport: sendBytesOverTransport request accepted, but output stream is null");
- }
- }
}
public synchronized void cancel() {
- mCancelled = true;
+ isHalted = true;
if (mOutputStream != null) {
synchronized (MultiplexTcpTransport.this) {
try {
@@ -410,4 +430,18 @@ public class MultiplexTcpTransport extends MultiplexBaseTransport {
}
}
}
+
+ private final class OutPacket{
+ byte[] bytes;
+ int count;
+ int offset;
+
+ OutPacket(byte[] bytes, int offset, int count){
+ this.bytes = bytes;
+ this.offset = offset;
+ this.count = count;
+ }
+ }
+
+
}
diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/transport/SdlRouterService.java b/android/sdl_android/src/main/java/com/smartdevicelink/transport/SdlRouterService.java
index dcfee9745..60ff45206 100644
--- a/android/sdl_android/src/main/java/com/smartdevicelink/transport/SdlRouterService.java
+++ b/android/sdl_android/src/main/java/com/smartdevicelink/transport/SdlRouterService.java
@@ -3173,10 +3173,10 @@ public class SdlRouterService extends Service{
* @return
*/
private TransportType getCompatPrimaryTransport(){
- if(this.registeredTransports != null){
+ if(this.registeredTransports != null && this.registeredTransports.size() > 0) {
List<TransportType> transportTypes = this.registeredTransports.valueAt(0);
- if(transportTypes != null){
- if(transportTypes.get(0) != null){
+ if (transportTypes != null) {
+ if (transportTypes.get(0) != null) {
return transportTypes.get(0);
}
}
@@ -3199,7 +3199,9 @@ public class SdlRouterService extends Service{
int flags = receivedBundle.getInt(TransportConstants.BYTES_TO_SEND_FLAGS, TransportConstants.BYTES_TO_SEND_FLAG_NONE);
TransportType transportType = TransportType.valueForString(receivedBundle.getString(TransportConstants.TRANSPORT_TYPE));
if(transportType == null){
- transportType = getCompatPrimaryTransport();
+ synchronized (TRANSPORT_LOCK){
+ transportType = getCompatPrimaryTransport();
+ }
receivedBundle.putString(TransportConstants.TRANSPORT_TYPE, transportType.name());
}
diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/transport/TCPTransportManager.java b/android/sdl_android/src/main/java/com/smartdevicelink/transport/TCPTransportManager.java
new file mode 100644
index 000000000..29e0c3aa1
--- /dev/null
+++ b/android/sdl_android/src/main/java/com/smartdevicelink/transport/TCPTransportManager.java
@@ -0,0 +1,135 @@
+package com.smartdevicelink.transport;
+
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+
+import com.smartdevicelink.protocol.SdlPacket;
+import com.smartdevicelink.transport.enums.TransportType;
+import com.smartdevicelink.transport.utl.TransportRecord;
+import com.smartdevicelink.util.DebugTool;
+
+import java.lang.ref.WeakReference;
+
+public class TCPTransportManager extends TransportManagerBase{
+
+ private static final String TAG = "TCPTransportManager";
+
+ private TCPHandler tcpHandler;
+ private MultiplexTcpTransport transport;
+ private TCPTransportConfig config;
+
+ public TCPTransportManager(TCPTransportConfig config, TransportEventListener transportEventListener){
+ super(config,transportEventListener);
+ Log.d(TAG, "USING THE TCP TRANSPORT MANAGER");
+ this.config = config;
+ tcpHandler = new TCPHandler(this);
+ transport = new MultiplexTcpTransport(config.getPort(), config.getIPAddress(),config.getAutoReconnect(),tcpHandler, null);
+ }
+
+ @Override
+ public void start() {
+ transport.start();
+
+ }
+
+ @Override
+ public void close(long sessionId) {
+ transport.stop();
+ }
+
+ @Override
+ public void resetSession() {
+ if(transport != null){
+ transport.stop();
+ }
+ //TODO make sure this makes sense
+ transport = new MultiplexTcpTransport(config.getPort(), config.getIPAddress(),config.getAutoReconnect(), tcpHandler, null);
+
+ }
+
+ @Override
+ public boolean isConnected(TransportType transportType, String address) {
+ return (transportType == null || TransportType.TCP.equals(transportType)) && transport.isConnected();
+ }
+
+ @Override
+ public TransportRecord getTransportRecord(TransportType transportType, String address) {
+ if(transport != null){
+ return transport.getTransportRecord();
+ }else{
+ return null;
+ }
+ }
+
+ @Override
+ public void sendPacket(SdlPacket packet) {
+ if(packet != null){
+ byte[] rawBytes = packet.constructPacket();
+ if(rawBytes != null && rawBytes.length >0){
+ transport.write(rawBytes, 0, rawBytes.length);
+ }
+ }
+
+ }
+
+
+ protected static class TCPHandler extends Handler {
+
+ final WeakReference<TCPTransportManager> provider;
+
+ public TCPHandler(TCPTransportManager provider){
+ this.provider = new WeakReference<>(provider);
+ }
+ @Override
+ public void handleMessage(Message msg) {
+ if(this.provider.get() == null){
+ return;
+ }
+ TCPTransportManager service = this.provider.get();
+ if(service.transportListener == null){
+ return;
+ }
+ switch (msg.what) {
+ case SdlRouterService.MESSAGE_STATE_CHANGE:
+ switch (msg.arg1) {
+ case MultiplexBaseTransport.STATE_CONNECTED:
+ synchronized (service.TRANSPORT_STATUS_LOCK){
+ service.transportStatus.clear();
+ service.transportStatus.add(service.transport.getTransportRecord());
+ }
+ DebugTool.logInfo("TCP transport has connected");
+ service.transportListener.onTransportConnected(service.transportStatus);
+ break;
+ case MultiplexBaseTransport.STATE_CONNECTING:
+ // Currently attempting to connect - update UI?
+ break;
+ case MultiplexBaseTransport.STATE_LISTEN:
+ if(service.transport != null){
+ service.transport.stop();
+ service.transport = null;
+ }
+ break;
+ case MultiplexBaseTransport.STATE_NONE:
+ // We've just lost the connection
+ if(service.transport != null){
+ service.transportListener.onTransportDisconnected("TCP transport disconnected", service.transport.transportRecord, null);
+ }else{
+ service.transportListener.onTransportDisconnected("TCP transport disconnected", null, null);
+
+ }
+ break;
+ case MultiplexBaseTransport.STATE_ERROR:
+ Log.d(TAG, "TCP transport encountered an error");
+ service.transportListener.onError("TCP transport encountered an error" );
+ break;
+ }
+ break;
+
+ case SdlRouterService.MESSAGE_READ:
+ service.transportListener.onPacketReceived((SdlPacket) msg.obj);
+ break;
+ }
+ }
+ }
+}
diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/transport/TransportBroker.java b/android/sdl_android/src/main/java/com/smartdevicelink/transport/TransportBroker.java
index 0ab335bf9..10cb518d4 100644
--- a/android/sdl_android/src/main/java/com/smartdevicelink/transport/TransportBroker.java
+++ b/android/sdl_android/src/main/java/com/smartdevicelink/transport/TransportBroker.java
@@ -55,6 +55,7 @@ import com.smartdevicelink.transport.enums.TransportType;
import com.smartdevicelink.transport.utl.ByteAraryMessageAssembler;
import com.smartdevicelink.transport.utl.ByteArrayMessageSpliter;
import com.smartdevicelink.transport.utl.TransportRecord;
+import com.smartdevicelink.util.DebugTool;
import java.lang.ref.WeakReference;
import java.text.SimpleDateFormat;
@@ -119,7 +120,6 @@ public class TransportBroker {
Log.d(TAG, "Unbound from service " + className.getClassName());
routerServiceMessenger = null;
registeredWithRouterService = false;
- unBindFromRouterService();
isBound = false;
onHardwareDisconnected(null, null);
}
@@ -158,6 +158,7 @@ public class TransportBroker {
Log.d(TAG, "Dead object while attempting to send packet");
routerServiceMessenger = null;
registeredWithRouterService = false;
+ unBindFromRouterService();
isBound = false;
onHardwareDisconnected(null, null);
return false;
@@ -166,6 +167,7 @@ public class TransportBroker {
Log.d(TAG, "Null messenger while attempting to send packet"); // NPE, routerServiceMessenger is null
routerServiceMessenger = null;
registeredWithRouterService = false;
+ unBindFromRouterService();
isBound = false;
onHardwareDisconnected(null, null);
return false;
@@ -448,7 +450,7 @@ public class TransportBroker {
* This method will end our communication with the router service.
*/
public void stop() {
- //Log.d(TAG, "STOPPING transport broker for " + whereToReply);
+ DebugTool.logInfo("Stopping transport broker for " + whereToReply);
synchronized (INIT_LOCK) {
unregisterWithRouterService();
unBindFromRouterService();
@@ -461,15 +463,13 @@ public class TransportBroker {
private synchronized void unBindFromRouterService() {
try {
- if (isBound && getContext() != null && routerConnection != null) {
- getContext().unbindService(routerConnection);
- isBound = false;
- } else {
- Log.w(TAG, "Unable to unbind from router service. bound? " + isBound + " context? " + (getContext()!=null) + " router connection?" + (routerConnection != null));
- }
+ getContext().unbindService(routerConnection);
- } catch (IllegalArgumentException e) {
+ } catch (Exception e) {
//This is ok
+ Log.w(TAG, "Unable to unbind from router service. bound? " + isBound + " context? " + (getContext()!=null) + " router connection?" + (routerConnection != null));
+ }finally {
+ isBound = false;
}
}
diff --git a/android/sdl_android/src/main/java/com/smartdevicelink/transport/utl/WiFiSocketFactory.java b/android/sdl_android/src/main/java/com/smartdevicelink/transport/utl/WiFiSocketFactory.java
index 6e7fd7c75..d33f4c374 100644
--- a/android/sdl_android/src/main/java/com/smartdevicelink/transport/utl/WiFiSocketFactory.java
+++ b/android/sdl_android/src/main/java/com/smartdevicelink/transport/utl/WiFiSocketFactory.java
@@ -72,6 +72,10 @@ public class WiFiSocketFactory {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private static Socket createWiFiSocket(Context context) {
+ if(context == null){
+ logInfo("Context supplied was null");
+ return null;
+ }
PackageManager pm = context.getPackageManager();
if (pm == null) {
logInfo("PackageManager isn't available.");