Some sip setting changes and registration fix.
+change add/remove account UI.
+add auto. registration per profile.
+fix the infinite loop for incorrect username/password during registration.
Change-Id: Ic763073c21a8a6cebac77207981f45c2c2b2d5e4
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 9d2b092..29d62a2 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -17,9 +17,11 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Sip Account Settings</string>
<string name="sip_settings_activity_title">Sip Settings Activity</string>
- <string name="auto_registration">Auto Registration</string>
+
+ <string name="auto_reg">Auto Registration</string>
<string name="call_priority">Outgoing Call via SIP</string>
<string name="add_sip_account">Add SIP account</string>
+ <string name="remove_sip_account">Remove SIP account</string>
<string name="sip_account_list">SIP accounts</string>
<string name="sip_menu_save">Save</string>
@@ -48,7 +50,11 @@
<string name="transport_summary">TCP</string>
<string name="send_keepalive_title">Send keep-alive</string>
<string name="send_keepalive_summary">Send SIP keep-alive messages</string>
+ <string name="auto_registration_title">Auto. Registration</string>
+ <string name="auto_registration_summary">Register the profile automatically</string>
+ <string name="sip_menu_enable_autoregister">Enable auto registration</string>
+ <string name="sip_menu_disable_autoregister">Disable auto registration</string>
<string name="sip_menu_register">Register the account</string>
<string name="sip_menu_unregister">Unregister the account</string>
<string name="sip_menu_edit">Edit the account</string>
@@ -66,4 +72,5 @@
<string name="port">Port</string>
<string name="transport">Protocol</string>
<string name="send_keepalive">SendKeepAlive</string>
+ <string name="auto_registration">AutoRegistration</string>
</resources>
diff --git a/res/xml/sip_edit.xml b/res/xml/sip_edit.xml
index fd44bb2..18306a9 100644
--- a/res/xml/sip_edit.xml
+++ b/res/xml/sip_edit.xml
@@ -88,4 +88,11 @@
android:defaultValue="false"
android:summary="@string/send_keepalive_summary"
android:dialogTitle="@string/send_keepalive_title"/>
+
+ <CheckBoxPreference
+ android:key="@string/auto_registration"
+ android:title="@string/auto_registration_title"
+ android:defaultValue="true"
+ android:summary="@string/auto_registration_summary"
+ android:dialogTitle="@string/auto_registration_title"/>
</PreferenceScreen>
diff --git a/res/xml/sip_setting.xml b/res/xml/sip_setting.xml
index 504b90e..20d7269 100644
--- a/res/xml/sip_setting.xml
+++ b/res/xml/sip_setting.xml
@@ -17,17 +17,14 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:title="@string/sip_settings_activity_title">
- <CheckBoxPreference android:key="auto_registration"
- android:title="@string/auto_registration">
- </CheckBoxPreference>
-
<CheckBoxPreference android:key="sip_call_first"
android:title="@string/call_priority">
</CheckBoxPreference>
- <PreferenceScreen android:key="add_sip_account"
- android:title="@string/add_sip_account">
- </PreferenceScreen>
+ <CheckBoxPreference android:key="auto_reg"
+ android:title="@string/auto_reg"
+ android:summary="@string/auto_registration_summary">
+ </CheckBoxPreference>
<PreferenceCategory android:key="sip_account_list" android:title="@string/sip_account_list">
</PreferenceCategory>
diff --git a/src/android/net/sip/SipProfile.java b/src/android/net/sip/SipProfile.java
index 91072c7..5410a33 100644
--- a/src/android/net/sip/SipProfile.java
+++ b/src/android/net/sip/SipProfile.java
@@ -47,6 +47,7 @@
private String mProtocol = ListeningPoint.UDP;
private String mProfileName;
private boolean mSendKeepAlive = false;
+ private boolean mAutoRegistration = true;
/** @hide */
public static final Parcelable.Creator<SipProfile> CREATOR =
@@ -213,6 +214,19 @@
return this;
}
+
+ /**
+ * Sets the auto. registration flag.
+ *
+ * @param flag true if the profile will be registered automatically,
+ * false otherwise
+ * @return this builder object
+ */
+ public Builder setAutoRegistration(boolean flag) {
+ mProfile.mAutoRegistration = flag;
+ return this;
+ }
+
/**
* Builds and returns the SIP profile object.
*
@@ -249,6 +263,7 @@
mProtocol = in.readString();
mProfileName = in.readString();
mSendKeepAlive = (in.readInt() == 0) ? false : true;
+ mAutoRegistration = (in.readInt() == 0) ? false : true;
}
/** @hide */
@@ -260,6 +275,7 @@
out.writeString(mProtocol);
out.writeString(mProfileName);
out.writeInt(mSendKeepAlive ? 1 : 0);
+ out.writeInt(mAutoRegistration ? 1 : 0);
}
/** @hide */
@@ -375,4 +391,13 @@
public boolean getSendKeepAlive() {
return mSendKeepAlive;
}
+
+ /**
+ * Gets the flag of 'Auto Registration'.
+ *
+ * @return the flag of registering the profile automatically.
+ */
+ public boolean getAutoRegistration() {
+ return mAutoRegistration;
+ }
}
diff --git a/src/com/android/settings/sip/SipEditor.java b/src/com/android/settings/sip/SipEditor.java
index 7fcd8fe..45168f6 100644
--- a/src/com/android/settings/sip/SipEditor.java
+++ b/src/com/android/settings/sip/SipEditor.java
@@ -35,6 +35,7 @@
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
+import android.widget.Button;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
@@ -68,7 +69,8 @@
ProxyAddress(R.string.proxy_address, 5, EMPTY),
Port(R.string.port, 6, DEFAULT_SIP_PORT),
Transport(R.string.transport, 7, DEFAULT_PROTOCOL),
- SendKeepAlive(R.string.send_keepalive, 8, EMPTY);
+ SendKeepAlive(R.string.send_keepalive, 8, EMPTY),
+ AutoRegistration(R.string.auto_registration, 9, EMPTY);
/**
* @param key The key name of the preference.
@@ -93,14 +95,30 @@
public void onCreate(Bundle savedInstanceState) {
Log.v(TAG, "start profile editor");
super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.sip_settings_ui);
addPreferencesFromResource(R.xml.sip_edit);
- SipProfile p = (SipProfile) ((savedInstanceState == null)
+ final SipProfile p = (SipProfile) ((savedInstanceState == null)
? getIntent().getParcelableExtra(SipSettings.KEY_SIP_PROFILE)
: savedInstanceState.getParcelable(KEY_PROFILE));
for (PreferenceKey key : PreferenceKey.values()) {
mPreferences[key.index] = setupPreference(getString(key.text));
}
+ if (p == null) {
+ findViewById(R.id.add_remove_account_bar)
+ .setVisibility(View.GONE);
+ } else {
+ Button removeButton =
+ (Button)findViewById(R.id.add_remove_account_button);
+ removeButton.setText(getString(R.string.remove_sip_account));
+ removeButton.setOnClickListener(
+ new android.view.View.OnClickListener() {
+ public void onClick(View v) {
+ setRemovedProfileAndFinish(p);
+ }
+ });
+ }
loadPreferencesFromProfile(p);
}
@@ -140,6 +158,17 @@
return super.onKeyDown(keyCode, event);
}
+ private void setRemovedProfileAndFinish(SipProfile p) {
+ try {
+ Intent intent = new Intent(this, SipSettings.class);
+ intent.putExtra(SipSettings.KEY_SIP_PROFILE, (Parcelable) p);
+ setResult(RESULT_FIRST_USER, intent);
+ finish();
+ } catch (Exception e) {
+ showAlert(e.getMessage());
+ }
+ }
+
private void showAlert(String message) {
new AlertDialog.Builder(this)
.setTitle(android.R.string.dialog_alert_title)
@@ -160,10 +189,11 @@
value = ((ListPreference)pref).getValue();
} else if (pref instanceof EditTextPreference) {
value = ((EditTextPreference)pref).getText();
+ } else if (pref instanceof CheckBoxPreference) {
+ continue;
}
if (TextUtils.isEmpty(value) &&
- (pref != mPreferences[PreferenceKey.ProxyAddress.index]) &&
- (pref != mPreferences[PreferenceKey.SendKeepAlive.index])) {
+ (pref != mPreferences[PreferenceKey.ProxyAddress.index])) {
showAlert(pref.getTitle() + " "
+ getString(R.string.empty_alert));
return false;
@@ -193,6 +223,8 @@
.setDisplayName(getValue(PreferenceKey.DisplayName))
.setPort(Integer.parseInt(getValue(PreferenceKey.Port)))
.setSendKeepAlive(isChecked(PreferenceKey.SendKeepAlive))
+ .setAutoRegistration(
+ isChecked(PreferenceKey.AutoRegistration))
.build();
} catch (Exception e) {
Log.e(TAG, "Can not create new SipProfile : " + e.getMessage());
@@ -223,7 +255,8 @@
if (key == PreferenceKey.Port) {
setValue(key,
String.valueOf(meth.invoke(p, (Object[])null)));
- } else if (key == PreferenceKey.SendKeepAlive) {
+ } else if (key == PreferenceKey.SendKeepAlive
+ || key == PreferenceKey.AutoRegistration) {
setCheckBox(key, ((Boolean)
meth.invoke(p, (Object[])null)).booleanValue());
} else {
diff --git a/src/com/android/settings/sip/SipSettings.java b/src/com/android/settings/sip/SipSettings.java
index b8088c7..679c55f 100644
--- a/src/com/android/settings/sip/SipSettings.java
+++ b/src/com/android/settings/sip/SipSettings.java
@@ -38,6 +38,7 @@
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.widget.AdapterView.AdapterContextMenuInfo;
+import android.widget.Button;
import java.io.File;
import java.io.FileInputStream;
@@ -61,9 +62,8 @@
static final String PROFILE_OBJ_FILE = ".pobj";
static final String PROFILES_DIR = "/profiles/";
- private static final String PREF_AUTO_REG = "auto_registration";
+ private static final String PREF_AUTO_REG = "auto_reg";
private static final String PREF_SIP_CALL_FIRST = "sip_call_first";
- private static final String PREF_ADD_SIP = "add_sip_account";
private static final String PREF_SIP_LIST = "sip_account_list";
private static final String TAG = "SipSettings";
private static final String REGISTERED = "REGISTERED";
@@ -114,6 +114,7 @@
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ setContentView(R.layout.sip_settings_ui);
addPreferencesFromResource(R.xml.sip_setting);
mProfilesDirectory = getFilesDir().getAbsolutePath() + PROFILES_DIR;
mSipListContainer = (PreferenceCategory) findPreference(PREF_SIP_LIST);
@@ -123,19 +124,16 @@
// for long-press gesture on a profile preference
registerForContextMenu(getListView());
- registerForAutoRegistrationListener();
+ registerForGlobalSettingsListener();
updateProfilesStatus();
}
private void registerForAddSipListener() {
- PreferenceScreen mAddSip =
- (PreferenceScreen) findPreference(PREF_ADD_SIP);
- mAddSip.setOnPreferenceClickListener(
- new OnPreferenceClickListener() {
- public boolean onPreferenceClick(Preference preference) {
+ ((Button) findViewById(R.id.add_remove_account_button))
+ .setOnClickListener(new android.view.View.OnClickListener() {
+ public void onClick(View v) {
startSipEditor(null);
- return true;
}
});
}
@@ -146,11 +144,11 @@
private class AutoRegistrationClickHandler implements ClickEventCallback {
public void handle(boolean enabled) {
- if (enabled) registerAllProfiles();
+ registerEnabledProfiles(enabled);
}
}
- private void registerForAutoRegistrationListener() {
+ private void registerForGlobalSettingsListener() {
mSettingsEditor = getSharedPreferences(
SipAutoRegistration.SIP_SHARED_PREFERENCES,
Context.MODE_WORLD_READABLE).edit();
@@ -237,15 +235,20 @@
}
}
- private void registerAllProfiles() {
+ private void registerEnabledProfiles(boolean enabled) {
try {
for (SipProfile p : mSipProfileList) {
- if (!mSipManager.isRegistered(p.getUriString())) {
- registerProfile(p);
+ if (p.getAutoRegistration() == false) continue;
+ if (enabled) {
+ if (!mSipManager.isRegistered(p.getUriString())) {
+ registerProfile(p);
+ }
+ } else {
+ unRegisterProfile(p);
}
}
} catch (SipException e) {
- Log.e(TAG, "Error!registerAllProfiles():", e);
+ Log.e(TAG, "Error!registerEnabledProfiles():", e);
}
}
@@ -292,56 +295,6 @@
return menuInfo.position - mSipListContainer.getOrder() - 1;
}
- @Override
- public void onCreateContextMenu(ContextMenu menu, View v,
- ContextMenuInfo menuInfo) {
- super.onCreateContextMenu(menu, v, menuInfo);
-
- SipProfile p = getProfile(getProfilePositionFrom(
- (AdapterContextMenuInfo) menuInfo));
- if (p != null) {
- boolean opened;
- try {
- opened = mSipManager.isOpened(p.getUriString());
- } catch (SipException e) {
- Log.e(TAG, "Cannot get status of " + p.getUriString(), e);
- return;
- }
- menu.setHeaderTitle(p.getProfileName());
- menu.add(0, CONTEXT_MENU_REGISTER_ID, 0,
- R.string.sip_menu_register).setEnabled(!opened);
- menu.add(0, CONTEXT_MENU_UNREGISTER_ID, 0,
- R.string.sip_menu_unregister).setEnabled(opened);
- menu.add(0, CONTEXT_MENU_EDIT_ID, 0, R.string.sip_menu_edit);
- menu.add(0, CONTEXT_MENU_DELETE_ID, 0, R.string.sip_menu_delete);
- }
- }
-
- @Override
- public boolean onContextItemSelected(MenuItem item) {
- SipProfile p = getProfile(getProfilePositionFrom(
- (AdapterContextMenuInfo) item.getMenuInfo()));
-
- switch(item.getItemId()) {
- case CONTEXT_MENU_REGISTER_ID:
- registerProfile(p);
- return true;
- case CONTEXT_MENU_UNREGISTER_ID:
- unRegisterProfile(p);
- return true;
-
- case CONTEXT_MENU_EDIT_ID:
- startSipEditor(p);
- return true;
-
- case CONTEXT_MENU_DELETE_ID:
- deleteProfile(p);
- return true;
- }
-
- return super.onContextItemSelected(item);
- }
-
private void registerProfile(SipProfile profile) {
if (profile != null) {
try {
@@ -376,7 +329,7 @@
file.delete();
}
- private void deleteProfile(SipProfile p) {
+ void deleteProfile(SipProfile p) {
mSipProfileList.remove(p);
SipPreference pref = mSipPreferenceMap.remove(p.getUriString());
mSipListContainer.removePreference(pref);
@@ -399,14 +352,24 @@
@Override
protected void onActivityResult(final int requestCode, final int resultCode,
final Intent intent) {
- if (resultCode != RESULT_OK) return;
+ if (resultCode != RESULT_OK && resultCode != RESULT_FIRST_USER) return;
SipProfile profile = intent.getParcelableExtra(KEY_SIP_PROFILE);
try {
- saveProfileToStorage(profile);
+ if (resultCode == RESULT_OK) {
+ Log.v(TAG, "New Profile Name:" + profile.getProfileName());
+ saveProfileToStorage(profile);
+ if (((CheckBoxPreference) findPreference
+ (PREF_AUTO_REG)).isChecked() &&
+ profile.getAutoRegistration() == true) {
+ registerProfile(profile);
+ }
+ } else {
+ Log.v(TAG, "Removed Profile Name:" + profile.getProfileName());
+ deleteProfile(profile);
+ }
} catch (IOException e) {
- Log.v(TAG, "Can not save the profile : " + e.getMessage());
+ Log.v(TAG, "Can not handle the profile : " + e.getMessage());
}
- Log.v(TAG, "New Profile Name is " + profile.getProfileName());
}
static SipProfile deserialize(File profileObjectFile) throws IOException {
diff --git a/src/com/android/sip/SipSessionGroup.java b/src/com/android/sip/SipSessionGroup.java
index 350d5a2..2924dd5 100644
--- a/src/com/android/sip/SipSessionGroup.java
+++ b/src/com/android/sip/SipSessionGroup.java
@@ -16,6 +16,9 @@
package com.android.sip;
+import gov.nist.javax.sip.header.SIPHeaderNames;
+import gov.nist.javax.sip.header.WWWAuthenticate;
+
import android.net.sip.ISipSession;
import android.net.sip.ISipSessionListener;
import android.net.sip.SessionDescription;
@@ -51,6 +54,7 @@
import javax.sip.SipStack;
import javax.sip.TimeoutEvent;
import javax.sip.Transaction;
+import javax.sip.TransactionState;
import javax.sip.TransactionTerminatedEvent;
import javax.sip.address.Address;
import javax.sip.address.SipURI;
@@ -66,6 +70,7 @@
*/
class SipSessionGroup implements SipListener {
private static final String TAG = "SipSession";
+ private static final String ANONYMOUS = "anonymous";
private static final int EXPIRY_TIME = 3600;
private static final EventObject DEREGISTER = new EventObject("Deregister");
@@ -77,6 +82,7 @@
private SipStack mSipStack;
private SipHelper mSipHelper;
private SipProfile mLocalProfile;
+ private String mLastNonce;
// session that processes INVITE requests
private SipSessionImpl mCallReceiverSession;
@@ -546,8 +552,16 @@
return true;
case Response.UNAUTHORIZED:
case Response.PROXY_AUTHENTICATION_REQUIRED:
- mSipHelper.handleChallenge(
- (ResponseEvent)evt, mLocalProfile);
+ String nonce = getNonceFromResponse(response);
+ if (((nonce != null) && nonce.equals(mLastNonce)) ||
+ (nonce == mLastNonce)) {
+ Log.v(TAG, "Incorrect username/password");
+ reset();
+ onRegistrationFailed(createCallbackException(response));
+ } else {
+ mSipHelper.handleChallenge(event, mLocalProfile);
+ mLastNonce = nonce;
+ }
return true;
default:
if (statusCode >= 500) {
@@ -560,6 +574,12 @@
return false;
}
+ private String getNonceFromResponse(Response response) {
+ WWWAuthenticate authHeader = (WWWAuthenticate)(response.getHeader(
+ SIPHeaderNames.WWW_AUTHENTICATE));
+ return (authHeader == null) ? null : authHeader.getNonce();
+ }
+
private boolean readyForCall(EventObject evt) throws SipException {
// expect MakeCallCommand, RegisterCommand, DEREGISTER
if (evt instanceof MakeCallCommand) {
@@ -887,7 +907,9 @@
(FromHeader) request.getHeader(FromHeader.NAME);
Address address = fromHeader.getAddress();
SipURI uri = (SipURI) address.getURI();
- return new SipProfile.Builder(uri.getUser(), uri.getHost())
+ String username = uri.getUser();
+ if (username == null) username = ANONYMOUS;
+ return new SipProfile.Builder(username, uri.getHost())
.setPort(uri.getPort())
.setDisplayName(address.getDisplayName())
.build();