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