presist http upload availibility
This commit is contained in:
		
							parent
							
								
									f2ea609b51
								
							
						
					
					
						commit
						5514958e93
					
				| 
						 | 
					@ -54,6 +54,7 @@ public class Account extends AbstractEntity {
 | 
				
			||||||
	public static final int OPTION_MAGIC_CREATE = 4;
 | 
						public static final int OPTION_MAGIC_CREATE = 4;
 | 
				
			||||||
	public static final int OPTION_REQUIRES_ACCESS_MODE_CHANGE = 5;
 | 
						public static final int OPTION_REQUIRES_ACCESS_MODE_CHANGE = 5;
 | 
				
			||||||
	public static final int OPTION_LOGGED_IN_SUCCESSFULLY = 6;
 | 
						public static final int OPTION_LOGGED_IN_SUCCESSFULLY = 6;
 | 
				
			||||||
 | 
						public static final int OPTION_HTTP_UPLOAD_AVAILABLE = 7;
 | 
				
			||||||
	public final HashSet<Pair<String, String>> inProgressDiscoFetches = new HashSet<>();
 | 
						public final HashSet<Pair<String, String>> inProgressDiscoFetches = new HashSet<>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public boolean httpUploadAvailable(long filesize) {
 | 
						public boolean httpUploadAvailable(long filesize) {
 | 
				
			||||||
| 
						 | 
					@ -61,7 +62,7 @@ public class Account extends AbstractEntity {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public boolean httpUploadAvailable() {
 | 
						public boolean httpUploadAvailable() {
 | 
				
			||||||
		return httpUploadAvailable(0);
 | 
							return isOptionSet(OPTION_HTTP_UPLOAD_AVAILABLE) || httpUploadAvailable(0);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public void setDisplayName(String displayName) {
 | 
						public void setDisplayName(String displayName) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,7 @@
 | 
				
			||||||
package eu.siacs.conversations.http;
 | 
					package eu.siacs.conversations.http;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import android.util.Log;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.apache.http.conn.ssl.StrictHostnameVerifier;
 | 
					import org.apache.http.conn.ssl.StrictHostnameVerifier;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.io.IOException;
 | 
					import java.io.IOException;
 | 
				
			||||||
| 
						 | 
					@ -16,10 +18,13 @@ import javax.net.ssl.HttpsURLConnection;
 | 
				
			||||||
import javax.net.ssl.SSLSocketFactory;
 | 
					import javax.net.ssl.SSLSocketFactory;
 | 
				
			||||||
import javax.net.ssl.X509TrustManager;
 | 
					import javax.net.ssl.X509TrustManager;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import eu.siacs.conversations.Config;
 | 
				
			||||||
 | 
					import eu.siacs.conversations.entities.Account;
 | 
				
			||||||
import eu.siacs.conversations.entities.Message;
 | 
					import eu.siacs.conversations.entities.Message;
 | 
				
			||||||
import eu.siacs.conversations.services.AbstractConnectionManager;
 | 
					import eu.siacs.conversations.services.AbstractConnectionManager;
 | 
				
			||||||
import eu.siacs.conversations.services.XmppConnectionService;
 | 
					import eu.siacs.conversations.services.XmppConnectionService;
 | 
				
			||||||
import eu.siacs.conversations.utils.TLSSocketFactory;
 | 
					import eu.siacs.conversations.utils.TLSSocketFactory;
 | 
				
			||||||
 | 
					import eu.siacs.conversations.xmpp.OnAdvancedStreamFeaturesLoaded;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class HttpConnectionManager extends AbstractConnectionManager {
 | 
					public class HttpConnectionManager extends AbstractConnectionManager {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -136,10 +136,6 @@ import rocks.xmpp.addr.Jid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class XmppConnectionService extends Service {
 | 
					public class XmppConnectionService extends Service {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	static {
 | 
					 | 
				
			||||||
		URL.setURLStreamHandlerFactory(new AesGcmURLStreamHandlerFactory());
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	public static final String ACTION_REPLY_TO_CONVERSATION = "reply_to_conversations";
 | 
						public static final String ACTION_REPLY_TO_CONVERSATION = "reply_to_conversations";
 | 
				
			||||||
	public static final String ACTION_MARK_AS_READ = "mark_as_read";
 | 
						public static final String ACTION_MARK_AS_READ = "mark_as_read";
 | 
				
			||||||
	public static final String ACTION_SNOOZE = "snooze";
 | 
						public static final String ACTION_SNOOZE = "snooze";
 | 
				
			||||||
| 
						 | 
					@ -147,24 +143,28 @@ public class XmppConnectionService extends Service {
 | 
				
			||||||
	public static final String ACTION_DISMISS_ERROR_NOTIFICATIONS = "dismiss_error";
 | 
						public static final String ACTION_DISMISS_ERROR_NOTIFICATIONS = "dismiss_error";
 | 
				
			||||||
	public static final String ACTION_TRY_AGAIN = "try_again";
 | 
						public static final String ACTION_TRY_AGAIN = "try_again";
 | 
				
			||||||
	public static final String ACTION_IDLE_PING = "idle_ping";
 | 
						public static final String ACTION_IDLE_PING = "idle_ping";
 | 
				
			||||||
	private static final String ACTION_MERGE_PHONE_CONTACTS = "merge_phone_contacts";
 | 
					 | 
				
			||||||
	public static final String ACTION_GCM_TOKEN_REFRESH = "gcm_token_refresh";
 | 
						public static final String ACTION_GCM_TOKEN_REFRESH = "gcm_token_refresh";
 | 
				
			||||||
	public static final String ACTION_GCM_MESSAGE_RECEIVED = "gcm_message_received";
 | 
						public static final String ACTION_GCM_MESSAGE_RECEIVED = "gcm_message_received";
 | 
				
			||||||
 | 
						private static final String ACTION_MERGE_PHONE_CONTACTS = "merge_phone_contacts";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						static {
 | 
				
			||||||
 | 
							URL.setURLStreamHandlerFactory(new AesGcmURLStreamHandlerFactory());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public final CountDownLatch restoredFromDatabaseLatch = new CountDownLatch(1);
 | 
				
			||||||
	private final SerialSingleThreadExecutor mFileAddingExecutor = new SerialSingleThreadExecutor("FileAdding");
 | 
						private final SerialSingleThreadExecutor mFileAddingExecutor = new SerialSingleThreadExecutor("FileAdding");
 | 
				
			||||||
	private final SerialSingleThreadExecutor mVideoCompressionExecutor = new SerialSingleThreadExecutor("VideoCompression");
 | 
						private final SerialSingleThreadExecutor mVideoCompressionExecutor = new SerialSingleThreadExecutor("VideoCompression");
 | 
				
			||||||
	private final SerialSingleThreadExecutor mDatabaseWriterExecutor = new SerialSingleThreadExecutor("DatabaseWriter");
 | 
						private final SerialSingleThreadExecutor mDatabaseWriterExecutor = new SerialSingleThreadExecutor("DatabaseWriter");
 | 
				
			||||||
	private final SerialSingleThreadExecutor mDatabaseReaderExecutor = new SerialSingleThreadExecutor("DatabaseReader");
 | 
						private final SerialSingleThreadExecutor mDatabaseReaderExecutor = new SerialSingleThreadExecutor("DatabaseReader");
 | 
				
			||||||
	private final SerialSingleThreadExecutor mNotificationExecutor = new SerialSingleThreadExecutor("NotificationExecutor");
 | 
						private final SerialSingleThreadExecutor mNotificationExecutor = new SerialSingleThreadExecutor("NotificationExecutor");
 | 
				
			||||||
	private ReplacingSerialSingleThreadExecutor mContactMergerExecutor = new ReplacingSerialSingleThreadExecutor(true);
 | 
					 | 
				
			||||||
	private final IBinder mBinder = new XmppConnectionBinder();
 | 
						private final IBinder mBinder = new XmppConnectionBinder();
 | 
				
			||||||
	private final List<Conversation> conversations = new CopyOnWriteArrayList<>();
 | 
						private final List<Conversation> conversations = new CopyOnWriteArrayList<>();
 | 
				
			||||||
	private final IqGenerator mIqGenerator = new IqGenerator(this);
 | 
						private final IqGenerator mIqGenerator = new IqGenerator(this);
 | 
				
			||||||
	private final List<String> mInProgressAvatarFetches = new ArrayList<>();
 | 
						private final List<String> mInProgressAvatarFetches = new ArrayList<>();
 | 
				
			||||||
	private final HashSet<Jid> mLowPingTimeoutMode = new HashSet<>();
 | 
						private final HashSet<Jid> mLowPingTimeoutMode = new HashSet<>();
 | 
				
			||||||
 | 
					 | 
				
			||||||
	private long mLastActivity = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	public DatabaseBackend databaseBackend;
 | 
						public DatabaseBackend databaseBackend;
 | 
				
			||||||
 | 
						private ReplacingSerialSingleThreadExecutor mContactMergerExecutor = new ReplacingSerialSingleThreadExecutor(true);
 | 
				
			||||||
 | 
						private long mLastActivity = 0;
 | 
				
			||||||
	private ContentObserver contactObserver = new ContentObserver(null) {
 | 
						private ContentObserver contactObserver = new ContentObserver(null) {
 | 
				
			||||||
		@Override
 | 
							@Override
 | 
				
			||||||
		public void onChange(boolean selfChange) {
 | 
							public void onChange(boolean selfChange) {
 | 
				
			||||||
| 
						 | 
					@ -197,10 +197,6 @@ public class XmppConnectionService extends Service {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
	private MessageGenerator mMessageGenerator = new MessageGenerator(this);
 | 
						private MessageGenerator mMessageGenerator = new MessageGenerator(this);
 | 
				
			||||||
	private PresenceGenerator mPresenceGenerator = new PresenceGenerator(this);
 | 
					 | 
				
			||||||
	private List<Account> accounts;
 | 
					 | 
				
			||||||
	private JingleConnectionManager mJingleConnectionManager = new JingleConnectionManager(
 | 
					 | 
				
			||||||
			this);
 | 
					 | 
				
			||||||
	public OnContactStatusChanged onContactStatusChanged = new OnContactStatusChanged() {
 | 
						public OnContactStatusChanged onContactStatusChanged = new OnContactStatusChanged() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		@Override
 | 
							@Override
 | 
				
			||||||
| 
						 | 
					@ -215,14 +211,23 @@ public class XmppConnectionService extends Service {
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
						private PresenceGenerator mPresenceGenerator = new PresenceGenerator(this);
 | 
				
			||||||
 | 
						private List<Account> accounts;
 | 
				
			||||||
 | 
						private JingleConnectionManager mJingleConnectionManager = new JingleConnectionManager(
 | 
				
			||||||
 | 
								this);
 | 
				
			||||||
 | 
						private final OnJinglePacketReceived jingleListener = new OnJinglePacketReceived() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							@Override
 | 
				
			||||||
 | 
							public void onJinglePacketReceived(Account account, JinglePacket packet) {
 | 
				
			||||||
 | 
								mJingleConnectionManager.deliverPacket(account, packet);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
	private HttpConnectionManager mHttpConnectionManager = new HttpConnectionManager(
 | 
						private HttpConnectionManager mHttpConnectionManager = new HttpConnectionManager(
 | 
				
			||||||
			this);
 | 
								this);
 | 
				
			||||||
	private AvatarService mAvatarService = new AvatarService(this);
 | 
						private AvatarService mAvatarService = new AvatarService(this);
 | 
				
			||||||
	private MessageArchiveService mMessageArchiveService = new MessageArchiveService(this);
 | 
						private MessageArchiveService mMessageArchiveService = new MessageArchiveService(this);
 | 
				
			||||||
	private PushManagementService mPushManagementService = new PushManagementService(this);
 | 
						private PushManagementService mPushManagementService = new PushManagementService(this);
 | 
				
			||||||
	private OnConversationUpdate mOnConversationUpdate = null;
 | 
						private OnConversationUpdate mOnConversationUpdate = null;
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	private final ConversationsFileObserver fileObserver = new ConversationsFileObserver(
 | 
						private final ConversationsFileObserver fileObserver = new ConversationsFileObserver(
 | 
				
			||||||
			Environment.getExternalStorageDirectory().getAbsolutePath()
 | 
								Environment.getExternalStorageDirectory().getAbsolutePath()
 | 
				
			||||||
	) {
 | 
						) {
 | 
				
			||||||
| 
						 | 
					@ -231,13 +236,6 @@ public class XmppConnectionService extends Service {
 | 
				
			||||||
			markFileDeleted(path);
 | 
								markFileDeleted(path);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
	private final OnJinglePacketReceived jingleListener = new OnJinglePacketReceived() {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		@Override
 | 
					 | 
				
			||||||
		public void onJinglePacketReceived(Account account, JinglePacket packet) {
 | 
					 | 
				
			||||||
			mJingleConnectionManager.deliverPacket(account, packet);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	private final OnMessageAcknowledged mOnMessageAcknowledgedListener = new OnMessageAcknowledged() {
 | 
						private final OnMessageAcknowledged mOnMessageAcknowledgedListener = new OnMessageAcknowledged() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		@Override
 | 
							@Override
 | 
				
			||||||
| 
						 | 
					@ -267,10 +265,6 @@ public class XmppConnectionService extends Service {
 | 
				
			||||||
	private OnMucRosterUpdate mOnMucRosterUpdate = null;
 | 
						private OnMucRosterUpdate mOnMucRosterUpdate = null;
 | 
				
			||||||
	private int mucRosterChangedListenerCount = 0;
 | 
						private int mucRosterChangedListenerCount = 0;
 | 
				
			||||||
	private OnKeyStatusUpdated mOnKeyStatusUpdated = null;
 | 
						private OnKeyStatusUpdated mOnKeyStatusUpdated = null;
 | 
				
			||||||
	private int keyStatusUpdatedListenerCount = 0;
 | 
					 | 
				
			||||||
	private AtomicLong mLastExpiryRun = new AtomicLong(0);
 | 
					 | 
				
			||||||
	private SecureRandom mRandom;
 | 
					 | 
				
			||||||
	private LruCache<Pair<String, String>, ServiceDiscoveryResult> discoCache = new LruCache<>(20);
 | 
					 | 
				
			||||||
	private final OnBindListener mOnBindListener = new OnBindListener() {
 | 
						private final OnBindListener mOnBindListener = new OnBindListener() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		@Override
 | 
							@Override
 | 
				
			||||||
| 
						 | 
					@ -283,19 +277,22 @@ public class XmppConnectionService extends Service {
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if (account.setOption(Account.OPTION_LOGGED_IN_SUCCESSFULLY, true)) {
 | 
								boolean needsUpdating = account.setOption(Account.OPTION_LOGGED_IN_SUCCESSFULLY, true);
 | 
				
			||||||
 | 
								needsUpdating |= account.setOption(Account.OPTION_HTTP_UPLOAD_AVAILABLE, account.getXmppConnection().getFeatures().httpUpload(0));
 | 
				
			||||||
 | 
								if (needsUpdating) {
 | 
				
			||||||
 | 
									Log.d(Config.LOGTAG, "account needed updating");
 | 
				
			||||||
				databaseBackend.updateAccount(account);
 | 
									databaseBackend.updateAccount(account);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			account.getRoster().clearPresences();
 | 
								account.getRoster().clearPresences();
 | 
				
			||||||
			mJingleConnectionManager.cancelInTransmission();
 | 
								mJingleConnectionManager.cancelInTransmission();
 | 
				
			||||||
			fetchRosterFromServer(account);
 | 
								fetchRosterFromServer(account);
 | 
				
			||||||
			fetchBookmarks(account);
 | 
								fetchBookmarks(account);
 | 
				
			||||||
			final boolean flexible= account.getXmppConnection().getFeatures().flexibleOfflineMessageRetrieval();
 | 
								final boolean flexible = account.getXmppConnection().getFeatures().flexibleOfflineMessageRetrieval();
 | 
				
			||||||
			final boolean catchup = getMessageArchiveService().inCatchup(account);
 | 
								final boolean catchup = getMessageArchiveService().inCatchup(account);
 | 
				
			||||||
			if (flexible && catchup) {
 | 
								if (flexible && catchup) {
 | 
				
			||||||
				sendIqPacket(account, mIqGenerator.purgeOfflineMessages(), (acc, packet) -> {
 | 
									sendIqPacket(account, mIqGenerator.purgeOfflineMessages(), (acc, packet) -> {
 | 
				
			||||||
					if (packet.getType() == IqPacket.TYPE.RESULT) {
 | 
										if (packet.getType() == IqPacket.TYPE.RESULT) {
 | 
				
			||||||
						Log.d(Config.LOGTAG, acc.getJid().asBareJid()+": successfully purged offline messages");
 | 
											Log.d(Config.LOGTAG, acc.getJid().asBareJid() + ": successfully purged offline messages");
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				});
 | 
									});
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					@ -307,6 +304,10 @@ public class XmppConnectionService extends Service {
 | 
				
			||||||
			syncDirtyContacts(account);
 | 
								syncDirtyContacts(account);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
						private int keyStatusUpdatedListenerCount = 0;
 | 
				
			||||||
 | 
						private AtomicLong mLastExpiryRun = new AtomicLong(0);
 | 
				
			||||||
 | 
						private SecureRandom mRandom;
 | 
				
			||||||
 | 
						private LruCache<Pair<String, String>, ServiceDiscoveryResult> discoCache = new LruCache<>(20);
 | 
				
			||||||
	private OnStatusChanged statusListener = new OnStatusChanged() {
 | 
						private OnStatusChanged statusListener = new OnStatusChanged() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		@Override
 | 
							@Override
 | 
				
			||||||
| 
						 | 
					@ -379,6 +380,16 @@ public class XmppConnectionService extends Service {
 | 
				
			||||||
			getNotificationService().updateErrorNotification();
 | 
								getNotificationService().updateErrorNotification();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
						private OpenPgpServiceConnection pgpServiceConnection;
 | 
				
			||||||
 | 
						private PgpEngine mPgpEngine = null;
 | 
				
			||||||
 | 
						private WakeLock wakeLock;
 | 
				
			||||||
 | 
						private PowerManager pm;
 | 
				
			||||||
 | 
						private LruCache<String, Bitmap> mBitmapCache;
 | 
				
			||||||
 | 
						private EventReceiver mEventReceiver = new EventReceiver();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private static String generateFetchKey(Account account, final Avatar avatar) {
 | 
				
			||||||
 | 
							return account.getJid().asBareJid() + "_" + avatar.owner + "_" + avatar.sha1sum;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private boolean isInLowPingTimeoutMode(Account account) {
 | 
						private boolean isInLowPingTimeoutMode(Account account) {
 | 
				
			||||||
		synchronized (mLowPingTimeoutMode) {
 | 
							synchronized (mLowPingTimeoutMode) {
 | 
				
			||||||
| 
						 | 
					@ -396,19 +407,6 @@ public class XmppConnectionService extends Service {
 | 
				
			||||||
		toggleForegroundService();
 | 
							toggleForegroundService();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private OpenPgpServiceConnection pgpServiceConnection;
 | 
					 | 
				
			||||||
	private PgpEngine mPgpEngine = null;
 | 
					 | 
				
			||||||
	private WakeLock wakeLock;
 | 
					 | 
				
			||||||
	private PowerManager pm;
 | 
					 | 
				
			||||||
	private LruCache<String, Bitmap> mBitmapCache;
 | 
					 | 
				
			||||||
	private EventReceiver mEventReceiver = new EventReceiver();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	public final CountDownLatch restoredFromDatabaseLatch = new CountDownLatch(1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	private static String generateFetchKey(Account account, final Avatar avatar) {
 | 
					 | 
				
			||||||
		return account.getJid().asBareJid() + "_" + avatar.owner + "_" + avatar.sha1sum;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	public boolean areMessagesInitialized() {
 | 
						public boolean areMessagesInitialized() {
 | 
				
			||||||
		return this.restoredFromDatabaseLatch.getCount() == 0;
 | 
							return this.restoredFromDatabaseLatch.getCount() == 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -447,7 +445,7 @@ public class XmppConnectionService extends Service {
 | 
				
			||||||
		return this.mAvatarService;
 | 
							return this.mAvatarService;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public void attachLocationToConversation(final Conversation conversation,final Uri uri, final UiCallback<Message> callback) {
 | 
						public void attachLocationToConversation(final Conversation conversation, final Uri uri, final UiCallback<Message> callback) {
 | 
				
			||||||
		int encryption = conversation.getNextEncryption();
 | 
							int encryption = conversation.getNextEncryption();
 | 
				
			||||||
		if (encryption == Message.ENCRYPTION_PGP) {
 | 
							if (encryption == Message.ENCRYPTION_PGP) {
 | 
				
			||||||
			encryption = Message.ENCRYPTION_DECRYPTED;
 | 
								encryption = Message.ENCRYPTION_DECRYPTED;
 | 
				
			||||||
| 
						 | 
					@ -511,26 +509,22 @@ public class XmppConnectionService extends Service {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		message.setCounterpart(conversation.getNextCounterpart());
 | 
							message.setCounterpart(conversation.getNextCounterpart());
 | 
				
			||||||
		message.setType(Message.TYPE_IMAGE);
 | 
							message.setType(Message.TYPE_IMAGE);
 | 
				
			||||||
		mFileAddingExecutor.execute(new Runnable() {
 | 
							mFileAddingExecutor.execute(() -> {
 | 
				
			||||||
 | 
								try {
 | 
				
			||||||
			@Override
 | 
									getFileBackend().copyImageToPrivateStorage(message, uri);
 | 
				
			||||||
			public void run() {
 | 
									if (conversation.getNextEncryption() == Message.ENCRYPTION_PGP) {
 | 
				
			||||||
				try {
 | 
										final PgpEngine pgpEngine = getPgpEngine();
 | 
				
			||||||
					getFileBackend().copyImageToPrivateStorage(message, uri);
 | 
										if (pgpEngine != null) {
 | 
				
			||||||
					if (conversation.getNextEncryption() == Message.ENCRYPTION_PGP) {
 | 
											pgpEngine.encrypt(message, callback);
 | 
				
			||||||
						final PgpEngine pgpEngine = getPgpEngine();
 | 
										} else if (callback != null) {
 | 
				
			||||||
						if (pgpEngine != null) {
 | 
											callback.error(R.string.unable_to_connect_to_keychain, null);
 | 
				
			||||||
							pgpEngine.encrypt(message, callback);
 | 
					 | 
				
			||||||
						} else if (callback != null) {
 | 
					 | 
				
			||||||
							callback.error(R.string.unable_to_connect_to_keychain, null);
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
					} else {
 | 
					 | 
				
			||||||
						sendMessage(message);
 | 
					 | 
				
			||||||
						callback.success(message);
 | 
					 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				} catch (final FileBackend.FileCopyException e) {
 | 
									} else {
 | 
				
			||||||
					callback.error(e.getResId(), message);
 | 
										sendMessage(message);
 | 
				
			||||||
 | 
										callback.success(message);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
								} catch (final FileBackend.FileCopyException e) {
 | 
				
			||||||
 | 
									callback.error(e.getResId(), message);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -576,7 +570,7 @@ public class XmppConnectionService extends Service {
 | 
				
			||||||
							restoredFromDatabaseLatch.await();
 | 
												restoredFromDatabaseLatch.await();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
						} catch (InterruptedException e) {
 | 
											} catch (InterruptedException e) {
 | 
				
			||||||
							Log.d(Config.LOGTAG,"unable to process clear notification");
 | 
												Log.d(Config.LOGTAG, "unable to process clear notification");
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
					});
 | 
										});
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
| 
						 | 
					@ -597,7 +591,7 @@ public class XmppConnectionService extends Service {
 | 
				
			||||||
					if (body == null || body.length() <= 0) {
 | 
										if (body == null || body.length() <= 0) {
 | 
				
			||||||
						break;
 | 
											break;
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					mNotificationExecutor.execute(()-> {
 | 
										mNotificationExecutor.execute(() -> {
 | 
				
			||||||
						try {
 | 
											try {
 | 
				
			||||||
							restoredFromDatabaseLatch.await();
 | 
												restoredFromDatabaseLatch.await();
 | 
				
			||||||
							final Conversation c = findConversationByUuid(uuid);
 | 
												final Conversation c = findConversationByUuid(uuid);
 | 
				
			||||||
| 
						 | 
					@ -605,7 +599,7 @@ public class XmppConnectionService extends Service {
 | 
				
			||||||
								directReply(c, body.toString(), dismissNotification);
 | 
													directReply(c, body.toString(), dismissNotification);
 | 
				
			||||||
							}
 | 
												}
 | 
				
			||||||
						} catch (InterruptedException e) {
 | 
											} catch (InterruptedException e) {
 | 
				
			||||||
							Log.d(Config.LOGTAG,"unable to process direct reply");
 | 
												Log.d(Config.LOGTAG, "unable to process direct reply");
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
					});
 | 
										});
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
| 
						 | 
					@ -620,7 +614,7 @@ public class XmppConnectionService extends Service {
 | 
				
			||||||
							restoredFromDatabaseLatch.await();
 | 
												restoredFromDatabaseLatch.await();
 | 
				
			||||||
							sendReadMarker(c);
 | 
												sendReadMarker(c);
 | 
				
			||||||
						} catch (InterruptedException e) {
 | 
											} catch (InterruptedException e) {
 | 
				
			||||||
							Log.d(Config.LOGTAG,"unable to process notification read marker for conversation "+c.getName());
 | 
												Log.d(Config.LOGTAG, "unable to process notification read marker for conversation " + c.getName());
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					});
 | 
										});
 | 
				
			||||||
| 
						 | 
					@ -629,7 +623,7 @@ public class XmppConnectionService extends Service {
 | 
				
			||||||
					mNotificationExecutor.execute(() -> {
 | 
										mNotificationExecutor.execute(() -> {
 | 
				
			||||||
						final Conversation c = findConversationByUuid(uuid);
 | 
											final Conversation c = findConversationByUuid(uuid);
 | 
				
			||||||
						if (c == null) {
 | 
											if (c == null) {
 | 
				
			||||||
							Log.d(Config.LOGTAG,"received snooze intent for unknown conversation ("+ uuid +")");
 | 
												Log.d(Config.LOGTAG, "received snooze intent for unknown conversation (" + uuid + ")");
 | 
				
			||||||
							return;
 | 
												return;
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
						c.setMutedTill(System.currentTimeMillis() + 30 * 60 * 1000);
 | 
											c.setMutedTill(System.currentTimeMillis() + 30 * 60 * 1000);
 | 
				
			||||||
| 
						 | 
					@ -663,7 +657,7 @@ public class XmppConnectionService extends Service {
 | 
				
			||||||
				case Intent.ACTION_SEND:
 | 
									case Intent.ACTION_SEND:
 | 
				
			||||||
					Uri uri = intent.getData();
 | 
										Uri uri = intent.getData();
 | 
				
			||||||
					if (uri != null) {
 | 
										if (uri != null) {
 | 
				
			||||||
						Log.d(Config.LOGTAG, "received uri permission for "+uri.toString());
 | 
											Log.d(Config.LOGTAG, "received uri permission for " + uri.toString());
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					return START_STICKY;
 | 
										return START_STICKY;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					@ -912,23 +906,20 @@ public class XmppConnectionService extends Service {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public void expireOldMessages(final boolean resetHasMessagesLeftOnServer) {
 | 
						public void expireOldMessages(final boolean resetHasMessagesLeftOnServer) {
 | 
				
			||||||
		mLastExpiryRun.set(SystemClock.elapsedRealtime());
 | 
							mLastExpiryRun.set(SystemClock.elapsedRealtime());
 | 
				
			||||||
		mDatabaseWriterExecutor.execute(new Runnable() {
 | 
							mDatabaseWriterExecutor.execute(() -> {
 | 
				
			||||||
			@Override
 | 
								long timestamp = getAutomaticMessageDeletionDate();
 | 
				
			||||||
			public void run() {
 | 
								if (timestamp > 0) {
 | 
				
			||||||
				long timestamp = getAutomaticMessageDeletionDate();
 | 
									databaseBackend.expireOldMessages(timestamp);
 | 
				
			||||||
				if (timestamp > 0) {
 | 
									synchronized (XmppConnectionService.this.conversations) {
 | 
				
			||||||
					databaseBackend.expireOldMessages(timestamp);
 | 
										for (Conversation conversation : XmppConnectionService.this.conversations) {
 | 
				
			||||||
					synchronized (XmppConnectionService.this.conversations) {
 | 
											conversation.expireOldMessages(timestamp);
 | 
				
			||||||
						for (Conversation conversation : XmppConnectionService.this.conversations) {
 | 
											if (resetHasMessagesLeftOnServer) {
 | 
				
			||||||
							conversation.expireOldMessages(timestamp);
 | 
												conversation.messagesLoaded.set(true);
 | 
				
			||||||
							if (resetHasMessagesLeftOnServer) {
 | 
												conversation.setHasMessagesLeftOnServer(true);
 | 
				
			||||||
								conversation.messagesLoaded.set(true);
 | 
					 | 
				
			||||||
								conversation.setHasMessagesLeftOnServer(true);
 | 
					 | 
				
			||||||
							}
 | 
					 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					updateConversationUi();
 | 
					 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
									updateConversationUi();
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -939,7 +930,7 @@ public class XmppConnectionService extends Service {
 | 
				
			||||||
			final NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
 | 
								final NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
 | 
				
			||||||
			return activeNetwork != null && activeNetwork.isConnected();
 | 
								return activeNetwork != null && activeNetwork.isConnected();
 | 
				
			||||||
		} catch (RuntimeException e) {
 | 
							} catch (RuntimeException e) {
 | 
				
			||||||
			Log.d(Config.LOGTAG,"unable to check for internet connection",e);
 | 
								Log.d(Config.LOGTAG, "unable to check for internet connection", e);
 | 
				
			||||||
			return true; //if internet connection can not be checked it is probably best to just try
 | 
								return true; //if internet connection can not be checked it is probably best to just try
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -976,12 +967,7 @@ public class XmppConnectionService extends Service {
 | 
				
			||||||
		restoreFromDatabase();
 | 
							restoreFromDatabase();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		getContentResolver().registerContentObserver(ContactsContract.Contacts.CONTENT_URI, true, contactObserver);
 | 
							getContentResolver().registerContentObserver(ContactsContract.Contacts.CONTENT_URI, true, contactObserver);
 | 
				
			||||||
		new Thread(new Runnable() {
 | 
							new Thread(() -> fileObserver.startWatching()).start();
 | 
				
			||||||
			@Override
 | 
					 | 
				
			||||||
			public void run() {
 | 
					 | 
				
			||||||
				fileObserver.startWatching();
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}).start();
 | 
					 | 
				
			||||||
		if (Config.supportOpenPgp()) {
 | 
							if (Config.supportOpenPgp()) {
 | 
				
			||||||
			this.pgpServiceConnection = new OpenPgpServiceConnection(this, "org.sufficientlysecure.keychain", new OpenPgpServiceConnection.OnBound() {
 | 
								this.pgpServiceConnection = new OpenPgpServiceConnection(this, "org.sufficientlysecure.keychain", new OpenPgpServiceConnection.OnBound() {
 | 
				
			||||||
				@Override
 | 
									@Override
 | 
				
			||||||
| 
						 | 
					@ -1081,12 +1067,7 @@ public class XmppConnectionService extends Service {
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			databaseBackend.writeRoster(account.getRoster());
 | 
								databaseBackend.writeRoster(account.getRoster());
 | 
				
			||||||
			if (account.getXmppConnection() != null) {
 | 
								if (account.getXmppConnection() != null) {
 | 
				
			||||||
				new Thread(new Runnable() {
 | 
									new Thread(() -> disconnect(account, false)).start();
 | 
				
			||||||
					@Override
 | 
					 | 
				
			||||||
					public void run() {
 | 
					 | 
				
			||||||
						disconnect(account, false);
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}).start();
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (stop || activeAccounts == 0) {
 | 
							if (stop || activeAccounts == 0) {
 | 
				
			||||||
| 
						 | 
					@ -1399,97 +1380,89 @@ public class XmppConnectionService extends Service {
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			long diffConversationsRestore = SystemClock.elapsedRealtime() - startTimeConversationsRestore;
 | 
								long diffConversationsRestore = SystemClock.elapsedRealtime() - startTimeConversationsRestore;
 | 
				
			||||||
			Log.d(Config.LOGTAG, "finished restoring conversations in " + diffConversationsRestore + "ms");
 | 
								Log.d(Config.LOGTAG, "finished restoring conversations in " + diffConversationsRestore + "ms");
 | 
				
			||||||
			Runnable runnable = new Runnable() {
 | 
								Runnable runnable = () -> {
 | 
				
			||||||
				@Override
 | 
									long deletionDate = getAutomaticMessageDeletionDate();
 | 
				
			||||||
				public void run() {
 | 
									mLastExpiryRun.set(SystemClock.elapsedRealtime());
 | 
				
			||||||
					long deletionDate = getAutomaticMessageDeletionDate();
 | 
									if (deletionDate > 0) {
 | 
				
			||||||
					mLastExpiryRun.set(SystemClock.elapsedRealtime());
 | 
										Log.d(Config.LOGTAG, "deleting messages that are older than " + AbstractGenerator.getTimestamp(deletionDate));
 | 
				
			||||||
					if (deletionDate > 0) {
 | 
										databaseBackend.expireOldMessages(deletionDate);
 | 
				
			||||||
						Log.d(Config.LOGTAG, "deleting messages that are older than " + AbstractGenerator.getTimestamp(deletionDate));
 | 
					 | 
				
			||||||
						databaseBackend.expireOldMessages(deletionDate);
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					Log.d(Config.LOGTAG, "restoring roster...");
 | 
					 | 
				
			||||||
					for (Account account : accounts) {
 | 
					 | 
				
			||||||
						databaseBackend.readRoster(account.getRoster());
 | 
					 | 
				
			||||||
						account.initAccountServices(XmppConnectionService.this); //roster needs to be loaded at this stage
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					getBitmapCache().evictAll();
 | 
					 | 
				
			||||||
					loadPhoneContacts();
 | 
					 | 
				
			||||||
					Log.d(Config.LOGTAG, "restoring messages...");
 | 
					 | 
				
			||||||
					final long startMessageRestore = SystemClock.elapsedRealtime();
 | 
					 | 
				
			||||||
					for (Conversation conversation : conversations) {
 | 
					 | 
				
			||||||
						conversation.addAll(0, databaseBackend.getMessages(conversation, Config.PAGE_SIZE));
 | 
					 | 
				
			||||||
						checkDeletedFiles(conversation);
 | 
					 | 
				
			||||||
						conversation.findUnsentTextMessages(new Conversation.OnMessageFound() {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
							@Override
 | 
					 | 
				
			||||||
							public void onMessageFound(Message message) {
 | 
					 | 
				
			||||||
								markMessage(message, Message.STATUS_WAITING);
 | 
					 | 
				
			||||||
							}
 | 
					 | 
				
			||||||
						});
 | 
					 | 
				
			||||||
						conversation.findUnreadMessages(new Conversation.OnMessageFound() {
 | 
					 | 
				
			||||||
							@Override
 | 
					 | 
				
			||||||
							public void onMessageFound(Message message) {
 | 
					 | 
				
			||||||
								mNotificationService.pushFromBacklog(message);
 | 
					 | 
				
			||||||
							}
 | 
					 | 
				
			||||||
						});
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					mNotificationService.finishBacklog(false);
 | 
					 | 
				
			||||||
					restoredFromDatabaseLatch.countDown();
 | 
					 | 
				
			||||||
					final long diffMessageRestore = SystemClock.elapsedRealtime() - startMessageRestore;
 | 
					 | 
				
			||||||
					Log.d(Config.LOGTAG, "finished restoring messages in " + diffMessageRestore + "ms");
 | 
					 | 
				
			||||||
					updateConversationUi();
 | 
					 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
									Log.d(Config.LOGTAG, "restoring roster...");
 | 
				
			||||||
 | 
									for (Account account : accounts) {
 | 
				
			||||||
 | 
										databaseBackend.readRoster(account.getRoster());
 | 
				
			||||||
 | 
										account.initAccountServices(XmppConnectionService.this); //roster needs to be loaded at this stage
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									getBitmapCache().evictAll();
 | 
				
			||||||
 | 
									loadPhoneContacts();
 | 
				
			||||||
 | 
									Log.d(Config.LOGTAG, "restoring messages...");
 | 
				
			||||||
 | 
									final long startMessageRestore = SystemClock.elapsedRealtime();
 | 
				
			||||||
 | 
									for (Conversation conversation : conversations) {
 | 
				
			||||||
 | 
										conversation.addAll(0, databaseBackend.getMessages(conversation, Config.PAGE_SIZE));
 | 
				
			||||||
 | 
										checkDeletedFiles(conversation);
 | 
				
			||||||
 | 
										conversation.findUnsentTextMessages(new Conversation.OnMessageFound() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											@Override
 | 
				
			||||||
 | 
											public void onMessageFound(Message message) {
 | 
				
			||||||
 | 
												markMessage(message, Message.STATUS_WAITING);
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										});
 | 
				
			||||||
 | 
										conversation.findUnreadMessages(new Conversation.OnMessageFound() {
 | 
				
			||||||
 | 
											@Override
 | 
				
			||||||
 | 
											public void onMessageFound(Message message) {
 | 
				
			||||||
 | 
												mNotificationService.pushFromBacklog(message);
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										});
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									mNotificationService.finishBacklog(false);
 | 
				
			||||||
 | 
									restoredFromDatabaseLatch.countDown();
 | 
				
			||||||
 | 
									final long diffMessageRestore = SystemClock.elapsedRealtime() - startMessageRestore;
 | 
				
			||||||
 | 
									Log.d(Config.LOGTAG, "finished restoring messages in " + diffMessageRestore + "ms");
 | 
				
			||||||
 | 
									updateConversationUi();
 | 
				
			||||||
			};
 | 
								};
 | 
				
			||||||
			mDatabaseReaderExecutor.execute(runnable); //will contain one write command (expiry) but that's fine
 | 
								mDatabaseReaderExecutor.execute(runnable); //will contain one write command (expiry) but that's fine
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public void loadPhoneContacts() {
 | 
						public void loadPhoneContacts() {
 | 
				
			||||||
		mContactMergerExecutor.execute(new Runnable() {
 | 
							mContactMergerExecutor.execute(() -> PhoneHelper.loadPhoneContacts(XmppConnectionService.this, new OnPhoneContactsLoadedListener() {
 | 
				
			||||||
			@Override
 | 
								@Override
 | 
				
			||||||
			public void run() {
 | 
								public void onPhoneContactsLoaded(List<Bundle> phoneContacts) {
 | 
				
			||||||
				PhoneHelper.loadPhoneContacts(XmppConnectionService.this, new OnPhoneContactsLoadedListener() {
 | 
									Log.d(Config.LOGTAG, "start merging phone contacts with roster");
 | 
				
			||||||
					@Override
 | 
									for (Account account : accounts) {
 | 
				
			||||||
					public void onPhoneContactsLoaded(List<Bundle> phoneContacts) {
 | 
										List<Contact> withSystemAccounts = account.getRoster().getWithSystemAccounts();
 | 
				
			||||||
						Log.d(Config.LOGTAG, "start merging phone contacts with roster");
 | 
										for (Bundle phoneContact : phoneContacts) {
 | 
				
			||||||
						for (Account account : accounts) {
 | 
											Jid jid;
 | 
				
			||||||
							List<Contact> withSystemAccounts = account.getRoster().getWithSystemAccounts();
 | 
											try {
 | 
				
			||||||
							for (Bundle phoneContact : phoneContacts) {
 | 
												jid = Jid.of(phoneContact.getString("jid"));
 | 
				
			||||||
								Jid jid;
 | 
											} catch (final IllegalArgumentException e) {
 | 
				
			||||||
								try {
 | 
												continue;
 | 
				
			||||||
									jid = Jid.of(phoneContact.getString("jid"));
 | 
					 | 
				
			||||||
								} catch (final IllegalArgumentException e) {
 | 
					 | 
				
			||||||
									continue;
 | 
					 | 
				
			||||||
								}
 | 
					 | 
				
			||||||
								final Contact contact = account.getRoster().getContact(jid);
 | 
					 | 
				
			||||||
								String systemAccount = phoneContact.getInt("phoneid")
 | 
					 | 
				
			||||||
										+ "#"
 | 
					 | 
				
			||||||
										+ phoneContact.getString("lookup");
 | 
					 | 
				
			||||||
								contact.setSystemAccount(systemAccount);
 | 
					 | 
				
			||||||
								boolean needsCacheClean = contact.setPhotoUri(phoneContact.getString("photouri"));
 | 
					 | 
				
			||||||
								needsCacheClean |= contact.setSystemName(phoneContact.getString("displayname"));
 | 
					 | 
				
			||||||
								if (needsCacheClean) {
 | 
					 | 
				
			||||||
									getAvatarService().clear(contact);
 | 
					 | 
				
			||||||
								}
 | 
					 | 
				
			||||||
								withSystemAccounts.remove(contact);
 | 
					 | 
				
			||||||
							}
 | 
					 | 
				
			||||||
							for (Contact contact : withSystemAccounts) {
 | 
					 | 
				
			||||||
								contact.setSystemAccount(null);
 | 
					 | 
				
			||||||
								boolean needsCacheClean = contact.setPhotoUri(null);
 | 
					 | 
				
			||||||
								needsCacheClean |= contact.setSystemName(null);
 | 
					 | 
				
			||||||
								if (needsCacheClean) {
 | 
					 | 
				
			||||||
									getAvatarService().clear(contact);
 | 
					 | 
				
			||||||
								}
 | 
					 | 
				
			||||||
							}
 | 
					 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
						Log.d(Config.LOGTAG, "finished merging phone contacts");
 | 
											final Contact contact = account.getRoster().getContact(jid);
 | 
				
			||||||
						mShortcutService.refresh(mInitialAddressbookSyncCompleted.compareAndSet(false, true));
 | 
											String systemAccount = phoneContact.getInt("phoneid")
 | 
				
			||||||
						updateAccountUi();
 | 
													+ "#"
 | 
				
			||||||
 | 
													+ phoneContact.getString("lookup");
 | 
				
			||||||
 | 
											contact.setSystemAccount(systemAccount);
 | 
				
			||||||
 | 
											boolean needsCacheClean = contact.setPhotoUri(phoneContact.getString("photouri"));
 | 
				
			||||||
 | 
											needsCacheClean |= contact.setSystemName(phoneContact.getString("displayname"));
 | 
				
			||||||
 | 
											if (needsCacheClean) {
 | 
				
			||||||
 | 
												getAvatarService().clear(contact);
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
											withSystemAccounts.remove(contact);
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				});
 | 
										for (Contact contact : withSystemAccounts) {
 | 
				
			||||||
 | 
											contact.setSystemAccount(null);
 | 
				
			||||||
 | 
											boolean needsCacheClean = contact.setPhotoUri(null);
 | 
				
			||||||
 | 
											needsCacheClean |= contact.setSystemName(null);
 | 
				
			||||||
 | 
											if (needsCacheClean) {
 | 
				
			||||||
 | 
												getAvatarService().clear(contact);
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									Log.d(Config.LOGTAG, "finished merging phone contacts");
 | 
				
			||||||
 | 
									mShortcutService.refresh(mInitialAddressbookSyncCompleted.compareAndSet(false, true));
 | 
				
			||||||
 | 
									updateAccountUi();
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		});
 | 
							}));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public List<Conversation> getConversations() {
 | 
						public List<Conversation> getConversations() {
 | 
				
			||||||
| 
						 | 
					@ -1497,16 +1470,12 @@ public class XmppConnectionService extends Service {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private void checkDeletedFiles(Conversation conversation) {
 | 
						private void checkDeletedFiles(Conversation conversation) {
 | 
				
			||||||
		conversation.findMessagesWithFiles(new Conversation.OnMessageFound() {
 | 
							conversation.findMessagesWithFiles(message -> {
 | 
				
			||||||
 | 
								if (!getFileBackend().isFileAvailable(message)) {
 | 
				
			||||||
			@Override
 | 
									message.setTransferable(new TransferablePlaceholder(Transferable.STATUS_DELETED));
 | 
				
			||||||
			public void onMessageFound(Message message) {
 | 
									final int s = message.getStatus();
 | 
				
			||||||
				if (!getFileBackend().isFileAvailable(message)) {
 | 
									if (s == Message.STATUS_WAITING || s == Message.STATUS_OFFERED || s == Message.STATUS_UNSEND) {
 | 
				
			||||||
					message.setTransferable(new TransferablePlaceholder(Transferable.STATUS_DELETED));
 | 
										markMessage(message, Message.STATUS_SEND_FAILED);
 | 
				
			||||||
					final int s = message.getStatus();
 | 
					 | 
				
			||||||
					if (s == Message.STATUS_WAITING || s == Message.STATUS_OFFERED || s == Message.STATUS_UNSEND) {
 | 
					 | 
				
			||||||
						markMessage(message, Message.STATUS_SEND_FAILED);
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
| 
						 | 
					@ -1515,22 +1484,19 @@ public class XmppConnectionService extends Service {
 | 
				
			||||||
	private void markFileDeleted(final String path) {
 | 
						private void markFileDeleted(final String path) {
 | 
				
			||||||
		Log.d(Config.LOGTAG, "deleted file " + path);
 | 
							Log.d(Config.LOGTAG, "deleted file " + path);
 | 
				
			||||||
		for (Conversation conversation : getConversations()) {
 | 
							for (Conversation conversation : getConversations()) {
 | 
				
			||||||
			conversation.findMessagesWithFiles(new Conversation.OnMessageFound() {
 | 
								conversation.findMessagesWithFiles(message -> {
 | 
				
			||||||
				@Override
 | 
									DownloadableFile file = fileBackend.getFile(message);
 | 
				
			||||||
				public void onMessageFound(Message message) {
 | 
									if (file.getAbsolutePath().equals(path)) {
 | 
				
			||||||
					DownloadableFile file = fileBackend.getFile(message);
 | 
										if (!file.exists()) {
 | 
				
			||||||
					if (file.getAbsolutePath().equals(path)) {
 | 
											message.setTransferable(new TransferablePlaceholder(Transferable.STATUS_DELETED));
 | 
				
			||||||
						if (!file.exists()) {
 | 
											final int s = message.getStatus();
 | 
				
			||||||
							message.setTransferable(new TransferablePlaceholder(Transferable.STATUS_DELETED));
 | 
											if (s == Message.STATUS_WAITING || s == Message.STATUS_OFFERED || s == Message.STATUS_UNSEND) {
 | 
				
			||||||
							final int s = message.getStatus();
 | 
												markMessage(message, Message.STATUS_SEND_FAILED);
 | 
				
			||||||
							if (s == Message.STATUS_WAITING || s == Message.STATUS_OFFERED || s == Message.STATUS_UNSEND) {
 | 
					 | 
				
			||||||
								markMessage(message, Message.STATUS_SEND_FAILED);
 | 
					 | 
				
			||||||
							} else {
 | 
					 | 
				
			||||||
								updateConversationUi();
 | 
					 | 
				
			||||||
							}
 | 
					 | 
				
			||||||
						} else {
 | 
											} else {
 | 
				
			||||||
							Log.d(Config.LOGTAG, "found matching message for file " + path + " but file still exists");
 | 
												updateConversationUi();
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
 | 
										} else {
 | 
				
			||||||
 | 
											Log.d(Config.LOGTAG, "found matching message for file " + path + " but file still exists");
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
| 
						 | 
					@ -2348,7 +2314,7 @@ public class XmppConnectionService extends Service {
 | 
				
			||||||
		final Conversation conversation = self.getConversation();
 | 
							final Conversation conversation = self.getConversation();
 | 
				
			||||||
		Jid full = self.getFullJid();
 | 
							Jid full = self.getFullJid();
 | 
				
			||||||
		if (!full.equals(conversation.getJid())) {
 | 
							if (!full.equals(conversation.getJid())) {
 | 
				
			||||||
			Log.d(Config.LOGTAG,"nick changed. updating");
 | 
								Log.d(Config.LOGTAG, "nick changed. updating");
 | 
				
			||||||
			conversation.setContactJid(full);
 | 
								conversation.setContactJid(full);
 | 
				
			||||||
			databaseBackend.updateConversation(conversation);
 | 
								databaseBackend.updateConversation(conversation);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -3066,12 +3032,7 @@ public class XmppConnectionService extends Service {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public void reconnectAccountInBackground(final Account account) {
 | 
						public void reconnectAccountInBackground(final Account account) {
 | 
				
			||||||
		new Thread(new Runnable() {
 | 
							new Thread(() -> reconnectAccount(account, false, true)).start();
 | 
				
			||||||
			@Override
 | 
					 | 
				
			||||||
			public void run() {
 | 
					 | 
				
			||||||
				reconnectAccount(account, false, true);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}).start();
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public void invite(Conversation conversation, Jid contact) {
 | 
						public void invite(Conversation conversation, Jid contact) {
 | 
				
			||||||
| 
						 | 
					@ -3298,12 +3259,9 @@ public class XmppConnectionService extends Service {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		final List<Message> readMessages = conversation.markRead();
 | 
							final List<Message> readMessages = conversation.markRead();
 | 
				
			||||||
		if (readMessages.size() > 0) {
 | 
							if (readMessages.size() > 0) {
 | 
				
			||||||
			Runnable runnable = new Runnable() {
 | 
								Runnable runnable = () -> {
 | 
				
			||||||
				@Override
 | 
									for (Message message : readMessages) {
 | 
				
			||||||
				public void run() {
 | 
										databaseBackend.updateMessage(message);
 | 
				
			||||||
					for (Message message : readMessages) {
 | 
					 | 
				
			||||||
						databaseBackend.updateMessage(message);
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			};
 | 
								};
 | 
				
			||||||
			mDatabaseWriterExecutor.execute(runnable);
 | 
								mDatabaseWriterExecutor.execute(runnable);
 | 
				
			||||||
| 
						 | 
					@ -3369,26 +3327,10 @@ public class XmppConnectionService extends Service {
 | 
				
			||||||
		setMemorizingTrustManager(tm);
 | 
							setMemorizingTrustManager(tm);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public PowerManager getPowerManager() {
 | 
					 | 
				
			||||||
		return this.pm;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	public LruCache<String, Bitmap> getBitmapCache() {
 | 
						public LruCache<String, Bitmap> getBitmapCache() {
 | 
				
			||||||
		return this.mBitmapCache;
 | 
							return this.mBitmapCache;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public void syncRosterToDisk(final Account account) {
 | 
					 | 
				
			||||||
		Runnable runnable = new Runnable() {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			@Override
 | 
					 | 
				
			||||||
			public void run() {
 | 
					 | 
				
			||||||
				databaseBackend.writeRoster(account.getRoster());
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
		mDatabaseWriterExecutor.execute(runnable);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	public Collection<String> getKnownHosts() {
 | 
						public Collection<String> getKnownHosts() {
 | 
				
			||||||
		final Set<String> hosts = new HashSet<>();
 | 
							final Set<String> hosts = new HashSet<>();
 | 
				
			||||||
		for (final Account account : getAccounts()) {
 | 
							for (final Account account : getAccounts()) {
 | 
				
			||||||
| 
						 | 
					@ -3449,7 +3391,7 @@ public class XmppConnectionService extends Service {
 | 
				
			||||||
		final XmppConnection connection = account.getXmppConnection();
 | 
							final XmppConnection connection = account.getXmppConnection();
 | 
				
			||||||
		if (connection != null) {
 | 
							if (connection != null) {
 | 
				
			||||||
			IqPacket request = mIqGenerator.generateCreateAccountWithCaptcha(account, id, data);
 | 
								IqPacket request = mIqGenerator.generateCreateAccountWithCaptcha(account, id, data);
 | 
				
			||||||
			connection.sendUnmodifiedIqPacket(request, connection.registrationResponseListener,true);
 | 
								connection.sendUnmodifiedIqPacket(request, connection.registrationResponseListener, true);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3471,7 +3413,7 @@ public class XmppConnectionService extends Service {
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			status = getTargetPresence();
 | 
								status = getTargetPresence();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		PresencePacket packet = mPresenceGenerator.selfPresence(account,status);
 | 
							PresencePacket packet = mPresenceGenerator.selfPresence(account, status);
 | 
				
			||||||
		String message = account.getPresenceStatusMessage();
 | 
							String message = account.getPresenceStatusMessage();
 | 
				
			||||||
		if (message != null && !message.isEmpty()) {
 | 
							if (message != null && !message.isEmpty()) {
 | 
				
			||||||
			packet.addChild(new Element("status").setContent(message));
 | 
								packet.addChild(new Element("status").setContent(message));
 | 
				
			||||||
| 
						 | 
					@ -3600,12 +3542,9 @@ public class XmppConnectionService extends Service {
 | 
				
			||||||
		conversation.clearMessages();
 | 
							conversation.clearMessages();
 | 
				
			||||||
		conversation.setHasMessagesLeftOnServer(false); //avoid messages getting loaded through mam
 | 
							conversation.setHasMessagesLeftOnServer(false); //avoid messages getting loaded through mam
 | 
				
			||||||
		conversation.setLastClearHistory(clearDate, reference);
 | 
							conversation.setLastClearHistory(clearDate, reference);
 | 
				
			||||||
		Runnable runnable = new Runnable() {
 | 
							Runnable runnable = () -> {
 | 
				
			||||||
			@Override
 | 
								databaseBackend.deleteMessagesInConversation(conversation);
 | 
				
			||||||
			public void run() {
 | 
								databaseBackend.updateConversation(conversation);
 | 
				
			||||||
				databaseBackend.deleteMessagesInConversation(conversation);
 | 
					 | 
				
			||||||
				databaseBackend.updateConversation(conversation);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
		mDatabaseWriterExecutor.execute(runnable);
 | 
							mDatabaseWriterExecutor.execute(runnable);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -3675,12 +3614,9 @@ public class XmppConnectionService extends Service {
 | 
				
			||||||
		String displayName = account.getDisplayName();
 | 
							String displayName = account.getDisplayName();
 | 
				
			||||||
		if (displayName != null && !displayName.isEmpty()) {
 | 
							if (displayName != null && !displayName.isEmpty()) {
 | 
				
			||||||
			IqPacket publish = mIqGenerator.publishNick(displayName);
 | 
								IqPacket publish = mIqGenerator.publishNick(displayName);
 | 
				
			||||||
			sendIqPacket(account, publish, new OnIqPacketReceived() {
 | 
								sendIqPacket(account, publish, (account1, packet) -> {
 | 
				
			||||||
				@Override
 | 
									if (packet.getType() == IqPacket.TYPE.ERROR) {
 | 
				
			||||||
				public void onIqPacketReceived(Account account, IqPacket packet) {
 | 
										Log.d(Config.LOGTAG, account1.getJid().asBareJid() + ": could not publish nick");
 | 
				
			||||||
					if (packet.getType() == IqPacket.TYPE.ERROR) {
 | 
					 | 
				
			||||||
						Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": could not publish nick");
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -3711,20 +3647,17 @@ public class XmppConnectionService extends Service {
 | 
				
			||||||
				request.setTo(jid);
 | 
									request.setTo(jid);
 | 
				
			||||||
				request.query("http://jabber.org/protocol/disco#info");
 | 
									request.query("http://jabber.org/protocol/disco#info");
 | 
				
			||||||
				Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": making disco request for " + key.second + " to " + jid);
 | 
									Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": making disco request for " + key.second + " to " + jid);
 | 
				
			||||||
				sendIqPacket(account, request, new OnIqPacketReceived() {
 | 
									sendIqPacket(account, request, (account1, discoPacket) -> {
 | 
				
			||||||
					@Override
 | 
										if (discoPacket.getType() == IqPacket.TYPE.RESULT) {
 | 
				
			||||||
					public void onIqPacketReceived(Account account, IqPacket discoPacket) {
 | 
											ServiceDiscoveryResult disco1 = new ServiceDiscoveryResult(discoPacket);
 | 
				
			||||||
						if (discoPacket.getType() == IqPacket.TYPE.RESULT) {
 | 
											if (presence.getVer().equals(disco1.getVer())) {
 | 
				
			||||||
							ServiceDiscoveryResult disco = new ServiceDiscoveryResult(discoPacket);
 | 
												databaseBackend.insertDiscoveryResult(disco1);
 | 
				
			||||||
							if (presence.getVer().equals(disco.getVer())) {
 | 
												injectServiceDiscorveryResult(account1.getRoster(), presence.getHash(), presence.getVer(), disco1);
 | 
				
			||||||
								databaseBackend.insertDiscoveryResult(disco);
 | 
											} else {
 | 
				
			||||||
								injectServiceDiscorveryResult(account.getRoster(), presence.getHash(), presence.getVer(), disco);
 | 
												Log.d(Config.LOGTAG, account1.getJid().asBareJid() + ": mismatch in caps for contact " + jid + " " + presence.getVer() + " vs " + disco1.getVer());
 | 
				
			||||||
							} else {
 | 
					 | 
				
			||||||
								Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": mismatch in caps for contact " + jid + " " + presence.getVer() + " vs " + disco.getVer());
 | 
					 | 
				
			||||||
							}
 | 
					 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
						account.inProgressDiscoFetches.remove(key);
 | 
					 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
 | 
										account1.inProgressDiscoFetches.remove(key);
 | 
				
			||||||
				});
 | 
									});
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -3744,15 +3677,12 @@ public class XmppConnectionService extends Service {
 | 
				
			||||||
		final boolean legacy = account.getXmppConnection().getFeatures().mamLegacy();
 | 
							final boolean legacy = account.getXmppConnection().getFeatures().mamLegacy();
 | 
				
			||||||
		IqPacket request = new IqPacket(IqPacket.TYPE.GET);
 | 
							IqPacket request = new IqPacket(IqPacket.TYPE.GET);
 | 
				
			||||||
		request.addChild("prefs", legacy ? Namespace.MAM_LEGACY : Namespace.MAM);
 | 
							request.addChild("prefs", legacy ? Namespace.MAM_LEGACY : Namespace.MAM);
 | 
				
			||||||
		sendIqPacket(account, request, new OnIqPacketReceived() {
 | 
							sendIqPacket(account, request, (account1, packet) -> {
 | 
				
			||||||
			@Override
 | 
								Element prefs = packet.findChild("prefs", legacy ? Namespace.MAM_LEGACY : Namespace.MAM);
 | 
				
			||||||
			public void onIqPacketReceived(Account account, IqPacket packet) {
 | 
								if (packet.getType() == IqPacket.TYPE.RESULT && prefs != null) {
 | 
				
			||||||
				Element prefs = packet.findChild("prefs", legacy ? Namespace.MAM_LEGACY : Namespace.MAM);
 | 
									callback.onPreferencesFetched(prefs);
 | 
				
			||||||
				if (packet.getType() == IqPacket.TYPE.RESULT && prefs != null) {
 | 
								} else {
 | 
				
			||||||
					callback.onPreferencesFetched(prefs);
 | 
									callback.onPreferencesFetchFailed();
 | 
				
			||||||
				} else {
 | 
					 | 
				
			||||||
					callback.onPreferencesFetchFailed();
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -3859,18 +3789,18 @@ public class XmppConnectionService extends Service {
 | 
				
			||||||
		return mShortcutService;
 | 
							return mShortcutService;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public interface OnMamPreferencesFetched {
 | 
					 | 
				
			||||||
		void onPreferencesFetched(Element prefs);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		void onPreferencesFetchFailed();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	public void pushMamPreferences(Account account, Element prefs) {
 | 
						public void pushMamPreferences(Account account, Element prefs) {
 | 
				
			||||||
		IqPacket set = new IqPacket(IqPacket.TYPE.SET);
 | 
							IqPacket set = new IqPacket(IqPacket.TYPE.SET);
 | 
				
			||||||
		set.addChild(prefs);
 | 
							set.addChild(prefs);
 | 
				
			||||||
		sendIqPacket(account, set, null);
 | 
							sendIqPacket(account, set, null);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public interface OnMamPreferencesFetched {
 | 
				
			||||||
 | 
							void onPreferencesFetched(Element prefs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void onPreferencesFetchFailed();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public interface OnAccountCreated {
 | 
						public interface OnAccountCreated {
 | 
				
			||||||
		void onAccountCreated(Account account);
 | 
							void onAccountCreated(Account account);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3910,10 +3840,7 @@ public class XmppConnectionService extends Service {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public interface OnCaptchaRequested {
 | 
						public interface OnCaptchaRequested {
 | 
				
			||||||
		void onCaptchaRequested(Account account,
 | 
							void onCaptchaRequested(Account account, String id, Data data, Bitmap captcha);
 | 
				
			||||||
		                        String id,
 | 
					 | 
				
			||||||
		                        Data data,
 | 
					 | 
				
			||||||
		                        Bitmap captcha);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public interface OnRosterUpdate {
 | 
						public interface OnRosterUpdate {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,6 +36,7 @@ import java.util.Hashtable;
 | 
				
			||||||
import java.util.Iterator;
 | 
					import java.util.Iterator;
 | 
				
			||||||
import java.util.List;
 | 
					import java.util.List;
 | 
				
			||||||
import java.util.Map.Entry;
 | 
					import java.util.Map.Entry;
 | 
				
			||||||
 | 
					import java.util.Set;
 | 
				
			||||||
import java.util.concurrent.CountDownLatch;
 | 
					import java.util.concurrent.CountDownLatch;
 | 
				
			||||||
import java.util.concurrent.TimeUnit;
 | 
					import java.util.concurrent.TimeUnit;
 | 
				
			||||||
import java.util.concurrent.atomic.AtomicBoolean;
 | 
					import java.util.concurrent.atomic.AtomicBoolean;
 | 
				
			||||||
| 
						 | 
					@ -135,7 +136,7 @@ public class XmppConnection implements Runnable {
 | 
				
			||||||
	private final HashMap<Jid, ServiceDiscoveryResult> disco = new HashMap<>();
 | 
						private final HashMap<Jid, ServiceDiscoveryResult> disco = new HashMap<>();
 | 
				
			||||||
	private final SparseArray<AbstractAcknowledgeableStanza> mStanzaQueue = new SparseArray<>();
 | 
						private final SparseArray<AbstractAcknowledgeableStanza> mStanzaQueue = new SparseArray<>();
 | 
				
			||||||
	private final Hashtable<String, Pair<IqPacket, OnIqPacketReceived>> packetCallbacks = new Hashtable<>();
 | 
						private final Hashtable<String, Pair<IqPacket, OnIqPacketReceived>> packetCallbacks = new Hashtable<>();
 | 
				
			||||||
	private final ArrayList<OnAdvancedStreamFeaturesLoaded> advancedStreamFeaturesLoadedListeners = new ArrayList<>();
 | 
						private final Set<OnAdvancedStreamFeaturesLoaded> advancedStreamFeaturesLoadedListeners = new HashSet<>();
 | 
				
			||||||
	private final XmppConnectionService mXmppConnectionService;
 | 
						private final XmppConnectionService mXmppConnectionService;
 | 
				
			||||||
	private Socket socket;
 | 
						private Socket socket;
 | 
				
			||||||
	private XmlReader tagReader;
 | 
						private XmlReader tagReader;
 | 
				
			||||||
| 
						 | 
					@ -1431,9 +1432,7 @@ public class XmppConnection implements Runnable {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public void addOnAdvancedStreamFeaturesAvailableListener(final OnAdvancedStreamFeaturesLoaded listener) {
 | 
						public void addOnAdvancedStreamFeaturesAvailableListener(final OnAdvancedStreamFeaturesLoaded listener) {
 | 
				
			||||||
		if (!this.advancedStreamFeaturesLoadedListeners.contains(listener)) {
 | 
							this.advancedStreamFeaturesLoadedListeners.add(listener);
 | 
				
			||||||
			this.advancedStreamFeaturesLoadedListeners.add(listener);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private void forceCloseSocket() {
 | 
						private void forceCloseSocket() {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue