diff --git a/README b/README
index 50cc863fb..9d01b6ad4 100644
--- a/README
+++ b/README
@@ -19,6 +19,7 @@ BUILD_X264 0 (don't build x264) or 1 (build x264)
BUILD_AMR 0 (don't build amr codec), light (try to use amr codec from android), full (build your own amr codec)
BUILD_GPLV3_ZRTP 0 (don't support ZRTP), 1 (support ZRTP and make the whole program GPLv3)
BUILD_SILK 0 (don't build silk plugin), 1 (build silk) [silk is Skype nonfree patented audio codec]
+BUILD_TUNNEL 0 (don't build tunnel), 1 (build tunnel) [requires a tunnel implementation in submodules/linphone/tunnel]
In order to use ZRTP you also need to define the media_encryption property to
"zrtp" in the sip section of linphonerc file.
diff --git a/jni/Android.mk b/jni/Android.mk
index d6f8cef16..95fd7fd3f 100755
--- a/jni/Android.mk
+++ b/jni/Android.mk
@@ -63,6 +63,10 @@ include $(linphone-root-dir)/submodules/linphone/mediastreamer2/build/android/An
include $(linphone-root-dir)/submodules/linphone/mediastreamer2/tests/Android.mk
+ifeq ($(BUILD_TUNNEL), 1)
+include $(linphone-root-dir)/submodules/linphone/tunnel/Android.mk
+endif
+
ifeq ($(BUILD_SILK), 1)
$(info Build proprietary SILK plugin for mediastreamer2)
include $(linphone-root-dir)/submodules/mssilk/Android.mk
diff --git a/jni/Application.mk b/jni/Application.mk
index 85985223d..bd23bae2a 100644
--- a/jni/Application.mk
+++ b/jni/Application.mk
@@ -2,10 +2,6 @@ APP_PROJECT_PATH := $(call my-dir)/../
APP_MODULES :=libspeex libgsm libortp libosip2 libeXosip2 libmediastreamer2 liblinphone
APP_STL := stlport_static
-ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
-APP_MODULES +=libmsilbc
-endif
-
ifeq ($(LINPHONE_VIDEO),1)
APP_MODULES += libavutil libavcore libavcodec libswscale libvpx
endif
@@ -14,10 +10,6 @@ ifeq ($(BUILD_AMR),1)
APP_MODULES += libopencoreamr libmsamr
endif
-ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
-APP_MODULES += liblincrypto liblinssl
-endif
-
ifeq ($(BUILD_X264),1)
APP_MODULES +=libx264 libmsx264
endif
@@ -30,7 +22,14 @@ ifeq ($(RING),yes)
APP_MODULES += libring
endif
+ifeq ($(BUILD_TUNNEL), 1)
+APP_MODULES += libtunnelclient
+endif
+
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
+APP_MODULES += liblincrypto liblinssl
+APP_MODULES +=libmsilbc
+
ifeq ($(BUILD_GPLV3_ZRTP), 1)
APP_MODULES += libzrtpcpp
endif
@@ -38,12 +37,13 @@ endif
ifeq ($(BUILD_SRTP), 1)
APP_MODULES += libsrtp
endif
-endif
+endif #armeabi-v7a
+
linphone-root-dir:=$(APP_PROJECT_PATH)
APP_BUILD_SCRIPT:=$(call my-dir)/Android.mk
APP_PLATFORM := android-8
-#APP_ABI := armeabi-v7a
+#APP_ABI := armeabi
APP_ABI := armeabi-v7a armeabi
APP_CFLAGS:=-DDISABLE_NEON
diff --git a/res/values/custom.xml b/res/values/custom.xml
index ae8368152..8f4ef1b67 100644
--- a/res/values/custom.xml
+++ b/res/values/custom.xml
@@ -8,5 +8,8 @@
Registered to %s
Fails to register to %s
Linphone %s SIP (rfc 3261) compatible phone under GNU Public License V2\n http://www.linphone.org\n\nInstructions\nhttp://www.linphone.org/m/help\n\n© 2011 Belledonne Communications
+
+
+ @string/tunnel_mode_entry_value_disabled
\ No newline at end of file
diff --git a/res/values/non_localizable_strings.xml b/res/values/non_localizable_strings.xml
index a5ef23b8b..0bf0c07b6 100644
--- a/res/values/non_localizable_strings.xml
+++ b/res/values/non_localizable_strings.xml
@@ -1,5 +1,21 @@
+
+
+ pref_tunnel_key
+ pref_tunnel_mode_key
+ disabled
+ 3G_only
+ always
+
+ - @string/tunnel_mode_entry_value_disabled
+ - @string/tunnel_mode_entry_value_3G_only
+ - @string/tunnel_mode_entry_value_always
+ - @string/tunnel_mode_entry_value_auto
+
+ pref_tunnel_host_key
+ pref_tunnel_port_key
+ auto
pref_audio_use_specific_mode_key
pref_audio_hacks_use_galaxys_hack_key
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 3f320de0e..a0f30fdc0 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1,6 +1,19 @@
+ Tunnel
+ Hostname
+ Port
+ Mode
+
+
+
+ - disabled
+ - 3G only
+ - always
+ - auto
+
+
Audio call ongoing
Paused call ongoing
Video capturing call ongoing
diff --git a/res/xml/preferences.xml b/res/xml/preferences.xml
index 26279ff3f..9f9ec184f 100644
--- a/res/xml/preferences.xml
+++ b/res/xml/preferences.xml
@@ -21,7 +21,20 @@
+
+
+
+
+
+
+
diff --git a/src/org/linphone/LinphoneManager.java b/src/org/linphone/LinphoneManager.java
index 123acbcd0..2d7f60f0c 100644
--- a/src/org/linphone/LinphoneManager.java
+++ b/src/org/linphone/LinphoneManager.java
@@ -403,6 +403,47 @@ public final class LinphoneManager implements LinphoneCoreListener {
}
}
+
+ private boolean isTunnelNeeded(NetworkInfo info) {
+ if (info == null) {
+ Log.i("No connectivity: tunnel should be disabled");
+ return false;
+ }
+
+ String pref = getPrefString(R.string.pref_tunnel_mode_key, R.string.default_tunnel_mode_entry_value);
+
+ if (getString(R.string.tunnel_mode_entry_value_always).equals(pref)) {
+ return true;
+ }
+
+ if (info.getType() != ConnectivityManager.TYPE_WIFI
+ && getString(R.string.tunnel_mode_entry_value_3G_only).equals(pref)) {
+ Log.i("need tunnel: 'no wifi' connection");
+ return true;
+ }
+
+ return false;
+ }
+
+ public void manageTunnelServer(NetworkInfo info) {
+ if (mLc == null) return;
+ if (!mLc.isTunnelAvailable()) return;
+
+ Log.i("Managing tunnel");
+ if (isTunnelNeeded(info)) {
+ Log.i("Tunnel need to be activated");
+ mLc.tunnelEnable(true);
+ } else {
+ Log.i("Tunnel should not be used");
+ String pref = getPrefString(R.string.pref_tunnel_mode_key, R.string.default_tunnel_mode_entry_value);
+ mLc.tunnelEnable(false);
+ if (getString(R.string.tunnel_mode_entry_value_auto).equals(pref)) {
+ mLc.tunnelAutoDetect();
+ }
+ }
+ }
+
+
private synchronized void startLibLinphone() {
try {
copyAssetsFromPackage();
@@ -484,7 +525,7 @@ public final class LinphoneManager implements LinphoneCoreListener {
void initMediaEncryption(){
String pref = getPrefString(R.string.pref_media_encryption_key,
- getString(R.string.pref_media_encryption_key_none));
+ R.string.pref_media_encryption_key_none);
MediaEncryption me=MediaEncryption.None;
if (pref.equals(getString(R.string.pref_media_encryption_key_srtp)))
me=MediaEncryption.SRTP;
@@ -494,11 +535,26 @@ public final class LinphoneManager implements LinphoneCoreListener {
mLc.setMediaEncryption(me);
}
+ private void initFromConfTunnel(){
+ if (!mLc.isTunnelAvailable()) return;
+ NetworkInfo info = mConnectivityManager.getActiveNetworkInfo();
+ mLc.tunnelEnableLogs(getPrefBoolean(R.string.pref_debug_key, false));
+ mLc.tunnelCleanServers();
+ String host = getString(R.string.tunnel_host);
+ if (host == null || host.length() == 0)
+ host = mPref.getString(getString(R.string.pref_tunnel_host_key), "");
+ int port = Integer.parseInt(getPrefString(R.string.pref_tunnel_port_key, "443"));
+ mLc.tunnelAddServerAndMirror(host, port, 12345,500);
+ manageTunnelServer(info);
+ }
+
public void initFromConf() throws LinphoneConfigException {
//traces
boolean lIsDebug = true;//mPref.getBoolean(getString(R.string.pref_debug_key), false);
LinphoneCoreFactory.instance().setDebugMode(lIsDebug);
-
+
+ initFromConfTunnel();
+
if (initialTransports == null)
initialTransports = mLc.getSignalingTransportPorts();
@@ -713,9 +769,32 @@ public final class LinphoneManager implements LinphoneCoreListener {
private String getPrefString(int key, String value) {
return mPref.getString(mR.getString(key), value);
}
+ private String getPrefString(int key, int value) {
+ return mPref.getString(mR.getString(key), mR.getString(value));
+ }
+ /* Simple implementation as Android way seems very complicate:
+ For example: with wifi and mobile actives; when pulling mobile down:
+ I/Linphone( 8397): WIFI connected: setting network reachable
+ I/Linphone( 8397): new state [RegistrationProgress]
+ I/Linphone( 8397): mobile disconnected: setting network unreachable
+ I/Linphone( 8397): Managing tunnel
+ I/Linphone( 8397): WIFI connected: setting network reachable
+ */
+ public void connectivityChanged(NetworkInfo eventInfo, ConnectivityManager cm) {
+ NetworkInfo activeInfo = cm.getActiveNetworkInfo();
+
+ if (eventInfo.getState() == NetworkInfo.State.DISCONNECTED) {
+ Log.i(eventInfo.getTypeName()," disconnected: setting network unreachable");
+ mLc.setNetworkReachable(false);
+ } else if (eventInfo.getState() == NetworkInfo.State.CONNECTED){
+ manageTunnelServer(activeInfo);
+ Log.i(eventInfo.getTypeName()," connected: setting network reachable");
+ mLc.setNetworkReachable(true);
+ }
+ }
diff --git a/src/org/linphone/LinphonePreferencesActivity.java b/src/org/linphone/LinphonePreferencesActivity.java
index 077fc0aa0..5c9f58555 100644
--- a/src/org/linphone/LinphonePreferencesActivity.java
+++ b/src/org/linphone/LinphonePreferencesActivity.java
@@ -52,6 +52,7 @@ import android.preference.CheckBoxPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
+import android.preference.PreferenceCategory;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.Preference.OnPreferenceClickListener;
@@ -144,6 +145,15 @@ public class LinphonePreferencesActivity extends PreferenceActivity implements E
if (Hacks.needSoftvolume()) checkAndDisableCheckbox(R.string.pref_audio_soft_volume_key);
+ if (!LinphoneManager.getLc().isTunnelAvailable()){
+ hidePreferenceCategory(R.string.pref_tunnel_key);
+ }
+ }
+
+ private void hidePreferenceCategory(int key) {
+ PreferenceCategory p = (PreferenceCategory) findPreference(key);
+ p.removeAll();
+ p.setLayoutResource(R.layout.hidden);
}
private void doOnFirstLaunch() {
diff --git a/src/org/linphone/LinphoneService.java b/src/org/linphone/LinphoneService.java
index 6e3c037df..c1a479ab2 100644
--- a/src/org/linphone/LinphoneService.java
+++ b/src/org/linphone/LinphoneService.java
@@ -414,7 +414,7 @@ public final class LinphoneService extends Service implements LinphoneServiceLis
sendNotification(IC_LEVEL_ORANGE, R.string.notification_registered);
}
- if (state == RegistrationState.RegistrationFailed) {
+ if (state == RegistrationState.RegistrationFailed || state == RegistrationState.RegistrationCleared) {
sendNotification(IC_LEVEL_OFFLINE, R.string.notification_register_failure);
}
diff --git a/src/org/linphone/NetworkManager.java b/src/org/linphone/NetworkManager.java
index fd7a93bd3..9714ceaed 100644
--- a/src/org/linphone/NetworkManager.java
+++ b/src/org/linphone/NetworkManager.java
@@ -51,11 +51,15 @@ public class NetworkManager extends BroadcastReceiver {
if (lNoConnectivity | ((lNetworkInfo.getState() == NetworkInfo.State.DISCONNECTED) /*&& !lIsFailOver*/)) {
LinphoneManager.getLc().setNetworkReachable(false);
- } else if (lNetworkInfo.getState() == NetworkInfo.State.CONNECTED){
+ } else if (lNetworkInfo.getState() == NetworkInfo.State.CONNECTED){
LinphoneManager.getLc().setNetworkReachable(true);
- } else {
+ } else {
// Other unhandled events
- }
+ }
+
+ NetworkInfo eventInfo = (NetworkInfo) intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
+ ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ LinphoneManager.getInstance().connectivityChanged(eventInfo, cm);
}
}
diff --git a/src/org/linphone/core/LinphoneCoreFactoryImpl.java b/src/org/linphone/core/LinphoneCoreFactoryImpl.java
index 1591a8b4e..39fbeee54 100644
--- a/src/org/linphone/core/LinphoneCoreFactoryImpl.java
+++ b/src/org/linphone/core/LinphoneCoreFactoryImpl.java
@@ -49,6 +49,9 @@ public class LinphoneCoreFactoryImpl extends LinphoneCoreFactory {
loadOptionalLibrary("srtp");
loadOptionalLibrary("zrtpcpp"); // GPLv3+
+ // Tunnel
+ loadOptionalLibrary("tunnelclient");
+
//Main library
System.loadLibrary("linphone");
diff --git a/src/org/linphone/core/LinphoneCoreImpl.java b/src/org/linphone/core/LinphoneCoreImpl.java
index 61ddbd4d6..5d04d745c 100644
--- a/src/org/linphone/core/LinphoneCoreImpl.java
+++ b/src/org/linphone/core/LinphoneCoreImpl.java
@@ -617,8 +617,43 @@ class LinphoneCoreImpl implements LinphoneCore {
}
private native void setPlayFile(long nativePtr, String path);
+
@Override
public void setPlayFile(String path) {
setPlayFile(nativePtr, path);
}
+
+
+ private native void tunnelAddServerAndMirror(long nativePtr, String host, int port, int mirror, int ms);
+ @Override
+ public void tunnelAddServerAndMirror(String host, int port, int mirror, int ms) {
+ tunnelAddServerAndMirror(nativePtr, host, port, mirror, ms);
+ }
+
+ private native void tunnelAutoDetect(long nativePtr);
+ @Override
+ public void tunnelAutoDetect() {
+ tunnelAutoDetect(nativePtr);
+ }
+
+ private native void tunnelCleanServers(long nativePtr);
+ @Override
+ public void tunnelCleanServers() {
+ tunnelCleanServers(nativePtr);
+ }
+
+ private native void tunnelEnable(long nativePtr, boolean enable);
+ @Override
+ public void tunnelEnable(boolean enable) {
+ tunnelEnable(nativePtr, enable);
+ }
+
+ private native void tunnelEnableLogs(long nativePtr, boolean enable);
+ @Override
+ public void tunnelEnableLogs(boolean enable) {
+ tunnelEnableLogs(nativePtr, enable);
+ }
+
+ @Override
+ public native boolean isTunnelAvailable();
}
diff --git a/submodules/externals/exosip b/submodules/externals/exosip
index 4eabd05b1..c3da03035 160000
--- a/submodules/externals/exosip
+++ b/submodules/externals/exosip
@@ -1 +1 @@
-Subproject commit 4eabd05b149d18629098f3254f15c8d14ff6664c
+Subproject commit c3da0303519ad3120355cb85baee9cf6d0e4d1c2
diff --git a/submodules/linphone b/submodules/linphone
index 75e7426eb..886d80bb6 160000
--- a/submodules/linphone
+++ b/submodules/linphone
@@ -1 +1 @@
-Subproject commit 75e7426eb68e6fdbaae229e05fe11398172fec7e
+Subproject commit 886d80bb6d8ac916d6cc0cf635ce25e82ff1f051