Detailed changes
@@ -779,6 +779,7 @@ public class Account extends AbstractEntity implements AvatarService.Avatarable
CONNECTING(false),
ONLINE(false),
NO_INTERNET(false),
+ CONNECTION_TIMEOUT,
UNAUTHORIZED,
TEMPORARY_AUTH_FAILURE,
SERVER_NOT_FOUND,
@@ -848,6 +849,8 @@ public class Account extends AbstractEntity implements AvatarService.Avatarable
return R.string.account_status_not_found;
case NO_INTERNET:
return R.string.account_status_no_internet;
+ case CONNECTION_TIMEOUT:
+ return R.string.account_status_connection_timeout;
case REGISTRATION_FAILED:
return R.string.account_status_regis_fail;
case REGISTRATION_WEB:
@@ -2,7 +2,6 @@ package eu.siacs.conversations.services;
import android.content.Context;
import android.content.pm.PackageManager;
-import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.ToneGenerator;
import android.net.Uri;
@@ -20,7 +19,6 @@ import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import eu.siacs.conversations.AppSettings;
import eu.siacs.conversations.Config;
-import eu.siacs.conversations.R;
import eu.siacs.conversations.ui.util.MainThreadExecutor;
import eu.siacs.conversations.xmpp.Jid;
import eu.siacs.conversations.xmpp.jingle.JingleConnectionManager;
@@ -374,7 +372,7 @@ public class CallIntegration extends Connection {
}
}
if (state == STATE_ACTIVE) {
- startTone(DEFAULT_TONE_VOLUME, ToneGenerator.TONE_CDMA_ANSWER, 100 );
+ startTone(DEFAULT_TONE_VOLUME, ToneGenerator.TONE_CDMA_ANSWER, 100);
} else if (state == STATE_DISCONNECTED) {
final var audioManager = this.appRTCAudioManager;
if (audioManager != null) {
@@ -5,7 +5,6 @@ import static eu.siacs.conversations.utils.Random.SECURE_RANDOM;
import android.Manifest;
import android.annotation.SuppressLint;
-import android.annotation.TargetApi;
import android.app.AlarmManager;
import android.app.KeyguardManager;
import android.app.Notification;
@@ -1036,6 +1035,7 @@ public class XmppConnectionService extends Service {
if (!account.getStatus().isAttemptReconnect()) {
return false;
}
+ final var requestCode = account.getUuid().hashCode();
if (!hasInternetConnection()) {
account.setStatus(Account.State.NO_INTERNET);
statusListener.onStatusChanged(account);
@@ -1065,8 +1065,7 @@ public class XmppConnectionService extends Service {
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": ping timeout");
this.reconnectAccount(account, true, interactive);
} else {
- int secs = (int) (pingTimeoutIn / 1000);
- this.scheduleWakeUpCall(secs, account.getUuid().hashCode());
+ this.scheduleWakeUpCall(pingTimeoutIn, requestCode);
}
} else {
pingCandidates.add(account);
@@ -1081,8 +1080,7 @@ public class XmppConnectionService extends Service {
} else if (msToNextPing <= 0) {
return true;
} else {
- this.scheduleWakeUpCall(
- (int) (msToNextPing / 1000), account.getUuid().hashCode());
+ this.scheduleWakeUpCall(msToNextPing, requestCode);
if (mLowPingTimeoutMode.remove(account.getJid().asBareJid())) {
Log.d(
Config.LOGTAG,
@@ -1095,32 +1093,18 @@ public class XmppConnectionService extends Service {
} else if (account.getStatus() == Account.State.OFFLINE) {
reconnectAccount(account, true, interactive);
} else if (account.getStatus() == Account.State.CONNECTING) {
- long secondsSinceLastConnect =
- (SystemClock.elapsedRealtime()
- - account.getXmppConnection().getLastConnect())
- / 1000;
- long secondsSinceLastDisco =
- (SystemClock.elapsedRealtime()
- - account.getXmppConnection().getLastDiscoStarted())
- / 1000;
- long discoTimeout = Config.CONNECT_DISCO_TIMEOUT - secondsSinceLastDisco;
- long timeout = Config.CONNECT_TIMEOUT - secondsSinceLastConnect;
- if (timeout < 0) {
- Log.d(
- Config.LOGTAG,
- account.getJid()
- + ": time out during connect reconnecting (secondsSinceLast="
- + secondsSinceLastConnect
- + ")");
- account.getXmppConnection().resetAttemptCount(false);
- reconnectAccount(account, true, interactive);
+ final var connection = account.getXmppConnection();
+ final var connectionDuration = connection.getConnectionDuration();
+ final var discoDuration = connection.getDiscoDuration();
+ final var connectionTimeout = Config.CONNECT_TIMEOUT * 1000L - connectionDuration;
+ final var discoTimeout = Config.CONNECT_DISCO_TIMEOUT * 1000L - discoDuration;
+ if (connectionTimeout < 0) {
+ connection.triggerConnectionTimeout();
} else if (discoTimeout < 0) {
- account.getXmppConnection().sendDiscoTimeout();
- scheduleWakeUpCall(
- (int) Math.min(timeout, discoTimeout), account.getUuid().hashCode());
+ connection.sendDiscoTimeout();
+ scheduleWakeUpCall(discoTimeout, requestCode);
} else {
- scheduleWakeUpCall(
- (int) Math.min(timeout, discoTimeout), account.getUuid().hashCode());
+ scheduleWakeUpCall(Math.min(connectionTimeout, discoTimeout), requestCode);
}
} else {
final boolean aggressive =
@@ -1768,12 +1752,12 @@ public class XmppConnectionService extends Service {
}
public void scheduleWakeUpCall(final int seconds, final int requestCode) {
- final long timeToWake =
- SystemClock.elapsedRealtime() + (seconds < 0 ? 1 : seconds + 1) * 1000L;
- final AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
- if (alarmManager == null) {
- return;
- }
+ scheduleWakeUpCall((long) (seconds < 0 ? 1 : seconds + 1), requestCode);
+ }
+
+ private void scheduleWakeUpCall(final long milliSeconds, final int requestCode) {
+ final var timeToWake = SystemClock.elapsedRealtime() + milliSeconds;
+ final var alarmManager = getSystemService(AlarmManager.class);
final Intent intent = new Intent(this, SystemEventReceiver.class);
intent.setAction(ACTION_PING);
try {
@@ -1781,12 +1765,11 @@ public class XmppConnectionService extends Service {
PendingIntent.getBroadcast(
this, requestCode, intent, PendingIntent.FLAG_IMMUTABLE);
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, timeToWake, pendingIntent);
- } catch (RuntimeException e) {
+ } catch (final RuntimeException e) {
Log.e(Config.LOGTAG, "unable to schedule alarm for ping", e);
}
}
- @TargetApi(Build.VERSION_CODES.M)
private void scheduleNextIdlePing() {
final long timeToWake = SystemClock.elapsedRealtime() + (Config.IDLE_PING_INTERVAL * 1000);
final AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
@@ -20,6 +20,7 @@ import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
+import com.google.common.primitives.Ints;
import eu.siacs.conversations.AppSettings;
import eu.siacs.conversations.BuildConfig;
import eu.siacs.conversations.Config;
@@ -166,7 +167,7 @@ public class XmppConnection implements Runnable {
private int stanzasSentBeforeAuthentication;
private long lastPacketReceived = 0;
private long lastPingSent = 0;
- private long lastConnect = 0;
+ private long lastConnectionStarted = 0;
private long lastSessionStarted = 0;
private long lastDiscoStarted = 0;
private boolean isMamPreferenceAlways = false;
@@ -264,7 +265,7 @@ public class XmppConnection implements Runnable {
}
public void prepareNewConnection() {
- this.lastConnect = SystemClock.elapsedRealtime();
+ this.lastConnectionStarted = SystemClock.elapsedRealtime();
this.lastPingSent = SystemClock.elapsedRealtime();
this.lastDiscoStarted = Long.MAX_VALUE;
this.mWaitingForSmCatchup.set(false);
@@ -526,15 +527,17 @@ public class XmppConnection implements Runnable {
if (Thread.currentThread().isInterrupted()) {
throw new InterruptedException();
}
+ // this means we have at least found a socket to connect to. give the connection another 90s
+ this.lastConnectionStarted = SystemClock.elapsedRealtime();
this.socket = socket;
- tagReader = new XmlReader();
+ this.tagReader = new XmlReader();
if (tagWriter != null) {
tagWriter.forceClose();
}
- tagWriter = new TagWriter();
- tagWriter.setOutputStream(socket.getOutputStream());
- tagReader.setInputStream(socket.getInputStream());
- tagWriter.beginDocument();
+ this.tagWriter = new TagWriter();
+ this.tagWriter.setOutputStream(socket.getOutputStream());
+ this.tagReader.setInputStream(socket.getInputStream());
+ this.tagWriter.beginDocument();
final boolean quickStart;
if (socket instanceof SSLSocket sslSocket) {
SSLSockets.log(account, sslSocket);
@@ -2372,7 +2375,7 @@ public class XmppConnection implements Runnable {
} else if (streamError.hasChild("host-unknown")) {
throw new StateChangingException(Account.State.HOST_UNKNOWN);
} else if (streamError.hasChild("policy-violation")) {
- this.lastConnect = SystemClock.elapsedRealtime();
+ this.lastConnectionStarted = SystemClock.elapsedRealtime();
final String text = streamError.findChildContent("text");
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": policy violation. " + text);
if (isSecureLoggedIn) {
@@ -2712,8 +2715,7 @@ public class XmppConnection implements Runnable {
}
public String getMucServer() {
- List<String> servers = getMucServers();
- return servers.size() > 0 ? servers.get(0) : null;
+ return Iterables.getFirst(getMucServers(), null);
}
public int getTimeToNextAttempt(final boolean aggressive) {
@@ -2725,9 +2727,8 @@ public class XmppConnection implements Runnable {
account.getLastErrorStatus() == Account.State.POLICY_VIOLATION ? 3 : 0;
interval = Math.min((int) (25 * Math.pow(1.3, (additionalTime + attempt))), 300);
}
- final int secondsSinceLast =
- (int) ((SystemClock.elapsedRealtime() - this.lastConnect) / 1000);
- return interval - secondsSinceLast;
+ final var connectionDuration = Ints.saturatedCast(getConnectionDuration() / 1000);
+ return interval - connectionDuration;
}
public int getAttempt() {
@@ -2743,16 +2744,16 @@ public class XmppConnection implements Runnable {
return System.currentTimeMillis() - diff;
}
- public long getLastConnect() {
- return this.lastConnect;
+ public long getConnectionDuration() {
+ return SystemClock.elapsedRealtime() - this.lastConnectionStarted;
}
- public long getLastPingSent() {
- return this.lastPingSent;
+ public long getDiscoDuration() {
+ return SystemClock.elapsedRealtime() - this.lastDiscoStarted;
}
- public long getLastDiscoStarted() {
- return this.lastDiscoStarted;
+ public long getLastPingSent() {
+ return this.lastPingSent;
}
public long getLastPacketReceived() {
@@ -2770,7 +2771,7 @@ public class XmppConnection implements Runnable {
public void resetAttemptCount(boolean resetConnectTime) {
this.attempt = 0;
if (resetConnectTime) {
- this.lastConnect = 0;
+ this.lastConnectionStarted = 0;
}
}
@@ -2818,6 +2819,16 @@ public class XmppConnection implements Runnable {
sendIqPacket(iqPacket, unregisteredIqListener);
}
+ public void triggerConnectionTimeout() {
+ final var duration = getConnectionDuration();
+ Log.d(
+ Config.LOGTAG,
+ account.getJid().asBareJid() + ": connection timeout after " + duration + "ms");
+ this.changeStatus(Account.State.CONNECTION_TIMEOUT);
+ this.interrupt();
+ this.forceCloseSocket();
+ }
+
private class MyKeyManager implements X509KeyManager {
@Override
public String chooseClientAlias(String[] strings, Principal[] principals, Socket socket) {
@@ -158,6 +158,7 @@
<string name="account_status_unauthorized">Unauthorized</string>
<string name="account_status_not_found">Server not found</string>
<string name="account_status_no_internet">No connectivity</string>
+ <string name="account_status_connection_timeout">Connection timeout</string>
<string name="account_status_regis_fail">Registration failed</string>
<string name="account_status_regis_conflict">Username already in use</string>
<string name="account_status_regis_success">Registration completed</string>