From ef94fd5090ca4e3fbdcb1edd3640205417151f35 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Fri, 13 Oct 2017 19:38:04 +0200 Subject: [PATCH] add helper class in java to access specific functions available only in Android SDK, such as retrieving DNS servers. Refactor wifi lock, multicast lock so that they use this new class. Manage the CPU lock required for call in the core, instead of app's LinphoneManager. --- coreapi/CMakeLists.txt | 3 + coreapi/android-helpers.cpp | 182 ++++++++++++++++++ coreapi/factory.c | 21 +- coreapi/linphonecall.c | 6 - coreapi/linphonecore.c | 57 ++---- coreapi/linphonecore_jni.cc | 51 +---- coreapi/platform-helpers.cpp | 49 +++++ coreapi/platform-helpers.h | 64 ++++++ coreapi/private.h | 30 ++- include/linphone/factory.h | 42 ++++ .../core/LinphoneCoreFactoryImpl.java | 6 +- .../org/linphone/core/LinphoneCoreImpl.java | 26 +-- .../core/util/AndroidPlatformHelper.java | 114 +++++++++++ 13 files changed, 518 insertions(+), 133 deletions(-) create mode 100644 coreapi/android-helpers.cpp create mode 100644 coreapi/platform-helpers.cpp create mode 100644 coreapi/platform-helpers.h create mode 100644 java/impl/org/linphone/core/util/AndroidPlatformHelper.java diff --git a/coreapi/CMakeLists.txt b/coreapi/CMakeLists.txt index f0a3bfdd6..11a8604fc 100644 --- a/coreapi/CMakeLists.txt +++ b/coreapi/CMakeLists.txt @@ -47,6 +47,7 @@ list(APPEND LINPHONE_PRIVATE_HEADER_FILES sqlite3_bctbx_vfs.h vcard_private.h xml2lpc.h + platform-helpers.h ) set(LINPHONE_SOURCE_FILES_C @@ -110,6 +111,8 @@ set(LINPHONE_SOURCE_FILES_C set(LINPHONE_SOURCE_FILES_CXX conference.cc tester_utils.cpp + platform-helpers.cpp + android-helpers.cpp ) set(LINPHONE_INCLUDE_DIRS ${LINPHONE_INCLUDE_DIRS}) if(ENABLE_JAVA_WRAPPER) diff --git a/coreapi/android-helpers.cpp b/coreapi/android-helpers.cpp new file mode 100644 index 000000000..bc1970a68 --- /dev/null +++ b/coreapi/android-helpers.cpp @@ -0,0 +1,182 @@ +/* +linphone +Copyright (C) 2017 Belledonne Communications SARL + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + + +#include "private.h" +#include "platform-helpers.h" +#include + + + +#ifdef __ANDROID__ + +namespace LinphonePrivate{ + +class AndroidPlatformHelpers : public PlatformHelpers{ +public: + AndroidPlatformHelpers(LinphoneCore *lc, void *system_context); + virtual void setDnsServers(); + virtual void acquireWifiLock(); + virtual void releaseWifiLock(); + virtual void acquireMcastLock(); + virtual void releaseMcastLock(); + virtual void acquireCpuLock(); + virtual void releaseCpuLock(); + ~AndroidPlatformHelpers(); +private: + int callVoidMethod(jmethodID id); + static jmethodID getMethodId(JNIEnv *env, jclass klass, const char *method, const char *signature); + jobject mJavaHelper; + jmethodID mWifiLockAcquireId; + jmethodID mWifiLockReleaseId; + jmethodID mMcastLockAcquireId; + jmethodID mMcastLockReleaseId; + jmethodID mCpuLockAcquireId; + jmethodID mCpuLockReleaseId; + jmethodID mGetDnsServersId; + jmethodID mGetPowerManagerId; + +}; + +jmethodID AndroidPlatformHelpers::getMethodId(JNIEnv *env, jclass klass, const char *method, const char *signature){ + jmethodID id = env->GetMethodID(klass, method, signature); + if (id == 0){ + ms_fatal("Could not find java method '%s %s'", method, signature); + } + return id; +} + +AndroidPlatformHelpers::AndroidPlatformHelpers(LinphoneCore *lc, void *system_context) : PlatformHelpers(lc) { + JNIEnv *env=ms_get_jni_env(); + jclass klass = env->FindClass("org/linphone/core/util/AndroidPlatformHelper"); + if (!klass){ + ms_fatal("Could not find java AndroidPlatformHelper class"); + return; + } + jmethodID ctor = env->GetMethodID(klass,"", "(Ljava/lang/Object;)V"); + mJavaHelper = env->NewObject(klass, ctor, (jobject)system_context); + if (!mJavaHelper){ + ms_error("Could not instanciate AndroidPlatformHelper object."); + return; + } + mJavaHelper = (jobject) env->NewGlobalRef(mJavaHelper); + + mWifiLockAcquireId = getMethodId(env, klass, "acquireWifiLock", "()V"); + mWifiLockReleaseId = getMethodId(env, klass, "releaseWifiLock", "()V"); + mMcastLockAcquireId = getMethodId(env, klass, "acquireMcastLock", "()V"); + mMcastLockReleaseId = getMethodId(env, klass, "releaseMcastLock", "()V"); + mCpuLockAcquireId = getMethodId(env, klass, "acquireCpuLock", "()V"); + mCpuLockReleaseId = getMethodId(env, klass, "releaseCpuLock", "()V"); + mGetDnsServersId = getMethodId(env, klass, "getDnsServers", "()[Ljava/lang/String;"); + mGetPowerManagerId = getMethodId(env, klass, "getPowerManager", "()Ljava/lang/Object;"); + + jobject pm = env->CallObjectMethod(mJavaHelper,mGetPowerManagerId); + belle_sip_wake_lock_init(env, pm); + + ms_message("AndroidPlatformHelpers is fully initialised"); +} + +AndroidPlatformHelpers::~AndroidPlatformHelpers(){ + if (mJavaHelper){ + JNIEnv *env = ms_get_jni_env(); + belle_sip_wake_lock_uninit(env); + env->DeleteGlobalRef(mJavaHelper); + mJavaHelper = NULL; + } +} + + +void AndroidPlatformHelpers::setDnsServers(){ + if (!mJavaHelper) return; + JNIEnv *env=ms_get_jni_env(); + if (env && mJavaHelper) { + jobjectArray jservers = (jobjectArray)env->CallObjectMethod(mJavaHelper,mGetDnsServersId); + bctbx_list_t *l = NULL; + if (env->ExceptionCheck()) { + env->ExceptionClear(); + ms_error("AndroidPlatformHelpers::setDnsServers() exception"); + return; + } + if (jservers != NULL){ + int count = env->GetArrayLength(jservers); + + for (int i=0; i < count; i++) { + jstring jserver = (jstring) env->GetObjectArrayElement(jservers, i); + const char *str = env->GetStringUTFChars(jserver, NULL); + if (str){ + l = bctbx_list_append(l, ms_strdup(str)); + env->ReleaseStringUTFChars(jserver, str); + } + } + } + linphone_core_set_dns_servers(mCore, l); + bctbx_list_free_with_data(l, ms_free); + } +} + +void AndroidPlatformHelpers::acquireWifiLock(){ + callVoidMethod(mWifiLockAcquireId); +} + +void AndroidPlatformHelpers::releaseWifiLock(){ + callVoidMethod(mWifiLockReleaseId); +} + +void AndroidPlatformHelpers::acquireMcastLock(){ + callVoidMethod(mMcastLockAcquireId); +} + +void AndroidPlatformHelpers::releaseMcastLock(){ + callVoidMethod(mMcastLockReleaseId); +} + +void AndroidPlatformHelpers::acquireCpuLock(){ + callVoidMethod(mCpuLockAcquireId); +} + +void AndroidPlatformHelpers::releaseCpuLock(){ + callVoidMethod(mCpuLockReleaseId); +} + + +int AndroidPlatformHelpers::callVoidMethod(jmethodID id) { + JNIEnv *env=ms_get_jni_env(); + if (env && mJavaHelper) { + env->CallVoidMethod(mJavaHelper,id); + if (env->ExceptionCheck()) { + env->ExceptionClear(); + return -1; + } else + return 0; + } else + return -1; +} + +PlatformHelpers *createAndroidPlatformHelpers(LinphoneCore *lc, void *system_context){ + return new AndroidPlatformHelpers(lc, system_context); +} + +}//end of namespace + + + + +#endif + diff --git a/coreapi/factory.c b/coreapi/factory.c index c85976ff5..80a0a42e7 100644 --- a/coreapi/factory.c +++ b/coreapi/factory.c @@ -32,7 +32,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #define PACKAGE_DATA_DIR "." #endif -extern LinphoneCore *_linphone_core_new_with_config(LinphoneCoreCbs *cbs, struct _LpConfig *config, void *userdata); extern LinphoneAddress *_linphone_address_new(const char *addr); typedef belle_sip_object_t_vptr_t LinphoneFactory_vptr_t; @@ -149,16 +148,26 @@ void linphone_factory_clean(void){ } } -LinphoneCore *linphone_factory_create_core(const LinphoneFactory *factory, LinphoneCoreCbs *cbs, - const char *config_path, const char *factory_config_path) { +LinphoneCore *linphone_factory_create_core_2(const LinphoneFactory *factory, LinphoneCoreCbs *cbs, + const char *config_path, const char *factory_config_path, void *user_data, void *system_context) { + bctbx_init_logger(FALSE); LpConfig *config = lp_config_new_with_factory(config_path, factory_config_path); - LinphoneCore *lc = _linphone_core_new_with_config(cbs, config, NULL); + LinphoneCore *lc = _linphone_core_new_with_config(cbs, config, user_data, system_context); lp_config_unref(config); return lc; } +LinphoneCore *linphone_factory_create_core(const LinphoneFactory *factory, LinphoneCoreCbs *cbs, + const char *config_path, const char *factory_config_path){ + return linphone_factory_create_core_2(factory, cbs, config_path, factory_config_path, NULL, NULL); +} + LinphoneCore *linphone_factory_create_core_with_config(const LinphoneFactory *factory, LinphoneCoreCbs *cbs, LinphoneConfig *config) { - return _linphone_core_new_with_config(cbs, config, NULL); + return _linphone_core_new_with_config(cbs, config, NULL, NULL); +} + +LinphoneCore *linphone_factory_create_core_with_config_2(const LinphoneFactory *factory, LinphoneCoreCbs *cbs, LinphoneConfig *config, void *user_data, void *system_context) { + return _linphone_core_new_with_config(cbs, config, user_data, system_context); } LinphoneCoreCbs *linphone_factory_create_core_cbs(const LinphoneFactory *factory) { @@ -369,4 +378,4 @@ void linphone_factory_set_log_collection_path(LinphoneFactory *factory, const ch void linphone_factory_enable_log_collection(LinphoneFactory *factory, LinphoneLogCollectionState state) { linphone_core_enable_log_collection(state); -} \ No newline at end of file +} diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 9962d373a..a290202a0 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -120,9 +120,3 @@ const char* linphone_privacy_to_string(LinphonePrivacy privacy) { default: return "Unknown privacy mode"; } } - -void set_playback_gain_db(AudioStream *st, float gain){ - if (st->volrecv){ - ms_filter_call_method(st->volrecv,MS_VOLUME_SET_DB_GAIN,&gain); - }else ms_warning("Could not apply playback gain: gain control wasn't activated."); -} diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 2fb96205c..555d70537 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -2191,6 +2191,7 @@ static void linphone_core_init(LinphoneCore * lc, LinphoneCoreCbs *cbs, LpConfig lc->config=lp_config_ref(config); lc->data=userdata; lc->ringstream_autorelease=TRUE; + lc->platform_helper = new LinphonePrivate::StubbedPlatformHelpers(lc); linphone_task_list_init(&lc->hooks); @@ -2268,9 +2269,21 @@ static void linphone_core_init(LinphoneCore * lc, LinphoneCoreCbs *cbs, LpConfig lc->group_chat_rooms = bctbx_mmap_cchar_new(); } -LinphoneCore *_linphone_core_new_with_config(LinphoneCoreCbs *cbs, struct _LpConfig *config, void *userdata) { +static void _linphone_core_set_platform_helpers(LinphoneCore *lc, LinphonePrivate::PlatformHelpers *ph){ + if (lc->platform_helper) delete getPlatformHelpers(lc); + lc->platform_helper = ph; +} + +static void _linphone_core_set_system_context(LinphoneCore *lc, void *system_context){ +#ifdef __ANDROID__ + _linphone_core_set_platform_helpers(lc, LinphonePrivate::createAndroidPlatformHelpers(lc, system_context)); +#endif +} + +LinphoneCore *_linphone_core_new_with_config(LinphoneCoreCbs *cbs, struct _LpConfig *config, void *userdata, void *system_context) { LinphoneCore *core = belle_sip_object_new(LinphoneCore); linphone_core_init(core, cbs, config, userdata); + _linphone_core_set_system_context(core, system_context); return core; } @@ -2280,7 +2293,7 @@ LinphoneCore *linphone_core_new_with_config(const LinphoneCoreVTable *vtable, st LinphoneCore *core = NULL; if (vtable != NULL) *local_vtable = *vtable; _linphone_core_cbs_set_v_table(cbs, local_vtable, TRUE); - core = _linphone_core_new_with_config(cbs, config, userdata); + core = _linphone_core_new_with_config(cbs, config, userdata, NULL); linphone_core_cbs_unref(cbs); return core; } @@ -6074,6 +6087,7 @@ static void linphone_core_uninit(LinphoneCore *lc) bctbx_list_free_with_data(lc->vtable_refs,(void (*)(void *))v_table_reference_destroy); ms_bandwidth_controller_destroy(lc->bw_controller); ms_factory_destroy(lc->factory); + if (lc->platform_helper) delete getPlatformHelpers(lc); bctbx_uninit_logger(); } @@ -6096,6 +6110,11 @@ static void set_sip_network_reachable(LinphoneCore* lc,bool_t is_sip_reachable, if (lc->sip_network_reachable==is_sip_reachable) return; // no change, ignore. lc->network_reachable_to_be_notified=TRUE; + + if (is_sip_reachable){ + getPlatformHelpers(lc)->setDnsServers(); + } + ms_message("SIP network reachability state is now [%s]",is_sip_reachable?"UP":"DOWN"); for(elem=linphone_core_get_proxy_config_list(lc);elem!=NULL;elem=elem->next){ LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)elem->data; @@ -6896,40 +6915,6 @@ const char * linphone_core_get_video_preset(const LinphoneCore *lc) { return lp_config_get_string(lc->config, "video", "preset", NULL); } -#ifdef __ANDROID__ -static int linphone_core_call_void_method(jobject obj, jmethodID id) { - JNIEnv *env=ms_get_jni_env(); - if (env && obj) { - env->CallVoidMethod(obj,id); - if (env->ExceptionCheck()) { - env->ExceptionClear(); - return -1; - } else - return 0; - } else - return -1; -} - -void linphone_core_wifi_lock_acquire(LinphoneCore *lc) { - if (linphone_core_call_void_method(lc->wifi_lock,lc->wifi_lock_acquire_id)) - ms_warning("No wifi lock configured or not usable for core [%p]",lc); -} - -void linphone_core_wifi_lock_release(LinphoneCore *lc) { - if (linphone_core_call_void_method(lc->wifi_lock,lc->wifi_lock_release_id)) - ms_warning("No wifi lock configured or not usable for core [%p]",lc); -} - -void linphone_core_multicast_lock_acquire(LinphoneCore *lc) { - if (linphone_core_call_void_method(lc->multicast_lock,lc->multicast_lock_acquire_id)) - ms_warning("No multicast lock configured or not usable for core [%p]",lc); -} - -void linphone_core_multicast_lock_release(LinphoneCore *lc) { - if (linphone_core_call_void_method(lc->multicast_lock,lc->multicast_lock_release_id)) - ms_warning("No wifi lock configured or not usable for core [%p]",lc); -} -#endif LINPHONE_PUBLIC const char *linphone_core_log_collection_upload_state_to_string(const LinphoneCoreLogCollectionUploadState lcus) { diff --git a/coreapi/linphonecore_jni.cc b/coreapi/linphonecore_jni.cc index 27002061b..8a3687f07 100644 --- a/coreapi/linphonecore_jni.cc +++ b/coreapi/linphonecore_jni.cc @@ -1635,7 +1635,7 @@ extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_newLinphoneCore(JNIEnv* ,jobject jlistener ,jstring juserConfig ,jstring jfactoryConfig - ,jobject juserdata){ + ,jobject juserdata, jobject context){ const char* userConfig = GetStringUTFChars(env, juserConfig); const char* factoryConfig = GetStringUTFChars(env, jfactoryConfig); @@ -1645,11 +1645,12 @@ extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_newLinphoneCore(JNIEnv* LinphoneCoreVTable *vTable = linphone_core_v_table_new(); LinphoneCoreData* ldata = new LinphoneCoreData(env, thiz, vTable, jlistener, ljb); linphone_core_v_table_set_user_data(vTable, ldata); - + LinphoneCoreCbs *cbs = linphone_factory_create_core_cbs(linphone_factory_get()); + _linphone_core_cbs_set_v_table(cbs, vTable, TRUE); jobject core = env->NewGlobalRef(thiz); ljb->setCore(core); - LinphoneCore *lc = linphone_core_new(vTable, userConfig, factoryConfig, ljb); + LinphoneCore *lc = linphone_factory_create_core_2(linphone_factory_get(), cbs, userConfig, factoryConfig, ljb, context); jlong nativePtr = (jlong)lc; ReleaseStringUTFChars(env, juserConfig, userConfig); @@ -1661,18 +1662,8 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_delete(JNIEnv* env, jobj LinphoneCore *lc=(LinphoneCore*)native_ptr; LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data(lc); - jobject multicast_lock = lc->multicast_lock; - jobject multicast_lock_class = lc->multicast_lock_class; - jobject wifi_lock = lc->wifi_lock; - jobject wifi_lock_class = lc->wifi_lock_class; - linphone_core_destroy(lc); - if (wifi_lock) env->DeleteGlobalRef(wifi_lock); - if (wifi_lock_class) env->DeleteGlobalRef(wifi_lock_class); - if (multicast_lock) env->DeleteGlobalRef(multicast_lock); - if (multicast_lock_class) env->DeleteGlobalRef(multicast_lock_class); - if (ljb) { jobject core = ljb->getCore(); if (core) { @@ -5949,43 +5940,9 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setAndroidPowerManager(J /*released in Java_org_linphone_core_LinphoneCoreImpl_delete*/ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setAndroidWifiLock(JNIEnv *env, jobject thiz, jlong ptr, jobject wifi_lock) { -#ifdef __ANDROID__ - LinphoneCore *lc=(LinphoneCore*)ptr; - if (lc->wifi_lock) { - env->DeleteGlobalRef(lc->wifi_lock); - env->DeleteGlobalRef(lc->wifi_lock_class); - } - if (wifi_lock != NULL) { - lc->wifi_lock=env->NewGlobalRef(wifi_lock); - lc->wifi_lock_class = env->FindClass("android/net/wifi/WifiManager$WifiLock"); - lc->wifi_lock_class = (jclass)env->NewGlobalRef(lc->wifi_lock_class); /*to make sure methodid are preserved*/ - lc->wifi_lock_acquire_id = env->GetMethodID(lc->wifi_lock_class, "acquire", "()V"); - lc->wifi_lock_release_id = env->GetMethodID(lc->wifi_lock_class, "release", "()V"); - } else { - lc->wifi_lock=NULL; - lc->wifi_lock_class=NULL; - } -#endif } /*released in Java_org_linphone_core_LinphoneCoreImpl_delete*/ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setAndroidMulticastLock(JNIEnv *env, jobject thiz, jlong ptr, jobject multicast_lock) { -#ifdef __ANDROID__ - LinphoneCore *lc=(LinphoneCore*)ptr; - if (lc->multicast_lock) { - env->DeleteGlobalRef(lc->multicast_lock); - env->DeleteGlobalRef(lc->multicast_lock_class); - } - if (multicast_lock != NULL) { - lc->multicast_lock=env->NewGlobalRef(multicast_lock); - lc->multicast_lock_class = env->FindClass("android/net/wifi/WifiManager$MulticastLock"); - lc->multicast_lock_class = (jclass)env->NewGlobalRef(lc->multicast_lock_class);/*to make sure methodid are preserved*/ - lc->multicast_lock_acquire_id = env->GetMethodID(lc->multicast_lock_class, "acquire", "()V"); - lc->multicast_lock_release_id = env->GetMethodID(lc->multicast_lock_class, "release", "()V"); - } else { - lc->multicast_lock=NULL; - lc->multicast_lock_class=NULL; - } -#endif } extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_getAudioDscp(JNIEnv* env,jobject thiz,jlong ptr){ diff --git a/coreapi/platform-helpers.cpp b/coreapi/platform-helpers.cpp new file mode 100644 index 000000000..05bbc00e6 --- /dev/null +++ b/coreapi/platform-helpers.cpp @@ -0,0 +1,49 @@ +/* +linphone +Copyright (C) 2017 Belledonne Communications SARL + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "private.h" + + +namespace LinphonePrivate{ + +PlatformHelpers::~PlatformHelpers(){ +} + +StubbedPlatformHelpers::StubbedPlatformHelpers(LinphoneCore *lc) : PlatformHelpers(lc){ +} + +void StubbedPlatformHelpers::setDnsServers(){ +} +void StubbedPlatformHelpers::acquireWifiLock(){ +} +void StubbedPlatformHelpers::releaseWifiLock(){ +} +void StubbedPlatformHelpers::acquireMcastLock(){ +} +void StubbedPlatformHelpers::releaseMcastLock(){ +} +void StubbedPlatformHelpers::acquireCpuLock(){ +} +void StubbedPlatformHelpers::releaseCpuLock(){ +} + +StubbedPlatformHelpers::~StubbedPlatformHelpers(){ +} + +} \ No newline at end of file diff --git a/coreapi/platform-helpers.h b/coreapi/platform-helpers.h new file mode 100644 index 000000000..8d4b6acf4 --- /dev/null +++ b/coreapi/platform-helpers.h @@ -0,0 +1,64 @@ +/* +linphone +Copyright (C) 2017 Belledonne Communications SARL + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef platform_helpers_h +#define platform_helpers_h + + +namespace LinphonePrivate{ + +/** + * This interface aims at abstracting some features offered by the platform, most often mobile platforms. + * A per platform implementation is to be made to implement these features, if available on the platform + */ +class PlatformHelpers{ + public: + //This method shall retrieve DNS server list from the platform and assign it to the core. + virtual void setDnsServers() = 0; + virtual void acquireWifiLock() = 0; + virtual void releaseWifiLock() = 0; + virtual void acquireMcastLock() = 0; + virtual void releaseMcastLock() = 0; + virtual void acquireCpuLock() = 0; + virtual void releaseCpuLock() = 0; + virtual ~PlatformHelpers(); + protected: + PlatformHelpers(LinphoneCore *lc) : mCore(lc){ + } + LinphoneCore *mCore; +}; + +class StubbedPlatformHelpers : public PlatformHelpers{ +public: + StubbedPlatformHelpers(LinphoneCore *lc); + virtual void setDnsServers(); + virtual void acquireWifiLock(); + virtual void releaseWifiLock(); + virtual void acquireMcastLock(); + virtual void releaseMcastLock(); + virtual void acquireCpuLock(); + virtual void releaseCpuLock(); + virtual ~StubbedPlatformHelpers(); +}; + +PlatformHelpers *createAndroidPlatformHelpers(LinphoneCore *lc, void *system_context); + +}//end of namespace + +#endif diff --git a/coreapi/private.h b/coreapi/private.h index eca250923..4cf7346a0 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -31,6 +31,7 @@ #include "linphone/tunnel.h" #include "linphone/core_utils.h" #include "linphone/conference.h" + #include "address/address.h" #include "c-wrapper/internal/c-sal.h" #include "core/core.h" @@ -39,6 +40,11 @@ #include "sal/message-op.h" #include "sal/presence-op.h" #include "sal/register-op.h" + +#ifdef __cplusplus +#include "platform-helpers.h" +#endif + #include "linphone/sipsetup.h" #include "quality_reporting.h" #include "linphone/ringtoneplayer.h" @@ -815,6 +821,8 @@ struct _LinphoneCore // For migration purposes LinphonePrivate::Core cppCore; + void *platform_helper; /*is a LinphonePrivate::PlatformHelpers but cannot be used as is because private.h is compiled as C in testers.*/ + LinphoneGlobalState state; struct _LpConfig *config; MSList *default_audio_codecs; @@ -920,16 +928,6 @@ struct _LinphoneCore LinphoneContent *log_collection_upload_information; LinphoneCoreCbs *current_cbs; // the latest LinphoneCoreCbs object to call a callback, see linphone_core_get_current_cbs() LinphoneRingtonePlayer *ringtoneplayer; -#ifdef __ANDROID__ - jobject wifi_lock; - jclass wifi_lock_class; - jmethodID wifi_lock_acquire_id; - jmethodID wifi_lock_release_id; - jobject multicast_lock; - jclass multicast_lock_class; - jmethodID multicast_lock_acquire_id; - jmethodID multicast_lock_release_id; -#endif LinphoneVcardContext *vcard_context; /*for tests only*/ @@ -945,6 +943,10 @@ struct _LinphoneCore MSBandwidthController *bw_controller; }; +#ifdef __cplusplus +#define getPlatformHelpers(lc) static_cast(lc->platform_helper) +#endif + struct _LinphoneEvent{ belle_sip_object_t base; @@ -1078,6 +1080,8 @@ LINPHONE_PUBLIC int linphone_core_get_call_history_size(LinphoneCore *lc); int linphone_core_get_edge_bw(LinphoneCore *lc); int linphone_core_get_edge_ptime(LinphoneCore *lc); +LinphoneCore *_linphone_core_new_with_config(LinphoneCoreCbs *cbs, struct _LpConfig *config, void *userdata, void *system_context); + int linphone_upnp_init(LinphoneCore *lc); void linphone_upnp_destroy(LinphoneCore *lc); @@ -1501,12 +1505,6 @@ SalStreamDir sal_dir_from_call_params_dir(LinphoneMediaDirection cpdir); */ void ** linphone_content_get_cryptoContext_address(LinphoneContent *content); -#ifdef __ANDROID__ -void linphone_core_wifi_lock_acquire(LinphoneCore *lc); -void linphone_core_wifi_lock_release(LinphoneCore *lc); -void linphone_core_multicast_lock_acquire(LinphoneCore *lc); -void linphone_core_multicast_lock_release(LinphoneCore *lc); -#endif struct _VTableReference{ LinphoneCoreCbs *cbs; diff --git a/include/linphone/factory.h b/include/linphone/factory.h index 26a5aa29b..7db488fbe 100644 --- a/include/linphone/factory.h +++ b/include/linphone/factory.h @@ -66,6 +66,32 @@ LINPHONE_PUBLIC void linphone_factory_clean(void); LINPHONE_PUBLIC LinphoneCore *linphone_factory_create_core(const LinphoneFactory *factory, LinphoneCoreCbs *cbs, const char *config_path, const char *factory_config_path); + +/** + * Instanciate a #LinphoneCore object. + * + * The LinphoneCore object is the primary handle for doing all phone actions. + * It should be unique within your application. + * @param factory The #LinphoneFactory singleton. + * @param cbs a #LinphoneCoreCbs object holding your application callbacks. A reference + * will be taken on it until the destruciton of the core or the unregistration + * with linphone_core_remove_cbs(). + * @param config_path a path to a config file. If it does not exists it will be created. + * The config file is used to store all settings, call logs, friends, proxies... so that all these settings + * become persistent over the life of the LinphoneCore object. + * It is allowed to set a NULL config file. In that case LinphoneCore will not store any settings. + * @param factory_config_path a path to a read-only config file that can be used to + * to store hard-coded preference such as proxy settings or internal preferences. + * The settings in this factory file always override the one in the normal config file. + * It is OPTIONAL, use NULL if unneeded. + * @param user_data an application pointer associated with the returned core. + * @param system_context a pointer to a system object required by the core to operate. Currently it is required to pass an android Context on android, pass NULL on other platforms. + * @see linphone_core_new_with_config + */ +LINPHONE_PUBLIC LinphoneCore *linphone_factory_create_core_2(const LinphoneFactory *factory, LinphoneCoreCbs *cbs, + const char *config_path, const char *factory_config_path, void *user_data, void *system_context); + + /** * Instantiates a LinphoneCore object with a given LpConfig. * @@ -80,6 +106,22 @@ LINPHONE_PUBLIC LinphoneCore *linphone_factory_create_core(const LinphoneFactory */ LINPHONE_PUBLIC LinphoneCore *linphone_factory_create_core_with_config(const LinphoneFactory *factory, LinphoneCoreCbs *cbs, LinphoneConfig *config); +/** + * Instantiates a LinphoneCore object with a given LpConfig. + * + * @param factory The #LinphoneFactory singleton. + * The LinphoneCore object is the primary handle for doing all phone actions. + * It should be unique within your application. + * @param cbs a #LinphoneCoreCbs object holding your application callbacks. A reference + * will be taken on it until the destruciton of the core or the unregistration + * with linphone_core_remove_cbs(). + * @param config a pointer to an LpConfig object holding the configuration of the LinphoneCore to be instantiated. + * @param user_data an application pointer associated with the returned core. + * @param system_context a pointer to a system object required by the core to operate. Currently it is required to pass an android Context on android, pass NULL on other platforms. + * @see linphone_core_new + */ +LINPHONE_PUBLIC LinphoneCore *linphone_factory_create_core_with_config_2(const LinphoneFactory *factory, LinphoneCoreCbs *cbs, LinphoneConfig *config, void *user_data, void *system_context); + /** * Instanciate a #LinphoneCoreCbs object. * @return a new #LinphoneCoreCbs. diff --git a/java/impl/org/linphone/core/LinphoneCoreFactoryImpl.java b/java/impl/org/linphone/core/LinphoneCoreFactoryImpl.java index 915e6e0c0..ba951efb4 100644 --- a/java/impl/org/linphone/core/LinphoneCoreFactoryImpl.java +++ b/java/impl/org/linphone/core/LinphoneCoreFactoryImpl.java @@ -107,9 +107,8 @@ public class LinphoneCoreFactoryImpl extends LinphoneCoreFactory { MediastreamerAndroidContext.setContext(context); File user = userConfig == null ? null : new File(userConfig); File factory = factoryConfig == null ? null : new File(factoryConfig); - LinphoneCore lc = new LinphoneCoreImpl(listener, user, factory, userdata); + LinphoneCore lc = new LinphoneCoreImpl(listener, user, factory, userdata, context); lc.enableDownloadOpenH264(openh264DownloadEnabled); - if (context != null) lc.setContext(context); return lc; } catch (IOException e) { throw new LinphoneCoreException("Cannot create LinphoneCore",e); @@ -123,9 +122,8 @@ public class LinphoneCoreFactoryImpl extends LinphoneCoreFactory { boolean openh264DownloadEnabled = false; if (context != null) openh264DownloadEnabled = loadingDownloadedOpenH264(fcontext); MediastreamerAndroidContext.setContext(context); - LinphoneCore lc = new LinphoneCoreImpl(listener); + LinphoneCore lc = new LinphoneCoreImpl(listener, context); lc.enableDownloadOpenH264(openh264DownloadEnabled); - if (context != null) lc.setContext(context); return lc; } catch (IOException e) { throw new LinphoneCoreException("Cannot create LinphoneCore",e); diff --git a/java/impl/org/linphone/core/LinphoneCoreImpl.java b/java/impl/org/linphone/core/LinphoneCoreImpl.java index 671fb1fcc..cd076e837 100644 --- a/java/impl/org/linphone/core/LinphoneCoreImpl.java +++ b/java/impl/org/linphone/core/LinphoneCoreImpl.java @@ -47,7 +47,7 @@ class LinphoneCoreImpl implements LinphoneCore { private AudioManager mAudioManager = null; private boolean openh264DownloadEnabled = false; private boolean mSpeakerEnabled = false; - private native long newLinphoneCore(LinphoneCoreListener listener,String userConfig,String factoryConfig,Object userdata); + private native long newLinphoneCore(LinphoneCoreListener listener,String userConfig,String factoryConfig,Object userdata, Object context); private native void iterate(long nativePtr); private native LinphoneProxyConfig getDefaultProxyConfig(long nativePtr); @@ -196,15 +196,17 @@ class LinphoneCoreImpl implements LinphoneCore { private native Object createFriendWithAddress(long nativePtr, String address); private native int getIncomingTimeout(long nativePtr); - LinphoneCoreImpl(LinphoneCoreListener listener, File userConfig, File factoryConfig, Object userdata) throws IOException { + LinphoneCoreImpl(LinphoneCoreListener listener, File userConfig, File factoryConfig, Object userdata, Object context) throws IOException { mListener = listener; String user = userConfig == null ? null : userConfig.getCanonicalPath(); String factory = factoryConfig == null ? null : factoryConfig.getCanonicalPath(); - nativePtr = newLinphoneCore(listener, user, factory, userdata); + nativePtr = newLinphoneCore(listener, user, factory, userdata, context); + setContext(context); } - LinphoneCoreImpl(LinphoneCoreListener listener) throws IOException { + LinphoneCoreImpl(LinphoneCoreListener listener, Object context) throws IOException { mListener = listener; - nativePtr = newLinphoneCore(listener,null,null,null); + nativePtr = newLinphoneCore(listener,null,null,null, context); + setContext(context); } protected void finalize() throws Throwable { @@ -223,19 +225,7 @@ class LinphoneCoreImpl implements LinphoneCore { ApplicationInfo info = mContext.getApplicationInfo(); reloadMsPlugins(info.nativeLibraryDir); mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); - setAndroidPowerManager(mContext.getSystemService(Context.POWER_SERVICE)); - if (Version.sdkAboveOrEqual(Version.API12_HONEYCOMB_MR1_31X)) { - WifiManager wifiManager=(WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); - WifiLock lock = wifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "linphonecore ["+ nativePtr+"] wifi-lock"); - lock.setReferenceCounted(true); - setAndroidWifiLock(nativePtr,lock); - } - if (Version.sdkAboveOrEqual(Version.API14_ICE_CREAM_SANDWICH_40)) { - WifiManager wifiManager=(WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); - MulticastLock lock = wifiManager.createMulticastLock("linphonecore ["+ nativePtr+"] multicast-lock"); - lock.setReferenceCounted(true); - setAndroidMulticastLock(nativePtr, lock); - } + } public Context getContext() { diff --git a/java/impl/org/linphone/core/util/AndroidPlatformHelper.java b/java/impl/org/linphone/core/util/AndroidPlatformHelper.java new file mode 100644 index 000000000..aeb44e15b --- /dev/null +++ b/java/impl/org/linphone/core/util/AndroidPlatformHelper.java @@ -0,0 +1,114 @@ +/* +AndroidPlatformHelper.java +Copyright (C) 2017 Belledonne Communications, Grenoble, France + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +package org.linphone.core.util; + +import org.linphone.mediastream.Log; + +import android.net.wifi.WifiManager; +import android.net.wifi.WifiManager.MulticastLock; +import android.net.wifi.WifiManager.WifiLock; +import android.content.Context; +import android.net.ConnectivityManager; +import android.net.Network; +import android.net.NetworkInfo; +import android.os.PowerManager; +import android.os.PowerManager.WakeLock; + +import java.net.InetAddress; +import java.util.List; +import android.os.Build; + +/** + * This class is instanciated directly by the linphone library in order to access specific features only accessible in java. +**/ + +public class AndroidPlatformHelper{ + private WifiManager.WifiLock mWifiLock; + private WifiManager.MulticastLock mMcastLock; + private ConnectivityManager mConnectivityManager; + private PowerManager mPowerManager; + private WakeLock mWakeLock; + + public AndroidPlatformHelper(Object ctx_obj){ + Context ctx = (Context) ctx_obj; + WifiManager wifiMgr = ctx.getSystemService(WifiManager.class); + mPowerManager = (PowerManager) ctx.getSystemService(Context.POWER_SERVICE); + mConnectivityManager = (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE); + + mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "AndroidPlatformHelper"); + mWakeLock.setReferenceCounted(true); + mMcastLock = wifiMgr.createMulticastLock("AndroidPlatformHelper"); + mMcastLock.setReferenceCounted(true); + mWifiLock = wifiMgr.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "AndroidPlatformHelper"); + mWifiLock.setReferenceCounted(true); + } + + public Object getPowerManager(){ + return mPowerManager; + } + + public String[] getDnsServers() { + if (mConnectivityManager == null || Build.VERSION.SDK_INT < Build.VERSION_CODES.M) + return null; + + if (mConnectivityManager.getActiveNetwork() == null + || mConnectivityManager.getLinkProperties(mConnectivityManager.getActiveNetwork()) == null) + return null; + + int i = 0; + List inetServers = null; + inetServers = mConnectivityManager.getLinkProperties(mConnectivityManager.getActiveNetwork()).getDnsServers(); + + String[] servers = new String[inetServers.size()]; + + for (InetAddress address : inetServers) { + servers[i++] = address.getHostAddress(); + } + Log.i("getDnsServers() returning"); + return servers; + } + public void acquireWifiLock(){ + Log.i("acquireWifiLock()"); + mWifiLock.acquire(); + } + public void releaseWifiLock(){ + Log.i("releaseWifiLock()"); + mWifiLock.release(); + } + public void acquireMcastLock(){ + Log.i("acquireMcastLock()"); + mMcastLock.acquire(); + } + public void releaseMcastLock(){ + Log.i("releaseMcastLock()"); + mMcastLock.release(); + } + public void acquireCpuLock(){ + Log.i("acquireCpuLock()"); + mWakeLock.acquire(); + } + public void releaseCpuLock(){ + Log.i("releaseCpuLock()"); + mWakeLock.release(); + } +}; + +