/*
* Copyright (c) 2010-2019 Belledonne Communications SARL.
*
* This file is part of linphone-android
* (see https://www.linphone.org).
*
* 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 3 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, see .
*/
package org.linphone.settings;
import android.content.Intent;
import android.os.Bundle;
import android.text.InputType;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import org.linphone.LinphoneManager;
import org.linphone.R;
import org.linphone.assistant.PhoneAccountLinkingAssistantActivity;
import org.linphone.core.AVPFMode;
import org.linphone.core.Address;
import org.linphone.core.AuthInfo;
import org.linphone.core.Core;
import org.linphone.core.Factory;
import org.linphone.core.NatPolicy;
import org.linphone.core.ProxyConfig;
import org.linphone.core.TransportType;
import org.linphone.core.tools.Log;
import org.linphone.settings.widget.BasicSetting;
import org.linphone.settings.widget.ListSetting;
import org.linphone.settings.widget.SettingListenerBase;
import org.linphone.settings.widget.SwitchSetting;
import org.linphone.settings.widget.TextSetting;
import org.linphone.utils.PushNotificationUtils;
public class AccountSettingsFragment extends SettingsFragment {
private View mRootView;
private int mAccountIndex;
private ProxyConfig mProxyConfig;
private AuthInfo mAuthInfo;
private boolean mIsNewlyCreatedAccount;
private TextSetting mUsername,
mUserId,
mPassword,
mDomain,
mDisplayName,
mProxy,
mStun,
mExpire,
mPrefix,
mAvpfInterval;
private SwitchSetting mDisable,
mUseAsDefault,
mOutboundProxy,
mIce,
mAvpf,
mReplacePlusBy00,
mPush;
private BasicSetting mChangePassword, mDeleteAccount, mLinkAccount;
private ListSetting mTransport;
@Nullable
@Override
public View onCreateView(
LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
mRootView = inflater.inflate(R.layout.settings_account, container, false);
loadSettings();
mIsNewlyCreatedAccount = true;
mAccountIndex = getArguments().getInt("Account", -1);
if (mAccountIndex == -1 && savedInstanceState != null) {
mAccountIndex = savedInstanceState.getInt("Account", -1);
}
mProxyConfig = null;
Core core = LinphoneManager.getCore();
if (mAccountIndex >= 0 && core != null) {
ProxyConfig[] proxyConfigs = core.getProxyConfigList();
if (proxyConfigs.length > mAccountIndex) {
mProxyConfig = proxyConfigs[mAccountIndex];
mIsNewlyCreatedAccount = false;
} else {
Log.e("[Account Settings] Proxy config not found !");
}
}
return mRootView;
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("Account", mAccountIndex);
}
@Override
public void onResume() {
super.onResume();
updateValues();
}
@Override
public void onPause() {
super.onPause();
if (mIsNewlyCreatedAccount) {
Core core = LinphoneManager.getCore();
if (core != null && mProxyConfig != null && mAuthInfo != null) {
core.addAuthInfo(mAuthInfo);
core.addProxyConfig(mProxyConfig);
if (mUseAsDefault.isChecked()) {
core.setDefaultProxyConfig(mProxyConfig);
}
}
}
}
private void loadSettings() {
mUsername = mRootView.findViewById(R.id.pref_username);
mUserId = mRootView.findViewById(R.id.pref_auth_userid);
mPassword = mRootView.findViewById(R.id.pref_passwd);
mPassword.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
mDomain = mRootView.findViewById(R.id.pref_domain);
mDisplayName = mRootView.findViewById(R.id.pref_display_name);
mDisplayName.setInputType(
InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PERSON_NAME);
mProxy = mRootView.findViewById(R.id.pref_proxy);
mProxy.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_URI);
mStun = mRootView.findViewById(R.id.pref_stun_server);
mStun.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_URI);
mExpire = mRootView.findViewById(R.id.pref_expire);
mExpire.setInputType(InputType.TYPE_CLASS_NUMBER);
mPrefix = mRootView.findViewById(R.id.pref_prefix);
mPrefix.setInputType(InputType.TYPE_CLASS_NUMBER);
mAvpfInterval = mRootView.findViewById(R.id.pref_avpf_rr_interval);
mAvpfInterval.setInputType(InputType.TYPE_CLASS_NUMBER);
mDisable = mRootView.findViewById(R.id.pref_disable_account);
mUseAsDefault = mRootView.findViewById(R.id.pref_default_account);
mOutboundProxy = mRootView.findViewById(R.id.pref_enable_outbound_proxy);
mIce = mRootView.findViewById(R.id.pref_ice_enable);
mAvpf = mRootView.findViewById(R.id.pref_avpf);
mReplacePlusBy00 = mRootView.findViewById(R.id.pref_escape_plus);
mPush = mRootView.findViewById(R.id.pref_push_notification);
mPush.setVisibility(
PushNotificationUtils.isAvailable(getActivity()) ? View.VISIBLE : View.GONE);
mChangePassword = mRootView.findViewById(R.id.pref_change_password);
mChangePassword.setVisibility(View.GONE); // TODO add feature
mDeleteAccount = mRootView.findViewById(R.id.pref_delete_account);
mLinkAccount = mRootView.findViewById(R.id.pref_link_account);
mTransport = mRootView.findViewById(R.id.pref_transport);
initTransportList();
}
private void setListeners() {
mUsername.setListener(
new SettingListenerBase() {
@Override
public void onTextValueChanged(String newValue) {
if (newValue.isEmpty()) {
return;
}
if (mAuthInfo != null) {
mAuthInfo.setUsername(newValue);
} else {
Log.e("[Account Settings] No auth info !");
}
if (mProxyConfig != null) {
mProxyConfig.edit();
Address identity = mProxyConfig.getIdentityAddress();
if (identity != null) {
identity.setUsername(newValue);
}
mProxyConfig.setIdentityAddress(identity);
mProxyConfig.done();
} else {
Log.e("[Account Settings] No proxy config !");
}
}
});
mUserId.setListener(
new SettingListenerBase() {
@Override
public void onTextValueChanged(String newValue) {
if (mAuthInfo != null) {
mAuthInfo.setUserid(newValue);
Core core = LinphoneManager.getCore();
if (core != null) {
core.refreshRegisters();
}
} else {
Log.e("[Account Settings] No auth info !");
}
}
});
mPassword.setListener(
new SettingListenerBase() {
@Override
public void onTextValueChanged(String newValue) {
if (mAuthInfo != null) {
mAuthInfo.setHa1(null);
mAuthInfo.setPassword(newValue);
// Reset algorithm to generate correct hash depending on
// algorithm set in next to come 401
mAuthInfo.setAlgorithm(null);
Core core = LinphoneManager.getCore();
if (core != null) {
core.addAuthInfo(mAuthInfo);
core.refreshRegisters();
}
} else {
Log.e("[Account Settings] No auth info !");
}
}
});
mDomain.setListener(
new SettingListenerBase() {
@Override
public void onTextValueChanged(String newValue) {
if (newValue.isEmpty()) {
return;
}
if (newValue.contains(":")) {
Log.e(
"[Account Settings] Do not specify port information inside domain field !");
return;
}
if (mAuthInfo != null) {
mAuthInfo.setDomain(newValue);
} else {
Log.e("[Account Settings] No auth info !");
}
if (mProxyConfig != null) {
mProxyConfig.edit();
Address identity = mProxyConfig.getIdentityAddress();
if (identity != null) {
identity.setDomain(newValue);
}
mProxyConfig.setIdentityAddress(identity);
mProxyConfig.done();
} else {
Log.e("[Account Settings] No proxy config !");
}
}
});
mDisplayName.setListener(
new SettingListenerBase() {
@Override
public void onTextValueChanged(String newValue) {
if (mProxyConfig != null) {
mProxyConfig.edit();
Address identity = mProxyConfig.getIdentityAddress();
if (identity != null) {
identity.setDisplayName(newValue);
}
mProxyConfig.setIdentityAddress(identity);
mProxyConfig.done();
} else {
Log.e("[Account Settings] No proxy config !");
}
}
});
mProxy.setListener(
new SettingListenerBase() {
@Override
public void onTextValueChanged(String newValue) {
if (mProxyConfig != null) {
mProxyConfig.edit();
Address proxy = Factory.instance().createAddress(newValue);
if (proxy != null) {
mProxyConfig.setServerAddr(proxy.asString());
if (mOutboundProxy.isChecked()) {
mProxyConfig.setRoute(proxy.asString());
}
mTransport.setValue(proxy.getTransport().toInt());
}
mProxyConfig.done();
} else {
Log.e("[Account Settings] No proxy config !");
}
}
});
mStun.setListener(
new SettingListenerBase() {
@Override
public void onTextValueChanged(String newValue) {
if (mProxyConfig != null) {
mProxyConfig.edit();
NatPolicy natPolicy = mProxyConfig.getNatPolicy();
if (natPolicy == null) {
Core core = LinphoneManager.getCore();
if (core != null) {
natPolicy = core.createNatPolicy();
mProxyConfig.setNatPolicy(natPolicy);
}
}
if (natPolicy != null) {
natPolicy.setStunServer(newValue);
}
if (newValue == null || newValue.isEmpty()) {
mIce.setChecked(false);
}
mIce.setEnabled(newValue != null && !newValue.isEmpty());
mProxyConfig.done();
} else {
Log.e("[Account Settings] No proxy config !");
}
}
});
mExpire.setListener(
new SettingListenerBase() {
@Override
public void onTextValueChanged(String newValue) {
if (mProxyConfig != null) {
mProxyConfig.edit();
try {
mProxyConfig.setExpires(Integer.parseInt(newValue));
} catch (NumberFormatException nfe) {
Log.e(nfe);
}
mProxyConfig.done();
} else {
Log.e("[Account Settings] No proxy config !");
}
}
});
mPrefix.setListener(
new SettingListenerBase() {
@Override
public void onTextValueChanged(String newValue) {
if (mProxyConfig != null) {
mProxyConfig.edit();
mProxyConfig.setDialPrefix(newValue);
mProxyConfig.done();
} else {
Log.e("[Account Settings] No proxy config !");
}
}
});
mAvpfInterval.setListener(
new SettingListenerBase() {
@Override
public void onTextValueChanged(String newValue) {
if (mProxyConfig != null) {
mProxyConfig.edit();
try {
mProxyConfig.setAvpfRrInterval(Integer.parseInt(newValue));
} catch (NumberFormatException nfe) {
Log.e(nfe);
}
mProxyConfig.done();
} else {
Log.e("[Account Settings] No proxy config !");
}
}
});
mDisable.setListener(
new SettingListenerBase() {
@Override
public void onBoolValueChanged(boolean newValue) {
if (mProxyConfig != null) {
mProxyConfig.edit();
mProxyConfig.enableRegister(!newValue);
mProxyConfig.done();
} else {
Log.e("[Account Settings] No proxy config !");
}
}
});
mUseAsDefault.setListener(
new SettingListenerBase() {
@Override
public void onBoolValueChanged(boolean newValue) {
if (mProxyConfig != null) {
Core core = LinphoneManager.getCore();
if (core != null && newValue) {
core.setDefaultProxyConfig(mProxyConfig);
mUseAsDefault.setEnabled(false);
}
((SettingsActivity) getActivity())
.getSideMenuFragment()
.displayAccountsInSideMenu();
} else {
Log.e("[Account Settings] No proxy config !");
}
}
});
mOutboundProxy.setListener(
new SettingListenerBase() {
@Override
public void onBoolValueChanged(boolean newValue) {
if (mProxyConfig != null) {
mProxyConfig.edit();
if (newValue) {
mProxyConfig.setRoute(mProxy.getValue());
} else {
mProxyConfig.setRoute(null);
}
mProxyConfig.done();
} else {
Log.e("[Account Settings] No proxy config !");
}
}
});
mIce.setListener(
new SettingListenerBase() {
@Override
public void onBoolValueChanged(boolean newValue) {
if (mProxyConfig != null) {
mProxyConfig.edit();
NatPolicy natPolicy = mProxyConfig.getNatPolicy();
if (natPolicy == null) {
Core core = LinphoneManager.getCore();
if (core != null) {
natPolicy = core.createNatPolicy();
mProxyConfig.setNatPolicy(natPolicy);
}
}
if (natPolicy != null) {
natPolicy.enableIce(newValue);
}
mProxyConfig.done();
} else {
Log.e("[Account Settings] No proxy config !");
}
}
});
mAvpf.setListener(
new SettingListenerBase() {
@Override
public void onBoolValueChanged(boolean newValue) {
if (mProxyConfig != null) {
mProxyConfig.edit();
mProxyConfig.setAvpfMode(
newValue ? AVPFMode.Enabled : AVPFMode.Disabled);
mAvpfInterval.setEnabled(mProxyConfig.avpfEnabled());
mProxyConfig.done();
} else {
Log.e("[Account Settings] No proxy config !");
}
}
});
mReplacePlusBy00.setListener(
new SettingListenerBase() {
@Override
public void onBoolValueChanged(boolean newValue) {
if (mProxyConfig != null) {
mProxyConfig.edit();
mProxyConfig.setDialEscapePlus(newValue);
mProxyConfig.done();
} else {
Log.e("[Account Settings] No proxy config !");
}
}
});
mPush.setListener(
new SettingListenerBase() {
@Override
public void onBoolValueChanged(boolean newValue) {
if (mProxyConfig != null) {
mProxyConfig.edit();
mProxyConfig.setPushNotificationAllowed(newValue);
mProxyConfig.done();
} else {
Log.e("[Account Settings] No proxy config !");
}
}
});
mChangePassword.setListener(
new SettingListenerBase() {
@Override
public void onClicked() {
// TODO add feature
}
});
mDeleteAccount.setListener(
new SettingListenerBase() {
@Override
public void onClicked() {
Core core = LinphoneManager.getCore();
if (core != null) {
if (mProxyConfig != null) {
core.removeProxyConfig(mProxyConfig);
}
if (mAuthInfo != null) {
core.removeAuthInfo(mAuthInfo);
}
}
// Set a new default proxy config if the current one has been removed
if (core != null && core.getDefaultProxyConfig() == null) {
ProxyConfig[] proxyConfigs = core.getProxyConfigList();
if (proxyConfigs.length > 0) {
core.setDefaultProxyConfig(proxyConfigs[0]);
}
}
((SettingsActivity) getActivity())
.getSideMenuFragment()
.displayAccountsInSideMenu();
((SettingsActivity) getActivity()).goBack();
}
});
mLinkAccount.setListener(
new SettingListenerBase() {
@Override
public void onClicked() {
Intent assistant = new Intent();
assistant.setClass(
getActivity(), PhoneAccountLinkingAssistantActivity.class);
assistant.putExtra("AccountNumber", mAccountIndex);
startActivity(assistant);
}
});
mTransport.setListener(
new SettingListenerBase() {
@Override
public void onListValueChanged(int position, String newLabel, String newValue) {
if (mProxyConfig != null) {
mProxyConfig.edit();
String server = mProxyConfig.getServerAddr();
Address serverAddr = Factory.instance().createAddress(server);
if (serverAddr != null) {
try {
serverAddr.setTransport(
TransportType.fromInt(Integer.parseInt(newValue)));
server = serverAddr.asString();
mProxyConfig.setServerAddr(server);
if (mOutboundProxy.isChecked()) {
mProxyConfig.setRoute(server);
}
mProxy.setValue(server);
} catch (NumberFormatException nfe) {
Log.e(nfe);
}
}
mProxyConfig.done();
} else {
Log.e("[Account Settings] No proxy config !");
}
}
});
}
private void updateValues() {
Core core = LinphoneManager.getCore();
if (core == null) return;
// Create a proxy config if there is none
if (mProxyConfig == null) {
// Ensure the default configuration is loaded first
String defaultConfig = LinphonePreferences.instance().getDefaultDynamicConfigFile();
core.loadConfigFromXml(defaultConfig);
mProxyConfig = core.createProxyConfig();
mAuthInfo = Factory.instance().createAuthInfo(null, null, null, null, null, null);
mIsNewlyCreatedAccount = true;
}
if (mProxyConfig != null) {
Address identityAddress = mProxyConfig.getIdentityAddress();
mAuthInfo = mProxyConfig.findAuthInfo();
NatPolicy natPolicy = mProxyConfig.getNatPolicy();
if (natPolicy == null) {
natPolicy = core.createNatPolicy();
core.setNatPolicy(natPolicy);
}
if (mAuthInfo != null) {
mUserId.setValue(mAuthInfo.getUserid());
// If password is hashed we can't display it
mPassword.setValue(mAuthInfo.getPassword());
}
mUsername.setValue(identityAddress.getUsername());
mDomain.setValue(identityAddress.getDomain());
mDisplayName.setValue(identityAddress.getDisplayName());
mProxy.setValue(mProxyConfig.getServerAddr());
mStun.setValue(natPolicy.getStunServer());
mExpire.setValue(mProxyConfig.getExpires());
mPrefix.setValue(mProxyConfig.getDialPrefix());
mAvpfInterval.setValue(mProxyConfig.getAvpfRrInterval());
mAvpfInterval.setEnabled(mProxyConfig.avpfEnabled());
mDisable.setChecked(!mProxyConfig.registerEnabled());
mUseAsDefault.setChecked(mProxyConfig.equals(core.getDefaultProxyConfig()));
mUseAsDefault.setEnabled(!mUseAsDefault.isChecked());
String[] routes = mProxyConfig.getRoutes();
mOutboundProxy.setChecked(routes != null && routes.length > 0);
mIce.setChecked(natPolicy.iceEnabled());
mIce.setEnabled(
natPolicy.getStunServer() != null && !natPolicy.getStunServer().isEmpty());
mAvpf.setChecked(mProxyConfig.avpfEnabled());
mReplacePlusBy00.setChecked(mProxyConfig.getDialEscapePlus());
mPush.setChecked(mProxyConfig.isPushNotificationAllowed());
Address proxy = Factory.instance().createAddress(mProxyConfig.getServerAddr());
if (proxy != null) {
mTransport.setValue(proxy.getTransport().toInt());
}
mLinkAccount.setEnabled(
mProxyConfig.getDomain().equals(getString(R.string.default_domain)));
}
setListeners();
}
private void initTransportList() {
List entries = new ArrayList<>();
List values = new ArrayList<>();
entries.add(getString(R.string.pref_transport_udp));
values.add(String.valueOf(TransportType.Udp.toInt()));
entries.add(getString(R.string.pref_transport_tcp));
values.add(String.valueOf(TransportType.Tcp.toInt()));
if (!getResources().getBoolean(R.bool.disable_all_security_features_for_markets)) {
entries.add(getString(R.string.pref_transport_tls));
values.add(String.valueOf(TransportType.Tls.toInt()));
}
mTransport.setItems(entries, values);
}
}