Merge pull request #2715 from k9mail/GH-2714_fix_ActivityListener_crash
Fix ActivityListener crash due to concurrent modification
This commit is contained in:
commit
66b5154b7d
2 changed files with 154 additions and 114 deletions
|
@ -35,6 +35,7 @@ dependencies {
|
||||||
compile 'com.github.amlcurran.showcaseview:library:5.4.1'
|
compile 'com.github.amlcurran.showcaseview:library:5.4.1'
|
||||||
compile 'com.squareup.moshi:moshi:1.2.0'
|
compile 'com.squareup.moshi:moshi:1.2.0'
|
||||||
compile "com.jakewharton.timber:timber:${timberVersion}"
|
compile "com.jakewharton.timber:timber:${timberVersion}"
|
||||||
|
compile 'net.jcip:jcip-annotations:1.0'
|
||||||
|
|
||||||
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
|
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.fsck.k9.activity;
|
package com.fsck.k9.activity;
|
||||||
|
|
||||||
|
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
@ -12,39 +13,45 @@ import com.fsck.k9.K9;
|
||||||
import com.fsck.k9.R;
|
import com.fsck.k9.R;
|
||||||
import com.fsck.k9.controller.SimpleMessagingListener;
|
import com.fsck.k9.controller.SimpleMessagingListener;
|
||||||
import com.fsck.k9.service.MailService;
|
import com.fsck.k9.service.MailService;
|
||||||
|
import net.jcip.annotations.GuardedBy;
|
||||||
|
|
||||||
|
|
||||||
public class ActivityListener extends SimpleMessagingListener {
|
public class ActivityListener extends SimpleMessagingListener {
|
||||||
private Account mAccount = null;
|
private final Object lock = new Object();
|
||||||
private String mLoadingFolderName = null;
|
|
||||||
private String mLoadingHeaderFolderName = null;
|
|
||||||
private String mLoadingAccountDescription = null;
|
|
||||||
private String mSendingAccountDescription = null;
|
|
||||||
private int mFolderCompleted = 0;
|
|
||||||
private int mFolderTotal = 0;
|
|
||||||
private String mProcessingAccountDescription = null;
|
|
||||||
private String mProcessingCommandTitle = null;
|
|
||||||
|
|
||||||
private BroadcastReceiver mTickReceiver = new BroadcastReceiver() {
|
@GuardedBy("lock") private Account account = null;
|
||||||
|
@GuardedBy("lock") private String loadingFolderName = null;
|
||||||
|
@GuardedBy("lock") private String loadingHeaderFolderName = null;
|
||||||
|
@GuardedBy("lock") private String loadingAccountDescription = null;
|
||||||
|
@GuardedBy("lock") private String sendingAccountDescription = null;
|
||||||
|
@GuardedBy("lock") private int folderCompleted = 0;
|
||||||
|
@GuardedBy("lock") private int folderTotal = 0;
|
||||||
|
@GuardedBy("lock") private String processingAccountDescription = null;
|
||||||
|
@GuardedBy("lock") private String processingCommandTitle = null;
|
||||||
|
|
||||||
|
private BroadcastReceiver tickReceiver = new BroadcastReceiver() {
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
informUserOfStatus();
|
informUserOfStatus();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
public String getOperation(Context context) {
|
public String getOperation(Context context) {
|
||||||
if (mLoadingAccountDescription != null
|
synchronized (lock) {
|
||||||
|| mSendingAccountDescription != null
|
if (loadingAccountDescription != null ||
|
||||||
|| mLoadingHeaderFolderName != null
|
sendingAccountDescription != null ||
|
||||||
|| mProcessingAccountDescription != null) {
|
loadingHeaderFolderName != null ||
|
||||||
|
processingAccountDescription != null) {
|
||||||
return getActionInProgressOperation(context);
|
return getActionInProgressOperation(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
|
||||||
long nextPollTime = MailService.getNextPollTime();
|
long nextPollTime = MailService.getNextPollTime();
|
||||||
if (nextPollTime != -1) {
|
if (nextPollTime != -1) {
|
||||||
return context.getString(R.string.status_next_poll,
|
CharSequence relativeTimeSpanString = DateUtils.getRelativeTimeSpanString(
|
||||||
DateUtils.getRelativeTimeSpanString(nextPollTime, System.currentTimeMillis(),
|
nextPollTime, System.currentTimeMillis(), DateUtils.MINUTE_IN_MILLIS, 0);
|
||||||
DateUtils.MINUTE_IN_MILLIS, 0));
|
return context.getString(R.string.status_next_poll, relativeTimeSpanString);
|
||||||
} else if (K9.isDebug() && MailService.isSyncDisabled()) {
|
} else if (K9.isDebug() && MailService.isSyncDisabled()) {
|
||||||
if (MailService.hasNoConnectivity()) {
|
if (MailService.hasNoConnectivity()) {
|
||||||
return context.getString(R.string.status_no_network);
|
return context.getString(R.string.status_no_network);
|
||||||
|
@ -63,165 +70,195 @@ public class ActivityListener extends SimpleMessagingListener {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
@GuardedBy("lock")
|
||||||
private String getActionInProgressOperation(Context context) {
|
private String getActionInProgressOperation(Context context) {
|
||||||
String progress = (mFolderTotal > 0 ?
|
String progress = folderTotal > 0 ?
|
||||||
context.getString(R.string.folder_progress, mFolderCompleted, mFolderTotal) : "");
|
context.getString(R.string.folder_progress, folderCompleted, folderTotal) : "";
|
||||||
|
|
||||||
if (mLoadingFolderName != null || mLoadingHeaderFolderName != null) {
|
if (loadingFolderName != null || loadingHeaderFolderName != null) {
|
||||||
String displayName = null;
|
String displayName;
|
||||||
if (mLoadingHeaderFolderName != null) {
|
if (loadingHeaderFolderName != null) {
|
||||||
displayName = mLoadingHeaderFolderName;
|
displayName = loadingHeaderFolderName;
|
||||||
} else if (mLoadingFolderName != null) {
|
} else {
|
||||||
displayName = mLoadingFolderName;
|
displayName = loadingFolderName;
|
||||||
}
|
}
|
||||||
if ((mAccount != null) && (mAccount.getInboxFolderName() != null)
|
|
||||||
&& mAccount.getInboxFolderName().equalsIgnoreCase(displayName)) {
|
if (account != null) {
|
||||||
|
if (displayName.equalsIgnoreCase(account.getInboxFolderName())) {
|
||||||
displayName = context.getString(R.string.special_mailbox_name_inbox);
|
displayName = context.getString(R.string.special_mailbox_name_inbox);
|
||||||
} else if ((mAccount != null) && (mAccount.getOutboxFolderName() != null)
|
} else if (displayName.equalsIgnoreCase(account.getOutboxFolderName())) {
|
||||||
&& mAccount.getOutboxFolderName().equals(displayName)) {
|
|
||||||
displayName = context.getString(R.string.special_mailbox_name_outbox);
|
displayName = context.getString(R.string.special_mailbox_name_outbox);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (mLoadingHeaderFolderName != null) {
|
if (loadingHeaderFolderName != null) {
|
||||||
return context.getString(R.string.status_loading_account_folder_headers,
|
return context.getString(R.string.status_loading_account_folder_headers,
|
||||||
mLoadingAccountDescription, displayName, progress);
|
loadingAccountDescription, displayName, progress);
|
||||||
} else {
|
} else {
|
||||||
return context.getString(R.string.status_loading_account_folder,
|
return context.getString(R.string.status_loading_account_folder,
|
||||||
mLoadingAccountDescription, displayName, progress);
|
loadingAccountDescription, displayName, progress);
|
||||||
}
|
}
|
||||||
}
|
} else if (sendingAccountDescription != null) {
|
||||||
|
return context.getString(R.string.status_sending_account, sendingAccountDescription, progress);
|
||||||
else if (mSendingAccountDescription != null) {
|
} else if (processingAccountDescription != null) {
|
||||||
return context.getString(R.string.status_sending_account, mSendingAccountDescription, progress);
|
return context.getString(R.string.status_processing_account, processingAccountDescription,
|
||||||
} else if (mProcessingAccountDescription != null) {
|
processingCommandTitle != null ? processingCommandTitle : "", progress);
|
||||||
return context.getString(R.string.status_processing_account, mProcessingAccountDescription,
|
|
||||||
mProcessingCommandTitle != null ? mProcessingCommandTitle : "",
|
|
||||||
progress);
|
|
||||||
} else {
|
} else {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onResume(Context context) {
|
public void onResume(Context context) {
|
||||||
context.registerReceiver(mTickReceiver, new IntentFilter(Intent.ACTION_TIME_TICK));
|
context.registerReceiver(tickReceiver, new IntentFilter(Intent.ACTION_TIME_TICK));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onPause(Context context) {
|
public void onPause(Context context) {
|
||||||
context.unregisterReceiver(mTickReceiver);
|
context.unregisterReceiver(tickReceiver);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void informUserOfStatus() {
|
public void informUserOfStatus() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void synchronizeMailboxFinished(
|
public void synchronizeMailboxFinished(Account account, String folder, int totalMessagesInMailbox,
|
||||||
Account account,
|
|
||||||
String folder,
|
|
||||||
int totalMessagesInMailbox,
|
|
||||||
int numNewMessages) {
|
int numNewMessages) {
|
||||||
mLoadingAccountDescription = null;
|
synchronized (lock) {
|
||||||
mLoadingFolderName = null;
|
loadingAccountDescription = null;
|
||||||
mAccount = null;
|
loadingFolderName = null;
|
||||||
|
this.account = null;
|
||||||
|
}
|
||||||
|
|
||||||
informUserOfStatus();
|
informUserOfStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void synchronizeMailboxStarted(Account account, String folder) {
|
public void synchronizeMailboxStarted(Account account, String folder) {
|
||||||
mLoadingAccountDescription = account.getDescription();
|
synchronized (lock) {
|
||||||
mLoadingFolderName = folder;
|
loadingAccountDescription = account.getDescription();
|
||||||
mAccount = account;
|
loadingFolderName = folder;
|
||||||
mFolderCompleted = 0;
|
this.account = account;
|
||||||
mFolderTotal = 0;
|
folderCompleted = 0;
|
||||||
informUserOfStatus();
|
folderTotal = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
informUserOfStatus();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void synchronizeMailboxHeadersStarted(Account account, String folder) {
|
public void synchronizeMailboxHeadersStarted(Account account, String folder) {
|
||||||
mLoadingAccountDescription = account.getDescription();
|
synchronized (lock) {
|
||||||
mLoadingHeaderFolderName = folder;
|
loadingAccountDescription = account.getDescription();
|
||||||
informUserOfStatus();
|
loadingHeaderFolderName = folder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
informUserOfStatus();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void synchronizeMailboxHeadersProgress(Account account, String folder, int completed, int total) {
|
public void synchronizeMailboxHeadersProgress(Account account, String folder, int completed, int total) {
|
||||||
mFolderCompleted = completed;
|
synchronized (lock) {
|
||||||
mFolderTotal = total;
|
folderCompleted = completed;
|
||||||
|
folderTotal = total;
|
||||||
|
}
|
||||||
|
|
||||||
informUserOfStatus();
|
informUserOfStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void synchronizeMailboxHeadersFinished(Account account, String folder,
|
public void synchronizeMailboxHeadersFinished(Account account, String folder, int total, int completed) {
|
||||||
int total, int completed) {
|
synchronized (lock) {
|
||||||
mLoadingHeaderFolderName = null;
|
loadingHeaderFolderName = null;
|
||||||
mFolderCompleted = 0;
|
folderCompleted = 0;
|
||||||
mFolderTotal = 0;
|
folderTotal = 0;
|
||||||
informUserOfStatus();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
informUserOfStatus();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void synchronizeMailboxProgress(Account account, String folder, int completed, int total) {
|
public void synchronizeMailboxProgress(Account account, String folder, int completed, int total) {
|
||||||
mFolderCompleted = completed;
|
synchronized (lock) {
|
||||||
mFolderTotal = total;
|
folderCompleted = completed;
|
||||||
|
folderTotal = total;
|
||||||
|
}
|
||||||
|
|
||||||
informUserOfStatus();
|
informUserOfStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void synchronizeMailboxFailed(Account account, String folder,
|
public void synchronizeMailboxFailed(Account account, String folder, String message) {
|
||||||
String message) {
|
synchronized (lock) {
|
||||||
mLoadingAccountDescription = null;
|
loadingAccountDescription = null;
|
||||||
mLoadingHeaderFolderName = null;
|
loadingHeaderFolderName = null;
|
||||||
mLoadingFolderName = null;
|
loadingFolderName = null;
|
||||||
mAccount = null;
|
this.account = null;
|
||||||
|
}
|
||||||
informUserOfStatus();
|
informUserOfStatus();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendPendingMessagesStarted(Account account) {
|
public void sendPendingMessagesStarted(Account account) {
|
||||||
mSendingAccountDescription = account.getDescription();
|
synchronized (lock) {
|
||||||
|
sendingAccountDescription = account.getDescription();
|
||||||
|
}
|
||||||
|
|
||||||
informUserOfStatus();
|
informUserOfStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendPendingMessagesCompleted(Account account) {
|
public void sendPendingMessagesCompleted(Account account) {
|
||||||
mSendingAccountDescription = null;
|
synchronized (lock) {
|
||||||
|
sendingAccountDescription = null;
|
||||||
|
}
|
||||||
|
|
||||||
informUserOfStatus();
|
informUserOfStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendPendingMessagesFailed(Account account) {
|
public void sendPendingMessagesFailed(Account account) {
|
||||||
mSendingAccountDescription = null;
|
synchronized (lock) {
|
||||||
|
sendingAccountDescription = null;
|
||||||
|
}
|
||||||
|
|
||||||
informUserOfStatus();
|
informUserOfStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void pendingCommandsProcessing(Account account) {
|
public void pendingCommandsProcessing(Account account) {
|
||||||
mProcessingAccountDescription = account.getDescription();
|
synchronized (lock) {
|
||||||
mFolderCompleted = 0;
|
processingAccountDescription = account.getDescription();
|
||||||
mFolderTotal = 0;
|
folderCompleted = 0;
|
||||||
|
folderTotal = 0;
|
||||||
|
}
|
||||||
|
|
||||||
informUserOfStatus();
|
informUserOfStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void pendingCommandsFinished(Account account) {
|
public void pendingCommandsFinished(Account account) {
|
||||||
mProcessingAccountDescription = null;
|
synchronized (lock) {
|
||||||
|
processingAccountDescription = null;
|
||||||
|
}
|
||||||
|
|
||||||
informUserOfStatus();
|
informUserOfStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void pendingCommandStarted(Account account, String commandTitle) {
|
public void pendingCommandStarted(Account account, String commandTitle) {
|
||||||
mProcessingCommandTitle = commandTitle;
|
synchronized (lock) {
|
||||||
|
processingCommandTitle = commandTitle;
|
||||||
|
|
||||||
|
}
|
||||||
informUserOfStatus();
|
informUserOfStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void pendingCommandCompleted(Account account, String commandTitle) {
|
public void pendingCommandCompleted(Account account, String commandTitle) {
|
||||||
mProcessingCommandTitle = null;
|
synchronized (lock) {
|
||||||
|
processingCommandTitle = null;
|
||||||
|
}
|
||||||
|
|
||||||
informUserOfStatus();
|
informUserOfStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,12 +278,14 @@ public class ActivityListener extends SimpleMessagingListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getFolderCompleted() {
|
public int getFolderCompleted() {
|
||||||
return mFolderCompleted;
|
synchronized (lock) {
|
||||||
|
return folderCompleted;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public int getFolderTotal() {
|
public int getFolderTotal() {
|
||||||
return mFolderTotal;
|
synchronized (lock) {
|
||||||
|
return folderTotal;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue